1896a1373cfdbaa25f4ab73ed4f27554016defecccerion
2896a1373cfdbaa25f4ab73ed4f27554016defecccerion/*--------------------------------------------------------------------*/
3752f90673ebbb6b2f55fc5e46606dea371313713sewardj/*--- begin                                       guest_ppc_toIR.c ---*/
4896a1373cfdbaa25f4ab73ed4f27554016defecccerion/*--------------------------------------------------------------------*/
5896a1373cfdbaa25f4ab73ed4f27554016defecccerion
6896a1373cfdbaa25f4ab73ed4f27554016defecccerion/*
7752f90673ebbb6b2f55fc5e46606dea371313713sewardj   This file is part of Valgrind, a dynamic binary instrumentation
8752f90673ebbb6b2f55fc5e46606dea371313713sewardj   framework.
9896a1373cfdbaa25f4ab73ed4f27554016defecccerion
10785952d4bf502fa756b2ac58595fd31fe0f88559sewardj   Copyright (C) 2004-2015 OpenWorks LLP
11752f90673ebbb6b2f55fc5e46606dea371313713sewardj      info@open-works.net
12896a1373cfdbaa25f4ab73ed4f27554016defecccerion
13752f90673ebbb6b2f55fc5e46606dea371313713sewardj   This program is free software; you can redistribute it and/or
14752f90673ebbb6b2f55fc5e46606dea371313713sewardj   modify it under the terms of the GNU General Public License as
15752f90673ebbb6b2f55fc5e46606dea371313713sewardj   published by the Free Software Foundation; either version 2 of the
16752f90673ebbb6b2f55fc5e46606dea371313713sewardj   License, or (at your option) any later version.
17896a1373cfdbaa25f4ab73ed4f27554016defecccerion
18752f90673ebbb6b2f55fc5e46606dea371313713sewardj   This program is distributed in the hope that it will be useful, but
19752f90673ebbb6b2f55fc5e46606dea371313713sewardj   WITHOUT ANY WARRANTY; without even the implied warranty of
20752f90673ebbb6b2f55fc5e46606dea371313713sewardj   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
21752f90673ebbb6b2f55fc5e46606dea371313713sewardj   General Public License for more details.
22752f90673ebbb6b2f55fc5e46606dea371313713sewardj
23752f90673ebbb6b2f55fc5e46606dea371313713sewardj   You should have received a copy of the GNU General Public License
24752f90673ebbb6b2f55fc5e46606dea371313713sewardj   along with this program; if not, write to the Free Software
25752f90673ebbb6b2f55fc5e46606dea371313713sewardj   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
267bd6ffe203f3aa9e7b25f7eae40a9b9cf48710cfsewardj   02110-1301, USA.
277bd6ffe203f3aa9e7b25f7eae40a9b9cf48710cfsewardj
28752f90673ebbb6b2f55fc5e46606dea371313713sewardj   The GNU General Public License is contained in the file COPYING.
29896a1373cfdbaa25f4ab73ed4f27554016defecccerion
30896a1373cfdbaa25f4ab73ed4f27554016defecccerion   Neither the names of the U.S. Department of Energy nor the
31896a1373cfdbaa25f4ab73ed4f27554016defecccerion   University of California nor the names of its contributors may be
32896a1373cfdbaa25f4ab73ed4f27554016defecccerion   used to endorse or promote products derived from this software
33896a1373cfdbaa25f4ab73ed4f27554016defecccerion   without prior written permission.
34896a1373cfdbaa25f4ab73ed4f27554016defecccerion*/
35896a1373cfdbaa25f4ab73ed4f27554016defecccerion
36edf7fc572e2decb93e9143961e8739c8fe18899dcerion/* TODO 18/Nov/05:
37b51f0f4f33256638ed953156a2635aa739b232f1sewardj
38cf8986c47a4c8c810566bb5b7b3da7a16a17dfe2sewardj   Spot rld... cases which are simply left/right shifts and emit
39cf8986c47a4c8c810566bb5b7b3da7a16a17dfe2sewardj   Shl64/Shr64 accordingly.
40e14bb9f862843c6b804097c124961b5567ded4f1sewardj
41edf7fc572e2decb93e9143961e8739c8fe18899dcerion   Altivec
42edf7fc572e2decb93e9143961e8739c8fe18899dcerion   - datastream insns
43edf7fc572e2decb93e9143961e8739c8fe18899dcerion   - lvxl,stvxl: load/store with 'least recently used' hint
44edf7fc572e2decb93e9143961e8739c8fe18899dcerion   - vexptefp, vlogefp
4587e651f40360a8f1c9418710e79c482028759f8csewardj
4687e651f40360a8f1c9418710e79c482028759f8csewardj   LIMITATIONS:
4787e651f40360a8f1c9418710e79c482028759f8csewardj
4887e651f40360a8f1c9418710e79c482028759f8csewardj   Various, including:
4987e651f40360a8f1c9418710e79c482028759f8csewardj
5087e651f40360a8f1c9418710e79c482028759f8csewardj   - Some invalid forms of lswi and lswx are accepted when they should
5187e651f40360a8f1c9418710e79c482028759f8csewardj     not be.
5287e651f40360a8f1c9418710e79c482028759f8csewardj
53edf7fc572e2decb93e9143961e8739c8fe18899dcerion   - Floating Point:
54edf7fc572e2decb93e9143961e8739c8fe18899dcerion     - All exceptions disabled in FPSCR
55edf7fc572e2decb93e9143961e8739c8fe18899dcerion     - condition codes not set in FPSCR
56edf7fc572e2decb93e9143961e8739c8fe18899dcerion
57edf7fc572e2decb93e9143961e8739c8fe18899dcerion   - Altivec floating point:
58edf7fc572e2decb93e9143961e8739c8fe18899dcerion     - vmaddfp, vnmsubfp
59edf7fc572e2decb93e9143961e8739c8fe18899dcerion       Because we're using Java/IEEE mode (FPSCR[NJ]), rather than the
60edf7fc572e2decb93e9143961e8739c8fe18899dcerion       system default of Non-Java mode, we get some small errors
61edf7fc572e2decb93e9143961e8739c8fe18899dcerion       (lowest bit only).
62edf7fc572e2decb93e9143961e8739c8fe18899dcerion       This is because Non-Java mode brutally hacks denormalised results
63edf7fc572e2decb93e9143961e8739c8fe18899dcerion       to zero, whereas we keep maximum accuracy.  However, using
64edf7fc572e2decb93e9143961e8739c8fe18899dcerion       Non-Java mode would give us more inaccuracy, as our intermediate
65edf7fc572e2decb93e9143961e8739c8fe18899dcerion       results would then be zeroed, too.
66cf8986c47a4c8c810566bb5b7b3da7a16a17dfe2sewardj
67aca070a5b3418a6a9b01e3c57a7eb0fbb5050908sewardj   - AbiHints for the stack red zone are only emitted for
68cf8986c47a4c8c810566bb5b7b3da7a16a17dfe2sewardj       unconditional calls and returns (bl, blr).  They should also be
69cf8986c47a4c8c810566bb5b7b3da7a16a17dfe2sewardj       emitted for conditional calls and returns, but we don't have a
70cf8986c47a4c8c810566bb5b7b3da7a16a17dfe2sewardj       way to express that right now.  Ah well.
7120a760ec66a13a93147a40d3c3530be21d7fe411sewardj
7220a760ec66a13a93147a40d3c3530be21d7fe411sewardj   - Uses of Iop_{Add,Sub,Mul}32Fx4: the backend (host_ppc_isel.c)
7320a760ec66a13a93147a40d3c3530be21d7fe411sewardj       ignores the rounding mode, and generates code that assumes
7420a760ec66a13a93147a40d3c3530be21d7fe411sewardj       round-to-nearest.  This means V will compute incorrect results
7520a760ec66a13a93147a40d3c3530be21d7fe411sewardj       for uses of these IROps when the rounding mode (first) arg is
7620a760ec66a13a93147a40d3c3530be21d7fe411sewardj       not mkU32(Irrm_NEAREST).
77b51f0f4f33256638ed953156a2635aa739b232f1sewardj*/
78b51f0f4f33256638ed953156a2635aa739b232f1sewardj
79ce02aa77bc02dbe225a068df0fb6b31faddedcdfsewardj/* "Special" instructions.
80ce02aa77bc02dbe225a068df0fb6b31faddedcdfsewardj
8109e88d11fceef4483f7803414b939e4173fe7f54sewardj   This instruction decoder can decode four special instructions
82ce02aa77bc02dbe225a068df0fb6b31faddedcdfsewardj   which mean nothing natively (are no-ops as far as regs/mem are
83ce02aa77bc02dbe225a068df0fb6b31faddedcdfsewardj   concerned) but have meaning for supporting Valgrind.  A special
841eb7e6b8f521143c9c4971b2cea36ade611c5da9sewardj   instruction is flagged by a 16-byte preamble:
851eb7e6b8f521143c9c4971b2cea36ade611c5da9sewardj
862171afd42a0168b49b06dbe723b606046e902099sewardj      32-bit mode: 5400183E 5400683E 5400E83E 5400983E
872171afd42a0168b49b06dbe723b606046e902099sewardj                   (rlwinm 0,0,3,0,31; rlwinm 0,0,13,0,31;
882171afd42a0168b49b06dbe723b606046e902099sewardj                    rlwinm 0,0,29,0,31; rlwinm 0,0,19,0,31)
891eb7e6b8f521143c9c4971b2cea36ade611c5da9sewardj
901eb7e6b8f521143c9c4971b2cea36ade611c5da9sewardj      64-bit mode: 78001800 78006800 7800E802 78009802
911eb7e6b8f521143c9c4971b2cea36ade611c5da9sewardj                   (rotldi 0,0,3; rotldi 0,0,13;
921eb7e6b8f521143c9c4971b2cea36ade611c5da9sewardj                    rotldi 0,0,61; rotldi 0,0,51)
931eb7e6b8f521143c9c4971b2cea36ade611c5da9sewardj
941eb7e6b8f521143c9c4971b2cea36ade611c5da9sewardj   Following that, one of the following 3 are allowed
95ce02aa77bc02dbe225a068df0fb6b31faddedcdfsewardj   (standard interpretation in parentheses):
96ce02aa77bc02dbe225a068df0fb6b31faddedcdfsewardj
97ce02aa77bc02dbe225a068df0fb6b31faddedcdfsewardj      7C210B78 (or 1,1,1)   %R3 = client_request ( %R4 )
98ce02aa77bc02dbe225a068df0fb6b31faddedcdfsewardj      7C421378 (or 2,2,2)   %R3 = guest_NRADDR
991f5fe1fc3a37ca729925e8eec25aa1025b4a6cdbcarll      7C631B78 (or 3,3,3)   branch-and-link-to-noredir %R11  Big endian
1001f5fe1fc3a37ca729925e8eec25aa1025b4a6cdbcarll      7C631B78 (or 3,3,3)   branch-and-link-to-noredir %R12  Little endian
101aca070a5b3418a6a9b01e3c57a7eb0fbb5050908sewardj      7C842378 (or 4,4,4)   %R3 = guest_NRADDR_GPR2
1022245ce9e834193d49261b8a433b4a0bd128c878eflorian      7CA52B78 (or 5,5,5)   IR injection
103ce02aa77bc02dbe225a068df0fb6b31faddedcdfsewardj
104ce02aa77bc02dbe225a068df0fb6b31faddedcdfsewardj   Any other bytes following the 16-byte preamble are illegal and
105ce02aa77bc02dbe225a068df0fb6b31faddedcdfsewardj   constitute a failure in instruction decoding.  This all assumes
106ce02aa77bc02dbe225a068df0fb6b31faddedcdfsewardj   that the preamble will never occur except in specific code
107ce02aa77bc02dbe225a068df0fb6b31faddedcdfsewardj   fragments designed for Valgrind to catch.
108ce02aa77bc02dbe225a068df0fb6b31faddedcdfsewardj*/
109ce02aa77bc02dbe225a068df0fb6b31faddedcdfsewardj
1101f5fe1fc3a37ca729925e8eec25aa1025b4a6cdbcarll/*  Little Endian notes  */
1111f5fe1fc3a37ca729925e8eec25aa1025b4a6cdbcarll/*
1121f5fe1fc3a37ca729925e8eec25aa1025b4a6cdbcarll * Vector operations in little Endian mode behave in non-obvious ways at times.
1131f5fe1fc3a37ca729925e8eec25aa1025b4a6cdbcarll * Below is an attempt at explaining this.
1141f5fe1fc3a37ca729925e8eec25aa1025b4a6cdbcarll *
1151f5fe1fc3a37ca729925e8eec25aa1025b4a6cdbcarll * LE/BE vector example
1161f5fe1fc3a37ca729925e8eec25aa1025b4a6cdbcarll *   With a vector of unsigned ints declared as follows:
1171f5fe1fc3a37ca729925e8eec25aa1025b4a6cdbcarll *     vector unsigned int vec_inA =
1181f5fe1fc3a37ca729925e8eec25aa1025b4a6cdbcarll                            { 0x11111111, 0x22222222, 0x33333333, 0x44444444 };
1191f5fe1fc3a37ca729925e8eec25aa1025b4a6cdbcarll *   The '0x11111111' word is word zero in both LE and BE format.  But the
1201f5fe1fc3a37ca729925e8eec25aa1025b4a6cdbcarll *   loaded vector register will have word zero on the far left in BE mode and
1211f5fe1fc3a37ca729925e8eec25aa1025b4a6cdbcarll *   on the far right in LE mode. The lvx and stvx instructions work naturally
1221f5fe1fc3a37ca729925e8eec25aa1025b4a6cdbcarll *   for whatever endianness is in effect.  For example, in LE mode, the stvx
1231f5fe1fc3a37ca729925e8eec25aa1025b4a6cdbcarll *   stores word zero (far right word) of the vector at the lowest memory
1241f5fe1fc3a37ca729925e8eec25aa1025b4a6cdbcarll *   address of the EA; in BE mode, stvx still stores word zero at the lowest
1251f5fe1fc3a37ca729925e8eec25aa1025b4a6cdbcarll *   memory address, but with word zero interpreted as the one at the far left
1261f5fe1fc3a37ca729925e8eec25aa1025b4a6cdbcarll *   of the register.
1271f5fe1fc3a37ca729925e8eec25aa1025b4a6cdbcarll *
1281f5fe1fc3a37ca729925e8eec25aa1025b4a6cdbcarll *   The lxvd2x and stxvd2x instructions are not so well suited for LE mode.
1291f5fe1fc3a37ca729925e8eec25aa1025b4a6cdbcarll *   When the compiler generates an lxvd2x instruction to load the
1301f5fe1fc3a37ca729925e8eec25aa1025b4a6cdbcarll *   above-declared vector of unsigned integers, it loads the vector as two
1311f5fe1fc3a37ca729925e8eec25aa1025b4a6cdbcarll *   double words, but they are in BE word-wise format.  To put the vector in
1321f5fe1fc3a37ca729925e8eec25aa1025b4a6cdbcarll *   the right order for LE, the compiler also generates an xxswapd after the
1331f5fe1fc3a37ca729925e8eec25aa1025b4a6cdbcarll *   load, which puts it in proper LE format.  Similarly, the stxvd2x
1341f5fe1fc3a37ca729925e8eec25aa1025b4a6cdbcarll *   instruction has a BE bias, storing the vector in BE word-wise format. But
1351f5fe1fc3a37ca729925e8eec25aa1025b4a6cdbcarll *   the compiler also generates an xxswapd prior to the store, thus ensuring
1361f5fe1fc3a37ca729925e8eec25aa1025b4a6cdbcarll *   the vector is stored in memory in the correct LE order.
1371f5fe1fc3a37ca729925e8eec25aa1025b4a6cdbcarll *
1381f5fe1fc3a37ca729925e8eec25aa1025b4a6cdbcarll *   Vector-flavored Iops, such Iop_V128Hito64, reference the hi and lo parts
1391f5fe1fc3a37ca729925e8eec25aa1025b4a6cdbcarll *   of a double words and words within a vector.  Because of the reverse order
1401f5fe1fc3a37ca729925e8eec25aa1025b4a6cdbcarll *   of numbering for LE as described above, the high part refers to word 1 in
1411f5fe1fc3a37ca729925e8eec25aa1025b4a6cdbcarll *   LE format. When input data is saved to a guest state vector register
1421f5fe1fc3a37ca729925e8eec25aa1025b4a6cdbcarll *   (e.g., via Iop_64HLtoV128), it is first saved to memory and then the
1431f5fe1fc3a37ca729925e8eec25aa1025b4a6cdbcarll *   register is loaded via PPCInstr_AvLdSt, which does an lvx instruction.
1441f5fe1fc3a37ca729925e8eec25aa1025b4a6cdbcarll *   The saving of the data to memory must be done in proper LE order.  For the
1451f5fe1fc3a37ca729925e8eec25aa1025b4a6cdbcarll *   inverse operation of extracting data from a vector register (e.g.,
1461f5fe1fc3a37ca729925e8eec25aa1025b4a6cdbcarll *   Iop_V128Hito64), the register is first saved (by PPCInstr_AvLdSt resulting
1471f5fe1fc3a37ca729925e8eec25aa1025b4a6cdbcarll *   in stvx), and then integer registers are loaded from the memory location
1481f5fe1fc3a37ca729925e8eec25aa1025b4a6cdbcarll *   from where the vector register was saved.  Again, this must be done in
1491f5fe1fc3a37ca729925e8eec25aa1025b4a6cdbcarll *   proper LE order.  So for these various vector Iops, we have LE-specific
1501f5fe1fc3a37ca729925e8eec25aa1025b4a6cdbcarll *   code in host_ppc_isel.c
1511f5fe1fc3a37ca729925e8eec25aa1025b4a6cdbcarll *
1521f5fe1fc3a37ca729925e8eec25aa1025b4a6cdbcarll *   Another unique behavior of vectors in LE mode is with the vector scalar
1531f5fe1fc3a37ca729925e8eec25aa1025b4a6cdbcarll *   (VSX) operations that operate on "double word 0" of the source register,
1541f5fe1fc3a37ca729925e8eec25aa1025b4a6cdbcarll *   storing the result in "double word 0" of the output vector register.  For
1551f5fe1fc3a37ca729925e8eec25aa1025b4a6cdbcarll *   these operations, "double word 0" is interpreted as "high half of the
1561f5fe1fc3a37ca729925e8eec25aa1025b4a6cdbcarll *   register" (i.e, the part on the left side).
1571f5fe1fc3a37ca729925e8eec25aa1025b4a6cdbcarll *
1581f5fe1fc3a37ca729925e8eec25aa1025b4a6cdbcarll */
1595b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion/* Translates PPC32/64 code to IR. */
160896a1373cfdbaa25f4ab73ed4f27554016defecccerion
161645c930b1a61f4493ee2d472b34fbb439233a874cerion/* References
162a982c0503d8c0c6069ae453bfe70657bd2c134aecerion
163a982c0503d8c0c6069ae453bfe70657bd2c134aecerion#define PPC32
164645c930b1a61f4493ee2d472b34fbb439233a874cerion   "PowerPC Microprocessor Family:
165d953ebb9b04cbad6891676df597bf0c542b1ec89cerion    The Programming Environments Manual for 32-Bit Microprocessors"
166e9d361ab43518b6dfbd3d846f48859534659dee0cerion    02/21/2000
167e9d361ab43518b6dfbd3d846f48859534659dee0cerion    http://www-3.ibm.com/chips/techlib/techlib.nsf/techdocs/852569B20050FF778525699600719DF2
168e9d361ab43518b6dfbd3d846f48859534659dee0cerion
169d953ebb9b04cbad6891676df597bf0c542b1ec89cerion#define PPC64
170d953ebb9b04cbad6891676df597bf0c542b1ec89cerion   "PowerPC Microprocessor Family:
171d953ebb9b04cbad6891676df597bf0c542b1ec89cerion    Programming Environments Manual for 64-Bit Microprocessors"
172d953ebb9b04cbad6891676df597bf0c542b1ec89cerion    06/10/2003
173d953ebb9b04cbad6891676df597bf0c542b1ec89cerion   http://www-3.ibm.com/chips/techlib/techlib.nsf/techdocs/F7E732FF811F783187256FDD004D3797
174d953ebb9b04cbad6891676df597bf0c542b1ec89cerion
175a982c0503d8c0c6069ae453bfe70657bd2c134aecerion#define AV
176a982c0503d8c0c6069ae453bfe70657bd2c134aecerion   "PowerPC Microprocessor Family:
177a982c0503d8c0c6069ae453bfe70657bd2c134aecerion    AltiVec(TM) Technology Programming Environments Manual"
178a982c0503d8c0c6069ae453bfe70657bd2c134aecerion    07/10/2003
179a982c0503d8c0c6069ae453bfe70657bd2c134aecerion   http://www-3.ibm.com/chips/techlib/techlib.nsf/techdocs/FBFA164F824370F987256D6A006F424D
180645c930b1a61f4493ee2d472b34fbb439233a874cerion*/
181645c930b1a61f4493ee2d472b34fbb439233a874cerion
182896a1373cfdbaa25f4ab73ed4f27554016defecccerion#include "libvex_basictypes.h"
183896a1373cfdbaa25f4ab73ed4f27554016defecccerion#include "libvex_ir.h"
184896a1373cfdbaa25f4ab73ed4f27554016defecccerion#include "libvex.h"
18558a637b6675d4d68e13d18b75cea7eee2a2a91feflorian#include "libvex_emnote.h"
1861515db99ce1abcd2147ac54aea1a7090c7895a43cerion#include "libvex_guest_ppc32.h"
187d953ebb9b04cbad6891676df597bf0c542b1ec89cerion#include "libvex_guest_ppc64.h"
188896a1373cfdbaa25f4ab73ed4f27554016defecccerion
189cef7d3e3df4796e35b4521158d9dc058f034aa87sewardj#include "main_util.h"
190cef7d3e3df4796e35b4521158d9dc058f034aa87sewardj#include "main_globals.h"
191cef7d3e3df4796e35b4521158d9dc058f034aa87sewardj#include "guest_generic_bb_to_IR.h"
192cef7d3e3df4796e35b4521158d9dc058f034aa87sewardj#include "guest_ppc_defs.h"
193896a1373cfdbaa25f4ab73ed4f27554016defecccerion
194896a1373cfdbaa25f4ab73ed4f27554016defecccerion/*------------------------------------------------------------*/
195896a1373cfdbaa25f4ab73ed4f27554016defecccerion/*--- Globals                                              ---*/
196896a1373cfdbaa25f4ab73ed4f27554016defecccerion/*------------------------------------------------------------*/
197896a1373cfdbaa25f4ab73ed4f27554016defecccerion
1989e6491ab55324b8e45e187b1e1e9632ac3cb3e27sewardj/* These are set at the start of the translation of an insn, right
1995b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion   down in disInstr_PPC, so that we don't have to pass them around
2009e6491ab55324b8e45e187b1e1e9632ac3cb3e27sewardj   endlessly.  They are all constant during the translation of any
2019e6491ab55324b8e45e187b1e1e9632ac3cb3e27sewardj   given insn. */
202896a1373cfdbaa25f4ab73ed4f27554016defecccerion
203ed623dbefb52ca3211490d656abc999a129df060cerion/* We need to know this to do sub-register accesses correctly. */
2049b76916dcc1628e133d57db001563429c6e3a590sewardjstatic VexEndness host_endness;
205ed623dbefb52ca3211490d656abc999a129df060cerion
206896a1373cfdbaa25f4ab73ed4f27554016defecccerion/* Pointer to the guest code area. */
2078462d113e3efeacceb304222dada8d85f748295aflorianstatic const UChar* guest_code;
208896a1373cfdbaa25f4ab73ed4f27554016defecccerion
209896a1373cfdbaa25f4ab73ed4f27554016defecccerion/* The guest address corresponding to guest_code[0]. */
210d953ebb9b04cbad6891676df597bf0c542b1ec89cerionstatic Addr64 guest_CIA_bbstart;
211896a1373cfdbaa25f4ab73ed4f27554016defecccerion
21201a9e808708130f82e935336c887c1bee2d89036sewardj/* The guest address for the instruction currently being
21301a9e808708130f82e935336c887c1bee2d89036sewardj   translated. */
214d953ebb9b04cbad6891676df597bf0c542b1ec89cerionstatic Addr64 guest_CIA_curr_instr;
21501a9e808708130f82e935336c887c1bee2d89036sewardj
216dd40fdf58cc8a6fe9466c4f00bdfc9fe9bf00449sewardj/* The IRSB* into which we're generating code. */
217dd40fdf58cc8a6fe9466c4f00bdfc9fe9bf00449sewardjstatic IRSB* irsb;
218896a1373cfdbaa25f4ab73ed4f27554016defecccerion
2195df65bb742f389a45657a0a6f4a9e46a33025407sewardj/* Is our guest binary 32 or 64bit?  Set at each call to
2205b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion   disInstr_PPC below. */
2215df65bb742f389a45657a0a6f4a9e46a33025407sewardjstatic Bool mode64 = False;
222d953ebb9b04cbad6891676df597bf0c542b1ec89cerion
2234c4f5ef69f89a19844a22a34b7a0cb717f83f033cerion// Given a pointer to a function as obtained by "& functionname" in C,
2244c4f5ef69f89a19844a22a34b7a0cb717f83f033cerion// produce a pointer to the actual entry point for the function.  For
2254c4f5ef69f89a19844a22a34b7a0cb717f83f033cerion// most platforms it's the identity function.  Unfortunately, on
2262322360949754bdcaa87e5ea704480e0b267b09aflorian// ppc64-linux it isn't (sigh)
227cacba8e675988fbf21b08feea1f317a9c896c053florianstatic void* fnptr_to_fnentry( const VexAbiInfo* vbi, void* f )
228aca070a5b3418a6a9b01e3c57a7eb0fbb5050908sewardj{
229dd40fdf58cc8a6fe9466c4f00bdfc9fe9bf00449sewardj   if (vbi->host_ppc_calls_use_fndescrs) {
230aca070a5b3418a6a9b01e3c57a7eb0fbb5050908sewardj      /* f is a pointer to a 3-word function descriptor, of which the
231aca070a5b3418a6a9b01e3c57a7eb0fbb5050908sewardj         first word is the entry address. */
232aca070a5b3418a6a9b01e3c57a7eb0fbb5050908sewardj      /* note, this is correct even with cross-jitting, since this is
233aca070a5b3418a6a9b01e3c57a7eb0fbb5050908sewardj         purely a host issue, not a guest one. */
234aca070a5b3418a6a9b01e3c57a7eb0fbb5050908sewardj      HWord* fdescr = (HWord*)f;
235aca070a5b3418a6a9b01e3c57a7eb0fbb5050908sewardj      return (void*)(fdescr[0]);
236aca070a5b3418a6a9b01e3c57a7eb0fbb5050908sewardj   } else {
237aca070a5b3418a6a9b01e3c57a7eb0fbb5050908sewardj      /* Simple; "& f" points directly at the code for f. */
238aca070a5b3418a6a9b01e3c57a7eb0fbb5050908sewardj      return f;
239aca070a5b3418a6a9b01e3c57a7eb0fbb5050908sewardj   }
2404c4f5ef69f89a19844a22a34b7a0cb717f83f033cerion}
2414c4f5ef69f89a19844a22a34b7a0cb717f83f033cerion
2424aa412af1d8166cc11f39a6e721df49431d23618sewardj#define SIGN_BIT  0x8000000000000000ULL
2434aa412af1d8166cc11f39a6e721df49431d23618sewardj#define SIGN_MASK 0x7fffffffffffffffULL
2444aa412af1d8166cc11f39a6e721df49431d23618sewardj#define SIGN_BIT32  0x80000000
2454aa412af1d8166cc11f39a6e721df49431d23618sewardj#define SIGN_MASK32 0x7fffffff
2464aa412af1d8166cc11f39a6e721df49431d23618sewardj
247896a1373cfdbaa25f4ab73ed4f27554016defecccerion
248896a1373cfdbaa25f4ab73ed4f27554016defecccerion/*------------------------------------------------------------*/
249896a1373cfdbaa25f4ab73ed4f27554016defecccerion/*--- Debugging output                                     ---*/
250896a1373cfdbaa25f4ab73ed4f27554016defecccerion/*------------------------------------------------------------*/
251896a1373cfdbaa25f4ab73ed4f27554016defecccerion
252896a1373cfdbaa25f4ab73ed4f27554016defecccerion#define DIP(format, args...)           \
253896a1373cfdbaa25f4ab73ed4f27554016defecccerion   if (vex_traceflags & VEX_TRACE_FE)  \
254896a1373cfdbaa25f4ab73ed4f27554016defecccerion      vex_printf(format, ## args)
255896a1373cfdbaa25f4ab73ed4f27554016defecccerion
256896a1373cfdbaa25f4ab73ed4f27554016defecccerion#define DIS(buf, format, args...)      \
257896a1373cfdbaa25f4ab73ed4f27554016defecccerion   if (vex_traceflags & VEX_TRACE_FE)  \
258896a1373cfdbaa25f4ab73ed4f27554016defecccerion      vex_sprintf(buf, format, ## args)
259896a1373cfdbaa25f4ab73ed4f27554016defecccerion
260896a1373cfdbaa25f4ab73ed4f27554016defecccerion
261896a1373cfdbaa25f4ab73ed4f27554016defecccerion/*------------------------------------------------------------*/
262d953ebb9b04cbad6891676df597bf0c542b1ec89cerion/*--- Offsets of various parts of the ppc32/64 guest state ---*/
263896a1373cfdbaa25f4ab73ed4f27554016defecccerion/*------------------------------------------------------------*/
264896a1373cfdbaa25f4ab73ed4f27554016defecccerion
2655b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion#define offsetofPPCGuestState(_x) \
2665b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion   (mode64 ? offsetof(VexGuestPPC64State, _x) : \
2675b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion             offsetof(VexGuestPPC32State, _x))
268d953ebb9b04cbad6891676df597bf0c542b1ec89cerion
269aca070a5b3418a6a9b01e3c57a7eb0fbb5050908sewardj#define OFFB_CIA         offsetofPPCGuestState(guest_CIA)
270e86310f555a233cc2ca02e1a5d0adb555f12bdcdsewardj#define OFFB_IP_AT_SYSCALL offsetofPPCGuestState(guest_IP_AT_SYSCALL)
271aca070a5b3418a6a9b01e3c57a7eb0fbb5050908sewardj#define OFFB_SPRG3_RO    offsetofPPCGuestState(guest_SPRG3_RO)
272aca070a5b3418a6a9b01e3c57a7eb0fbb5050908sewardj#define OFFB_LR          offsetofPPCGuestState(guest_LR)
273aca070a5b3418a6a9b01e3c57a7eb0fbb5050908sewardj#define OFFB_CTR         offsetofPPCGuestState(guest_CTR)
274aca070a5b3418a6a9b01e3c57a7eb0fbb5050908sewardj#define OFFB_XER_SO      offsetofPPCGuestState(guest_XER_SO)
275aca070a5b3418a6a9b01e3c57a7eb0fbb5050908sewardj#define OFFB_XER_OV      offsetofPPCGuestState(guest_XER_OV)
276aca070a5b3418a6a9b01e3c57a7eb0fbb5050908sewardj#define OFFB_XER_CA      offsetofPPCGuestState(guest_XER_CA)
277aca070a5b3418a6a9b01e3c57a7eb0fbb5050908sewardj#define OFFB_XER_BC      offsetofPPCGuestState(guest_XER_BC)
278aca070a5b3418a6a9b01e3c57a7eb0fbb5050908sewardj#define OFFB_FPROUND     offsetofPPCGuestState(guest_FPROUND)
279c6bbd470e9bd9898b84959227a406d3972d95f3bsewardj#define OFFB_DFPROUND    offsetofPPCGuestState(guest_DFPROUND)
280aca070a5b3418a6a9b01e3c57a7eb0fbb5050908sewardj#define OFFB_VRSAVE      offsetofPPCGuestState(guest_VRSAVE)
281aca070a5b3418a6a9b01e3c57a7eb0fbb5050908sewardj#define OFFB_VSCR        offsetofPPCGuestState(guest_VSCR)
2826ef84bed9bb3af22060eb1759788034602bbcc88florian#define OFFB_EMNOTE      offsetofPPCGuestState(guest_EMNOTE)
28305f5e0172384dd2983fb16fbb7deebd74d71cd35sewardj#define OFFB_CMSTART     offsetofPPCGuestState(guest_CMSTART)
28405f5e0172384dd2983fb16fbb7deebd74d71cd35sewardj#define OFFB_CMLEN       offsetofPPCGuestState(guest_CMLEN)
285aca070a5b3418a6a9b01e3c57a7eb0fbb5050908sewardj#define OFFB_NRADDR      offsetofPPCGuestState(guest_NRADDR)
286aca070a5b3418a6a9b01e3c57a7eb0fbb5050908sewardj#define OFFB_NRADDR_GPR2 offsetofPPCGuestState(guest_NRADDR_GPR2)
2878943d02aa373f45c6e5fdcbe5947620285d442b1carll#define OFFB_TFHAR       offsetofPPCGuestState(guest_TFHAR)
2888943d02aa373f45c6e5fdcbe5947620285d442b1carll#define OFFB_TEXASR      offsetofPPCGuestState(guest_TEXASR)
289486db12d4767b5c2cc5ae764616e758f30ce21f5carll#define OFFB_TEXASRU     offsetofPPCGuestState(guest_TEXASRU)
2908943d02aa373f45c6e5fdcbe5947620285d442b1carll#define OFFB_TFIAR       offsetofPPCGuestState(guest_TFIAR)
291ed013fe8f56c070823d15f31ec010093f5de00dacarll#define OFFB_PPR         offsetofPPCGuestState(guest_PPR)
292ed013fe8f56c070823d15f31ec010093f5de00dacarll#define OFFB_PSPB        offsetofPPCGuestState(guest_PSPB)
2935ff11ddafe3e0080711657a1cf581e1a64dbf117sewardj
29491ad5368eb6354ad4fabc86f2b2e641736997a38cerion
2953867460f7533d6dc4e2c85656664ee341ea81e7dcerion/*------------------------------------------------------------*/
296b51f0f4f33256638ed953156a2635aa739b232f1sewardj/*--- Extract instruction fields                          --- */
2973867460f7533d6dc4e2c85656664ee341ea81e7dcerion/*------------------------------------------------------------*/
298e9d361ab43518b6dfbd3d846f48859534659dee0cerion
29976de5cf615380b23b4b5bcced6541233cd4a93a0cerion/* Extract field from insn, given idx (zero = lsb) and field length */
30076de5cf615380b23b4b5bcced6541233cd4a93a0cerion#define IFIELD( insn, idx, len ) ((insn >> idx) & ((1<<len)-1))
30176de5cf615380b23b4b5bcced6541233cd4a93a0cerion
302b51f0f4f33256638ed953156a2635aa739b232f1sewardj/* Extract primary opcode, instr[31:26] */
30376de5cf615380b23b4b5bcced6541233cd4a93a0cerionstatic UChar ifieldOPC( UInt instr ) {
30476de5cf615380b23b4b5bcced6541233cd4a93a0cerion   return toUChar( IFIELD( instr, 26, 6 ) );
305b51f0f4f33256638ed953156a2635aa739b232f1sewardj}
306b51f0f4f33256638ed953156a2635aa739b232f1sewardj
30776de5cf615380b23b4b5bcced6541233cd4a93a0cerion/* Extract 10-bit secondary opcode, instr[10:1] */
308b51f0f4f33256638ed953156a2635aa739b232f1sewardjstatic UInt ifieldOPClo10 ( UInt instr) {
30976de5cf615380b23b4b5bcced6541233cd4a93a0cerion   return IFIELD( instr, 1, 10 );
31076de5cf615380b23b4b5bcced6541233cd4a93a0cerion}
31176de5cf615380b23b4b5bcced6541233cd4a93a0cerion
31276de5cf615380b23b4b5bcced6541233cd4a93a0cerion/* Extract 9-bit secondary opcode, instr[9:1] */
31376de5cf615380b23b4b5bcced6541233cd4a93a0cerionstatic UInt ifieldOPClo9 ( UInt instr) {
31476de5cf615380b23b4b5bcced6541233cd4a93a0cerion   return IFIELD( instr, 1, 9 );
31576de5cf615380b23b4b5bcced6541233cd4a93a0cerion}
31676de5cf615380b23b4b5bcced6541233cd4a93a0cerion
317cdc376dcb5a4560b0a35d4abcb2146c499756f0dsewardj/* Extract 8-bit secondary opcode, instr[8:1] */
318cdc376dcb5a4560b0a35d4abcb2146c499756f0dsewardjstatic UInt ifieldOPClo8 ( UInt instr) {
319cdc376dcb5a4560b0a35d4abcb2146c499756f0dsewardj   return IFIELD( instr, 1, 8 );
320cdc376dcb5a4560b0a35d4abcb2146c499756f0dsewardj}
321cdc376dcb5a4560b0a35d4abcb2146c499756f0dsewardj
32276de5cf615380b23b4b5bcced6541233cd4a93a0cerion/* Extract 5-bit secondary opcode, instr[5:1] */
32376de5cf615380b23b4b5bcced6541233cd4a93a0cerionstatic UInt ifieldOPClo5 ( UInt instr) {
32476de5cf615380b23b4b5bcced6541233cd4a93a0cerion   return IFIELD( instr, 1, 5 );
325b51f0f4f33256638ed953156a2635aa739b232f1sewardj}
326b51f0f4f33256638ed953156a2635aa739b232f1sewardj
327b51f0f4f33256638ed953156a2635aa739b232f1sewardj/* Extract RD (destination register) field, instr[25:21] */
32876de5cf615380b23b4b5bcced6541233cd4a93a0cerionstatic UChar ifieldRegDS( UInt instr ) {
32976de5cf615380b23b4b5bcced6541233cd4a93a0cerion   return toUChar( IFIELD( instr, 21, 5 ) );
33076de5cf615380b23b4b5bcced6541233cd4a93a0cerion}
33176de5cf615380b23b4b5bcced6541233cd4a93a0cerion
33266d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj/* Extract XT (destination register) field, instr[0,25:21] */
33366d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardjstatic UChar ifieldRegXT ( UInt instr )
33466d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj{
33566d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj  UChar upper_bit = toUChar (IFIELD (instr, 0, 1));
33666d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj  UChar lower_bits = toUChar (IFIELD (instr, 21, 5));
33766d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj  return (upper_bit << 5) | lower_bits;
33866d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj}
33966d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj
34066d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj/* Extract XS (store source register) field, instr[0,25:21] */
34166d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardjstatic inline UChar ifieldRegXS ( UInt instr )
34266d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj{
34366d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj  return ifieldRegXT ( instr );
34466d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj}
34566d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj
34676de5cf615380b23b4b5bcced6541233cd4a93a0cerion/* Extract RA (1st source register) field, instr[20:16] */
34776de5cf615380b23b4b5bcced6541233cd4a93a0cerionstatic UChar ifieldRegA ( UInt instr ) {
34876de5cf615380b23b4b5bcced6541233cd4a93a0cerion   return toUChar( IFIELD( instr, 16, 5 ) );
34976de5cf615380b23b4b5bcced6541233cd4a93a0cerion}
35076de5cf615380b23b4b5bcced6541233cd4a93a0cerion
35166d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj/* Extract XA (1st source register) field, instr[2,20:16] */
35266d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardjstatic UChar ifieldRegXA ( UInt instr )
35366d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj{
35466d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj  UChar upper_bit = toUChar (IFIELD (instr, 2, 1));
35566d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj  UChar lower_bits = toUChar (IFIELD (instr, 16, 5));
35666d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj  return (upper_bit << 5) | lower_bits;
35766d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj}
35866d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj
35976de5cf615380b23b4b5bcced6541233cd4a93a0cerion/* Extract RB (2nd source register) field, instr[15:11] */
36076de5cf615380b23b4b5bcced6541233cd4a93a0cerionstatic UChar ifieldRegB ( UInt instr ) {
36176de5cf615380b23b4b5bcced6541233cd4a93a0cerion   return toUChar( IFIELD( instr, 11, 5 ) );
362b51f0f4f33256638ed953156a2635aa739b232f1sewardj}
363b51f0f4f33256638ed953156a2635aa739b232f1sewardj
36466d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj/* Extract XB (2nd source register) field, instr[1,15:11] */
36566d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardjstatic UChar ifieldRegXB ( UInt instr )
36666d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj{
36766d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj  UChar upper_bit = toUChar (IFIELD (instr, 1, 1));
36866d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj  UChar lower_bits = toUChar (IFIELD (instr, 11, 5));
36966d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj  return (upper_bit << 5) | lower_bits;
37066d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj}
37166d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj
37276de5cf615380b23b4b5bcced6541233cd4a93a0cerion/* Extract RC (3rd source register) field, instr[10:6] */
37376de5cf615380b23b4b5bcced6541233cd4a93a0cerionstatic UChar ifieldRegC ( UInt instr ) {
37476de5cf615380b23b4b5bcced6541233cd4a93a0cerion   return toUChar( IFIELD( instr, 6, 5 ) );
375b51f0f4f33256638ed953156a2635aa739b232f1sewardj}
376b51f0f4f33256638ed953156a2635aa739b232f1sewardj
3774aa412af1d8166cc11f39a6e721df49431d23618sewardj/* Extract XC (3rd source register) field, instr[3,10:6] */
3784aa412af1d8166cc11f39a6e721df49431d23618sewardjstatic UChar ifieldRegXC ( UInt instr )
3794aa412af1d8166cc11f39a6e721df49431d23618sewardj{
3804aa412af1d8166cc11f39a6e721df49431d23618sewardj  UChar upper_bit = toUChar (IFIELD (instr, 3, 1));
3814aa412af1d8166cc11f39a6e721df49431d23618sewardj  UChar lower_bits = toUChar (IFIELD (instr, 6, 5));
3824aa412af1d8166cc11f39a6e721df49431d23618sewardj  return (upper_bit << 5) | lower_bits;
3834aa412af1d8166cc11f39a6e721df49431d23618sewardj}
3844aa412af1d8166cc11f39a6e721df49431d23618sewardj
38566d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj/* Extract bit 10, instr[10] */
38676de5cf615380b23b4b5bcced6541233cd4a93a0cerionstatic UChar ifieldBIT10 ( UInt instr ) {
38776de5cf615380b23b4b5bcced6541233cd4a93a0cerion   return toUChar( IFIELD( instr, 10, 1 ) );
388b51f0f4f33256638ed953156a2635aa739b232f1sewardj}
389b51f0f4f33256638ed953156a2635aa739b232f1sewardj
39076de5cf615380b23b4b5bcced6541233cd4a93a0cerion/* Extract 2nd lowest bit, instr[1] */
39176de5cf615380b23b4b5bcced6541233cd4a93a0cerionstatic UChar ifieldBIT1 ( UInt instr ) {
39276de5cf615380b23b4b5bcced6541233cd4a93a0cerion   return toUChar( IFIELD( instr, 1, 1 ) );
393b51f0f4f33256638ed953156a2635aa739b232f1sewardj}
394e9d361ab43518b6dfbd3d846f48859534659dee0cerion
39576de5cf615380b23b4b5bcced6541233cd4a93a0cerion/* Extract lowest bit, instr[0] */
39676de5cf615380b23b4b5bcced6541233cd4a93a0cerionstatic UChar ifieldBIT0 ( UInt instr ) {
39776de5cf615380b23b4b5bcced6541233cd4a93a0cerion   return toUChar( instr & 0x1 );
39876de5cf615380b23b4b5bcced6541233cd4a93a0cerion}
39976de5cf615380b23b4b5bcced6541233cd4a93a0cerion
40076de5cf615380b23b4b5bcced6541233cd4a93a0cerion/* Extract unsigned bottom half, instr[15:0] */
40176de5cf615380b23b4b5bcced6541233cd4a93a0cerionstatic UInt ifieldUIMM16 ( UInt instr ) {
40276de5cf615380b23b4b5bcced6541233cd4a93a0cerion   return instr & 0xFFFF;
40376de5cf615380b23b4b5bcced6541233cd4a93a0cerion}
40476de5cf615380b23b4b5bcced6541233cd4a93a0cerion
405d953ebb9b04cbad6891676df597bf0c542b1ec89cerion/* Extract unsigned bottom 26 bits, instr[25:0] */
406d953ebb9b04cbad6891676df597bf0c542b1ec89cerionstatic UInt ifieldUIMM26 ( UInt instr ) {
407d953ebb9b04cbad6891676df597bf0c542b1ec89cerion   return instr & 0x3FFFFFF;
40876de5cf615380b23b4b5bcced6541233cd4a93a0cerion}
40976de5cf615380b23b4b5bcced6541233cd4a93a0cerion
41066d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj/* Extract DM field, instr[9:8] */
41166d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardjstatic UChar ifieldDM ( UInt instr ) {
41266d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj   return toUChar( IFIELD( instr, 8, 2 ) );
41366d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj}
41466d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj
41566d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj/* Extract SHW field, instr[9:8] */
41666d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardjstatic inline UChar ifieldSHW ( UInt instr )
41766d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj{
41866d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj  return ifieldDM ( instr );
41966d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj}
420094d1397b3f69b1a538e80ab509ea8cd75f4be3bcerion
421edf7fc572e2decb93e9143961e8739c8fe18899dcerion/*------------------------------------------------------------*/
422d953ebb9b04cbad6891676df597bf0c542b1ec89cerion/*--- Guest-state identifiers                              ---*/
423edf7fc572e2decb93e9143961e8739c8fe18899dcerion/*------------------------------------------------------------*/
424094d1397b3f69b1a538e80ab509ea8cd75f4be3bcerion
425e9d361ab43518b6dfbd3d846f48859534659dee0ceriontypedef enum {
426d953ebb9b04cbad6891676df597bf0c542b1ec89cerion    PPC_GST_CIA,    // Current Instruction Address
427d953ebb9b04cbad6891676df597bf0c542b1ec89cerion    PPC_GST_LR,     // Link Register
428d953ebb9b04cbad6891676df597bf0c542b1ec89cerion    PPC_GST_CTR,    // Count Register
429d953ebb9b04cbad6891676df597bf0c542b1ec89cerion    PPC_GST_XER,    // Overflow, carry flags, byte count
430d953ebb9b04cbad6891676df597bf0c542b1ec89cerion    PPC_GST_CR,     // Condition Register
431d953ebb9b04cbad6891676df597bf0c542b1ec89cerion    PPC_GST_FPSCR,  // Floating Point Status/Control Register
432d953ebb9b04cbad6891676df597bf0c542b1ec89cerion    PPC_GST_VRSAVE, // Vector Save/Restore Register
433d953ebb9b04cbad6891676df597bf0c542b1ec89cerion    PPC_GST_VSCR,   // Vector Status and Control Register
434d953ebb9b04cbad6891676df597bf0c542b1ec89cerion    PPC_GST_EMWARN, // Emulation warnings
43505f5e0172384dd2983fb16fbb7deebd74d71cd35sewardj    PPC_GST_CMSTART,// For icbi: start of area to invalidate
43605f5e0172384dd2983fb16fbb7deebd74d71cd35sewardj    PPC_GST_CMLEN,  // For icbi: length of area to invalidate
437e86310f555a233cc2ca02e1a5d0adb555f12bdcdsewardj    PPC_GST_IP_AT_SYSCALL, // the CIA of the most recently executed SC insn
438aca070a5b3418a6a9b01e3c57a7eb0fbb5050908sewardj    PPC_GST_SPRG3_RO, // SPRG3
4398943d02aa373f45c6e5fdcbe5947620285d442b1carll    PPC_GST_TFHAR,  // Transactional Failure Handler Address Register
4408943d02aa373f45c6e5fdcbe5947620285d442b1carll    PPC_GST_TFIAR,  // Transactional Failure Instruction Address Register
4418943d02aa373f45c6e5fdcbe5947620285d442b1carll    PPC_GST_TEXASR, // Transactional EXception And Summary Register
442486db12d4767b5c2cc5ae764616e758f30ce21f5carll    PPC_GST_TEXASRU, // Transactional EXception And Summary Register Upper
443ed013fe8f56c070823d15f31ec010093f5de00dacarll    PPC_GST_PPR,     // Program Priority register
444ed013fe8f56c070823d15f31ec010093f5de00dacarll    PPC_GST_PPR32,   // Upper 32-bits of Program Priority register
445ed013fe8f56c070823d15f31ec010093f5de00dacarll    PPC_GST_PSPB,    /* Problem State Priority Boost register, Note, the
446ed013fe8f56c070823d15f31ec010093f5de00dacarll                      * register is initialized to a non-zero value.  Currently
447ed013fe8f56c070823d15f31ec010093f5de00dacarll                      * Valgrind is not supporting the register value to
448ed013fe8f56c070823d15f31ec010093f5de00dacarll                      * automatically decrement. Could be added later if
449ed013fe8f56c070823d15f31ec010093f5de00dacarll                      * needed.
450ed013fe8f56c070823d15f31ec010093f5de00dacarll                      */
451d953ebb9b04cbad6891676df597bf0c542b1ec89cerion    PPC_GST_MAX
452d953ebb9b04cbad6891676df597bf0c542b1ec89cerion} PPC_GST;
453e9d361ab43518b6dfbd3d846f48859534659dee0cerion
454c6bbd470e9bd9898b84959227a406d3972d95f3bsewardj#define MASK_FPSCR_RN   0x3ULL  // Binary floating point rounding mode
455c6bbd470e9bd9898b84959227a406d3972d95f3bsewardj#define MASK_FPSCR_DRN  0x700000000ULL // Decimal floating point rounding mode
456edf7fc572e2decb93e9143961e8739c8fe18899dcerion#define MASK_VSCR_VALID 0x00010001
457e14bb9f862843c6b804097c124961b5567ded4f1sewardj
458094d1397b3f69b1a538e80ab509ea8cd75f4be3bcerion
459edf7fc572e2decb93e9143961e8739c8fe18899dcerion/*------------------------------------------------------------*/
460edf7fc572e2decb93e9143961e8739c8fe18899dcerion/*---  FP Helpers                                          ---*/
461edf7fc572e2decb93e9143961e8739c8fe18899dcerion/*------------------------------------------------------------*/
4623867460f7533d6dc4e2c85656664ee341ea81e7dcerion
4632ead522cf1c0069fbc55f7c5d1e8b2a00a044d6bsewardj/* Produce the 32-bit pattern corresponding to the supplied
4642ead522cf1c0069fbc55f7c5d1e8b2a00a044d6bsewardj   float. */
4652ead522cf1c0069fbc55f7c5d1e8b2a00a044d6bsewardjstatic UInt float_to_bits ( Float f )
4662ead522cf1c0069fbc55f7c5d1e8b2a00a044d6bsewardj{
4672ead522cf1c0069fbc55f7c5d1e8b2a00a044d6bsewardj   union { UInt i; Float f; } u;
4682ead522cf1c0069fbc55f7c5d1e8b2a00a044d6bsewardj   vassert(4 == sizeof(UInt));
4692ead522cf1c0069fbc55f7c5d1e8b2a00a044d6bsewardj   vassert(4 == sizeof(Float));
4702ead522cf1c0069fbc55f7c5d1e8b2a00a044d6bsewardj   vassert(4 == sizeof(u));
4712ead522cf1c0069fbc55f7c5d1e8b2a00a044d6bsewardj   u.f = f;
4722ead522cf1c0069fbc55f7c5d1e8b2a00a044d6bsewardj   return u.i;
4732ead522cf1c0069fbc55f7c5d1e8b2a00a044d6bsewardj}
4742ead522cf1c0069fbc55f7c5d1e8b2a00a044d6bsewardj
4753867460f7533d6dc4e2c85656664ee341ea81e7dcerion
4763867460f7533d6dc4e2c85656664ee341ea81e7dcerion/*------------------------------------------------------------*/
4773867460f7533d6dc4e2c85656664ee341ea81e7dcerion/*--- Misc Helpers                                         ---*/
4783867460f7533d6dc4e2c85656664ee341ea81e7dcerion/*------------------------------------------------------------*/
4793867460f7533d6dc4e2c85656664ee341ea81e7dcerion
480f0de28cf1a762b0d6f74c93d3532c89a230673bbcerion/* Generate mask with 1's from 'begin' through 'end',
481f0de28cf1a762b0d6f74c93d3532c89a230673bbcerion   wrapping if begin > end.
482f0de28cf1a762b0d6f74c93d3532c89a230673bbcerion   begin->end works from right to left, 0=lsb
483f0de28cf1a762b0d6f74c93d3532c89a230673bbcerion*/
484d953ebb9b04cbad6891676df597bf0c542b1ec89cerionstatic UInt MASK32( UInt begin, UInt end )
4853867460f7533d6dc4e2c85656664ee341ea81e7dcerion{
486633274098fafebdc79cf1c8a1ef7f9a9914669f1sewardj   UInt m1, m2, mask;
487d953ebb9b04cbad6891676df597bf0c542b1ec89cerion   vassert(begin < 32);
488d953ebb9b04cbad6891676df597bf0c542b1ec89cerion   vassert(end < 32);
489633274098fafebdc79cf1c8a1ef7f9a9914669f1sewardj   m1   = ((UInt)(-1)) << begin;
490633274098fafebdc79cf1c8a1ef7f9a9914669f1sewardj   m2   = ((UInt)(-1)) << end << 1;
491633274098fafebdc79cf1c8a1ef7f9a9914669f1sewardj   mask = m1 ^ m2;
492b85e8bba97fdae7d892f7bfd12e4601307e4721dcerion   if (begin > end) mask = ~mask;  // wrap mask
493b85e8bba97fdae7d892f7bfd12e4601307e4721dcerion   return mask;
4943867460f7533d6dc4e2c85656664ee341ea81e7dcerion}
4953867460f7533d6dc4e2c85656664ee341ea81e7dcerion
496d953ebb9b04cbad6891676df597bf0c542b1ec89cerionstatic ULong MASK64( UInt begin, UInt end )
497d953ebb9b04cbad6891676df597bf0c542b1ec89cerion{
498633274098fafebdc79cf1c8a1ef7f9a9914669f1sewardj   ULong m1, m2, mask;
499d953ebb9b04cbad6891676df597bf0c542b1ec89cerion   vassert(begin < 64);
500d953ebb9b04cbad6891676df597bf0c542b1ec89cerion   vassert(end < 64);
501633274098fafebdc79cf1c8a1ef7f9a9914669f1sewardj   m1   = ((ULong)(-1)) << begin;
502633274098fafebdc79cf1c8a1ef7f9a9914669f1sewardj   m2   = ((ULong)(-1)) << end << 1;
503633274098fafebdc79cf1c8a1ef7f9a9914669f1sewardj   mask = m1 ^ m2;
504d953ebb9b04cbad6891676df597bf0c542b1ec89cerion   if (begin > end) mask = ~mask;  // wrap mask
505d953ebb9b04cbad6891676df597bf0c542b1ec89cerion   return mask;
506d953ebb9b04cbad6891676df597bf0c542b1ec89cerion}
507d953ebb9b04cbad6891676df597bf0c542b1ec89cerion
508f0de28cf1a762b0d6f74c93d3532c89a230673bbcerionstatic Addr64 nextInsnAddr( void )
509f0de28cf1a762b0d6f74c93d3532c89a230673bbcerion{
510f0de28cf1a762b0d6f74c93d3532c89a230673bbcerion   return guest_CIA_curr_instr + 4;
511f0de28cf1a762b0d6f74c93d3532c89a230673bbcerion}
512d953ebb9b04cbad6891676df597bf0c542b1ec89cerion
513896a1373cfdbaa25f4ab73ed4f27554016defecccerion
514896a1373cfdbaa25f4ab73ed4f27554016defecccerion/*------------------------------------------------------------*/
515896a1373cfdbaa25f4ab73ed4f27554016defecccerion/*--- Helper bits and pieces for deconstructing the        ---*/
516d953ebb9b04cbad6891676df597bf0c542b1ec89cerion/*--- ppc32/64 insn stream.                                ---*/
517896a1373cfdbaa25f4ab73ed4f27554016defecccerion/*------------------------------------------------------------*/
518896a1373cfdbaa25f4ab73ed4f27554016defecccerion
519dd40fdf58cc8a6fe9466c4f00bdfc9fe9bf00449sewardj/* Add a statement to the list held by "irsb". */
520896a1373cfdbaa25f4ab73ed4f27554016defecccerionstatic void stmt ( IRStmt* st )
521896a1373cfdbaa25f4ab73ed4f27554016defecccerion{
522dd40fdf58cc8a6fe9466c4f00bdfc9fe9bf00449sewardj   addStmtToIRSB( irsb, st );
523896a1373cfdbaa25f4ab73ed4f27554016defecccerion}
524896a1373cfdbaa25f4ab73ed4f27554016defecccerion
525896a1373cfdbaa25f4ab73ed4f27554016defecccerion/* Generate a new temporary of the given type. */
526896a1373cfdbaa25f4ab73ed4f27554016defecccerionstatic IRTemp newTemp ( IRType ty )
527896a1373cfdbaa25f4ab73ed4f27554016defecccerion{
528496a58d130a28ac3a5ba33c9012dabbe61dc852csewardj   vassert(isPlausibleIRType(ty));
529dd40fdf58cc8a6fe9466c4f00bdfc9fe9bf00449sewardj   return newIRTemp( irsb->tyenv, ty );
530896a1373cfdbaa25f4ab73ed4f27554016defecccerion}
531896a1373cfdbaa25f4ab73ed4f27554016defecccerion
53232aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion/* Various simple conversions */
53332aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion
53432aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerionstatic UChar extend_s_5to8 ( UChar x )
53532aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion{
53632aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion   return toUChar((((Int)x) << 27) >> 27);
53732aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion}
53832aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion
53992d9d876af80d14fa2f319f7109964f2d6231f15cerionstatic UInt extend_s_8to32( UChar x )
54092d9d876af80d14fa2f319f7109964f2d6231f15cerion{
54192d9d876af80d14fa2f319f7109964f2d6231f15cerion   return (UInt)((((Int)x) << 24) >> 24);
54292d9d876af80d14fa2f319f7109964f2d6231f15cerion}
543896a1373cfdbaa25f4ab73ed4f27554016defecccerion
54491ad5368eb6354ad4fabc86f2b2e641736997a38cerionstatic UInt extend_s_16to32 ( UInt x )
545896a1373cfdbaa25f4ab73ed4f27554016defecccerion{
54691ad5368eb6354ad4fabc86f2b2e641736997a38cerion   return (UInt)((((Int)x) << 16) >> 16);
547896a1373cfdbaa25f4ab73ed4f27554016defecccerion}
548896a1373cfdbaa25f4ab73ed4f27554016defecccerion
549d953ebb9b04cbad6891676df597bf0c542b1ec89cerionstatic ULong extend_s_16to64 ( UInt x )
550d953ebb9b04cbad6891676df597bf0c542b1ec89cerion{
551d953ebb9b04cbad6891676df597bf0c542b1ec89cerion   return (ULong)((((Long)x) << 48) >> 48);
552d953ebb9b04cbad6891676df597bf0c542b1ec89cerion}
553d953ebb9b04cbad6891676df597bf0c542b1ec89cerion
554d953ebb9b04cbad6891676df597bf0c542b1ec89cerionstatic ULong extend_s_26to64 ( UInt x )
555d953ebb9b04cbad6891676df597bf0c542b1ec89cerion{
556d953ebb9b04cbad6891676df597bf0c542b1ec89cerion   return (ULong)((((Long)x) << 38) >> 38);
557d953ebb9b04cbad6891676df597bf0c542b1ec89cerion}
558d953ebb9b04cbad6891676df597bf0c542b1ec89cerion
559d953ebb9b04cbad6891676df597bf0c542b1ec89cerionstatic ULong extend_s_32to64 ( UInt x )
560d953ebb9b04cbad6891676df597bf0c542b1ec89cerion{
561d953ebb9b04cbad6891676df597bf0c542b1ec89cerion   return (ULong)((((Long)x) << 32) >> 32);
562d953ebb9b04cbad6891676df597bf0c542b1ec89cerion}
563d953ebb9b04cbad6891676df597bf0c542b1ec89cerion
5641f5fe1fc3a37ca729925e8eec25aa1025b4a6cdbcarll/* Do a proper-endian load of a 32-bit word, regardless of the endianness
565684aa951cf6c31dab26997f63ba6ea81491a45c9sewardj   of the underlying host. */
5668462d113e3efeacceb304222dada8d85f748295aflorianstatic UInt getUIntPPCendianly ( const UChar* p )
567684aa951cf6c31dab26997f63ba6ea81491a45c9sewardj{
568cf0044688fed807d49677656d2c6d12e0424bcfccerion   UInt w = 0;
5691f5fe1fc3a37ca729925e8eec25aa1025b4a6cdbcarll   if (host_endness == VexEndnessBE) {
5701f5fe1fc3a37ca729925e8eec25aa1025b4a6cdbcarll       w = (w << 8) | p[0];
5711f5fe1fc3a37ca729925e8eec25aa1025b4a6cdbcarll       w = (w << 8) | p[1];
5721f5fe1fc3a37ca729925e8eec25aa1025b4a6cdbcarll       w = (w << 8) | p[2];
5731f5fe1fc3a37ca729925e8eec25aa1025b4a6cdbcarll       w = (w << 8) | p[3];
5741f5fe1fc3a37ca729925e8eec25aa1025b4a6cdbcarll   } else {
5751f5fe1fc3a37ca729925e8eec25aa1025b4a6cdbcarll       w = (w << 8) | p[3];
5761f5fe1fc3a37ca729925e8eec25aa1025b4a6cdbcarll       w = (w << 8) | p[2];
5771f5fe1fc3a37ca729925e8eec25aa1025b4a6cdbcarll       w = (w << 8) | p[1];
5781f5fe1fc3a37ca729925e8eec25aa1025b4a6cdbcarll       w = (w << 8) | p[0];
5791f5fe1fc3a37ca729925e8eec25aa1025b4a6cdbcarll   }
580684aa951cf6c31dab26997f63ba6ea81491a45c9sewardj   return w;
581684aa951cf6c31dab26997f63ba6ea81491a45c9sewardj}
582684aa951cf6c31dab26997f63ba6ea81491a45c9sewardj
583896a1373cfdbaa25f4ab73ed4f27554016defecccerion
584896a1373cfdbaa25f4ab73ed4f27554016defecccerion/*------------------------------------------------------------*/
585896a1373cfdbaa25f4ab73ed4f27554016defecccerion/*--- Helpers for constructing IR.                         ---*/
586896a1373cfdbaa25f4ab73ed4f27554016defecccerion/*------------------------------------------------------------*/
587896a1373cfdbaa25f4ab73ed4f27554016defecccerion
588b51f0f4f33256638ed953156a2635aa739b232f1sewardjstatic void assign ( IRTemp dst, IRExpr* e )
589b51f0f4f33256638ed953156a2635aa739b232f1sewardj{
590dd40fdf58cc8a6fe9466c4f00bdfc9fe9bf00449sewardj   stmt( IRStmt_WrTmp(dst, e) );
591b51f0f4f33256638ed953156a2635aa739b232f1sewardj}
592b51f0f4f33256638ed953156a2635aa739b232f1sewardj
593e9d8a26b690c2561ac54ab0cd6ad83ecbadcbe76sewardj/* This generates a normal (non store-conditional) store. */
5941f5fe1fc3a37ca729925e8eec25aa1025b4a6cdbcarllstatic void store ( IRExpr* addr, IRExpr* data )
595b51f0f4f33256638ed953156a2635aa739b232f1sewardj{
596e9d8a26b690c2561ac54ab0cd6ad83ecbadcbe76sewardj   IRType tyA = typeOfIRExpr(irsb->tyenv, addr);
597e9d8a26b690c2561ac54ab0cd6ad83ecbadcbe76sewardj   vassert(tyA == Ity_I32 || tyA == Ity_I64);
5981f5fe1fc3a37ca729925e8eec25aa1025b4a6cdbcarll
5991f5fe1fc3a37ca729925e8eec25aa1025b4a6cdbcarll   if (host_endness == VexEndnessBE)
6001f5fe1fc3a37ca729925e8eec25aa1025b4a6cdbcarll      stmt( IRStmt_Store(Iend_BE, addr, data) );
6011f5fe1fc3a37ca729925e8eec25aa1025b4a6cdbcarll   else
6021f5fe1fc3a37ca729925e8eec25aa1025b4a6cdbcarll      stmt( IRStmt_Store(Iend_LE, addr, data) );
603b51f0f4f33256638ed953156a2635aa739b232f1sewardj}
604b51f0f4f33256638ed953156a2635aa739b232f1sewardj
605b51f0f4f33256638ed953156a2635aa739b232f1sewardjstatic IRExpr* unop ( IROp op, IRExpr* a )
606b51f0f4f33256638ed953156a2635aa739b232f1sewardj{
607b51f0f4f33256638ed953156a2635aa739b232f1sewardj   return IRExpr_Unop(op, a);
608b51f0f4f33256638ed953156a2635aa739b232f1sewardj}
609b51f0f4f33256638ed953156a2635aa739b232f1sewardj
610b51f0f4f33256638ed953156a2635aa739b232f1sewardjstatic IRExpr* binop ( IROp op, IRExpr* a1, IRExpr* a2 )
611b51f0f4f33256638ed953156a2635aa739b232f1sewardj{
612b51f0f4f33256638ed953156a2635aa739b232f1sewardj   return IRExpr_Binop(op, a1, a2);
613b51f0f4f33256638ed953156a2635aa739b232f1sewardj}
614b51f0f4f33256638ed953156a2635aa739b232f1sewardj
615b183b8571b4ec98866ce2b3653a9d066cf5f16f4sewardjstatic IRExpr* triop ( IROp op, IRExpr* a1, IRExpr* a2, IRExpr* a3 )
616b183b8571b4ec98866ce2b3653a9d066cf5f16f4sewardj{
617b183b8571b4ec98866ce2b3653a9d066cf5f16f4sewardj   return IRExpr_Triop(op, a1, a2, a3);
618b183b8571b4ec98866ce2b3653a9d066cf5f16f4sewardj}
619b183b8571b4ec98866ce2b3653a9d066cf5f16f4sewardj
62040c802659108a96bb87cbc1a30b7b77e2abd0829sewardjstatic IRExpr* qop ( IROp op, IRExpr* a1, IRExpr* a2,
62140c802659108a96bb87cbc1a30b7b77e2abd0829sewardj                              IRExpr* a3, IRExpr* a4 )
62240c802659108a96bb87cbc1a30b7b77e2abd0829sewardj{
62340c802659108a96bb87cbc1a30b7b77e2abd0829sewardj   return IRExpr_Qop(op, a1, a2, a3, a4);
62440c802659108a96bb87cbc1a30b7b77e2abd0829sewardj}
62540c802659108a96bb87cbc1a30b7b77e2abd0829sewardj
626b51f0f4f33256638ed953156a2635aa739b232f1sewardjstatic IRExpr* mkexpr ( IRTemp tmp )
627b51f0f4f33256638ed953156a2635aa739b232f1sewardj{
628dd40fdf58cc8a6fe9466c4f00bdfc9fe9bf00449sewardj   return IRExpr_RdTmp(tmp);
629b51f0f4f33256638ed953156a2635aa739b232f1sewardj}
630b51f0f4f33256638ed953156a2635aa739b232f1sewardj
631b51f0f4f33256638ed953156a2635aa739b232f1sewardjstatic IRExpr* mkU8 ( UChar i )
632b51f0f4f33256638ed953156a2635aa739b232f1sewardj{
633b51f0f4f33256638ed953156a2635aa739b232f1sewardj   return IRExpr_Const(IRConst_U8(i));
634b51f0f4f33256638ed953156a2635aa739b232f1sewardj}
635b51f0f4f33256638ed953156a2635aa739b232f1sewardj
63692d9d876af80d14fa2f319f7109964f2d6231f15cerionstatic IRExpr* mkU16 ( UInt i )
63792d9d876af80d14fa2f319f7109964f2d6231f15cerion{
63892d9d876af80d14fa2f319f7109964f2d6231f15cerion   return IRExpr_Const(IRConst_U16(i));
63992d9d876af80d14fa2f319f7109964f2d6231f15cerion}
64092d9d876af80d14fa2f319f7109964f2d6231f15cerion
641b51f0f4f33256638ed953156a2635aa739b232f1sewardjstatic IRExpr* mkU32 ( UInt i )
642b51f0f4f33256638ed953156a2635aa739b232f1sewardj{
643b51f0f4f33256638ed953156a2635aa739b232f1sewardj   return IRExpr_Const(IRConst_U32(i));
644b51f0f4f33256638ed953156a2635aa739b232f1sewardj}
645b51f0f4f33256638ed953156a2635aa739b232f1sewardj
6464a49b0393204185f87664ea58f2b7a2ae1d37338cerionstatic IRExpr* mkU64 ( ULong i )
6474a49b0393204185f87664ea58f2b7a2ae1d37338cerion{
6484a49b0393204185f87664ea58f2b7a2ae1d37338cerion   return IRExpr_Const(IRConst_U64(i));
6494a49b0393204185f87664ea58f2b7a2ae1d37338cerion}
6504a49b0393204185f87664ea58f2b7a2ae1d37338cerion
65166d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardjstatic IRExpr* mkV128 ( UShort i )
65266d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj{
65366d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj   vassert(i == 0 || i == 0xffff);
65466d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj   return IRExpr_Const(IRConst_V128(i));
65566d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj}
65666d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj
657e9d8a26b690c2561ac54ab0cd6ad83ecbadcbe76sewardj/* This generates a normal (non load-linked) load. */
6581f5fe1fc3a37ca729925e8eec25aa1025b4a6cdbcarllstatic IRExpr* load ( IRType ty, IRExpr* addr )
6591f5fe1fc3a37ca729925e8eec25aa1025b4a6cdbcarll{
6601f5fe1fc3a37ca729925e8eec25aa1025b4a6cdbcarll   if (host_endness == VexEndnessBE)
6611f5fe1fc3a37ca729925e8eec25aa1025b4a6cdbcarll      return IRExpr_Load(Iend_BE, ty, addr);
6621f5fe1fc3a37ca729925e8eec25aa1025b4a6cdbcarll   else
6631f5fe1fc3a37ca729925e8eec25aa1025b4a6cdbcarll      return IRExpr_Load(Iend_LE, ty, addr);
6641f5fe1fc3a37ca729925e8eec25aa1025b4a6cdbcarll}
6651f5fe1fc3a37ca729925e8eec25aa1025b4a6cdbcarll
6661f5fe1fc3a37ca729925e8eec25aa1025b4a6cdbcarllstatic IRStmt* stmt_load ( IRTemp result,
6671f5fe1fc3a37ca729925e8eec25aa1025b4a6cdbcarll                           IRExpr* addr, IRExpr* storedata )
668b51f0f4f33256638ed953156a2635aa739b232f1sewardj{
6691f5fe1fc3a37ca729925e8eec25aa1025b4a6cdbcarll   if (host_endness == VexEndnessBE)
6701f5fe1fc3a37ca729925e8eec25aa1025b4a6cdbcarll      return IRStmt_LLSC(Iend_BE, result, addr, storedata);
6711f5fe1fc3a37ca729925e8eec25aa1025b4a6cdbcarll   else
6721f5fe1fc3a37ca729925e8eec25aa1025b4a6cdbcarll      return IRStmt_LLSC(Iend_LE, result, addr, storedata);
673b51f0f4f33256638ed953156a2635aa739b232f1sewardj}
674b51f0f4f33256638ed953156a2635aa739b232f1sewardj
67520ef5472eac767474c93b7835364a23f24c0ec5dsewardjstatic IRExpr* mkOR1 ( IRExpr* arg1, IRExpr* arg2 )
67620ef5472eac767474c93b7835364a23f24c0ec5dsewardj{
677dd40fdf58cc8a6fe9466c4f00bdfc9fe9bf00449sewardj   vassert(typeOfIRExpr(irsb->tyenv, arg1) == Ity_I1);
678dd40fdf58cc8a6fe9466c4f00bdfc9fe9bf00449sewardj   vassert(typeOfIRExpr(irsb->tyenv, arg2) == Ity_I1);
6795b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion   return unop(Iop_32to1, binop(Iop_Or32, unop(Iop_1Uto32, arg1),
6805b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion                                          unop(Iop_1Uto32, arg2)));
68120ef5472eac767474c93b7835364a23f24c0ec5dsewardj}
68220ef5472eac767474c93b7835364a23f24c0ec5dsewardj
68320ef5472eac767474c93b7835364a23f24c0ec5dsewardjstatic IRExpr* mkAND1 ( IRExpr* arg1, IRExpr* arg2 )
68420ef5472eac767474c93b7835364a23f24c0ec5dsewardj{
685dd40fdf58cc8a6fe9466c4f00bdfc9fe9bf00449sewardj   vassert(typeOfIRExpr(irsb->tyenv, arg1) == Ity_I1);
686dd40fdf58cc8a6fe9466c4f00bdfc9fe9bf00449sewardj   vassert(typeOfIRExpr(irsb->tyenv, arg2) == Ity_I1);
6875b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion   return unop(Iop_32to1, binop(Iop_And32, unop(Iop_1Uto32, arg1),
6885b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion                                           unop(Iop_1Uto32, arg2)));
68920ef5472eac767474c93b7835364a23f24c0ec5dsewardj}
690b51f0f4f33256638ed953156a2635aa739b232f1sewardj
6914a49b0393204185f87664ea58f2b7a2ae1d37338cerion/* expand V128_8Ux16 to 2x V128_16Ux8's */
6925b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerionstatic void expand8Ux16( IRExpr* vIn,
6935b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion                         /*OUTs*/ IRTemp* vEvn, IRTemp* vOdd )
6944a49b0393204185f87664ea58f2b7a2ae1d37338cerion{
6954a49b0393204185f87664ea58f2b7a2ae1d37338cerion   IRTemp ones8x16 = newTemp(Ity_V128);
6964a49b0393204185f87664ea58f2b7a2ae1d37338cerion
697dd40fdf58cc8a6fe9466c4f00bdfc9fe9bf00449sewardj   vassert(typeOfIRExpr(irsb->tyenv, vIn) == Ity_V128);
6984a49b0393204185f87664ea58f2b7a2ae1d37338cerion   vassert(vEvn && *vEvn == IRTemp_INVALID);
6994a49b0393204185f87664ea58f2b7a2ae1d37338cerion   vassert(vOdd && *vOdd == IRTemp_INVALID);
7004a49b0393204185f87664ea58f2b7a2ae1d37338cerion   *vEvn = newTemp(Ity_V128);
7014a49b0393204185f87664ea58f2b7a2ae1d37338cerion   *vOdd = newTemp(Ity_V128);
7024a49b0393204185f87664ea58f2b7a2ae1d37338cerion
7034a49b0393204185f87664ea58f2b7a2ae1d37338cerion   assign( ones8x16, unop(Iop_Dup8x16, mkU8(0x1)) );
70424d06f124e3325e8edcc1c495d15736d5adcda96cerion   assign( *vOdd, binop(Iop_MullEven8Ux16, mkexpr(ones8x16), vIn) );
70524d06f124e3325e8edcc1c495d15736d5adcda96cerion   assign( *vEvn, binop(Iop_MullEven8Ux16, mkexpr(ones8x16),
70624d06f124e3325e8edcc1c495d15736d5adcda96cerion                        binop(Iop_ShrV128, vIn, mkU8(8))) );
7074a49b0393204185f87664ea58f2b7a2ae1d37338cerion}
7084a49b0393204185f87664ea58f2b7a2ae1d37338cerion
7094a49b0393204185f87664ea58f2b7a2ae1d37338cerion/* expand V128_8Sx16 to 2x V128_16Sx8's */
7105b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerionstatic void expand8Sx16( IRExpr* vIn,
7115b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion                         /*OUTs*/ IRTemp* vEvn, IRTemp* vOdd )
7124a49b0393204185f87664ea58f2b7a2ae1d37338cerion{
7134a49b0393204185f87664ea58f2b7a2ae1d37338cerion   IRTemp ones8x16 = newTemp(Ity_V128);
7144a49b0393204185f87664ea58f2b7a2ae1d37338cerion
715dd40fdf58cc8a6fe9466c4f00bdfc9fe9bf00449sewardj   vassert(typeOfIRExpr(irsb->tyenv, vIn) == Ity_V128);
7164a49b0393204185f87664ea58f2b7a2ae1d37338cerion   vassert(vEvn && *vEvn == IRTemp_INVALID);
7174a49b0393204185f87664ea58f2b7a2ae1d37338cerion   vassert(vOdd && *vOdd == IRTemp_INVALID);
7184a49b0393204185f87664ea58f2b7a2ae1d37338cerion   *vEvn = newTemp(Ity_V128);
7194a49b0393204185f87664ea58f2b7a2ae1d37338cerion   *vOdd = newTemp(Ity_V128);
7204a49b0393204185f87664ea58f2b7a2ae1d37338cerion
7214a49b0393204185f87664ea58f2b7a2ae1d37338cerion   assign( ones8x16, unop(Iop_Dup8x16, mkU8(0x1)) );
72224d06f124e3325e8edcc1c495d15736d5adcda96cerion   assign( *vOdd, binop(Iop_MullEven8Sx16, mkexpr(ones8x16), vIn) );
72324d06f124e3325e8edcc1c495d15736d5adcda96cerion   assign( *vEvn, binop(Iop_MullEven8Sx16, mkexpr(ones8x16),
72424d06f124e3325e8edcc1c495d15736d5adcda96cerion                        binop(Iop_ShrV128, vIn, mkU8(8))) );
7254a49b0393204185f87664ea58f2b7a2ae1d37338cerion}
7264a49b0393204185f87664ea58f2b7a2ae1d37338cerion
7274a49b0393204185f87664ea58f2b7a2ae1d37338cerion/* expand V128_16Uto8 to 2x V128_32Ux4's */
7285b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerionstatic void expand16Ux8( IRExpr* vIn,
7295b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion                         /*OUTs*/ IRTemp* vEvn, IRTemp* vOdd )
7304a49b0393204185f87664ea58f2b7a2ae1d37338cerion{
7314a49b0393204185f87664ea58f2b7a2ae1d37338cerion   IRTemp ones16x8 = newTemp(Ity_V128);
7324a49b0393204185f87664ea58f2b7a2ae1d37338cerion
733dd40fdf58cc8a6fe9466c4f00bdfc9fe9bf00449sewardj   vassert(typeOfIRExpr(irsb->tyenv, vIn) == Ity_V128);
7344a49b0393204185f87664ea58f2b7a2ae1d37338cerion   vassert(vEvn && *vEvn == IRTemp_INVALID);
7354a49b0393204185f87664ea58f2b7a2ae1d37338cerion   vassert(vOdd && *vOdd == IRTemp_INVALID);
7364a49b0393204185f87664ea58f2b7a2ae1d37338cerion   *vEvn = newTemp(Ity_V128);
7374a49b0393204185f87664ea58f2b7a2ae1d37338cerion   *vOdd = newTemp(Ity_V128);
7384a49b0393204185f87664ea58f2b7a2ae1d37338cerion
7394a49b0393204185f87664ea58f2b7a2ae1d37338cerion   assign( ones16x8, unop(Iop_Dup16x8, mkU16(0x1)) );
74024d06f124e3325e8edcc1c495d15736d5adcda96cerion   assign( *vOdd, binop(Iop_MullEven16Ux8, mkexpr(ones16x8), vIn) );
74124d06f124e3325e8edcc1c495d15736d5adcda96cerion   assign( *vEvn, binop(Iop_MullEven16Ux8, mkexpr(ones16x8),
74224d06f124e3325e8edcc1c495d15736d5adcda96cerion                        binop(Iop_ShrV128, vIn, mkU8(16))) );
7434a49b0393204185f87664ea58f2b7a2ae1d37338cerion}
7444a49b0393204185f87664ea58f2b7a2ae1d37338cerion
7454a49b0393204185f87664ea58f2b7a2ae1d37338cerion/* expand V128_16Sto8 to 2x V128_32Sx4's */
7465b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerionstatic void expand16Sx8( IRExpr* vIn,
7475b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion                         /*OUTs*/ IRTemp* vEvn, IRTemp* vOdd )
7484a49b0393204185f87664ea58f2b7a2ae1d37338cerion{
7494a49b0393204185f87664ea58f2b7a2ae1d37338cerion   IRTemp ones16x8 = newTemp(Ity_V128);
7504a49b0393204185f87664ea58f2b7a2ae1d37338cerion
751dd40fdf58cc8a6fe9466c4f00bdfc9fe9bf00449sewardj   vassert(typeOfIRExpr(irsb->tyenv, vIn) == Ity_V128);
7524a49b0393204185f87664ea58f2b7a2ae1d37338cerion   vassert(vEvn && *vEvn == IRTemp_INVALID);
7534a49b0393204185f87664ea58f2b7a2ae1d37338cerion   vassert(vOdd && *vOdd == IRTemp_INVALID);
7544a49b0393204185f87664ea58f2b7a2ae1d37338cerion   *vEvn = newTemp(Ity_V128);
7554a49b0393204185f87664ea58f2b7a2ae1d37338cerion   *vOdd = newTemp(Ity_V128);
7564a49b0393204185f87664ea58f2b7a2ae1d37338cerion
7574a49b0393204185f87664ea58f2b7a2ae1d37338cerion   assign( ones16x8, unop(Iop_Dup16x8, mkU16(0x1)) );
75824d06f124e3325e8edcc1c495d15736d5adcda96cerion   assign( *vOdd, binop(Iop_MullEven16Sx8, mkexpr(ones16x8), vIn) );
75924d06f124e3325e8edcc1c495d15736d5adcda96cerion   assign( *vEvn, binop(Iop_MullEven16Sx8, mkexpr(ones16x8),
76024d06f124e3325e8edcc1c495d15736d5adcda96cerion                       binop(Iop_ShrV128, vIn, mkU8(16))) );
7614a49b0393204185f87664ea58f2b7a2ae1d37338cerion}
7624a49b0393204185f87664ea58f2b7a2ae1d37338cerion
7634aa412af1d8166cc11f39a6e721df49431d23618sewardj/* break V128 to 4xF64's*/
7644aa412af1d8166cc11f39a6e721df49431d23618sewardjstatic void breakV128to4xF64( IRExpr* t128,
7654aa412af1d8166cc11f39a6e721df49431d23618sewardj                              /*OUTs*/
7664aa412af1d8166cc11f39a6e721df49431d23618sewardj                              IRTemp* t3, IRTemp* t2,
7674aa412af1d8166cc11f39a6e721df49431d23618sewardj                              IRTemp* t1, IRTemp* t0 )
7684aa412af1d8166cc11f39a6e721df49431d23618sewardj{
7694aa412af1d8166cc11f39a6e721df49431d23618sewardj   IRTemp hi64 = newTemp(Ity_I64);
7704aa412af1d8166cc11f39a6e721df49431d23618sewardj   IRTemp lo64 = newTemp(Ity_I64);
7714aa412af1d8166cc11f39a6e721df49431d23618sewardj
7724aa412af1d8166cc11f39a6e721df49431d23618sewardj   vassert(typeOfIRExpr(irsb->tyenv, t128) == Ity_V128);
7734aa412af1d8166cc11f39a6e721df49431d23618sewardj   vassert(t0 && *t0 == IRTemp_INVALID);
7744aa412af1d8166cc11f39a6e721df49431d23618sewardj   vassert(t1 && *t1 == IRTemp_INVALID);
7754aa412af1d8166cc11f39a6e721df49431d23618sewardj   vassert(t2 && *t2 == IRTemp_INVALID);
7764aa412af1d8166cc11f39a6e721df49431d23618sewardj   vassert(t3 && *t3 == IRTemp_INVALID);
7774aa412af1d8166cc11f39a6e721df49431d23618sewardj   *t0 = newTemp(Ity_F64);
7784aa412af1d8166cc11f39a6e721df49431d23618sewardj   *t1 = newTemp(Ity_F64);
7794aa412af1d8166cc11f39a6e721df49431d23618sewardj   *t2 = newTemp(Ity_F64);
7804aa412af1d8166cc11f39a6e721df49431d23618sewardj   *t3 = newTemp(Ity_F64);
7814aa412af1d8166cc11f39a6e721df49431d23618sewardj
7824aa412af1d8166cc11f39a6e721df49431d23618sewardj   assign( hi64, unop(Iop_V128HIto64, t128) );
7834aa412af1d8166cc11f39a6e721df49431d23618sewardj   assign( lo64, unop(Iop_V128to64,   t128) );
7844aa412af1d8166cc11f39a6e721df49431d23618sewardj   assign( *t3,
7854aa412af1d8166cc11f39a6e721df49431d23618sewardj           unop( Iop_F32toF64,
7864aa412af1d8166cc11f39a6e721df49431d23618sewardj                 unop( Iop_ReinterpI32asF32,
7874aa412af1d8166cc11f39a6e721df49431d23618sewardj                       unop( Iop_64HIto32, mkexpr( hi64 ) ) ) ) );
7884aa412af1d8166cc11f39a6e721df49431d23618sewardj   assign( *t2,
7894aa412af1d8166cc11f39a6e721df49431d23618sewardj           unop( Iop_F32toF64,
7904aa412af1d8166cc11f39a6e721df49431d23618sewardj                 unop( Iop_ReinterpI32asF32, unop( Iop_64to32, mkexpr( hi64 ) ) ) ) );
7914aa412af1d8166cc11f39a6e721df49431d23618sewardj   assign( *t1,
7924aa412af1d8166cc11f39a6e721df49431d23618sewardj           unop( Iop_F32toF64,
7934aa412af1d8166cc11f39a6e721df49431d23618sewardj                 unop( Iop_ReinterpI32asF32,
7944aa412af1d8166cc11f39a6e721df49431d23618sewardj                       unop( Iop_64HIto32, mkexpr( lo64 ) ) ) ) );
7954aa412af1d8166cc11f39a6e721df49431d23618sewardj   assign( *t0,
7964aa412af1d8166cc11f39a6e721df49431d23618sewardj           unop( Iop_F32toF64,
7974aa412af1d8166cc11f39a6e721df49431d23618sewardj                 unop( Iop_ReinterpI32asF32, unop( Iop_64to32, mkexpr( lo64 ) ) ) ) );
7984aa412af1d8166cc11f39a6e721df49431d23618sewardj}
7994aa412af1d8166cc11f39a6e721df49431d23618sewardj
8004aa412af1d8166cc11f39a6e721df49431d23618sewardj
8014a49b0393204185f87664ea58f2b7a2ae1d37338cerion/* break V128 to 4xI32's, then sign-extend to I64's */
8024a49b0393204185f87664ea58f2b7a2ae1d37338cerionstatic void breakV128to4x64S( IRExpr* t128,
8034a49b0393204185f87664ea58f2b7a2ae1d37338cerion                              /*OUTs*/
8044a49b0393204185f87664ea58f2b7a2ae1d37338cerion                              IRTemp* t3, IRTemp* t2,
8054a49b0393204185f87664ea58f2b7a2ae1d37338cerion                              IRTemp* t1, IRTemp* t0 )
8064a49b0393204185f87664ea58f2b7a2ae1d37338cerion{
8074a49b0393204185f87664ea58f2b7a2ae1d37338cerion   IRTemp hi64 = newTemp(Ity_I64);
8084a49b0393204185f87664ea58f2b7a2ae1d37338cerion   IRTemp lo64 = newTemp(Ity_I64);
8094a49b0393204185f87664ea58f2b7a2ae1d37338cerion
810dd40fdf58cc8a6fe9466c4f00bdfc9fe9bf00449sewardj   vassert(typeOfIRExpr(irsb->tyenv, t128) == Ity_V128);
8114a49b0393204185f87664ea58f2b7a2ae1d37338cerion   vassert(t0 && *t0 == IRTemp_INVALID);
8124a49b0393204185f87664ea58f2b7a2ae1d37338cerion   vassert(t1 && *t1 == IRTemp_INVALID);
8134a49b0393204185f87664ea58f2b7a2ae1d37338cerion   vassert(t2 && *t2 == IRTemp_INVALID);
8144a49b0393204185f87664ea58f2b7a2ae1d37338cerion   vassert(t3 && *t3 == IRTemp_INVALID);
8154a49b0393204185f87664ea58f2b7a2ae1d37338cerion   *t0 = newTemp(Ity_I64);
8164a49b0393204185f87664ea58f2b7a2ae1d37338cerion   *t1 = newTemp(Ity_I64);
8174a49b0393204185f87664ea58f2b7a2ae1d37338cerion   *t2 = newTemp(Ity_I64);
8184a49b0393204185f87664ea58f2b7a2ae1d37338cerion   *t3 = newTemp(Ity_I64);
8194a49b0393204185f87664ea58f2b7a2ae1d37338cerion
8204a49b0393204185f87664ea58f2b7a2ae1d37338cerion   assign( hi64, unop(Iop_V128HIto64, t128) );
8214a49b0393204185f87664ea58f2b7a2ae1d37338cerion   assign( lo64, unop(Iop_V128to64,   t128) );
8224a49b0393204185f87664ea58f2b7a2ae1d37338cerion   assign( *t3, unop(Iop_32Sto64, unop(Iop_64HIto32, mkexpr(hi64))) );
8234a49b0393204185f87664ea58f2b7a2ae1d37338cerion   assign( *t2, unop(Iop_32Sto64, unop(Iop_64to32,   mkexpr(hi64))) );
8244a49b0393204185f87664ea58f2b7a2ae1d37338cerion   assign( *t1, unop(Iop_32Sto64, unop(Iop_64HIto32, mkexpr(lo64))) );
8254a49b0393204185f87664ea58f2b7a2ae1d37338cerion   assign( *t0, unop(Iop_32Sto64, unop(Iop_64to32,   mkexpr(lo64))) );
8264a49b0393204185f87664ea58f2b7a2ae1d37338cerion}
8274a49b0393204185f87664ea58f2b7a2ae1d37338cerion
8284a49b0393204185f87664ea58f2b7a2ae1d37338cerion/* break V128 to 4xI32's, then zero-extend to I64's */
8294a49b0393204185f87664ea58f2b7a2ae1d37338cerionstatic void breakV128to4x64U ( IRExpr* t128,
8304a49b0393204185f87664ea58f2b7a2ae1d37338cerion                               /*OUTs*/
8314a49b0393204185f87664ea58f2b7a2ae1d37338cerion                               IRTemp* t3, IRTemp* t2,
8324a49b0393204185f87664ea58f2b7a2ae1d37338cerion                               IRTemp* t1, IRTemp* t0 )
8334a49b0393204185f87664ea58f2b7a2ae1d37338cerion{
8344a49b0393204185f87664ea58f2b7a2ae1d37338cerion   IRTemp hi64 = newTemp(Ity_I64);
8354a49b0393204185f87664ea58f2b7a2ae1d37338cerion   IRTemp lo64 = newTemp(Ity_I64);
8364a49b0393204185f87664ea58f2b7a2ae1d37338cerion
837dd40fdf58cc8a6fe9466c4f00bdfc9fe9bf00449sewardj   vassert(typeOfIRExpr(irsb->tyenv, t128) == Ity_V128);
8384a49b0393204185f87664ea58f2b7a2ae1d37338cerion   vassert(t0 && *t0 == IRTemp_INVALID);
8394a49b0393204185f87664ea58f2b7a2ae1d37338cerion   vassert(t1 && *t1 == IRTemp_INVALID);
8404a49b0393204185f87664ea58f2b7a2ae1d37338cerion   vassert(t2 && *t2 == IRTemp_INVALID);
8414a49b0393204185f87664ea58f2b7a2ae1d37338cerion   vassert(t3 && *t3 == IRTemp_INVALID);
8424a49b0393204185f87664ea58f2b7a2ae1d37338cerion   *t0 = newTemp(Ity_I64);
8434a49b0393204185f87664ea58f2b7a2ae1d37338cerion   *t1 = newTemp(Ity_I64);
8444a49b0393204185f87664ea58f2b7a2ae1d37338cerion   *t2 = newTemp(Ity_I64);
8454a49b0393204185f87664ea58f2b7a2ae1d37338cerion   *t3 = newTemp(Ity_I64);
8464a49b0393204185f87664ea58f2b7a2ae1d37338cerion
8474a49b0393204185f87664ea58f2b7a2ae1d37338cerion   assign( hi64, unop(Iop_V128HIto64, t128) );
8484a49b0393204185f87664ea58f2b7a2ae1d37338cerion   assign( lo64, unop(Iop_V128to64,   t128) );
8494a49b0393204185f87664ea58f2b7a2ae1d37338cerion   assign( *t3, unop(Iop_32Uto64, unop(Iop_64HIto32, mkexpr(hi64))) );
8504a49b0393204185f87664ea58f2b7a2ae1d37338cerion   assign( *t2, unop(Iop_32Uto64, unop(Iop_64to32,   mkexpr(hi64))) );
8514a49b0393204185f87664ea58f2b7a2ae1d37338cerion   assign( *t1, unop(Iop_32Uto64, unop(Iop_64HIto32, mkexpr(lo64))) );
8524a49b0393204185f87664ea58f2b7a2ae1d37338cerion   assign( *t0, unop(Iop_32Uto64, unop(Iop_64to32,   mkexpr(lo64))) );
8534a49b0393204185f87664ea58f2b7a2ae1d37338cerion}
8544a49b0393204185f87664ea58f2b7a2ae1d37338cerion
855e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardjstatic void breakV128to4x32( IRExpr* t128,
856e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj                              /*OUTs*/
857e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj                              IRTemp* t3, IRTemp* t2,
858e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj                              IRTemp* t1, IRTemp* t0 )
859e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj{
860e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj   IRTemp hi64 = newTemp(Ity_I64);
861e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj   IRTemp lo64 = newTemp(Ity_I64);
862e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj
863e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj   vassert(typeOfIRExpr(irsb->tyenv, t128) == Ity_V128);
864e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj   vassert(t0 && *t0 == IRTemp_INVALID);
865e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj   vassert(t1 && *t1 == IRTemp_INVALID);
866e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj   vassert(t2 && *t2 == IRTemp_INVALID);
867e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj   vassert(t3 && *t3 == IRTemp_INVALID);
868e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj   *t0 = newTemp(Ity_I32);
869e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj   *t1 = newTemp(Ity_I32);
870e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj   *t2 = newTemp(Ity_I32);
871e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj   *t3 = newTemp(Ity_I32);
872e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj
873e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj   assign( hi64, unop(Iop_V128HIto64, t128) );
874e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj   assign( lo64, unop(Iop_V128to64,   t128) );
875e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj   assign( *t3, unop(Iop_64HIto32, mkexpr(hi64)) );
876e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj   assign( *t2, unop(Iop_64to32,   mkexpr(hi64)) );
877e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj   assign( *t1, unop(Iop_64HIto32, mkexpr(lo64)) );
878e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj   assign( *t0, unop(Iop_64to32,   mkexpr(lo64)) );
879e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj}
880e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj
8817deaf9552b546b847528cf39b38898fb7742b5f5carllstatic IRExpr* mkV128from32( IRTemp t3, IRTemp t2,
8827deaf9552b546b847528cf39b38898fb7742b5f5carll                               IRTemp t1, IRTemp t0 )
8837deaf9552b546b847528cf39b38898fb7742b5f5carll{
8847deaf9552b546b847528cf39b38898fb7742b5f5carll   return
8857deaf9552b546b847528cf39b38898fb7742b5f5carll      binop( Iop_64HLtoV128,
8867deaf9552b546b847528cf39b38898fb7742b5f5carll             binop(Iop_32HLto64, mkexpr(t3), mkexpr(t2)),
8877deaf9552b546b847528cf39b38898fb7742b5f5carll             binop(Iop_32HLto64, mkexpr(t1), mkexpr(t0))
8887deaf9552b546b847528cf39b38898fb7742b5f5carll   );
8897deaf9552b546b847528cf39b38898fb7742b5f5carll}
8907deaf9552b546b847528cf39b38898fb7742b5f5carll
891e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj
8924a49b0393204185f87664ea58f2b7a2ae1d37338cerion/* Signed saturating narrow 64S to 32 */
8934a49b0393204185f87664ea58f2b7a2ae1d37338cerionstatic IRExpr* mkQNarrow64Sto32 ( IRExpr* t64 )
8944a49b0393204185f87664ea58f2b7a2ae1d37338cerion{
8954a49b0393204185f87664ea58f2b7a2ae1d37338cerion   IRTemp hi32 = newTemp(Ity_I32);
8964a49b0393204185f87664ea58f2b7a2ae1d37338cerion   IRTemp lo32 = newTemp(Ity_I32);
8974a49b0393204185f87664ea58f2b7a2ae1d37338cerion
898dd40fdf58cc8a6fe9466c4f00bdfc9fe9bf00449sewardj   vassert(typeOfIRExpr(irsb->tyenv, t64) == Ity_I64);
8994a49b0393204185f87664ea58f2b7a2ae1d37338cerion
9004a49b0393204185f87664ea58f2b7a2ae1d37338cerion   assign( hi32, unop(Iop_64HIto32, t64));
9014a49b0393204185f87664ea58f2b7a2ae1d37338cerion   assign( lo32, unop(Iop_64to32,   t64));
9024a49b0393204185f87664ea58f2b7a2ae1d37338cerion
90399dd03e04a6914d90d5fee727d61d76905334becflorian   return IRExpr_ITE(
9044a49b0393204185f87664ea58f2b7a2ae1d37338cerion             /* if (hi32 == (lo32 >>s 31)) */
905009230b9758291b594e60d7c0243a73d53e81854sewardj             binop(Iop_CmpEQ32, mkexpr(hi32),
906009230b9758291b594e60d7c0243a73d53e81854sewardj                   binop( Iop_Sar32, mkexpr(lo32), mkU8(31))),
90799dd03e04a6914d90d5fee727d61d76905334becflorian             /* then: within signed-32 range: lo half good enough */
90899dd03e04a6914d90d5fee727d61d76905334becflorian             mkexpr(lo32),
9094a49b0393204185f87664ea58f2b7a2ae1d37338cerion             /* else: sign dep saturate: 1->0x80000000, 0->0x7FFFFFFF */
9104a49b0393204185f87664ea58f2b7a2ae1d37338cerion             binop(Iop_Add32, mkU32(0x7FFFFFFF),
91199dd03e04a6914d90d5fee727d61d76905334becflorian                   binop(Iop_Shr32, mkexpr(hi32), mkU8(31))));
9124a49b0393204185f87664ea58f2b7a2ae1d37338cerion}
9134a49b0393204185f87664ea58f2b7a2ae1d37338cerion
9144a49b0393204185f87664ea58f2b7a2ae1d37338cerion/* Unsigned saturating narrow 64S to 32 */
9154a49b0393204185f87664ea58f2b7a2ae1d37338cerionstatic IRExpr* mkQNarrow64Uto32 ( IRExpr* t64 )
9164a49b0393204185f87664ea58f2b7a2ae1d37338cerion{
9174a49b0393204185f87664ea58f2b7a2ae1d37338cerion   IRTemp hi32 = newTemp(Ity_I32);
9184a49b0393204185f87664ea58f2b7a2ae1d37338cerion   IRTemp lo32 = newTemp(Ity_I32);
9194a49b0393204185f87664ea58f2b7a2ae1d37338cerion
920dd40fdf58cc8a6fe9466c4f00bdfc9fe9bf00449sewardj   vassert(typeOfIRExpr(irsb->tyenv, t64) == Ity_I64);
9214a49b0393204185f87664ea58f2b7a2ae1d37338cerion
9224a49b0393204185f87664ea58f2b7a2ae1d37338cerion   assign( hi32, unop(Iop_64HIto32, t64));
9234a49b0393204185f87664ea58f2b7a2ae1d37338cerion   assign( lo32, unop(Iop_64to32,   t64));
9244a49b0393204185f87664ea58f2b7a2ae1d37338cerion
92599dd03e04a6914d90d5fee727d61d76905334becflorian   return IRExpr_ITE(
9264a49b0393204185f87664ea58f2b7a2ae1d37338cerion            /* if (top 32 bits of t64 are 0) */
927009230b9758291b594e60d7c0243a73d53e81854sewardj            binop(Iop_CmpEQ32, mkexpr(hi32), mkU32(0)),
9284a49b0393204185f87664ea58f2b7a2ae1d37338cerion            /* then: within unsigned-32 range: lo half good enough */
92999dd03e04a6914d90d5fee727d61d76905334becflorian            mkexpr(lo32),
93099dd03e04a6914d90d5fee727d61d76905334becflorian            /* else: positive saturate -> 0xFFFFFFFF */
93199dd03e04a6914d90d5fee727d61d76905334becflorian            mkU32(0xFFFFFFFF));
9324a49b0393204185f87664ea58f2b7a2ae1d37338cerion}
9334a49b0393204185f87664ea58f2b7a2ae1d37338cerion
9344a49b0393204185f87664ea58f2b7a2ae1d37338cerion/* Signed saturate narrow 64->32, combining to V128 */
9354a49b0393204185f87664ea58f2b7a2ae1d37338cerionstatic IRExpr* mkV128from4x64S ( IRExpr* t3, IRExpr* t2,
9364a49b0393204185f87664ea58f2b7a2ae1d37338cerion                                 IRExpr* t1, IRExpr* t0 )
9374a49b0393204185f87664ea58f2b7a2ae1d37338cerion{
938dd40fdf58cc8a6fe9466c4f00bdfc9fe9bf00449sewardj   vassert(typeOfIRExpr(irsb->tyenv, t3) == Ity_I64);
939dd40fdf58cc8a6fe9466c4f00bdfc9fe9bf00449sewardj   vassert(typeOfIRExpr(irsb->tyenv, t2) == Ity_I64);
940dd40fdf58cc8a6fe9466c4f00bdfc9fe9bf00449sewardj   vassert(typeOfIRExpr(irsb->tyenv, t1) == Ity_I64);
941dd40fdf58cc8a6fe9466c4f00bdfc9fe9bf00449sewardj   vassert(typeOfIRExpr(irsb->tyenv, t0) == Ity_I64);
9424a49b0393204185f87664ea58f2b7a2ae1d37338cerion   return binop(Iop_64HLtoV128,
9434a49b0393204185f87664ea58f2b7a2ae1d37338cerion                binop(Iop_32HLto64,
9444a49b0393204185f87664ea58f2b7a2ae1d37338cerion                      mkQNarrow64Sto32( t3 ),
9454a49b0393204185f87664ea58f2b7a2ae1d37338cerion                      mkQNarrow64Sto32( t2 )),
9464a49b0393204185f87664ea58f2b7a2ae1d37338cerion                binop(Iop_32HLto64,
9474a49b0393204185f87664ea58f2b7a2ae1d37338cerion                      mkQNarrow64Sto32( t1 ),
9484a49b0393204185f87664ea58f2b7a2ae1d37338cerion                      mkQNarrow64Sto32( t0 )));
9494a49b0393204185f87664ea58f2b7a2ae1d37338cerion}
9504a49b0393204185f87664ea58f2b7a2ae1d37338cerion
9514a49b0393204185f87664ea58f2b7a2ae1d37338cerion/* Unsigned saturate narrow 64->32, combining to V128 */
9524a49b0393204185f87664ea58f2b7a2ae1d37338cerionstatic IRExpr* mkV128from4x64U ( IRExpr* t3, IRExpr* t2,
9534a49b0393204185f87664ea58f2b7a2ae1d37338cerion                                 IRExpr* t1, IRExpr* t0 )
9544a49b0393204185f87664ea58f2b7a2ae1d37338cerion{
955dd40fdf58cc8a6fe9466c4f00bdfc9fe9bf00449sewardj   vassert(typeOfIRExpr(irsb->tyenv, t3) == Ity_I64);
956dd40fdf58cc8a6fe9466c4f00bdfc9fe9bf00449sewardj   vassert(typeOfIRExpr(irsb->tyenv, t2) == Ity_I64);
957dd40fdf58cc8a6fe9466c4f00bdfc9fe9bf00449sewardj   vassert(typeOfIRExpr(irsb->tyenv, t1) == Ity_I64);
958dd40fdf58cc8a6fe9466c4f00bdfc9fe9bf00449sewardj   vassert(typeOfIRExpr(irsb->tyenv, t0) == Ity_I64);
9594a49b0393204185f87664ea58f2b7a2ae1d37338cerion   return binop(Iop_64HLtoV128,
9604a49b0393204185f87664ea58f2b7a2ae1d37338cerion                binop(Iop_32HLto64,
9614a49b0393204185f87664ea58f2b7a2ae1d37338cerion                      mkQNarrow64Uto32( t3 ),
9624a49b0393204185f87664ea58f2b7a2ae1d37338cerion                      mkQNarrow64Uto32( t2 )),
9634a49b0393204185f87664ea58f2b7a2ae1d37338cerion                binop(Iop_32HLto64,
9644a49b0393204185f87664ea58f2b7a2ae1d37338cerion                      mkQNarrow64Uto32( t1 ),
9654a49b0393204185f87664ea58f2b7a2ae1d37338cerion                      mkQNarrow64Uto32( t0 )));
9664a49b0393204185f87664ea58f2b7a2ae1d37338cerion}
9674a49b0393204185f87664ea58f2b7a2ae1d37338cerion
96824d06f124e3325e8edcc1c495d15736d5adcda96cerion/* Simulate irops Iop_MullOdd*, since we don't have them  */
96924d06f124e3325e8edcc1c495d15736d5adcda96cerion#define MK_Iop_MullOdd8Ux16( expr_vA, expr_vB ) \
97024d06f124e3325e8edcc1c495d15736d5adcda96cerion      binop(Iop_MullEven8Ux16, \
97124d06f124e3325e8edcc1c495d15736d5adcda96cerion            binop(Iop_ShrV128, expr_vA, mkU8(8)), \
97224d06f124e3325e8edcc1c495d15736d5adcda96cerion            binop(Iop_ShrV128, expr_vB, mkU8(8)))
97324d06f124e3325e8edcc1c495d15736d5adcda96cerion
97424d06f124e3325e8edcc1c495d15736d5adcda96cerion#define MK_Iop_MullOdd8Sx16( expr_vA, expr_vB ) \
97524d06f124e3325e8edcc1c495d15736d5adcda96cerion      binop(Iop_MullEven8Sx16, \
97624d06f124e3325e8edcc1c495d15736d5adcda96cerion            binop(Iop_ShrV128, expr_vA, mkU8(8)), \
97724d06f124e3325e8edcc1c495d15736d5adcda96cerion            binop(Iop_ShrV128, expr_vB, mkU8(8)))
97824d06f124e3325e8edcc1c495d15736d5adcda96cerion
97924d06f124e3325e8edcc1c495d15736d5adcda96cerion#define MK_Iop_MullOdd16Ux8( expr_vA, expr_vB ) \
98024d06f124e3325e8edcc1c495d15736d5adcda96cerion      binop(Iop_MullEven16Ux8, \
98124d06f124e3325e8edcc1c495d15736d5adcda96cerion            binop(Iop_ShrV128, expr_vA, mkU8(16)), \
98224d06f124e3325e8edcc1c495d15736d5adcda96cerion            binop(Iop_ShrV128, expr_vB, mkU8(16)))
98324d06f124e3325e8edcc1c495d15736d5adcda96cerion
98448ae46b56cef87c90638b25d6b2462c475033da8carll#define MK_Iop_MullOdd32Ux4( expr_vA, expr_vB ) \
98548ae46b56cef87c90638b25d6b2462c475033da8carll      binop(Iop_MullEven32Ux4, \
98648ae46b56cef87c90638b25d6b2462c475033da8carll            binop(Iop_ShrV128, expr_vA, mkU8(32)), \
98748ae46b56cef87c90638b25d6b2462c475033da8carll            binop(Iop_ShrV128, expr_vB, mkU8(32)))
98848ae46b56cef87c90638b25d6b2462c475033da8carll
98924d06f124e3325e8edcc1c495d15736d5adcda96cerion#define MK_Iop_MullOdd16Sx8( expr_vA, expr_vB ) \
99024d06f124e3325e8edcc1c495d15736d5adcda96cerion      binop(Iop_MullEven16Sx8, \
99124d06f124e3325e8edcc1c495d15736d5adcda96cerion            binop(Iop_ShrV128, expr_vA, mkU8(16)), \
99224d06f124e3325e8edcc1c495d15736d5adcda96cerion            binop(Iop_ShrV128, expr_vB, mkU8(16)))
99324d06f124e3325e8edcc1c495d15736d5adcda96cerion
99448ae46b56cef87c90638b25d6b2462c475033da8carll#define MK_Iop_MullOdd32Sx4( expr_vA, expr_vB ) \
99548ae46b56cef87c90638b25d6b2462c475033da8carll      binop(Iop_MullEven32Sx4, \
99648ae46b56cef87c90638b25d6b2462c475033da8carll            binop(Iop_ShrV128, expr_vA, mkU8(32)), \
99748ae46b56cef87c90638b25d6b2462c475033da8carll            binop(Iop_ShrV128, expr_vB, mkU8(32)))
99848ae46b56cef87c90638b25d6b2462c475033da8carll
99948ae46b56cef87c90638b25d6b2462c475033da8carll
100059b2c31da51314587b72a76430e766d6b7ec16cecerionstatic IRExpr* /* :: Ity_I64 */ mk64lo32Sto64 ( IRExpr* src )
1001d953ebb9b04cbad6891676df597bf0c542b1ec89cerion{
1002dd40fdf58cc8a6fe9466c4f00bdfc9fe9bf00449sewardj   vassert(typeOfIRExpr(irsb->tyenv, src) == Ity_I64);
1003d953ebb9b04cbad6891676df597bf0c542b1ec89cerion   return unop(Iop_32Sto64, unop(Iop_64to32, src));
1004d953ebb9b04cbad6891676df597bf0c542b1ec89cerion}
1005d953ebb9b04cbad6891676df597bf0c542b1ec89cerion
100659b2c31da51314587b72a76430e766d6b7ec16cecerionstatic IRExpr* /* :: Ity_I64 */ mk64lo32Uto64 ( IRExpr* src )
1007bb01b7cbfd84c27dd213f67a144ea5a99af36961cerion{
1008dd40fdf58cc8a6fe9466c4f00bdfc9fe9bf00449sewardj   vassert(typeOfIRExpr(irsb->tyenv, src) == Ity_I64);
1009bb01b7cbfd84c27dd213f67a144ea5a99af36961cerion   return unop(Iop_32Uto64, unop(Iop_64to32, src));
1010bb01b7cbfd84c27dd213f67a144ea5a99af36961cerion}
1011bb01b7cbfd84c27dd213f67a144ea5a99af36961cerion
10122831b00c4950d6c2b061def05fd67528fe132ececerionstatic IROp mkSzOp ( IRType ty, IROp op8 )
1013d953ebb9b04cbad6891676df597bf0c542b1ec89cerion{
1014d953ebb9b04cbad6891676df597bf0c542b1ec89cerion   Int adj;
1015d953ebb9b04cbad6891676df597bf0c542b1ec89cerion   vassert(ty == Ity_I8  || ty == Ity_I16 ||
1016d953ebb9b04cbad6891676df597bf0c542b1ec89cerion           ty == Ity_I32 || ty == Ity_I64);
1017d953ebb9b04cbad6891676df597bf0c542b1ec89cerion   vassert(op8 == Iop_Add8   || op8 == Iop_Sub8   || op8 == Iop_Mul8 ||
1018d953ebb9b04cbad6891676df597bf0c542b1ec89cerion           op8 == Iop_Or8    || op8 == Iop_And8   || op8 == Iop_Xor8 ||
1019d953ebb9b04cbad6891676df597bf0c542b1ec89cerion           op8 == Iop_Shl8   || op8 == Iop_Shr8   || op8 == Iop_Sar8 ||
1020d953ebb9b04cbad6891676df597bf0c542b1ec89cerion           op8 == Iop_CmpEQ8 || op8 == Iop_CmpNE8 ||
1021eb17e49565dd7867a56c8ba6e45fdca01a576bb3sewardj           op8 == Iop_Not8 );
1022d953ebb9b04cbad6891676df597bf0c542b1ec89cerion   adj = ty==Ity_I8 ? 0 : (ty==Ity_I16 ? 1 : (ty==Ity_I32 ? 2 : 3));
1023d953ebb9b04cbad6891676df597bf0c542b1ec89cerion   return adj + op8;
1024d953ebb9b04cbad6891676df597bf0c542b1ec89cerion}
1025d953ebb9b04cbad6891676df597bf0c542b1ec89cerion
10265b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion/* Make sure we get valid 32 and 64bit addresses */
10272831b00c4950d6c2b061def05fd67528fe132ececerionstatic Addr64 mkSzAddr ( IRType ty, Addr64 addr )
1028d953ebb9b04cbad6891676df597bf0c542b1ec89cerion{
1029d953ebb9b04cbad6891676df597bf0c542b1ec89cerion   vassert(ty == Ity_I32 || ty == Ity_I64);
1030d953ebb9b04cbad6891676df597bf0c542b1ec89cerion   return ( ty == Ity_I64 ?
1031d953ebb9b04cbad6891676df597bf0c542b1ec89cerion            (Addr64)addr :
1032d953ebb9b04cbad6891676df597bf0c542b1ec89cerion            (Addr64)extend_s_32to64( toUInt(addr) ) );
1033d953ebb9b04cbad6891676df597bf0c542b1ec89cerion}
1034d953ebb9b04cbad6891676df597bf0c542b1ec89cerion
1035d953ebb9b04cbad6891676df597bf0c542b1ec89cerion/* sz, ULong -> IRExpr */
10362831b00c4950d6c2b061def05fd67528fe132ececerionstatic IRExpr* mkSzImm ( IRType ty, ULong imm64 )
1037d953ebb9b04cbad6891676df597bf0c542b1ec89cerion{
1038d953ebb9b04cbad6891676df597bf0c542b1ec89cerion   vassert(ty == Ity_I32 || ty == Ity_I64);
1039d953ebb9b04cbad6891676df597bf0c542b1ec89cerion   return ty == Ity_I64 ? mkU64(imm64) : mkU32((UInt)imm64);
1040d953ebb9b04cbad6891676df597bf0c542b1ec89cerion}
1041d953ebb9b04cbad6891676df597bf0c542b1ec89cerion
1042d953ebb9b04cbad6891676df597bf0c542b1ec89cerion/* sz, ULong -> IRConst */
10432831b00c4950d6c2b061def05fd67528fe132ececerionstatic IRConst* mkSzConst ( IRType ty, ULong imm64 )
1044d953ebb9b04cbad6891676df597bf0c542b1ec89cerion{
1045d953ebb9b04cbad6891676df597bf0c542b1ec89cerion   vassert(ty == Ity_I32 || ty == Ity_I64);
1046d953ebb9b04cbad6891676df597bf0c542b1ec89cerion   return ( ty == Ity_I64 ?
1047d953ebb9b04cbad6891676df597bf0c542b1ec89cerion            IRConst_U64(imm64) :
1048d953ebb9b04cbad6891676df597bf0c542b1ec89cerion            IRConst_U32((UInt)imm64) );
1049d953ebb9b04cbad6891676df597bf0c542b1ec89cerion}
1050d953ebb9b04cbad6891676df597bf0c542b1ec89cerion
1051d953ebb9b04cbad6891676df597bf0c542b1ec89cerion/* Sign extend imm16 -> IRExpr* */
10522831b00c4950d6c2b061def05fd67528fe132ececerionstatic IRExpr* mkSzExtendS16 ( IRType ty, UInt imm16 )
1053d953ebb9b04cbad6891676df597bf0c542b1ec89cerion{
1054d953ebb9b04cbad6891676df597bf0c542b1ec89cerion   vassert(ty == Ity_I32 || ty == Ity_I64);
1055d953ebb9b04cbad6891676df597bf0c542b1ec89cerion   return ( ty == Ity_I64 ?
1056d953ebb9b04cbad6891676df597bf0c542b1ec89cerion            mkU64(extend_s_16to64(imm16)) :
1057d953ebb9b04cbad6891676df597bf0c542b1ec89cerion            mkU32(extend_s_16to32(imm16)) );
1058d953ebb9b04cbad6891676df597bf0c542b1ec89cerion}
1059d953ebb9b04cbad6891676df597bf0c542b1ec89cerion
1060d953ebb9b04cbad6891676df597bf0c542b1ec89cerion/* Sign extend imm32 -> IRExpr* */
10612831b00c4950d6c2b061def05fd67528fe132ececerionstatic IRExpr* mkSzExtendS32 ( IRType ty, UInt imm32 )
1062d953ebb9b04cbad6891676df597bf0c542b1ec89cerion{
1063d953ebb9b04cbad6891676df597bf0c542b1ec89cerion   vassert(ty == Ity_I32 || ty == Ity_I64);
1064d953ebb9b04cbad6891676df597bf0c542b1ec89cerion   return ( ty == Ity_I64 ?
1065d953ebb9b04cbad6891676df597bf0c542b1ec89cerion            mkU64(extend_s_32to64(imm32)) :
1066d953ebb9b04cbad6891676df597bf0c542b1ec89cerion            mkU32(imm32) );
1067d953ebb9b04cbad6891676df597bf0c542b1ec89cerion}
1068d953ebb9b04cbad6891676df597bf0c542b1ec89cerion
1069d953ebb9b04cbad6891676df597bf0c542b1ec89cerion/* IR narrows I32/I64 -> I8/I16/I32 */
1070e9d8a26b690c2561ac54ab0cd6ad83ecbadcbe76sewardjstatic IRExpr* mkNarrowTo8 ( IRType ty, IRExpr* src )
1071d953ebb9b04cbad6891676df597bf0c542b1ec89cerion{
1072d953ebb9b04cbad6891676df597bf0c542b1ec89cerion   vassert(ty == Ity_I32 || ty == Ity_I64);
1073d953ebb9b04cbad6891676df597bf0c542b1ec89cerion   return ty == Ity_I64 ? unop(Iop_64to8, src) : unop(Iop_32to8, src);
1074d953ebb9b04cbad6891676df597bf0c542b1ec89cerion}
1075d953ebb9b04cbad6891676df597bf0c542b1ec89cerion
1076e9d8a26b690c2561ac54ab0cd6ad83ecbadcbe76sewardjstatic IRExpr* mkNarrowTo16 ( IRType ty, IRExpr* src )
1077d953ebb9b04cbad6891676df597bf0c542b1ec89cerion{
1078d953ebb9b04cbad6891676df597bf0c542b1ec89cerion   vassert(ty == Ity_I32 || ty == Ity_I64);
1079d953ebb9b04cbad6891676df597bf0c542b1ec89cerion   return ty == Ity_I64 ? unop(Iop_64to16, src) : unop(Iop_32to16, src);
1080d953ebb9b04cbad6891676df597bf0c542b1ec89cerion}
1081d953ebb9b04cbad6891676df597bf0c542b1ec89cerion
1082e9d8a26b690c2561ac54ab0cd6ad83ecbadcbe76sewardjstatic IRExpr* mkNarrowTo32 ( IRType ty, IRExpr* src )
1083d953ebb9b04cbad6891676df597bf0c542b1ec89cerion{
1084d953ebb9b04cbad6891676df597bf0c542b1ec89cerion   vassert(ty == Ity_I32 || ty == Ity_I64);
1085d953ebb9b04cbad6891676df597bf0c542b1ec89cerion   return ty == Ity_I64 ? unop(Iop_64to32, src) : src;
1086d953ebb9b04cbad6891676df597bf0c542b1ec89cerion}
1087d953ebb9b04cbad6891676df597bf0c542b1ec89cerion
1088d953ebb9b04cbad6891676df597bf0c542b1ec89cerion/* Signed/Unsigned IR widens I8/I16/I32 -> I32/I64 */
1089e9d8a26b690c2561ac54ab0cd6ad83ecbadcbe76sewardjstatic IRExpr* mkWidenFrom8 ( IRType ty, IRExpr* src, Bool sined )
1090d953ebb9b04cbad6891676df597bf0c542b1ec89cerion{
1091d953ebb9b04cbad6891676df597bf0c542b1ec89cerion   IROp op;
1092633274098fafebdc79cf1c8a1ef7f9a9914669f1sewardj   vassert(ty == Ity_I32 || ty == Ity_I64);
1093d953ebb9b04cbad6891676df597bf0c542b1ec89cerion   if (sined) op = (ty==Ity_I32) ? Iop_8Sto32 : Iop_8Sto64;
1094d953ebb9b04cbad6891676df597bf0c542b1ec89cerion   else       op = (ty==Ity_I32) ? Iop_8Uto32 : Iop_8Uto64;
1095d953ebb9b04cbad6891676df597bf0c542b1ec89cerion   return unop(op, src);
1096d953ebb9b04cbad6891676df597bf0c542b1ec89cerion}
1097d953ebb9b04cbad6891676df597bf0c542b1ec89cerion
1098e9d8a26b690c2561ac54ab0cd6ad83ecbadcbe76sewardjstatic IRExpr* mkWidenFrom16 ( IRType ty, IRExpr* src, Bool sined )
1099d953ebb9b04cbad6891676df597bf0c542b1ec89cerion{
1100d953ebb9b04cbad6891676df597bf0c542b1ec89cerion   IROp op;
1101633274098fafebdc79cf1c8a1ef7f9a9914669f1sewardj   vassert(ty == Ity_I32 || ty == Ity_I64);
1102d953ebb9b04cbad6891676df597bf0c542b1ec89cerion   if (sined) op = (ty==Ity_I32) ? Iop_16Sto32 : Iop_16Sto64;
1103d953ebb9b04cbad6891676df597bf0c542b1ec89cerion   else       op = (ty==Ity_I32) ? Iop_16Uto32 : Iop_16Uto64;
1104d953ebb9b04cbad6891676df597bf0c542b1ec89cerion   return unop(op, src);
1105d953ebb9b04cbad6891676df597bf0c542b1ec89cerion}
1106d953ebb9b04cbad6891676df597bf0c542b1ec89cerion
1107e9d8a26b690c2561ac54ab0cd6ad83ecbadcbe76sewardjstatic IRExpr* mkWidenFrom32 ( IRType ty, IRExpr* src, Bool sined )
1108d953ebb9b04cbad6891676df597bf0c542b1ec89cerion{
1109d953ebb9b04cbad6891676df597bf0c542b1ec89cerion   vassert(ty == Ity_I32 || ty == Ity_I64);
1110d953ebb9b04cbad6891676df597bf0c542b1ec89cerion   if (ty == Ity_I32)
1111d953ebb9b04cbad6891676df597bf0c542b1ec89cerion      return src;
1112d953ebb9b04cbad6891676df597bf0c542b1ec89cerion   return (sined) ? unop(Iop_32Sto64, src) : unop(Iop_32Uto64, src);
1113d953ebb9b04cbad6891676df597bf0c542b1ec89cerion}
111424d06f124e3325e8edcc1c495d15736d5adcda96cerion
11154a49b0393204185f87664ea58f2b7a2ae1d37338cerion
1116896a1373cfdbaa25f4ab73ed4f27554016defecccerionstatic Int integerGuestRegOffset ( UInt archreg )
1117896a1373cfdbaa25f4ab73ed4f27554016defecccerion{
1118896a1373cfdbaa25f4ab73ed4f27554016defecccerion   vassert(archreg < 32);
1119b85e8bba97fdae7d892f7bfd12e4601307e4721dcerion
1120e9d361ab43518b6dfbd3d846f48859534659dee0cerion   // jrs: probably not necessary; only matters if we reference sub-parts
11215b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion   // of the ppc registers, but that isn't the case
11229e6491ab55324b8e45e187b1e1e9632ac3cb3e27sewardj   // later: this might affect Altivec though?
1123e9d361ab43518b6dfbd3d846f48859534659dee0cerion
11245b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion   switch (archreg) {
11255b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion   case  0: return offsetofPPCGuestState(guest_GPR0);
11265b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion   case  1: return offsetofPPCGuestState(guest_GPR1);
11275b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion   case  2: return offsetofPPCGuestState(guest_GPR2);
11285b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion   case  3: return offsetofPPCGuestState(guest_GPR3);
11295b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion   case  4: return offsetofPPCGuestState(guest_GPR4);
11305b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion   case  5: return offsetofPPCGuestState(guest_GPR5);
11315b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion   case  6: return offsetofPPCGuestState(guest_GPR6);
11325b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion   case  7: return offsetofPPCGuestState(guest_GPR7);
11335b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion   case  8: return offsetofPPCGuestState(guest_GPR8);
11345b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion   case  9: return offsetofPPCGuestState(guest_GPR9);
11355b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion   case 10: return offsetofPPCGuestState(guest_GPR10);
11365b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion   case 11: return offsetofPPCGuestState(guest_GPR11);
11375b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion   case 12: return offsetofPPCGuestState(guest_GPR12);
11385b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion   case 13: return offsetofPPCGuestState(guest_GPR13);
11395b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion   case 14: return offsetofPPCGuestState(guest_GPR14);
11405b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion   case 15: return offsetofPPCGuestState(guest_GPR15);
11415b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion   case 16: return offsetofPPCGuestState(guest_GPR16);
11425b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion   case 17: return offsetofPPCGuestState(guest_GPR17);
11435b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion   case 18: return offsetofPPCGuestState(guest_GPR18);
11445b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion   case 19: return offsetofPPCGuestState(guest_GPR19);
11455b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion   case 20: return offsetofPPCGuestState(guest_GPR20);
11465b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion   case 21: return offsetofPPCGuestState(guest_GPR21);
11475b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion   case 22: return offsetofPPCGuestState(guest_GPR22);
11485b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion   case 23: return offsetofPPCGuestState(guest_GPR23);
11495b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion   case 24: return offsetofPPCGuestState(guest_GPR24);
11505b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion   case 25: return offsetofPPCGuestState(guest_GPR25);
11515b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion   case 26: return offsetofPPCGuestState(guest_GPR26);
11525b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion   case 27: return offsetofPPCGuestState(guest_GPR27);
11535b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion   case 28: return offsetofPPCGuestState(guest_GPR28);
11545b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion   case 29: return offsetofPPCGuestState(guest_GPR29);
11555b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion   case 30: return offsetofPPCGuestState(guest_GPR30);
11565b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion   case 31: return offsetofPPCGuestState(guest_GPR31);
11575b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion   default: break;
11585b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion   }
11595b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion   vpanic("integerGuestRegOffset(ppc,be)"); /*notreached*/
1160896a1373cfdbaa25f4ab73ed4f27554016defecccerion}
1161896a1373cfdbaa25f4ab73ed4f27554016defecccerion
1162896a1373cfdbaa25f4ab73ed4f27554016defecccerionstatic IRExpr* getIReg ( UInt archreg )
1163896a1373cfdbaa25f4ab73ed4f27554016defecccerion{
1164d953ebb9b04cbad6891676df597bf0c542b1ec89cerion   IRType ty = mode64 ? Ity_I64 : Ity_I32;
1165896a1373cfdbaa25f4ab73ed4f27554016defecccerion   vassert(archreg < 32);
1166d953ebb9b04cbad6891676df597bf0c542b1ec89cerion   return IRExpr_Get( integerGuestRegOffset(archreg), ty );
1167896a1373cfdbaa25f4ab73ed4f27554016defecccerion}
1168896a1373cfdbaa25f4ab73ed4f27554016defecccerion
1169896a1373cfdbaa25f4ab73ed4f27554016defecccerion/* Ditto, but write to a reg instead. */
1170896a1373cfdbaa25f4ab73ed4f27554016defecccerionstatic void putIReg ( UInt archreg, IRExpr* e )
1171896a1373cfdbaa25f4ab73ed4f27554016defecccerion{
1172d953ebb9b04cbad6891676df597bf0c542b1ec89cerion   IRType ty = mode64 ? Ity_I64 : Ity_I32;
1173896a1373cfdbaa25f4ab73ed4f27554016defecccerion   vassert(archreg < 32);
1174dd40fdf58cc8a6fe9466c4f00bdfc9fe9bf00449sewardj   vassert(typeOfIRExpr(irsb->tyenv, e) == ty );
1175896a1373cfdbaa25f4ab73ed4f27554016defecccerion   stmt( IRStmt_Put(integerGuestRegOffset(archreg), e) );
1176896a1373cfdbaa25f4ab73ed4f27554016defecccerion}
1177896a1373cfdbaa25f4ab73ed4f27554016defecccerion
1178094d1397b3f69b1a538e80ab509ea8cd75f4be3bcerion
117966d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj/* Floating point egisters are mapped to VSX registers[0..31]. */
1180094d1397b3f69b1a538e80ab509ea8cd75f4be3bcerionstatic Int floatGuestRegOffset ( UInt archreg )
1181094d1397b3f69b1a538e80ab509ea8cd75f4be3bcerion{
1182094d1397b3f69b1a538e80ab509ea8cd75f4be3bcerion   vassert(archreg < 32);
1183094d1397b3f69b1a538e80ab509ea8cd75f4be3bcerion
11841f5fe1fc3a37ca729925e8eec25aa1025b4a6cdbcarll   if (host_endness == VexEndnessLE) {
11851f5fe1fc3a37ca729925e8eec25aa1025b4a6cdbcarll      switch (archreg) {
11862f93145a08ad90721cf267fc141eb6daebd53f46carll         case  0: return offsetofPPCGuestState(guest_VSR0) + 8;
11872f93145a08ad90721cf267fc141eb6daebd53f46carll         case  1: return offsetofPPCGuestState(guest_VSR1) + 8;
11882f93145a08ad90721cf267fc141eb6daebd53f46carll         case  2: return offsetofPPCGuestState(guest_VSR2) + 8;
11892f93145a08ad90721cf267fc141eb6daebd53f46carll         case  3: return offsetofPPCGuestState(guest_VSR3) + 8;
11902f93145a08ad90721cf267fc141eb6daebd53f46carll         case  4: return offsetofPPCGuestState(guest_VSR4) + 8;
11912f93145a08ad90721cf267fc141eb6daebd53f46carll         case  5: return offsetofPPCGuestState(guest_VSR5) + 8;
11922f93145a08ad90721cf267fc141eb6daebd53f46carll         case  6: return offsetofPPCGuestState(guest_VSR6) + 8;
11932f93145a08ad90721cf267fc141eb6daebd53f46carll         case  7: return offsetofPPCGuestState(guest_VSR7) + 8;
11942f93145a08ad90721cf267fc141eb6daebd53f46carll         case  8: return offsetofPPCGuestState(guest_VSR8) + 8;
11952f93145a08ad90721cf267fc141eb6daebd53f46carll         case  9: return offsetofPPCGuestState(guest_VSR9) + 8;
11962f93145a08ad90721cf267fc141eb6daebd53f46carll         case 10: return offsetofPPCGuestState(guest_VSR10) + 8;
11972f93145a08ad90721cf267fc141eb6daebd53f46carll         case 11: return offsetofPPCGuestState(guest_VSR11) + 8;
11982f93145a08ad90721cf267fc141eb6daebd53f46carll         case 12: return offsetofPPCGuestState(guest_VSR12) + 8;
11992f93145a08ad90721cf267fc141eb6daebd53f46carll         case 13: return offsetofPPCGuestState(guest_VSR13) + 8;
12002f93145a08ad90721cf267fc141eb6daebd53f46carll         case 14: return offsetofPPCGuestState(guest_VSR14) + 8;
12012f93145a08ad90721cf267fc141eb6daebd53f46carll         case 15: return offsetofPPCGuestState(guest_VSR15) + 8;
12022f93145a08ad90721cf267fc141eb6daebd53f46carll         case 16: return offsetofPPCGuestState(guest_VSR16) + 8;
12032f93145a08ad90721cf267fc141eb6daebd53f46carll         case 17: return offsetofPPCGuestState(guest_VSR17) + 8;
12042f93145a08ad90721cf267fc141eb6daebd53f46carll         case 18: return offsetofPPCGuestState(guest_VSR18) + 8;
12052f93145a08ad90721cf267fc141eb6daebd53f46carll         case 19: return offsetofPPCGuestState(guest_VSR19) + 8;
12062f93145a08ad90721cf267fc141eb6daebd53f46carll         case 20: return offsetofPPCGuestState(guest_VSR20) + 8;
12072f93145a08ad90721cf267fc141eb6daebd53f46carll         case 21: return offsetofPPCGuestState(guest_VSR21) + 8;
12082f93145a08ad90721cf267fc141eb6daebd53f46carll         case 22: return offsetofPPCGuestState(guest_VSR22) + 8;
12092f93145a08ad90721cf267fc141eb6daebd53f46carll         case 23: return offsetofPPCGuestState(guest_VSR23) + 8;
12102f93145a08ad90721cf267fc141eb6daebd53f46carll         case 24: return offsetofPPCGuestState(guest_VSR24) + 8;
12112f93145a08ad90721cf267fc141eb6daebd53f46carll         case 25: return offsetofPPCGuestState(guest_VSR25) + 8;
12122f93145a08ad90721cf267fc141eb6daebd53f46carll         case 26: return offsetofPPCGuestState(guest_VSR26) + 8;
12132f93145a08ad90721cf267fc141eb6daebd53f46carll         case 27: return offsetofPPCGuestState(guest_VSR27) + 8;
12142f93145a08ad90721cf267fc141eb6daebd53f46carll         case 28: return offsetofPPCGuestState(guest_VSR28) + 8;
12152f93145a08ad90721cf267fc141eb6daebd53f46carll         case 29: return offsetofPPCGuestState(guest_VSR29) + 8;
12162f93145a08ad90721cf267fc141eb6daebd53f46carll         case 30: return offsetofPPCGuestState(guest_VSR30) + 8;
12172f93145a08ad90721cf267fc141eb6daebd53f46carll         case 31: return offsetofPPCGuestState(guest_VSR31) + 8;
12181f5fe1fc3a37ca729925e8eec25aa1025b4a6cdbcarll         default: break;
12191f5fe1fc3a37ca729925e8eec25aa1025b4a6cdbcarll      }
12201f5fe1fc3a37ca729925e8eec25aa1025b4a6cdbcarll   } else {
12211f5fe1fc3a37ca729925e8eec25aa1025b4a6cdbcarll      switch (archreg) {
12221f5fe1fc3a37ca729925e8eec25aa1025b4a6cdbcarll         case  0: return offsetofPPCGuestState(guest_VSR0);
12231f5fe1fc3a37ca729925e8eec25aa1025b4a6cdbcarll         case  1: return offsetofPPCGuestState(guest_VSR1);
12241f5fe1fc3a37ca729925e8eec25aa1025b4a6cdbcarll         case  2: return offsetofPPCGuestState(guest_VSR2);
12251f5fe1fc3a37ca729925e8eec25aa1025b4a6cdbcarll         case  3: return offsetofPPCGuestState(guest_VSR3);
12261f5fe1fc3a37ca729925e8eec25aa1025b4a6cdbcarll         case  4: return offsetofPPCGuestState(guest_VSR4);
12271f5fe1fc3a37ca729925e8eec25aa1025b4a6cdbcarll         case  5: return offsetofPPCGuestState(guest_VSR5);
12281f5fe1fc3a37ca729925e8eec25aa1025b4a6cdbcarll         case  6: return offsetofPPCGuestState(guest_VSR6);
12291f5fe1fc3a37ca729925e8eec25aa1025b4a6cdbcarll         case  7: return offsetofPPCGuestState(guest_VSR7);
12301f5fe1fc3a37ca729925e8eec25aa1025b4a6cdbcarll         case  8: return offsetofPPCGuestState(guest_VSR8);
12311f5fe1fc3a37ca729925e8eec25aa1025b4a6cdbcarll         case  9: return offsetofPPCGuestState(guest_VSR9);
12321f5fe1fc3a37ca729925e8eec25aa1025b4a6cdbcarll         case 10: return offsetofPPCGuestState(guest_VSR10);
12331f5fe1fc3a37ca729925e8eec25aa1025b4a6cdbcarll         case 11: return offsetofPPCGuestState(guest_VSR11);
12341f5fe1fc3a37ca729925e8eec25aa1025b4a6cdbcarll         case 12: return offsetofPPCGuestState(guest_VSR12);
12351f5fe1fc3a37ca729925e8eec25aa1025b4a6cdbcarll         case 13: return offsetofPPCGuestState(guest_VSR13);
12361f5fe1fc3a37ca729925e8eec25aa1025b4a6cdbcarll         case 14: return offsetofPPCGuestState(guest_VSR14);
12371f5fe1fc3a37ca729925e8eec25aa1025b4a6cdbcarll         case 15: return offsetofPPCGuestState(guest_VSR15);
12381f5fe1fc3a37ca729925e8eec25aa1025b4a6cdbcarll         case 16: return offsetofPPCGuestState(guest_VSR16);
12391f5fe1fc3a37ca729925e8eec25aa1025b4a6cdbcarll         case 17: return offsetofPPCGuestState(guest_VSR17);
12401f5fe1fc3a37ca729925e8eec25aa1025b4a6cdbcarll         case 18: return offsetofPPCGuestState(guest_VSR18);
12411f5fe1fc3a37ca729925e8eec25aa1025b4a6cdbcarll         case 19: return offsetofPPCGuestState(guest_VSR19);
12421f5fe1fc3a37ca729925e8eec25aa1025b4a6cdbcarll         case 20: return offsetofPPCGuestState(guest_VSR20);
12431f5fe1fc3a37ca729925e8eec25aa1025b4a6cdbcarll         case 21: return offsetofPPCGuestState(guest_VSR21);
12441f5fe1fc3a37ca729925e8eec25aa1025b4a6cdbcarll         case 22: return offsetofPPCGuestState(guest_VSR22);
12451f5fe1fc3a37ca729925e8eec25aa1025b4a6cdbcarll         case 23: return offsetofPPCGuestState(guest_VSR23);
12461f5fe1fc3a37ca729925e8eec25aa1025b4a6cdbcarll         case 24: return offsetofPPCGuestState(guest_VSR24);
12471f5fe1fc3a37ca729925e8eec25aa1025b4a6cdbcarll         case 25: return offsetofPPCGuestState(guest_VSR25);
12481f5fe1fc3a37ca729925e8eec25aa1025b4a6cdbcarll         case 26: return offsetofPPCGuestState(guest_VSR26);
12491f5fe1fc3a37ca729925e8eec25aa1025b4a6cdbcarll         case 27: return offsetofPPCGuestState(guest_VSR27);
12501f5fe1fc3a37ca729925e8eec25aa1025b4a6cdbcarll         case 28: return offsetofPPCGuestState(guest_VSR28);
12511f5fe1fc3a37ca729925e8eec25aa1025b4a6cdbcarll         case 29: return offsetofPPCGuestState(guest_VSR29);
12521f5fe1fc3a37ca729925e8eec25aa1025b4a6cdbcarll         case 30: return offsetofPPCGuestState(guest_VSR30);
12531f5fe1fc3a37ca729925e8eec25aa1025b4a6cdbcarll         case 31: return offsetofPPCGuestState(guest_VSR31);
12541f5fe1fc3a37ca729925e8eec25aa1025b4a6cdbcarll         default: break;
12551f5fe1fc3a37ca729925e8eec25aa1025b4a6cdbcarll      }
12565b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion   }
12575b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion   vpanic("floatGuestRegOffset(ppc)"); /*notreached*/
1258094d1397b3f69b1a538e80ab509ea8cd75f4be3bcerion}
1259094d1397b3f69b1a538e80ab509ea8cd75f4be3bcerion
1260094d1397b3f69b1a538e80ab509ea8cd75f4be3bcerionstatic IRExpr* getFReg ( UInt archreg )
1261094d1397b3f69b1a538e80ab509ea8cd75f4be3bcerion{
1262094d1397b3f69b1a538e80ab509ea8cd75f4be3bcerion   vassert(archreg < 32);
1263094d1397b3f69b1a538e80ab509ea8cd75f4be3bcerion   return IRExpr_Get( floatGuestRegOffset(archreg), Ity_F64 );
1264094d1397b3f69b1a538e80ab509ea8cd75f4be3bcerion}
1265094d1397b3f69b1a538e80ab509ea8cd75f4be3bcerion
1266094d1397b3f69b1a538e80ab509ea8cd75f4be3bcerion/* Ditto, but write to a reg instead. */
1267094d1397b3f69b1a538e80ab509ea8cd75f4be3bcerionstatic void putFReg ( UInt archreg, IRExpr* e )
1268094d1397b3f69b1a538e80ab509ea8cd75f4be3bcerion{
1269094d1397b3f69b1a538e80ab509ea8cd75f4be3bcerion   vassert(archreg < 32);
1270dd40fdf58cc8a6fe9466c4f00bdfc9fe9bf00449sewardj   vassert(typeOfIRExpr(irsb->tyenv, e) == Ity_F64);
1271094d1397b3f69b1a538e80ab509ea8cd75f4be3bcerion   stmt( IRStmt_Put(floatGuestRegOffset(archreg), e) );
1272094d1397b3f69b1a538e80ab509ea8cd75f4be3bcerion}
1273094d1397b3f69b1a538e80ab509ea8cd75f4be3bcerion
1274c6bbd470e9bd9898b84959227a406d3972d95f3bsewardj/* get Decimal float value.  Note, they share floating point register file. */
1275c6bbd470e9bd9898b84959227a406d3972d95f3bsewardjstatic IRExpr* getDReg(UInt archreg) {
1276c6bbd470e9bd9898b84959227a406d3972d95f3bsewardj   IRExpr *e;
1277c6bbd470e9bd9898b84959227a406d3972d95f3bsewardj   vassert( archreg < 32 );
1278c6bbd470e9bd9898b84959227a406d3972d95f3bsewardj   e = IRExpr_Get( floatGuestRegOffset( archreg ), Ity_D64 );
1279c6bbd470e9bd9898b84959227a406d3972d95f3bsewardj   return e;
1280c6bbd470e9bd9898b84959227a406d3972d95f3bsewardj}
1281f704eb2bab3d06d983c850b0bcf243e178060f75carllstatic IRExpr* getDReg32(UInt archreg) {
1282f704eb2bab3d06d983c850b0bcf243e178060f75carll   IRExpr *e;
1283f704eb2bab3d06d983c850b0bcf243e178060f75carll   vassert( archreg < 32 );
1284f704eb2bab3d06d983c850b0bcf243e178060f75carll   e = IRExpr_Get( floatGuestRegOffset( archreg ), Ity_D32 );
1285f704eb2bab3d06d983c850b0bcf243e178060f75carll   return e;
1286f704eb2bab3d06d983c850b0bcf243e178060f75carll}
1287c6bbd470e9bd9898b84959227a406d3972d95f3bsewardj
1288c6bbd470e9bd9898b84959227a406d3972d95f3bsewardj/* Read a floating point register pair and combine their contents into a
1289c6bbd470e9bd9898b84959227a406d3972d95f3bsewardj 128-bit value */
1290c6bbd470e9bd9898b84959227a406d3972d95f3bsewardjstatic IRExpr *getDReg_pair(UInt archreg) {
1291c6bbd470e9bd9898b84959227a406d3972d95f3bsewardj   IRExpr *high = getDReg( archreg );
1292c6bbd470e9bd9898b84959227a406d3972d95f3bsewardj   IRExpr *low = getDReg( archreg + 1 );
1293c6bbd470e9bd9898b84959227a406d3972d95f3bsewardj
1294c6bbd470e9bd9898b84959227a406d3972d95f3bsewardj   return binop( Iop_D64HLtoD128, high, low );
1295c6bbd470e9bd9898b84959227a406d3972d95f3bsewardj}
1296c6bbd470e9bd9898b84959227a406d3972d95f3bsewardj
1297c6bbd470e9bd9898b84959227a406d3972d95f3bsewardj/* Ditto, but write to a reg instead. */
1298f704eb2bab3d06d983c850b0bcf243e178060f75carllstatic void putDReg32(UInt archreg, IRExpr* e) {
1299f704eb2bab3d06d983c850b0bcf243e178060f75carll   vassert( archreg < 32 );
1300f704eb2bab3d06d983c850b0bcf243e178060f75carll   vassert( typeOfIRExpr(irsb->tyenv, e) == Ity_D32 );
1301f704eb2bab3d06d983c850b0bcf243e178060f75carll   stmt( IRStmt_Put( floatGuestRegOffset( archreg ), e ) );
1302f704eb2bab3d06d983c850b0bcf243e178060f75carll}
1303f704eb2bab3d06d983c850b0bcf243e178060f75carll
1304c6bbd470e9bd9898b84959227a406d3972d95f3bsewardjstatic void putDReg(UInt archreg, IRExpr* e) {
1305c6bbd470e9bd9898b84959227a406d3972d95f3bsewardj   vassert( archreg < 32 );
1306c6bbd470e9bd9898b84959227a406d3972d95f3bsewardj   vassert( typeOfIRExpr(irsb->tyenv, e) == Ity_D64 );
1307c6bbd470e9bd9898b84959227a406d3972d95f3bsewardj   stmt( IRStmt_Put( floatGuestRegOffset( archreg ), e ) );
1308c6bbd470e9bd9898b84959227a406d3972d95f3bsewardj}
1309c6bbd470e9bd9898b84959227a406d3972d95f3bsewardj
1310c6bbd470e9bd9898b84959227a406d3972d95f3bsewardj/* Write a 128-bit floating point value into a register pair. */
1311c6bbd470e9bd9898b84959227a406d3972d95f3bsewardjstatic void putDReg_pair(UInt archreg, IRExpr *e) {
1312c6bbd470e9bd9898b84959227a406d3972d95f3bsewardj   IRTemp low = newTemp( Ity_D64 );
1313c6bbd470e9bd9898b84959227a406d3972d95f3bsewardj   IRTemp high = newTemp( Ity_D64 );
1314c6bbd470e9bd9898b84959227a406d3972d95f3bsewardj
1315c6bbd470e9bd9898b84959227a406d3972d95f3bsewardj   vassert( archreg < 32 );
1316c6bbd470e9bd9898b84959227a406d3972d95f3bsewardj   vassert( typeOfIRExpr(irsb->tyenv, e) == Ity_D128 );
1317c6bbd470e9bd9898b84959227a406d3972d95f3bsewardj
1318c6bbd470e9bd9898b84959227a406d3972d95f3bsewardj   assign( low, unop( Iop_D128LOtoD64, e ) );
1319c6bbd470e9bd9898b84959227a406d3972d95f3bsewardj   assign( high, unop( Iop_D128HItoD64, e ) );
1320c6bbd470e9bd9898b84959227a406d3972d95f3bsewardj
1321c6bbd470e9bd9898b84959227a406d3972d95f3bsewardj   stmt( IRStmt_Put( floatGuestRegOffset( archreg ), mkexpr( high ) ) );
1322c6bbd470e9bd9898b84959227a406d3972d95f3bsewardj   stmt( IRStmt_Put( floatGuestRegOffset( archreg + 1 ), mkexpr( low ) ) );
1323c6bbd470e9bd9898b84959227a406d3972d95f3bsewardj}
1324c6bbd470e9bd9898b84959227a406d3972d95f3bsewardj
132566d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardjstatic Int vsxGuestRegOffset ( UInt archreg )
132666d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj{
132766d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj   vassert(archreg < 64);
132866d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj   switch (archreg) {
132966d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj   case  0: return offsetofPPCGuestState(guest_VSR0);
133066d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj   case  1: return offsetofPPCGuestState(guest_VSR1);
133166d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj   case  2: return offsetofPPCGuestState(guest_VSR2);
133266d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj   case  3: return offsetofPPCGuestState(guest_VSR3);
133366d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj   case  4: return offsetofPPCGuestState(guest_VSR4);
133466d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj   case  5: return offsetofPPCGuestState(guest_VSR5);
133566d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj   case  6: return offsetofPPCGuestState(guest_VSR6);
133666d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj   case  7: return offsetofPPCGuestState(guest_VSR7);
133766d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj   case  8: return offsetofPPCGuestState(guest_VSR8);
133866d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj   case  9: return offsetofPPCGuestState(guest_VSR9);
133966d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj   case 10: return offsetofPPCGuestState(guest_VSR10);
134066d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj   case 11: return offsetofPPCGuestState(guest_VSR11);
134166d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj   case 12: return offsetofPPCGuestState(guest_VSR12);
134266d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj   case 13: return offsetofPPCGuestState(guest_VSR13);
134366d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj   case 14: return offsetofPPCGuestState(guest_VSR14);
134466d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj   case 15: return offsetofPPCGuestState(guest_VSR15);
134566d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj   case 16: return offsetofPPCGuestState(guest_VSR16);
134666d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj   case 17: return offsetofPPCGuestState(guest_VSR17);
134766d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj   case 18: return offsetofPPCGuestState(guest_VSR18);
134866d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj   case 19: return offsetofPPCGuestState(guest_VSR19);
134966d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj   case 20: return offsetofPPCGuestState(guest_VSR20);
135066d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj   case 21: return offsetofPPCGuestState(guest_VSR21);
135166d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj   case 22: return offsetofPPCGuestState(guest_VSR22);
135266d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj   case 23: return offsetofPPCGuestState(guest_VSR23);
135366d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj   case 24: return offsetofPPCGuestState(guest_VSR24);
135466d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj   case 25: return offsetofPPCGuestState(guest_VSR25);
135566d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj   case 26: return offsetofPPCGuestState(guest_VSR26);
135666d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj   case 27: return offsetofPPCGuestState(guest_VSR27);
135766d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj   case 28: return offsetofPPCGuestState(guest_VSR28);
135866d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj   case 29: return offsetofPPCGuestState(guest_VSR29);
135966d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj   case 30: return offsetofPPCGuestState(guest_VSR30);
136066d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj   case 31: return offsetofPPCGuestState(guest_VSR31);
136166d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj   case 32: return offsetofPPCGuestState(guest_VSR32);
136266d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj   case 33: return offsetofPPCGuestState(guest_VSR33);
136366d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj   case 34: return offsetofPPCGuestState(guest_VSR34);
136466d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj   case 35: return offsetofPPCGuestState(guest_VSR35);
136566d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj   case 36: return offsetofPPCGuestState(guest_VSR36);
136666d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj   case 37: return offsetofPPCGuestState(guest_VSR37);
136766d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj   case 38: return offsetofPPCGuestState(guest_VSR38);
136866d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj   case 39: return offsetofPPCGuestState(guest_VSR39);
136966d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj   case 40: return offsetofPPCGuestState(guest_VSR40);
137066d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj   case 41: return offsetofPPCGuestState(guest_VSR41);
137166d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj   case 42: return offsetofPPCGuestState(guest_VSR42);
137266d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj   case 43: return offsetofPPCGuestState(guest_VSR43);
137366d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj   case 44: return offsetofPPCGuestState(guest_VSR44);
137466d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj   case 45: return offsetofPPCGuestState(guest_VSR45);
137566d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj   case 46: return offsetofPPCGuestState(guest_VSR46);
137666d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj   case 47: return offsetofPPCGuestState(guest_VSR47);
137766d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj   case 48: return offsetofPPCGuestState(guest_VSR48);
137866d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj   case 49: return offsetofPPCGuestState(guest_VSR49);
137966d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj   case 50: return offsetofPPCGuestState(guest_VSR50);
138066d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj   case 51: return offsetofPPCGuestState(guest_VSR51);
138166d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj   case 52: return offsetofPPCGuestState(guest_VSR52);
138266d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj   case 53: return offsetofPPCGuestState(guest_VSR53);
138366d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj   case 54: return offsetofPPCGuestState(guest_VSR54);
138466d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj   case 55: return offsetofPPCGuestState(guest_VSR55);
138566d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj   case 56: return offsetofPPCGuestState(guest_VSR56);
138666d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj   case 57: return offsetofPPCGuestState(guest_VSR57);
138766d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj   case 58: return offsetofPPCGuestState(guest_VSR58);
138866d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj   case 59: return offsetofPPCGuestState(guest_VSR59);
138966d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj   case 60: return offsetofPPCGuestState(guest_VSR60);
139066d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj   case 61: return offsetofPPCGuestState(guest_VSR61);
139166d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj   case 62: return offsetofPPCGuestState(guest_VSR62);
139266d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj   case 63: return offsetofPPCGuestState(guest_VSR63);
139366d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj   default: break;
139466d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj   }
139566d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj   vpanic("vsxGuestRegOffset(ppc)"); /*notreached*/
139666d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj}
1397094d1397b3f69b1a538e80ab509ea8cd75f4be3bcerion
139866d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj/* Vector registers are mapped to VSX registers[32..63]. */
1399a982c0503d8c0c6069ae453bfe70657bd2c134aecerionstatic Int vectorGuestRegOffset ( UInt archreg )
1400a982c0503d8c0c6069ae453bfe70657bd2c134aecerion{
1401a982c0503d8c0c6069ae453bfe70657bd2c134aecerion   vassert(archreg < 32);
1402a982c0503d8c0c6069ae453bfe70657bd2c134aecerion
14035b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion   switch (archreg) {
140466d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj   case  0: return offsetofPPCGuestState(guest_VSR32);
140566d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj   case  1: return offsetofPPCGuestState(guest_VSR33);
140666d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj   case  2: return offsetofPPCGuestState(guest_VSR34);
140766d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj   case  3: return offsetofPPCGuestState(guest_VSR35);
140866d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj   case  4: return offsetofPPCGuestState(guest_VSR36);
140966d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj   case  5: return offsetofPPCGuestState(guest_VSR37);
141066d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj   case  6: return offsetofPPCGuestState(guest_VSR38);
141166d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj   case  7: return offsetofPPCGuestState(guest_VSR39);
141266d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj   case  8: return offsetofPPCGuestState(guest_VSR40);
141366d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj   case  9: return offsetofPPCGuestState(guest_VSR41);
141466d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj   case 10: return offsetofPPCGuestState(guest_VSR42);
141566d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj   case 11: return offsetofPPCGuestState(guest_VSR43);
141666d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj   case 12: return offsetofPPCGuestState(guest_VSR44);
141766d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj   case 13: return offsetofPPCGuestState(guest_VSR45);
141866d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj   case 14: return offsetofPPCGuestState(guest_VSR46);
141966d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj   case 15: return offsetofPPCGuestState(guest_VSR47);
142066d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj   case 16: return offsetofPPCGuestState(guest_VSR48);
142166d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj   case 17: return offsetofPPCGuestState(guest_VSR49);
142266d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj   case 18: return offsetofPPCGuestState(guest_VSR50);
142366d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj   case 19: return offsetofPPCGuestState(guest_VSR51);
142466d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj   case 20: return offsetofPPCGuestState(guest_VSR52);
142566d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj   case 21: return offsetofPPCGuestState(guest_VSR53);
142666d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj   case 22: return offsetofPPCGuestState(guest_VSR54);
142766d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj   case 23: return offsetofPPCGuestState(guest_VSR55);
142866d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj   case 24: return offsetofPPCGuestState(guest_VSR56);
142966d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj   case 25: return offsetofPPCGuestState(guest_VSR57);
143066d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj   case 26: return offsetofPPCGuestState(guest_VSR58);
143166d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj   case 27: return offsetofPPCGuestState(guest_VSR59);
143266d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj   case 28: return offsetofPPCGuestState(guest_VSR60);
143366d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj   case 29: return offsetofPPCGuestState(guest_VSR61);
143466d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj   case 30: return offsetofPPCGuestState(guest_VSR62);
143566d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj   case 31: return offsetofPPCGuestState(guest_VSR63);
14365b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion   default: break;
14375b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion   }
14385b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion   vpanic("vextorGuestRegOffset(ppc)"); /*notreached*/
1439a982c0503d8c0c6069ae453bfe70657bd2c134aecerion}
1440a982c0503d8c0c6069ae453bfe70657bd2c134aecerion
1441a982c0503d8c0c6069ae453bfe70657bd2c134aecerionstatic IRExpr* getVReg ( UInt archreg )
1442a982c0503d8c0c6069ae453bfe70657bd2c134aecerion{
1443a982c0503d8c0c6069ae453bfe70657bd2c134aecerion   vassert(archreg < 32);
1444a982c0503d8c0c6069ae453bfe70657bd2c134aecerion   return IRExpr_Get( vectorGuestRegOffset(archreg), Ity_V128 );
1445a982c0503d8c0c6069ae453bfe70657bd2c134aecerion}
1446a982c0503d8c0c6069ae453bfe70657bd2c134aecerion
1447a982c0503d8c0c6069ae453bfe70657bd2c134aecerion/* Ditto, but write to a reg instead. */
1448a982c0503d8c0c6069ae453bfe70657bd2c134aecerionstatic void putVReg ( UInt archreg, IRExpr* e )
1449a982c0503d8c0c6069ae453bfe70657bd2c134aecerion{
1450a982c0503d8c0c6069ae453bfe70657bd2c134aecerion   vassert(archreg < 32);
1451dd40fdf58cc8a6fe9466c4f00bdfc9fe9bf00449sewardj   vassert(typeOfIRExpr(irsb->tyenv, e) == Ity_V128);
1452a982c0503d8c0c6069ae453bfe70657bd2c134aecerion   stmt( IRStmt_Put(vectorGuestRegOffset(archreg), e) );
1453a982c0503d8c0c6069ae453bfe70657bd2c134aecerion}
1454a982c0503d8c0c6069ae453bfe70657bd2c134aecerion
145566d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj/* Get contents of VSX guest register */
145666d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardjstatic IRExpr* getVSReg ( UInt archreg )
145766d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj{
145866d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj   vassert(archreg < 64);
145966d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj   return IRExpr_Get( vsxGuestRegOffset(archreg), Ity_V128 );
146066d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj}
146166d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj
146266d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj/* Ditto, but write to a VSX reg instead. */
146366d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardjstatic void putVSReg ( UInt archreg, IRExpr* e )
146466d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj{
146566d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj   vassert(archreg < 64);
146666d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj   vassert(typeOfIRExpr(irsb->tyenv, e) == Ity_V128);
146766d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj   stmt( IRStmt_Put(vsxGuestRegOffset(archreg), e) );
146866d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj}
146966d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj
147066d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj
1471b51f0f4f33256638ed953156a2635aa739b232f1sewardjstatic Int guestCR321offset ( UInt cr )
1472896a1373cfdbaa25f4ab73ed4f27554016defecccerion{
14735b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion   switch (cr) {
14745b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion   case 0: return offsetofPPCGuestState(guest_CR0_321 );
14755b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion   case 1: return offsetofPPCGuestState(guest_CR1_321 );
14765b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion   case 2: return offsetofPPCGuestState(guest_CR2_321 );
14775b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion   case 3: return offsetofPPCGuestState(guest_CR3_321 );
14785b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion   case 4: return offsetofPPCGuestState(guest_CR4_321 );
14795b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion   case 5: return offsetofPPCGuestState(guest_CR5_321 );
14805b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion   case 6: return offsetofPPCGuestState(guest_CR6_321 );
14815b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion   case 7: return offsetofPPCGuestState(guest_CR7_321 );
14825b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion   default: vpanic("guestCR321offset(ppc)");
1483b51f0f4f33256638ed953156a2635aa739b232f1sewardj   }
1484b51f0f4f33256638ed953156a2635aa739b232f1sewardj}
1485896a1373cfdbaa25f4ab73ed4f27554016defecccerion
1486b51f0f4f33256638ed953156a2635aa739b232f1sewardjstatic Int guestCR0offset ( UInt cr )
1487896a1373cfdbaa25f4ab73ed4f27554016defecccerion{
14885b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion   switch (cr) {
14895b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion   case 0: return offsetofPPCGuestState(guest_CR0_0 );
14905b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion   case 1: return offsetofPPCGuestState(guest_CR1_0 );
14915b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion   case 2: return offsetofPPCGuestState(guest_CR2_0 );
14925b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion   case 3: return offsetofPPCGuestState(guest_CR3_0 );
14935b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion   case 4: return offsetofPPCGuestState(guest_CR4_0 );
14945b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion   case 5: return offsetofPPCGuestState(guest_CR5_0 );
14955b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion   case 6: return offsetofPPCGuestState(guest_CR6_0 );
14965b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion   case 7: return offsetofPPCGuestState(guest_CR7_0 );
14975b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion   default: vpanic("guestCR3offset(ppc)");
1498b51f0f4f33256638ed953156a2635aa739b232f1sewardj   }
1499896a1373cfdbaa25f4ab73ed4f27554016defecccerion}
1500896a1373cfdbaa25f4ab73ed4f27554016defecccerion
15017deaf9552b546b847528cf39b38898fb7742b5f5carlltypedef enum {
15027deaf9552b546b847528cf39b38898fb7742b5f5carll   _placeholder0,
15037deaf9552b546b847528cf39b38898fb7742b5f5carll   _placeholder1,
15047deaf9552b546b847528cf39b38898fb7742b5f5carll   _placeholder2,
15057deaf9552b546b847528cf39b38898fb7742b5f5carll   BYTE,
15067deaf9552b546b847528cf39b38898fb7742b5f5carll   HWORD,
15077deaf9552b546b847528cf39b38898fb7742b5f5carll   WORD,
15087deaf9552b546b847528cf39b38898fb7742b5f5carll   DWORD
15097deaf9552b546b847528cf39b38898fb7742b5f5carll} _popcount_data_type;
15107deaf9552b546b847528cf39b38898fb7742b5f5carll
151166d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj/* Generate an IR sequence to do a popcount operation on the supplied
1512e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj   IRTemp, and return a new IRTemp holding the result.  'ty' may be
1513e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj   Ity_I32 or Ity_I64 only. */
15147deaf9552b546b847528cf39b38898fb7742b5f5carllstatic IRTemp gen_POPCOUNT ( IRType ty, IRTemp src, _popcount_data_type data_type )
151566d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj{
15167deaf9552b546b847528cf39b38898fb7742b5f5carll  /* Do count across 2^data_type bits,
15177deaf9552b546b847528cf39b38898fb7742b5f5carll     byte:        data_type = 3
15187deaf9552b546b847528cf39b38898fb7742b5f5carll     half word:   data_type = 4
15197deaf9552b546b847528cf39b38898fb7742b5f5carll     word:        data_type = 5
15207deaf9552b546b847528cf39b38898fb7742b5f5carll     double word: data_type = 6  (not supported for 32-bit type)
15217deaf9552b546b847528cf39b38898fb7742b5f5carll    */
15227deaf9552b546b847528cf39b38898fb7742b5f5carll   Int shift[6];
15237deaf9552b546b847528cf39b38898fb7742b5f5carll   _popcount_data_type idx, i;
1524e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj   IRTemp mask[6];
152566d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj   IRTemp old = IRTemp_INVALID;
152666d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj   IRTemp nyu = IRTemp_INVALID;
152766d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj
1528e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj   vassert(ty == Ity_I64 || ty == Ity_I32);
1529e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj
1530e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj   if (ty == Ity_I32) {
1531738d9dddf788cd66fc04081f5fca872f38859813philippe
15327deaf9552b546b847528cf39b38898fb7742b5f5carll      for (idx = 0; idx < WORD; idx++) {
15337deaf9552b546b847528cf39b38898fb7742b5f5carll         mask[idx]  = newTemp(ty);
15347deaf9552b546b847528cf39b38898fb7742b5f5carll         shift[idx] = 1 << idx;
1535e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj      }
1536e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj      assign(mask[0], mkU32(0x55555555));
1537e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj      assign(mask[1], mkU32(0x33333333));
1538e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj      assign(mask[2], mkU32(0x0F0F0F0F));
1539e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj      assign(mask[3], mkU32(0x00FF00FF));
1540e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj      assign(mask[4], mkU32(0x0000FFFF));
1541e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj      old = src;
15427deaf9552b546b847528cf39b38898fb7742b5f5carll      for (i = 0; i < data_type; i++) {
1543e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj         nyu = newTemp(ty);
1544e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj         assign(nyu,
1545e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj                binop(Iop_Add32,
1546e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj                      binop(Iop_And32,
1547e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj                            mkexpr(old),
1548e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj                            mkexpr(mask[i])),
1549e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj                      binop(Iop_And32,
1550e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj                            binop(Iop_Shr32, mkexpr(old), mkU8(shift[i])),
1551e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj                            mkexpr(mask[i]))));
1552e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj         old = nyu;
1553e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj      }
1554e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj      return nyu;
1555e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj   }
15567deaf9552b546b847528cf39b38898fb7742b5f5carll
1557e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj// else, ty == Ity_I64
15587deaf9552b546b847528cf39b38898fb7742b5f5carll   vassert(mode64);
1559738d9dddf788cd66fc04081f5fca872f38859813philippe
15607deaf9552b546b847528cf39b38898fb7742b5f5carll   for (i = 0; i < DWORD; i++) {
156166d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj      mask[i] = newTemp( Ity_I64 );
156266d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj      shift[i] = 1 << i;
156366d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj   }
156466d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj   assign( mask[0], mkU64( 0x5555555555555555ULL ) );
156566d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj   assign( mask[1], mkU64( 0x3333333333333333ULL ) );
156666d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj   assign( mask[2], mkU64( 0x0F0F0F0F0F0F0F0FULL ) );
156766d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj   assign( mask[3], mkU64( 0x00FF00FF00FF00FFULL ) );
156866d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj   assign( mask[4], mkU64( 0x0000FFFF0000FFFFULL ) );
156966d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj   assign( mask[5], mkU64( 0x00000000FFFFFFFFULL ) );
157066d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj   old = src;
15717deaf9552b546b847528cf39b38898fb7742b5f5carll   for (i = 0; i < data_type; i++) {
157266d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj      nyu = newTemp( Ity_I64 );
157366d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj      assign( nyu,
157466d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj              binop( Iop_Add64,
157566d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj                     binop( Iop_And64, mkexpr( old ), mkexpr( mask[i] ) ),
157666d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj                     binop( Iop_And64,
157766d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj                            binop( Iop_Shr64, mkexpr( old ), mkU8( shift[i] ) ),
157866d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj                            mkexpr( mask[i] ) ) ) );
157966d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj      old = nyu;
158066d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj   }
158166d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj   return nyu;
158266d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj}
158366d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj
15847deaf9552b546b847528cf39b38898fb7742b5f5carll/* Special purpose population count function for
15857deaf9552b546b847528cf39b38898fb7742b5f5carll * vpopcntd in 32-bit mode.
15867deaf9552b546b847528cf39b38898fb7742b5f5carll */
15877deaf9552b546b847528cf39b38898fb7742b5f5carllstatic IRTemp gen_vpopcntd_mode32 ( IRTemp src1, IRTemp src2 )
15887deaf9552b546b847528cf39b38898fb7742b5f5carll{
15897deaf9552b546b847528cf39b38898fb7742b5f5carll   Int i, shift[6];
15907deaf9552b546b847528cf39b38898fb7742b5f5carll   IRTemp mask[6];
15917deaf9552b546b847528cf39b38898fb7742b5f5carll   IRTemp old = IRTemp_INVALID;
15927deaf9552b546b847528cf39b38898fb7742b5f5carll   IRTemp nyu1 = IRTemp_INVALID;
15937deaf9552b546b847528cf39b38898fb7742b5f5carll   IRTemp nyu2 = IRTemp_INVALID;
15947deaf9552b546b847528cf39b38898fb7742b5f5carll   IRTemp retval = newTemp(Ity_I64);
15957deaf9552b546b847528cf39b38898fb7742b5f5carll
15967deaf9552b546b847528cf39b38898fb7742b5f5carll   vassert(!mode64);
15977deaf9552b546b847528cf39b38898fb7742b5f5carll
15987deaf9552b546b847528cf39b38898fb7742b5f5carll   for (i = 0; i < WORD; i++) {
15997deaf9552b546b847528cf39b38898fb7742b5f5carll      mask[i]  = newTemp(Ity_I32);
16007deaf9552b546b847528cf39b38898fb7742b5f5carll      shift[i] = 1 << i;
16017deaf9552b546b847528cf39b38898fb7742b5f5carll   }
16027deaf9552b546b847528cf39b38898fb7742b5f5carll   assign(mask[0], mkU32(0x55555555));
16037deaf9552b546b847528cf39b38898fb7742b5f5carll   assign(mask[1], mkU32(0x33333333));
16047deaf9552b546b847528cf39b38898fb7742b5f5carll   assign(mask[2], mkU32(0x0F0F0F0F));
16057deaf9552b546b847528cf39b38898fb7742b5f5carll   assign(mask[3], mkU32(0x00FF00FF));
16067deaf9552b546b847528cf39b38898fb7742b5f5carll   assign(mask[4], mkU32(0x0000FFFF));
16077deaf9552b546b847528cf39b38898fb7742b5f5carll   old = src1;
16087deaf9552b546b847528cf39b38898fb7742b5f5carll   for (i = 0; i < WORD; i++) {
16097deaf9552b546b847528cf39b38898fb7742b5f5carll      nyu1 = newTemp(Ity_I32);
16107deaf9552b546b847528cf39b38898fb7742b5f5carll      assign(nyu1,
16117deaf9552b546b847528cf39b38898fb7742b5f5carll             binop(Iop_Add32,
16127deaf9552b546b847528cf39b38898fb7742b5f5carll                   binop(Iop_And32,
16137deaf9552b546b847528cf39b38898fb7742b5f5carll                         mkexpr(old),
16147deaf9552b546b847528cf39b38898fb7742b5f5carll                         mkexpr(mask[i])),
16157deaf9552b546b847528cf39b38898fb7742b5f5carll                   binop(Iop_And32,
16167deaf9552b546b847528cf39b38898fb7742b5f5carll                         binop(Iop_Shr32, mkexpr(old), mkU8(shift[i])),
16177deaf9552b546b847528cf39b38898fb7742b5f5carll                         mkexpr(mask[i]))));
16187deaf9552b546b847528cf39b38898fb7742b5f5carll      old = nyu1;
16197deaf9552b546b847528cf39b38898fb7742b5f5carll   }
16207deaf9552b546b847528cf39b38898fb7742b5f5carll
16217deaf9552b546b847528cf39b38898fb7742b5f5carll   old = src2;
16227deaf9552b546b847528cf39b38898fb7742b5f5carll   for (i = 0; i < WORD; i++) {
16237deaf9552b546b847528cf39b38898fb7742b5f5carll      nyu2 = newTemp(Ity_I32);
16247deaf9552b546b847528cf39b38898fb7742b5f5carll      assign(nyu2,
16257deaf9552b546b847528cf39b38898fb7742b5f5carll             binop(Iop_Add32,
16267deaf9552b546b847528cf39b38898fb7742b5f5carll                   binop(Iop_And32,
16277deaf9552b546b847528cf39b38898fb7742b5f5carll                         mkexpr(old),
16287deaf9552b546b847528cf39b38898fb7742b5f5carll                         mkexpr(mask[i])),
16297deaf9552b546b847528cf39b38898fb7742b5f5carll                   binop(Iop_And32,
16307deaf9552b546b847528cf39b38898fb7742b5f5carll                         binop(Iop_Shr32, mkexpr(old), mkU8(shift[i])),
16317deaf9552b546b847528cf39b38898fb7742b5f5carll                         mkexpr(mask[i]))));
16327deaf9552b546b847528cf39b38898fb7742b5f5carll      old = nyu2;
16337deaf9552b546b847528cf39b38898fb7742b5f5carll   }
16347deaf9552b546b847528cf39b38898fb7742b5f5carll   assign(retval, unop(Iop_32Uto64, binop(Iop_Add32, mkexpr(nyu1), mkexpr(nyu2))));
16357deaf9552b546b847528cf39b38898fb7742b5f5carll   return retval;
16367deaf9552b546b847528cf39b38898fb7742b5f5carll}
16377deaf9552b546b847528cf39b38898fb7742b5f5carll
163866d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj
163907b07a966a2fdbcf621251a0c1a8ab84807fb120cerion// ROTL(src32/64, rot_amt5/6)
1640d953ebb9b04cbad6891676df597bf0c542b1ec89cerionstatic IRExpr* /* :: Ity_I32/64 */ ROTL ( IRExpr* src,
1641d953ebb9b04cbad6891676df597bf0c542b1ec89cerion                                          IRExpr* rot_amt )
1642896a1373cfdbaa25f4ab73ed4f27554016defecccerion{
1643d953ebb9b04cbad6891676df597bf0c542b1ec89cerion   IRExpr *mask, *rot;
1644dd40fdf58cc8a6fe9466c4f00bdfc9fe9bf00449sewardj   vassert(typeOfIRExpr(irsb->tyenv,rot_amt) == Ity_I8);
1645d953ebb9b04cbad6891676df597bf0c542b1ec89cerion
1646dd40fdf58cc8a6fe9466c4f00bdfc9fe9bf00449sewardj   if (typeOfIRExpr(irsb->tyenv,src) == Ity_I64) {
1647d953ebb9b04cbad6891676df597bf0c542b1ec89cerion      // rot = (src << rot_amt) | (src >> (64-rot_amt))
1648d953ebb9b04cbad6891676df597bf0c542b1ec89cerion      mask = binop(Iop_And8, rot_amt, mkU8(63));
1649d953ebb9b04cbad6891676df597bf0c542b1ec89cerion      rot  = binop(Iop_Or64,
1650d953ebb9b04cbad6891676df597bf0c542b1ec89cerion                binop(Iop_Shl64, src, mask),
1651d953ebb9b04cbad6891676df597bf0c542b1ec89cerion                binop(Iop_Shr64, src, binop(Iop_Sub8, mkU8(64), mask)));
1652d953ebb9b04cbad6891676df597bf0c542b1ec89cerion   } else {
1653d953ebb9b04cbad6891676df597bf0c542b1ec89cerion      // rot = (src << rot_amt) | (src >> (32-rot_amt))
1654f0de28cf1a762b0d6f74c93d3532c89a230673bbcerion      mask = binop(Iop_And8, rot_amt, mkU8(31));
1655d953ebb9b04cbad6891676df597bf0c542b1ec89cerion      rot  = binop(Iop_Or32,
1656d953ebb9b04cbad6891676df597bf0c542b1ec89cerion                binop(Iop_Shl32, src, mask),
1657d953ebb9b04cbad6891676df597bf0c542b1ec89cerion                binop(Iop_Shr32, src, binop(Iop_Sub8, mkU8(32), mask)));
16582831b00c4950d6c2b061def05fd67528fe132ececerion   }
165999dd03e04a6914d90d5fee727d61d76905334becflorian   /* Note: the ITE not merely an optimisation; it's needed
1660f0de28cf1a762b0d6f74c93d3532c89a230673bbcerion      because otherwise the Shr is a shift by the word size when
1661d953ebb9b04cbad6891676df597bf0c542b1ec89cerion      mask denotes zero.  For rotates by immediates, a lot of
1662c965953e12be58c7d01cd6d024d6f42326b2b797sewardj      this junk gets folded out. */
166399dd03e04a6914d90d5fee727d61d76905334becflorian   return IRExpr_ITE( binop(Iop_CmpNE8, mask, mkU8(0)),
166499dd03e04a6914d90d5fee727d61d76905334becflorian                      /* non-zero rotate */ rot,
166599dd03e04a6914d90d5fee727d61d76905334becflorian                      /*     zero rotate */ src);
1666d953ebb9b04cbad6891676df597bf0c542b1ec89cerion}
1667d953ebb9b04cbad6891676df597bf0c542b1ec89cerion
1668d953ebb9b04cbad6891676df597bf0c542b1ec89cerion/* Standard effective address calc: (rA + rB) */
1669d953ebb9b04cbad6891676df597bf0c542b1ec89cerionstatic IRExpr* ea_rA_idxd ( UInt rA, UInt rB )
1670d953ebb9b04cbad6891676df597bf0c542b1ec89cerion{
1671d953ebb9b04cbad6891676df597bf0c542b1ec89cerion   IRType ty = mode64 ? Ity_I64 : Ity_I32;
1672d953ebb9b04cbad6891676df597bf0c542b1ec89cerion   vassert(rA < 32);
1673d953ebb9b04cbad6891676df597bf0c542b1ec89cerion   vassert(rB < 32);
16742831b00c4950d6c2b061def05fd67528fe132ececerion   return binop(mkSzOp(ty, Iop_Add8), getIReg(rA), getIReg(rB));
1675d953ebb9b04cbad6891676df597bf0c542b1ec89cerion}
1676d953ebb9b04cbad6891676df597bf0c542b1ec89cerion
1677d953ebb9b04cbad6891676df597bf0c542b1ec89cerion/* Standard effective address calc: (rA + simm) */
1678d953ebb9b04cbad6891676df597bf0c542b1ec89cerionstatic IRExpr* ea_rA_simm ( UInt rA, UInt simm16 )
1679d953ebb9b04cbad6891676df597bf0c542b1ec89cerion{
1680d953ebb9b04cbad6891676df597bf0c542b1ec89cerion   IRType ty = mode64 ? Ity_I64 : Ity_I32;
1681d953ebb9b04cbad6891676df597bf0c542b1ec89cerion   vassert(rA < 32);
16822831b00c4950d6c2b061def05fd67528fe132ececerion   return binop(mkSzOp(ty, Iop_Add8), getIReg(rA),
16832831b00c4950d6c2b061def05fd67528fe132ececerion                mkSzExtendS16(ty, simm16));
168445b70ff2e85482063232b4e7c6f47be2ddeeb5d9cerion}
1685896a1373cfdbaa25f4ab73ed4f27554016defecccerion
1686d953ebb9b04cbad6891676df597bf0c542b1ec89cerion/* Standard effective address calc: (rA|0) */
1687d953ebb9b04cbad6891676df597bf0c542b1ec89cerionstatic IRExpr* ea_rAor0 ( UInt rA )
168887e651f40360a8f1c9418710e79c482028759f8csewardj{
1689d953ebb9b04cbad6891676df597bf0c542b1ec89cerion   IRType ty = mode64 ? Ity_I64 : Ity_I32;
1690d953ebb9b04cbad6891676df597bf0c542b1ec89cerion   vassert(rA < 32);
169187e651f40360a8f1c9418710e79c482028759f8csewardj   if (rA == 0) {
16922831b00c4950d6c2b061def05fd67528fe132ececerion      return mkSzImm(ty, 0);
169387e651f40360a8f1c9418710e79c482028759f8csewardj   } else {
1694d953ebb9b04cbad6891676df597bf0c542b1ec89cerion      return getIReg(rA);
169587e651f40360a8f1c9418710e79c482028759f8csewardj   }
169687e651f40360a8f1c9418710e79c482028759f8csewardj}
169787e651f40360a8f1c9418710e79c482028759f8csewardj
1698d953ebb9b04cbad6891676df597bf0c542b1ec89cerion/* Standard effective address calc: (rA|0) + rB */
1699d953ebb9b04cbad6891676df597bf0c542b1ec89cerionstatic IRExpr* ea_rAor0_idxd ( UInt rA, UInt rB )
1700d953ebb9b04cbad6891676df597bf0c542b1ec89cerion{
1701d953ebb9b04cbad6891676df597bf0c542b1ec89cerion   vassert(rA < 32);
1702d953ebb9b04cbad6891676df597bf0c542b1ec89cerion   vassert(rB < 32);
1703d953ebb9b04cbad6891676df597bf0c542b1ec89cerion   return (rA == 0) ? getIReg(rB) : ea_rA_idxd( rA, rB );
1704d953ebb9b04cbad6891676df597bf0c542b1ec89cerion}
1705d953ebb9b04cbad6891676df597bf0c542b1ec89cerion
1706d953ebb9b04cbad6891676df597bf0c542b1ec89cerion/* Standard effective address calc: (rA|0) + simm16 */
1707d953ebb9b04cbad6891676df597bf0c542b1ec89cerionstatic IRExpr* ea_rAor0_simm ( UInt rA, UInt simm16 )
170887e651f40360a8f1c9418710e79c482028759f8csewardj{
1709d953ebb9b04cbad6891676df597bf0c542b1ec89cerion   IRType ty = mode64 ? Ity_I64 : Ity_I32;
1710d953ebb9b04cbad6891676df597bf0c542b1ec89cerion   vassert(rA < 32);
171187e651f40360a8f1c9418710e79c482028759f8csewardj   if (rA == 0) {
17122831b00c4950d6c2b061def05fd67528fe132ececerion      return mkSzExtendS16(ty, simm16);
171387e651f40360a8f1c9418710e79c482028759f8csewardj   } else {
1714d953ebb9b04cbad6891676df597bf0c542b1ec89cerion      return ea_rA_simm( rA, simm16 );
1715d953ebb9b04cbad6891676df597bf0c542b1ec89cerion   }
1716d953ebb9b04cbad6891676df597bf0c542b1ec89cerion}
1717d953ebb9b04cbad6891676df597bf0c542b1ec89cerion
1718d953ebb9b04cbad6891676df597bf0c542b1ec89cerion
1719d953ebb9b04cbad6891676df597bf0c542b1ec89cerion/* Align effective address */
1720d953ebb9b04cbad6891676df597bf0c542b1ec89cerionstatic IRExpr* addr_align( IRExpr* addr, UChar align )
1721d953ebb9b04cbad6891676df597bf0c542b1ec89cerion{
1722d953ebb9b04cbad6891676df597bf0c542b1ec89cerion   IRType ty = mode64 ? Ity_I64 : Ity_I32;
172359d2075ac6ff846cd1ad83391c42c84bcf25ad39florian   ULong mask;
1724d953ebb9b04cbad6891676df597bf0c542b1ec89cerion   switch (align) {
17252831b00c4950d6c2b061def05fd67528fe132ececerion   case 1:  return addr;                    // byte aligned
172659d2075ac6ff846cd1ad83391c42c84bcf25ad39florian   case 2:  mask = ~0ULL << 1; break;       // half-word aligned
172759d2075ac6ff846cd1ad83391c42c84bcf25ad39florian   case 4:  mask = ~0ULL << 2; break;       // word aligned
172859d2075ac6ff846cd1ad83391c42c84bcf25ad39florian   case 16: mask = ~0ULL << 4; break;       // quad-word aligned
1729d953ebb9b04cbad6891676df597bf0c542b1ec89cerion   default:
1730d953ebb9b04cbad6891676df597bf0c542b1ec89cerion      vex_printf("addr_align: align = %u\n", align);
17315b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion      vpanic("addr_align(ppc)");
173287e651f40360a8f1c9418710e79c482028759f8csewardj   }
1733d953ebb9b04cbad6891676df597bf0c542b1ec89cerion
1734dd40fdf58cc8a6fe9466c4f00bdfc9fe9bf00449sewardj   vassert(typeOfIRExpr(irsb->tyenv,addr) == ty);
1735fb197c49c89d04987ef801657b2bedc4050e1539cerion   return binop( mkSzOp(ty, Iop_And8), addr, mkSzImm(ty, mask) );
173687e651f40360a8f1c9418710e79c482028759f8csewardj}
173787e651f40360a8f1c9418710e79c482028759f8csewardj
1738896a1373cfdbaa25f4ab73ed4f27554016defecccerion
1739e9d8a26b690c2561ac54ab0cd6ad83ecbadcbe76sewardj/* Exit the trace if ADDR (intended to be a guest memory address) is
1740e9d8a26b690c2561ac54ab0cd6ad83ecbadcbe76sewardj   not ALIGN-aligned, generating a request for a SIGBUS followed by a
1741e9d8a26b690c2561ac54ab0cd6ad83ecbadcbe76sewardj   restart of the current insn. */
1742e9d8a26b690c2561ac54ab0cd6ad83ecbadcbe76sewardjstatic void gen_SIGBUS_if_misaligned ( IRTemp addr, UChar align )
1743e9d8a26b690c2561ac54ab0cd6ad83ecbadcbe76sewardj{
1744d826889bd512ded2fbbc4781c595ecf0513f46f6carll   vassert(align == 2 || align == 4 || align == 8 || align == 16);
1745e9d8a26b690c2561ac54ab0cd6ad83ecbadcbe76sewardj   if (mode64) {
1746e9d8a26b690c2561ac54ab0cd6ad83ecbadcbe76sewardj      vassert(typeOfIRTemp(irsb->tyenv, addr) == Ity_I64);
1747e9d8a26b690c2561ac54ab0cd6ad83ecbadcbe76sewardj      stmt(
1748e9d8a26b690c2561ac54ab0cd6ad83ecbadcbe76sewardj         IRStmt_Exit(
1749e9d8a26b690c2561ac54ab0cd6ad83ecbadcbe76sewardj            binop(Iop_CmpNE64,
1750e9d8a26b690c2561ac54ab0cd6ad83ecbadcbe76sewardj                  binop(Iop_And64, mkexpr(addr), mkU64(align-1)),
1751e9d8a26b690c2561ac54ab0cd6ad83ecbadcbe76sewardj                  mkU64(0)),
1752e9d8a26b690c2561ac54ab0cd6ad83ecbadcbe76sewardj            Ijk_SigBUS,
17533dee849ec7c38746749065e67dc53b75daa7617dsewardj            IRConst_U64( guest_CIA_curr_instr ), OFFB_CIA
1754e9d8a26b690c2561ac54ab0cd6ad83ecbadcbe76sewardj         )
1755e9d8a26b690c2561ac54ab0cd6ad83ecbadcbe76sewardj      );
1756e9d8a26b690c2561ac54ab0cd6ad83ecbadcbe76sewardj   } else {
1757e9d8a26b690c2561ac54ab0cd6ad83ecbadcbe76sewardj      vassert(typeOfIRTemp(irsb->tyenv, addr) == Ity_I32);
1758e9d8a26b690c2561ac54ab0cd6ad83ecbadcbe76sewardj      stmt(
1759e9d8a26b690c2561ac54ab0cd6ad83ecbadcbe76sewardj         IRStmt_Exit(
1760e9d8a26b690c2561ac54ab0cd6ad83ecbadcbe76sewardj            binop(Iop_CmpNE32,
1761e9d8a26b690c2561ac54ab0cd6ad83ecbadcbe76sewardj                  binop(Iop_And32, mkexpr(addr), mkU32(align-1)),
1762e9d8a26b690c2561ac54ab0cd6ad83ecbadcbe76sewardj                  mkU32(0)),
1763e9d8a26b690c2561ac54ab0cd6ad83ecbadcbe76sewardj            Ijk_SigBUS,
17643dee849ec7c38746749065e67dc53b75daa7617dsewardj            IRConst_U32( guest_CIA_curr_instr ), OFFB_CIA
1765e9d8a26b690c2561ac54ab0cd6ad83ecbadcbe76sewardj         )
1766e9d8a26b690c2561ac54ab0cd6ad83ecbadcbe76sewardj      );
1767e9d8a26b690c2561ac54ab0cd6ad83ecbadcbe76sewardj   }
1768e9d8a26b690c2561ac54ab0cd6ad83ecbadcbe76sewardj}
1769e9d8a26b690c2561ac54ab0cd6ad83ecbadcbe76sewardj
1770e9d8a26b690c2561ac54ab0cd6ad83ecbadcbe76sewardj
1771aca070a5b3418a6a9b01e3c57a7eb0fbb5050908sewardj/* Generate AbiHints which mark points at which the ELF or PowerOpen
1772aca070a5b3418a6a9b01e3c57a7eb0fbb5050908sewardj   ABIs say that the stack red zone (viz, -N(r1) .. -1(r1), for some
1773aca070a5b3418a6a9b01e3c57a7eb0fbb5050908sewardj   N) becomes undefined.  That is at function calls and returns.  ELF
1774478646f54befaba01cbceb40fd5e46cdf562fdb5sewardj   ppc32 doesn't have this "feature" (how fortunate for it).  nia is
1775478646f54befaba01cbceb40fd5e46cdf562fdb5sewardj   the address of the next instruction to be executed.
1776cf8986c47a4c8c810566bb5b7b3da7a16a17dfe2sewardj*/
1777cacba8e675988fbf21b08feea1f317a9c896c053florianstatic void make_redzone_AbiHint ( const VexAbiInfo* vbi,
177855085f8680acc89d727e321f3b34cae1a8c4093aflorian                                   IRTemp nia, const HChar* who )
1779cf8986c47a4c8c810566bb5b7b3da7a16a17dfe2sewardj{
1780dd40fdf58cc8a6fe9466c4f00bdfc9fe9bf00449sewardj   Int szB = vbi->guest_stack_redzone_size;
1781cf8986c47a4c8c810566bb5b7b3da7a16a17dfe2sewardj   if (0) vex_printf("AbiHint: %s\n", who);
1782aca070a5b3418a6a9b01e3c57a7eb0fbb5050908sewardj   vassert(szB >= 0);
1783aca070a5b3418a6a9b01e3c57a7eb0fbb5050908sewardj   if (szB > 0) {
1784478646f54befaba01cbceb40fd5e46cdf562fdb5sewardj      if (mode64) {
1785478646f54befaba01cbceb40fd5e46cdf562fdb5sewardj         vassert(typeOfIRTemp(irsb->tyenv, nia) == Ity_I64);
1786aca070a5b3418a6a9b01e3c57a7eb0fbb5050908sewardj         stmt( IRStmt_AbiHint(
1787aca070a5b3418a6a9b01e3c57a7eb0fbb5050908sewardj                  binop(Iop_Sub64, getIReg(1), mkU64(szB)),
1788478646f54befaba01cbceb40fd5e46cdf562fdb5sewardj                  szB,
1789478646f54befaba01cbceb40fd5e46cdf562fdb5sewardj                  mkexpr(nia)
1790aca070a5b3418a6a9b01e3c57a7eb0fbb5050908sewardj         ));
1791478646f54befaba01cbceb40fd5e46cdf562fdb5sewardj      } else {
1792478646f54befaba01cbceb40fd5e46cdf562fdb5sewardj         vassert(typeOfIRTemp(irsb->tyenv, nia) == Ity_I32);
1793aca070a5b3418a6a9b01e3c57a7eb0fbb5050908sewardj         stmt( IRStmt_AbiHint(
1794aca070a5b3418a6a9b01e3c57a7eb0fbb5050908sewardj                  binop(Iop_Sub32, getIReg(1), mkU32(szB)),
1795478646f54befaba01cbceb40fd5e46cdf562fdb5sewardj                  szB,
1796478646f54befaba01cbceb40fd5e46cdf562fdb5sewardj                  mkexpr(nia)
1797aca070a5b3418a6a9b01e3c57a7eb0fbb5050908sewardj         ));
1798478646f54befaba01cbceb40fd5e46cdf562fdb5sewardj      }
1799aca070a5b3418a6a9b01e3c57a7eb0fbb5050908sewardj   }
1800cf8986c47a4c8c810566bb5b7b3da7a16a17dfe2sewardj}
1801cf8986c47a4c8c810566bb5b7b3da7a16a17dfe2sewardj
1802cf8986c47a4c8c810566bb5b7b3da7a16a17dfe2sewardj
1803b51f0f4f33256638ed953156a2635aa739b232f1sewardj/*------------------------------------------------------------*/
1804b51f0f4f33256638ed953156a2635aa739b232f1sewardj/*--- Helpers for condition codes.                         ---*/
1805b51f0f4f33256638ed953156a2635aa739b232f1sewardj/*------------------------------------------------------------*/
1806b51f0f4f33256638ed953156a2635aa739b232f1sewardj
1807b51f0f4f33256638ed953156a2635aa739b232f1sewardj/* Condition register layout.
1808896a1373cfdbaa25f4ab73ed4f27554016defecccerion
1809b51f0f4f33256638ed953156a2635aa739b232f1sewardj   In the hardware, CR is laid out like this.  The leftmost end is the
1810b51f0f4f33256638ed953156a2635aa739b232f1sewardj   most significant bit in the register; however the IBM documentation
1811b51f0f4f33256638ed953156a2635aa739b232f1sewardj   numbers the bits backwards for some reason.
1812896a1373cfdbaa25f4ab73ed4f27554016defecccerion
1813b51f0f4f33256638ed953156a2635aa739b232f1sewardj   CR0      CR1    ..........   CR6       CR7
1814b51f0f4f33256638ed953156a2635aa739b232f1sewardj   0 .. 3   .......................  28 .. 31    (IBM bit numbering)
1815b51f0f4f33256638ed953156a2635aa739b232f1sewardj   31  28                             3    0     (normal bit numbering)
1816896a1373cfdbaa25f4ab73ed4f27554016defecccerion
1817edf7fc572e2decb93e9143961e8739c8fe18899dcerion   Each CR field is 4 bits:  [<,>,==,SO]
1818896a1373cfdbaa25f4ab73ed4f27554016defecccerion
1819edf7fc572e2decb93e9143961e8739c8fe18899dcerion   Hence in IBM's notation, BI=0 is CR7[SO], BI=1 is CR7[==], etc.
1820b51f0f4f33256638ed953156a2635aa739b232f1sewardj
1821b51f0f4f33256638ed953156a2635aa739b232f1sewardj   Indexing from BI to guest state:
1822b51f0f4f33256638ed953156a2635aa739b232f1sewardj
1823b51f0f4f33256638ed953156a2635aa739b232f1sewardj     let    n = BI / 4
1824b51f0f4f33256638ed953156a2635aa739b232f1sewardj          off = BI % 4
1825b51f0f4f33256638ed953156a2635aa739b232f1sewardj     this references CR n:
1826b51f0f4f33256638ed953156a2635aa739b232f1sewardj
1827edf7fc572e2decb93e9143961e8739c8fe18899dcerion        off==0   ->  guest_CRn_321 >> 3
1828edf7fc572e2decb93e9143961e8739c8fe18899dcerion        off==1   ->  guest_CRn_321 >> 2
1829edf7fc572e2decb93e9143961e8739c8fe18899dcerion        off==2   ->  guest_CRn_321 >> 1
1830b51f0f4f33256638ed953156a2635aa739b232f1sewardj        off==3   ->  guest_CRn_SO
1831b51f0f4f33256638ed953156a2635aa739b232f1sewardj
1832b51f0f4f33256638ed953156a2635aa739b232f1sewardj   Bear in mind the only significant bit in guest_CRn_SO is bit 0
1833edf7fc572e2decb93e9143961e8739c8fe18899dcerion   (normal notation) and in guest_CRn_321 the significant bits are
1834b51f0f4f33256638ed953156a2635aa739b232f1sewardj   3, 2 and 1 (normal notation).
1835b51f0f4f33256638ed953156a2635aa739b232f1sewardj*/
1836edf7fc572e2decb93e9143961e8739c8fe18899dcerion
1837edf7fc572e2decb93e9143961e8739c8fe18899dcerionstatic void putCR321 ( UInt cr, IRExpr* e )
1838edf7fc572e2decb93e9143961e8739c8fe18899dcerion{
1839edf7fc572e2decb93e9143961e8739c8fe18899dcerion   vassert(cr < 8);
1840dd40fdf58cc8a6fe9466c4f00bdfc9fe9bf00449sewardj   vassert(typeOfIRExpr(irsb->tyenv, e) == Ity_I8);
1841edf7fc572e2decb93e9143961e8739c8fe18899dcerion   stmt( IRStmt_Put(guestCR321offset(cr), e) );
1842edf7fc572e2decb93e9143961e8739c8fe18899dcerion}
1843edf7fc572e2decb93e9143961e8739c8fe18899dcerion
1844edf7fc572e2decb93e9143961e8739c8fe18899dcerionstatic void putCR0 ( UInt cr, IRExpr* e )
1845edf7fc572e2decb93e9143961e8739c8fe18899dcerion{
1846edf7fc572e2decb93e9143961e8739c8fe18899dcerion   vassert(cr < 8);
1847dd40fdf58cc8a6fe9466c4f00bdfc9fe9bf00449sewardj   vassert(typeOfIRExpr(irsb->tyenv, e) == Ity_I8);
1848edf7fc572e2decb93e9143961e8739c8fe18899dcerion   stmt( IRStmt_Put(guestCR0offset(cr), e) );
1849edf7fc572e2decb93e9143961e8739c8fe18899dcerion}
1850edf7fc572e2decb93e9143961e8739c8fe18899dcerion
1851edf7fc572e2decb93e9143961e8739c8fe18899dcerionstatic IRExpr* /* :: Ity_I8 */ getCR0 ( UInt cr )
1852edf7fc572e2decb93e9143961e8739c8fe18899dcerion{
1853edf7fc572e2decb93e9143961e8739c8fe18899dcerion   vassert(cr < 8);
1854edf7fc572e2decb93e9143961e8739c8fe18899dcerion   return IRExpr_Get(guestCR0offset(cr), Ity_I8);
1855edf7fc572e2decb93e9143961e8739c8fe18899dcerion}
1856edf7fc572e2decb93e9143961e8739c8fe18899dcerion
1857edf7fc572e2decb93e9143961e8739c8fe18899dcerionstatic IRExpr* /* :: Ity_I8 */ getCR321 ( UInt cr )
1858edf7fc572e2decb93e9143961e8739c8fe18899dcerion{
1859edf7fc572e2decb93e9143961e8739c8fe18899dcerion   vassert(cr < 8);
1860edf7fc572e2decb93e9143961e8739c8fe18899dcerion   return IRExpr_Get(guestCR321offset(cr), Ity_I8);
1861edf7fc572e2decb93e9143961e8739c8fe18899dcerion}
1862edf7fc572e2decb93e9143961e8739c8fe18899dcerion
1863b51f0f4f33256638ed953156a2635aa739b232f1sewardj/* Fetch the specified CR bit (as per IBM/hardware notation) and
1864b51f0f4f33256638ed953156a2635aa739b232f1sewardj   return it at the bottom of an I32; the top 31 bits are guaranteed
1865b51f0f4f33256638ed953156a2635aa739b232f1sewardj   to be zero. */
1866b51f0f4f33256638ed953156a2635aa739b232f1sewardjstatic IRExpr* /* :: Ity_I32 */ getCRbit ( UInt bi )
1867896a1373cfdbaa25f4ab73ed4f27554016defecccerion{
1868b51f0f4f33256638ed953156a2635aa739b232f1sewardj   UInt n   = bi / 4;
1869b51f0f4f33256638ed953156a2635aa739b232f1sewardj   UInt off = bi % 4;
1870b51f0f4f33256638ed953156a2635aa739b232f1sewardj   vassert(bi < 32);
1871b51f0f4f33256638ed953156a2635aa739b232f1sewardj   if (off == 3) {
1872b51f0f4f33256638ed953156a2635aa739b232f1sewardj      /* Fetch the SO bit for this CR field */
1873b51f0f4f33256638ed953156a2635aa739b232f1sewardj      /* Note: And32 is redundant paranoia iff guest state only has 0
1874b51f0f4f33256638ed953156a2635aa739b232f1sewardj         or 1 in that slot. */
1875b51f0f4f33256638ed953156a2635aa739b232f1sewardj      return binop(Iop_And32, unop(Iop_8Uto32, getCR0(n)), mkU32(1));
1876b51f0f4f33256638ed953156a2635aa739b232f1sewardj   } else {
1877b51f0f4f33256638ed953156a2635aa739b232f1sewardj      /* Fetch the <, > or == bit for this CR field */
1878b51f0f4f33256638ed953156a2635aa739b232f1sewardj      return binop( Iop_And32,
1879b51f0f4f33256638ed953156a2635aa739b232f1sewardj                    binop( Iop_Shr32,
1880b51f0f4f33256638ed953156a2635aa739b232f1sewardj                           unop(Iop_8Uto32, getCR321(n)),
1881c7cd2142ff0172bd3702d0607426a8014d8842e5sewardj                           mkU8(toUChar(3-off)) ),
1882b51f0f4f33256638ed953156a2635aa739b232f1sewardj                    mkU32(1) );
1883b51f0f4f33256638ed953156a2635aa739b232f1sewardj   }
1884b51f0f4f33256638ed953156a2635aa739b232f1sewardj}
1885b51f0f4f33256638ed953156a2635aa739b232f1sewardj
1886b51f0f4f33256638ed953156a2635aa739b232f1sewardj/* Dually, write the least significant bit of BIT to the specified CR
1887b51f0f4f33256638ed953156a2635aa739b232f1sewardj   bit.  Indexing as per getCRbit. */
1888b51f0f4f33256638ed953156a2635aa739b232f1sewardjstatic void putCRbit ( UInt bi, IRExpr* bit )
1889b51f0f4f33256638ed953156a2635aa739b232f1sewardj{
1890197bd17d3ba8ac5204cd5c9ba5fab571249eb791sewardj   UInt    n, off;
1891b51f0f4f33256638ed953156a2635aa739b232f1sewardj   IRExpr* safe;
1892dd40fdf58cc8a6fe9466c4f00bdfc9fe9bf00449sewardj   vassert(typeOfIRExpr(irsb->tyenv,bit) == Ity_I32);
1893b51f0f4f33256638ed953156a2635aa739b232f1sewardj   safe = binop(Iop_And32, bit, mkU32(1));
1894197bd17d3ba8ac5204cd5c9ba5fab571249eb791sewardj   n   = bi / 4;
1895197bd17d3ba8ac5204cd5c9ba5fab571249eb791sewardj   off = bi % 4;
1896b51f0f4f33256638ed953156a2635aa739b232f1sewardj   vassert(bi < 32);
1897b51f0f4f33256638ed953156a2635aa739b232f1sewardj   if (off == 3) {
1898b51f0f4f33256638ed953156a2635aa739b232f1sewardj      /* This is the SO bit for this CR field */
1899b51f0f4f33256638ed953156a2635aa739b232f1sewardj      putCR0(n, unop(Iop_32to8, safe));
1900b51f0f4f33256638ed953156a2635aa739b232f1sewardj   } else {
1901b51f0f4f33256638ed953156a2635aa739b232f1sewardj      off = 3 - off;
1902b51f0f4f33256638ed953156a2635aa739b232f1sewardj      vassert(off == 1 || off == 2 || off == 3);
1903b51f0f4f33256638ed953156a2635aa739b232f1sewardj      putCR321(
1904b51f0f4f33256638ed953156a2635aa739b232f1sewardj         n,
1905b51f0f4f33256638ed953156a2635aa739b232f1sewardj         unop( Iop_32to8,
1906b51f0f4f33256638ed953156a2635aa739b232f1sewardj               binop( Iop_Or32,
1907b51f0f4f33256638ed953156a2635aa739b232f1sewardj                      /* old value with field masked out */
1908b51f0f4f33256638ed953156a2635aa739b232f1sewardj                      binop(Iop_And32, unop(Iop_8Uto32, getCR321(n)),
1909b51f0f4f33256638ed953156a2635aa739b232f1sewardj                                       mkU32(~(1 << off))),
1910b51f0f4f33256638ed953156a2635aa739b232f1sewardj                      /* new value in the right place */
1911c7cd2142ff0172bd3702d0607426a8014d8842e5sewardj                      binop(Iop_Shl32, safe, mkU8(toUChar(off)))
1912b51f0f4f33256638ed953156a2635aa739b232f1sewardj               )
1913b51f0f4f33256638ed953156a2635aa739b232f1sewardj         )
1914b51f0f4f33256638ed953156a2635aa739b232f1sewardj      );
1915b51f0f4f33256638ed953156a2635aa739b232f1sewardj   }
1916b51f0f4f33256638ed953156a2635aa739b232f1sewardj}
1917896a1373cfdbaa25f4ab73ed4f27554016defecccerion
1918b51f0f4f33256638ed953156a2635aa739b232f1sewardj/* Fetch the specified CR bit (as per IBM/hardware notation) and
1919b51f0f4f33256638ed953156a2635aa739b232f1sewardj   return it somewhere in an I32; it does not matter where, but
1920b51f0f4f33256638ed953156a2635aa739b232f1sewardj   whichever bit it is, all other bits are guaranteed to be zero.  In
1921b51f0f4f33256638ed953156a2635aa739b232f1sewardj   other words, the I32-typed expression will be zero if the bit is
1922b51f0f4f33256638ed953156a2635aa739b232f1sewardj   zero and nonzero if the bit is 1.  Write into *where the index
1923b51f0f4f33256638ed953156a2635aa739b232f1sewardj   of where the bit will be. */
192491ad5368eb6354ad4fabc86f2b2e641736997a38cerion
19255b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerionstatic
19265b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerionIRExpr* /* :: Ity_I32 */ getCRbit_anywhere ( UInt bi, Int* where )
1927b51f0f4f33256638ed953156a2635aa739b232f1sewardj{
1928b51f0f4f33256638ed953156a2635aa739b232f1sewardj   UInt n   = bi / 4;
1929b51f0f4f33256638ed953156a2635aa739b232f1sewardj   UInt off = bi % 4;
1930b51f0f4f33256638ed953156a2635aa739b232f1sewardj   vassert(bi < 32);
1931b51f0f4f33256638ed953156a2635aa739b232f1sewardj   if (off == 3) {
1932b51f0f4f33256638ed953156a2635aa739b232f1sewardj      /* Fetch the SO bit for this CR field */
1933b51f0f4f33256638ed953156a2635aa739b232f1sewardj      /* Note: And32 is redundant paranoia iff guest state only has 0
1934b51f0f4f33256638ed953156a2635aa739b232f1sewardj         or 1 in that slot. */
1935b51f0f4f33256638ed953156a2635aa739b232f1sewardj      *where = 0;
1936b51f0f4f33256638ed953156a2635aa739b232f1sewardj      return binop(Iop_And32, unop(Iop_8Uto32, getCR0(n)), mkU32(1));
1937b51f0f4f33256638ed953156a2635aa739b232f1sewardj   } else {
1938b51f0f4f33256638ed953156a2635aa739b232f1sewardj      /* Fetch the <, > or == bit for this CR field */
1939b51f0f4f33256638ed953156a2635aa739b232f1sewardj      *where = 3-off;
1940b51f0f4f33256638ed953156a2635aa739b232f1sewardj      return binop( Iop_And32,
1941b51f0f4f33256638ed953156a2635aa739b232f1sewardj                    unop(Iop_8Uto32, getCR321(n)),
1942b51f0f4f33256638ed953156a2635aa739b232f1sewardj                    mkU32(1 << (3-off)) );
1943b51f0f4f33256638ed953156a2635aa739b232f1sewardj   }
194491ad5368eb6354ad4fabc86f2b2e641736997a38cerion}
194591ad5368eb6354ad4fabc86f2b2e641736997a38cerion
1946edf7fc572e2decb93e9143961e8739c8fe18899dcerion/* Set the CR0 flags following an arithmetic operation.
1947edf7fc572e2decb93e9143961e8739c8fe18899dcerion   (Condition Register CR0 Field Definition, PPC32 p60)
1948edf7fc572e2decb93e9143961e8739c8fe18899dcerion*/
1949edf7fc572e2decb93e9143961e8739c8fe18899dcerionstatic IRExpr* getXER_SO ( void );
1950edf7fc572e2decb93e9143961e8739c8fe18899dcerionstatic void set_CR0 ( IRExpr* result )
1951edf7fc572e2decb93e9143961e8739c8fe18899dcerion{
1952dd40fdf58cc8a6fe9466c4f00bdfc9fe9bf00449sewardj   vassert(typeOfIRExpr(irsb->tyenv,result) == Ity_I32 ||
1953dd40fdf58cc8a6fe9466c4f00bdfc9fe9bf00449sewardj           typeOfIRExpr(irsb->tyenv,result) == Ity_I64);
1954d953ebb9b04cbad6891676df597bf0c542b1ec89cerion   if (mode64) {
1955d953ebb9b04cbad6891676df597bf0c542b1ec89cerion      putCR321( 0, unop(Iop_64to8,
19562831b00c4950d6c2b061def05fd67528fe132ececerion                        binop(Iop_CmpORD64S, result, mkU64(0))) );
1957d953ebb9b04cbad6891676df597bf0c542b1ec89cerion   } else {
1958d953ebb9b04cbad6891676df597bf0c542b1ec89cerion      putCR321( 0, unop(Iop_32to8,
1959d953ebb9b04cbad6891676df597bf0c542b1ec89cerion                        binop(Iop_CmpORD32S, result, mkU32(0))) );
1960d953ebb9b04cbad6891676df597bf0c542b1ec89cerion   }
1961edf7fc572e2decb93e9143961e8739c8fe18899dcerion   putCR0( 0, getXER_SO() );
1962edf7fc572e2decb93e9143961e8739c8fe18899dcerion}
1963edf7fc572e2decb93e9143961e8739c8fe18899dcerion
1964edf7fc572e2decb93e9143961e8739c8fe18899dcerion
19654aa412af1d8166cc11f39a6e721df49431d23618sewardj/* Set the CR6 flags following an AltiVec compare operation.
19664aa412af1d8166cc11f39a6e721df49431d23618sewardj * NOTE: This also works for VSX single-precision compares.
19674aa412af1d8166cc11f39a6e721df49431d23618sewardj * */
1968edf7fc572e2decb93e9143961e8739c8fe18899dcerionstatic void set_AV_CR6 ( IRExpr* result, Bool test_all_ones )
1969edf7fc572e2decb93e9143961e8739c8fe18899dcerion{
1970edf7fc572e2decb93e9143961e8739c8fe18899dcerion   /* CR6[0:3] = {all_ones, 0, all_zeros, 0}
1971edf7fc572e2decb93e9143961e8739c8fe18899dcerion      all_ones  = (v[0] && v[1] && v[2] && v[3])
1972edf7fc572e2decb93e9143961e8739c8fe18899dcerion      all_zeros = ~(v[0] || v[1] || v[2] || v[3])
1973edf7fc572e2decb93e9143961e8739c8fe18899dcerion   */
1974edf7fc572e2decb93e9143961e8739c8fe18899dcerion   IRTemp v0 = newTemp(Ity_V128);
1975edf7fc572e2decb93e9143961e8739c8fe18899dcerion   IRTemp v1 = newTemp(Ity_V128);
1976edf7fc572e2decb93e9143961e8739c8fe18899dcerion   IRTemp v2 = newTemp(Ity_V128);
1977edf7fc572e2decb93e9143961e8739c8fe18899dcerion   IRTemp v3 = newTemp(Ity_V128);
1978edf7fc572e2decb93e9143961e8739c8fe18899dcerion   IRTemp rOnes  = newTemp(Ity_I8);
1979edf7fc572e2decb93e9143961e8739c8fe18899dcerion   IRTemp rZeros = newTemp(Ity_I8);
1980edf7fc572e2decb93e9143961e8739c8fe18899dcerion
1981dd40fdf58cc8a6fe9466c4f00bdfc9fe9bf00449sewardj   vassert(typeOfIRExpr(irsb->tyenv,result) == Ity_V128);
1982edf7fc572e2decb93e9143961e8739c8fe18899dcerion
1983edf7fc572e2decb93e9143961e8739c8fe18899dcerion   assign( v0, result );
1984edf7fc572e2decb93e9143961e8739c8fe18899dcerion   assign( v1, binop(Iop_ShrV128, result, mkU8(32)) );
1985edf7fc572e2decb93e9143961e8739c8fe18899dcerion   assign( v2, binop(Iop_ShrV128, result, mkU8(64)) );
1986edf7fc572e2decb93e9143961e8739c8fe18899dcerion   assign( v3, binop(Iop_ShrV128, result, mkU8(96)) );
1987edf7fc572e2decb93e9143961e8739c8fe18899dcerion
1988edf7fc572e2decb93e9143961e8739c8fe18899dcerion   assign( rZeros, unop(Iop_1Uto8,
1989edf7fc572e2decb93e9143961e8739c8fe18899dcerion       binop(Iop_CmpEQ32, mkU32(0xFFFFFFFF),
1990edf7fc572e2decb93e9143961e8739c8fe18899dcerion             unop(Iop_Not32,
1991edf7fc572e2decb93e9143961e8739c8fe18899dcerion                  unop(Iop_V128to32,
1992edf7fc572e2decb93e9143961e8739c8fe18899dcerion                       binop(Iop_OrV128,
1993edf7fc572e2decb93e9143961e8739c8fe18899dcerion                             binop(Iop_OrV128, mkexpr(v0), mkexpr(v1)),
1994edf7fc572e2decb93e9143961e8739c8fe18899dcerion                             binop(Iop_OrV128, mkexpr(v2), mkexpr(v3))))
1995edf7fc572e2decb93e9143961e8739c8fe18899dcerion                  ))) );
1996edf7fc572e2decb93e9143961e8739c8fe18899dcerion
1997edf7fc572e2decb93e9143961e8739c8fe18899dcerion   if (test_all_ones) {
1998edf7fc572e2decb93e9143961e8739c8fe18899dcerion      assign( rOnes, unop(Iop_1Uto8,
1999edf7fc572e2decb93e9143961e8739c8fe18899dcerion         binop(Iop_CmpEQ32, mkU32(0xFFFFFFFF),
2000edf7fc572e2decb93e9143961e8739c8fe18899dcerion               unop(Iop_V128to32,
2001edf7fc572e2decb93e9143961e8739c8fe18899dcerion                    binop(Iop_AndV128,
2002edf7fc572e2decb93e9143961e8739c8fe18899dcerion                          binop(Iop_AndV128, mkexpr(v0), mkexpr(v1)),
20035b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion                          binop(Iop_AndV128, mkexpr(v2), mkexpr(v3)))
20045b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion                    ))) );
2005edf7fc572e2decb93e9143961e8739c8fe18899dcerion      putCR321( 6, binop(Iop_Or8,
2006edf7fc572e2decb93e9143961e8739c8fe18899dcerion                         binop(Iop_Shl8, mkexpr(rOnes),  mkU8(3)),
2007edf7fc572e2decb93e9143961e8739c8fe18899dcerion                         binop(Iop_Shl8, mkexpr(rZeros), mkU8(1))) );
2008edf7fc572e2decb93e9143961e8739c8fe18899dcerion   } else {
2009edf7fc572e2decb93e9143961e8739c8fe18899dcerion      putCR321( 6, binop(Iop_Shl8, mkexpr(rZeros), mkU8(1)) );
2010edf7fc572e2decb93e9143961e8739c8fe18899dcerion   }
2011edf7fc572e2decb93e9143961e8739c8fe18899dcerion   putCR0( 6, mkU8(0) );
2012edf7fc572e2decb93e9143961e8739c8fe18899dcerion}
2013edf7fc572e2decb93e9143961e8739c8fe18899dcerion
2014edf7fc572e2decb93e9143961e8739c8fe18899dcerion
2015edf7fc572e2decb93e9143961e8739c8fe18899dcerion
2016edf7fc572e2decb93e9143961e8739c8fe18899dcerion/*------------------------------------------------------------*/
2017edf7fc572e2decb93e9143961e8739c8fe18899dcerion/*--- Helpers for XER flags.                               ---*/
2018edf7fc572e2decb93e9143961e8739c8fe18899dcerion/*------------------------------------------------------------*/
2019edf7fc572e2decb93e9143961e8739c8fe18899dcerion
2020edf7fc572e2decb93e9143961e8739c8fe18899dcerionstatic void putXER_SO ( IRExpr* e )
2021edf7fc572e2decb93e9143961e8739c8fe18899dcerion{
2022633274098fafebdc79cf1c8a1ef7f9a9914669f1sewardj   IRExpr* so;
2023dd40fdf58cc8a6fe9466c4f00bdfc9fe9bf00449sewardj   vassert(typeOfIRExpr(irsb->tyenv, e) == Ity_I8);
2024633274098fafebdc79cf1c8a1ef7f9a9914669f1sewardj   so = binop(Iop_And8, e, mkU8(1));
20255b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion   stmt( IRStmt_Put( OFFB_XER_SO, so ) );
2026edf7fc572e2decb93e9143961e8739c8fe18899dcerion}
2027edf7fc572e2decb93e9143961e8739c8fe18899dcerion
2028edf7fc572e2decb93e9143961e8739c8fe18899dcerionstatic void putXER_OV ( IRExpr* e )
2029edf7fc572e2decb93e9143961e8739c8fe18899dcerion{
2030633274098fafebdc79cf1c8a1ef7f9a9914669f1sewardj   IRExpr* ov;
2031dd40fdf58cc8a6fe9466c4f00bdfc9fe9bf00449sewardj   vassert(typeOfIRExpr(irsb->tyenv, e) == Ity_I8);
2032633274098fafebdc79cf1c8a1ef7f9a9914669f1sewardj   ov = binop(Iop_And8, e, mkU8(1));
20335b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion   stmt( IRStmt_Put( OFFB_XER_OV, ov ) );
2034edf7fc572e2decb93e9143961e8739c8fe18899dcerion}
2035b51f0f4f33256638ed953156a2635aa739b232f1sewardj
2036edf7fc572e2decb93e9143961e8739c8fe18899dcerionstatic void putXER_CA ( IRExpr* e )
2037edf7fc572e2decb93e9143961e8739c8fe18899dcerion{
2038633274098fafebdc79cf1c8a1ef7f9a9914669f1sewardj   IRExpr* ca;
2039dd40fdf58cc8a6fe9466c4f00bdfc9fe9bf00449sewardj   vassert(typeOfIRExpr(irsb->tyenv, e) == Ity_I8);
2040633274098fafebdc79cf1c8a1ef7f9a9914669f1sewardj   ca = binop(Iop_And8, e, mkU8(1));
20415b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion   stmt( IRStmt_Put( OFFB_XER_CA, ca ) );
2042edf7fc572e2decb93e9143961e8739c8fe18899dcerion}
2043b51f0f4f33256638ed953156a2635aa739b232f1sewardj
2044edf7fc572e2decb93e9143961e8739c8fe18899dcerionstatic void putXER_BC ( IRExpr* e )
204591ad5368eb6354ad4fabc86f2b2e641736997a38cerion{
2046633274098fafebdc79cf1c8a1ef7f9a9914669f1sewardj   IRExpr* bc;
2047dd40fdf58cc8a6fe9466c4f00bdfc9fe9bf00449sewardj   vassert(typeOfIRExpr(irsb->tyenv, e) == Ity_I8);
2048633274098fafebdc79cf1c8a1ef7f9a9914669f1sewardj   bc = binop(Iop_And8, e, mkU8(0x7F));
20495b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion   stmt( IRStmt_Put( OFFB_XER_BC, bc ) );
2050b51f0f4f33256638ed953156a2635aa739b232f1sewardj}
205191ad5368eb6354ad4fabc86f2b2e641736997a38cerion
2052edf7fc572e2decb93e9143961e8739c8fe18899dcerionstatic IRExpr* /* :: Ity_I8 */ getXER_SO ( void )
2053b51f0f4f33256638ed953156a2635aa739b232f1sewardj{
20545b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion   return IRExpr_Get( OFFB_XER_SO, Ity_I8 );
2055edf7fc572e2decb93e9143961e8739c8fe18899dcerion}
2056edf7fc572e2decb93e9143961e8739c8fe18899dcerion
2057edf7fc572e2decb93e9143961e8739c8fe18899dcerionstatic IRExpr* /* :: Ity_I32 */ getXER_SO32 ( void )
2058edf7fc572e2decb93e9143961e8739c8fe18899dcerion{
2059edf7fc572e2decb93e9143961e8739c8fe18899dcerion   return binop( Iop_And32, unop(Iop_8Uto32, getXER_SO()), mkU32(1) );
206091ad5368eb6354ad4fabc86f2b2e641736997a38cerion}
206191ad5368eb6354ad4fabc86f2b2e641736997a38cerion
2062edf7fc572e2decb93e9143961e8739c8fe18899dcerionstatic IRExpr* /* :: Ity_I8 */ getXER_OV ( void )
2063edf7fc572e2decb93e9143961e8739c8fe18899dcerion{
20645b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion   return IRExpr_Get( OFFB_XER_OV, Ity_I8 );
2065edf7fc572e2decb93e9143961e8739c8fe18899dcerion}
2066b51f0f4f33256638ed953156a2635aa739b232f1sewardj
2067edf7fc572e2decb93e9143961e8739c8fe18899dcerionstatic IRExpr* /* :: Ity_I32 */ getXER_OV32 ( void )
2068896a1373cfdbaa25f4ab73ed4f27554016defecccerion{
2069edf7fc572e2decb93e9143961e8739c8fe18899dcerion   return binop( Iop_And32, unop(Iop_8Uto32, getXER_OV()), mkU32(1) );
2070edf7fc572e2decb93e9143961e8739c8fe18899dcerion}
2071edf7fc572e2decb93e9143961e8739c8fe18899dcerion
2072edf7fc572e2decb93e9143961e8739c8fe18899dcerionstatic IRExpr* /* :: Ity_I32 */ getXER_CA32 ( void )
2073edf7fc572e2decb93e9143961e8739c8fe18899dcerion{
20745b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion   IRExpr* ca = IRExpr_Get( OFFB_XER_CA, Ity_I8 );
2075d953ebb9b04cbad6891676df597bf0c542b1ec89cerion   return binop( Iop_And32, unop(Iop_8Uto32, ca ), mkU32(1) );
2076edf7fc572e2decb93e9143961e8739c8fe18899dcerion}
2077edf7fc572e2decb93e9143961e8739c8fe18899dcerion
2078edf7fc572e2decb93e9143961e8739c8fe18899dcerionstatic IRExpr* /* :: Ity_I8 */ getXER_BC ( void )
2079edf7fc572e2decb93e9143961e8739c8fe18899dcerion{
20805b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion   return IRExpr_Get( OFFB_XER_BC, Ity_I8 );
2081edf7fc572e2decb93e9143961e8739c8fe18899dcerion}
2082edf7fc572e2decb93e9143961e8739c8fe18899dcerion
2083edf7fc572e2decb93e9143961e8739c8fe18899dcerionstatic IRExpr* /* :: Ity_I32 */ getXER_BC32 ( void )
2084edf7fc572e2decb93e9143961e8739c8fe18899dcerion{
20855b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion   IRExpr* bc = IRExpr_Get( OFFB_XER_BC, Ity_I8 );
2086d953ebb9b04cbad6891676df597bf0c542b1ec89cerion   return binop( Iop_And32, unop(Iop_8Uto32, bc), mkU32(0x7F) );
208791ad5368eb6354ad4fabc86f2b2e641736997a38cerion}
2088896a1373cfdbaa25f4ab73ed4f27554016defecccerion
208920ef5472eac767474c93b7835364a23f24c0ec5dsewardj
209020ef5472eac767474c93b7835364a23f24c0ec5dsewardj/* RES is the result of doing OP on ARGL and ARGR.  Set %XER.OV and
209120ef5472eac767474c93b7835364a23f24c0ec5dsewardj   %XER.SO accordingly. */
209220ef5472eac767474c93b7835364a23f24c0ec5dsewardj
2093d953ebb9b04cbad6891676df597bf0c542b1ec89cerionstatic void set_XER_OV_32( UInt op, IRExpr* res,
2094d953ebb9b04cbad6891676df597bf0c542b1ec89cerion                           IRExpr* argL, IRExpr* argR )
209520ef5472eac767474c93b7835364a23f24c0ec5dsewardj{
209620ef5472eac767474c93b7835364a23f24c0ec5dsewardj   IRTemp  t64;
209720ef5472eac767474c93b7835364a23f24c0ec5dsewardj   IRExpr* xer_ov;
20985b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion   vassert(op < PPCG_FLAG_OP_NUMBER);
2099dd40fdf58cc8a6fe9466c4f00bdfc9fe9bf00449sewardj   vassert(typeOfIRExpr(irsb->tyenv,res)  == Ity_I32);
2100dd40fdf58cc8a6fe9466c4f00bdfc9fe9bf00449sewardj   vassert(typeOfIRExpr(irsb->tyenv,argL) == Ity_I32);
2101dd40fdf58cc8a6fe9466c4f00bdfc9fe9bf00449sewardj   vassert(typeOfIRExpr(irsb->tyenv,argR) == Ity_I32);
210220ef5472eac767474c93b7835364a23f24c0ec5dsewardj
210320ef5472eac767474c93b7835364a23f24c0ec5dsewardj#  define INT32_MIN 0x80000000
210420ef5472eac767474c93b7835364a23f24c0ec5dsewardj
210520ef5472eac767474c93b7835364a23f24c0ec5dsewardj#  define XOR2(_aa,_bb) \
210620ef5472eac767474c93b7835364a23f24c0ec5dsewardj      binop(Iop_Xor32,(_aa),(_bb))
210720ef5472eac767474c93b7835364a23f24c0ec5dsewardj
210820ef5472eac767474c93b7835364a23f24c0ec5dsewardj#  define XOR3(_cc,_dd,_ee) \
210920ef5472eac767474c93b7835364a23f24c0ec5dsewardj      binop(Iop_Xor32,binop(Iop_Xor32,(_cc),(_dd)),(_ee))
211020ef5472eac767474c93b7835364a23f24c0ec5dsewardj
211120ef5472eac767474c93b7835364a23f24c0ec5dsewardj#  define AND3(_ff,_gg,_hh) \
211220ef5472eac767474c93b7835364a23f24c0ec5dsewardj      binop(Iop_And32,binop(Iop_And32,(_ff),(_gg)),(_hh))
211320ef5472eac767474c93b7835364a23f24c0ec5dsewardj
211420ef5472eac767474c93b7835364a23f24c0ec5dsewardj#define NOT(_jj) \
211520ef5472eac767474c93b7835364a23f24c0ec5dsewardj      unop(Iop_Not32, (_jj))
211620ef5472eac767474c93b7835364a23f24c0ec5dsewardj
211720ef5472eac767474c93b7835364a23f24c0ec5dsewardj   switch (op) {
21185b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion   case /* 0  */ PPCG_FLAG_OP_ADD:
21195b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion   case /* 1  */ PPCG_FLAG_OP_ADDE:
2120d953ebb9b04cbad6891676df597bf0c542b1ec89cerion      /* (argL^argR^-1) & (argL^res) & (1<<31)  ?1:0 */
2121d953ebb9b04cbad6891676df597bf0c542b1ec89cerion      // i.e. ((both_same_sign) & (sign_changed) & (sign_mask))
2122d953ebb9b04cbad6891676df597bf0c542b1ec89cerion      xer_ov
2123d953ebb9b04cbad6891676df597bf0c542b1ec89cerion         = AND3( XOR3(argL,argR,mkU32(-1)),
2124d953ebb9b04cbad6891676df597bf0c542b1ec89cerion                 XOR2(argL,res),
2125d953ebb9b04cbad6891676df597bf0c542b1ec89cerion                 mkU32(INT32_MIN) );
2126d953ebb9b04cbad6891676df597bf0c542b1ec89cerion      /* xer_ov can only be 0 or 1<<31 */
2127d953ebb9b04cbad6891676df597bf0c542b1ec89cerion      xer_ov
2128d953ebb9b04cbad6891676df597bf0c542b1ec89cerion         = binop(Iop_Shr32, xer_ov, mkU8(31) );
2129d953ebb9b04cbad6891676df597bf0c542b1ec89cerion      break;
2130d953ebb9b04cbad6891676df597bf0c542b1ec89cerion
21315b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion   case /* 2  */ PPCG_FLAG_OP_DIVW:
2132d953ebb9b04cbad6891676df597bf0c542b1ec89cerion      /* (argL == INT32_MIN && argR == -1) || argR == 0 */
2133d953ebb9b04cbad6891676df597bf0c542b1ec89cerion      xer_ov
2134d953ebb9b04cbad6891676df597bf0c542b1ec89cerion         = mkOR1(
2135d953ebb9b04cbad6891676df597bf0c542b1ec89cerion              mkAND1(
2136d953ebb9b04cbad6891676df597bf0c542b1ec89cerion                 binop(Iop_CmpEQ32, argL, mkU32(INT32_MIN)),
2137d953ebb9b04cbad6891676df597bf0c542b1ec89cerion                 binop(Iop_CmpEQ32, argR, mkU32(-1))
2138d953ebb9b04cbad6891676df597bf0c542b1ec89cerion              ),
2139d953ebb9b04cbad6891676df597bf0c542b1ec89cerion              binop(Iop_CmpEQ32, argR, mkU32(0) )
2140d953ebb9b04cbad6891676df597bf0c542b1ec89cerion           );
2141d953ebb9b04cbad6891676df597bf0c542b1ec89cerion      xer_ov
2142d953ebb9b04cbad6891676df597bf0c542b1ec89cerion         = unop(Iop_1Uto32, xer_ov);
2143d953ebb9b04cbad6891676df597bf0c542b1ec89cerion      break;
2144d953ebb9b04cbad6891676df597bf0c542b1ec89cerion
21455b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion   case /* 3  */ PPCG_FLAG_OP_DIVWU:
2146d953ebb9b04cbad6891676df597bf0c542b1ec89cerion      /* argR == 0 */
2147d953ebb9b04cbad6891676df597bf0c542b1ec89cerion      xer_ov
2148d953ebb9b04cbad6891676df597bf0c542b1ec89cerion         = unop(Iop_1Uto32, binop(Iop_CmpEQ32, argR, mkU32(0)));
2149d953ebb9b04cbad6891676df597bf0c542b1ec89cerion      break;
2150d953ebb9b04cbad6891676df597bf0c542b1ec89cerion
21515b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion   case /* 4  */ PPCG_FLAG_OP_MULLW:
2152d953ebb9b04cbad6891676df597bf0c542b1ec89cerion      /* OV true if result can't be represented in 32 bits
2153d953ebb9b04cbad6891676df597bf0c542b1ec89cerion         i.e sHi != sign extension of sLo */
2154d953ebb9b04cbad6891676df597bf0c542b1ec89cerion      t64 = newTemp(Ity_I64);
2155d953ebb9b04cbad6891676df597bf0c542b1ec89cerion      assign( t64, binop(Iop_MullS32, argL, argR) );
2156d953ebb9b04cbad6891676df597bf0c542b1ec89cerion      xer_ov
2157d953ebb9b04cbad6891676df597bf0c542b1ec89cerion         = binop( Iop_CmpNE32,
2158d953ebb9b04cbad6891676df597bf0c542b1ec89cerion                  unop(Iop_64HIto32, mkexpr(t64)),
2159d953ebb9b04cbad6891676df597bf0c542b1ec89cerion                  binop( Iop_Sar32,
2160d953ebb9b04cbad6891676df597bf0c542b1ec89cerion                         unop(Iop_64to32, mkexpr(t64)),
2161d953ebb9b04cbad6891676df597bf0c542b1ec89cerion                         mkU8(31))
2162d953ebb9b04cbad6891676df597bf0c542b1ec89cerion                  );
2163d953ebb9b04cbad6891676df597bf0c542b1ec89cerion      xer_ov
2164d953ebb9b04cbad6891676df597bf0c542b1ec89cerion         = unop(Iop_1Uto32, xer_ov);
2165d953ebb9b04cbad6891676df597bf0c542b1ec89cerion      break;
2166d953ebb9b04cbad6891676df597bf0c542b1ec89cerion
21675b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion   case /* 5  */ PPCG_FLAG_OP_NEG:
2168d953ebb9b04cbad6891676df597bf0c542b1ec89cerion      /* argL == INT32_MIN */
2169d953ebb9b04cbad6891676df597bf0c542b1ec89cerion      xer_ov
2170d953ebb9b04cbad6891676df597bf0c542b1ec89cerion         = unop( Iop_1Uto32,
2171d953ebb9b04cbad6891676df597bf0c542b1ec89cerion                 binop(Iop_CmpEQ32, argL, mkU32(INT32_MIN)) );
2172d953ebb9b04cbad6891676df597bf0c542b1ec89cerion      break;
2173d953ebb9b04cbad6891676df597bf0c542b1ec89cerion
21745b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion   case /* 6  */ PPCG_FLAG_OP_SUBF:
21755b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion   case /* 7  */ PPCG_FLAG_OP_SUBFC:
21765b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion   case /* 8  */ PPCG_FLAG_OP_SUBFE:
2177d953ebb9b04cbad6891676df597bf0c542b1ec89cerion      /* ((~argL)^argR^-1) & ((~argL)^res) & (1<<31) ?1:0; */
2178d953ebb9b04cbad6891676df597bf0c542b1ec89cerion      xer_ov
2179d953ebb9b04cbad6891676df597bf0c542b1ec89cerion         = AND3( XOR3(NOT(argL),argR,mkU32(-1)),
2180d953ebb9b04cbad6891676df597bf0c542b1ec89cerion                 XOR2(NOT(argL),res),
2181d953ebb9b04cbad6891676df597bf0c542b1ec89cerion                 mkU32(INT32_MIN) );
2182d953ebb9b04cbad6891676df597bf0c542b1ec89cerion      /* xer_ov can only be 0 or 1<<31 */
2183d953ebb9b04cbad6891676df597bf0c542b1ec89cerion      xer_ov
2184d953ebb9b04cbad6891676df597bf0c542b1ec89cerion         = binop(Iop_Shr32, xer_ov, mkU8(31) );
2185d953ebb9b04cbad6891676df597bf0c542b1ec89cerion      break;
2186d953ebb9b04cbad6891676df597bf0c542b1ec89cerion
21874aa412af1d8166cc11f39a6e721df49431d23618sewardj   case PPCG_FLAG_OP_DIVWEU:
21884aa412af1d8166cc11f39a6e721df49431d23618sewardj      xer_ov
21894aa412af1d8166cc11f39a6e721df49431d23618sewardj               = binop( Iop_Or32,
21904aa412af1d8166cc11f39a6e721df49431d23618sewardj                        unop( Iop_1Uto32, binop( Iop_CmpEQ32, argR, mkU32( 0 ) ) ),
21914aa412af1d8166cc11f39a6e721df49431d23618sewardj                        unop( Iop_1Uto32, binop( Iop_CmpLT32U, argR, argL ) ) );
21924aa412af1d8166cc11f39a6e721df49431d23618sewardj      break;
21934aa412af1d8166cc11f39a6e721df49431d23618sewardj
2194e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj   case PPCG_FLAG_OP_DIVWE:
2195e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj
2196e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj      /* If argR == 0 of if the result cannot fit in the 32-bit destination register,
2197e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj       * then OV <- 1.   If dest reg is 0 AND both dividend and divisor are non-zero,
2198e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj       * an overflow is implied.
2199e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj       */
2200e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj      xer_ov = binop( Iop_Or32,
2201e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj                      unop( Iop_1Uto32, binop( Iop_CmpEQ32, argR, mkU32( 0 ) ) ),
2202e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj                      unop( Iop_1Uto32, mkAND1( binop( Iop_CmpEQ32, res, mkU32( 0 ) ),
2203e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj                              mkAND1( binop( Iop_CmpNE32, argL, mkU32( 0 ) ),
2204e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj                                      binop( Iop_CmpNE32, argR, mkU32( 0 ) ) ) ) ) );
2205e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj      break;
2206e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj
2207e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj
2208e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj
2209d953ebb9b04cbad6891676df597bf0c542b1ec89cerion   default:
2210d953ebb9b04cbad6891676df597bf0c542b1ec89cerion      vex_printf("set_XER_OV: op = %u\n", op);
22115b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion      vpanic("set_XER_OV(ppc)");
2212d953ebb9b04cbad6891676df597bf0c542b1ec89cerion   }
2213d953ebb9b04cbad6891676df597bf0c542b1ec89cerion
2214d953ebb9b04cbad6891676df597bf0c542b1ec89cerion   /* xer_ov MUST denote either 0 or 1, no other value allowed */
2215d953ebb9b04cbad6891676df597bf0c542b1ec89cerion   putXER_OV( unop(Iop_32to8, xer_ov) );
221620ef5472eac767474c93b7835364a23f24c0ec5dsewardj
2217d953ebb9b04cbad6891676df597bf0c542b1ec89cerion   /* Update the summary overflow */
2218d953ebb9b04cbad6891676df597bf0c542b1ec89cerion   putXER_SO( binop(Iop_Or8, getXER_SO(), getXER_OV()) );
221920ef5472eac767474c93b7835364a23f24c0ec5dsewardj
2220d953ebb9b04cbad6891676df597bf0c542b1ec89cerion#  undef INT32_MIN
2221d953ebb9b04cbad6891676df597bf0c542b1ec89cerion#  undef AND3
2222d953ebb9b04cbad6891676df597bf0c542b1ec89cerion#  undef XOR3
2223d953ebb9b04cbad6891676df597bf0c542b1ec89cerion#  undef XOR2
2224d953ebb9b04cbad6891676df597bf0c542b1ec89cerion#  undef NOT
2225d953ebb9b04cbad6891676df597bf0c542b1ec89cerion}
222620ef5472eac767474c93b7835364a23f24c0ec5dsewardj
2227d953ebb9b04cbad6891676df597bf0c542b1ec89cerionstatic void set_XER_OV_64( UInt op, IRExpr* res,
2228d953ebb9b04cbad6891676df597bf0c542b1ec89cerion                           IRExpr* argL, IRExpr* argR )
2229d953ebb9b04cbad6891676df597bf0c542b1ec89cerion{
2230d953ebb9b04cbad6891676df597bf0c542b1ec89cerion   IRExpr* xer_ov;
22315b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion   vassert(op < PPCG_FLAG_OP_NUMBER);
2232dd40fdf58cc8a6fe9466c4f00bdfc9fe9bf00449sewardj   vassert(typeOfIRExpr(irsb->tyenv,res)  == Ity_I64);
2233dd40fdf58cc8a6fe9466c4f00bdfc9fe9bf00449sewardj   vassert(typeOfIRExpr(irsb->tyenv,argL) == Ity_I64);
2234dd40fdf58cc8a6fe9466c4f00bdfc9fe9bf00449sewardj   vassert(typeOfIRExpr(irsb->tyenv,argR) == Ity_I64);
223520ef5472eac767474c93b7835364a23f24c0ec5dsewardj
22362831b00c4950d6c2b061def05fd67528fe132ececerion#  define INT64_MIN 0x8000000000000000ULL
223720ef5472eac767474c93b7835364a23f24c0ec5dsewardj
2238d953ebb9b04cbad6891676df597bf0c542b1ec89cerion#  define XOR2(_aa,_bb) \
2239d953ebb9b04cbad6891676df597bf0c542b1ec89cerion      binop(Iop_Xor64,(_aa),(_bb))
224020ef5472eac767474c93b7835364a23f24c0ec5dsewardj
2241d953ebb9b04cbad6891676df597bf0c542b1ec89cerion#  define XOR3(_cc,_dd,_ee) \
2242d953ebb9b04cbad6891676df597bf0c542b1ec89cerion      binop(Iop_Xor64,binop(Iop_Xor64,(_cc),(_dd)),(_ee))
2243d953ebb9b04cbad6891676df597bf0c542b1ec89cerion
2244d953ebb9b04cbad6891676df597bf0c542b1ec89cerion#  define AND3(_ff,_gg,_hh) \
2245d953ebb9b04cbad6891676df597bf0c542b1ec89cerion      binop(Iop_And64,binop(Iop_And64,(_ff),(_gg)),(_hh))
2246d953ebb9b04cbad6891676df597bf0c542b1ec89cerion
2247d953ebb9b04cbad6891676df597bf0c542b1ec89cerion#define NOT(_jj) \
2248d953ebb9b04cbad6891676df597bf0c542b1ec89cerion      unop(Iop_Not64, (_jj))
224920ef5472eac767474c93b7835364a23f24c0ec5dsewardj
2250d953ebb9b04cbad6891676df597bf0c542b1ec89cerion   switch (op) {
22515b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion   case /* 0  */ PPCG_FLAG_OP_ADD:
22525b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion   case /* 1  */ PPCG_FLAG_OP_ADDE:
2253d953ebb9b04cbad6891676df597bf0c542b1ec89cerion      /* (argL^argR^-1) & (argL^res) & (1<<63)  ? 1:0 */
2254d953ebb9b04cbad6891676df597bf0c542b1ec89cerion      // i.e. ((both_same_sign) & (sign_changed) & (sign_mask))
2255d953ebb9b04cbad6891676df597bf0c542b1ec89cerion      xer_ov
2256d953ebb9b04cbad6891676df597bf0c542b1ec89cerion         = AND3( XOR3(argL,argR,mkU64(-1)),
2257d953ebb9b04cbad6891676df597bf0c542b1ec89cerion                 XOR2(argL,res),
2258d953ebb9b04cbad6891676df597bf0c542b1ec89cerion                 mkU64(INT64_MIN) );
2259d953ebb9b04cbad6891676df597bf0c542b1ec89cerion      /* xer_ov can only be 0 or 1<<63 */
2260d953ebb9b04cbad6891676df597bf0c542b1ec89cerion      xer_ov
2261d953ebb9b04cbad6891676df597bf0c542b1ec89cerion         = unop(Iop_64to1, binop(Iop_Shr64, xer_ov, mkU8(63)));
2262d953ebb9b04cbad6891676df597bf0c542b1ec89cerion      break;
2263d953ebb9b04cbad6891676df597bf0c542b1ec89cerion
22645b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion   case /* 2  */ PPCG_FLAG_OP_DIVW:
2265d953ebb9b04cbad6891676df597bf0c542b1ec89cerion      /* (argL == INT64_MIN && argR == -1) || argR == 0 */
2266d953ebb9b04cbad6891676df597bf0c542b1ec89cerion      xer_ov
2267d953ebb9b04cbad6891676df597bf0c542b1ec89cerion         = mkOR1(
2268d953ebb9b04cbad6891676df597bf0c542b1ec89cerion              mkAND1(
2269d953ebb9b04cbad6891676df597bf0c542b1ec89cerion                 binop(Iop_CmpEQ64, argL, mkU64(INT64_MIN)),
2270d953ebb9b04cbad6891676df597bf0c542b1ec89cerion                 binop(Iop_CmpEQ64, argR, mkU64(-1))
2271d953ebb9b04cbad6891676df597bf0c542b1ec89cerion              ),
2272d953ebb9b04cbad6891676df597bf0c542b1ec89cerion              binop(Iop_CmpEQ64, argR, mkU64(0) )
2273d953ebb9b04cbad6891676df597bf0c542b1ec89cerion           );
2274d953ebb9b04cbad6891676df597bf0c542b1ec89cerion      break;
2275d953ebb9b04cbad6891676df597bf0c542b1ec89cerion
22765b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion   case /* 3  */ PPCG_FLAG_OP_DIVWU:
2277d953ebb9b04cbad6891676df597bf0c542b1ec89cerion      /* argR == 0 */
2278d953ebb9b04cbad6891676df597bf0c542b1ec89cerion      xer_ov
2279d953ebb9b04cbad6891676df597bf0c542b1ec89cerion         = binop(Iop_CmpEQ64, argR, mkU64(0));
2280d953ebb9b04cbad6891676df597bf0c542b1ec89cerion      break;
2281d953ebb9b04cbad6891676df597bf0c542b1ec89cerion
22825b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion   case /* 4  */ PPCG_FLAG_OP_MULLW: {
2283d953ebb9b04cbad6891676df597bf0c542b1ec89cerion      /* OV true if result can't be represented in 64 bits
2284d953ebb9b04cbad6891676df597bf0c542b1ec89cerion         i.e sHi != sign extension of sLo */
2285d953ebb9b04cbad6891676df597bf0c542b1ec89cerion      xer_ov
2286bb01b7cbfd84c27dd213f67a144ea5a99af36961cerion         = binop( Iop_CmpNE32,
2287bb01b7cbfd84c27dd213f67a144ea5a99af36961cerion                  unop(Iop_64HIto32, res),
2288bb01b7cbfd84c27dd213f67a144ea5a99af36961cerion                  binop( Iop_Sar32,
2289bb01b7cbfd84c27dd213f67a144ea5a99af36961cerion                         unop(Iop_64to32, res),
2290bb01b7cbfd84c27dd213f67a144ea5a99af36961cerion                         mkU8(31))
2291bb01b7cbfd84c27dd213f67a144ea5a99af36961cerion                  );
2292d953ebb9b04cbad6891676df597bf0c542b1ec89cerion      break;
229320ef5472eac767474c93b7835364a23f24c0ec5dsewardj   }
2294d953ebb9b04cbad6891676df597bf0c542b1ec89cerion
22955b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion   case /* 5  */ PPCG_FLAG_OP_NEG:
2296d953ebb9b04cbad6891676df597bf0c542b1ec89cerion      /* argL == INT64_MIN */
2297d953ebb9b04cbad6891676df597bf0c542b1ec89cerion      xer_ov
2298d953ebb9b04cbad6891676df597bf0c542b1ec89cerion         = binop(Iop_CmpEQ64, argL, mkU64(INT64_MIN));
2299d953ebb9b04cbad6891676df597bf0c542b1ec89cerion      break;
2300d953ebb9b04cbad6891676df597bf0c542b1ec89cerion
23015b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion   case /* 6  */ PPCG_FLAG_OP_SUBF:
23025b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion   case /* 7  */ PPCG_FLAG_OP_SUBFC:
23035b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion   case /* 8  */ PPCG_FLAG_OP_SUBFE:
2304d953ebb9b04cbad6891676df597bf0c542b1ec89cerion      /* ((~argL)^argR^-1) & ((~argL)^res) & (1<<63) ?1:0; */
2305d953ebb9b04cbad6891676df597bf0c542b1ec89cerion      xer_ov
2306d953ebb9b04cbad6891676df597bf0c542b1ec89cerion         = AND3( XOR3(NOT(argL),argR,mkU64(-1)),
2307d953ebb9b04cbad6891676df597bf0c542b1ec89cerion                 XOR2(NOT(argL),res),
2308d953ebb9b04cbad6891676df597bf0c542b1ec89cerion                 mkU64(INT64_MIN) );
2309d953ebb9b04cbad6891676df597bf0c542b1ec89cerion      /* xer_ov can only be 0 or 1<<63 */
2310d953ebb9b04cbad6891676df597bf0c542b1ec89cerion      xer_ov
2311d953ebb9b04cbad6891676df597bf0c542b1ec89cerion         = unop(Iop_64to1, binop(Iop_Shr64, xer_ov, mkU8(63)));
2312d953ebb9b04cbad6891676df597bf0c542b1ec89cerion      break;
2313d953ebb9b04cbad6891676df597bf0c542b1ec89cerion
23144aa412af1d8166cc11f39a6e721df49431d23618sewardj   case PPCG_FLAG_OP_DIVDE:
23154aa412af1d8166cc11f39a6e721df49431d23618sewardj
23164aa412af1d8166cc11f39a6e721df49431d23618sewardj      /* If argR == 0, we must set the OV bit.  But there's another condition
23174aa412af1d8166cc11f39a6e721df49431d23618sewardj       * where we can get overflow set for divde . . . when the
23184aa412af1d8166cc11f39a6e721df49431d23618sewardj       * result cannot fit in the 64-bit destination register.  If dest reg is 0 AND
23194aa412af1d8166cc11f39a6e721df49431d23618sewardj       * both dividend and divisor are non-zero, it implies an overflow.
23204aa412af1d8166cc11f39a6e721df49431d23618sewardj       */
23214aa412af1d8166cc11f39a6e721df49431d23618sewardj      xer_ov
23224aa412af1d8166cc11f39a6e721df49431d23618sewardj                  = mkOR1( binop( Iop_CmpEQ64, argR, mkU64( 0 ) ),
23234aa412af1d8166cc11f39a6e721df49431d23618sewardj                           mkAND1( binop( Iop_CmpEQ64, res, mkU64( 0 ) ),
23244aa412af1d8166cc11f39a6e721df49431d23618sewardj                                   mkAND1( binop( Iop_CmpNE64, argL, mkU64( 0 ) ),
23254aa412af1d8166cc11f39a6e721df49431d23618sewardj                                           binop( Iop_CmpNE64, argR, mkU64( 0 ) ) ) ) );
23264aa412af1d8166cc11f39a6e721df49431d23618sewardj      break;
23274aa412af1d8166cc11f39a6e721df49431d23618sewardj
2328e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj   case PPCG_FLAG_OP_DIVDEU:
2329e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj     /* If argR == 0 or if argL >= argR, set OV. */
2330e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj     xer_ov = mkOR1( binop( Iop_CmpEQ64, argR, mkU64( 0 ) ),
2331e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj                         binop( Iop_CmpLE64U, argR, argL ) );
2332e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj     break;
2333e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj
233438b79ace9613df76a5feb7a237226f4a4cc02ecdcarll   case /* 18 */ PPCG_FLAG_OP_MULLD: {
233538b79ace9613df76a5feb7a237226f4a4cc02ecdcarll      IRTemp  t128;
233638b79ace9613df76a5feb7a237226f4a4cc02ecdcarll      /* OV true if result can't be represented in 64 bits
233738b79ace9613df76a5feb7a237226f4a4cc02ecdcarll         i.e sHi != sign extension of sLo */
233838b79ace9613df76a5feb7a237226f4a4cc02ecdcarll      t128 = newTemp(Ity_I128);
233938b79ace9613df76a5feb7a237226f4a4cc02ecdcarll      assign( t128, binop(Iop_MullS64, argL, argR) );
234038b79ace9613df76a5feb7a237226f4a4cc02ecdcarll      xer_ov
234138b79ace9613df76a5feb7a237226f4a4cc02ecdcarll         = binop( Iop_CmpNE64,
234238b79ace9613df76a5feb7a237226f4a4cc02ecdcarll                  unop(Iop_128HIto64, mkexpr(t128)),
234338b79ace9613df76a5feb7a237226f4a4cc02ecdcarll                  binop( Iop_Sar64,
234438b79ace9613df76a5feb7a237226f4a4cc02ecdcarll                         unop(Iop_128to64, mkexpr(t128)),
234538b79ace9613df76a5feb7a237226f4a4cc02ecdcarll                         mkU8(63))
234638b79ace9613df76a5feb7a237226f4a4cc02ecdcarll                  );
234738b79ace9613df76a5feb7a237226f4a4cc02ecdcarll      break;
234838b79ace9613df76a5feb7a237226f4a4cc02ecdcarll   }
234938b79ace9613df76a5feb7a237226f4a4cc02ecdcarll
2350d953ebb9b04cbad6891676df597bf0c542b1ec89cerion   default:
2351d953ebb9b04cbad6891676df597bf0c542b1ec89cerion      vex_printf("set_XER_OV: op = %u\n", op);
23525b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion      vpanic("set_XER_OV(ppc64)");
2353d953ebb9b04cbad6891676df597bf0c542b1ec89cerion   }
2354d953ebb9b04cbad6891676df597bf0c542b1ec89cerion
235520ef5472eac767474c93b7835364a23f24c0ec5dsewardj   /* xer_ov MUST denote either 0 or 1, no other value allowed */
2356d953ebb9b04cbad6891676df597bf0c542b1ec89cerion   putXER_OV( unop(Iop_1Uto8, xer_ov) );
235720ef5472eac767474c93b7835364a23f24c0ec5dsewardj
235820ef5472eac767474c93b7835364a23f24c0ec5dsewardj   /* Update the summary overflow */
2359edf7fc572e2decb93e9143961e8739c8fe18899dcerion   putXER_SO( binop(Iop_Or8, getXER_SO(), getXER_OV()) );
236020ef5472eac767474c93b7835364a23f24c0ec5dsewardj
2361d953ebb9b04cbad6891676df597bf0c542b1ec89cerion#  undef INT64_MIN
236220ef5472eac767474c93b7835364a23f24c0ec5dsewardj#  undef AND3
236320ef5472eac767474c93b7835364a23f24c0ec5dsewardj#  undef XOR3
236420ef5472eac767474c93b7835364a23f24c0ec5dsewardj#  undef XOR2
236520ef5472eac767474c93b7835364a23f24c0ec5dsewardj#  undef NOT
236620ef5472eac767474c93b7835364a23f24c0ec5dsewardj}
236720ef5472eac767474c93b7835364a23f24c0ec5dsewardj
2368d953ebb9b04cbad6891676df597bf0c542b1ec89cerionstatic void set_XER_OV ( IRType ty, UInt op, IRExpr* res,
2369d953ebb9b04cbad6891676df597bf0c542b1ec89cerion                         IRExpr* argL, IRExpr* argR )
2370d953ebb9b04cbad6891676df597bf0c542b1ec89cerion{
2371d953ebb9b04cbad6891676df597bf0c542b1ec89cerion   if (ty == Ity_I32)
2372d953ebb9b04cbad6891676df597bf0c542b1ec89cerion      set_XER_OV_32( op, res, argL, argR );
2373d953ebb9b04cbad6891676df597bf0c542b1ec89cerion   else
2374d953ebb9b04cbad6891676df597bf0c542b1ec89cerion      set_XER_OV_64( op, res, argL, argR );
2375d953ebb9b04cbad6891676df597bf0c542b1ec89cerion}
2376d953ebb9b04cbad6891676df597bf0c542b1ec89cerion
2377d953ebb9b04cbad6891676df597bf0c542b1ec89cerion
2378d953ebb9b04cbad6891676df597bf0c542b1ec89cerion
2379b51f0f4f33256638ed953156a2635aa739b232f1sewardj/* RES is the result of doing OP on ARGL and ARGR with the old %XER.CA
2380b51f0f4f33256638ed953156a2635aa739b232f1sewardj   value being OLDCA.  Set %XER.CA accordingly. */
2381b51f0f4f33256638ed953156a2635aa739b232f1sewardj
23822831b00c4950d6c2b061def05fd67528fe132ececerionstatic void set_XER_CA_32 ( UInt op, IRExpr* res,
23832831b00c4950d6c2b061def05fd67528fe132ececerion                            IRExpr* argL, IRExpr* argR, IRExpr* oldca )
23843867460f7533d6dc4e2c85656664ee341ea81e7dcerion{
2385b51f0f4f33256638ed953156a2635aa739b232f1sewardj   IRExpr* xer_ca;
23865b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion   vassert(op < PPCG_FLAG_OP_NUMBER);
2387dd40fdf58cc8a6fe9466c4f00bdfc9fe9bf00449sewardj   vassert(typeOfIRExpr(irsb->tyenv,res)   == Ity_I32);
2388dd40fdf58cc8a6fe9466c4f00bdfc9fe9bf00449sewardj   vassert(typeOfIRExpr(irsb->tyenv,argL)  == Ity_I32);
2389dd40fdf58cc8a6fe9466c4f00bdfc9fe9bf00449sewardj   vassert(typeOfIRExpr(irsb->tyenv,argR)  == Ity_I32);
2390dd40fdf58cc8a6fe9466c4f00bdfc9fe9bf00449sewardj   vassert(typeOfIRExpr(irsb->tyenv,oldca) == Ity_I32);
2391b51f0f4f33256638ed953156a2635aa739b232f1sewardj
239220ef5472eac767474c93b7835364a23f24c0ec5dsewardj   /* Incoming oldca is assumed to hold the values 0 or 1 only.  This
239320ef5472eac767474c93b7835364a23f24c0ec5dsewardj      seems reasonable given that it's always generated by
2394edf7fc572e2decb93e9143961e8739c8fe18899dcerion      getXER_CA32(), which masks it accordingly.  In any case it being
23957594920259781fa292dd6a3b27beb63f5875c308cerion      0 or 1 is an invariant of the ppc guest state representation;
239620ef5472eac767474c93b7835364a23f24c0ec5dsewardj      if it has any other value, that invariant has been violated. */
239720ef5472eac767474c93b7835364a23f24c0ec5dsewardj
239820ef5472eac767474c93b7835364a23f24c0ec5dsewardj   switch (op) {
23995b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion   case /* 0 */ PPCG_FLAG_OP_ADD:
2400d953ebb9b04cbad6891676df597bf0c542b1ec89cerion      /* res <u argL */
2401d953ebb9b04cbad6891676df597bf0c542b1ec89cerion      xer_ca
2402d953ebb9b04cbad6891676df597bf0c542b1ec89cerion         = unop(Iop_1Uto32, binop(Iop_CmpLT32U, res, argL));
2403d953ebb9b04cbad6891676df597bf0c542b1ec89cerion      break;
2404d953ebb9b04cbad6891676df597bf0c542b1ec89cerion
24055b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion   case /* 1 */ PPCG_FLAG_OP_ADDE:
2406d953ebb9b04cbad6891676df597bf0c542b1ec89cerion      /* res <u argL || (old_ca==1 && res==argL) */
2407d953ebb9b04cbad6891676df597bf0c542b1ec89cerion      xer_ca
2408d953ebb9b04cbad6891676df597bf0c542b1ec89cerion         = mkOR1(
2409d953ebb9b04cbad6891676df597bf0c542b1ec89cerion              binop(Iop_CmpLT32U, res, argL),
2410d953ebb9b04cbad6891676df597bf0c542b1ec89cerion              mkAND1(
2411d953ebb9b04cbad6891676df597bf0c542b1ec89cerion                 binop(Iop_CmpEQ32, oldca, mkU32(1)),
2412d953ebb9b04cbad6891676df597bf0c542b1ec89cerion                 binop(Iop_CmpEQ32, res, argL)
2413d953ebb9b04cbad6891676df597bf0c542b1ec89cerion              )
2414d953ebb9b04cbad6891676df597bf0c542b1ec89cerion           );
2415d953ebb9b04cbad6891676df597bf0c542b1ec89cerion      xer_ca
2416d953ebb9b04cbad6891676df597bf0c542b1ec89cerion         = unop(Iop_1Uto32, xer_ca);
2417d953ebb9b04cbad6891676df597bf0c542b1ec89cerion      break;
2418d953ebb9b04cbad6891676df597bf0c542b1ec89cerion
24195b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion   case /* 8 */ PPCG_FLAG_OP_SUBFE:
2420d953ebb9b04cbad6891676df597bf0c542b1ec89cerion      /* res <u argR || (old_ca==1 && res==argR) */
2421d953ebb9b04cbad6891676df597bf0c542b1ec89cerion      xer_ca
2422d953ebb9b04cbad6891676df597bf0c542b1ec89cerion         = mkOR1(
2423d953ebb9b04cbad6891676df597bf0c542b1ec89cerion              binop(Iop_CmpLT32U, res, argR),
2424d953ebb9b04cbad6891676df597bf0c542b1ec89cerion              mkAND1(
2425d953ebb9b04cbad6891676df597bf0c542b1ec89cerion                 binop(Iop_CmpEQ32, oldca, mkU32(1)),
2426d953ebb9b04cbad6891676df597bf0c542b1ec89cerion                 binop(Iop_CmpEQ32, res, argR)
2427d953ebb9b04cbad6891676df597bf0c542b1ec89cerion              )
2428d953ebb9b04cbad6891676df597bf0c542b1ec89cerion           );
2429d953ebb9b04cbad6891676df597bf0c542b1ec89cerion      xer_ca
2430d953ebb9b04cbad6891676df597bf0c542b1ec89cerion         = unop(Iop_1Uto32, xer_ca);
2431d953ebb9b04cbad6891676df597bf0c542b1ec89cerion      break;
2432d953ebb9b04cbad6891676df597bf0c542b1ec89cerion
24335b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion   case /* 7 */ PPCG_FLAG_OP_SUBFC:
24345b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion   case /* 9 */ PPCG_FLAG_OP_SUBFI:
2435d953ebb9b04cbad6891676df597bf0c542b1ec89cerion      /* res <=u argR */
2436d953ebb9b04cbad6891676df597bf0c542b1ec89cerion      xer_ca
2437d953ebb9b04cbad6891676df597bf0c542b1ec89cerion         = unop(Iop_1Uto32, binop(Iop_CmpLE32U, res, argR));
2438d953ebb9b04cbad6891676df597bf0c542b1ec89cerion      break;
2439d953ebb9b04cbad6891676df597bf0c542b1ec89cerion
24405b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion   case /* 10 */ PPCG_FLAG_OP_SRAW:
2441d953ebb9b04cbad6891676df597bf0c542b1ec89cerion      /* The shift amount is guaranteed to be in 0 .. 63 inclusive.
2442d953ebb9b04cbad6891676df597bf0c542b1ec89cerion         If it is <= 31, behave like SRAWI; else XER.CA is the sign
2443d953ebb9b04cbad6891676df597bf0c542b1ec89cerion         bit of argL. */
2444d953ebb9b04cbad6891676df597bf0c542b1ec89cerion      /* This term valid for shift amount < 32 only */
2445d953ebb9b04cbad6891676df597bf0c542b1ec89cerion      xer_ca
2446d953ebb9b04cbad6891676df597bf0c542b1ec89cerion         = binop(
2447d953ebb9b04cbad6891676df597bf0c542b1ec89cerion              Iop_And32,
2448d953ebb9b04cbad6891676df597bf0c542b1ec89cerion              binop(Iop_Sar32, argL, mkU8(31)),
2449d953ebb9b04cbad6891676df597bf0c542b1ec89cerion              binop( Iop_And32,
2450d953ebb9b04cbad6891676df597bf0c542b1ec89cerion                     argL,
2451d953ebb9b04cbad6891676df597bf0c542b1ec89cerion                     binop( Iop_Sub32,
24525b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion                            binop(Iop_Shl32, mkU32(1),
24535b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion                                             unop(Iop_32to8,argR)),
2454d953ebb9b04cbad6891676df597bf0c542b1ec89cerion                            mkU32(1) )
2455d953ebb9b04cbad6891676df597bf0c542b1ec89cerion                     )
245620ef5472eac767474c93b7835364a23f24c0ec5dsewardj              );
2457d953ebb9b04cbad6891676df597bf0c542b1ec89cerion      xer_ca
245899dd03e04a6914d90d5fee727d61d76905334becflorian         = IRExpr_ITE(
2459d953ebb9b04cbad6891676df597bf0c542b1ec89cerion              /* shift amt > 31 ? */
2460009230b9758291b594e60d7c0243a73d53e81854sewardj              binop(Iop_CmpLT32U, mkU32(31), argR),
2461d953ebb9b04cbad6891676df597bf0c542b1ec89cerion              /* yes -- get sign bit of argL */
246299dd03e04a6914d90d5fee727d61d76905334becflorian              binop(Iop_Shr32, argL, mkU8(31)),
246399dd03e04a6914d90d5fee727d61d76905334becflorian              /* no -- be like srawi */
246499dd03e04a6914d90d5fee727d61d76905334becflorian              unop(Iop_1Uto32, binop(Iop_CmpNE32, xer_ca, mkU32(0)))
2465d953ebb9b04cbad6891676df597bf0c542b1ec89cerion           );
2466d953ebb9b04cbad6891676df597bf0c542b1ec89cerion      break;
2467d953ebb9b04cbad6891676df597bf0c542b1ec89cerion
24685b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion   case /* 11 */ PPCG_FLAG_OP_SRAWI:
2469d953ebb9b04cbad6891676df597bf0c542b1ec89cerion      /* xer_ca is 1 iff src was negative and bits_shifted_out !=
2470d953ebb9b04cbad6891676df597bf0c542b1ec89cerion         0.  Since the shift amount is known to be in the range
2471d953ebb9b04cbad6891676df597bf0c542b1ec89cerion         0 .. 31 inclusive the following seems viable:
2472d953ebb9b04cbad6891676df597bf0c542b1ec89cerion         xer.ca == 1 iff the following is nonzero:
2473d953ebb9b04cbad6891676df597bf0c542b1ec89cerion         (argL >>s 31)           -- either all 0s or all 1s
2474d953ebb9b04cbad6891676df597bf0c542b1ec89cerion         & (argL & (1<<argR)-1)  -- the stuff shifted out */
2475d953ebb9b04cbad6891676df597bf0c542b1ec89cerion      xer_ca
2476d953ebb9b04cbad6891676df597bf0c542b1ec89cerion         = binop(
2477d953ebb9b04cbad6891676df597bf0c542b1ec89cerion              Iop_And32,
2478d953ebb9b04cbad6891676df597bf0c542b1ec89cerion              binop(Iop_Sar32, argL, mkU8(31)),
2479d953ebb9b04cbad6891676df597bf0c542b1ec89cerion              binop( Iop_And32,
2480d953ebb9b04cbad6891676df597bf0c542b1ec89cerion                     argL,
2481d953ebb9b04cbad6891676df597bf0c542b1ec89cerion                     binop( Iop_Sub32,
24825b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion                            binop(Iop_Shl32, mkU32(1),
24835b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion                                             unop(Iop_32to8,argR)),
2484d953ebb9b04cbad6891676df597bf0c542b1ec89cerion                            mkU32(1) )
2485d953ebb9b04cbad6891676df597bf0c542b1ec89cerion                     )
248620ef5472eac767474c93b7835364a23f24c0ec5dsewardj              );
2487d953ebb9b04cbad6891676df597bf0c542b1ec89cerion      xer_ca
2488d953ebb9b04cbad6891676df597bf0c542b1ec89cerion         = unop(Iop_1Uto32, binop(Iop_CmpNE32, xer_ca, mkU32(0)));
2489d953ebb9b04cbad6891676df597bf0c542b1ec89cerion      break;
2490d953ebb9b04cbad6891676df597bf0c542b1ec89cerion
2491d953ebb9b04cbad6891676df597bf0c542b1ec89cerion   default:
2492d953ebb9b04cbad6891676df597bf0c542b1ec89cerion      vex_printf("set_XER_CA: op = %u\n", op);
24935b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion      vpanic("set_XER_CA(ppc)");
2494d953ebb9b04cbad6891676df597bf0c542b1ec89cerion   }
249520ef5472eac767474c93b7835364a23f24c0ec5dsewardj
2496d953ebb9b04cbad6891676df597bf0c542b1ec89cerion   /* xer_ca MUST denote either 0 or 1, no other value allowed */
2497d953ebb9b04cbad6891676df597bf0c542b1ec89cerion   putXER_CA( unop(Iop_32to8, xer_ca) );
2498d953ebb9b04cbad6891676df597bf0c542b1ec89cerion}
249920ef5472eac767474c93b7835364a23f24c0ec5dsewardj
25002831b00c4950d6c2b061def05fd67528fe132ececerionstatic void set_XER_CA_64 ( UInt op, IRExpr* res,
25012831b00c4950d6c2b061def05fd67528fe132ececerion                            IRExpr* argL, IRExpr* argR, IRExpr* oldca )
2502d953ebb9b04cbad6891676df597bf0c542b1ec89cerion{
2503d953ebb9b04cbad6891676df597bf0c542b1ec89cerion   IRExpr* xer_ca;
25045b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion   vassert(op < PPCG_FLAG_OP_NUMBER);
2505dd40fdf58cc8a6fe9466c4f00bdfc9fe9bf00449sewardj   vassert(typeOfIRExpr(irsb->tyenv,res)   == Ity_I64);
2506dd40fdf58cc8a6fe9466c4f00bdfc9fe9bf00449sewardj   vassert(typeOfIRExpr(irsb->tyenv,argL)  == Ity_I64);
2507dd40fdf58cc8a6fe9466c4f00bdfc9fe9bf00449sewardj   vassert(typeOfIRExpr(irsb->tyenv,argR)  == Ity_I64);
2508dd40fdf58cc8a6fe9466c4f00bdfc9fe9bf00449sewardj   vassert(typeOfIRExpr(irsb->tyenv,oldca) == Ity_I64);
250920ef5472eac767474c93b7835364a23f24c0ec5dsewardj
2510d953ebb9b04cbad6891676df597bf0c542b1ec89cerion   /* Incoming oldca is assumed to hold the values 0 or 1 only.  This
2511d953ebb9b04cbad6891676df597bf0c542b1ec89cerion      seems reasonable given that it's always generated by
2512d953ebb9b04cbad6891676df597bf0c542b1ec89cerion      getXER_CA32(), which masks it accordingly.  In any case it being
25137594920259781fa292dd6a3b27beb63f5875c308cerion      0 or 1 is an invariant of the ppc guest state representation;
2514d953ebb9b04cbad6891676df597bf0c542b1ec89cerion      if it has any other value, that invariant has been violated. */
2515d953ebb9b04cbad6891676df597bf0c542b1ec89cerion
2516d953ebb9b04cbad6891676df597bf0c542b1ec89cerion   switch (op) {
25175b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion   case /* 0 */ PPCG_FLAG_OP_ADD:
2518d953ebb9b04cbad6891676df597bf0c542b1ec89cerion      /* res <u argL */
2519d953ebb9b04cbad6891676df597bf0c542b1ec89cerion      xer_ca
2520f0de28cf1a762b0d6f74c93d3532c89a230673bbcerion         = unop(Iop_1Uto32, binop(Iop_CmpLT64U, res, argL));
2521d953ebb9b04cbad6891676df597bf0c542b1ec89cerion      break;
2522d953ebb9b04cbad6891676df597bf0c542b1ec89cerion
25235b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion   case /* 1 */ PPCG_FLAG_OP_ADDE:
2524d953ebb9b04cbad6891676df597bf0c542b1ec89cerion      /* res <u argL || (old_ca==1 && res==argL) */
2525d953ebb9b04cbad6891676df597bf0c542b1ec89cerion      xer_ca
2526d953ebb9b04cbad6891676df597bf0c542b1ec89cerion         = mkOR1(
2527d953ebb9b04cbad6891676df597bf0c542b1ec89cerion              binop(Iop_CmpLT64U, res, argL),
2528d953ebb9b04cbad6891676df597bf0c542b1ec89cerion              mkAND1(
2529f0de28cf1a762b0d6f74c93d3532c89a230673bbcerion                 binop(Iop_CmpEQ64, oldca, mkU64(1)),
2530d953ebb9b04cbad6891676df597bf0c542b1ec89cerion                 binop(Iop_CmpEQ64, res, argL)
2531d953ebb9b04cbad6891676df597bf0c542b1ec89cerion                 )
2532d953ebb9b04cbad6891676df597bf0c542b1ec89cerion              );
2533f0de28cf1a762b0d6f74c93d3532c89a230673bbcerion      xer_ca
2534f0de28cf1a762b0d6f74c93d3532c89a230673bbcerion         = unop(Iop_1Uto32, xer_ca);
2535d953ebb9b04cbad6891676df597bf0c542b1ec89cerion      break;
2536d953ebb9b04cbad6891676df597bf0c542b1ec89cerion
25375b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion   case /* 8 */ PPCG_FLAG_OP_SUBFE:
2538d953ebb9b04cbad6891676df597bf0c542b1ec89cerion      /* res <u argR || (old_ca==1 && res==argR) */
2539d953ebb9b04cbad6891676df597bf0c542b1ec89cerion      xer_ca
2540d953ebb9b04cbad6891676df597bf0c542b1ec89cerion         = mkOR1(
2541d953ebb9b04cbad6891676df597bf0c542b1ec89cerion              binop(Iop_CmpLT64U, res, argR),
2542d953ebb9b04cbad6891676df597bf0c542b1ec89cerion              mkAND1(
2543d953ebb9b04cbad6891676df597bf0c542b1ec89cerion                 binop(Iop_CmpEQ64, oldca, mkU64(1)),
2544d953ebb9b04cbad6891676df597bf0c542b1ec89cerion                 binop(Iop_CmpEQ64, res, argR)
2545d953ebb9b04cbad6891676df597bf0c542b1ec89cerion              )
2546d953ebb9b04cbad6891676df597bf0c542b1ec89cerion           );
2547f0de28cf1a762b0d6f74c93d3532c89a230673bbcerion      xer_ca
2548f0de28cf1a762b0d6f74c93d3532c89a230673bbcerion         = unop(Iop_1Uto32, xer_ca);
2549d953ebb9b04cbad6891676df597bf0c542b1ec89cerion      break;
2550d953ebb9b04cbad6891676df597bf0c542b1ec89cerion
25515b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion   case /* 7 */ PPCG_FLAG_OP_SUBFC:
25525b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion   case /* 9 */ PPCG_FLAG_OP_SUBFI:
2553d953ebb9b04cbad6891676df597bf0c542b1ec89cerion      /* res <=u argR */
2554d953ebb9b04cbad6891676df597bf0c542b1ec89cerion      xer_ca
2555f0de28cf1a762b0d6f74c93d3532c89a230673bbcerion         = unop(Iop_1Uto32, binop(Iop_CmpLE64U, res, argR));
2556d953ebb9b04cbad6891676df597bf0c542b1ec89cerion      break;
2557d953ebb9b04cbad6891676df597bf0c542b1ec89cerion
2558d953ebb9b04cbad6891676df597bf0c542b1ec89cerion
25595b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion   case /* 10 */ PPCG_FLAG_OP_SRAW:
2560f0de28cf1a762b0d6f74c93d3532c89a230673bbcerion      /* The shift amount is guaranteed to be in 0 .. 31 inclusive.
2561d953ebb9b04cbad6891676df597bf0c542b1ec89cerion         If it is <= 31, behave like SRAWI; else XER.CA is the sign
2562d953ebb9b04cbad6891676df597bf0c542b1ec89cerion         bit of argL. */
2563f0de28cf1a762b0d6f74c93d3532c89a230673bbcerion         /* This term valid for shift amount < 31 only */
2564f0de28cf1a762b0d6f74c93d3532c89a230673bbcerion
2565d953ebb9b04cbad6891676df597bf0c542b1ec89cerion      xer_ca
2566d953ebb9b04cbad6891676df597bf0c542b1ec89cerion         = binop(
2567f0de28cf1a762b0d6f74c93d3532c89a230673bbcerion              Iop_And64,
2568f0de28cf1a762b0d6f74c93d3532c89a230673bbcerion              binop(Iop_Sar64, argL, mkU8(31)),
2569f0de28cf1a762b0d6f74c93d3532c89a230673bbcerion              binop( Iop_And64,
2570d953ebb9b04cbad6891676df597bf0c542b1ec89cerion                     argL,
2571f0de28cf1a762b0d6f74c93d3532c89a230673bbcerion                     binop( Iop_Sub64,
25725b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion                            binop(Iop_Shl64, mkU64(1),
25735b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion                                             unop(Iop_64to8,argR)),
2574f0de28cf1a762b0d6f74c93d3532c89a230673bbcerion                            mkU64(1) )
2575d953ebb9b04cbad6891676df597bf0c542b1ec89cerion              )
2576d953ebb9b04cbad6891676df597bf0c542b1ec89cerion           );
2577d953ebb9b04cbad6891676df597bf0c542b1ec89cerion      xer_ca
257899dd03e04a6914d90d5fee727d61d76905334becflorian         = IRExpr_ITE(
2579d953ebb9b04cbad6891676df597bf0c542b1ec89cerion              /* shift amt > 31 ? */
2580009230b9758291b594e60d7c0243a73d53e81854sewardj              binop(Iop_CmpLT64U, mkU64(31), argR),
2581d953ebb9b04cbad6891676df597bf0c542b1ec89cerion              /* yes -- get sign bit of argL */
258299dd03e04a6914d90d5fee727d61d76905334becflorian              unop(Iop_64to32, binop(Iop_Shr64, argL, mkU8(63))),
258399dd03e04a6914d90d5fee727d61d76905334becflorian              /* no -- be like srawi */
258499dd03e04a6914d90d5fee727d61d76905334becflorian              unop(Iop_1Uto32, binop(Iop_CmpNE64, xer_ca, mkU64(0)))
258599dd03e04a6914d90d5fee727d61d76905334becflorian          );
2586d953ebb9b04cbad6891676df597bf0c542b1ec89cerion      break;
2587d953ebb9b04cbad6891676df597bf0c542b1ec89cerion
25885b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion   case /* 11 */ PPCG_FLAG_OP_SRAWI:
2589f0de28cf1a762b0d6f74c93d3532c89a230673bbcerion      /* xer_ca is 1 iff src was negative and bits_shifted_out != 0.
2590f0de28cf1a762b0d6f74c93d3532c89a230673bbcerion         Since the shift amount is known to be in the range 0 .. 31
2591f0de28cf1a762b0d6f74c93d3532c89a230673bbcerion         inclusive the following seems viable:
2592d953ebb9b04cbad6891676df597bf0c542b1ec89cerion         xer.ca == 1 iff the following is nonzero:
2593d953ebb9b04cbad6891676df597bf0c542b1ec89cerion         (argL >>s 31)           -- either all 0s or all 1s
2594d953ebb9b04cbad6891676df597bf0c542b1ec89cerion         & (argL & (1<<argR)-1)  -- the stuff shifted out */
2595f0de28cf1a762b0d6f74c93d3532c89a230673bbcerion
2596d953ebb9b04cbad6891676df597bf0c542b1ec89cerion      xer_ca
2597d953ebb9b04cbad6891676df597bf0c542b1ec89cerion         = binop(
2598f0de28cf1a762b0d6f74c93d3532c89a230673bbcerion              Iop_And64,
2599f0de28cf1a762b0d6f74c93d3532c89a230673bbcerion              binop(Iop_Sar64, argL, mkU8(31)),
2600f0de28cf1a762b0d6f74c93d3532c89a230673bbcerion              binop( Iop_And64,
2601d953ebb9b04cbad6891676df597bf0c542b1ec89cerion                     argL,
2602f0de28cf1a762b0d6f74c93d3532c89a230673bbcerion                     binop( Iop_Sub64,
26035b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion                            binop(Iop_Shl64, mkU64(1),
26045b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion                                             unop(Iop_64to8,argR)),
2605f0de28cf1a762b0d6f74c93d3532c89a230673bbcerion                            mkU64(1) )
2606d953ebb9b04cbad6891676df597bf0c542b1ec89cerion              )
2607d953ebb9b04cbad6891676df597bf0c542b1ec89cerion           );
2608d953ebb9b04cbad6891676df597bf0c542b1ec89cerion      xer_ca
2609f0de28cf1a762b0d6f74c93d3532c89a230673bbcerion         = unop(Iop_1Uto32, binop(Iop_CmpNE64, xer_ca, mkU64(0)));
2610d953ebb9b04cbad6891676df597bf0c542b1ec89cerion      break;
2611d953ebb9b04cbad6891676df597bf0c542b1ec89cerion
2612f0de28cf1a762b0d6f74c93d3532c89a230673bbcerion
26135b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion   case /* 12 */ PPCG_FLAG_OP_SRAD:
2614f0de28cf1a762b0d6f74c93d3532c89a230673bbcerion      /* The shift amount is guaranteed to be in 0 .. 63 inclusive.
2615f0de28cf1a762b0d6f74c93d3532c89a230673bbcerion         If it is <= 63, behave like SRADI; else XER.CA is the sign
2616f0de28cf1a762b0d6f74c93d3532c89a230673bbcerion         bit of argL. */
2617f0de28cf1a762b0d6f74c93d3532c89a230673bbcerion         /* This term valid for shift amount < 63 only */
2618f0de28cf1a762b0d6f74c93d3532c89a230673bbcerion
2619f0de28cf1a762b0d6f74c93d3532c89a230673bbcerion      xer_ca
2620f0de28cf1a762b0d6f74c93d3532c89a230673bbcerion         = binop(
2621f0de28cf1a762b0d6f74c93d3532c89a230673bbcerion              Iop_And64,
2622f0de28cf1a762b0d6f74c93d3532c89a230673bbcerion              binop(Iop_Sar64, argL, mkU8(63)),
2623f0de28cf1a762b0d6f74c93d3532c89a230673bbcerion              binop( Iop_And64,
2624f0de28cf1a762b0d6f74c93d3532c89a230673bbcerion                     argL,
2625f0de28cf1a762b0d6f74c93d3532c89a230673bbcerion                     binop( Iop_Sub64,
26265b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion                            binop(Iop_Shl64, mkU64(1),
26275b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion                                             unop(Iop_64to8,argR)),
2628f0de28cf1a762b0d6f74c93d3532c89a230673bbcerion                            mkU64(1) )
2629f0de28cf1a762b0d6f74c93d3532c89a230673bbcerion              )
2630f0de28cf1a762b0d6f74c93d3532c89a230673bbcerion           );
2631f0de28cf1a762b0d6f74c93d3532c89a230673bbcerion      xer_ca
263299dd03e04a6914d90d5fee727d61d76905334becflorian         = IRExpr_ITE(
2633f0de28cf1a762b0d6f74c93d3532c89a230673bbcerion              /* shift amt > 63 ? */
2634009230b9758291b594e60d7c0243a73d53e81854sewardj              binop(Iop_CmpLT64U, mkU64(63), argR),
2635f0de28cf1a762b0d6f74c93d3532c89a230673bbcerion              /* yes -- get sign bit of argL */
263699dd03e04a6914d90d5fee727d61d76905334becflorian              unop(Iop_64to32, binop(Iop_Shr64, argL, mkU8(63))),
263799dd03e04a6914d90d5fee727d61d76905334becflorian              /* no -- be like sradi */
263899dd03e04a6914d90d5fee727d61d76905334becflorian              unop(Iop_1Uto32, binop(Iop_CmpNE64, xer_ca, mkU64(0)))
2639f0de28cf1a762b0d6f74c93d3532c89a230673bbcerion           );
2640f0de28cf1a762b0d6f74c93d3532c89a230673bbcerion      break;
2641f0de28cf1a762b0d6f74c93d3532c89a230673bbcerion
2642f0de28cf1a762b0d6f74c93d3532c89a230673bbcerion
26435b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion   case /* 13 */ PPCG_FLAG_OP_SRADI:
2644f0de28cf1a762b0d6f74c93d3532c89a230673bbcerion      /* xer_ca is 1 iff src was negative and bits_shifted_out != 0.
2645f0de28cf1a762b0d6f74c93d3532c89a230673bbcerion         Since the shift amount is known to be in the range 0 .. 63
2646f0de28cf1a762b0d6f74c93d3532c89a230673bbcerion         inclusive, the following seems viable:
2647f0de28cf1a762b0d6f74c93d3532c89a230673bbcerion         xer.ca == 1 iff the following is nonzero:
2648f0de28cf1a762b0d6f74c93d3532c89a230673bbcerion         (argL >>s 63)           -- either all 0s or all 1s
2649f0de28cf1a762b0d6f74c93d3532c89a230673bbcerion         & (argL & (1<<argR)-1)  -- the stuff shifted out */
2650f0de28cf1a762b0d6f74c93d3532c89a230673bbcerion
2651f0de28cf1a762b0d6f74c93d3532c89a230673bbcerion      xer_ca
2652f0de28cf1a762b0d6f74c93d3532c89a230673bbcerion         = binop(
2653f0de28cf1a762b0d6f74c93d3532c89a230673bbcerion              Iop_And64,
2654f0de28cf1a762b0d6f74c93d3532c89a230673bbcerion              binop(Iop_Sar64, argL, mkU8(63)),
2655f0de28cf1a762b0d6f74c93d3532c89a230673bbcerion              binop( Iop_And64,
2656f0de28cf1a762b0d6f74c93d3532c89a230673bbcerion                     argL,
2657f0de28cf1a762b0d6f74c93d3532c89a230673bbcerion                     binop( Iop_Sub64,
26585b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion                            binop(Iop_Shl64, mkU64(1),
26595b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion                                             unop(Iop_64to8,argR)),
2660f0de28cf1a762b0d6f74c93d3532c89a230673bbcerion                            mkU64(1) )
2661f0de28cf1a762b0d6f74c93d3532c89a230673bbcerion              )
2662f0de28cf1a762b0d6f74c93d3532c89a230673bbcerion           );
2663f0de28cf1a762b0d6f74c93d3532c89a230673bbcerion      xer_ca
2664f0de28cf1a762b0d6f74c93d3532c89a230673bbcerion         = unop(Iop_1Uto32, binop(Iop_CmpNE64, xer_ca, mkU64(0)));
2665f0de28cf1a762b0d6f74c93d3532c89a230673bbcerion      break;
2666f0de28cf1a762b0d6f74c93d3532c89a230673bbcerion
2667d953ebb9b04cbad6891676df597bf0c542b1ec89cerion   default:
2668d953ebb9b04cbad6891676df597bf0c542b1ec89cerion      vex_printf("set_XER_CA: op = %u\n", op);
2669f0de28cf1a762b0d6f74c93d3532c89a230673bbcerion      vpanic("set_XER_CA(ppc64)");
267020ef5472eac767474c93b7835364a23f24c0ec5dsewardj   }
2671b51f0f4f33256638ed953156a2635aa739b232f1sewardj
267220ef5472eac767474c93b7835364a23f24c0ec5dsewardj   /* xer_ca MUST denote either 0 or 1, no other value allowed */
2673f0de28cf1a762b0d6f74c93d3532c89a230673bbcerion   putXER_CA( unop(Iop_32to8, xer_ca) );
2674d953ebb9b04cbad6891676df597bf0c542b1ec89cerion}
2675d953ebb9b04cbad6891676df597bf0c542b1ec89cerion
26762831b00c4950d6c2b061def05fd67528fe132ececerionstatic void set_XER_CA ( IRType ty, UInt op, IRExpr* res,
26772831b00c4950d6c2b061def05fd67528fe132ececerion                         IRExpr* argL, IRExpr* argR, IRExpr* oldca )
2678d953ebb9b04cbad6891676df597bf0c542b1ec89cerion{
26792831b00c4950d6c2b061def05fd67528fe132ececerion   if (ty == Ity_I32)
2680d953ebb9b04cbad6891676df597bf0c542b1ec89cerion      set_XER_CA_32( op, res, argL, argR, oldca );
2681d953ebb9b04cbad6891676df597bf0c542b1ec89cerion   else
2682d953ebb9b04cbad6891676df597bf0c542b1ec89cerion      set_XER_CA_64( op, res, argL, argR, oldca );
2683e9d361ab43518b6dfbd3d846f48859534659dee0cerion}
2684896a1373cfdbaa25f4ab73ed4f27554016defecccerion
2685896a1373cfdbaa25f4ab73ed4f27554016defecccerion
268662bec57d758aefcb5cb6265864f62fc33ad8391dcerion
2687e14bb9f862843c6b804097c124961b5567ded4f1sewardj/*------------------------------------------------------------*/
2688d953ebb9b04cbad6891676df597bf0c542b1ec89cerion/*--- Read/write to guest-state                           --- */
2689e14bb9f862843c6b804097c124961b5567ded4f1sewardj/*------------------------------------------------------------*/
2690e14bb9f862843c6b804097c124961b5567ded4f1sewardj
2691f0de28cf1a762b0d6f74c93d3532c89a230673bbcerionstatic IRExpr* /* :: Ity_I32/64 */ getGST ( PPC_GST reg )
2692d953ebb9b04cbad6891676df597bf0c542b1ec89cerion{
2693d953ebb9b04cbad6891676df597bf0c542b1ec89cerion   IRType ty = mode64 ? Ity_I64 : Ity_I32;
2694d953ebb9b04cbad6891676df597bf0c542b1ec89cerion   switch (reg) {
2695aca070a5b3418a6a9b01e3c57a7eb0fbb5050908sewardj   case PPC_GST_SPRG3_RO:
2696aca070a5b3418a6a9b01e3c57a7eb0fbb5050908sewardj      return IRExpr_Get( OFFB_SPRG3_RO, ty );
2697aca070a5b3418a6a9b01e3c57a7eb0fbb5050908sewardj
2698aca070a5b3418a6a9b01e3c57a7eb0fbb5050908sewardj   case PPC_GST_CIA:
2699aca070a5b3418a6a9b01e3c57a7eb0fbb5050908sewardj      return IRExpr_Get( OFFB_CIA, ty );
2700aca070a5b3418a6a9b01e3c57a7eb0fbb5050908sewardj
2701d953ebb9b04cbad6891676df597bf0c542b1ec89cerion   case PPC_GST_LR:
27025b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion      return IRExpr_Get( OFFB_LR, ty );
2703d953ebb9b04cbad6891676df597bf0c542b1ec89cerion
2704d953ebb9b04cbad6891676df597bf0c542b1ec89cerion   case PPC_GST_CTR:
27055b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion      return IRExpr_Get( OFFB_CTR, ty );
2706d953ebb9b04cbad6891676df597bf0c542b1ec89cerion
2707d953ebb9b04cbad6891676df597bf0c542b1ec89cerion   case PPC_GST_VRSAVE:
27085b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion      return IRExpr_Get( OFFB_VRSAVE, Ity_I32 );
2709d953ebb9b04cbad6891676df597bf0c542b1ec89cerion
2710d953ebb9b04cbad6891676df597bf0c542b1ec89cerion   case PPC_GST_VSCR:
27115b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion      return binop(Iop_And32, IRExpr_Get( OFFB_VSCR,Ity_I32 ),
27125b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion                              mkU32(MASK_VSCR_VALID));
2713d953ebb9b04cbad6891676df597bf0c542b1ec89cerion
2714d953ebb9b04cbad6891676df597bf0c542b1ec89cerion   case PPC_GST_CR: {
2715d953ebb9b04cbad6891676df597bf0c542b1ec89cerion      /* Synthesise the entire CR into a single word.  Expensive. */
2716d953ebb9b04cbad6891676df597bf0c542b1ec89cerion#     define FIELD(_n)                                               \
2717d953ebb9b04cbad6891676df597bf0c542b1ec89cerion         binop(Iop_Shl32,                                            \
2718d953ebb9b04cbad6891676df597bf0c542b1ec89cerion               unop(Iop_8Uto32,                                      \
2719d953ebb9b04cbad6891676df597bf0c542b1ec89cerion                    binop(Iop_Or8,                                   \
2720d953ebb9b04cbad6891676df597bf0c542b1ec89cerion                          binop(Iop_And8, getCR321(_n), mkU8(7<<1)), \
2721d953ebb9b04cbad6891676df597bf0c542b1ec89cerion                          binop(Iop_And8, getCR0(_n), mkU8(1))       \
2722d953ebb9b04cbad6891676df597bf0c542b1ec89cerion                    )                                                \
2723d953ebb9b04cbad6891676df597bf0c542b1ec89cerion               ),                                                    \
2724d953ebb9b04cbad6891676df597bf0c542b1ec89cerion               mkU8(4 * (7-(_n)))                                    \
2725d953ebb9b04cbad6891676df597bf0c542b1ec89cerion         )
2726d953ebb9b04cbad6891676df597bf0c542b1ec89cerion      return binop(Iop_Or32,
2727d953ebb9b04cbad6891676df597bf0c542b1ec89cerion                   binop(Iop_Or32,
2728d953ebb9b04cbad6891676df597bf0c542b1ec89cerion                         binop(Iop_Or32, FIELD(0), FIELD(1)),
2729d953ebb9b04cbad6891676df597bf0c542b1ec89cerion                         binop(Iop_Or32, FIELD(2), FIELD(3))
2730d953ebb9b04cbad6891676df597bf0c542b1ec89cerion                         ),
2731d953ebb9b04cbad6891676df597bf0c542b1ec89cerion                   binop(Iop_Or32,
2732d953ebb9b04cbad6891676df597bf0c542b1ec89cerion                         binop(Iop_Or32, FIELD(4), FIELD(5)),
2733d953ebb9b04cbad6891676df597bf0c542b1ec89cerion                         binop(Iop_Or32, FIELD(6), FIELD(7))
2734d953ebb9b04cbad6891676df597bf0c542b1ec89cerion                         )
2735d953ebb9b04cbad6891676df597bf0c542b1ec89cerion                   );
2736d953ebb9b04cbad6891676df597bf0c542b1ec89cerion#     undef FIELD
2737d953ebb9b04cbad6891676df597bf0c542b1ec89cerion   }
2738d953ebb9b04cbad6891676df597bf0c542b1ec89cerion
2739d953ebb9b04cbad6891676df597bf0c542b1ec89cerion   case PPC_GST_XER:
2740d953ebb9b04cbad6891676df597bf0c542b1ec89cerion      return binop(Iop_Or32,
2741d953ebb9b04cbad6891676df597bf0c542b1ec89cerion                   binop(Iop_Or32,
2742d953ebb9b04cbad6891676df597bf0c542b1ec89cerion                         binop( Iop_Shl32, getXER_SO32(), mkU8(31)),
2743d953ebb9b04cbad6891676df597bf0c542b1ec89cerion                         binop( Iop_Shl32, getXER_OV32(), mkU8(30))),
2744d953ebb9b04cbad6891676df597bf0c542b1ec89cerion                   binop(Iop_Or32,
2745d953ebb9b04cbad6891676df597bf0c542b1ec89cerion                         binop( Iop_Shl32, getXER_CA32(), mkU8(29)),
2746d953ebb9b04cbad6891676df597bf0c542b1ec89cerion                         getXER_BC32()));
2747d953ebb9b04cbad6891676df597bf0c542b1ec89cerion
27488943d02aa373f45c6e5fdcbe5947620285d442b1carll   case PPC_GST_TFHAR:
27498943d02aa373f45c6e5fdcbe5947620285d442b1carll      return IRExpr_Get( OFFB_TFHAR, ty );
27508943d02aa373f45c6e5fdcbe5947620285d442b1carll
27518943d02aa373f45c6e5fdcbe5947620285d442b1carll   case PPC_GST_TEXASR:
27528943d02aa373f45c6e5fdcbe5947620285d442b1carll      return IRExpr_Get( OFFB_TEXASR, ty );
27538943d02aa373f45c6e5fdcbe5947620285d442b1carll
2754486db12d4767b5c2cc5ae764616e758f30ce21f5carll   case PPC_GST_TEXASRU:
2755486db12d4767b5c2cc5ae764616e758f30ce21f5carll      return IRExpr_Get( OFFB_TEXASRU, ty );
2756486db12d4767b5c2cc5ae764616e758f30ce21f5carll
27578943d02aa373f45c6e5fdcbe5947620285d442b1carll   case PPC_GST_TFIAR:
27588943d02aa373f45c6e5fdcbe5947620285d442b1carll      return IRExpr_Get( OFFB_TFIAR, ty );
27598943d02aa373f45c6e5fdcbe5947620285d442b1carll
2760ed013fe8f56c070823d15f31ec010093f5de00dacarll   case PPC_GST_PPR:
2761ed013fe8f56c070823d15f31ec010093f5de00dacarll      return IRExpr_Get( OFFB_PPR, ty );
2762ed013fe8f56c070823d15f31ec010093f5de00dacarll
2763ed013fe8f56c070823d15f31ec010093f5de00dacarll   case PPC_GST_PPR32:
2764ed013fe8f56c070823d15f31ec010093f5de00dacarll      return unop( Iop_64HIto32, IRExpr_Get( OFFB_PPR, ty ) );
2765ed013fe8f56c070823d15f31ec010093f5de00dacarll
2766ed013fe8f56c070823d15f31ec010093f5de00dacarll   case PPC_GST_PSPB:
2767ed013fe8f56c070823d15f31ec010093f5de00dacarll      return IRExpr_Get( OFFB_PSPB, ty );
2768ed013fe8f56c070823d15f31ec010093f5de00dacarll
2769d953ebb9b04cbad6891676df597bf0c542b1ec89cerion   default:
27705b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion      vex_printf("getGST(ppc): reg = %u", reg);
27715b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion      vpanic("getGST(ppc)");
2772d953ebb9b04cbad6891676df597bf0c542b1ec89cerion   }
2773d953ebb9b04cbad6891676df597bf0c542b1ec89cerion}
2774d953ebb9b04cbad6891676df597bf0c542b1ec89cerion
2775e14bb9f862843c6b804097c124961b5567ded4f1sewardj/* Get a masked word from the given reg */
2776d953ebb9b04cbad6891676df597bf0c542b1ec89cerionstatic IRExpr* /* ::Ity_I32 */ getGST_masked ( PPC_GST reg, UInt mask )
2777e14bb9f862843c6b804097c124961b5567ded4f1sewardj{
2778e14bb9f862843c6b804097c124961b5567ded4f1sewardj   IRTemp val = newTemp(Ity_I32);
2779d953ebb9b04cbad6891676df597bf0c542b1ec89cerion   vassert( reg < PPC_GST_MAX );
2780e14bb9f862843c6b804097c124961b5567ded4f1sewardj
2781e14bb9f862843c6b804097c124961b5567ded4f1sewardj   switch (reg) {
2782e14bb9f862843c6b804097c124961b5567ded4f1sewardj
2783d953ebb9b04cbad6891676df597bf0c542b1ec89cerion   case PPC_GST_FPSCR: {
27845b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion      /* Vex-generated code expects the FPSCR to be set as follows:
278576de5cf615380b23b4b5bcced6541233cd4a93a0cerion         all exceptions masked, round-to-nearest.
278676de5cf615380b23b4b5bcced6541233cd4a93a0cerion         This corresponds to a FPSCR value of 0x0. */
2787e14bb9f862843c6b804097c124961b5567ded4f1sewardj
2788c6bbd470e9bd9898b84959227a406d3972d95f3bsewardj      /* In the lower 32 bits of FPSCR, we're only keeping track of
2789c6bbd470e9bd9898b84959227a406d3972d95f3bsewardj       * the binary floating point rounding mode, so if the mask isn't
2790c6bbd470e9bd9898b84959227a406d3972d95f3bsewardj       * asking for this, just return 0x0.
2791c6bbd470e9bd9898b84959227a406d3972d95f3bsewardj       */
2792c6bbd470e9bd9898b84959227a406d3972d95f3bsewardj      if (mask & MASK_FPSCR_RN) {
2793c6bbd470e9bd9898b84959227a406d3972d95f3bsewardj         assign( val, unop( Iop_8Uto32, IRExpr_Get( OFFB_FPROUND, Ity_I8 ) ) );
2794e14bb9f862843c6b804097c124961b5567ded4f1sewardj      } else {
2795e14bb9f862843c6b804097c124961b5567ded4f1sewardj         assign( val, mkU32(0x0) );
2796e14bb9f862843c6b804097c124961b5567ded4f1sewardj      }
2797225a034683024109da729a4d2f080364b9485007cerion      break;
2798edf7fc572e2decb93e9143961e8739c8fe18899dcerion   }
2799e14bb9f862843c6b804097c124961b5567ded4f1sewardj
2800e14bb9f862843c6b804097c124961b5567ded4f1sewardj   default:
28015b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion      vex_printf("getGST_masked(ppc): reg = %u", reg);
28025b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion      vpanic("getGST_masked(ppc)");
2803e14bb9f862843c6b804097c124961b5567ded4f1sewardj   }
2804e14bb9f862843c6b804097c124961b5567ded4f1sewardj
2805e14bb9f862843c6b804097c124961b5567ded4f1sewardj   if (mask != 0xFFFFFFFF) {
2806e14bb9f862843c6b804097c124961b5567ded4f1sewardj      return binop(Iop_And32, mkexpr(val), mkU32(mask));
2807e14bb9f862843c6b804097c124961b5567ded4f1sewardj   } else {
2808e14bb9f862843c6b804097c124961b5567ded4f1sewardj      return mkexpr(val);
2809e14bb9f862843c6b804097c124961b5567ded4f1sewardj   }
2810e14bb9f862843c6b804097c124961b5567ded4f1sewardj}
2811e14bb9f862843c6b804097c124961b5567ded4f1sewardj
2812c6bbd470e9bd9898b84959227a406d3972d95f3bsewardj/* Get a masked word from the given reg */
2813c6bbd470e9bd9898b84959227a406d3972d95f3bsewardjstatic IRExpr* /* ::Ity_I32 */getGST_masked_upper(PPC_GST reg, ULong mask) {
2814c6bbd470e9bd9898b84959227a406d3972d95f3bsewardj   IRExpr * val;
2815c6bbd470e9bd9898b84959227a406d3972d95f3bsewardj   vassert( reg < PPC_GST_MAX );
2816c6bbd470e9bd9898b84959227a406d3972d95f3bsewardj
2817c6bbd470e9bd9898b84959227a406d3972d95f3bsewardj   switch (reg) {
2818c6bbd470e9bd9898b84959227a406d3972d95f3bsewardj
2819c6bbd470e9bd9898b84959227a406d3972d95f3bsewardj   case PPC_GST_FPSCR: {
2820c6bbd470e9bd9898b84959227a406d3972d95f3bsewardj      /* In the upper 32 bits of FPSCR, we're only keeping track
2821c6bbd470e9bd9898b84959227a406d3972d95f3bsewardj       * of the decimal floating point rounding mode, so if the mask
2822c6bbd470e9bd9898b84959227a406d3972d95f3bsewardj       * isn't asking for this, just return 0x0.
2823c6bbd470e9bd9898b84959227a406d3972d95f3bsewardj       */
2824c6bbd470e9bd9898b84959227a406d3972d95f3bsewardj      if (mask & MASK_FPSCR_DRN) {
2825c6bbd470e9bd9898b84959227a406d3972d95f3bsewardj         val = binop( Iop_And32,
2826c6bbd470e9bd9898b84959227a406d3972d95f3bsewardj                      unop( Iop_8Uto32, IRExpr_Get( OFFB_DFPROUND, Ity_I8 ) ),
2827c6bbd470e9bd9898b84959227a406d3972d95f3bsewardj                      unop( Iop_64HIto32, mkU64( mask ) ) );
2828c6bbd470e9bd9898b84959227a406d3972d95f3bsewardj      } else {
2829c6bbd470e9bd9898b84959227a406d3972d95f3bsewardj         val = mkU32( 0x0ULL );
2830c6bbd470e9bd9898b84959227a406d3972d95f3bsewardj      }
2831c6bbd470e9bd9898b84959227a406d3972d95f3bsewardj      break;
2832c6bbd470e9bd9898b84959227a406d3972d95f3bsewardj   }
2833c6bbd470e9bd9898b84959227a406d3972d95f3bsewardj
2834c6bbd470e9bd9898b84959227a406d3972d95f3bsewardj   default:
2835c6bbd470e9bd9898b84959227a406d3972d95f3bsewardj      vex_printf( "getGST_masked_upper(ppc): reg = %u", reg );
2836c6bbd470e9bd9898b84959227a406d3972d95f3bsewardj      vpanic( "getGST_masked_upper(ppc)" );
2837c6bbd470e9bd9898b84959227a406d3972d95f3bsewardj   }
2838c6bbd470e9bd9898b84959227a406d3972d95f3bsewardj   return val;
2839c6bbd470e9bd9898b84959227a406d3972d95f3bsewardj}
2840c6bbd470e9bd9898b84959227a406d3972d95f3bsewardj
2841c6bbd470e9bd9898b84959227a406d3972d95f3bsewardj
2842edf7fc572e2decb93e9143961e8739c8fe18899dcerion/* Fetch the specified REG[FLD] nibble (as per IBM/hardware notation)
2843edf7fc572e2decb93e9143961e8739c8fe18899dcerion   and return it at the bottom of an I32; the top 27 bits are
2844edf7fc572e2decb93e9143961e8739c8fe18899dcerion   guaranteed to be zero. */
2845d953ebb9b04cbad6891676df597bf0c542b1ec89cerionstatic IRExpr* /* ::Ity_I32 */ getGST_field ( PPC_GST reg, UInt fld )
2846edf7fc572e2decb93e9143961e8739c8fe18899dcerion{
284741a7b70f888cf73cf3da6a53b31937ce0d26e8f4sewardj   UInt shft, mask;
284841a7b70f888cf73cf3da6a53b31937ce0d26e8f4sewardj
2849edf7fc572e2decb93e9143961e8739c8fe18899dcerion   vassert( fld < 8 );
2850d953ebb9b04cbad6891676df597bf0c542b1ec89cerion   vassert( reg < PPC_GST_MAX );
2851edf7fc572e2decb93e9143961e8739c8fe18899dcerion
285241a7b70f888cf73cf3da6a53b31937ce0d26e8f4sewardj   shft = 4*(7-fld);
285341a7b70f888cf73cf3da6a53b31937ce0d26e8f4sewardj   mask = 0xF<<shft;
2854e14bb9f862843c6b804097c124961b5567ded4f1sewardj
2855edf7fc572e2decb93e9143961e8739c8fe18899dcerion   switch (reg) {
2856d953ebb9b04cbad6891676df597bf0c542b1ec89cerion   case PPC_GST_XER:
2857edf7fc572e2decb93e9143961e8739c8fe18899dcerion      vassert(fld ==7);
2858edf7fc572e2decb93e9143961e8739c8fe18899dcerion      return binop(Iop_Or32,
2859edf7fc572e2decb93e9143961e8739c8fe18899dcerion                   binop(Iop_Or32,
2860edf7fc572e2decb93e9143961e8739c8fe18899dcerion                         binop(Iop_Shl32, getXER_SO32(), mkU8(3)),
2861edf7fc572e2decb93e9143961e8739c8fe18899dcerion                         binop(Iop_Shl32, getXER_OV32(), mkU8(2))),
2862edf7fc572e2decb93e9143961e8739c8fe18899dcerion                   binop(      Iop_Shl32, getXER_CA32(), mkU8(1)));
2863edf7fc572e2decb93e9143961e8739c8fe18899dcerion      break;
2864e14bb9f862843c6b804097c124961b5567ded4f1sewardj
2865edf7fc572e2decb93e9143961e8739c8fe18899dcerion   default:
2866edf7fc572e2decb93e9143961e8739c8fe18899dcerion      if (shft == 0)
2867d953ebb9b04cbad6891676df597bf0c542b1ec89cerion         return getGST_masked( reg, mask );
2868edf7fc572e2decb93e9143961e8739c8fe18899dcerion      else
2869edf7fc572e2decb93e9143961e8739c8fe18899dcerion         return binop(Iop_Shr32,
2870d953ebb9b04cbad6891676df597bf0c542b1ec89cerion                      getGST_masked( reg, mask ),
2871edf7fc572e2decb93e9143961e8739c8fe18899dcerion                      mkU8(toUChar( shft )));
2872edf7fc572e2decb93e9143961e8739c8fe18899dcerion   }
2873edf7fc572e2decb93e9143961e8739c8fe18899dcerion}
2874edf7fc572e2decb93e9143961e8739c8fe18899dcerion
2875d953ebb9b04cbad6891676df597bf0c542b1ec89cerionstatic void putGST ( PPC_GST reg, IRExpr* src )
2876edf7fc572e2decb93e9143961e8739c8fe18899dcerion{
28775b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion   IRType ty     = mode64 ? Ity_I64 : Ity_I32;
2878dd40fdf58cc8a6fe9466c4f00bdfc9fe9bf00449sewardj   IRType ty_src = typeOfIRExpr(irsb->tyenv,src );
2879d953ebb9b04cbad6891676df597bf0c542b1ec89cerion   vassert( reg < PPC_GST_MAX );
2880edf7fc572e2decb93e9143961e8739c8fe18899dcerion   switch (reg) {
2881e86310f555a233cc2ca02e1a5d0adb555f12bdcdsewardj   case PPC_GST_IP_AT_SYSCALL:
2882aca070a5b3418a6a9b01e3c57a7eb0fbb5050908sewardj      vassert( ty_src == ty );
2883e86310f555a233cc2ca02e1a5d0adb555f12bdcdsewardj      stmt( IRStmt_Put( OFFB_IP_AT_SYSCALL, src ) );
2884aca070a5b3418a6a9b01e3c57a7eb0fbb5050908sewardj      break;
2885d953ebb9b04cbad6891676df597bf0c542b1ec89cerion   case PPC_GST_CIA:
28865b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion      vassert( ty_src == ty );
28875b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion      stmt( IRStmt_Put( OFFB_CIA, src ) );
2888d953ebb9b04cbad6891676df597bf0c542b1ec89cerion      break;
2889d953ebb9b04cbad6891676df597bf0c542b1ec89cerion   case PPC_GST_LR:
28905b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion      vassert( ty_src == ty );
28915b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion      stmt( IRStmt_Put( OFFB_LR, src ) );
2892d953ebb9b04cbad6891676df597bf0c542b1ec89cerion      break;
2893d953ebb9b04cbad6891676df597bf0c542b1ec89cerion   case PPC_GST_CTR:
28945b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion      vassert( ty_src == ty );
28955b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion      stmt( IRStmt_Put( OFFB_CTR, src ) );
2896d953ebb9b04cbad6891676df597bf0c542b1ec89cerion      break;
2897d953ebb9b04cbad6891676df597bf0c542b1ec89cerion   case PPC_GST_VRSAVE:
28985b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion      vassert( ty_src == Ity_I32 );
28995b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion      stmt( IRStmt_Put( OFFB_VRSAVE,src));
2900d953ebb9b04cbad6891676df597bf0c542b1ec89cerion      break;
2901d953ebb9b04cbad6891676df597bf0c542b1ec89cerion   case PPC_GST_VSCR:
29025b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion      vassert( ty_src == Ity_I32 );
29035b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion      stmt( IRStmt_Put( OFFB_VSCR,
2904d953ebb9b04cbad6891676df597bf0c542b1ec89cerion                        binop(Iop_And32, src,
2905d953ebb9b04cbad6891676df597bf0c542b1ec89cerion                              mkU32(MASK_VSCR_VALID)) ) );
2906d953ebb9b04cbad6891676df597bf0c542b1ec89cerion      break;
2907d953ebb9b04cbad6891676df597bf0c542b1ec89cerion   case PPC_GST_XER:
29085b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion      vassert( ty_src == Ity_I32 );
2909d953ebb9b04cbad6891676df597bf0c542b1ec89cerion      putXER_SO( unop(Iop_32to8, binop(Iop_Shr32, src, mkU8(31))) );
2910d953ebb9b04cbad6891676df597bf0c542b1ec89cerion      putXER_OV( unop(Iop_32to8, binop(Iop_Shr32, src, mkU8(30))) );
2911d953ebb9b04cbad6891676df597bf0c542b1ec89cerion      putXER_CA( unop(Iop_32to8, binop(Iop_Shr32, src, mkU8(29))) );
2912d953ebb9b04cbad6891676df597bf0c542b1ec89cerion      putXER_BC( unop(Iop_32to8, src) );
2913d953ebb9b04cbad6891676df597bf0c542b1ec89cerion      break;
2914d953ebb9b04cbad6891676df597bf0c542b1ec89cerion
2915d953ebb9b04cbad6891676df597bf0c542b1ec89cerion   case PPC_GST_EMWARN:
29165b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion      vassert( ty_src == Ity_I32 );
29176ef84bed9bb3af22060eb1759788034602bbcc88florian      stmt( IRStmt_Put( OFFB_EMNOTE,src) );
2918d953ebb9b04cbad6891676df597bf0c542b1ec89cerion      break;
2919d953ebb9b04cbad6891676df597bf0c542b1ec89cerion
292005f5e0172384dd2983fb16fbb7deebd74d71cd35sewardj   case PPC_GST_CMSTART:
29215b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion      vassert( ty_src == ty );
292205f5e0172384dd2983fb16fbb7deebd74d71cd35sewardj      stmt( IRStmt_Put( OFFB_CMSTART, src) );
2923d953ebb9b04cbad6891676df597bf0c542b1ec89cerion      break;
2924d953ebb9b04cbad6891676df597bf0c542b1ec89cerion
292505f5e0172384dd2983fb16fbb7deebd74d71cd35sewardj   case PPC_GST_CMLEN:
29265b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion      vassert( ty_src == ty );
292705f5e0172384dd2983fb16fbb7deebd74d71cd35sewardj      stmt( IRStmt_Put( OFFB_CMLEN, src) );
2928d953ebb9b04cbad6891676df597bf0c542b1ec89cerion      break;
2929d953ebb9b04cbad6891676df597bf0c542b1ec89cerion
29308943d02aa373f45c6e5fdcbe5947620285d442b1carll   case PPC_GST_TEXASR:
29318943d02aa373f45c6e5fdcbe5947620285d442b1carll      vassert( ty_src == Ity_I64 );
29328943d02aa373f45c6e5fdcbe5947620285d442b1carll      stmt( IRStmt_Put( OFFB_TEXASR, src ) );
29338943d02aa373f45c6e5fdcbe5947620285d442b1carll      break;
2934486db12d4767b5c2cc5ae764616e758f30ce21f5carll
2935486db12d4767b5c2cc5ae764616e758f30ce21f5carll   case PPC_GST_TEXASRU:
2936486db12d4767b5c2cc5ae764616e758f30ce21f5carll      vassert( ty_src == Ity_I32 );
2937486db12d4767b5c2cc5ae764616e758f30ce21f5carll      stmt( IRStmt_Put( OFFB_TEXASRU, src ) );
2938486db12d4767b5c2cc5ae764616e758f30ce21f5carll      break;
2939486db12d4767b5c2cc5ae764616e758f30ce21f5carll
29408943d02aa373f45c6e5fdcbe5947620285d442b1carll   case PPC_GST_TFIAR:
29418943d02aa373f45c6e5fdcbe5947620285d442b1carll      vassert( ty_src == Ity_I64 );
29428943d02aa373f45c6e5fdcbe5947620285d442b1carll      stmt( IRStmt_Put( OFFB_TFIAR, src ) );
29438943d02aa373f45c6e5fdcbe5947620285d442b1carll      break;
29448943d02aa373f45c6e5fdcbe5947620285d442b1carll   case PPC_GST_TFHAR:
29458943d02aa373f45c6e5fdcbe5947620285d442b1carll      vassert( ty_src == Ity_I64 );
29468943d02aa373f45c6e5fdcbe5947620285d442b1carll      stmt( IRStmt_Put( OFFB_TFHAR, src ) );
29478943d02aa373f45c6e5fdcbe5947620285d442b1carll      break;
2948ed013fe8f56c070823d15f31ec010093f5de00dacarll
2949ed013fe8f56c070823d15f31ec010093f5de00dacarll   case PPC_GST_PPR32:
2950ed013fe8f56c070823d15f31ec010093f5de00dacarll   case PPC_GST_PPR:
2951ed013fe8f56c070823d15f31ec010093f5de00dacarll      {
2952ed013fe8f56c070823d15f31ec010093f5de00dacarll         /* The Program Priority Register (PPR) stores the priority in
2953ed013fe8f56c070823d15f31ec010093f5de00dacarll          * bits [52:50].  The user setable priorities are:
2954ed013fe8f56c070823d15f31ec010093f5de00dacarll          *
2955ed013fe8f56c070823d15f31ec010093f5de00dacarll          *    001  very low
2956ed013fe8f56c070823d15f31ec010093f5de00dacarll          *    010  low
2957ed013fe8f56c070823d15f31ec010093f5de00dacarll          *    011  medium low
2958ed013fe8f56c070823d15f31ec010093f5de00dacarll          *    100  medium
2959ed013fe8f56c070823d15f31ec010093f5de00dacarll          *    101  medium high
2960ed013fe8f56c070823d15f31ec010093f5de00dacarll          *
2961ed013fe8f56c070823d15f31ec010093f5de00dacarll          * If the argument is not between 0b001 and 0b100 the priority is set
2962ed013fe8f56c070823d15f31ec010093f5de00dacarll          * to 0b100.  The priority can only be set to 0b101 if the the Problem
2963ed013fe8f56c070823d15f31ec010093f5de00dacarll          * State Boost Register is non-zero.  The value of the PPR is not
2964ed013fe8f56c070823d15f31ec010093f5de00dacarll          * changed if the input is not valid.
2965ed013fe8f56c070823d15f31ec010093f5de00dacarll          */
2966ed013fe8f56c070823d15f31ec010093f5de00dacarll
2967ed013fe8f56c070823d15f31ec010093f5de00dacarll         IRTemp not_valid = newTemp(Ity_I64);
2968ed013fe8f56c070823d15f31ec010093f5de00dacarll         IRTemp has_perm = newTemp(Ity_I64);
2969ed013fe8f56c070823d15f31ec010093f5de00dacarll         IRTemp new_src  = newTemp(Ity_I64);
2970ed013fe8f56c070823d15f31ec010093f5de00dacarll         IRTemp PSPB_val = newTemp(Ity_I64);
2971ed013fe8f56c070823d15f31ec010093f5de00dacarll         IRTemp value    = newTemp(Ity_I64);
2972ed013fe8f56c070823d15f31ec010093f5de00dacarll
2973ed013fe8f56c070823d15f31ec010093f5de00dacarll         vassert(( ty_src == Ity_I64 ) || ( ty_src == Ity_I32 ));
2974ed013fe8f56c070823d15f31ec010093f5de00dacarll         assign( PSPB_val, binop( Iop_32HLto64,
2975ed013fe8f56c070823d15f31ec010093f5de00dacarll                                  mkU32( 0 ),
2976ed013fe8f56c070823d15f31ec010093f5de00dacarll                                  IRExpr_Get( OFFB_PSPB, Ity_I32 ) ) );
2977ed013fe8f56c070823d15f31ec010093f5de00dacarll         if( reg == PPC_GST_PPR32 ) {
2978ed013fe8f56c070823d15f31ec010093f5de00dacarll            vassert( ty_src == Ity_I32 );
2979ed013fe8f56c070823d15f31ec010093f5de00dacarll            assign( value, binop( Iop_32HLto64,
2980ed013fe8f56c070823d15f31ec010093f5de00dacarll                                  mkU32(0),
2981ed013fe8f56c070823d15f31ec010093f5de00dacarll                                  binop( Iop_And32,
2982ed013fe8f56c070823d15f31ec010093f5de00dacarll                                         binop( Iop_Shr32, src,  mkU8( 18 ) ),
2983ed013fe8f56c070823d15f31ec010093f5de00dacarll                                         mkU32( 0x7 ) ) ) );
2984ed013fe8f56c070823d15f31ec010093f5de00dacarll         } else {
2985ed013fe8f56c070823d15f31ec010093f5de00dacarll            vassert( ty_src == Ity_I64 );
2986ed013fe8f56c070823d15f31ec010093f5de00dacarll            assign( value, binop( Iop_And64,
2987ed013fe8f56c070823d15f31ec010093f5de00dacarll                                  binop( Iop_Shr64, src,  mkU8( 50 ) ),
2988ed013fe8f56c070823d15f31ec010093f5de00dacarll                                  mkU64( 0x7 ) ) );
2989ed013fe8f56c070823d15f31ec010093f5de00dacarll         }
2990ed013fe8f56c070823d15f31ec010093f5de00dacarll         assign( has_perm,
2991ed013fe8f56c070823d15f31ec010093f5de00dacarll                 binop( Iop_And64,
2992ed013fe8f56c070823d15f31ec010093f5de00dacarll                        unop( Iop_1Sto64,
2993ed013fe8f56c070823d15f31ec010093f5de00dacarll                              binop( Iop_CmpEQ64,
2994ed013fe8f56c070823d15f31ec010093f5de00dacarll                                     mkexpr( PSPB_val ),
2995ed013fe8f56c070823d15f31ec010093f5de00dacarll                                     mkU64( 0 ) ) ),
2996ed013fe8f56c070823d15f31ec010093f5de00dacarll                        unop( Iop_1Sto64,
2997ed013fe8f56c070823d15f31ec010093f5de00dacarll                              binop( Iop_CmpEQ64,
2998ed013fe8f56c070823d15f31ec010093f5de00dacarll                                     mkU64( 0x5 ),
2999ed013fe8f56c070823d15f31ec010093f5de00dacarll                                     mkexpr( value ) ) ) ) );
3000ed013fe8f56c070823d15f31ec010093f5de00dacarll         assign( not_valid,
3001ed013fe8f56c070823d15f31ec010093f5de00dacarll                 binop( Iop_Or64,
3002ed013fe8f56c070823d15f31ec010093f5de00dacarll                        unop( Iop_1Sto64,
3003ed013fe8f56c070823d15f31ec010093f5de00dacarll                              binop( Iop_CmpEQ64,
3004ed013fe8f56c070823d15f31ec010093f5de00dacarll                                     mkexpr( value ),
3005ed013fe8f56c070823d15f31ec010093f5de00dacarll                                     mkU64( 0 ) ) ),
3006ed013fe8f56c070823d15f31ec010093f5de00dacarll                        unop( Iop_1Sto64,
3007ed013fe8f56c070823d15f31ec010093f5de00dacarll                              binop( Iop_CmpLT64U,
3008ed013fe8f56c070823d15f31ec010093f5de00dacarll                                     mkU64( 0x5 ),
3009ed013fe8f56c070823d15f31ec010093f5de00dacarll                                     mkexpr( value ) ) ) ) );
3010ed013fe8f56c070823d15f31ec010093f5de00dacarll         assign( new_src,
3011ed013fe8f56c070823d15f31ec010093f5de00dacarll                 binop( Iop_Or64,
3012ed013fe8f56c070823d15f31ec010093f5de00dacarll                        binop( Iop_And64,
3013ed013fe8f56c070823d15f31ec010093f5de00dacarll                               unop( Iop_Not64,
3014ed013fe8f56c070823d15f31ec010093f5de00dacarll                                     mkexpr( not_valid ) ),
3015ed013fe8f56c070823d15f31ec010093f5de00dacarll                               src ),
3016ed013fe8f56c070823d15f31ec010093f5de00dacarll                        binop( Iop_And64,
3017ed013fe8f56c070823d15f31ec010093f5de00dacarll                               mkexpr( not_valid ),
3018ed013fe8f56c070823d15f31ec010093f5de00dacarll                               binop( Iop_Or64,
3019ed013fe8f56c070823d15f31ec010093f5de00dacarll                                      binop( Iop_And64,
3020ed013fe8f56c070823d15f31ec010093f5de00dacarll                                             mkexpr( has_perm),
3021ed013fe8f56c070823d15f31ec010093f5de00dacarll                                             binop( Iop_Shl64,
3022ed013fe8f56c070823d15f31ec010093f5de00dacarll                                                    mkexpr( value ),
3023ed013fe8f56c070823d15f31ec010093f5de00dacarll                                                    mkU8( 50 ) ) ),
3024ed013fe8f56c070823d15f31ec010093f5de00dacarll                                      binop( Iop_And64,
3025ed013fe8f56c070823d15f31ec010093f5de00dacarll                                             IRExpr_Get( OFFB_PPR, ty ),
3026ed013fe8f56c070823d15f31ec010093f5de00dacarll                                             unop( Iop_Not64,
3027ed013fe8f56c070823d15f31ec010093f5de00dacarll                                                   mkexpr( has_perm )
3028ed013fe8f56c070823d15f31ec010093f5de00dacarll                                                   ) ) ) ) ) );
3029ed013fe8f56c070823d15f31ec010093f5de00dacarll
3030ed013fe8f56c070823d15f31ec010093f5de00dacarll                 /* make sure we only set the valid bit field [52:50] */
3031ed013fe8f56c070823d15f31ec010093f5de00dacarll                 stmt( IRStmt_Put( OFFB_PPR,
3032ed013fe8f56c070823d15f31ec010093f5de00dacarll                                   binop( Iop_And64,
3033ed013fe8f56c070823d15f31ec010093f5de00dacarll                                          mkexpr( new_src ),
3034ed013fe8f56c070823d15f31ec010093f5de00dacarll                                          mkU64( 0x1C000000000000) ) ) );
3035ed013fe8f56c070823d15f31ec010093f5de00dacarll      break;
3036ed013fe8f56c070823d15f31ec010093f5de00dacarll      }
3037edf7fc572e2decb93e9143961e8739c8fe18899dcerion   default:
30385b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion      vex_printf("putGST(ppc): reg = %u", reg);
30395b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion      vpanic("putGST(ppc)");
3040edf7fc572e2decb93e9143961e8739c8fe18899dcerion   }
3041edf7fc572e2decb93e9143961e8739c8fe18899dcerion}
3042e14bb9f862843c6b804097c124961b5567ded4f1sewardj
3043e14bb9f862843c6b804097c124961b5567ded4f1sewardj/* Write masked src to the given reg */
3044c6bbd470e9bd9898b84959227a406d3972d95f3bsewardjstatic void putGST_masked ( PPC_GST reg, IRExpr* src, ULong mask )
3045e14bb9f862843c6b804097c124961b5567ded4f1sewardj{
3046d953ebb9b04cbad6891676df597bf0c542b1ec89cerion   IRType ty = mode64 ? Ity_I64 : Ity_I32;
3047d953ebb9b04cbad6891676df597bf0c542b1ec89cerion   vassert( reg < PPC_GST_MAX );
3048c6bbd470e9bd9898b84959227a406d3972d95f3bsewardj   vassert( typeOfIRExpr( irsb->tyenv,src ) == Ity_I64 );
3049c6bbd470e9bd9898b84959227a406d3972d95f3bsewardj
3050e14bb9f862843c6b804097c124961b5567ded4f1sewardj   switch (reg) {
3051d953ebb9b04cbad6891676df597bf0c542b1ec89cerion   case PPC_GST_FPSCR: {
3052c6bbd470e9bd9898b84959227a406d3972d95f3bsewardj      /* Allow writes to either binary or decimal floating point
3053150794d0aae744f36797e7727cfbbfc44a980bb5sewardj         Rounding Mode.
3054150794d0aae744f36797e7727cfbbfc44a980bb5sewardj      */
3055150794d0aae744f36797e7727cfbbfc44a980bb5sewardj      /* If any part of |mask| covers FPSCR.RN, update the bits of
3056150794d0aae744f36797e7727cfbbfc44a980bb5sewardj         FPSCR.RN by copying in |src| for locations where the
3057150794d0aae744f36797e7727cfbbfc44a980bb5sewardj         corresponding bit in |mask| is 1, and leaving it unchanged
3058150794d0aae744f36797e7727cfbbfc44a980bb5sewardj         for corresponding |mask| zero bits. */
3059c6bbd470e9bd9898b84959227a406d3972d95f3bsewardj      if (mask & MASK_FPSCR_RN) {
3060150794d0aae744f36797e7727cfbbfc44a980bb5sewardj         stmt(
3061150794d0aae744f36797e7727cfbbfc44a980bb5sewardj            IRStmt_Put(
3062150794d0aae744f36797e7727cfbbfc44a980bb5sewardj               OFFB_FPROUND,
3063150794d0aae744f36797e7727cfbbfc44a980bb5sewardj               unop(
3064150794d0aae744f36797e7727cfbbfc44a980bb5sewardj                  Iop_32to8,
3065150794d0aae744f36797e7727cfbbfc44a980bb5sewardj                  binop(
3066150794d0aae744f36797e7727cfbbfc44a980bb5sewardj                     Iop_Or32,
3067150794d0aae744f36797e7727cfbbfc44a980bb5sewardj                     binop(
3068150794d0aae744f36797e7727cfbbfc44a980bb5sewardj                        Iop_And32,
3069150794d0aae744f36797e7727cfbbfc44a980bb5sewardj                        unop(Iop_64to32, src),
3070150794d0aae744f36797e7727cfbbfc44a980bb5sewardj                        mkU32(MASK_FPSCR_RN & mask)
3071150794d0aae744f36797e7727cfbbfc44a980bb5sewardj                     ),
3072150794d0aae744f36797e7727cfbbfc44a980bb5sewardj                     binop(
3073150794d0aae744f36797e7727cfbbfc44a980bb5sewardj                        Iop_And32,
3074150794d0aae744f36797e7727cfbbfc44a980bb5sewardj                        unop(Iop_8Uto32, IRExpr_Get(OFFB_FPROUND,Ity_I8)),
3075150794d0aae744f36797e7727cfbbfc44a980bb5sewardj                        mkU32(MASK_FPSCR_RN & ~mask)
3076150794d0aae744f36797e7727cfbbfc44a980bb5sewardj                     )
3077150794d0aae744f36797e7727cfbbfc44a980bb5sewardj                  )
3078150794d0aae744f36797e7727cfbbfc44a980bb5sewardj               )
3079150794d0aae744f36797e7727cfbbfc44a980bb5sewardj            )
3080150794d0aae744f36797e7727cfbbfc44a980bb5sewardj         );
3081150794d0aae744f36797e7727cfbbfc44a980bb5sewardj      }
3082150794d0aae744f36797e7727cfbbfc44a980bb5sewardj      /* Similarly, update FPSCR.DRN if any bits of |mask|
3083150794d0aae744f36797e7727cfbbfc44a980bb5sewardj         corresponding to FPSCR.DRN are set. */
3084150794d0aae744f36797e7727cfbbfc44a980bb5sewardj      if (mask & MASK_FPSCR_DRN) {
3085150794d0aae744f36797e7727cfbbfc44a980bb5sewardj         stmt(
3086150794d0aae744f36797e7727cfbbfc44a980bb5sewardj            IRStmt_Put(
3087150794d0aae744f36797e7727cfbbfc44a980bb5sewardj               OFFB_DFPROUND,
3088150794d0aae744f36797e7727cfbbfc44a980bb5sewardj               unop(
3089150794d0aae744f36797e7727cfbbfc44a980bb5sewardj                  Iop_32to8,
3090150794d0aae744f36797e7727cfbbfc44a980bb5sewardj                  binop(
3091150794d0aae744f36797e7727cfbbfc44a980bb5sewardj                     Iop_Or32,
3092150794d0aae744f36797e7727cfbbfc44a980bb5sewardj                     binop(
3093150794d0aae744f36797e7727cfbbfc44a980bb5sewardj                        Iop_And32,
3094150794d0aae744f36797e7727cfbbfc44a980bb5sewardj                        unop(Iop_64HIto32, src),
3095150794d0aae744f36797e7727cfbbfc44a980bb5sewardj                        mkU32((MASK_FPSCR_DRN & mask) >> 32)
3096150794d0aae744f36797e7727cfbbfc44a980bb5sewardj                     ),
3097150794d0aae744f36797e7727cfbbfc44a980bb5sewardj                     binop(
3098150794d0aae744f36797e7727cfbbfc44a980bb5sewardj                        Iop_And32,
3099150794d0aae744f36797e7727cfbbfc44a980bb5sewardj                        unop(Iop_8Uto32, IRExpr_Get(OFFB_DFPROUND,Ity_I8)),
3100150794d0aae744f36797e7727cfbbfc44a980bb5sewardj                        mkU32((MASK_FPSCR_DRN & ~mask) >> 32)
3101150794d0aae744f36797e7727cfbbfc44a980bb5sewardj                     )
3102150794d0aae744f36797e7727cfbbfc44a980bb5sewardj                  )
3103150794d0aae744f36797e7727cfbbfc44a980bb5sewardj               )
3104150794d0aae744f36797e7727cfbbfc44a980bb5sewardj            )
3105150794d0aae744f36797e7727cfbbfc44a980bb5sewardj         );
3106e14bb9f862843c6b804097c124961b5567ded4f1sewardj      }
3107e14bb9f862843c6b804097c124961b5567ded4f1sewardj
31086ef84bed9bb3af22060eb1759788034602bbcc88florian      /* Give EmNote for attempted writes to:
3109e14bb9f862843c6b804097c124961b5567ded4f1sewardj         - Exception Controls
3110e14bb9f862843c6b804097c124961b5567ded4f1sewardj         - Non-IEEE Mode
3111e14bb9f862843c6b804097c124961b5567ded4f1sewardj      */
3112e14bb9f862843c6b804097c124961b5567ded4f1sewardj      if (mask & 0xFC) {  // Exception Control, Non-IEE mode
31136ef84bed9bb3af22060eb1759788034602bbcc88florian         VexEmNote ew = EmWarn_PPCexns;
3114e14bb9f862843c6b804097c124961b5567ded4f1sewardj
3115e14bb9f862843c6b804097c124961b5567ded4f1sewardj         /* If any of the src::exception_control bits are actually set,
3116e14bb9f862843c6b804097c124961b5567ded4f1sewardj            side-exit to the next insn, reporting the warning,
3117e14bb9f862843c6b804097c124961b5567ded4f1sewardj            so that Valgrind's dispatcher sees the warning. */
3118d953ebb9b04cbad6891676df597bf0c542b1ec89cerion         putGST( PPC_GST_EMWARN, mkU32(ew) );
3119e14bb9f862843c6b804097c124961b5567ded4f1sewardj         stmt(
3120e14bb9f862843c6b804097c124961b5567ded4f1sewardj            IRStmt_Exit(
31216ef84bed9bb3af22060eb1759788034602bbcc88florian               binop(Iop_CmpNE32, mkU32(ew), mkU32(EmNote_NONE)),
3122e14bb9f862843c6b804097c124961b5567ded4f1sewardj               Ijk_EmWarn,
31233dee849ec7c38746749065e67dc53b75daa7617dsewardj               mkSzConst( ty, nextInsnAddr()), OFFB_CIA ));
3124e14bb9f862843c6b804097c124961b5567ded4f1sewardj      }
3125e14bb9f862843c6b804097c124961b5567ded4f1sewardj
3126edf7fc572e2decb93e9143961e8739c8fe18899dcerion      /* Ignore all other writes */
3127e14bb9f862843c6b804097c124961b5567ded4f1sewardj      break;
3128edf7fc572e2decb93e9143961e8739c8fe18899dcerion   }
3129e14bb9f862843c6b804097c124961b5567ded4f1sewardj
3130edf7fc572e2decb93e9143961e8739c8fe18899dcerion   default:
31315b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion      vex_printf("putGST_masked(ppc): reg = %u", reg);
31325b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion      vpanic("putGST_masked(ppc)");
3133edf7fc572e2decb93e9143961e8739c8fe18899dcerion   }
3134edf7fc572e2decb93e9143961e8739c8fe18899dcerion}
3135225a034683024109da729a4d2f080364b9485007cerion
3136edf7fc572e2decb93e9143961e8739c8fe18899dcerion/* Write the least significant nibble of src to the specified
3137edf7fc572e2decb93e9143961e8739c8fe18899dcerion   REG[FLD] (as per IBM/hardware notation). */
3138d953ebb9b04cbad6891676df597bf0c542b1ec89cerionstatic void putGST_field ( PPC_GST reg, IRExpr* src, UInt fld )
3139edf7fc572e2decb93e9143961e8739c8fe18899dcerion{
3140c6bbd470e9bd9898b84959227a406d3972d95f3bsewardj   UInt shft;
3141c6bbd470e9bd9898b84959227a406d3972d95f3bsewardj   ULong mask;
314241a7b70f888cf73cf3da6a53b31937ce0d26e8f4sewardj
3143dd40fdf58cc8a6fe9466c4f00bdfc9fe9bf00449sewardj   vassert( typeOfIRExpr(irsb->tyenv,src ) == Ity_I32 );
3144c6bbd470e9bd9898b84959227a406d3972d95f3bsewardj   vassert( fld < 16 );
3145d953ebb9b04cbad6891676df597bf0c542b1ec89cerion   vassert( reg < PPC_GST_MAX );
3146edf7fc572e2decb93e9143961e8739c8fe18899dcerion
3147c6bbd470e9bd9898b84959227a406d3972d95f3bsewardj   if (fld < 8)
3148c6bbd470e9bd9898b84959227a406d3972d95f3bsewardj      shft = 4*(7-fld);
3149c6bbd470e9bd9898b84959227a406d3972d95f3bsewardj   else
3150c6bbd470e9bd9898b84959227a406d3972d95f3bsewardj      shft = 4*(15-fld);
3151654b7f977db549c2365a5d95f774db0748c0d29aflorian   mask = 0xF;
3152654b7f977db549c2365a5d95f774db0748c0d29aflorian   mask = mask << shft;
3153edf7fc572e2decb93e9143961e8739c8fe18899dcerion
3154edf7fc572e2decb93e9143961e8739c8fe18899dcerion   switch (reg) {
3155d953ebb9b04cbad6891676df597bf0c542b1ec89cerion   case PPC_GST_CR:
3156edf7fc572e2decb93e9143961e8739c8fe18899dcerion      putCR0  (fld, binop(Iop_And8, mkU8(1   ), unop(Iop_32to8, src)));
3157edf7fc572e2decb93e9143961e8739c8fe18899dcerion      putCR321(fld, binop(Iop_And8, mkU8(7<<1), unop(Iop_32to8, src)));
3158225a034683024109da729a4d2f080364b9485007cerion      break;
3159e14bb9f862843c6b804097c124961b5567ded4f1sewardj
3160e14bb9f862843c6b804097c124961b5567ded4f1sewardj   default:
3161c6bbd470e9bd9898b84959227a406d3972d95f3bsewardj      {
3162c6bbd470e9bd9898b84959227a406d3972d95f3bsewardj         IRExpr * src64 = unop( Iop_32Uto64, src );
3163c6bbd470e9bd9898b84959227a406d3972d95f3bsewardj
3164c6bbd470e9bd9898b84959227a406d3972d95f3bsewardj         if (shft == 0) {
3165c6bbd470e9bd9898b84959227a406d3972d95f3bsewardj            putGST_masked( reg, src64, mask );
3166c6bbd470e9bd9898b84959227a406d3972d95f3bsewardj         } else {
3167c6bbd470e9bd9898b84959227a406d3972d95f3bsewardj            putGST_masked( reg,
3168c6bbd470e9bd9898b84959227a406d3972d95f3bsewardj                           binop( Iop_Shl64, src64, mkU8( toUChar( shft ) ) ),
3169c6bbd470e9bd9898b84959227a406d3972d95f3bsewardj                           mask );
3170c6bbd470e9bd9898b84959227a406d3972d95f3bsewardj         }
3171edf7fc572e2decb93e9143961e8739c8fe18899dcerion      }
3172e14bb9f862843c6b804097c124961b5567ded4f1sewardj   }
3173e14bb9f862843c6b804097c124961b5567ded4f1sewardj}
3174e14bb9f862843c6b804097c124961b5567ded4f1sewardj
317566d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj/*------------------------------------------------------------*/
317666d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj/* Helpers for VSX instructions that do floating point
317766d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj * operations and need to determine if a src contains a
317866d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj * special FP value.
317966d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj *
318066d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj *------------------------------------------------------------*/
318166d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj
318266d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj#define NONZERO_FRAC_MASK 0x000fffffffffffffULL
318366d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj#define FP_FRAC_PART(x) binop( Iop_And64, \
318466d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj                               mkexpr( x ), \
318566d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj                               mkU64( NONZERO_FRAC_MASK ) )
318666d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj
3187e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj// Returns exponent part of a single precision floating point as I32
3188e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardjstatic IRExpr * fp_exp_part_sp(IRTemp src)
3189e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj{
3190e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj   return binop( Iop_And32,
3191e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj                 binop( Iop_Shr32, mkexpr( src ), mkU8( 23 ) ),
3192e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj                 mkU32( 0xff ) );
3193e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj}
3194e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj
319566d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj// Returns exponent part of floating point as I32
3196e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardjstatic IRExpr * fp_exp_part(IRTemp src, Bool sp)
319766d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj{
319866d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj   IRExpr * exp;
3199e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj   if (sp)
3200e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj      return fp_exp_part_sp(src);
3201e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj
320266d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj   if (!mode64)
320366d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj      exp = binop( Iop_And32, binop( Iop_Shr32, unop( Iop_64HIto32,
320466d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj                                                      mkexpr( src ) ),
320566d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj                                     mkU8( 20 ) ), mkU32( 0x7ff ) );
320666d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj   else
320766d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj      exp = unop( Iop_64to32,
320866d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj                  binop( Iop_And64,
320966d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj                         binop( Iop_Shr64, mkexpr( src ), mkU8( 52 ) ),
321066d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj                         mkU64( 0x7ff ) ) );
321166d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj   return exp;
321266d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj}
321366d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj
3214e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardjstatic IRExpr * is_Inf_sp(IRTemp src)
3215e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj{
3216e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj   IRTemp frac_part = newTemp(Ity_I32);
3217e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj   IRExpr * Inf_exp;
3218e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj
3219e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj   assign( frac_part, binop( Iop_And32, mkexpr(src), mkU32(0x007fffff)) );
3220e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj   Inf_exp = binop( Iop_CmpEQ32, fp_exp_part( src, True /*single precision*/ ), mkU32( 0xff ) );
3221e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj   return mkAND1( Inf_exp, binop( Iop_CmpEQ32, mkexpr( frac_part ), mkU32( 0 ) ) );
3222e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj}
3223e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj
322466d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj
322566d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj// Infinity: exp = 7ff and fraction is zero; s = 0/1
3226e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardjstatic IRExpr * is_Inf(IRTemp src, Bool sp)
322766d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj{
322866d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj   IRExpr * Inf_exp, * hi32, * low32;
3229e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj   IRTemp frac_part;
323066d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj
3231e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj   if (sp)
3232e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj      return is_Inf_sp(src);
3233e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj
3234e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj   frac_part = newTemp(Ity_I64);
323566d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj   assign( frac_part, FP_FRAC_PART(src) );
3236e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj   Inf_exp = binop( Iop_CmpEQ32, fp_exp_part( src, False /*not single precision*/  ), mkU32( 0x7ff ) );
323766d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj   hi32 = unop( Iop_64HIto32, mkexpr( frac_part ) );
323866d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj   low32 = unop( Iop_64to32, mkexpr( frac_part ) );
323966d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj   return mkAND1( Inf_exp, binop( Iop_CmpEQ32, binop( Iop_Or32, low32, hi32 ),
324066d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj                                  mkU32( 0 ) ) );
324166d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj}
324266d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj
3243e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardjstatic IRExpr * is_Zero_sp(IRTemp src)
3244e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj{
3245e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj   IRTemp sign_less_part = newTemp(Ity_I32);
3246e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj   assign( sign_less_part, binop( Iop_And32, mkexpr( src ), mkU32( SIGN_MASK32 ) ) );
3247e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj   return binop( Iop_CmpEQ32, mkexpr( sign_less_part ), mkU32( 0 ) );
3248e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj}
3249e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj
325066d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj// Zero: exp is zero and fraction is zero; s = 0/1
3251e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardjstatic IRExpr * is_Zero(IRTemp src, Bool sp)
325266d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj{
325366d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj   IRExpr * hi32, * low32;
3254e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj   IRTemp sign_less_part;
3255e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj   if (sp)
3256e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj      return is_Zero_sp(src);
3257e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj
3258e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj   sign_less_part = newTemp(Ity_I64);
325966d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj
326066d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj   assign( sign_less_part, binop( Iop_And64, mkexpr( src ), mkU64( SIGN_MASK ) ) );
326166d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj   hi32 = unop( Iop_64HIto32, mkexpr( sign_less_part ) );
326266d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj   low32 = unop( Iop_64to32, mkexpr( sign_less_part ) );
326366d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj   return binop( Iop_CmpEQ32, binop( Iop_Or32, low32, hi32 ),
326466d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj                              mkU32( 0 ) );
326566d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj}
326666d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj
326766d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj/*  SNAN: s = 1/0; exp = 0x7ff; fraction is nonzero, with highest bit '1'
326866d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj *  QNAN: s = 1/0; exp = 0x7ff; fraction is nonzero, with highest bit '0'
326966d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj *  This function returns an IRExpr value of '1' for any type of NaN.
327066d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj */
327166d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardjstatic IRExpr * is_NaN(IRTemp src)
327266d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj{
327366d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj   IRExpr * NaN_exp, * hi32, * low32;
327466d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj   IRTemp frac_part = newTemp(Ity_I64);
327566d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj
327666d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj   assign( frac_part, FP_FRAC_PART(src) );
327766d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj   hi32 = unop( Iop_64HIto32, mkexpr( frac_part ) );
327866d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj   low32 = unop( Iop_64to32, mkexpr( frac_part ) );
3279e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj   NaN_exp = binop( Iop_CmpEQ32, fp_exp_part( src, False /*not single precision*/ ),
3280e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj                    mkU32( 0x7ff ) );
328166d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj
328266d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj   return mkAND1( NaN_exp, binop( Iop_CmpNE32, binop( Iop_Or32, low32, hi32 ),
328366d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj                                               mkU32( 0 ) ) );
328466d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj}
32850e2cc67b30d1bb4d0515a1e09d944143becb3881sewardj
32864aa412af1d8166cc11f39a6e721df49431d23618sewardj/* This function returns an IRExpr value of '1' for any type of NaN.
32874aa412af1d8166cc11f39a6e721df49431d23618sewardj * The passed 'src' argument is assumed to be Ity_I32.
32884aa412af1d8166cc11f39a6e721df49431d23618sewardj */
32894aa412af1d8166cc11f39a6e721df49431d23618sewardjstatic IRExpr * is_NaN_32(IRTemp src)
32904aa412af1d8166cc11f39a6e721df49431d23618sewardj{
32914aa412af1d8166cc11f39a6e721df49431d23618sewardj#define NONZERO_FRAC_MASK32 0x007fffffULL
32924aa412af1d8166cc11f39a6e721df49431d23618sewardj#define FP_FRAC_PART32(x) binop( Iop_And32, \
32934aa412af1d8166cc11f39a6e721df49431d23618sewardj                                 mkexpr( x ), \
32944aa412af1d8166cc11f39a6e721df49431d23618sewardj                                 mkU32( NONZERO_FRAC_MASK32 ) )
32954aa412af1d8166cc11f39a6e721df49431d23618sewardj
32964aa412af1d8166cc11f39a6e721df49431d23618sewardj   IRExpr * frac_part = FP_FRAC_PART32(src);
32974aa412af1d8166cc11f39a6e721df49431d23618sewardj   IRExpr * exp_part = binop( Iop_And32,
32984aa412af1d8166cc11f39a6e721df49431d23618sewardj                              binop( Iop_Shr32, mkexpr( src ), mkU8( 23 ) ),
32994aa412af1d8166cc11f39a6e721df49431d23618sewardj                              mkU32( 0x0ff ) );
33004aa412af1d8166cc11f39a6e721df49431d23618sewardj   IRExpr * NaN_exp = binop( Iop_CmpEQ32, exp_part, mkU32( 0xff ) );
33014aa412af1d8166cc11f39a6e721df49431d23618sewardj
33024aa412af1d8166cc11f39a6e721df49431d23618sewardj   return mkAND1( NaN_exp, binop( Iop_CmpNE32, frac_part, mkU32( 0 ) ) );
33034aa412af1d8166cc11f39a6e721df49431d23618sewardj}
33044aa412af1d8166cc11f39a6e721df49431d23618sewardj
33056fef87a15cd79526ece8c38798e2d304b805a1f3carll/* This function takes an Ity_I32 input argument interpreted
33066fef87a15cd79526ece8c38798e2d304b805a1f3carll * as a single-precision floating point value. If src is a
33076fef87a15cd79526ece8c38798e2d304b805a1f3carll * SNaN, it is changed to a QNaN and returned; otherwise,
33086fef87a15cd79526ece8c38798e2d304b805a1f3carll * the original value is returned.
33096fef87a15cd79526ece8c38798e2d304b805a1f3carll */
33106fef87a15cd79526ece8c38798e2d304b805a1f3carllstatic IRExpr * handle_SNaN_to_QNaN_32(IRExpr * src)
33116fef87a15cd79526ece8c38798e2d304b805a1f3carll{
33126fef87a15cd79526ece8c38798e2d304b805a1f3carll#define SNAN_MASK32 0x00400000
33136fef87a15cd79526ece8c38798e2d304b805a1f3carll   IRTemp tmp = newTemp(Ity_I32);
33146fef87a15cd79526ece8c38798e2d304b805a1f3carll   IRTemp mask = newTemp(Ity_I32);
33156fef87a15cd79526ece8c38798e2d304b805a1f3carll   IRTemp is_SNAN = newTemp(Ity_I1);
33166fef87a15cd79526ece8c38798e2d304b805a1f3carll
33176fef87a15cd79526ece8c38798e2d304b805a1f3carll   vassert( typeOfIRExpr(irsb->tyenv, src ) == Ity_I32 );
33186fef87a15cd79526ece8c38798e2d304b805a1f3carll   assign(tmp, src);
33196fef87a15cd79526ece8c38798e2d304b805a1f3carll
33206fef87a15cd79526ece8c38798e2d304b805a1f3carll   /* check if input is SNaN, if it is convert to QNaN */
33216fef87a15cd79526ece8c38798e2d304b805a1f3carll   assign( is_SNAN,
33226fef87a15cd79526ece8c38798e2d304b805a1f3carll           mkAND1( is_NaN_32( tmp ),
33236fef87a15cd79526ece8c38798e2d304b805a1f3carll                   binop( Iop_CmpEQ32,
33246fef87a15cd79526ece8c38798e2d304b805a1f3carll                          binop( Iop_And32, mkexpr( tmp ),
33256fef87a15cd79526ece8c38798e2d304b805a1f3carll                                 mkU32( SNAN_MASK32 ) ),
33266fef87a15cd79526ece8c38798e2d304b805a1f3carll                          mkU32( 0 ) ) ) );
33276fef87a15cd79526ece8c38798e2d304b805a1f3carll   /* create mask with QNaN bit set to make it a QNaN if tmp is SNaN */
33286fef87a15cd79526ece8c38798e2d304b805a1f3carll   assign ( mask, binop( Iop_And32,
33296fef87a15cd79526ece8c38798e2d304b805a1f3carll                         unop( Iop_1Sto32, mkexpr( is_SNAN ) ),
33306fef87a15cd79526ece8c38798e2d304b805a1f3carll                         mkU32( SNAN_MASK32 ) ) );
33316fef87a15cd79526ece8c38798e2d304b805a1f3carll   return binop( Iop_Or32, mkexpr( mask ), mkexpr( tmp) );
33326fef87a15cd79526ece8c38798e2d304b805a1f3carll}
33336fef87a15cd79526ece8c38798e2d304b805a1f3carll
33346fef87a15cd79526ece8c38798e2d304b805a1f3carll
33354aa412af1d8166cc11f39a6e721df49431d23618sewardj/* This helper function performs the negation part of operations of the form:
33364aa412af1d8166cc11f39a6e721df49431d23618sewardj *    "Negate Multiply-<op>"
33374aa412af1d8166cc11f39a6e721df49431d23618sewardj *  where "<op>" is either "Add" or "Sub".
33384aa412af1d8166cc11f39a6e721df49431d23618sewardj *
33394aa412af1d8166cc11f39a6e721df49431d23618sewardj * This function takes one argument -- the floating point intermediate result (converted to
33404aa412af1d8166cc11f39a6e721df49431d23618sewardj * Ity_I64 via Iop_ReinterpF64asI64) that was obtained from the "Multip-<op>" part of
33414aa412af1d8166cc11f39a6e721df49431d23618sewardj * the operation described above.
33424aa412af1d8166cc11f39a6e721df49431d23618sewardj */
33434aa412af1d8166cc11f39a6e721df49431d23618sewardjstatic IRTemp getNegatedResult(IRTemp intermediateResult)
33444aa412af1d8166cc11f39a6e721df49431d23618sewardj{
33454aa412af1d8166cc11f39a6e721df49431d23618sewardj   ULong signbit_mask = 0x8000000000000000ULL;
33464aa412af1d8166cc11f39a6e721df49431d23618sewardj   IRTemp signbit_32 = newTemp(Ity_I32);
33474aa412af1d8166cc11f39a6e721df49431d23618sewardj   IRTemp resultantSignbit = newTemp(Ity_I1);
33484aa412af1d8166cc11f39a6e721df49431d23618sewardj   IRTemp negatedResult = newTemp(Ity_I64);
33494aa412af1d8166cc11f39a6e721df49431d23618sewardj   assign( signbit_32, binop( Iop_Shr32,
33504aa412af1d8166cc11f39a6e721df49431d23618sewardj                          unop( Iop_64HIto32,
33514aa412af1d8166cc11f39a6e721df49431d23618sewardj                                 binop( Iop_And64, mkexpr( intermediateResult ),
33524aa412af1d8166cc11f39a6e721df49431d23618sewardj                                        mkU64( signbit_mask ) ) ),
33534aa412af1d8166cc11f39a6e721df49431d23618sewardj                                 mkU8( 31 ) ) );
33544aa412af1d8166cc11f39a6e721df49431d23618sewardj   /* We negate the signbit if and only if the intermediate result from the
33554aa412af1d8166cc11f39a6e721df49431d23618sewardj    * multiply-<op> was NOT a NaN.  This is an XNOR predicate.
33564aa412af1d8166cc11f39a6e721df49431d23618sewardj    */
33574aa412af1d8166cc11f39a6e721df49431d23618sewardj   assign( resultantSignbit,
33584aa412af1d8166cc11f39a6e721df49431d23618sewardj        unop( Iop_Not1,
33594aa412af1d8166cc11f39a6e721df49431d23618sewardj              binop( Iop_CmpEQ32,
33604aa412af1d8166cc11f39a6e721df49431d23618sewardj                     binop( Iop_Xor32,
33614aa412af1d8166cc11f39a6e721df49431d23618sewardj                            mkexpr( signbit_32 ),
33624aa412af1d8166cc11f39a6e721df49431d23618sewardj                            unop( Iop_1Uto32, is_NaN( intermediateResult ) ) ),
33634aa412af1d8166cc11f39a6e721df49431d23618sewardj                     mkU32( 1 ) ) ) );
33644aa412af1d8166cc11f39a6e721df49431d23618sewardj
33654aa412af1d8166cc11f39a6e721df49431d23618sewardj   assign( negatedResult,
33664aa412af1d8166cc11f39a6e721df49431d23618sewardj        binop( Iop_Or64,
33674aa412af1d8166cc11f39a6e721df49431d23618sewardj               binop( Iop_And64,
33684aa412af1d8166cc11f39a6e721df49431d23618sewardj                      mkexpr( intermediateResult ),
33694aa412af1d8166cc11f39a6e721df49431d23618sewardj                      mkU64( ~signbit_mask ) ),
33704aa412af1d8166cc11f39a6e721df49431d23618sewardj               binop( Iop_32HLto64,
33714aa412af1d8166cc11f39a6e721df49431d23618sewardj                      binop( Iop_Shl32,
33724aa412af1d8166cc11f39a6e721df49431d23618sewardj                             unop( Iop_1Uto32, mkexpr( resultantSignbit ) ),
33734aa412af1d8166cc11f39a6e721df49431d23618sewardj                             mkU8( 31 ) ),
33744aa412af1d8166cc11f39a6e721df49431d23618sewardj                      mkU32( 0 ) ) ) );
33754aa412af1d8166cc11f39a6e721df49431d23618sewardj
33764aa412af1d8166cc11f39a6e721df49431d23618sewardj   return negatedResult;
33774aa412af1d8166cc11f39a6e721df49431d23618sewardj}
33784aa412af1d8166cc11f39a6e721df49431d23618sewardj
33794aa412af1d8166cc11f39a6e721df49431d23618sewardj/* This helper function performs the negation part of operations of the form:
33804aa412af1d8166cc11f39a6e721df49431d23618sewardj *    "Negate Multiply-<op>"
33814aa412af1d8166cc11f39a6e721df49431d23618sewardj *  where "<op>" is either "Add" or "Sub".
33824aa412af1d8166cc11f39a6e721df49431d23618sewardj *
33834aa412af1d8166cc11f39a6e721df49431d23618sewardj * This function takes one argument -- the floating point intermediate result (converted to
33844aa412af1d8166cc11f39a6e721df49431d23618sewardj * Ity_I32 via Iop_ReinterpF32asI32) that was obtained from the "Multip-<op>" part of
33854aa412af1d8166cc11f39a6e721df49431d23618sewardj * the operation described above.
33864aa412af1d8166cc11f39a6e721df49431d23618sewardj */
33874aa412af1d8166cc11f39a6e721df49431d23618sewardjstatic IRTemp getNegatedResult_32(IRTemp intermediateResult)
33884aa412af1d8166cc11f39a6e721df49431d23618sewardj{
33894aa412af1d8166cc11f39a6e721df49431d23618sewardj   UInt signbit_mask = 0x80000000;
33904aa412af1d8166cc11f39a6e721df49431d23618sewardj   IRTemp signbit_32 = newTemp(Ity_I32);
33914aa412af1d8166cc11f39a6e721df49431d23618sewardj   IRTemp resultantSignbit = newTemp(Ity_I1);
33924aa412af1d8166cc11f39a6e721df49431d23618sewardj   IRTemp negatedResult = newTemp(Ity_I32);
33934aa412af1d8166cc11f39a6e721df49431d23618sewardj   assign( signbit_32, binop( Iop_Shr32,
33944aa412af1d8166cc11f39a6e721df49431d23618sewardj                                 binop( Iop_And32, mkexpr( intermediateResult ),
33954aa412af1d8166cc11f39a6e721df49431d23618sewardj                                        mkU32( signbit_mask ) ),
33964aa412af1d8166cc11f39a6e721df49431d23618sewardj                                 mkU8( 31 ) ) );
33974aa412af1d8166cc11f39a6e721df49431d23618sewardj   /* We negate the signbit if and only if the intermediate result from the
33984aa412af1d8166cc11f39a6e721df49431d23618sewardj    * multiply-<op> was NOT a NaN.  This is an XNOR predicate.
33994aa412af1d8166cc11f39a6e721df49431d23618sewardj    */
34004aa412af1d8166cc11f39a6e721df49431d23618sewardj   assign( resultantSignbit,
34014aa412af1d8166cc11f39a6e721df49431d23618sewardj        unop( Iop_Not1,
34024aa412af1d8166cc11f39a6e721df49431d23618sewardj              binop( Iop_CmpEQ32,
34034aa412af1d8166cc11f39a6e721df49431d23618sewardj                     binop( Iop_Xor32,
34044aa412af1d8166cc11f39a6e721df49431d23618sewardj                            mkexpr( signbit_32 ),
34054aa412af1d8166cc11f39a6e721df49431d23618sewardj                            unop( Iop_1Uto32, is_NaN_32( intermediateResult ) ) ),
34064aa412af1d8166cc11f39a6e721df49431d23618sewardj                     mkU32( 1 ) ) ) );
34074aa412af1d8166cc11f39a6e721df49431d23618sewardj
34084aa412af1d8166cc11f39a6e721df49431d23618sewardj   assign( negatedResult,
34094aa412af1d8166cc11f39a6e721df49431d23618sewardj           binop( Iop_Or32,
34104aa412af1d8166cc11f39a6e721df49431d23618sewardj                  binop( Iop_And32,
34114aa412af1d8166cc11f39a6e721df49431d23618sewardj                         mkexpr( intermediateResult ),
34124aa412af1d8166cc11f39a6e721df49431d23618sewardj                         mkU32( ~signbit_mask ) ),
34134aa412af1d8166cc11f39a6e721df49431d23618sewardj                  binop( Iop_Shl32,
34144aa412af1d8166cc11f39a6e721df49431d23618sewardj                         unop( Iop_1Uto32, mkexpr( resultantSignbit ) ),
34154aa412af1d8166cc11f39a6e721df49431d23618sewardj                         mkU8( 31 ) ) ) );
34164aa412af1d8166cc11f39a6e721df49431d23618sewardj
34174aa412af1d8166cc11f39a6e721df49431d23618sewardj   return negatedResult;
34184aa412af1d8166cc11f39a6e721df49431d23618sewardj}
34193007c7fb4f226f2db7e250b0ebb114618ab1980ccerion
3420b51f0f4f33256638ed953156a2635aa739b232f1sewardj/*------------------------------------------------------------*/
34218943d02aa373f45c6e5fdcbe5947620285d442b1carll/* Transactional memory helpers
34228943d02aa373f45c6e5fdcbe5947620285d442b1carll *
34238943d02aa373f45c6e5fdcbe5947620285d442b1carll *------------------------------------------------------------*/
34248943d02aa373f45c6e5fdcbe5947620285d442b1carll
34258943d02aa373f45c6e5fdcbe5947620285d442b1carllstatic ULong generate_TMreason( UInt failure_code,
34268943d02aa373f45c6e5fdcbe5947620285d442b1carll                                             UInt persistant,
34278943d02aa373f45c6e5fdcbe5947620285d442b1carll                                             UInt nest_overflow,
34288943d02aa373f45c6e5fdcbe5947620285d442b1carll                                             UInt tm_exact )
34298943d02aa373f45c6e5fdcbe5947620285d442b1carll{
34308943d02aa373f45c6e5fdcbe5947620285d442b1carll   ULong tm_err_code =
34318943d02aa373f45c6e5fdcbe5947620285d442b1carll     ( (ULong) 0) << (63-6)   /* Failure code */
34328943d02aa373f45c6e5fdcbe5947620285d442b1carll     | ( (ULong) persistant) << (63-7)     /* Failure persistant */
34338943d02aa373f45c6e5fdcbe5947620285d442b1carll     | ( (ULong) 0) << (63-8)   /* Disallowed */
34348943d02aa373f45c6e5fdcbe5947620285d442b1carll     | ( (ULong) nest_overflow) << (63-9)   /* Nesting Overflow */
34358943d02aa373f45c6e5fdcbe5947620285d442b1carll     | ( (ULong) 0) << (63-10)  /* Footprint Overflow */
34368943d02aa373f45c6e5fdcbe5947620285d442b1carll     | ( (ULong) 0) << (63-11)  /* Self-Induced Conflict */
34378943d02aa373f45c6e5fdcbe5947620285d442b1carll     | ( (ULong) 0) << (63-12)  /* Non-Transactional Conflict */
34388943d02aa373f45c6e5fdcbe5947620285d442b1carll     | ( (ULong) 0) << (63-13)  /* Transactional Conflict */
34398943d02aa373f45c6e5fdcbe5947620285d442b1carll     | ( (ULong) 0) << (63-14)  /* Translation Invalidation Conflict */
34408943d02aa373f45c6e5fdcbe5947620285d442b1carll     | ( (ULong) 0) << (63-15)  /* Implementation-specific */
34418943d02aa373f45c6e5fdcbe5947620285d442b1carll     | ( (ULong) 0) << (63-16)  /* Instruction Fetch Conflict */
34428943d02aa373f45c6e5fdcbe5947620285d442b1carll     | ( (ULong) 0) << (63-30)  /* Reserved */
34438943d02aa373f45c6e5fdcbe5947620285d442b1carll     | ( (ULong) 0) << (63-31)  /* Abort */
34448943d02aa373f45c6e5fdcbe5947620285d442b1carll     | ( (ULong) 0) << (63-32)  /* Suspend */
34458943d02aa373f45c6e5fdcbe5947620285d442b1carll     | ( (ULong) 0) << (63-33)  /* Reserved */
34468943d02aa373f45c6e5fdcbe5947620285d442b1carll     | ( (ULong) 0) << (63-35)  /* Privilege */
34478943d02aa373f45c6e5fdcbe5947620285d442b1carll     | ( (ULong) 0) << (63-36)  /* Failure Summary */
34488943d02aa373f45c6e5fdcbe5947620285d442b1carll     | ( (ULong) tm_exact) << (63-37)  /* TFIAR Exact */
34498943d02aa373f45c6e5fdcbe5947620285d442b1carll     | ( (ULong) 0) << (63-38)  /* ROT */
34508943d02aa373f45c6e5fdcbe5947620285d442b1carll     | ( (ULong) 0) << (63-51)  /* Reserved */
34518943d02aa373f45c6e5fdcbe5947620285d442b1carll     | ( (ULong) 0) << (63-63);  /* Transaction Level */
34528943d02aa373f45c6e5fdcbe5947620285d442b1carll
34538943d02aa373f45c6e5fdcbe5947620285d442b1carll     return tm_err_code;
34548943d02aa373f45c6e5fdcbe5947620285d442b1carll}
34558943d02aa373f45c6e5fdcbe5947620285d442b1carll
34568943d02aa373f45c6e5fdcbe5947620285d442b1carllstatic void storeTMfailure( Addr64 err_address, ULong tm_reason,
34578943d02aa373f45c6e5fdcbe5947620285d442b1carll                            Addr64 handler_address )
34588943d02aa373f45c6e5fdcbe5947620285d442b1carll{
3459486db12d4767b5c2cc5ae764616e758f30ce21f5carll   putGST( PPC_GST_TFIAR,   mkU64( err_address ) );
3460486db12d4767b5c2cc5ae764616e758f30ce21f5carll   putGST( PPC_GST_TEXASR,  mkU64( tm_reason ) );
3461486db12d4767b5c2cc5ae764616e758f30ce21f5carll   putGST( PPC_GST_TEXASRU, mkU32( 0 ) );
3462486db12d4767b5c2cc5ae764616e758f30ce21f5carll   putGST( PPC_GST_TFHAR,   mkU64( handler_address ) );
34638943d02aa373f45c6e5fdcbe5947620285d442b1carll}
34648943d02aa373f45c6e5fdcbe5947620285d442b1carll
34658943d02aa373f45c6e5fdcbe5947620285d442b1carll/*------------------------------------------------------------*/
3466b51f0f4f33256638ed953156a2635aa739b232f1sewardj/*--- Integer Instruction Translation                     --- */
3467b51f0f4f33256638ed953156a2635aa739b232f1sewardj/*------------------------------------------------------------*/
34683007c7fb4f226f2db7e250b0ebb114618ab1980ccerion
3469b51f0f4f33256638ed953156a2635aa739b232f1sewardj/*
3470b51f0f4f33256638ed953156a2635aa739b232f1sewardj  Integer Arithmetic Instructions
3471b51f0f4f33256638ed953156a2635aa739b232f1sewardj*/
3472b51f0f4f33256638ed953156a2635aa739b232f1sewardjstatic Bool dis_int_arith ( UInt theInstr )
34737622226e8a2f15e2532a8cf5fb0e2f75a0aac128cerion{
347476de5cf615380b23b4b5bcced6541233cd4a93a0cerion   /* D-Form, XO-Form */
347576de5cf615380b23b4b5bcced6541233cd4a93a0cerion   UChar opc1    = ifieldOPC(theInstr);
347676de5cf615380b23b4b5bcced6541233cd4a93a0cerion   UChar rD_addr = ifieldRegDS(theInstr);
347776de5cf615380b23b4b5bcced6541233cd4a93a0cerion   UChar rA_addr = ifieldRegA(theInstr);
3478d953ebb9b04cbad6891676df597bf0c542b1ec89cerion   UInt  uimm16  = ifieldUIMM16(theInstr);
347976de5cf615380b23b4b5bcced6541233cd4a93a0cerion   UChar rB_addr = ifieldRegB(theInstr);
348076de5cf615380b23b4b5bcced6541233cd4a93a0cerion   UChar flag_OE = ifieldBIT10(theInstr);
348176de5cf615380b23b4b5bcced6541233cd4a93a0cerion   UInt  opc2    = ifieldOPClo9(theInstr);
348276de5cf615380b23b4b5bcced6541233cd4a93a0cerion   UChar flag_rC = ifieldBIT0(theInstr);
348376de5cf615380b23b4b5bcced6541233cd4a93a0cerion
3484d953ebb9b04cbad6891676df597bf0c542b1ec89cerion   Long   simm16 = extend_s_16to64(uimm16);
3485d953ebb9b04cbad6891676df597bf0c542b1ec89cerion   IRType ty     = mode64 ? Ity_I64 : Ity_I32;
3486d953ebb9b04cbad6891676df597bf0c542b1ec89cerion   IRTemp rA     = newTemp(ty);
3487d953ebb9b04cbad6891676df597bf0c542b1ec89cerion   IRTemp rB     = newTemp(ty);
3488d953ebb9b04cbad6891676df597bf0c542b1ec89cerion   IRTemp rD     = newTemp(ty);
348970e2412f623c955d7b199f09401732cf57417fc2cerion
3490b85e8bba97fdae7d892f7bfd12e4601307e4721dcerion   Bool do_rc = False;
3491b85e8bba97fdae7d892f7bfd12e4601307e4721dcerion
349276de5cf615380b23b4b5bcced6541233cd4a93a0cerion   assign( rA, getIReg(rA_addr) );
349376de5cf615380b23b4b5bcced6541233cd4a93a0cerion   assign( rB, getIReg(rB_addr) );         // XO-Form: rD, rA, rB
3494b51f0f4f33256638ed953156a2635aa739b232f1sewardj
3495b85e8bba97fdae7d892f7bfd12e4601307e4721dcerion   switch (opc1) {
3496b85e8bba97fdae7d892f7bfd12e4601307e4721dcerion   /* D-Form */
3497e9d361ab43518b6dfbd3d846f48859534659dee0cerion   case 0x0C: // addic  (Add Immediate Carrying, PPC32 p351
3498d953ebb9b04cbad6891676df597bf0c542b1ec89cerion      DIP("addic r%u,r%u,%d\n", rD_addr, rA_addr, (Int)simm16);
34992831b00c4950d6c2b061def05fd67528fe132ececerion      assign( rD, binop( mkSzOp(ty, Iop_Add8), mkexpr(rA),
35002831b00c4950d6c2b061def05fd67528fe132ececerion                         mkSzExtendS16(ty, uimm16) ) );
35015b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion      set_XER_CA( ty, PPCG_FLAG_OP_ADD,
35022831b00c4950d6c2b061def05fd67528fe132ececerion                  mkexpr(rD), mkexpr(rA), mkSzExtendS16(ty, uimm16),
35032831b00c4950d6c2b061def05fd67528fe132ececerion                  mkSzImm(ty, 0)/*old xer.ca, which is ignored*/ );
3504b85e8bba97fdae7d892f7bfd12e4601307e4721dcerion      break;
3505b51f0f4f33256638ed953156a2635aa739b232f1sewardj
3506e9d361ab43518b6dfbd3d846f48859534659dee0cerion   case 0x0D: // addic. (Add Immediate Carrying and Record, PPC32 p352)
3507d953ebb9b04cbad6891676df597bf0c542b1ec89cerion      DIP("addic. r%u,r%u,%d\n", rD_addr, rA_addr, (Int)simm16);
35082831b00c4950d6c2b061def05fd67528fe132ececerion      assign( rD, binop( mkSzOp(ty, Iop_Add8), mkexpr(rA),
35092831b00c4950d6c2b061def05fd67528fe132ececerion                         mkSzExtendS16(ty, uimm16) ) );
35105b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion      set_XER_CA( ty, PPCG_FLAG_OP_ADD,
35112831b00c4950d6c2b061def05fd67528fe132ececerion                  mkexpr(rD), mkexpr(rA), mkSzExtendS16(ty, uimm16),
35122831b00c4950d6c2b061def05fd67528fe132ececerion                  mkSzImm(ty, 0)/*old xer.ca, which is ignored*/ );
351370e2412f623c955d7b199f09401732cf57417fc2cerion      do_rc = True;  // Always record to CR
351476de5cf615380b23b4b5bcced6541233cd4a93a0cerion      flag_rC = 1;
3515b85e8bba97fdae7d892f7bfd12e4601307e4721dcerion      break;
3516b85e8bba97fdae7d892f7bfd12e4601307e4721dcerion
3517e9d361ab43518b6dfbd3d846f48859534659dee0cerion   case 0x0E: // addi   (Add Immediate, PPC32 p350)
35184561acb2fed3ea11b7b1f95a373da8ec62e6d483cerion      // li rD,val   == addi rD,0,val
35194561acb2fed3ea11b7b1f95a373da8ec62e6d483cerion      // la disp(rA) == addi rD,rA,disp
352076de5cf615380b23b4b5bcced6541233cd4a93a0cerion      if ( rA_addr == 0 ) {
3521d953ebb9b04cbad6891676df597bf0c542b1ec89cerion         DIP("li r%u,%d\n", rD_addr, (Int)simm16);
35222831b00c4950d6c2b061def05fd67528fe132ececerion         assign( rD, mkSzExtendS16(ty, uimm16) );
35234561acb2fed3ea11b7b1f95a373da8ec62e6d483cerion      } else {
3524d953ebb9b04cbad6891676df597bf0c542b1ec89cerion         DIP("addi r%u,r%u,%d\n", rD_addr, rA_addr, (Int)simm16);
35252831b00c4950d6c2b061def05fd67528fe132ececerion         assign( rD, binop( mkSzOp(ty, Iop_Add8), mkexpr(rA),
35262831b00c4950d6c2b061def05fd67528fe132ececerion                            mkSzExtendS16(ty, uimm16) ) );
35274561acb2fed3ea11b7b1f95a373da8ec62e6d483cerion      }
35284561acb2fed3ea11b7b1f95a373da8ec62e6d483cerion      break;
35294561acb2fed3ea11b7b1f95a373da8ec62e6d483cerion
3530e9d361ab43518b6dfbd3d846f48859534659dee0cerion   case 0x0F: // addis  (Add Immediate Shifted, PPC32 p353)
3531b85e8bba97fdae7d892f7bfd12e4601307e4721dcerion      // lis rD,val == addis rD,0,val
353276de5cf615380b23b4b5bcced6541233cd4a93a0cerion      if ( rA_addr == 0 ) {
3533d953ebb9b04cbad6891676df597bf0c542b1ec89cerion         DIP("lis r%u,%d\n", rD_addr, (Int)simm16);
35342831b00c4950d6c2b061def05fd67528fe132ececerion         assign( rD, mkSzExtendS32(ty, uimm16 << 16) );
3535b85e8bba97fdae7d892f7bfd12e4601307e4721dcerion      } else {
3536b173774421d015736c2316b5e6e998e7de545a5cflorian         DIP("addis r%u,r%u,0x%x\n", rD_addr, rA_addr, (UInt)simm16);
35372831b00c4950d6c2b061def05fd67528fe132ececerion         assign( rD, binop( mkSzOp(ty, Iop_Add8), mkexpr(rA),
35382831b00c4950d6c2b061def05fd67528fe132ececerion                            mkSzExtendS32(ty, uimm16 << 16) ) );
3539b85e8bba97fdae7d892f7bfd12e4601307e4721dcerion      }
3540b85e8bba97fdae7d892f7bfd12e4601307e4721dcerion      break;
3541b85e8bba97fdae7d892f7bfd12e4601307e4721dcerion
3542e9d361ab43518b6dfbd3d846f48859534659dee0cerion   case 0x07: // mulli    (Multiply Low Immediate, PPC32 p490)
3543d953ebb9b04cbad6891676df597bf0c542b1ec89cerion      DIP("mulli r%u,r%u,%d\n", rD_addr, rA_addr, (Int)simm16);
3544d953ebb9b04cbad6891676df597bf0c542b1ec89cerion      if (mode64)
3545d953ebb9b04cbad6891676df597bf0c542b1ec89cerion         assign( rD, unop(Iop_128to64,
3546d953ebb9b04cbad6891676df597bf0c542b1ec89cerion                          binop(Iop_MullS64, mkexpr(rA),
35472831b00c4950d6c2b061def05fd67528fe132ececerion                                mkSzExtendS16(ty, uimm16))) );
3548d953ebb9b04cbad6891676df597bf0c542b1ec89cerion      else
3549d953ebb9b04cbad6891676df597bf0c542b1ec89cerion         assign( rD, unop(Iop_64to32,
3550d953ebb9b04cbad6891676df597bf0c542b1ec89cerion                          binop(Iop_MullS32, mkexpr(rA),
35512831b00c4950d6c2b061def05fd67528fe132ececerion                                mkSzExtendS16(ty, uimm16))) );
3552b85e8bba97fdae7d892f7bfd12e4601307e4721dcerion      break;
3553b85e8bba97fdae7d892f7bfd12e4601307e4721dcerion
3554e9d361ab43518b6dfbd3d846f48859534659dee0cerion   case 0x08: // subfic   (Subtract from Immediate Carrying, PPC32 p540)
3555d953ebb9b04cbad6891676df597bf0c542b1ec89cerion      DIP("subfic r%u,r%u,%d\n", rD_addr, rA_addr, (Int)simm16);
355676de5cf615380b23b4b5bcced6541233cd4a93a0cerion      // rD = simm16 - rA
35572831b00c4950d6c2b061def05fd67528fe132ececerion      assign( rD, binop( mkSzOp(ty, Iop_Sub8),
35582831b00c4950d6c2b061def05fd67528fe132ececerion                         mkSzExtendS16(ty, uimm16),
3559d953ebb9b04cbad6891676df597bf0c542b1ec89cerion                         mkexpr(rA)) );
35605b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion      set_XER_CA( ty, PPCG_FLAG_OP_SUBFI,
35612831b00c4950d6c2b061def05fd67528fe132ececerion                  mkexpr(rD), mkexpr(rA), mkSzExtendS16(ty, uimm16),
35622831b00c4950d6c2b061def05fd67528fe132ececerion                  mkSzImm(ty, 0)/*old xer.ca, which is ignored*/ );
3563b85e8bba97fdae7d892f7bfd12e4601307e4721dcerion      break;
3564b85e8bba97fdae7d892f7bfd12e4601307e4721dcerion
3565b85e8bba97fdae7d892f7bfd12e4601307e4721dcerion   /* XO-Form */
3566b85e8bba97fdae7d892f7bfd12e4601307e4721dcerion   case 0x1F:
3567b85e8bba97fdae7d892f7bfd12e4601307e4721dcerion      do_rc = True;    // All below record to CR
3568b85e8bba97fdae7d892f7bfd12e4601307e4721dcerion
3569b85e8bba97fdae7d892f7bfd12e4601307e4721dcerion      switch (opc2) {
3570e9d361ab43518b6dfbd3d846f48859534659dee0cerion      case 0x10A: // add  (Add, PPC32 p347)
3571d953ebb9b04cbad6891676df597bf0c542b1ec89cerion         DIP("add%s%s r%u,r%u,r%u\n",
35725b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion             flag_OE ? "o" : "", flag_rC ? ".":"",
357376de5cf615380b23b4b5bcced6541233cd4a93a0cerion             rD_addr, rA_addr, rB_addr);
35742831b00c4950d6c2b061def05fd67528fe132ececerion         assign( rD, binop( mkSzOp(ty, Iop_Add8),
3575d953ebb9b04cbad6891676df597bf0c542b1ec89cerion                            mkexpr(rA), mkexpr(rB) ) );
357670e2412f623c955d7b199f09401732cf57417fc2cerion         if (flag_OE) {
35775b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion            set_XER_OV( ty, PPCG_FLAG_OP_ADD,
357876de5cf615380b23b4b5bcced6541233cd4a93a0cerion                        mkexpr(rD), mkexpr(rA), mkexpr(rB) );
357970e2412f623c955d7b199f09401732cf57417fc2cerion         }
3580b85e8bba97fdae7d892f7bfd12e4601307e4721dcerion         break;
3581b85e8bba97fdae7d892f7bfd12e4601307e4721dcerion
3582e9d361ab43518b6dfbd3d846f48859534659dee0cerion      case 0x00A: // addc      (Add Carrying, PPC32 p348)
3583d953ebb9b04cbad6891676df597bf0c542b1ec89cerion         DIP("addc%s%s r%u,r%u,r%u\n",
35845b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion             flag_OE ? "o" : "", flag_rC ? ".":"",
358576de5cf615380b23b4b5bcced6541233cd4a93a0cerion             rD_addr, rA_addr, rB_addr);
35862831b00c4950d6c2b061def05fd67528fe132ececerion         assign( rD, binop( mkSzOp(ty, Iop_Add8),
3587d953ebb9b04cbad6891676df597bf0c542b1ec89cerion                            mkexpr(rA), mkexpr(rB)) );
35885b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion         set_XER_CA( ty, PPCG_FLAG_OP_ADD,
358976de5cf615380b23b4b5bcced6541233cd4a93a0cerion                     mkexpr(rD), mkexpr(rA), mkexpr(rB),
35902831b00c4950d6c2b061def05fd67528fe132ececerion                     mkSzImm(ty, 0)/*old xer.ca, which is ignored*/ );
359170e2412f623c955d7b199f09401732cf57417fc2cerion         if (flag_OE) {
35925b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion            set_XER_OV( ty, PPCG_FLAG_OP_ADD,
359376de5cf615380b23b4b5bcced6541233cd4a93a0cerion                        mkexpr(rD), mkexpr(rA), mkexpr(rB) );
359470e2412f623c955d7b199f09401732cf57417fc2cerion         }
3595b85e8bba97fdae7d892f7bfd12e4601307e4721dcerion         break;
3596b85e8bba97fdae7d892f7bfd12e4601307e4721dcerion
3597b51f0f4f33256638ed953156a2635aa739b232f1sewardj      case 0x08A: { // adde      (Add Extended, PPC32 p349)
35982831b00c4950d6c2b061def05fd67528fe132ececerion         IRTemp old_xer_ca = newTemp(ty);
3599d953ebb9b04cbad6891676df597bf0c542b1ec89cerion         DIP("adde%s%s r%u,r%u,r%u\n",
36005b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion             flag_OE ? "o" : "", flag_rC ? ".":"",
360176de5cf615380b23b4b5bcced6541233cd4a93a0cerion             rD_addr, rA_addr, rB_addr);
3602b85e8bba97fdae7d892f7bfd12e4601307e4721dcerion         // rD = rA + rB + XER[CA]
3603e9d8a26b690c2561ac54ab0cd6ad83ecbadcbe76sewardj         assign( old_xer_ca, mkWidenFrom32(ty, getXER_CA32(), False) );
36042831b00c4950d6c2b061def05fd67528fe132ececerion         assign( rD, binop( mkSzOp(ty, Iop_Add8), mkexpr(rA),
36052831b00c4950d6c2b061def05fd67528fe132ececerion                            binop( mkSzOp(ty, Iop_Add8),
36062831b00c4950d6c2b061def05fd67528fe132ececerion                                   mkexpr(rB), mkexpr(old_xer_ca))) );
36075b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion         set_XER_CA( ty, PPCG_FLAG_OP_ADDE,
360876de5cf615380b23b4b5bcced6541233cd4a93a0cerion                     mkexpr(rD), mkexpr(rA), mkexpr(rB),
36092831b00c4950d6c2b061def05fd67528fe132ececerion                     mkexpr(old_xer_ca) );
361070e2412f623c955d7b199f09401732cf57417fc2cerion         if (flag_OE) {
36115b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion            set_XER_OV( ty, PPCG_FLAG_OP_ADDE,
361276de5cf615380b23b4b5bcced6541233cd4a93a0cerion                        mkexpr(rD), mkexpr(rA), mkexpr(rB) );
361370e2412f623c955d7b199f09401732cf57417fc2cerion         }
3614b85e8bba97fdae7d892f7bfd12e4601307e4721dcerion         break;
3615b51f0f4f33256638ed953156a2635aa739b232f1sewardj      }
3616b51f0f4f33256638ed953156a2635aa739b232f1sewardj
36175b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion      case 0x0EA: { // addme     (Add to Minus One Extended, PPC32 p354)
36182831b00c4950d6c2b061def05fd67528fe132ececerion         IRTemp old_xer_ca = newTemp(ty);
36192831b00c4950d6c2b061def05fd67528fe132ececerion         IRExpr *min_one;
362076de5cf615380b23b4b5bcced6541233cd4a93a0cerion         if (rB_addr != 0) {
36215b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion            vex_printf("dis_int_arith(ppc)(addme,rB_addr)\n");
3622b85e8bba97fdae7d892f7bfd12e4601307e4721dcerion            return False;
3623b85e8bba97fdae7d892f7bfd12e4601307e4721dcerion         }
3624d953ebb9b04cbad6891676df597bf0c542b1ec89cerion         DIP("addme%s%s r%u,r%u,r%u\n",
36255b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion             flag_OE ? "o" : "", flag_rC ? ".":"",
362676de5cf615380b23b4b5bcced6541233cd4a93a0cerion             rD_addr, rA_addr, rB_addr);
362770e2412f623c955d7b199f09401732cf57417fc2cerion         // rD = rA + (-1) + XER[CA]
362870e2412f623c955d7b199f09401732cf57417fc2cerion         // => Just another form of adde
3629e9d8a26b690c2561ac54ab0cd6ad83ecbadcbe76sewardj         assign( old_xer_ca, mkWidenFrom32(ty, getXER_CA32(), False) );
36302831b00c4950d6c2b061def05fd67528fe132ececerion         min_one = mkSzImm(ty, (Long)-1);
36312831b00c4950d6c2b061def05fd67528fe132ececerion         assign( rD, binop( mkSzOp(ty, Iop_Add8), mkexpr(rA),
36322831b00c4950d6c2b061def05fd67528fe132ececerion                            binop( mkSzOp(ty, Iop_Add8),
36332831b00c4950d6c2b061def05fd67528fe132ececerion                                   min_one, mkexpr(old_xer_ca)) ));
36345b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion         set_XER_CA( ty, PPCG_FLAG_OP_ADDE,
3635d953ebb9b04cbad6891676df597bf0c542b1ec89cerion                     mkexpr(rD), mkexpr(rA), min_one,
36362831b00c4950d6c2b061def05fd67528fe132ececerion                     mkexpr(old_xer_ca) );
363770e2412f623c955d7b199f09401732cf57417fc2cerion         if (flag_OE) {
36385b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion            set_XER_OV( ty, PPCG_FLAG_OP_ADDE,
3639d953ebb9b04cbad6891676df597bf0c542b1ec89cerion                        mkexpr(rD), mkexpr(rA), min_one );
364070e2412f623c955d7b199f09401732cf57417fc2cerion         }
3641b85e8bba97fdae7d892f7bfd12e4601307e4721dcerion         break;
3642b51f0f4f33256638ed953156a2635aa739b232f1sewardj      }
3643b51f0f4f33256638ed953156a2635aa739b232f1sewardj
3644b51f0f4f33256638ed953156a2635aa739b232f1sewardj      case 0x0CA: { // addze      (Add to Zero Extended, PPC32 p355)
36452831b00c4950d6c2b061def05fd67528fe132ececerion         IRTemp old_xer_ca = newTemp(ty);
364676de5cf615380b23b4b5bcced6541233cd4a93a0cerion         if (rB_addr != 0) {
36475b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion            vex_printf("dis_int_arith(ppc)(addze,rB_addr)\n");
3648b85e8bba97fdae7d892f7bfd12e4601307e4721dcerion            return False;
3649b85e8bba97fdae7d892f7bfd12e4601307e4721dcerion         }
3650d953ebb9b04cbad6891676df597bf0c542b1ec89cerion         DIP("addze%s%s r%u,r%u,r%u\n",
36515b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion             flag_OE ? "o" : "", flag_rC ? ".":"",
365276de5cf615380b23b4b5bcced6541233cd4a93a0cerion             rD_addr, rA_addr, rB_addr);
365370e2412f623c955d7b199f09401732cf57417fc2cerion         // rD = rA + (0) + XER[CA]
365470e2412f623c955d7b199f09401732cf57417fc2cerion         // => Just another form of adde
3655e9d8a26b690c2561ac54ab0cd6ad83ecbadcbe76sewardj         assign( old_xer_ca, mkWidenFrom32(ty, getXER_CA32(), False) );
36562831b00c4950d6c2b061def05fd67528fe132ececerion         assign( rD, binop( mkSzOp(ty, Iop_Add8),
36572831b00c4950d6c2b061def05fd67528fe132ececerion                            mkexpr(rA), mkexpr(old_xer_ca)) );
36585b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion         set_XER_CA( ty, PPCG_FLAG_OP_ADDE,
36592831b00c4950d6c2b061def05fd67528fe132ececerion                     mkexpr(rD), mkexpr(rA), mkSzImm(ty, 0),
36602831b00c4950d6c2b061def05fd67528fe132ececerion                     mkexpr(old_xer_ca) );
366170e2412f623c955d7b199f09401732cf57417fc2cerion         if (flag_OE) {
36625b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion            set_XER_OV( ty, PPCG_FLAG_OP_ADDE,
36632831b00c4950d6c2b061def05fd67528fe132ececerion                        mkexpr(rD), mkexpr(rA), mkSzImm(ty, 0) );
366470e2412f623c955d7b199f09401732cf57417fc2cerion         }
3665b85e8bba97fdae7d892f7bfd12e4601307e4721dcerion         break;
3666b51f0f4f33256638ed953156a2635aa739b232f1sewardj      }
3667b85e8bba97fdae7d892f7bfd12e4601307e4721dcerion
3668e9d361ab43518b6dfbd3d846f48859534659dee0cerion      case 0x1EB: // divw       (Divide Word, PPC32 p388)
3669d953ebb9b04cbad6891676df597bf0c542b1ec89cerion         DIP("divw%s%s r%u,r%u,r%u\n",
36705b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion             flag_OE ? "o" : "", flag_rC ? ".":"",
367176de5cf615380b23b4b5bcced6541233cd4a93a0cerion             rD_addr, rA_addr, rB_addr);
3672d953ebb9b04cbad6891676df597bf0c542b1ec89cerion         if (mode64) {
36732831b00c4950d6c2b061def05fd67528fe132ececerion            /* Note:
36742831b00c4950d6c2b061def05fd67528fe132ececerion               XER settings are mode independent, and reflect the
36752831b00c4950d6c2b061def05fd67528fe132ececerion               overflow of the low-order 32bit result
36762831b00c4950d6c2b061def05fd67528fe132ececerion               CR0[LT|GT|EQ] are undefined if flag_rC && mode64
36772831b00c4950d6c2b061def05fd67528fe132ececerion            */
3678bb01b7cbfd84c27dd213f67a144ea5a99af36961cerion            /* rD[hi32] are undefined: setting them to sign of lo32
3679bb01b7cbfd84c27dd213f67a144ea5a99af36961cerion                - makes set_CR0 happy */
3680bb01b7cbfd84c27dd213f67a144ea5a99af36961cerion            IRExpr* dividend = mk64lo32Sto64( mkexpr(rA) );
3681bb01b7cbfd84c27dd213f67a144ea5a99af36961cerion            IRExpr* divisor  = mk64lo32Sto64( mkexpr(rB) );
36825b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion            assign( rD, mk64lo32Uto64( binop(Iop_DivS64, dividend,
36835b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion                                                         divisor) ) );
3684d953ebb9b04cbad6891676df597bf0c542b1ec89cerion            if (flag_OE) {
36855b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion               set_XER_OV( ty, PPCG_FLAG_OP_DIVW,
3686f0de28cf1a762b0d6f74c93d3532c89a230673bbcerion                           mkexpr(rD), dividend, divisor );
3687d953ebb9b04cbad6891676df597bf0c542b1ec89cerion            }
3688d953ebb9b04cbad6891676df597bf0c542b1ec89cerion         } else {
3689d953ebb9b04cbad6891676df597bf0c542b1ec89cerion            assign( rD, binop(Iop_DivS32, mkexpr(rA), mkexpr(rB)) );
3690d953ebb9b04cbad6891676df597bf0c542b1ec89cerion            if (flag_OE) {
36915b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion               set_XER_OV( ty, PPCG_FLAG_OP_DIVW,
3692d953ebb9b04cbad6891676df597bf0c542b1ec89cerion                           mkexpr(rD), mkexpr(rA), mkexpr(rB) );
3693d953ebb9b04cbad6891676df597bf0c542b1ec89cerion            }
369470e2412f623c955d7b199f09401732cf57417fc2cerion         }
3695b85e8bba97fdae7d892f7bfd12e4601307e4721dcerion         /* Note:
3696b85e8bba97fdae7d892f7bfd12e4601307e4721dcerion            if (0x8000_0000 / -1) or (x / 0)
369776de5cf615380b23b4b5bcced6541233cd4a93a0cerion            => rD=undef, if(flag_rC) CR7=undef, if(flag_OE) XER_OV=1
3698b85e8bba97fdae7d892f7bfd12e4601307e4721dcerion            => But _no_ exception raised. */
3699b85e8bba97fdae7d892f7bfd12e4601307e4721dcerion         break;
3700b85e8bba97fdae7d892f7bfd12e4601307e4721dcerion
3701e9d361ab43518b6dfbd3d846f48859534659dee0cerion      case 0x1CB: // divwu      (Divide Word Unsigned, PPC32 p389)
3702d953ebb9b04cbad6891676df597bf0c542b1ec89cerion         DIP("divwu%s%s r%u,r%u,r%u\n",
37035b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion             flag_OE ? "o" : "", flag_rC ? ".":"",
370476de5cf615380b23b4b5bcced6541233cd4a93a0cerion             rD_addr, rA_addr, rB_addr);
3705d953ebb9b04cbad6891676df597bf0c542b1ec89cerion         if (mode64) {
37062831b00c4950d6c2b061def05fd67528fe132ececerion            /* Note:
37072831b00c4950d6c2b061def05fd67528fe132ececerion               XER settings are mode independent, and reflect the
37082831b00c4950d6c2b061def05fd67528fe132ececerion               overflow of the low-order 32bit result
37092831b00c4950d6c2b061def05fd67528fe132ececerion               CR0[LT|GT|EQ] are undefined if flag_rC && mode64
37102831b00c4950d6c2b061def05fd67528fe132ececerion            */
3711bb01b7cbfd84c27dd213f67a144ea5a99af36961cerion            IRExpr* dividend = mk64lo32Uto64( mkexpr(rA) );
3712bb01b7cbfd84c27dd213f67a144ea5a99af36961cerion            IRExpr* divisor  = mk64lo32Uto64( mkexpr(rB) );
37135b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion            assign( rD, mk64lo32Uto64( binop(Iop_DivU64, dividend,
37145b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion                                                         divisor) ) );
3715d953ebb9b04cbad6891676df597bf0c542b1ec89cerion            if (flag_OE) {
37165b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion               set_XER_OV( ty, PPCG_FLAG_OP_DIVWU,
3717f0de28cf1a762b0d6f74c93d3532c89a230673bbcerion                           mkexpr(rD), dividend, divisor );
3718d953ebb9b04cbad6891676df597bf0c542b1ec89cerion            }
37192831b00c4950d6c2b061def05fd67528fe132ececerion         } else {
3720d953ebb9b04cbad6891676df597bf0c542b1ec89cerion            assign( rD, binop(Iop_DivU32, mkexpr(rA), mkexpr(rB)) );
3721d953ebb9b04cbad6891676df597bf0c542b1ec89cerion            if (flag_OE) {
37225b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion               set_XER_OV( ty, PPCG_FLAG_OP_DIVWU,
3723d953ebb9b04cbad6891676df597bf0c542b1ec89cerion                           mkexpr(rD), mkexpr(rA), mkexpr(rB) );
3724d953ebb9b04cbad6891676df597bf0c542b1ec89cerion            }
372570e2412f623c955d7b199f09401732cf57417fc2cerion         }
3726b85e8bba97fdae7d892f7bfd12e4601307e4721dcerion         /* Note: ditto comment divw, for (x / 0) */
3727b85e8bba97fdae7d892f7bfd12e4601307e4721dcerion         break;
3728b85e8bba97fdae7d892f7bfd12e4601307e4721dcerion
3729e9d361ab43518b6dfbd3d846f48859534659dee0cerion      case 0x04B: // mulhw      (Multiply High Word, PPC32 p488)
3730b85e8bba97fdae7d892f7bfd12e4601307e4721dcerion         if (flag_OE != 0) {
37315b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion            vex_printf("dis_int_arith(ppc)(mulhw,flag_OE)\n");
3732b85e8bba97fdae7d892f7bfd12e4601307e4721dcerion            return False;
3733b85e8bba97fdae7d892f7bfd12e4601307e4721dcerion         }
37345b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion         DIP("mulhw%s r%u,r%u,r%u\n", flag_rC ? ".":"",
373576de5cf615380b23b4b5bcced6541233cd4a93a0cerion             rD_addr, rA_addr, rB_addr);
37362831b00c4950d6c2b061def05fd67528fe132ececerion         if (mode64) {
3737bb01b7cbfd84c27dd213f67a144ea5a99af36961cerion            /* rD[hi32] are undefined: setting them to sign of lo32
3738bb01b7cbfd84c27dd213f67a144ea5a99af36961cerion                - makes set_CR0 happy */
3739bb01b7cbfd84c27dd213f67a144ea5a99af36961cerion            assign( rD, binop(Iop_Sar64,
3740bb01b7cbfd84c27dd213f67a144ea5a99af36961cerion                           binop(Iop_Mul64,
3741bb01b7cbfd84c27dd213f67a144ea5a99af36961cerion                                 mk64lo32Sto64( mkexpr(rA) ),
3742bb01b7cbfd84c27dd213f67a144ea5a99af36961cerion                                 mk64lo32Sto64( mkexpr(rB) )),
3743bb01b7cbfd84c27dd213f67a144ea5a99af36961cerion                              mkU8(32)) );
37442831b00c4950d6c2b061def05fd67528fe132ececerion         } else {
3745d953ebb9b04cbad6891676df597bf0c542b1ec89cerion            assign( rD, unop(Iop_64HIto32,
3746d953ebb9b04cbad6891676df597bf0c542b1ec89cerion                             binop(Iop_MullS32,
3747d953ebb9b04cbad6891676df597bf0c542b1ec89cerion                                   mkexpr(rA), mkexpr(rB))) );
37482831b00c4950d6c2b061def05fd67528fe132ececerion         }
3749b85e8bba97fdae7d892f7bfd12e4601307e4721dcerion         break;
3750b85e8bba97fdae7d892f7bfd12e4601307e4721dcerion
37515b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion      case 0x00B: // mulhwu    (Multiply High Word Unsigned, PPC32 p489)
3752b85e8bba97fdae7d892f7bfd12e4601307e4721dcerion         if (flag_OE != 0) {
37535b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion            vex_printf("dis_int_arith(ppc)(mulhwu,flag_OE)\n");
3754b85e8bba97fdae7d892f7bfd12e4601307e4721dcerion            return False;
3755b85e8bba97fdae7d892f7bfd12e4601307e4721dcerion         }
37565b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion         DIP("mulhwu%s r%u,r%u,r%u\n", flag_rC ? ".":"",
375776de5cf615380b23b4b5bcced6541233cd4a93a0cerion             rD_addr, rA_addr, rB_addr);
37582831b00c4950d6c2b061def05fd67528fe132ececerion         if (mode64) {
3759bb01b7cbfd84c27dd213f67a144ea5a99af36961cerion            /* rD[hi32] are undefined: setting them to sign of lo32
3760bb01b7cbfd84c27dd213f67a144ea5a99af36961cerion                - makes set_CR0 happy */
3761bb01b7cbfd84c27dd213f67a144ea5a99af36961cerion            assign( rD, binop(Iop_Sar64,
3762bb01b7cbfd84c27dd213f67a144ea5a99af36961cerion                           binop(Iop_Mul64,
3763bb01b7cbfd84c27dd213f67a144ea5a99af36961cerion                                 mk64lo32Uto64( mkexpr(rA) ),
3764bb01b7cbfd84c27dd213f67a144ea5a99af36961cerion                                 mk64lo32Uto64( mkexpr(rB) ) ),
3765bb01b7cbfd84c27dd213f67a144ea5a99af36961cerion                              mkU8(32)) );
37662831b00c4950d6c2b061def05fd67528fe132ececerion         } else {
3767d953ebb9b04cbad6891676df597bf0c542b1ec89cerion            assign( rD, unop(Iop_64HIto32,
3768d953ebb9b04cbad6891676df597bf0c542b1ec89cerion                             binop(Iop_MullU32,
3769d953ebb9b04cbad6891676df597bf0c542b1ec89cerion                                   mkexpr(rA), mkexpr(rB))) );
37702831b00c4950d6c2b061def05fd67528fe132ececerion         }
3771b85e8bba97fdae7d892f7bfd12e4601307e4721dcerion         break;
3772b85e8bba97fdae7d892f7bfd12e4601307e4721dcerion
3773e9d361ab43518b6dfbd3d846f48859534659dee0cerion      case 0x0EB: // mullw      (Multiply Low Word, PPC32 p491)
3774d953ebb9b04cbad6891676df597bf0c542b1ec89cerion         DIP("mullw%s%s r%u,r%u,r%u\n",
37755b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion             flag_OE ? "o" : "", flag_rC ? ".":"",
377676de5cf615380b23b4b5bcced6541233cd4a93a0cerion             rD_addr, rA_addr, rB_addr);
37772831b00c4950d6c2b061def05fd67528fe132ececerion         if (mode64) {
3778bb01b7cbfd84c27dd213f67a144ea5a99af36961cerion            /* rD[hi32] are undefined: setting them to sign of lo32
3779bb01b7cbfd84c27dd213f67a144ea5a99af36961cerion                - set_XER_OV() and set_CR0() depend on this */
3780bb01b7cbfd84c27dd213f67a144ea5a99af36961cerion            IRExpr *a = unop(Iop_64to32, mkexpr(rA) );
3781bb01b7cbfd84c27dd213f67a144ea5a99af36961cerion            IRExpr *b = unop(Iop_64to32, mkexpr(rB) );
3782bb01b7cbfd84c27dd213f67a144ea5a99af36961cerion            assign( rD, binop(Iop_MullS32, a, b) );
3783bb01b7cbfd84c27dd213f67a144ea5a99af36961cerion            if (flag_OE) {
37845b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion               set_XER_OV( ty, PPCG_FLAG_OP_MULLW,
3785bb01b7cbfd84c27dd213f67a144ea5a99af36961cerion                           mkexpr(rD),
3786bb01b7cbfd84c27dd213f67a144ea5a99af36961cerion                           unop(Iop_32Uto64, a), unop(Iop_32Uto64, b) );
3787bb01b7cbfd84c27dd213f67a144ea5a99af36961cerion            }
37882831b00c4950d6c2b061def05fd67528fe132ececerion         } else {
3789d953ebb9b04cbad6891676df597bf0c542b1ec89cerion            assign( rD, unop(Iop_64to32,
3790d953ebb9b04cbad6891676df597bf0c542b1ec89cerion                             binop(Iop_MullU32,
3791d953ebb9b04cbad6891676df597bf0c542b1ec89cerion                                   mkexpr(rA), mkexpr(rB))) );
3792bb01b7cbfd84c27dd213f67a144ea5a99af36961cerion            if (flag_OE) {
37935b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion               set_XER_OV( ty, PPCG_FLAG_OP_MULLW,
3794bb01b7cbfd84c27dd213f67a144ea5a99af36961cerion                           mkexpr(rD), mkexpr(rA), mkexpr(rB) );
3795bb01b7cbfd84c27dd213f67a144ea5a99af36961cerion            }
379670e2412f623c955d7b199f09401732cf57417fc2cerion         }
3797b85e8bba97fdae7d892f7bfd12e4601307e4721dcerion         break;
3798b85e8bba97fdae7d892f7bfd12e4601307e4721dcerion
3799e9d361ab43518b6dfbd3d846f48859534659dee0cerion      case 0x068: // neg        (Negate, PPC32 p493)
380076de5cf615380b23b4b5bcced6541233cd4a93a0cerion         if (rB_addr != 0) {
38015b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion            vex_printf("dis_int_arith(ppc)(neg,rB_addr)\n");
3802b85e8bba97fdae7d892f7bfd12e4601307e4721dcerion            return False;
3803b85e8bba97fdae7d892f7bfd12e4601307e4721dcerion         }
3804d953ebb9b04cbad6891676df597bf0c542b1ec89cerion         DIP("neg%s%s r%u,r%u\n",
38055b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion             flag_OE ? "o" : "", flag_rC ? ".":"",
380676de5cf615380b23b4b5bcced6541233cd4a93a0cerion             rD_addr, rA_addr);
3807d953ebb9b04cbad6891676df597bf0c542b1ec89cerion         // rD = (~rA) + 1
38082831b00c4950d6c2b061def05fd67528fe132ececerion         assign( rD, binop( mkSzOp(ty, Iop_Add8),
38092831b00c4950d6c2b061def05fd67528fe132ececerion                            unop( mkSzOp(ty, Iop_Not8), mkexpr(rA) ),
38102831b00c4950d6c2b061def05fd67528fe132ececerion                            mkSzImm(ty, 1)) );
381170e2412f623c955d7b199f09401732cf57417fc2cerion         if (flag_OE) {
38125b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion            set_XER_OV( ty, PPCG_FLAG_OP_NEG,
381376de5cf615380b23b4b5bcced6541233cd4a93a0cerion                        mkexpr(rD), mkexpr(rA), mkexpr(rB) );
381470e2412f623c955d7b199f09401732cf57417fc2cerion         }
3815b85e8bba97fdae7d892f7bfd12e4601307e4721dcerion         break;
3816b85e8bba97fdae7d892f7bfd12e4601307e4721dcerion
3817e9d361ab43518b6dfbd3d846f48859534659dee0cerion      case 0x028: // subf       (Subtract From, PPC32 p537)
3818d953ebb9b04cbad6891676df597bf0c542b1ec89cerion         DIP("subf%s%s r%u,r%u,r%u\n",
38195b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion             flag_OE ? "o" : "", flag_rC ? ".":"",
382076de5cf615380b23b4b5bcced6541233cd4a93a0cerion             rD_addr, rA_addr, rB_addr);
382101908478d5402ff3f7a19780c8b37ec5c8bf8973cerion         // rD = rB - rA
38222831b00c4950d6c2b061def05fd67528fe132ececerion         assign( rD, binop( mkSzOp(ty, Iop_Sub8),
3823d953ebb9b04cbad6891676df597bf0c542b1ec89cerion                            mkexpr(rB), mkexpr(rA)) );
382470e2412f623c955d7b199f09401732cf57417fc2cerion         if (flag_OE) {
38255b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion            set_XER_OV( ty, PPCG_FLAG_OP_SUBF,
382676de5cf615380b23b4b5bcced6541233cd4a93a0cerion                        mkexpr(rD), mkexpr(rA), mkexpr(rB) );
382770e2412f623c955d7b199f09401732cf57417fc2cerion         }
3828b85e8bba97fdae7d892f7bfd12e4601307e4721dcerion         break;
3829b85e8bba97fdae7d892f7bfd12e4601307e4721dcerion
3830e9d361ab43518b6dfbd3d846f48859534659dee0cerion      case 0x008: // subfc      (Subtract from Carrying, PPC32 p538)
3831d953ebb9b04cbad6891676df597bf0c542b1ec89cerion         DIP("subfc%s%s r%u,r%u,r%u\n",
38325b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion             flag_OE ? "o" : "", flag_rC ? ".":"",
383376de5cf615380b23b4b5bcced6541233cd4a93a0cerion             rD_addr, rA_addr, rB_addr);
383401908478d5402ff3f7a19780c8b37ec5c8bf8973cerion         // rD = rB - rA
38352831b00c4950d6c2b061def05fd67528fe132ececerion         assign( rD, binop( mkSzOp(ty, Iop_Sub8),
3836d953ebb9b04cbad6891676df597bf0c542b1ec89cerion                            mkexpr(rB), mkexpr(rA)) );
38375b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion         set_XER_CA( ty, PPCG_FLAG_OP_SUBFC,
383876de5cf615380b23b4b5bcced6541233cd4a93a0cerion                     mkexpr(rD), mkexpr(rA), mkexpr(rB),
38392831b00c4950d6c2b061def05fd67528fe132ececerion                     mkSzImm(ty, 0)/*old xer.ca, which is ignored*/ );
384070e2412f623c955d7b199f09401732cf57417fc2cerion         if (flag_OE) {
38415b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion            set_XER_OV( ty, PPCG_FLAG_OP_SUBFC,
384276de5cf615380b23b4b5bcced6541233cd4a93a0cerion                        mkexpr(rD), mkexpr(rA), mkexpr(rB) );
384370e2412f623c955d7b199f09401732cf57417fc2cerion         }
3844b85e8bba97fdae7d892f7bfd12e4601307e4721dcerion         break;
3845b85e8bba97fdae7d892f7bfd12e4601307e4721dcerion
3846b51f0f4f33256638ed953156a2635aa739b232f1sewardj      case 0x088: {// subfe      (Subtract from Extended, PPC32 p539)
38472831b00c4950d6c2b061def05fd67528fe132ececerion         IRTemp old_xer_ca = newTemp(ty);
3848d953ebb9b04cbad6891676df597bf0c542b1ec89cerion         DIP("subfe%s%s r%u,r%u,r%u\n",
38495b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion             flag_OE ? "o" : "", flag_rC ? ".":"",
385076de5cf615380b23b4b5bcced6541233cd4a93a0cerion             rD_addr, rA_addr, rB_addr);
3851b85e8bba97fdae7d892f7bfd12e4601307e4721dcerion         // rD = (log not)rA + rB + XER[CA]
3852e9d8a26b690c2561ac54ab0cd6ad83ecbadcbe76sewardj         assign( old_xer_ca, mkWidenFrom32(ty, getXER_CA32(), False) );
38532831b00c4950d6c2b061def05fd67528fe132ececerion         assign( rD, binop( mkSzOp(ty, Iop_Add8),
38542831b00c4950d6c2b061def05fd67528fe132ececerion                            unop( mkSzOp(ty, Iop_Not8), mkexpr(rA)),
38552831b00c4950d6c2b061def05fd67528fe132ececerion                            binop( mkSzOp(ty, Iop_Add8),
38562831b00c4950d6c2b061def05fd67528fe132ececerion                                   mkexpr(rB), mkexpr(old_xer_ca))) );
38575b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion         set_XER_CA( ty, PPCG_FLAG_OP_SUBFE,
385876de5cf615380b23b4b5bcced6541233cd4a93a0cerion                     mkexpr(rD), mkexpr(rA), mkexpr(rB),
38592831b00c4950d6c2b061def05fd67528fe132ececerion                     mkexpr(old_xer_ca) );
386070e2412f623c955d7b199f09401732cf57417fc2cerion         if (flag_OE) {
38615b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion            set_XER_OV( ty, PPCG_FLAG_OP_SUBFE,
386276de5cf615380b23b4b5bcced6541233cd4a93a0cerion                        mkexpr(rD), mkexpr(rA), mkexpr(rB) );
386320ef5472eac767474c93b7835364a23f24c0ec5dsewardj         }
386420ef5472eac767474c93b7835364a23f24c0ec5dsewardj         break;
386520ef5472eac767474c93b7835364a23f24c0ec5dsewardj      }
386620ef5472eac767474c93b7835364a23f24c0ec5dsewardj
38675b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion      case 0x0E8: { // subfme    (Subtract from -1 Extended, PPC32 p541)
38682831b00c4950d6c2b061def05fd67528fe132ececerion         IRTemp old_xer_ca = newTemp(ty);
38692831b00c4950d6c2b061def05fd67528fe132ececerion         IRExpr *min_one;
387076de5cf615380b23b4b5bcced6541233cd4a93a0cerion         if (rB_addr != 0) {
38715b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion            vex_printf("dis_int_arith(ppc)(subfme,rB_addr)\n");
387220ef5472eac767474c93b7835364a23f24c0ec5dsewardj            return False;
387320ef5472eac767474c93b7835364a23f24c0ec5dsewardj         }
3874d953ebb9b04cbad6891676df597bf0c542b1ec89cerion         DIP("subfme%s%s r%u,r%u\n",
38755b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion             flag_OE ? "o" : "", flag_rC ? ".":"",
387676de5cf615380b23b4b5bcced6541233cd4a93a0cerion             rD_addr, rA_addr);
387720ef5472eac767474c93b7835364a23f24c0ec5dsewardj         // rD = (log not)rA + (-1) + XER[CA]
387820ef5472eac767474c93b7835364a23f24c0ec5dsewardj         // => Just another form of subfe
3879e9d8a26b690c2561ac54ab0cd6ad83ecbadcbe76sewardj         assign( old_xer_ca, mkWidenFrom32(ty, getXER_CA32(), False) );
38802831b00c4950d6c2b061def05fd67528fe132ececerion         min_one = mkSzImm(ty, (Long)-1);
38812831b00c4950d6c2b061def05fd67528fe132ececerion         assign( rD, binop( mkSzOp(ty, Iop_Add8),
38822831b00c4950d6c2b061def05fd67528fe132ececerion                            unop( mkSzOp(ty, Iop_Not8), mkexpr(rA)),
38832831b00c4950d6c2b061def05fd67528fe132ececerion                            binop( mkSzOp(ty, Iop_Add8),
38842831b00c4950d6c2b061def05fd67528fe132ececerion                                   min_one, mkexpr(old_xer_ca))) );
38855b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion         set_XER_CA( ty, PPCG_FLAG_OP_SUBFE,
3886d953ebb9b04cbad6891676df597bf0c542b1ec89cerion                     mkexpr(rD), mkexpr(rA), min_one,
38872831b00c4950d6c2b061def05fd67528fe132ececerion                     mkexpr(old_xer_ca) );
388820ef5472eac767474c93b7835364a23f24c0ec5dsewardj         if (flag_OE) {
38895b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion            set_XER_OV( ty, PPCG_FLAG_OP_SUBFE,
3890d953ebb9b04cbad6891676df597bf0c542b1ec89cerion                        mkexpr(rD), mkexpr(rA), min_one );
389170e2412f623c955d7b199f09401732cf57417fc2cerion         }
3892b85e8bba97fdae7d892f7bfd12e4601307e4721dcerion         break;
3893b51f0f4f33256638ed953156a2635aa739b232f1sewardj      }
3894b51f0f4f33256638ed953156a2635aa739b232f1sewardj
38955b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion      case 0x0C8: { // subfze  (Subtract from Zero Extended, PPC32 p542)
38962831b00c4950d6c2b061def05fd67528fe132ececerion         IRTemp old_xer_ca = newTemp(ty);
389776de5cf615380b23b4b5bcced6541233cd4a93a0cerion         if (rB_addr != 0) {
38985b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion            vex_printf("dis_int_arith(ppc)(subfze,rB_addr)\n");
3899b85e8bba97fdae7d892f7bfd12e4601307e4721dcerion            return False;
3900b85e8bba97fdae7d892f7bfd12e4601307e4721dcerion         }
3901d953ebb9b04cbad6891676df597bf0c542b1ec89cerion         DIP("subfze%s%s r%u,r%u\n",
39025b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion             flag_OE ? "o" : "", flag_rC ? ".":"",
390376de5cf615380b23b4b5bcced6541233cd4a93a0cerion             rD_addr, rA_addr);
390470e2412f623c955d7b199f09401732cf57417fc2cerion         // rD = (log not)rA + (0) + XER[CA]
390570e2412f623c955d7b199f09401732cf57417fc2cerion         // => Just another form of subfe
3906e9d8a26b690c2561ac54ab0cd6ad83ecbadcbe76sewardj         assign( old_xer_ca, mkWidenFrom32(ty, getXER_CA32(), False) );
39072831b00c4950d6c2b061def05fd67528fe132ececerion         assign( rD, binop( mkSzOp(ty, Iop_Add8),
39082831b00c4950d6c2b061def05fd67528fe132ececerion                           unop( mkSzOp(ty, Iop_Not8),
39092831b00c4950d6c2b061def05fd67528fe132ececerion                                 mkexpr(rA)), mkexpr(old_xer_ca)) );
39105b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion         set_XER_CA( ty, PPCG_FLAG_OP_SUBFE,
39112831b00c4950d6c2b061def05fd67528fe132ececerion                     mkexpr(rD), mkexpr(rA), mkSzImm(ty, 0),
39122831b00c4950d6c2b061def05fd67528fe132ececerion                     mkexpr(old_xer_ca) );
391370e2412f623c955d7b199f09401732cf57417fc2cerion         if (flag_OE) {
39145b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion            set_XER_OV( ty, PPCG_FLAG_OP_SUBFE,
39152831b00c4950d6c2b061def05fd67528fe132ececerion                        mkexpr(rD), mkexpr(rA), mkSzImm(ty, 0) );
391670e2412f623c955d7b199f09401732cf57417fc2cerion         }
3917b85e8bba97fdae7d892f7bfd12e4601307e4721dcerion         break;
3918b51f0f4f33256638ed953156a2635aa739b232f1sewardj      }
3919b85e8bba97fdae7d892f7bfd12e4601307e4721dcerion
3920f0de28cf1a762b0d6f74c93d3532c89a230673bbcerion
3921f0de28cf1a762b0d6f74c93d3532c89a230673bbcerion      /* 64bit Arithmetic */
39225b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion      case 0x49:  // mulhd (Multiply High DWord, PPC64 p539)
3923f0de28cf1a762b0d6f74c93d3532c89a230673bbcerion         if (flag_OE != 0) {
39245b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion            vex_printf("dis_int_arith(ppc)(mulhd,flagOE)\n");
3925f0de28cf1a762b0d6f74c93d3532c89a230673bbcerion            return False;
3926f0de28cf1a762b0d6f74c93d3532c89a230673bbcerion         }
39275b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion         DIP("mulhd%s r%u,r%u,r%u\n", flag_rC ? ".":"",
3928f0de28cf1a762b0d6f74c93d3532c89a230673bbcerion             rD_addr, rA_addr, rB_addr);
3929f0de28cf1a762b0d6f74c93d3532c89a230673bbcerion         assign( rD, unop(Iop_128HIto64,
393007b07a966a2fdbcf621251a0c1a8ab84807fb120cerion                          binop(Iop_MullS64,
3931f0de28cf1a762b0d6f74c93d3532c89a230673bbcerion                                mkexpr(rA), mkexpr(rB))) );
393207b07a966a2fdbcf621251a0c1a8ab84807fb120cerion
393307b07a966a2fdbcf621251a0c1a8ab84807fb120cerion         break;
3934f0de28cf1a762b0d6f74c93d3532c89a230673bbcerion
39355b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion      case 0x9:   // mulhdu  (Multiply High DWord Unsigned, PPC64 p540)
3936f0de28cf1a762b0d6f74c93d3532c89a230673bbcerion         if (flag_OE != 0) {
39375b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion            vex_printf("dis_int_arith(ppc)(mulhdu,flagOE)\n");
3938f0de28cf1a762b0d6f74c93d3532c89a230673bbcerion            return False;
3939f0de28cf1a762b0d6f74c93d3532c89a230673bbcerion         }
39405b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion         DIP("mulhdu%s r%u,r%u,r%u\n", flag_rC ? ".":"",
3941f0de28cf1a762b0d6f74c93d3532c89a230673bbcerion             rD_addr, rA_addr, rB_addr);
394207b07a966a2fdbcf621251a0c1a8ab84807fb120cerion         assign( rD, unop(Iop_128HIto64,
394307b07a966a2fdbcf621251a0c1a8ab84807fb120cerion                          binop(Iop_MullU64,
394407b07a966a2fdbcf621251a0c1a8ab84807fb120cerion                                mkexpr(rA), mkexpr(rB))) );
394507b07a966a2fdbcf621251a0c1a8ab84807fb120cerion         break;
3946f0de28cf1a762b0d6f74c93d3532c89a230673bbcerion
39475b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion      case 0xE9:  // mulld (Multiply Low DWord, PPC64 p543)
3948f0de28cf1a762b0d6f74c93d3532c89a230673bbcerion         DIP("mulld%s%s r%u,r%u,r%u\n",
39495b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion             flag_OE ? "o" : "", flag_rC ? ".":"",
3950f0de28cf1a762b0d6f74c93d3532c89a230673bbcerion             rD_addr, rA_addr, rB_addr);
3951f0de28cf1a762b0d6f74c93d3532c89a230673bbcerion         assign( rD, binop(Iop_Mul64, mkexpr(rA), mkexpr(rB)) );
3952f0de28cf1a762b0d6f74c93d3532c89a230673bbcerion         if (flag_OE) {
395338b79ace9613df76a5feb7a237226f4a4cc02ecdcarll            set_XER_OV( ty, PPCG_FLAG_OP_MULLD,
3954f0de28cf1a762b0d6f74c93d3532c89a230673bbcerion                        mkexpr(rD), mkexpr(rA), mkexpr(rB) );
3955f0de28cf1a762b0d6f74c93d3532c89a230673bbcerion         }
3956f0de28cf1a762b0d6f74c93d3532c89a230673bbcerion         break;
3957f0de28cf1a762b0d6f74c93d3532c89a230673bbcerion
39585b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion      case 0x1E9: // divd (Divide DWord, PPC64 p419)
3959f0de28cf1a762b0d6f74c93d3532c89a230673bbcerion         DIP("divd%s%s r%u,r%u,r%u\n",
39605b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion             flag_OE ? "o" : "", flag_rC ? ".":"",
3961f0de28cf1a762b0d6f74c93d3532c89a230673bbcerion             rD_addr, rA_addr, rB_addr);
396207b07a966a2fdbcf621251a0c1a8ab84807fb120cerion         assign( rD, binop(Iop_DivS64, mkexpr(rA), mkexpr(rB)) );
396307b07a966a2fdbcf621251a0c1a8ab84807fb120cerion         if (flag_OE) {
39645b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion            set_XER_OV( ty, PPCG_FLAG_OP_DIVW,
396507b07a966a2fdbcf621251a0c1a8ab84807fb120cerion                        mkexpr(rD), mkexpr(rA), mkexpr(rB) );
396607b07a966a2fdbcf621251a0c1a8ab84807fb120cerion         }
396707b07a966a2fdbcf621251a0c1a8ab84807fb120cerion         break;
3968f0de28cf1a762b0d6f74c93d3532c89a230673bbcerion         /* Note:
396907b07a966a2fdbcf621251a0c1a8ab84807fb120cerion            if (0x8000_0000_0000_0000 / -1) or (x / 0)
3970f0de28cf1a762b0d6f74c93d3532c89a230673bbcerion            => rD=undef, if(flag_rC) CR7=undef, if(flag_OE) XER_OV=1
3971f0de28cf1a762b0d6f74c93d3532c89a230673bbcerion            => But _no_ exception raised. */
3972f0de28cf1a762b0d6f74c93d3532c89a230673bbcerion
39735b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion      case 0x1C9: // divdu (Divide DWord Unsigned, PPC64 p420)
3974f0de28cf1a762b0d6f74c93d3532c89a230673bbcerion         DIP("divdu%s%s r%u,r%u,r%u\n",
39755b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion             flag_OE ? "o" : "", flag_rC ? ".":"",
3976f0de28cf1a762b0d6f74c93d3532c89a230673bbcerion             rD_addr, rA_addr, rB_addr);
397707b07a966a2fdbcf621251a0c1a8ab84807fb120cerion         assign( rD, binop(Iop_DivU64, mkexpr(rA), mkexpr(rB)) );
397807b07a966a2fdbcf621251a0c1a8ab84807fb120cerion         if (flag_OE) {
39795b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion            set_XER_OV( ty, PPCG_FLAG_OP_DIVWU,
398007b07a966a2fdbcf621251a0c1a8ab84807fb120cerion                        mkexpr(rD), mkexpr(rA), mkexpr(rB) );
398107b07a966a2fdbcf621251a0c1a8ab84807fb120cerion         }
398207b07a966a2fdbcf621251a0c1a8ab84807fb120cerion         break;
3983f0de28cf1a762b0d6f74c93d3532c89a230673bbcerion         /* Note: ditto comment divd, for (x / 0) */
3984f0de28cf1a762b0d6f74c93d3532c89a230673bbcerion
39854aa412af1d8166cc11f39a6e721df49431d23618sewardj      case 0x18B: // divweu (Divide Word Extended Unsigned)
39864aa412af1d8166cc11f39a6e721df49431d23618sewardj      {
39874aa412af1d8166cc11f39a6e721df49431d23618sewardj        /*
39884aa412af1d8166cc11f39a6e721df49431d23618sewardj         *  If (RA) >= (RB), or if an attempt is made to perform the division
39894aa412af1d8166cc11f39a6e721df49431d23618sewardj         *         <anything> / 0
39904aa412af1d8166cc11f39a6e721df49431d23618sewardj         * then the contents of register RD are undefined as are (if Rc=1) the contents of
39914aa412af1d8166cc11f39a6e721df49431d23618sewardj         * the LT, GT, and EQ bits of CR Field 0. In these cases, if OE=1 then OV is set
39924aa412af1d8166cc11f39a6e721df49431d23618sewardj         * to 1.
39934aa412af1d8166cc11f39a6e721df49431d23618sewardj         */
39944aa412af1d8166cc11f39a6e721df49431d23618sewardj         IRTemp res = newTemp(Ity_I32);
39954aa412af1d8166cc11f39a6e721df49431d23618sewardj         IRExpr * dividend, * divisor;
39964aa412af1d8166cc11f39a6e721df49431d23618sewardj         DIP("divweu%s%s r%u,r%u,r%u\n",
39974aa412af1d8166cc11f39a6e721df49431d23618sewardj             flag_OE ? "o" : "", flag_rC ? ".":"",
39984aa412af1d8166cc11f39a6e721df49431d23618sewardj                                         rD_addr, rA_addr, rB_addr);
39994aa412af1d8166cc11f39a6e721df49431d23618sewardj         if (mode64) {
40004aa412af1d8166cc11f39a6e721df49431d23618sewardj            dividend = unop( Iop_64to32, mkexpr( rA ) );
40014aa412af1d8166cc11f39a6e721df49431d23618sewardj            divisor = unop( Iop_64to32, mkexpr( rB ) );
40024aa412af1d8166cc11f39a6e721df49431d23618sewardj            assign( res, binop( Iop_DivU32E, dividend, divisor ) );
40034aa412af1d8166cc11f39a6e721df49431d23618sewardj            assign( rD, binop( Iop_32HLto64, mkU32( 0 ), mkexpr( res ) ) );
40044aa412af1d8166cc11f39a6e721df49431d23618sewardj         } else {
40054aa412af1d8166cc11f39a6e721df49431d23618sewardj            dividend = mkexpr( rA );
40064aa412af1d8166cc11f39a6e721df49431d23618sewardj            divisor =  mkexpr( rB );
40074aa412af1d8166cc11f39a6e721df49431d23618sewardj            assign( res, binop( Iop_DivU32E, dividend, divisor ) );
40084aa412af1d8166cc11f39a6e721df49431d23618sewardj            assign( rD, mkexpr( res) );
40094aa412af1d8166cc11f39a6e721df49431d23618sewardj         }
40104aa412af1d8166cc11f39a6e721df49431d23618sewardj
40114aa412af1d8166cc11f39a6e721df49431d23618sewardj         if (flag_OE) {
40124aa412af1d8166cc11f39a6e721df49431d23618sewardj            set_XER_OV_32( PPCG_FLAG_OP_DIVWEU,
40134aa412af1d8166cc11f39a6e721df49431d23618sewardj                           mkexpr(res), dividend, divisor );
40144aa412af1d8166cc11f39a6e721df49431d23618sewardj         }
40154aa412af1d8166cc11f39a6e721df49431d23618sewardj         break;
40164aa412af1d8166cc11f39a6e721df49431d23618sewardj      }
40174aa412af1d8166cc11f39a6e721df49431d23618sewardj
4018e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj      case 0x1AB: // divwe (Divide Word Extended)
4019e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj      {
4020e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj         /*
4021e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj          * If the quotient cannot be represented in 32 bits, or if an
4022e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj          * attempt is made to perform the division
4023e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj          *      <anything> / 0
4024e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj          * then the contents of register RD are undefined as are (if
4025e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj          * Rc=1) the contents of the LT, GT, and EQ bits of CR
4026e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj          * Field 0. In these cases, if OE=1 then OV is set to 1.
4027e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj          */
4028e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj
4029e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj         IRTemp res = newTemp(Ity_I32);
4030e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj         IRExpr * dividend, * divisor;
4031e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj         DIP("divwe%s%s r%u,r%u,r%u\n",
4032e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj             flag_OE ? "o" : "", flag_rC ? ".":"",
4033e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj                                         rD_addr, rA_addr, rB_addr);
4034e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj         if (mode64) {
4035e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj            dividend = unop( Iop_64to32, mkexpr( rA ) );
4036e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj            divisor = unop( Iop_64to32, mkexpr( rB ) );
4037e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj            assign( res, binop( Iop_DivS32E, dividend, divisor ) );
4038e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj            assign( rD, binop( Iop_32HLto64, mkU32( 0 ), mkexpr( res ) ) );
4039e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj         } else {
4040e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj            dividend = mkexpr( rA );
4041e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj            divisor =  mkexpr( rB );
4042e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj            assign( res, binop( Iop_DivS32E, dividend, divisor ) );
4043e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj            assign( rD, mkexpr( res) );
4044e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj         }
4045e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj
4046e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj         if (flag_OE) {
4047e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj            set_XER_OV_32( PPCG_FLAG_OP_DIVWE,
4048e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj                           mkexpr(res), dividend, divisor );
4049e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj         }
4050e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj         break;
4051e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj      }
4052e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj
4053e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj
40544aa412af1d8166cc11f39a6e721df49431d23618sewardj      case 0x1A9: // divde (Divide Doubleword Extended)
40554aa412af1d8166cc11f39a6e721df49431d23618sewardj        /*
40564aa412af1d8166cc11f39a6e721df49431d23618sewardj         * If the quotient cannot be represented in 64 bits, or if an
40574aa412af1d8166cc11f39a6e721df49431d23618sewardj         * attempt is made to perform the division
40584aa412af1d8166cc11f39a6e721df49431d23618sewardj         *      <anything> / 0
40594aa412af1d8166cc11f39a6e721df49431d23618sewardj         * then the contents of register RD are undefined as are (if
40604aa412af1d8166cc11f39a6e721df49431d23618sewardj         * Rc=1) the contents of the LT, GT, and EQ bits of CR
40614aa412af1d8166cc11f39a6e721df49431d23618sewardj         * Field 0. In these cases, if OE=1 then OV is set to 1.
40624aa412af1d8166cc11f39a6e721df49431d23618sewardj         */
40634aa412af1d8166cc11f39a6e721df49431d23618sewardj         DIP("divde%s%s r%u,r%u,r%u\n",
40644aa412af1d8166cc11f39a6e721df49431d23618sewardj             flag_OE ? "o" : "", flag_rC ? ".":"",
40654aa412af1d8166cc11f39a6e721df49431d23618sewardj             rD_addr, rA_addr, rB_addr);
40664aa412af1d8166cc11f39a6e721df49431d23618sewardj         assign( rD, binop(Iop_DivS64E, mkexpr(rA), mkexpr(rB)) );
40674aa412af1d8166cc11f39a6e721df49431d23618sewardj         if (flag_OE) {
40684aa412af1d8166cc11f39a6e721df49431d23618sewardj            set_XER_OV_64( PPCG_FLAG_OP_DIVDE, mkexpr( rD ),
40694aa412af1d8166cc11f39a6e721df49431d23618sewardj                           mkexpr( rA ), mkexpr( rB ) );
40704aa412af1d8166cc11f39a6e721df49431d23618sewardj         }
40714aa412af1d8166cc11f39a6e721df49431d23618sewardj         break;
40724aa412af1d8166cc11f39a6e721df49431d23618sewardj
4073e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj      case 0x189: //  divdeuo (Divide Doubleword Extended Unsigned)
4074e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj        // Same CR and OV rules as given for divweu above
4075e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj        DIP("divdeu%s%s r%u,r%u,r%u\n",
4076e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj            flag_OE ? "o" : "", flag_rC ? ".":"",
4077e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj            rD_addr, rA_addr, rB_addr);
4078e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj        assign( rD, binop(Iop_DivU64E, mkexpr(rA), mkexpr(rB)) );
4079e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj        if (flag_OE) {
4080e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj           set_XER_OV_64( PPCG_FLAG_OP_DIVDEU, mkexpr( rD ),
4081e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj                          mkexpr( rA ), mkexpr( rB ) );
4082e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj        }
4083e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj        break;
4084e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj
4085b85e8bba97fdae7d892f7bfd12e4601307e4721dcerion      default:
40865b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion         vex_printf("dis_int_arith(ppc)(opc2)\n");
4087b85e8bba97fdae7d892f7bfd12e4601307e4721dcerion         return False;
4088b85e8bba97fdae7d892f7bfd12e4601307e4721dcerion      }
4089b85e8bba97fdae7d892f7bfd12e4601307e4721dcerion      break;
4090f0de28cf1a762b0d6f74c93d3532c89a230673bbcerion
4091b85e8bba97fdae7d892f7bfd12e4601307e4721dcerion   default:
40925b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion      vex_printf("dis_int_arith(ppc)(opc1)\n");
4093b85e8bba97fdae7d892f7bfd12e4601307e4721dcerion      return False;
4094b85e8bba97fdae7d892f7bfd12e4601307e4721dcerion   }
4095b85e8bba97fdae7d892f7bfd12e4601307e4721dcerion
409676de5cf615380b23b4b5bcced6541233cd4a93a0cerion   putIReg( rD_addr, mkexpr(rD) );
409776de5cf615380b23b4b5bcced6541233cd4a93a0cerion
409876de5cf615380b23b4b5bcced6541233cd4a93a0cerion   if (do_rc && flag_rC) {
409976de5cf615380b23b4b5bcced6541233cd4a93a0cerion      set_CR0( mkexpr(rD) );
4100b85e8bba97fdae7d892f7bfd12e4601307e4721dcerion   }
4101b85e8bba97fdae7d892f7bfd12e4601307e4721dcerion   return True;
4102896a1373cfdbaa25f4ab73ed4f27554016defecccerion}
4103896a1373cfdbaa25f4ab73ed4f27554016defecccerion
4104896a1373cfdbaa25f4ab73ed4f27554016defecccerion
4105896a1373cfdbaa25f4ab73ed4f27554016defecccerion
41063d870a39e4d145e2f3d9f9a0eeed3475ec934ac1cerion/*
41073d870a39e4d145e2f3d9f9a0eeed3475ec934ac1cerion  Integer Compare Instructions
41083d870a39e4d145e2f3d9f9a0eeed3475ec934ac1cerion*/
41097aa4bbc850d2978cccd8e12cd7c4cfeaa5ab3e4dcerionstatic Bool dis_int_cmp ( UInt theInstr )
41107aa4bbc850d2978cccd8e12cd7c4cfeaa5ab3e4dcerion{
411176de5cf615380b23b4b5bcced6541233cd4a93a0cerion   /* D-Form, X-Form */
411276de5cf615380b23b4b5bcced6541233cd4a93a0cerion   UChar opc1    = ifieldOPC(theInstr);
411376de5cf615380b23b4b5bcced6541233cd4a93a0cerion   UChar crfD    = toUChar( IFIELD( theInstr, 23, 3 ) );
411476de5cf615380b23b4b5bcced6541233cd4a93a0cerion   UChar b22     = toUChar( IFIELD( theInstr, 22, 1 ) );
411576de5cf615380b23b4b5bcced6541233cd4a93a0cerion   UChar flag_L  = toUChar( IFIELD( theInstr, 21, 1 ) );
411676de5cf615380b23b4b5bcced6541233cd4a93a0cerion   UChar rA_addr = ifieldRegA(theInstr);
4117d953ebb9b04cbad6891676df597bf0c542b1ec89cerion   UInt  uimm16  = ifieldUIMM16(theInstr);
411876de5cf615380b23b4b5bcced6541233cd4a93a0cerion   UChar rB_addr = ifieldRegB(theInstr);
411976de5cf615380b23b4b5bcced6541233cd4a93a0cerion   UInt  opc2    = ifieldOPClo10(theInstr);
412076de5cf615380b23b4b5bcced6541233cd4a93a0cerion   UChar b0      = ifieldBIT0(theInstr);
412176de5cf615380b23b4b5bcced6541233cd4a93a0cerion
4122bb01b7cbfd84c27dd213f67a144ea5a99af36961cerion   IRType ty = mode64 ? Ity_I64 : Ity_I32;
4123bb01b7cbfd84c27dd213f67a144ea5a99af36961cerion   IRExpr *a = getIReg(rA_addr);
4124bb01b7cbfd84c27dd213f67a144ea5a99af36961cerion   IRExpr *b;
412576de5cf615380b23b4b5bcced6541233cd4a93a0cerion
4126d953ebb9b04cbad6891676df597bf0c542b1ec89cerion   if (!mode64 && flag_L==1) {  // L==1 invalid for 32 bit.
41275b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion      vex_printf("dis_int_cmp(ppc)(flag_L)\n");
4128b85e8bba97fdae7d892f7bfd12e4601307e4721dcerion      return False;
4129b85e8bba97fdae7d892f7bfd12e4601307e4721dcerion   }
4130b85e8bba97fdae7d892f7bfd12e4601307e4721dcerion
413176de5cf615380b23b4b5bcced6541233cd4a93a0cerion   if (b22 != 0) {
41325b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion      vex_printf("dis_int_cmp(ppc)(b22)\n");
4133b85e8bba97fdae7d892f7bfd12e4601307e4721dcerion      return False;
4134b85e8bba97fdae7d892f7bfd12e4601307e4721dcerion   }
4135b85e8bba97fdae7d892f7bfd12e4601307e4721dcerion
4136b85e8bba97fdae7d892f7bfd12e4601307e4721dcerion   switch (opc1) {
4137d953ebb9b04cbad6891676df597bf0c542b1ec89cerion   case 0x0B: // cmpi (Compare Immediate, PPC32 p368)
4138d953ebb9b04cbad6891676df597bf0c542b1ec89cerion      DIP("cmpi cr%u,%u,r%u,%d\n", crfD, flag_L, rA_addr,
4139d953ebb9b04cbad6891676df597bf0c542b1ec89cerion          (Int)extend_s_16to32(uimm16));
41402831b00c4950d6c2b061def05fd67528fe132ececerion      b = mkSzExtendS16( ty, uimm16 );
4141bb01b7cbfd84c27dd213f67a144ea5a99af36961cerion      if (flag_L == 1) {
41422831b00c4950d6c2b061def05fd67528fe132ececerion         putCR321(crfD, unop(Iop_64to8, binop(Iop_CmpORD64S, a, b)));
4143d953ebb9b04cbad6891676df597bf0c542b1ec89cerion      } else {
4144e9d8a26b690c2561ac54ab0cd6ad83ecbadcbe76sewardj         a = mkNarrowTo32( ty, a );
4145e9d8a26b690c2561ac54ab0cd6ad83ecbadcbe76sewardj         b = mkNarrowTo32( ty, b );
4146d953ebb9b04cbad6891676df597bf0c542b1ec89cerion         putCR321(crfD, unop(Iop_32to8, binop(Iop_CmpORD32S, a, b)));
4147d953ebb9b04cbad6891676df597bf0c542b1ec89cerion      }
4148d953ebb9b04cbad6891676df597bf0c542b1ec89cerion      putCR0( crfD, getXER_SO() );
4149d953ebb9b04cbad6891676df597bf0c542b1ec89cerion      break;
4150d953ebb9b04cbad6891676df597bf0c542b1ec89cerion
4151d953ebb9b04cbad6891676df597bf0c542b1ec89cerion   case 0x0A: // cmpli (Compare Logical Immediate, PPC32 p370)
4152d953ebb9b04cbad6891676df597bf0c542b1ec89cerion      DIP("cmpli cr%u,%u,r%u,0x%x\n", crfD, flag_L, rA_addr, uimm16);
41532831b00c4950d6c2b061def05fd67528fe132ececerion      b = mkSzImm( ty, uimm16 );
4154bb01b7cbfd84c27dd213f67a144ea5a99af36961cerion      if (flag_L == 1) {
41552831b00c4950d6c2b061def05fd67528fe132ececerion         putCR321(crfD, unop(Iop_64to8, binop(Iop_CmpORD64U, a, b)));
4156d953ebb9b04cbad6891676df597bf0c542b1ec89cerion      } else {
4157e9d8a26b690c2561ac54ab0cd6ad83ecbadcbe76sewardj         a = mkNarrowTo32( ty, a );
4158e9d8a26b690c2561ac54ab0cd6ad83ecbadcbe76sewardj         b = mkNarrowTo32( ty, b );
4159d953ebb9b04cbad6891676df597bf0c542b1ec89cerion         putCR321(crfD, unop(Iop_32to8, binop(Iop_CmpORD32U, a, b)));
4160d953ebb9b04cbad6891676df597bf0c542b1ec89cerion      }
4161d953ebb9b04cbad6891676df597bf0c542b1ec89cerion      putCR0( crfD, getXER_SO() );
4162d953ebb9b04cbad6891676df597bf0c542b1ec89cerion      break;
4163b85e8bba97fdae7d892f7bfd12e4601307e4721dcerion
4164b85e8bba97fdae7d892f7bfd12e4601307e4721dcerion   /* X Form */
4165b85e8bba97fdae7d892f7bfd12e4601307e4721dcerion   case 0x1F:
4166b85e8bba97fdae7d892f7bfd12e4601307e4721dcerion      if (b0 != 0) {
41675b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion         vex_printf("dis_int_cmp(ppc)(0x1F,b0)\n");
4168b85e8bba97fdae7d892f7bfd12e4601307e4721dcerion         return False;
4169b85e8bba97fdae7d892f7bfd12e4601307e4721dcerion      }
4170bb01b7cbfd84c27dd213f67a144ea5a99af36961cerion      b = getIReg(rB_addr);
4171c342f4ada40bc4c2c554d8ea69b325fe6f6439bacerion
4172b85e8bba97fdae7d892f7bfd12e4601307e4721dcerion      switch (opc2) {
4173d953ebb9b04cbad6891676df597bf0c542b1ec89cerion      case 0x000: // cmp (Compare, PPC32 p367)
4174d953ebb9b04cbad6891676df597bf0c542b1ec89cerion         DIP("cmp cr%u,%u,r%u,r%u\n", crfD, flag_L, rA_addr, rB_addr);
4175a9cb67bd4f3f27df6897a240d492bf17b798f10asewardj         /* Comparing a reg with itself produces a result which
4176a9cb67bd4f3f27df6897a240d492bf17b798f10asewardj            doesn't depend on the contents of the reg.  Therefore
4177a9cb67bd4f3f27df6897a240d492bf17b798f10asewardj            remove the false dependency, which has been known to cause
4178a9cb67bd4f3f27df6897a240d492bf17b798f10asewardj            memcheck to produce false errors. */
41799195aa111e0483b88cae8a4eb4e8455167b48942sewardj         if (rA_addr == rB_addr)
4180dd40fdf58cc8a6fe9466c4f00bdfc9fe9bf00449sewardj            a = b = typeOfIRExpr(irsb->tyenv,a) == Ity_I64
41819195aa111e0483b88cae8a4eb4e8455167b48942sewardj                    ? mkU64(0)  : mkU32(0);
4182bb01b7cbfd84c27dd213f67a144ea5a99af36961cerion         if (flag_L == 1) {
4183bb01b7cbfd84c27dd213f67a144ea5a99af36961cerion            putCR321(crfD, unop(Iop_64to8, binop(Iop_CmpORD64S, a, b)));
4184d953ebb9b04cbad6891676df597bf0c542b1ec89cerion         } else {
4185e9d8a26b690c2561ac54ab0cd6ad83ecbadcbe76sewardj            a = mkNarrowTo32( ty, a );
4186e9d8a26b690c2561ac54ab0cd6ad83ecbadcbe76sewardj            b = mkNarrowTo32( ty, b );
4187bb01b7cbfd84c27dd213f67a144ea5a99af36961cerion            putCR321(crfD, unop(Iop_32to8,binop(Iop_CmpORD32S, a, b)));
4188d953ebb9b04cbad6891676df597bf0c542b1ec89cerion         }
4189d953ebb9b04cbad6891676df597bf0c542b1ec89cerion         putCR0( crfD, getXER_SO() );
4190d953ebb9b04cbad6891676df597bf0c542b1ec89cerion         break;
4191b85e8bba97fdae7d892f7bfd12e4601307e4721dcerion
4192d953ebb9b04cbad6891676df597bf0c542b1ec89cerion      case 0x020: // cmpl (Compare Logical, PPC32 p369)
4193d953ebb9b04cbad6891676df597bf0c542b1ec89cerion         DIP("cmpl cr%u,%u,r%u,r%u\n", crfD, flag_L, rA_addr, rB_addr);
4194a9cb67bd4f3f27df6897a240d492bf17b798f10asewardj         /* Comparing a reg with itself produces a result which
4195a9cb67bd4f3f27df6897a240d492bf17b798f10asewardj            doesn't depend on the contents of the reg.  Therefore
4196a9cb67bd4f3f27df6897a240d492bf17b798f10asewardj            remove the false dependency, which has been known to cause
4197a9cb67bd4f3f27df6897a240d492bf17b798f10asewardj            memcheck to produce false errors. */
41989195aa111e0483b88cae8a4eb4e8455167b48942sewardj         if (rA_addr == rB_addr)
4199dd40fdf58cc8a6fe9466c4f00bdfc9fe9bf00449sewardj            a = b = typeOfIRExpr(irsb->tyenv,a) == Ity_I64
42009195aa111e0483b88cae8a4eb4e8455167b48942sewardj                    ? mkU64(0)  : mkU32(0);
4201bb01b7cbfd84c27dd213f67a144ea5a99af36961cerion         if (flag_L == 1) {
4202bb01b7cbfd84c27dd213f67a144ea5a99af36961cerion            putCR321(crfD, unop(Iop_64to8, binop(Iop_CmpORD64U, a, b)));
4203d953ebb9b04cbad6891676df597bf0c542b1ec89cerion         } else {
4204e9d8a26b690c2561ac54ab0cd6ad83ecbadcbe76sewardj            a = mkNarrowTo32( ty, a );
4205e9d8a26b690c2561ac54ab0cd6ad83ecbadcbe76sewardj            b = mkNarrowTo32( ty, b );
4206bb01b7cbfd84c27dd213f67a144ea5a99af36961cerion            putCR321(crfD, unop(Iop_32to8, binop(Iop_CmpORD32U, a, b)));
4207d953ebb9b04cbad6891676df597bf0c542b1ec89cerion         }
4208d953ebb9b04cbad6891676df597bf0c542b1ec89cerion         putCR0( crfD, getXER_SO() );
4209d953ebb9b04cbad6891676df597bf0c542b1ec89cerion         break;
4210b51f0f4f33256638ed953156a2635aa739b232f1sewardj
4211d953ebb9b04cbad6891676df597bf0c542b1ec89cerion      default:
42125b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion         vex_printf("dis_int_cmp(ppc)(opc2)\n");
4213d953ebb9b04cbad6891676df597bf0c542b1ec89cerion         return False;
4214b85e8bba97fdae7d892f7bfd12e4601307e4721dcerion      }
4215b85e8bba97fdae7d892f7bfd12e4601307e4721dcerion      break;
4216d953ebb9b04cbad6891676df597bf0c542b1ec89cerion
4217b85e8bba97fdae7d892f7bfd12e4601307e4721dcerion   default:
42185b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion      vex_printf("dis_int_cmp(ppc)(opc1)\n");
4219b85e8bba97fdae7d892f7bfd12e4601307e4721dcerion      return False;
4220b85e8bba97fdae7d892f7bfd12e4601307e4721dcerion   }
4221b85e8bba97fdae7d892f7bfd12e4601307e4721dcerion
4222b85e8bba97fdae7d892f7bfd12e4601307e4721dcerion   return True;
42237aa4bbc850d2978cccd8e12cd7c4cfeaa5ab3e4dcerion}
42247aa4bbc850d2978cccd8e12cd7c4cfeaa5ab3e4dcerion
42257aa4bbc850d2978cccd8e12cd7c4cfeaa5ab3e4dcerion
42263d870a39e4d145e2f3d9f9a0eeed3475ec934ac1cerion/*
42273d870a39e4d145e2f3d9f9a0eeed3475ec934ac1cerion  Integer Logical Instructions
42283d870a39e4d145e2f3d9f9a0eeed3475ec934ac1cerion*/
42297aa4bbc850d2978cccd8e12cd7c4cfeaa5ab3e4dcerionstatic Bool dis_int_logic ( UInt theInstr )
42307aa4bbc850d2978cccd8e12cd7c4cfeaa5ab3e4dcerion{
423176de5cf615380b23b4b5bcced6541233cd4a93a0cerion   /* D-Form, X-Form */
423276de5cf615380b23b4b5bcced6541233cd4a93a0cerion   UChar opc1    = ifieldOPC(theInstr);
423376de5cf615380b23b4b5bcced6541233cd4a93a0cerion   UChar rS_addr = ifieldRegDS(theInstr);
423476de5cf615380b23b4b5bcced6541233cd4a93a0cerion   UChar rA_addr = ifieldRegA(theInstr);
4235d953ebb9b04cbad6891676df597bf0c542b1ec89cerion   UInt  uimm16  = ifieldUIMM16(theInstr);
423676de5cf615380b23b4b5bcced6541233cd4a93a0cerion   UChar rB_addr = ifieldRegB(theInstr);
423776de5cf615380b23b4b5bcced6541233cd4a93a0cerion   UInt  opc2    = ifieldOPClo10(theInstr);
423876de5cf615380b23b4b5bcced6541233cd4a93a0cerion   UChar flag_rC = ifieldBIT0(theInstr);
4239b85e8bba97fdae7d892f7bfd12e4601307e4721dcerion
4240d953ebb9b04cbad6891676df597bf0c542b1ec89cerion   IRType ty     = mode64 ? Ity_I64 : Ity_I32;
4241d953ebb9b04cbad6891676df597bf0c542b1ec89cerion   IRTemp rS     = newTemp(ty);
4242d953ebb9b04cbad6891676df597bf0c542b1ec89cerion   IRTemp rA     = newTemp(ty);
4243d953ebb9b04cbad6891676df597bf0c542b1ec89cerion   IRTemp rB     = newTemp(ty);
4244e9d361ab43518b6dfbd3d846f48859534659dee0cerion   IRExpr* irx;
4245d953ebb9b04cbad6891676df597bf0c542b1ec89cerion   Bool do_rc    = False;
4246d953ebb9b04cbad6891676df597bf0c542b1ec89cerion
424776de5cf615380b23b4b5bcced6541233cd4a93a0cerion   assign( rS, getIReg(rS_addr) );
424876de5cf615380b23b4b5bcced6541233cd4a93a0cerion   assign( rB, getIReg(rB_addr) );
4249b85e8bba97fdae7d892f7bfd12e4601307e4721dcerion
4250b85e8bba97fdae7d892f7bfd12e4601307e4721dcerion   switch (opc1) {
4251e9d361ab43518b6dfbd3d846f48859534659dee0cerion   case 0x1C: // andi. (AND Immediate, PPC32 p358)
4252d953ebb9b04cbad6891676df597bf0c542b1ec89cerion      DIP("andi. r%u,r%u,0x%x\n", rA_addr, rS_addr, uimm16);
42532831b00c4950d6c2b061def05fd67528fe132ececerion      assign( rA, binop( mkSzOp(ty, Iop_And8), mkexpr(rS),
42542831b00c4950d6c2b061def05fd67528fe132ececerion                         mkSzImm(ty, uimm16)) );
425570e2412f623c955d7b199f09401732cf57417fc2cerion      do_rc = True;  // Always record to CR
425676de5cf615380b23b4b5bcced6541233cd4a93a0cerion      flag_rC = 1;
4257b85e8bba97fdae7d892f7bfd12e4601307e4721dcerion      break;
4258b85e8bba97fdae7d892f7bfd12e4601307e4721dcerion
4259e9d361ab43518b6dfbd3d846f48859534659dee0cerion   case 0x1D: // andis. (AND Immediate Shifted, PPC32 p359)
4260d953ebb9b04cbad6891676df597bf0c542b1ec89cerion      DIP("andis r%u,r%u,0x%x\n", rA_addr, rS_addr, uimm16);
42612831b00c4950d6c2b061def05fd67528fe132ececerion      assign( rA, binop( mkSzOp(ty, Iop_And8), mkexpr(rS),
42622831b00c4950d6c2b061def05fd67528fe132ececerion                         mkSzImm(ty, uimm16 << 16)) );
426370e2412f623c955d7b199f09401732cf57417fc2cerion      do_rc = True;  // Always record to CR
426476de5cf615380b23b4b5bcced6541233cd4a93a0cerion      flag_rC = 1;
4265b85e8bba97fdae7d892f7bfd12e4601307e4721dcerion      break;
4266b85e8bba97fdae7d892f7bfd12e4601307e4721dcerion
4267e9d361ab43518b6dfbd3d846f48859534659dee0cerion   case 0x18: // ori (OR Immediate, PPC32 p497)
4268d953ebb9b04cbad6891676df597bf0c542b1ec89cerion      DIP("ori r%u,r%u,0x%x\n", rA_addr, rS_addr, uimm16);
42692831b00c4950d6c2b061def05fd67528fe132ececerion      assign( rA, binop( mkSzOp(ty, Iop_Or8), mkexpr(rS),
42702831b00c4950d6c2b061def05fd67528fe132ececerion                         mkSzImm(ty, uimm16)) );
4271b85e8bba97fdae7d892f7bfd12e4601307e4721dcerion      break;
4272b85e8bba97fdae7d892f7bfd12e4601307e4721dcerion
4273e9d361ab43518b6dfbd3d846f48859534659dee0cerion   case 0x19: // oris (OR Immediate Shifted, PPC32 p498)
4274d953ebb9b04cbad6891676df597bf0c542b1ec89cerion      DIP("oris r%u,r%u,0x%x\n", rA_addr, rS_addr, uimm16);
42752831b00c4950d6c2b061def05fd67528fe132ececerion      assign( rA, binop( mkSzOp(ty, Iop_Or8), mkexpr(rS),
42762831b00c4950d6c2b061def05fd67528fe132ececerion                         mkSzImm(ty, uimm16 << 16)) );
4277b85e8bba97fdae7d892f7bfd12e4601307e4721dcerion      break;
4278b85e8bba97fdae7d892f7bfd12e4601307e4721dcerion
4279e9d361ab43518b6dfbd3d846f48859534659dee0cerion   case 0x1A: // xori (XOR Immediate, PPC32 p550)
4280d953ebb9b04cbad6891676df597bf0c542b1ec89cerion      DIP("xori r%u,r%u,0x%x\n", rA_addr, rS_addr, uimm16);
42812831b00c4950d6c2b061def05fd67528fe132ececerion      assign( rA, binop( mkSzOp(ty, Iop_Xor8), mkexpr(rS),
42822831b00c4950d6c2b061def05fd67528fe132ececerion                         mkSzImm(ty, uimm16)) );
4283b85e8bba97fdae7d892f7bfd12e4601307e4721dcerion      break;
4284b85e8bba97fdae7d892f7bfd12e4601307e4721dcerion
4285e9d361ab43518b6dfbd3d846f48859534659dee0cerion   case 0x1B: // xoris (XOR Immediate Shifted, PPC32 p551)
4286d953ebb9b04cbad6891676df597bf0c542b1ec89cerion      DIP("xoris r%u,r%u,0x%x\n", rA_addr, rS_addr, uimm16);
42872831b00c4950d6c2b061def05fd67528fe132ececerion      assign( rA, binop( mkSzOp(ty, Iop_Xor8), mkexpr(rS),
42882831b00c4950d6c2b061def05fd67528fe132ececerion                         mkSzImm(ty, uimm16 << 16)) );
4289b85e8bba97fdae7d892f7bfd12e4601307e4721dcerion      break;
4290b85e8bba97fdae7d892f7bfd12e4601307e4721dcerion
4291b85e8bba97fdae7d892f7bfd12e4601307e4721dcerion   /* X Form */
4292b85e8bba97fdae7d892f7bfd12e4601307e4721dcerion   case 0x1F:
42934aa412af1d8166cc11f39a6e721df49431d23618sewardj      do_rc = True; // All below record to CR, except for where we return at case end.
429470e2412f623c955d7b199f09401732cf57417fc2cerion
4295b85e8bba97fdae7d892f7bfd12e4601307e4721dcerion      switch (opc2) {
4296d953ebb9b04cbad6891676df597bf0c542b1ec89cerion      case 0x01C: // and (AND, PPC32 p356)
4297d953ebb9b04cbad6891676df597bf0c542b1ec89cerion         DIP("and%s r%u,r%u,r%u\n",
42985b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion             flag_rC ? ".":"", rA_addr, rS_addr, rB_addr);
42992831b00c4950d6c2b061def05fd67528fe132ececerion         assign(rA, binop( mkSzOp(ty, Iop_And8),
4300d953ebb9b04cbad6891676df597bf0c542b1ec89cerion                           mkexpr(rS), mkexpr(rB)));
4301d953ebb9b04cbad6891676df597bf0c542b1ec89cerion         break;
4302b85e8bba97fdae7d892f7bfd12e4601307e4721dcerion
4303d953ebb9b04cbad6891676df597bf0c542b1ec89cerion      case 0x03C: // andc (AND with Complement, PPC32 p357)
4304d953ebb9b04cbad6891676df597bf0c542b1ec89cerion         DIP("andc%s r%u,r%u,r%u\n",
43055b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion             flag_rC ? ".":"", rA_addr, rS_addr, rB_addr);
43062831b00c4950d6c2b061def05fd67528fe132ececerion         assign(rA, binop( mkSzOp(ty, Iop_And8), mkexpr(rS),
43072831b00c4950d6c2b061def05fd67528fe132ececerion                           unop( mkSzOp(ty, Iop_Not8),
4308d953ebb9b04cbad6891676df597bf0c542b1ec89cerion                                 mkexpr(rB))));
4309d953ebb9b04cbad6891676df597bf0c542b1ec89cerion         break;
4310d953ebb9b04cbad6891676df597bf0c542b1ec89cerion
4311d953ebb9b04cbad6891676df597bf0c542b1ec89cerion      case 0x01A: { // cntlzw (Count Leading Zeros Word, PPC32 p371)
4312d953ebb9b04cbad6891676df597bf0c542b1ec89cerion         IRExpr* lo32;
4313d953ebb9b04cbad6891676df597bf0c542b1ec89cerion         if (rB_addr!=0) {
43145b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion            vex_printf("dis_int_logic(ppc)(cntlzw,rB_addr)\n");
4315d953ebb9b04cbad6891676df597bf0c542b1ec89cerion            return False;
4316d953ebb9b04cbad6891676df597bf0c542b1ec89cerion         }
4317d953ebb9b04cbad6891676df597bf0c542b1ec89cerion         DIP("cntlzw%s r%u,r%u\n",
43185b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion             flag_rC ? ".":"", rA_addr, rS_addr);
4319d953ebb9b04cbad6891676df597bf0c542b1ec89cerion
4320d953ebb9b04cbad6891676df597bf0c542b1ec89cerion         // mode64: count in low word only
4321d953ebb9b04cbad6891676df597bf0c542b1ec89cerion         lo32 = mode64 ? unop(Iop_64to32, mkexpr(rS)) : mkexpr(rS);
4322d953ebb9b04cbad6891676df597bf0c542b1ec89cerion
4323d953ebb9b04cbad6891676df597bf0c542b1ec89cerion         // Iop_Clz32 undefined for arg==0, so deal with that case:
4324d953ebb9b04cbad6891676df597bf0c542b1ec89cerion         irx =  binop(Iop_CmpNE32, lo32, mkU32(0));
4325e9d8a26b690c2561ac54ab0cd6ad83ecbadcbe76sewardj         assign(rA, mkWidenFrom32(ty,
432699dd03e04a6914d90d5fee727d61d76905334becflorian                         IRExpr_ITE( irx,
432799dd03e04a6914d90d5fee727d61d76905334becflorian                                     unop(Iop_Clz32, lo32),
432899dd03e04a6914d90d5fee727d61d76905334becflorian                                     mkU32(32)),
43295b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion                         False));
43305b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion
4331d953ebb9b04cbad6891676df597bf0c542b1ec89cerion         // TODO: alternatively: assign(rA, verbose_Clz32(rS));
4332d953ebb9b04cbad6891676df597bf0c542b1ec89cerion         break;
4333d953ebb9b04cbad6891676df597bf0c542b1ec89cerion      }
4334b85e8bba97fdae7d892f7bfd12e4601307e4721dcerion
433520ef5472eac767474c93b7835364a23f24c0ec5dsewardj      case 0x11C: // eqv (Equivalent, PPC32 p396)
4336d953ebb9b04cbad6891676df597bf0c542b1ec89cerion         DIP("eqv%s r%u,r%u,r%u\n",
43375b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion             flag_rC ? ".":"", rA_addr, rS_addr, rB_addr);
43382831b00c4950d6c2b061def05fd67528fe132ececerion         assign( rA, unop( mkSzOp(ty, Iop_Not8),
43392831b00c4950d6c2b061def05fd67528fe132ececerion                           binop( mkSzOp(ty, Iop_Xor8),
4340d953ebb9b04cbad6891676df597bf0c542b1ec89cerion                                  mkexpr(rS), mkexpr(rB))) );
434120ef5472eac767474c93b7835364a23f24c0ec5dsewardj         break;
4342b85e8bba97fdae7d892f7bfd12e4601307e4721dcerion
4343e9d361ab43518b6dfbd3d846f48859534659dee0cerion      case 0x3BA: // extsb (Extend Sign Byte, PPC32 p397
434476de5cf615380b23b4b5bcced6541233cd4a93a0cerion         if (rB_addr!=0) {
43455b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion            vex_printf("dis_int_logic(ppc)(extsb,rB_addr)\n");
4346b85e8bba97fdae7d892f7bfd12e4601307e4721dcerion            return False;
4347b85e8bba97fdae7d892f7bfd12e4601307e4721dcerion         }
4348d953ebb9b04cbad6891676df597bf0c542b1ec89cerion         DIP("extsb%s r%u,r%u\n",
43495b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion             flag_rC ? ".":"", rA_addr, rS_addr);
4350d953ebb9b04cbad6891676df597bf0c542b1ec89cerion         if (mode64)
4351d953ebb9b04cbad6891676df597bf0c542b1ec89cerion            assign( rA, unop(Iop_8Sto64, unop(Iop_64to8, mkexpr(rS))) );
4352d953ebb9b04cbad6891676df597bf0c542b1ec89cerion         else
4353d953ebb9b04cbad6891676df597bf0c542b1ec89cerion            assign( rA, unop(Iop_8Sto32, unop(Iop_32to8, mkexpr(rS))) );
4354b85e8bba97fdae7d892f7bfd12e4601307e4721dcerion         break;
4355b85e8bba97fdae7d892f7bfd12e4601307e4721dcerion
4356e9d361ab43518b6dfbd3d846f48859534659dee0cerion      case 0x39A: // extsh (Extend Sign Half Word, PPC32 p398)
435776de5cf615380b23b4b5bcced6541233cd4a93a0cerion         if (rB_addr!=0) {
43585b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion            vex_printf("dis_int_logic(ppc)(extsh,rB_addr)\n");
4359b85e8bba97fdae7d892f7bfd12e4601307e4721dcerion            return False;
4360b85e8bba97fdae7d892f7bfd12e4601307e4721dcerion         }
4361d953ebb9b04cbad6891676df597bf0c542b1ec89cerion         DIP("extsh%s r%u,r%u\n",
43625b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion             flag_rC ? ".":"", rA_addr, rS_addr);
4363d953ebb9b04cbad6891676df597bf0c542b1ec89cerion         if (mode64)
43645b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion            assign( rA, unop(Iop_16Sto64,
43655b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion                             unop(Iop_64to16, mkexpr(rS))) );
4366d953ebb9b04cbad6891676df597bf0c542b1ec89cerion         else
43675b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion            assign( rA, unop(Iop_16Sto32,
43685b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion                             unop(Iop_32to16, mkexpr(rS))) );
4369b85e8bba97fdae7d892f7bfd12e4601307e4721dcerion         break;
4370b85e8bba97fdae7d892f7bfd12e4601307e4721dcerion
4371e9d361ab43518b6dfbd3d846f48859534659dee0cerion      case 0x1DC: // nand (NAND, PPC32 p492)
4372d953ebb9b04cbad6891676df597bf0c542b1ec89cerion         DIP("nand%s r%u,r%u,r%u\n",
43735b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion             flag_rC ? ".":"", rA_addr, rS_addr, rB_addr);
43742831b00c4950d6c2b061def05fd67528fe132ececerion         assign( rA, unop( mkSzOp(ty, Iop_Not8),
43752831b00c4950d6c2b061def05fd67528fe132ececerion                           binop( mkSzOp(ty, Iop_And8),
4376d953ebb9b04cbad6891676df597bf0c542b1ec89cerion                                  mkexpr(rS), mkexpr(rB))) );
4377b85e8bba97fdae7d892f7bfd12e4601307e4721dcerion         break;
4378b85e8bba97fdae7d892f7bfd12e4601307e4721dcerion
4379e9d361ab43518b6dfbd3d846f48859534659dee0cerion      case 0x07C: // nor (NOR, PPC32 p494)
4380d953ebb9b04cbad6891676df597bf0c542b1ec89cerion         DIP("nor%s r%u,r%u,r%u\n",
43815b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion             flag_rC ? ".":"", rA_addr, rS_addr, rB_addr);
43822831b00c4950d6c2b061def05fd67528fe132ececerion         assign( rA, unop( mkSzOp(ty, Iop_Not8),
43832831b00c4950d6c2b061def05fd67528fe132ececerion                           binop( mkSzOp(ty, Iop_Or8),
4384d953ebb9b04cbad6891676df597bf0c542b1ec89cerion                                  mkexpr(rS), mkexpr(rB))) );
4385b85e8bba97fdae7d892f7bfd12e4601307e4721dcerion         break;
4386b85e8bba97fdae7d892f7bfd12e4601307e4721dcerion
4387e9d361ab43518b6dfbd3d846f48859534659dee0cerion      case 0x1BC: // or (OR, PPC32 p495)
438876de5cf615380b23b4b5bcced6541233cd4a93a0cerion         if ((!flag_rC) && rS_addr == rB_addr) {
4389d953ebb9b04cbad6891676df597bf0c542b1ec89cerion            DIP("mr r%u,r%u\n", rA_addr, rS_addr);
439076de5cf615380b23b4b5bcced6541233cd4a93a0cerion            assign( rA, mkexpr(rS) );
4391b51f0f4f33256638ed953156a2635aa739b232f1sewardj         } else {
4392d953ebb9b04cbad6891676df597bf0c542b1ec89cerion            DIP("or%s r%u,r%u,r%u\n",
43935b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion                flag_rC ? ".":"", rA_addr, rS_addr, rB_addr);
43942831b00c4950d6c2b061def05fd67528fe132ececerion            assign( rA, binop( mkSzOp(ty, Iop_Or8),
4395d953ebb9b04cbad6891676df597bf0c542b1ec89cerion                               mkexpr(rS), mkexpr(rB)) );
4396b51f0f4f33256638ed953156a2635aa739b232f1sewardj         }
4397b85e8bba97fdae7d892f7bfd12e4601307e4721dcerion         break;
4398b85e8bba97fdae7d892f7bfd12e4601307e4721dcerion
4399e9d361ab43518b6dfbd3d846f48859534659dee0cerion      case 0x19C: // orc  (OR with Complement, PPC32 p496)
4400d953ebb9b04cbad6891676df597bf0c542b1ec89cerion         DIP("orc%s r%u,r%u,r%u\n",
44015b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion             flag_rC ? ".":"", rA_addr, rS_addr, rB_addr);
44022831b00c4950d6c2b061def05fd67528fe132ececerion         assign( rA, binop( mkSzOp(ty, Iop_Or8), mkexpr(rS),
44032831b00c4950d6c2b061def05fd67528fe132ececerion                            unop(mkSzOp(ty, Iop_Not8), mkexpr(rB))));
4404b85e8bba97fdae7d892f7bfd12e4601307e4721dcerion         break;
4405b85e8bba97fdae7d892f7bfd12e4601307e4721dcerion
4406e9d361ab43518b6dfbd3d846f48859534659dee0cerion      case 0x13C: // xor (XOR, PPC32 p549)
4407d953ebb9b04cbad6891676df597bf0c542b1ec89cerion         DIP("xor%s r%u,r%u,r%u\n",
44085b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion             flag_rC ? ".":"", rA_addr, rS_addr, rB_addr);
44092831b00c4950d6c2b061def05fd67528fe132ececerion         assign( rA, binop( mkSzOp(ty, Iop_Xor8),
4410d953ebb9b04cbad6891676df597bf0c542b1ec89cerion                            mkexpr(rS), mkexpr(rB)) );
4411b85e8bba97fdae7d892f7bfd12e4601307e4721dcerion         break;
4412b85e8bba97fdae7d892f7bfd12e4601307e4721dcerion
4413f0de28cf1a762b0d6f74c93d3532c89a230673bbcerion
4414f0de28cf1a762b0d6f74c93d3532c89a230673bbcerion      /* 64bit Integer Logical Instructions */
4415f0de28cf1a762b0d6f74c93d3532c89a230673bbcerion      case 0x3DA: // extsw (Extend Sign Word, PPC64 p430)
4416f0de28cf1a762b0d6f74c93d3532c89a230673bbcerion         if (rB_addr!=0) {
44175b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion            vex_printf("dis_int_logic(ppc)(extsw,rB_addr)\n");
4418f0de28cf1a762b0d6f74c93d3532c89a230673bbcerion            return False;
4419f0de28cf1a762b0d6f74c93d3532c89a230673bbcerion         }
44205b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion         DIP("extsw%s r%u,r%u\n", flag_rC ? ".":"", rA_addr, rS_addr);
4421f0de28cf1a762b0d6f74c93d3532c89a230673bbcerion         assign(rA, unop(Iop_32Sto64, unop(Iop_64to32, mkexpr(rS))));
4422f0de28cf1a762b0d6f74c93d3532c89a230673bbcerion         break;
4423f0de28cf1a762b0d6f74c93d3532c89a230673bbcerion
44245b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion      case 0x03A: // cntlzd (Count Leading Zeros DWord, PPC64 p401)
4425f0de28cf1a762b0d6f74c93d3532c89a230673bbcerion         if (rB_addr!=0) {
44265b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion            vex_printf("dis_int_logic(ppc)(cntlzd,rB_addr)\n");
4427f0de28cf1a762b0d6f74c93d3532c89a230673bbcerion            return False;
4428f0de28cf1a762b0d6f74c93d3532c89a230673bbcerion         }
44295b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion         DIP("cntlzd%s r%u,r%u\n",
44305b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion             flag_rC ? ".":"", rA_addr, rS_addr);
443107b07a966a2fdbcf621251a0c1a8ab84807fb120cerion         // Iop_Clz64 undefined for arg==0, so deal with that case:
443207b07a966a2fdbcf621251a0c1a8ab84807fb120cerion         irx =  binop(Iop_CmpNE64, mkexpr(rS), mkU64(0));
443399dd03e04a6914d90d5fee727d61d76905334becflorian         assign(rA, IRExpr_ITE( irx,
443499dd03e04a6914d90d5fee727d61d76905334becflorian                                unop(Iop_Clz64, mkexpr(rS)),
443599dd03e04a6914d90d5fee727d61d76905334becflorian                                mkU64(64) ));
44365b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion         // TODO: alternatively: assign(rA, verbose_Clz64(rS));
443707b07a966a2fdbcf621251a0c1a8ab84807fb120cerion         break;
4438f0de28cf1a762b0d6f74c93d3532c89a230673bbcerion
44397e84630580f89c1022dde97007bffbf6aef81814sewardj      case 0x1FC: // cmpb (Power6: compare bytes)
44407e84630580f89c1022dde97007bffbf6aef81814sewardj         DIP("cmpb r%u,r%u,r%u\n", rA_addr, rS_addr, rB_addr);
44417e84630580f89c1022dde97007bffbf6aef81814sewardj
44427e84630580f89c1022dde97007bffbf6aef81814sewardj         if (mode64)
44437e84630580f89c1022dde97007bffbf6aef81814sewardj            assign( rA, unop( Iop_V128to64,
44447e84630580f89c1022dde97007bffbf6aef81814sewardj                              binop( Iop_CmpEQ8x16,
44457e84630580f89c1022dde97007bffbf6aef81814sewardj                                     binop( Iop_64HLtoV128, mkU64(0), mkexpr(rS) ),
44467e84630580f89c1022dde97007bffbf6aef81814sewardj                                     binop( Iop_64HLtoV128, mkU64(0), mkexpr(rB) )
44477e84630580f89c1022dde97007bffbf6aef81814sewardj                                     )) );
44487e84630580f89c1022dde97007bffbf6aef81814sewardj         else
44497e84630580f89c1022dde97007bffbf6aef81814sewardj            assign( rA, unop( Iop_V128to32,
44507e84630580f89c1022dde97007bffbf6aef81814sewardj                              binop( Iop_CmpEQ8x16,
44517e84630580f89c1022dde97007bffbf6aef81814sewardj                                     unop( Iop_32UtoV128, mkexpr(rS) ),
44527e84630580f89c1022dde97007bffbf6aef81814sewardj                                     unop( Iop_32UtoV128, mkexpr(rB) )
44537e84630580f89c1022dde97007bffbf6aef81814sewardj                                     )) );
44547e84630580f89c1022dde97007bffbf6aef81814sewardj         break;
44557e84630580f89c1022dde97007bffbf6aef81814sewardj
44567e84630580f89c1022dde97007bffbf6aef81814sewardj      case 0x2DF: { // mftgpr (move floating-point to general purpose register)
44577e84630580f89c1022dde97007bffbf6aef81814sewardj         IRTemp frB = newTemp(Ity_F64);
44587e84630580f89c1022dde97007bffbf6aef81814sewardj         DIP("mftgpr r%u,fr%u\n", rS_addr, rB_addr);
44597e84630580f89c1022dde97007bffbf6aef81814sewardj
44607e84630580f89c1022dde97007bffbf6aef81814sewardj         assign( frB, getFReg(rB_addr));  // always F64
44617e84630580f89c1022dde97007bffbf6aef81814sewardj         if (mode64)
44627e84630580f89c1022dde97007bffbf6aef81814sewardj            assign( rA, unop( Iop_ReinterpF64asI64, mkexpr(frB)) );
44637e84630580f89c1022dde97007bffbf6aef81814sewardj         else
44647e84630580f89c1022dde97007bffbf6aef81814sewardj            assign( rA, unop( Iop_64to32, unop( Iop_ReinterpF64asI64, mkexpr(frB))) );
44657e84630580f89c1022dde97007bffbf6aef81814sewardj
44667e84630580f89c1022dde97007bffbf6aef81814sewardj         putIReg( rS_addr, mkexpr(rA));
44677e84630580f89c1022dde97007bffbf6aef81814sewardj         return True;
44687e84630580f89c1022dde97007bffbf6aef81814sewardj      }
44697e84630580f89c1022dde97007bffbf6aef81814sewardj
44707e84630580f89c1022dde97007bffbf6aef81814sewardj      case 0x25F: { // mffgpr (move floating-point from general purpose register)
44717e84630580f89c1022dde97007bffbf6aef81814sewardj         IRTemp frA = newTemp(Ity_F64);
44727e84630580f89c1022dde97007bffbf6aef81814sewardj         DIP("mffgpr fr%u,r%u\n", rS_addr, rB_addr);
44737e84630580f89c1022dde97007bffbf6aef81814sewardj
44747e84630580f89c1022dde97007bffbf6aef81814sewardj         if (mode64)
44757e84630580f89c1022dde97007bffbf6aef81814sewardj            assign( frA, unop( Iop_ReinterpI64asF64, mkexpr(rB)) );
44767e84630580f89c1022dde97007bffbf6aef81814sewardj         else
44777e84630580f89c1022dde97007bffbf6aef81814sewardj            assign( frA, unop( Iop_ReinterpI64asF64, unop( Iop_32Uto64, mkexpr(rB))) );
44787e84630580f89c1022dde97007bffbf6aef81814sewardj
44797e84630580f89c1022dde97007bffbf6aef81814sewardj         putFReg( rS_addr, mkexpr(frA));
44807e84630580f89c1022dde97007bffbf6aef81814sewardj         return True;
44817e84630580f89c1022dde97007bffbf6aef81814sewardj      }
448266d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj      case 0x1FA: // popcntd (population count doubleword
448366d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj      {
448466d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj    	  DIP("popcntd r%u,r%u\n", rA_addr, rS_addr);
44857deaf9552b546b847528cf39b38898fb7742b5f5carll    	  IRTemp result = gen_POPCOUNT(ty, rS, DWORD);
448666d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj    	  putIReg( rA_addr, mkexpr(result) );
448766d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj    	  return True;
448866d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj      }
4489e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj      case 0x17A: // popcntw (Population Count Words)
4490e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj      {
4491e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj         DIP("popcntw r%u,r%u\n", rA_addr, rS_addr);
4492e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj         if (mode64) {
4493e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj            IRTemp resultHi, resultLo;
4494e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj            IRTemp argLo = newTemp(Ity_I32);
4495e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj            IRTemp argHi = newTemp(Ity_I32);
4496e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj            assign(argLo, unop(Iop_64to32, mkexpr(rS)));
4497e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj            assign(argHi, unop(Iop_64HIto32, mkexpr(rS)));
44987deaf9552b546b847528cf39b38898fb7742b5f5carll            resultLo = gen_POPCOUNT(Ity_I32, argLo, WORD);
44997deaf9552b546b847528cf39b38898fb7742b5f5carll            resultHi = gen_POPCOUNT(Ity_I32, argHi, WORD);
4500e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj            putIReg( rA_addr, binop(Iop_32HLto64, mkexpr(resultHi), mkexpr(resultLo)));
4501e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj         } else {
45027deaf9552b546b847528cf39b38898fb7742b5f5carll            IRTemp result = gen_POPCOUNT(ty, rS, WORD);
4503738d9dddf788cd66fc04081f5fca872f38859813philippe            putIReg( rA_addr, mkexpr(result) );
4504738d9dddf788cd66fc04081f5fca872f38859813philippe         }
4505738d9dddf788cd66fc04081f5fca872f38859813philippe         return True;
4506738d9dddf788cd66fc04081f5fca872f38859813philippe      }
4507738d9dddf788cd66fc04081f5fca872f38859813philippe      case 0x7A: // popcntb (Population Count Byte)
4508738d9dddf788cd66fc04081f5fca872f38859813philippe      {
4509738d9dddf788cd66fc04081f5fca872f38859813philippe         DIP("popcntb r%u,r%u\n", rA_addr, rS_addr);
4510738d9dddf788cd66fc04081f5fca872f38859813philippe
4511738d9dddf788cd66fc04081f5fca872f38859813philippe         if (mode64) {
4512738d9dddf788cd66fc04081f5fca872f38859813philippe            IRTemp resultHi, resultLo;
4513738d9dddf788cd66fc04081f5fca872f38859813philippe            IRTemp argLo = newTemp(Ity_I32);
4514738d9dddf788cd66fc04081f5fca872f38859813philippe            IRTemp argHi = newTemp(Ity_I32);
4515738d9dddf788cd66fc04081f5fca872f38859813philippe            assign(argLo, unop(Iop_64to32, mkexpr(rS)));
4516738d9dddf788cd66fc04081f5fca872f38859813philippe            assign(argHi, unop(Iop_64HIto32, mkexpr(rS)));
45177deaf9552b546b847528cf39b38898fb7742b5f5carll            resultLo = gen_POPCOUNT(Ity_I32, argLo, BYTE);
45187deaf9552b546b847528cf39b38898fb7742b5f5carll            resultHi = gen_POPCOUNT(Ity_I32, argHi, BYTE);
4519738d9dddf788cd66fc04081f5fca872f38859813philippe            putIReg( rA_addr, binop(Iop_32HLto64, mkexpr(resultHi),
4520738d9dddf788cd66fc04081f5fca872f38859813philippe                                    mkexpr(resultLo)));
4521738d9dddf788cd66fc04081f5fca872f38859813philippe         } else {
45227deaf9552b546b847528cf39b38898fb7742b5f5carll            IRTemp result = gen_POPCOUNT(ty, rS, BYTE);
4523e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj            putIReg( rA_addr, mkexpr(result) );
4524e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj         }
4525e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj         return True;
4526e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj      }
45274aa412af1d8166cc11f39a6e721df49431d23618sewardj       case 0x0FC: // bpermd (Bit Permute Doubleword)
45284aa412af1d8166cc11f39a6e721df49431d23618sewardj       {
45294aa412af1d8166cc11f39a6e721df49431d23618sewardj          /* This is a lot of rigmarole to emulate bpermd like this, as it
45304aa412af1d8166cc11f39a6e721df49431d23618sewardj           * could be done much faster by implementing a call to the native
45314aa412af1d8166cc11f39a6e721df49431d23618sewardj           * instruction.  However, where possible I want to avoid using new
45324aa412af1d8166cc11f39a6e721df49431d23618sewardj           * native instructions so that we can use valgrind to emulate those
45334aa412af1d8166cc11f39a6e721df49431d23618sewardj           * instructions on older PPC64 hardware.
45344aa412af1d8166cc11f39a6e721df49431d23618sewardj           */
45354aa412af1d8166cc11f39a6e721df49431d23618sewardj #define BPERMD_IDX_MASK 0x00000000000000FFULL
45364aa412af1d8166cc11f39a6e721df49431d23618sewardj #define BPERMD_BIT_MASK 0x8000000000000000ULL
45374aa412af1d8166cc11f39a6e721df49431d23618sewardj          int i;
45384aa412af1d8166cc11f39a6e721df49431d23618sewardj          IRExpr * rS_expr = mkexpr(rS);
45394aa412af1d8166cc11f39a6e721df49431d23618sewardj          IRExpr * res = binop(Iop_And64, mkU64(0), mkU64(0));
45404aa412af1d8166cc11f39a6e721df49431d23618sewardj          DIP("bpermd r%u,r%u,r%u\n", rA_addr, rS_addr, rB_addr);
45414aa412af1d8166cc11f39a6e721df49431d23618sewardj          for (i = 0; i < 8; i++) {
45424aa412af1d8166cc11f39a6e721df49431d23618sewardj             IRTemp idx_tmp = newTemp( Ity_I64 );
45434aa412af1d8166cc11f39a6e721df49431d23618sewardj             IRTemp perm_bit = newTemp( Ity_I64 );
45444aa412af1d8166cc11f39a6e721df49431d23618sewardj             IRTemp idx = newTemp( Ity_I8 );
45454aa412af1d8166cc11f39a6e721df49431d23618sewardj             IRTemp idx_LT64 = newTemp( Ity_I1 );
45464aa412af1d8166cc11f39a6e721df49431d23618sewardj             IRTemp idx_LT64_ity64 = newTemp( Ity_I64 );
45474aa412af1d8166cc11f39a6e721df49431d23618sewardj
45484aa412af1d8166cc11f39a6e721df49431d23618sewardj             assign( idx_tmp,
45494aa412af1d8166cc11f39a6e721df49431d23618sewardj                     binop( Iop_And64, mkU64( BPERMD_IDX_MASK ), rS_expr ) );
45504aa412af1d8166cc11f39a6e721df49431d23618sewardj             assign( idx_LT64,
45514aa412af1d8166cc11f39a6e721df49431d23618sewardj                           binop( Iop_CmpLT64U, mkexpr( idx_tmp ), mkU64( 64 ) ) );
45524aa412af1d8166cc11f39a6e721df49431d23618sewardj             assign( idx,
45534aa412af1d8166cc11f39a6e721df49431d23618sewardj                           binop( Iop_And8,
45544aa412af1d8166cc11f39a6e721df49431d23618sewardj                                  unop( Iop_1Sto8,
45554aa412af1d8166cc11f39a6e721df49431d23618sewardj                                        mkexpr(idx_LT64) ),
45564aa412af1d8166cc11f39a6e721df49431d23618sewardj                                  unop( Iop_64to8, mkexpr( idx_tmp ) ) ) );
45574aa412af1d8166cc11f39a6e721df49431d23618sewardj             /* If idx_LT64 == 0, we must force the perm bit to '0'. Below, we se idx
45584aa412af1d8166cc11f39a6e721df49431d23618sewardj              * to determine which bit of rB to use for the perm bit, and then we shift
45594aa412af1d8166cc11f39a6e721df49431d23618sewardj              * that bit to the MSB position.  We AND that with a 64-bit-ized idx_LT64
45604aa412af1d8166cc11f39a6e721df49431d23618sewardj              * to set the final perm bit.
45614aa412af1d8166cc11f39a6e721df49431d23618sewardj              */
45624aa412af1d8166cc11f39a6e721df49431d23618sewardj             assign( idx_LT64_ity64,
45634aa412af1d8166cc11f39a6e721df49431d23618sewardj                           unop( Iop_32Uto64, unop( Iop_1Uto32, mkexpr(idx_LT64 ) ) ) );
45644aa412af1d8166cc11f39a6e721df49431d23618sewardj             assign( perm_bit,
45654aa412af1d8166cc11f39a6e721df49431d23618sewardj                           binop( Iop_And64,
45664aa412af1d8166cc11f39a6e721df49431d23618sewardj                                  mkexpr( idx_LT64_ity64 ),
45674aa412af1d8166cc11f39a6e721df49431d23618sewardj                                  binop( Iop_Shr64,
45684aa412af1d8166cc11f39a6e721df49431d23618sewardj                                         binop( Iop_And64,
45694aa412af1d8166cc11f39a6e721df49431d23618sewardj                                                mkU64( BPERMD_BIT_MASK ),
45704aa412af1d8166cc11f39a6e721df49431d23618sewardj                                                binop( Iop_Shl64,
45714aa412af1d8166cc11f39a6e721df49431d23618sewardj                                                       mkexpr( rB ),
45724aa412af1d8166cc11f39a6e721df49431d23618sewardj                                                       mkexpr( idx ) ) ),
45734aa412af1d8166cc11f39a6e721df49431d23618sewardj                                         mkU8( 63 ) ) ) );
45744aa412af1d8166cc11f39a6e721df49431d23618sewardj             res = binop( Iop_Or64,
45754aa412af1d8166cc11f39a6e721df49431d23618sewardj                                res,
45764aa412af1d8166cc11f39a6e721df49431d23618sewardj                                binop( Iop_Shl64,
45774aa412af1d8166cc11f39a6e721df49431d23618sewardj                                       mkexpr( perm_bit ),
45784aa412af1d8166cc11f39a6e721df49431d23618sewardj                                       mkU8( i ) ) );
45794aa412af1d8166cc11f39a6e721df49431d23618sewardj             rS_expr = binop( Iop_Shr64, rS_expr, mkU8( 8 ) );
45804aa412af1d8166cc11f39a6e721df49431d23618sewardj          }
45814aa412af1d8166cc11f39a6e721df49431d23618sewardj          putIReg(rA_addr, res);
45824aa412af1d8166cc11f39a6e721df49431d23618sewardj          return True;
45834aa412af1d8166cc11f39a6e721df49431d23618sewardj       }
45844aa412af1d8166cc11f39a6e721df49431d23618sewardj
4585b85e8bba97fdae7d892f7bfd12e4601307e4721dcerion      default:
45865b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion         vex_printf("dis_int_logic(ppc)(opc2)\n");
4587b85e8bba97fdae7d892f7bfd12e4601307e4721dcerion         return False;
4588b85e8bba97fdae7d892f7bfd12e4601307e4721dcerion      }
4589b85e8bba97fdae7d892f7bfd12e4601307e4721dcerion      break;
4590b85e8bba97fdae7d892f7bfd12e4601307e4721dcerion
4591b85e8bba97fdae7d892f7bfd12e4601307e4721dcerion   default:
45925b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion      vex_printf("dis_int_logic(ppc)(opc1)\n");
4593b85e8bba97fdae7d892f7bfd12e4601307e4721dcerion      return False;
4594b85e8bba97fdae7d892f7bfd12e4601307e4721dcerion   }
459570e2412f623c955d7b199f09401732cf57417fc2cerion
459676de5cf615380b23b4b5bcced6541233cd4a93a0cerion   putIReg( rA_addr, mkexpr(rA) );
459776de5cf615380b23b4b5bcced6541233cd4a93a0cerion
459876de5cf615380b23b4b5bcced6541233cd4a93a0cerion   if (do_rc && flag_rC) {
459976de5cf615380b23b4b5bcced6541233cd4a93a0cerion      set_CR0( mkexpr(rA) );
4600b85e8bba97fdae7d892f7bfd12e4601307e4721dcerion   }
4601b85e8bba97fdae7d892f7bfd12e4601307e4721dcerion   return True;
4602645c930b1a61f4493ee2d472b34fbb439233a874cerion}
4603645c930b1a61f4493ee2d472b34fbb439233a874cerion
46047e84630580f89c1022dde97007bffbf6aef81814sewardj/*
46057e84630580f89c1022dde97007bffbf6aef81814sewardj  Integer Parity Instructions
46067e84630580f89c1022dde97007bffbf6aef81814sewardj*/
46077e84630580f89c1022dde97007bffbf6aef81814sewardjstatic Bool dis_int_parity ( UInt theInstr )
46087e84630580f89c1022dde97007bffbf6aef81814sewardj{
46097e84630580f89c1022dde97007bffbf6aef81814sewardj   /* X-Form */
46107e84630580f89c1022dde97007bffbf6aef81814sewardj   UChar opc1    = ifieldOPC(theInstr);
46117e84630580f89c1022dde97007bffbf6aef81814sewardj   UChar rS_addr = ifieldRegDS(theInstr);
46127e84630580f89c1022dde97007bffbf6aef81814sewardj   UChar rA_addr = ifieldRegA(theInstr);
46137e84630580f89c1022dde97007bffbf6aef81814sewardj   UChar rB_addr = ifieldRegB(theInstr);
46147e84630580f89c1022dde97007bffbf6aef81814sewardj   UInt  opc2    = ifieldOPClo10(theInstr);
46157e84630580f89c1022dde97007bffbf6aef81814sewardj   UChar b0      = ifieldBIT0(theInstr);
46167e84630580f89c1022dde97007bffbf6aef81814sewardj   IRType ty     = mode64 ? Ity_I64 : Ity_I32;
46177e84630580f89c1022dde97007bffbf6aef81814sewardj
46187e84630580f89c1022dde97007bffbf6aef81814sewardj   IRTemp rS     = newTemp(ty);
46197e84630580f89c1022dde97007bffbf6aef81814sewardj   IRTemp rA     = newTemp(ty);
46207e84630580f89c1022dde97007bffbf6aef81814sewardj   IRTemp iTot1  = newTemp(Ity_I32);
46217e84630580f89c1022dde97007bffbf6aef81814sewardj   IRTemp iTot2  = newTemp(Ity_I32);
46227e84630580f89c1022dde97007bffbf6aef81814sewardj   IRTemp iTot3  = newTemp(Ity_I32);
46237e84630580f89c1022dde97007bffbf6aef81814sewardj   IRTemp iTot4  = newTemp(Ity_I32);
46247e84630580f89c1022dde97007bffbf6aef81814sewardj   IRTemp iTot5  = newTemp(Ity_I32);
46257e84630580f89c1022dde97007bffbf6aef81814sewardj   IRTemp iTot6  = newTemp(Ity_I32);
46267e84630580f89c1022dde97007bffbf6aef81814sewardj   IRTemp iTot7  = newTemp(Ity_I32);
46277e84630580f89c1022dde97007bffbf6aef81814sewardj   IRTemp iTot8  = newTemp(Ity_I32);
46287e84630580f89c1022dde97007bffbf6aef81814sewardj   IRTemp rS1    = newTemp(ty);
46297e84630580f89c1022dde97007bffbf6aef81814sewardj   IRTemp rS2    = newTemp(ty);
46307e84630580f89c1022dde97007bffbf6aef81814sewardj   IRTemp rS3    = newTemp(ty);
46317e84630580f89c1022dde97007bffbf6aef81814sewardj   IRTemp rS4    = newTemp(ty);
46327e84630580f89c1022dde97007bffbf6aef81814sewardj   IRTemp rS5    = newTemp(ty);
46337e84630580f89c1022dde97007bffbf6aef81814sewardj   IRTemp rS6    = newTemp(ty);
46347e84630580f89c1022dde97007bffbf6aef81814sewardj   IRTemp rS7    = newTemp(ty);
46357e84630580f89c1022dde97007bffbf6aef81814sewardj   IRTemp iHi    = newTemp(Ity_I32);
46367e84630580f89c1022dde97007bffbf6aef81814sewardj   IRTemp iLo    = newTemp(Ity_I32);
46377e84630580f89c1022dde97007bffbf6aef81814sewardj   IROp to_bit   = (mode64 ? Iop_64to1 : Iop_32to1);
46387e84630580f89c1022dde97007bffbf6aef81814sewardj   IROp shr_op   = (mode64 ? Iop_Shr64 : Iop_Shr32);
46397e84630580f89c1022dde97007bffbf6aef81814sewardj
46407e84630580f89c1022dde97007bffbf6aef81814sewardj   if (opc1 != 0x1f || rB_addr || b0) {
46417e84630580f89c1022dde97007bffbf6aef81814sewardj      vex_printf("dis_int_parity(ppc)(0x1F,opc1:rB|b0)\n");
46427e84630580f89c1022dde97007bffbf6aef81814sewardj      return False;
46437e84630580f89c1022dde97007bffbf6aef81814sewardj   }
46447e84630580f89c1022dde97007bffbf6aef81814sewardj
46457e84630580f89c1022dde97007bffbf6aef81814sewardj   assign( rS, getIReg(rS_addr) );
46467e84630580f89c1022dde97007bffbf6aef81814sewardj
46477e84630580f89c1022dde97007bffbf6aef81814sewardj   switch (opc2) {
46487e84630580f89c1022dde97007bffbf6aef81814sewardj   case 0xba:  // prtyd (Parity Doubleword, ISA 2.05 p320)
46497e84630580f89c1022dde97007bffbf6aef81814sewardj      DIP("prtyd r%u,r%u\n", rA_addr, rS_addr);
46507e84630580f89c1022dde97007bffbf6aef81814sewardj      assign( iTot1, unop(Iop_1Uto32, unop(to_bit, mkexpr(rS))) );
46517e84630580f89c1022dde97007bffbf6aef81814sewardj      assign( rS1, binop(shr_op, mkexpr(rS), mkU8(8)) );
46527e84630580f89c1022dde97007bffbf6aef81814sewardj      assign( iTot2, binop(Iop_Add32,
46537e84630580f89c1022dde97007bffbf6aef81814sewardj                           unop(Iop_1Uto32, unop(to_bit, mkexpr(rS1))),
46547e84630580f89c1022dde97007bffbf6aef81814sewardj                           mkexpr(iTot1)) );
46557e84630580f89c1022dde97007bffbf6aef81814sewardj      assign( rS2, binop(shr_op, mkexpr(rS1), mkU8(8)) );
46567e84630580f89c1022dde97007bffbf6aef81814sewardj      assign( iTot3, binop(Iop_Add32,
46577e84630580f89c1022dde97007bffbf6aef81814sewardj                           unop(Iop_1Uto32, unop(to_bit, mkexpr(rS2))),
46587e84630580f89c1022dde97007bffbf6aef81814sewardj                           mkexpr(iTot2)) );
46597e84630580f89c1022dde97007bffbf6aef81814sewardj      assign( rS3, binop(shr_op, mkexpr(rS2), mkU8(8)) );
46607e84630580f89c1022dde97007bffbf6aef81814sewardj      assign( iTot4, binop(Iop_Add32,
46617e84630580f89c1022dde97007bffbf6aef81814sewardj                           unop(Iop_1Uto32, unop(to_bit, mkexpr(rS3))),
46627e84630580f89c1022dde97007bffbf6aef81814sewardj                           mkexpr(iTot3)) );
46637e84630580f89c1022dde97007bffbf6aef81814sewardj      if (mode64) {
46647e84630580f89c1022dde97007bffbf6aef81814sewardj         assign( rS4, binop(shr_op, mkexpr(rS3), mkU8(8)) );
46657e84630580f89c1022dde97007bffbf6aef81814sewardj         assign( iTot5, binop(Iop_Add32,
46667e84630580f89c1022dde97007bffbf6aef81814sewardj                              unop(Iop_1Uto32, unop(to_bit, mkexpr(rS4))),
46677e84630580f89c1022dde97007bffbf6aef81814sewardj                              mkexpr(iTot4)) );
46687e84630580f89c1022dde97007bffbf6aef81814sewardj         assign( rS5, binop(shr_op, mkexpr(rS4), mkU8(8)) );
46697e84630580f89c1022dde97007bffbf6aef81814sewardj         assign( iTot6, binop(Iop_Add32,
46707e84630580f89c1022dde97007bffbf6aef81814sewardj                              unop(Iop_1Uto32, unop(to_bit, mkexpr(rS5))),
46717e84630580f89c1022dde97007bffbf6aef81814sewardj                              mkexpr(iTot5)) );
46727e84630580f89c1022dde97007bffbf6aef81814sewardj         assign( rS6, binop(shr_op, mkexpr(rS5), mkU8(8)) );
46737e84630580f89c1022dde97007bffbf6aef81814sewardj         assign( iTot7, binop(Iop_Add32,
46747e84630580f89c1022dde97007bffbf6aef81814sewardj                              unop(Iop_1Uto32, unop(to_bit, mkexpr(rS6))),
46757e84630580f89c1022dde97007bffbf6aef81814sewardj                              mkexpr(iTot6)) );
46767e84630580f89c1022dde97007bffbf6aef81814sewardj         assign( rS7, binop(shr_op, mkexpr(rS6), mkU8(8)) );
46777e84630580f89c1022dde97007bffbf6aef81814sewardj         assign( iTot8, binop(Iop_Add32,
46787e84630580f89c1022dde97007bffbf6aef81814sewardj                              unop(Iop_1Uto32, unop(to_bit, mkexpr(rS7))),
46797e84630580f89c1022dde97007bffbf6aef81814sewardj                              mkexpr(iTot7)) );
46807e84630580f89c1022dde97007bffbf6aef81814sewardj         assign( rA, unop(Iop_32Uto64,
46817e84630580f89c1022dde97007bffbf6aef81814sewardj                          binop(Iop_And32, mkexpr(iTot8), mkU32(1))) );
46827e84630580f89c1022dde97007bffbf6aef81814sewardj      } else
46837e84630580f89c1022dde97007bffbf6aef81814sewardj         assign( rA, mkexpr(iTot4) );
46847e84630580f89c1022dde97007bffbf6aef81814sewardj
46857e84630580f89c1022dde97007bffbf6aef81814sewardj      break;
46867e84630580f89c1022dde97007bffbf6aef81814sewardj   case 0x9a:  // prtyw (Parity Word, ISA 2.05 p320)
46877e84630580f89c1022dde97007bffbf6aef81814sewardj      assign( iTot1, unop(Iop_1Uto32, unop(to_bit, mkexpr(rS))) );
46887e84630580f89c1022dde97007bffbf6aef81814sewardj      assign( rS1, binop(shr_op, mkexpr(rS), mkU8(8)) );
46897e84630580f89c1022dde97007bffbf6aef81814sewardj      assign( iTot2, binop(Iop_Add32,
46907e84630580f89c1022dde97007bffbf6aef81814sewardj                           unop(Iop_1Uto32, unop(to_bit, mkexpr(rS1))),
46917e84630580f89c1022dde97007bffbf6aef81814sewardj                           mkexpr(iTot1)) );
46927e84630580f89c1022dde97007bffbf6aef81814sewardj      assign( rS2, binop(shr_op, mkexpr(rS1), mkU8(8)) );
46937e84630580f89c1022dde97007bffbf6aef81814sewardj      assign( iTot3, binop(Iop_Add32,
46947e84630580f89c1022dde97007bffbf6aef81814sewardj                           unop(Iop_1Uto32, unop(to_bit, mkexpr(rS2))),
46957e84630580f89c1022dde97007bffbf6aef81814sewardj                           mkexpr(iTot2)) );
46967e84630580f89c1022dde97007bffbf6aef81814sewardj      assign( rS3, binop(shr_op, mkexpr(rS2), mkU8(8)) );
46977e84630580f89c1022dde97007bffbf6aef81814sewardj      assign( iTot4, binop(Iop_Add32,
46987e84630580f89c1022dde97007bffbf6aef81814sewardj                           unop(Iop_1Uto32, unop(to_bit, mkexpr(rS3))),
46997e84630580f89c1022dde97007bffbf6aef81814sewardj                           mkexpr(iTot3)) );
47007e84630580f89c1022dde97007bffbf6aef81814sewardj      assign( iLo, unop(Iop_1Uto32, unop(Iop_32to1, mkexpr(iTot4) )) );
47017e84630580f89c1022dde97007bffbf6aef81814sewardj
47027e84630580f89c1022dde97007bffbf6aef81814sewardj      if (mode64) {
47037e84630580f89c1022dde97007bffbf6aef81814sewardj         assign( rS4, binop(shr_op, mkexpr(rS3), mkU8(8)) );
47047e84630580f89c1022dde97007bffbf6aef81814sewardj         assign( iTot5, unop(Iop_1Uto32, unop(to_bit, mkexpr(rS4))) );
47057e84630580f89c1022dde97007bffbf6aef81814sewardj         assign( rS5, binop(shr_op, mkexpr(rS4), mkU8(8)) );
47067e84630580f89c1022dde97007bffbf6aef81814sewardj         assign( iTot6, binop(Iop_Add32,
47077e84630580f89c1022dde97007bffbf6aef81814sewardj                              unop(Iop_1Uto32, unop(to_bit, mkexpr(rS5))),
47087e84630580f89c1022dde97007bffbf6aef81814sewardj                              mkexpr(iTot5)) );
47097e84630580f89c1022dde97007bffbf6aef81814sewardj         assign( rS6, binop(shr_op, mkexpr(rS5), mkU8(8)) );
47107e84630580f89c1022dde97007bffbf6aef81814sewardj         assign( iTot7, binop(Iop_Add32,
47117e84630580f89c1022dde97007bffbf6aef81814sewardj                              unop(Iop_1Uto32, unop(to_bit, mkexpr(rS6))),
47127e84630580f89c1022dde97007bffbf6aef81814sewardj                              mkexpr(iTot6)) );
47137e84630580f89c1022dde97007bffbf6aef81814sewardj         assign( rS7, binop(shr_op, mkexpr(rS6), mkU8(8)));
47147e84630580f89c1022dde97007bffbf6aef81814sewardj         assign( iTot8, binop(Iop_Add32,
47157e84630580f89c1022dde97007bffbf6aef81814sewardj                              unop(Iop_1Uto32, unop(to_bit, mkexpr(rS7))),
47167e84630580f89c1022dde97007bffbf6aef81814sewardj                              mkexpr(iTot7)) );
47177e84630580f89c1022dde97007bffbf6aef81814sewardj         assign( iHi, binop(Iop_And32, mkU32(1), mkexpr(iTot8)) ),
47187e84630580f89c1022dde97007bffbf6aef81814sewardj            assign( rA, binop(Iop_32HLto64, mkexpr(iHi), mkexpr(iLo)) );
47197e84630580f89c1022dde97007bffbf6aef81814sewardj      } else
47207e84630580f89c1022dde97007bffbf6aef81814sewardj         assign( rA, binop(Iop_Or32, mkU32(0), mkexpr(iLo)) );
47217e84630580f89c1022dde97007bffbf6aef81814sewardj      break;
47227e84630580f89c1022dde97007bffbf6aef81814sewardj   default:
47237e84630580f89c1022dde97007bffbf6aef81814sewardj      vex_printf("dis_int_parity(ppc)(opc2)\n");
47247e84630580f89c1022dde97007bffbf6aef81814sewardj      return False;
47257e84630580f89c1022dde97007bffbf6aef81814sewardj   }
47267e84630580f89c1022dde97007bffbf6aef81814sewardj
47277e84630580f89c1022dde97007bffbf6aef81814sewardj   putIReg( rA_addr, mkexpr(rA) );
47287e84630580f89c1022dde97007bffbf6aef81814sewardj
47297e84630580f89c1022dde97007bffbf6aef81814sewardj   return True;
47307e84630580f89c1022dde97007bffbf6aef81814sewardj}
4731645c930b1a61f4493ee2d472b34fbb439233a874cerion
4732645c930b1a61f4493ee2d472b34fbb439233a874cerion
47333d870a39e4d145e2f3d9f9a0eeed3475ec934ac1cerion/*
47343d870a39e4d145e2f3d9f9a0eeed3475ec934ac1cerion  Integer Rotate Instructions
47353d870a39e4d145e2f3d9f9a0eeed3475ec934ac1cerion*/
4736645c930b1a61f4493ee2d472b34fbb439233a874cerionstatic Bool dis_int_rot ( UInt theInstr )
4737645c930b1a61f4493ee2d472b34fbb439233a874cerion{
4738f0de28cf1a762b0d6f74c93d3532c89a230673bbcerion   /* M-Form, MDS-Form */
4739d953ebb9b04cbad6891676df597bf0c542b1ec89cerion   UChar opc1    = ifieldOPC(theInstr);
4740d953ebb9b04cbad6891676df597bf0c542b1ec89cerion   UChar rS_addr = ifieldRegDS(theInstr);
4741d953ebb9b04cbad6891676df597bf0c542b1ec89cerion   UChar rA_addr = ifieldRegA(theInstr);
4742d953ebb9b04cbad6891676df597bf0c542b1ec89cerion   UChar rB_addr = ifieldRegB(theInstr);
4743d953ebb9b04cbad6891676df597bf0c542b1ec89cerion   UChar sh_imm  = rB_addr;
4744d953ebb9b04cbad6891676df597bf0c542b1ec89cerion   UChar MaskBeg = toUChar( IFIELD( theInstr, 6, 5 ) );
4745d953ebb9b04cbad6891676df597bf0c542b1ec89cerion   UChar MaskEnd = toUChar( IFIELD( theInstr, 1, 5 ) );
4746f0de28cf1a762b0d6f74c93d3532c89a230673bbcerion   UChar msk_imm = toUChar( IFIELD( theInstr, 5, 6 ) );
4747f0de28cf1a762b0d6f74c93d3532c89a230673bbcerion   UChar opc2    = toUChar( IFIELD( theInstr, 2, 3 ) );
4748f0de28cf1a762b0d6f74c93d3532c89a230673bbcerion   UChar b1      = ifieldBIT1(theInstr);
4749d953ebb9b04cbad6891676df597bf0c542b1ec89cerion   UChar flag_rC = ifieldBIT0(theInstr);
4750d953ebb9b04cbad6891676df597bf0c542b1ec89cerion
4751d953ebb9b04cbad6891676df597bf0c542b1ec89cerion   IRType ty     = mode64 ? Ity_I64 : Ity_I32;
4752d953ebb9b04cbad6891676df597bf0c542b1ec89cerion   IRTemp rS     = newTemp(ty);
4753d953ebb9b04cbad6891676df597bf0c542b1ec89cerion   IRTemp rA     = newTemp(ty);
4754d953ebb9b04cbad6891676df597bf0c542b1ec89cerion   IRTemp rB     = newTemp(ty);
4755bb01b7cbfd84c27dd213f67a144ea5a99af36961cerion   IRTemp rot    = newTemp(ty);
4756d953ebb9b04cbad6891676df597bf0c542b1ec89cerion   IRExpr *r;
4757f0de28cf1a762b0d6f74c93d3532c89a230673bbcerion   UInt   mask32;
4758f0de28cf1a762b0d6f74c93d3532c89a230673bbcerion   ULong  mask64;
475976de5cf615380b23b4b5bcced6541233cd4a93a0cerion
476076de5cf615380b23b4b5bcced6541233cd4a93a0cerion   assign( rS, getIReg(rS_addr) );
476176de5cf615380b23b4b5bcced6541233cd4a93a0cerion   assign( rB, getIReg(rB_addr) );
4762d953ebb9b04cbad6891676df597bf0c542b1ec89cerion
4763b85e8bba97fdae7d892f7bfd12e4601307e4721dcerion   switch (opc1) {
4764d953ebb9b04cbad6891676df597bf0c542b1ec89cerion   case 0x14: {
47655b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion      // rlwimi (Rotate Left Word Imm then Mask Insert, PPC32 p500)
47665b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion      DIP("rlwimi%s r%u,r%u,%d,%d,%d\n", flag_rC ? ".":"",
4767d953ebb9b04cbad6891676df597bf0c542b1ec89cerion          rA_addr, rS_addr, sh_imm, MaskBeg, MaskEnd);
4768d953ebb9b04cbad6891676df597bf0c542b1ec89cerion      if (mode64) {
4769d953ebb9b04cbad6891676df597bf0c542b1ec89cerion         // tmp32 = (ROTL(rS_Lo32, Imm)
4770d953ebb9b04cbad6891676df597bf0c542b1ec89cerion         // rA = ((tmp32 || tmp32) & mask64) | (rA & ~mask64)
4771f0de28cf1a762b0d6f74c93d3532c89a230673bbcerion         mask64 = MASK64(31-MaskEnd, 31-MaskBeg);
4772d953ebb9b04cbad6891676df597bf0c542b1ec89cerion         r = ROTL( unop(Iop_64to32, mkexpr(rS) ), mkU8(sh_imm) );
4773d953ebb9b04cbad6891676df597bf0c542b1ec89cerion         r = unop(Iop_32Uto64, r);
47745b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion         assign( rot, binop(Iop_Or64, r,
47755b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion                            binop(Iop_Shl64, r, mkU8(32))) );
4776d953ebb9b04cbad6891676df597bf0c542b1ec89cerion         assign( rA,
4777d953ebb9b04cbad6891676df597bf0c542b1ec89cerion            binop(Iop_Or64,
4778bb01b7cbfd84c27dd213f67a144ea5a99af36961cerion                  binop(Iop_And64, mkexpr(rot), mkU64(mask64)),
4779f0de28cf1a762b0d6f74c93d3532c89a230673bbcerion                  binop(Iop_And64, getIReg(rA_addr), mkU64(~mask64))) );
4780d953ebb9b04cbad6891676df597bf0c542b1ec89cerion      }
4781d953ebb9b04cbad6891676df597bf0c542b1ec89cerion      else {
4782d953ebb9b04cbad6891676df597bf0c542b1ec89cerion         // rA = (ROTL(rS, Imm) & mask) | (rA & ~mask);
4783f0de28cf1a762b0d6f74c93d3532c89a230673bbcerion         mask32 = MASK32(31-MaskEnd, 31-MaskBeg);
4784f0de28cf1a762b0d6f74c93d3532c89a230673bbcerion         r = ROTL(mkexpr(rS), mkU8(sh_imm));
4785d953ebb9b04cbad6891676df597bf0c542b1ec89cerion         assign( rA,
4786d953ebb9b04cbad6891676df597bf0c542b1ec89cerion            binop(Iop_Or32,
4787f0de28cf1a762b0d6f74c93d3532c89a230673bbcerion                  binop(Iop_And32, mkU32(mask32), r),
4788f0de28cf1a762b0d6f74c93d3532c89a230673bbcerion                  binop(Iop_And32, getIReg(rA_addr), mkU32(~mask32))) );
4789d953ebb9b04cbad6891676df597bf0c542b1ec89cerion      }
4790b85e8bba97fdae7d892f7bfd12e4601307e4721dcerion      break;
4791d953ebb9b04cbad6891676df597bf0c542b1ec89cerion   }
4792b85e8bba97fdae7d892f7bfd12e4601307e4721dcerion
4793d953ebb9b04cbad6891676df597bf0c542b1ec89cerion   case 0x15: {
47945b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion      // rlwinm (Rotate Left Word Imm then AND with Mask, PPC32 p501)
4795d953ebb9b04cbad6891676df597bf0c542b1ec89cerion      vassert(MaskBeg < 32);
4796d953ebb9b04cbad6891676df597bf0c542b1ec89cerion      vassert(MaskEnd < 32);
4797d953ebb9b04cbad6891676df597bf0c542b1ec89cerion      vassert(sh_imm  < 32);
4798d953ebb9b04cbad6891676df597bf0c542b1ec89cerion
4799d953ebb9b04cbad6891676df597bf0c542b1ec89cerion      if (mode64) {
4800ef4433b5487a1a639af07883417a1d5cb75eee89sewardj         IRTemp rTmp = newTemp(Ity_I64);
4801f0de28cf1a762b0d6f74c93d3532c89a230673bbcerion         mask64 = MASK64(31-MaskEnd, 31-MaskBeg);
48025b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion         DIP("rlwinm%s r%u,r%u,%d,%d,%d\n", flag_rC ? ".":"",
4803d953ebb9b04cbad6891676df597bf0c542b1ec89cerion             rA_addr, rS_addr, sh_imm, MaskBeg, MaskEnd);
4804d953ebb9b04cbad6891676df597bf0c542b1ec89cerion         // tmp32 = (ROTL(rS_Lo32, Imm)
4805d953ebb9b04cbad6891676df597bf0c542b1ec89cerion         // rA = ((tmp32 || tmp32) & mask64)
4806d953ebb9b04cbad6891676df597bf0c542b1ec89cerion         r = ROTL( unop(Iop_64to32, mkexpr(rS) ), mkU8(sh_imm) );
4807d953ebb9b04cbad6891676df597bf0c542b1ec89cerion         r = unop(Iop_32Uto64, r);
4808ef4433b5487a1a639af07883417a1d5cb75eee89sewardj         assign( rTmp, r );
4809ef4433b5487a1a639af07883417a1d5cb75eee89sewardj         r = NULL;
4810ef4433b5487a1a639af07883417a1d5cb75eee89sewardj         assign( rot, binop(Iop_Or64, mkexpr(rTmp),
4811ef4433b5487a1a639af07883417a1d5cb75eee89sewardj                            binop(Iop_Shl64, mkexpr(rTmp), mkU8(32))) );
4812bb01b7cbfd84c27dd213f67a144ea5a99af36961cerion         assign( rA, binop(Iop_And64, mkexpr(rot), mkU64(mask64)) );
481326b3320973ccdd634fc5461d832e86b3b6aa878fsewardj      }
481426b3320973ccdd634fc5461d832e86b3b6aa878fsewardj      else {
4815d953ebb9b04cbad6891676df597bf0c542b1ec89cerion         if (MaskBeg == 0 && sh_imm+MaskEnd == 31) {
4816d953ebb9b04cbad6891676df597bf0c542b1ec89cerion            /* Special-case the ,n,0,31-n form as that is just n-bit
48175b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion               shift left, PPC32 p501 */
48185b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion            DIP("slwi%s r%u,r%u,%d\n", flag_rC ? ".":"",
4819d953ebb9b04cbad6891676df597bf0c542b1ec89cerion                rA_addr, rS_addr, sh_imm);
4820d953ebb9b04cbad6891676df597bf0c542b1ec89cerion            assign( rA, binop(Iop_Shl32, mkexpr(rS), mkU8(sh_imm)) );
4821d953ebb9b04cbad6891676df597bf0c542b1ec89cerion         }
48222831b00c4950d6c2b061def05fd67528fe132ececerion         else if (MaskEnd == 31 && sh_imm+MaskBeg == 32) {
48232831b00c4950d6c2b061def05fd67528fe132ececerion            /* Special-case the ,32-n,n,31 form as that is just n-bit
48245b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion               unsigned shift right, PPC32 p501 */
48255b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion            DIP("srwi%s r%u,r%u,%d\n", flag_rC ? ".":"",
4826ee4a859c6da6539f6c6df225cb920dc6fc37facdsewardj                rA_addr, rS_addr, MaskBeg);
48272831b00c4950d6c2b061def05fd67528fe132ececerion            assign( rA, binop(Iop_Shr32, mkexpr(rS), mkU8(MaskBeg)) );
48282831b00c4950d6c2b061def05fd67528fe132ececerion         }
48292831b00c4950d6c2b061def05fd67528fe132ececerion         else {
48302831b00c4950d6c2b061def05fd67528fe132ececerion            /* General case. */
4831f0de28cf1a762b0d6f74c93d3532c89a230673bbcerion            mask32 = MASK32(31-MaskEnd, 31-MaskBeg);
48325b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion            DIP("rlwinm%s r%u,r%u,%d,%d,%d\n", flag_rC ? ".":"",
48332831b00c4950d6c2b061def05fd67528fe132ececerion                rA_addr, rS_addr, sh_imm, MaskBeg, MaskEnd);
48342831b00c4950d6c2b061def05fd67528fe132ececerion            // rA = ROTL(rS, Imm) & mask
48355b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion            assign( rA, binop(Iop_And32,
48365b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion                              ROTL(mkexpr(rS), mkU8(sh_imm)),
4837f0de28cf1a762b0d6f74c93d3532c89a230673bbcerion                              mkU32(mask32)) );
48382831b00c4950d6c2b061def05fd67528fe132ececerion         }
483926b3320973ccdd634fc5461d832e86b3b6aa878fsewardj      }
4840b85e8bba97fdae7d892f7bfd12e4601307e4721dcerion      break;
4841d953ebb9b04cbad6891676df597bf0c542b1ec89cerion   }
4842b85e8bba97fdae7d892f7bfd12e4601307e4721dcerion
4843d953ebb9b04cbad6891676df597bf0c542b1ec89cerion   case 0x17: {
4844c965953e12be58c7d01cd6d024d6f42326b2b797sewardj      // rlwnm (Rotate Left Word then AND with Mask, PPC32 p503
48455b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion      DIP("rlwnm%s r%u,r%u,r%u,%d,%d\n", flag_rC ? ".":"",
4846d953ebb9b04cbad6891676df597bf0c542b1ec89cerion          rA_addr, rS_addr, rB_addr, MaskBeg, MaskEnd);
4847d953ebb9b04cbad6891676df597bf0c542b1ec89cerion      if (mode64) {
4848f0de28cf1a762b0d6f74c93d3532c89a230673bbcerion         mask64 = MASK64(31-MaskEnd, 31-MaskBeg);
4849bb01b7cbfd84c27dd213f67a144ea5a99af36961cerion         /* weird insn alert!
4850bb01b7cbfd84c27dd213f67a144ea5a99af36961cerion            tmp32 = (ROTL(rS_Lo32, rB[0-4])
4851bb01b7cbfd84c27dd213f67a144ea5a99af36961cerion            rA = ((tmp32 || tmp32) & mask64)
4852bb01b7cbfd84c27dd213f67a144ea5a99af36961cerion         */
4853d953ebb9b04cbad6891676df597bf0c542b1ec89cerion         // note, ROTL does the masking, so we don't do it here
4854d953ebb9b04cbad6891676df597bf0c542b1ec89cerion         r = ROTL( unop(Iop_64to32, mkexpr(rS)),
4855bb01b7cbfd84c27dd213f67a144ea5a99af36961cerion                   unop(Iop_64to8, mkexpr(rB)) );
4856d953ebb9b04cbad6891676df597bf0c542b1ec89cerion         r = unop(Iop_32Uto64, r);
4857bb01b7cbfd84c27dd213f67a144ea5a99af36961cerion         assign(rot, binop(Iop_Or64, r, binop(Iop_Shl64, r, mkU8(32))));
4858bb01b7cbfd84c27dd213f67a144ea5a99af36961cerion         assign( rA, binop(Iop_And64, mkexpr(rot), mkU64(mask64)) );
4859d953ebb9b04cbad6891676df597bf0c542b1ec89cerion      } else {
4860f0de28cf1a762b0d6f74c93d3532c89a230673bbcerion         mask32 = MASK32(31-MaskEnd, 31-MaskBeg);
4861d953ebb9b04cbad6891676df597bf0c542b1ec89cerion         // rA = ROTL(rS, rB[0-4]) & mask
4862d953ebb9b04cbad6891676df597bf0c542b1ec89cerion         // note, ROTL does the masking, so we don't do it here
4863d953ebb9b04cbad6891676df597bf0c542b1ec89cerion         assign( rA, binop(Iop_And32,
48645b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion                           ROTL(mkexpr(rS),
48655b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion                                unop(Iop_32to8, mkexpr(rB))),
4866f0de28cf1a762b0d6f74c93d3532c89a230673bbcerion                           mkU32(mask32)) );
4867d953ebb9b04cbad6891676df597bf0c542b1ec89cerion      }
4868c965953e12be58c7d01cd6d024d6f42326b2b797sewardj      break;
4869d953ebb9b04cbad6891676df597bf0c542b1ec89cerion   }
4870645c930b1a61f4493ee2d472b34fbb439233a874cerion
4871f0de28cf1a762b0d6f74c93d3532c89a230673bbcerion   /* 64bit Integer Rotates */
4872f0de28cf1a762b0d6f74c93d3532c89a230673bbcerion   case 0x1E: {
4873f0de28cf1a762b0d6f74c93d3532c89a230673bbcerion      msk_imm = ((msk_imm & 1) << 5) | (msk_imm >> 1);
4874f0de28cf1a762b0d6f74c93d3532c89a230673bbcerion      sh_imm |= b1 << 5;
4875f0de28cf1a762b0d6f74c93d3532c89a230673bbcerion
4876f0de28cf1a762b0d6f74c93d3532c89a230673bbcerion      vassert( msk_imm < 64 );
4877f0de28cf1a762b0d6f74c93d3532c89a230673bbcerion      vassert( sh_imm < 64 );
4878f0de28cf1a762b0d6f74c93d3532c89a230673bbcerion
4879f0de28cf1a762b0d6f74c93d3532c89a230673bbcerion      switch (opc2) {
488007b07a966a2fdbcf621251a0c1a8ab84807fb120cerion      case 0x4: {
488107b07a966a2fdbcf621251a0c1a8ab84807fb120cerion         /* r = ROTL64( rS, rB_lo6) */
488207b07a966a2fdbcf621251a0c1a8ab84807fb120cerion         r = ROTL( mkexpr(rS), unop(Iop_64to8, mkexpr(rB)) );
488307b07a966a2fdbcf621251a0c1a8ab84807fb120cerion
48845b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion         if (b1 == 0) { // rldcl (Rotl DWord, Clear Left, PPC64 p555)
48855b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion            DIP("rldcl%s r%u,r%u,r%u,%u\n", flag_rC ? ".":"",
4886f0de28cf1a762b0d6f74c93d3532c89a230673bbcerion                rA_addr, rS_addr, rB_addr, msk_imm);
488707b07a966a2fdbcf621251a0c1a8ab84807fb120cerion            // note, ROTL does the masking, so we don't do it here
4888f0de28cf1a762b0d6f74c93d3532c89a230673bbcerion            mask64 = MASK64(0, 63-msk_imm);
4889f0de28cf1a762b0d6f74c93d3532c89a230673bbcerion            assign( rA, binop(Iop_And64, r, mkU64(mask64)) );
4890f0de28cf1a762b0d6f74c93d3532c89a230673bbcerion            break;
48915b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion         } else {       // rldcr (Rotl DWord, Clear Right, PPC64 p556)
48925b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion            DIP("rldcr%s r%u,r%u,r%u,%u\n", flag_rC ? ".":"",
4893f0de28cf1a762b0d6f74c93d3532c89a230673bbcerion                rA_addr, rS_addr, rB_addr, msk_imm);
4894f0de28cf1a762b0d6f74c93d3532c89a230673bbcerion            mask64 = MASK64(63-msk_imm, 63);
4895f0de28cf1a762b0d6f74c93d3532c89a230673bbcerion            assign( rA, binop(Iop_And64, r, mkU64(mask64)) );
4896f0de28cf1a762b0d6f74c93d3532c89a230673bbcerion            break;
4897f0de28cf1a762b0d6f74c93d3532c89a230673bbcerion         }
4898f0de28cf1a762b0d6f74c93d3532c89a230673bbcerion         break;
489907b07a966a2fdbcf621251a0c1a8ab84807fb120cerion      }
49005b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion      case 0x2: // rldic (Rotl DWord Imm, Clear, PPC64 p557)
49015b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion         DIP("rldic%s r%u,r%u,%u,%u\n", flag_rC ? ".":"",
4902f0de28cf1a762b0d6f74c93d3532c89a230673bbcerion             rA_addr, rS_addr, sh_imm, msk_imm);
4903f0de28cf1a762b0d6f74c93d3532c89a230673bbcerion         r = ROTL(mkexpr(rS), mkU8(sh_imm));
4904f0de28cf1a762b0d6f74c93d3532c89a230673bbcerion         mask64 = MASK64(sh_imm, 63-msk_imm);
4905f0de28cf1a762b0d6f74c93d3532c89a230673bbcerion         assign( rA, binop(Iop_And64, r, mkU64(mask64)) );
4906f0de28cf1a762b0d6f74c93d3532c89a230673bbcerion         break;
4907f0de28cf1a762b0d6f74c93d3532c89a230673bbcerion         // later: deal with special case: (msk_imm==0) => SHL(sh_imm)
4908f0de28cf1a762b0d6f74c93d3532c89a230673bbcerion         /*
4909f0de28cf1a762b0d6f74c93d3532c89a230673bbcerion           Hmm... looks like this'll do the job more simply:
4910f0de28cf1a762b0d6f74c93d3532c89a230673bbcerion           r = SHL(rS, sh_imm)
4911f0de28cf1a762b0d6f74c93d3532c89a230673bbcerion           m = ~(1 << (63-msk_imm))
4912f0de28cf1a762b0d6f74c93d3532c89a230673bbcerion           assign(rA, r & m);
4913f0de28cf1a762b0d6f74c93d3532c89a230673bbcerion         */
4914f0de28cf1a762b0d6f74c93d3532c89a230673bbcerion
49155b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion      case 0x0: // rldicl (Rotl DWord Imm, Clear Left, PPC64 p558)
4916ee4a859c6da6539f6c6df225cb920dc6fc37facdsewardj         if (mode64
4917ee4a859c6da6539f6c6df225cb920dc6fc37facdsewardj             && sh_imm + msk_imm == 64 && msk_imm >= 1 && msk_imm <= 63) {
4918ee4a859c6da6539f6c6df225cb920dc6fc37facdsewardj            /* special-case the ,64-n,n form as that is just
4919ee4a859c6da6539f6c6df225cb920dc6fc37facdsewardj               unsigned shift-right by n */
4920ee4a859c6da6539f6c6df225cb920dc6fc37facdsewardj            DIP("srdi%s r%u,r%u,%u\n",
4921ee4a859c6da6539f6c6df225cb920dc6fc37facdsewardj                flag_rC ? ".":"", rA_addr, rS_addr, msk_imm);
4922ee4a859c6da6539f6c6df225cb920dc6fc37facdsewardj            assign( rA, binop(Iop_Shr64, mkexpr(rS), mkU8(msk_imm)) );
4923ee4a859c6da6539f6c6df225cb920dc6fc37facdsewardj         } else {
4924ee4a859c6da6539f6c6df225cb920dc6fc37facdsewardj            DIP("rldicl%s r%u,r%u,%u,%u\n", flag_rC ? ".":"",
4925ee4a859c6da6539f6c6df225cb920dc6fc37facdsewardj                rA_addr, rS_addr, sh_imm, msk_imm);
4926ee4a859c6da6539f6c6df225cb920dc6fc37facdsewardj            r = ROTL(mkexpr(rS), mkU8(sh_imm));
4927ee4a859c6da6539f6c6df225cb920dc6fc37facdsewardj            mask64 = MASK64(0, 63-msk_imm);
4928ee4a859c6da6539f6c6df225cb920dc6fc37facdsewardj            assign( rA, binop(Iop_And64, r, mkU64(mask64)) );
4929ee4a859c6da6539f6c6df225cb920dc6fc37facdsewardj         }
4930f0de28cf1a762b0d6f74c93d3532c89a230673bbcerion         break;
4931f0de28cf1a762b0d6f74c93d3532c89a230673bbcerion
49325b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion      case 0x1: // rldicr (Rotl DWord Imm, Clear Right, PPC64 p559)
4933ee4a859c6da6539f6c6df225cb920dc6fc37facdsewardj         if (mode64
4934ee4a859c6da6539f6c6df225cb920dc6fc37facdsewardj             && sh_imm + msk_imm == 63 && sh_imm >= 1 && sh_imm <= 63) {
4935ee4a859c6da6539f6c6df225cb920dc6fc37facdsewardj            /* special-case the ,n,63-n form as that is just
4936ee4a859c6da6539f6c6df225cb920dc6fc37facdsewardj               shift-left by n */
4937ee4a859c6da6539f6c6df225cb920dc6fc37facdsewardj            DIP("sldi%s r%u,r%u,%u\n",
4938ee4a859c6da6539f6c6df225cb920dc6fc37facdsewardj                flag_rC ? ".":"", rA_addr, rS_addr, sh_imm);
4939ee4a859c6da6539f6c6df225cb920dc6fc37facdsewardj            assign( rA, binop(Iop_Shl64, mkexpr(rS), mkU8(sh_imm)) );
4940ee4a859c6da6539f6c6df225cb920dc6fc37facdsewardj         } else {
4941ee4a859c6da6539f6c6df225cb920dc6fc37facdsewardj            DIP("rldicr%s r%u,r%u,%u,%u\n", flag_rC ? ".":"",
4942ee4a859c6da6539f6c6df225cb920dc6fc37facdsewardj                rA_addr, rS_addr, sh_imm, msk_imm);
4943ee4a859c6da6539f6c6df225cb920dc6fc37facdsewardj            r = ROTL(mkexpr(rS), mkU8(sh_imm));
4944ee4a859c6da6539f6c6df225cb920dc6fc37facdsewardj            mask64 = MASK64(63-msk_imm, 63);
4945ee4a859c6da6539f6c6df225cb920dc6fc37facdsewardj            assign( rA, binop(Iop_And64, r, mkU64(mask64)) );
4946ee4a859c6da6539f6c6df225cb920dc6fc37facdsewardj         }
4947f0de28cf1a762b0d6f74c93d3532c89a230673bbcerion         break;
4948f0de28cf1a762b0d6f74c93d3532c89a230673bbcerion
49495b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion      case 0x3: { // rldimi (Rotl DWord Imm, Mask Insert, PPC64 p560)
495007b07a966a2fdbcf621251a0c1a8ab84807fb120cerion         IRTemp rA_orig = newTemp(ty);
49515b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion         DIP("rldimi%s r%u,r%u,%u,%u\n", flag_rC ? ".":"",
4952f0de28cf1a762b0d6f74c93d3532c89a230673bbcerion             rA_addr, rS_addr, sh_imm, msk_imm);
4953f0de28cf1a762b0d6f74c93d3532c89a230673bbcerion         r = ROTL(mkexpr(rS), mkU8(sh_imm));
4954f0de28cf1a762b0d6f74c93d3532c89a230673bbcerion         mask64 = MASK64(sh_imm, 63-msk_imm);
495507b07a966a2fdbcf621251a0c1a8ab84807fb120cerion         assign( rA_orig, getIReg(rA_addr) );
4956f0de28cf1a762b0d6f74c93d3532c89a230673bbcerion         assign( rA, binop(Iop_Or64,
4957f0de28cf1a762b0d6f74c93d3532c89a230673bbcerion                           binop(Iop_And64, mkU64(mask64),  r),
49585b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion                           binop(Iop_And64, mkU64(~mask64),
49595b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion                                            mkexpr(rA_orig))) );
4960f0de28cf1a762b0d6f74c93d3532c89a230673bbcerion         break;
496107b07a966a2fdbcf621251a0c1a8ab84807fb120cerion      }
4962f0de28cf1a762b0d6f74c93d3532c89a230673bbcerion      default:
49635b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion         vex_printf("dis_int_rot(ppc)(opc2)\n");
4964f0de28cf1a762b0d6f74c93d3532c89a230673bbcerion         return False;
4965f0de28cf1a762b0d6f74c93d3532c89a230673bbcerion      }
4966f0de28cf1a762b0d6f74c93d3532c89a230673bbcerion      break;
4967f0de28cf1a762b0d6f74c93d3532c89a230673bbcerion   }
4968f0de28cf1a762b0d6f74c93d3532c89a230673bbcerion
4969b85e8bba97fdae7d892f7bfd12e4601307e4721dcerion   default:
49705b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion      vex_printf("dis_int_rot(ppc)(opc1)\n");
4971b85e8bba97fdae7d892f7bfd12e4601307e4721dcerion      return False;
4972b85e8bba97fdae7d892f7bfd12e4601307e4721dcerion   }
4973b85e8bba97fdae7d892f7bfd12e4601307e4721dcerion
497476de5cf615380b23b4b5bcced6541233cd4a93a0cerion   putIReg( rA_addr, mkexpr(rA) );
497576de5cf615380b23b4b5bcced6541233cd4a93a0cerion
497676de5cf615380b23b4b5bcced6541233cd4a93a0cerion   if (flag_rC) {
497776de5cf615380b23b4b5bcced6541233cd4a93a0cerion      set_CR0( mkexpr(rA) );
4978b85e8bba97fdae7d892f7bfd12e4601307e4721dcerion   }
4979b85e8bba97fdae7d892f7bfd12e4601307e4721dcerion   return True;
4980645c930b1a61f4493ee2d472b34fbb439233a874cerion}
4981645c930b1a61f4493ee2d472b34fbb439233a874cerion
4982645c930b1a61f4493ee2d472b34fbb439233a874cerion
49833d870a39e4d145e2f3d9f9a0eeed3475ec934ac1cerion/*
49843d870a39e4d145e2f3d9f9a0eeed3475ec934ac1cerion  Integer Load Instructions
49853d870a39e4d145e2f3d9f9a0eeed3475ec934ac1cerion*/
4986645c930b1a61f4493ee2d472b34fbb439233a874cerionstatic Bool dis_int_load ( UInt theInstr )
4987645c930b1a61f4493ee2d472b34fbb439233a874cerion{
4988f0de28cf1a762b0d6f74c93d3532c89a230673bbcerion   /* D-Form, X-Form, DS-Form */
498976de5cf615380b23b4b5bcced6541233cd4a93a0cerion   UChar opc1     = ifieldOPC(theInstr);
499076de5cf615380b23b4b5bcced6541233cd4a93a0cerion   UChar rD_addr  = ifieldRegDS(theInstr);
499176de5cf615380b23b4b5bcced6541233cd4a93a0cerion   UChar rA_addr  = ifieldRegA(theInstr);
4992d953ebb9b04cbad6891676df597bf0c542b1ec89cerion   UInt  uimm16   = ifieldUIMM16(theInstr);
499376de5cf615380b23b4b5bcced6541233cd4a93a0cerion   UChar rB_addr  = ifieldRegB(theInstr);
499476de5cf615380b23b4b5bcced6541233cd4a93a0cerion   UInt  opc2     = ifieldOPClo10(theInstr);
4995f0de28cf1a762b0d6f74c93d3532c89a230673bbcerion   UChar b1       = ifieldBIT1(theInstr);
499676de5cf615380b23b4b5bcced6541233cd4a93a0cerion   UChar b0       = ifieldBIT0(theInstr);
499776de5cf615380b23b4b5bcced6541233cd4a93a0cerion
4998d953ebb9b04cbad6891676df597bf0c542b1ec89cerion   Int     simm16 = extend_s_16to32(uimm16);
4999d953ebb9b04cbad6891676df597bf0c542b1ec89cerion   IRType  ty     = mode64 ? Ity_I64 : Ity_I32;
5000d953ebb9b04cbad6891676df597bf0c542b1ec89cerion   IRTemp  EA     = newTemp(ty);
5001d953ebb9b04cbad6891676df597bf0c542b1ec89cerion   IRExpr* val;
5002edf7fc572e2decb93e9143961e8739c8fe18899dcerion
5003f0de28cf1a762b0d6f74c93d3532c89a230673bbcerion   switch (opc1) {
5004f0de28cf1a762b0d6f74c93d3532c89a230673bbcerion   case 0x1F: // register offset
5005d953ebb9b04cbad6891676df597bf0c542b1ec89cerion      assign( EA, ea_rAor0_idxd( rA_addr, rB_addr ) );
5006f0de28cf1a762b0d6f74c93d3532c89a230673bbcerion      break;
500778850ae9874a90ea625fcee1fd4c359375b7b538carll   case 0x38: // immediate offset: 64bit: lq: maskoff
500878850ae9874a90ea625fcee1fd4c359375b7b538carll              // lowest 4 bits of immediate before forming EA
500978850ae9874a90ea625fcee1fd4c359375b7b538carll      simm16 = simm16 & 0xFFFFFFF0;
501078850ae9874a90ea625fcee1fd4c359375b7b538carll      assign( EA, ea_rAor0_simm( rA_addr, simm16  ) );
501178850ae9874a90ea625fcee1fd4c359375b7b538carll      break;
50126d83422ba5b685adc40fdc97651bcca4ecd47d1dsewardj   case 0x3A: // immediate offset: 64bit: ld/ldu/lwa: mask off
50136d83422ba5b685adc40fdc97651bcca4ecd47d1dsewardj              // lowest 2 bits of immediate before forming EA
5014f0de28cf1a762b0d6f74c93d3532c89a230673bbcerion      simm16 = simm16 & 0xFFFFFFFC;
501578850ae9874a90ea625fcee1fd4c359375b7b538carll      assign( EA, ea_rAor0_simm( rA_addr, simm16  ) );
501678850ae9874a90ea625fcee1fd4c359375b7b538carll      break;
5017f0de28cf1a762b0d6f74c93d3532c89a230673bbcerion   default:   // immediate offset
5018f0de28cf1a762b0d6f74c93d3532c89a230673bbcerion      assign( EA, ea_rAor0_simm( rA_addr, simm16  ) );
5019f0de28cf1a762b0d6f74c93d3532c89a230673bbcerion      break;
5020d953ebb9b04cbad6891676df597bf0c542b1ec89cerion   }
5021e9d361ab43518b6dfbd3d846f48859534659dee0cerion
5022b85e8bba97fdae7d892f7bfd12e4601307e4721dcerion   switch (opc1) {
5023e9d361ab43518b6dfbd3d846f48859534659dee0cerion   case 0x22: // lbz (Load B & Zero, PPC32 p433)
5024d953ebb9b04cbad6891676df597bf0c542b1ec89cerion      DIP("lbz r%u,%d(r%u)\n", rD_addr, (Int)simm16, rA_addr);
50251f5fe1fc3a37ca729925e8eec25aa1025b4a6cdbcarll      val = load(Ity_I8, mkexpr(EA));
5026e9d8a26b690c2561ac54ab0cd6ad83ecbadcbe76sewardj      putIReg( rD_addr, mkWidenFrom8(ty, val, False) );
5027b85e8bba97fdae7d892f7bfd12e4601307e4721dcerion      break;
5028b85e8bba97fdae7d892f7bfd12e4601307e4721dcerion
50295b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion   case 0x23: // lbzu (Load B & Zero, Update, PPC32 p434)
503076de5cf615380b23b4b5bcced6541233cd4a93a0cerion      if (rA_addr == 0 || rA_addr == rD_addr) {
50315b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion         vex_printf("dis_int_load(ppc)(lbzu,rA_addr|rD_addr)\n");
5032b85e8bba97fdae7d892f7bfd12e4601307e4721dcerion         return False;
5033b85e8bba97fdae7d892f7bfd12e4601307e4721dcerion      }
5034d953ebb9b04cbad6891676df597bf0c542b1ec89cerion      DIP("lbzu r%u,%d(r%u)\n", rD_addr, (Int)simm16, rA_addr);
50351f5fe1fc3a37ca729925e8eec25aa1025b4a6cdbcarll      val = load(Ity_I8, mkexpr(EA));
5036e9d8a26b690c2561ac54ab0cd6ad83ecbadcbe76sewardj      putIReg( rD_addr, mkWidenFrom8(ty, val, False) );
5037d953ebb9b04cbad6891676df597bf0c542b1ec89cerion      putIReg( rA_addr, mkexpr(EA) );
5038b85e8bba97fdae7d892f7bfd12e4601307e4721dcerion      break;
5039b85e8bba97fdae7d892f7bfd12e4601307e4721dcerion
50405b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion   case 0x2A: // lha (Load HW Alg, PPC32 p445)
5041d953ebb9b04cbad6891676df597bf0c542b1ec89cerion      DIP("lha r%u,%d(r%u)\n", rD_addr, (Int)simm16, rA_addr);
50421f5fe1fc3a37ca729925e8eec25aa1025b4a6cdbcarll      val = load(Ity_I16, mkexpr(EA));
5043e9d8a26b690c2561ac54ab0cd6ad83ecbadcbe76sewardj      putIReg( rD_addr, mkWidenFrom16(ty, val, True) );
5044b85e8bba97fdae7d892f7bfd12e4601307e4721dcerion      break;
5045b85e8bba97fdae7d892f7bfd12e4601307e4721dcerion
50465b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion   case 0x2B: // lhau (Load HW Alg, Update, PPC32 p446)
504776de5cf615380b23b4b5bcced6541233cd4a93a0cerion      if (rA_addr == 0 || rA_addr == rD_addr) {
50485b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion         vex_printf("dis_int_load(ppc)(lhau,rA_addr|rD_addr)\n");
5049cb14e73e1556145a29ae2c8f4f7ab73cf2963864cerion         return False;
5050cb14e73e1556145a29ae2c8f4f7ab73cf2963864cerion      }
5051d953ebb9b04cbad6891676df597bf0c542b1ec89cerion      DIP("lhau r%u,%d(r%u)\n", rD_addr, (Int)simm16, rA_addr);
50521f5fe1fc3a37ca729925e8eec25aa1025b4a6cdbcarll      val = load(Ity_I16, mkexpr(EA));
5053e9d8a26b690c2561ac54ab0cd6ad83ecbadcbe76sewardj      putIReg( rD_addr, mkWidenFrom16(ty, val, True) );
5054d953ebb9b04cbad6891676df597bf0c542b1ec89cerion      putIReg( rA_addr, mkexpr(EA) );
5055cb14e73e1556145a29ae2c8f4f7ab73cf2963864cerion      break;
5056b85e8bba97fdae7d892f7bfd12e4601307e4721dcerion
5057e9d361ab43518b6dfbd3d846f48859534659dee0cerion   case 0x28: // lhz (Load HW & Zero, PPC32 p450)
5058d953ebb9b04cbad6891676df597bf0c542b1ec89cerion      DIP("lhz r%u,%d(r%u)\n", rD_addr, (Int)simm16, rA_addr);
50591f5fe1fc3a37ca729925e8eec25aa1025b4a6cdbcarll      val = load(Ity_I16, mkexpr(EA));
5060e9d8a26b690c2561ac54ab0cd6ad83ecbadcbe76sewardj      putIReg( rD_addr, mkWidenFrom16(ty, val, False) );
5061b85e8bba97fdae7d892f7bfd12e4601307e4721dcerion      break;
5062b85e8bba97fdae7d892f7bfd12e4601307e4721dcerion
50635b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion   case 0x29: // lhzu (Load HW & and Zero, Update, PPC32 p451)
506476de5cf615380b23b4b5bcced6541233cd4a93a0cerion      if (rA_addr == 0 || rA_addr == rD_addr) {
50655b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion         vex_printf("dis_int_load(ppc)(lhzu,rA_addr|rD_addr)\n");
50660e2cc67b30d1bb4d0515a1e09d944143becb3881sewardj         return False;
50670e2cc67b30d1bb4d0515a1e09d944143becb3881sewardj      }
5068d953ebb9b04cbad6891676df597bf0c542b1ec89cerion      DIP("lhzu r%u,%d(r%u)\n", rD_addr, (Int)simm16, rA_addr);
50691f5fe1fc3a37ca729925e8eec25aa1025b4a6cdbcarll      val = load(Ity_I16, mkexpr(EA));
5070e9d8a26b690c2561ac54ab0cd6ad83ecbadcbe76sewardj      putIReg( rD_addr, mkWidenFrom16(ty, val, False) );
5071d953ebb9b04cbad6891676df597bf0c542b1ec89cerion      putIReg( rA_addr, mkexpr(EA) );
50720e2cc67b30d1bb4d0515a1e09d944143becb3881sewardj      break;
5073b85e8bba97fdae7d892f7bfd12e4601307e4721dcerion
5074e9d361ab43518b6dfbd3d846f48859534659dee0cerion   case 0x20: // lwz (Load W & Zero, PPC32 p460)
5075d953ebb9b04cbad6891676df597bf0c542b1ec89cerion      DIP("lwz r%u,%d(r%u)\n", rD_addr, (Int)simm16, rA_addr);
50761f5fe1fc3a37ca729925e8eec25aa1025b4a6cdbcarll      val = load(Ity_I32, mkexpr(EA));
5077e9d8a26b690c2561ac54ab0cd6ad83ecbadcbe76sewardj      putIReg( rD_addr, mkWidenFrom32(ty, val, False) );
5078b85e8bba97fdae7d892f7bfd12e4601307e4721dcerion      break;
5079b85e8bba97fdae7d892f7bfd12e4601307e4721dcerion
50805b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion   case 0x21: // lwzu (Load W & Zero, Update, PPC32 p461))
508176de5cf615380b23b4b5bcced6541233cd4a93a0cerion      if (rA_addr == 0 || rA_addr == rD_addr) {
50825b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion         vex_printf("dis_int_load(ppc)(lwzu,rA_addr|rD_addr)\n");
5083b85e8bba97fdae7d892f7bfd12e4601307e4721dcerion         return False;
5084b85e8bba97fdae7d892f7bfd12e4601307e4721dcerion      }
5085d953ebb9b04cbad6891676df597bf0c542b1ec89cerion      DIP("lwzu r%u,%d(r%u)\n", rD_addr, (Int)simm16, rA_addr);
50861f5fe1fc3a37ca729925e8eec25aa1025b4a6cdbcarll      val = load(Ity_I32, mkexpr(EA));
5087e9d8a26b690c2561ac54ab0cd6ad83ecbadcbe76sewardj      putIReg( rD_addr, mkWidenFrom32(ty, val, False) );
5088d953ebb9b04cbad6891676df597bf0c542b1ec89cerion      putIReg( rA_addr, mkexpr(EA) );
5089b85e8bba97fdae7d892f7bfd12e4601307e4721dcerion      break;
5090b85e8bba97fdae7d892f7bfd12e4601307e4721dcerion
5091b85e8bba97fdae7d892f7bfd12e4601307e4721dcerion   /* X Form */
5092b85e8bba97fdae7d892f7bfd12e4601307e4721dcerion   case 0x1F:
5093b85e8bba97fdae7d892f7bfd12e4601307e4721dcerion      if (b0 != 0) {
50945b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion         vex_printf("dis_int_load(ppc)(Ox1F,b0)\n");
5095b85e8bba97fdae7d892f7bfd12e4601307e4721dcerion         return False;
5096b85e8bba97fdae7d892f7bfd12e4601307e4721dcerion      }
5097b85e8bba97fdae7d892f7bfd12e4601307e4721dcerion
5098b85e8bba97fdae7d892f7bfd12e4601307e4721dcerion      switch (opc2) {
50995b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion      case 0x077: // lbzux (Load B & Zero, Update Indexed, PPC32 p435)
5100d953ebb9b04cbad6891676df597bf0c542b1ec89cerion         DIP("lbzux r%u,r%u,r%u\n", rD_addr, rA_addr, rB_addr);
510176de5cf615380b23b4b5bcced6541233cd4a93a0cerion         if (rA_addr == 0 || rA_addr == rD_addr) {
51025b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion            vex_printf("dis_int_load(ppc)(lwzux,rA_addr|rD_addr)\n");
5103b85e8bba97fdae7d892f7bfd12e4601307e4721dcerion            return False;
5104b85e8bba97fdae7d892f7bfd12e4601307e4721dcerion         }
51051f5fe1fc3a37ca729925e8eec25aa1025b4a6cdbcarll         val = load(Ity_I8, mkexpr(EA));
5106e9d8a26b690c2561ac54ab0cd6ad83ecbadcbe76sewardj         putIReg( rD_addr, mkWidenFrom8(ty, val, False) );
5107d953ebb9b04cbad6891676df597bf0c542b1ec89cerion         putIReg( rA_addr, mkexpr(EA) );
5108b85e8bba97fdae7d892f7bfd12e4601307e4721dcerion         break;
5109b85e8bba97fdae7d892f7bfd12e4601307e4721dcerion
51105b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion      case 0x057: // lbzx (Load B & Zero, Indexed, PPC32 p436)
5111d953ebb9b04cbad6891676df597bf0c542b1ec89cerion         DIP("lbzx r%u,r%u,r%u\n", rD_addr, rA_addr, rB_addr);
51121f5fe1fc3a37ca729925e8eec25aa1025b4a6cdbcarll         val = load(Ity_I8, mkexpr(EA));
5113e9d8a26b690c2561ac54ab0cd6ad83ecbadcbe76sewardj         putIReg( rD_addr, mkWidenFrom8(ty, val, False) );
5114b85e8bba97fdae7d892f7bfd12e4601307e4721dcerion         break;
5115b85e8bba97fdae7d892f7bfd12e4601307e4721dcerion
51165b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion      case 0x177: // lhaux (Load HW Alg, Update Indexed, PPC32 p447)
511776de5cf615380b23b4b5bcced6541233cd4a93a0cerion         if (rA_addr == 0 || rA_addr == rD_addr) {
51185b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion            vex_printf("dis_int_load(ppc)(lhaux,rA_addr|rD_addr)\n");
5119cb14e73e1556145a29ae2c8f4f7ab73cf2963864cerion            return False;
5120cb14e73e1556145a29ae2c8f4f7ab73cf2963864cerion         }
5121d953ebb9b04cbad6891676df597bf0c542b1ec89cerion         DIP("lhaux r%u,r%u,r%u\n", rD_addr, rA_addr, rB_addr);
51221f5fe1fc3a37ca729925e8eec25aa1025b4a6cdbcarll         val = load(Ity_I16, mkexpr(EA));
5123e9d8a26b690c2561ac54ab0cd6ad83ecbadcbe76sewardj         putIReg( rD_addr, mkWidenFrom16(ty, val, True) );
5124d953ebb9b04cbad6891676df597bf0c542b1ec89cerion         putIReg( rA_addr, mkexpr(EA) );
5125cb14e73e1556145a29ae2c8f4f7ab73cf2963864cerion         break;
5126b85e8bba97fdae7d892f7bfd12e4601307e4721dcerion
51275b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion      case 0x157: // lhax (Load HW Alg, Indexed, PPC32 p448)
5128d953ebb9b04cbad6891676df597bf0c542b1ec89cerion         DIP("lhax r%u,r%u,r%u\n", rD_addr, rA_addr, rB_addr);
51291f5fe1fc3a37ca729925e8eec25aa1025b4a6cdbcarll         val = load(Ity_I16, mkexpr(EA));
5130e9d8a26b690c2561ac54ab0cd6ad83ecbadcbe76sewardj         putIReg( rD_addr, mkWidenFrom16(ty, val, True) );
5131b85e8bba97fdae7d892f7bfd12e4601307e4721dcerion         break;
5132b85e8bba97fdae7d892f7bfd12e4601307e4721dcerion
51335b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion      case 0x137: // lhzux (Load HW & Zero, Update Indexed, PPC32 p452)
513476de5cf615380b23b4b5bcced6541233cd4a93a0cerion         if (rA_addr == 0 || rA_addr == rD_addr) {
51355b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion            vex_printf("dis_int_load(ppc)(lhzux,rA_addr|rD_addr)\n");
5136b85e8bba97fdae7d892f7bfd12e4601307e4721dcerion            return False;
5137b85e8bba97fdae7d892f7bfd12e4601307e4721dcerion         }
5138d953ebb9b04cbad6891676df597bf0c542b1ec89cerion         DIP("lhzux r%u,r%u,r%u\n", rD_addr, rA_addr, rB_addr);
51391f5fe1fc3a37ca729925e8eec25aa1025b4a6cdbcarll         val = load(Ity_I16, mkexpr(EA));
5140e9d8a26b690c2561ac54ab0cd6ad83ecbadcbe76sewardj         putIReg( rD_addr, mkWidenFrom16(ty, val, False) );
5141d953ebb9b04cbad6891676df597bf0c542b1ec89cerion         putIReg( rA_addr, mkexpr(EA) );
5142b85e8bba97fdae7d892f7bfd12e4601307e4721dcerion         break;
5143b85e8bba97fdae7d892f7bfd12e4601307e4721dcerion
51445b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion      case 0x117: // lhzx (Load HW & Zero, Indexed, PPC32 p453)
5145d953ebb9b04cbad6891676df597bf0c542b1ec89cerion         DIP("lhzx r%u,r%u,r%u\n", rD_addr, rA_addr, rB_addr);
51461f5fe1fc3a37ca729925e8eec25aa1025b4a6cdbcarll         val = load(Ity_I16, mkexpr(EA));
5147e9d8a26b690c2561ac54ab0cd6ad83ecbadcbe76sewardj         putIReg( rD_addr, mkWidenFrom16(ty, val, False) );
5148b85e8bba97fdae7d892f7bfd12e4601307e4721dcerion         break;
5149b85e8bba97fdae7d892f7bfd12e4601307e4721dcerion
51505b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion      case 0x037: // lwzux (Load W & Zero, Update Indexed, PPC32 p462)
515176de5cf615380b23b4b5bcced6541233cd4a93a0cerion         if (rA_addr == 0 || rA_addr == rD_addr) {
51525b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion            vex_printf("dis_int_load(ppc)(lwzux,rA_addr|rD_addr)\n");
51537787af415a9104b601c2f0ce5b56749e4fd86691sewardj            return False;
51547787af415a9104b601c2f0ce5b56749e4fd86691sewardj         }
5155d953ebb9b04cbad6891676df597bf0c542b1ec89cerion         DIP("lwzux r%u,r%u,r%u\n", rD_addr, rA_addr, rB_addr);
51561f5fe1fc3a37ca729925e8eec25aa1025b4a6cdbcarll         val = load(Ity_I32, mkexpr(EA));
5157e9d8a26b690c2561ac54ab0cd6ad83ecbadcbe76sewardj         putIReg( rD_addr, mkWidenFrom32(ty, val, False) );
5158d953ebb9b04cbad6891676df597bf0c542b1ec89cerion         putIReg( rA_addr, mkexpr(EA) );
51597787af415a9104b601c2f0ce5b56749e4fd86691sewardj         break;
5160b85e8bba97fdae7d892f7bfd12e4601307e4721dcerion
51615b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion      case 0x017: // lwzx (Load W & Zero, Indexed, PPC32 p463)
5162d953ebb9b04cbad6891676df597bf0c542b1ec89cerion         DIP("lwzx r%u,r%u,r%u\n", rD_addr, rA_addr, rB_addr);
51631f5fe1fc3a37ca729925e8eec25aa1025b4a6cdbcarll         val = load(Ity_I32, mkexpr(EA));
5164e9d8a26b690c2561ac54ab0cd6ad83ecbadcbe76sewardj         putIReg( rD_addr, mkWidenFrom32(ty, val, False) );
5165b85e8bba97fdae7d892f7bfd12e4601307e4721dcerion         break;
5166b85e8bba97fdae7d892f7bfd12e4601307e4721dcerion
5167f0de28cf1a762b0d6f74c93d3532c89a230673bbcerion
5168f0de28cf1a762b0d6f74c93d3532c89a230673bbcerion      /* 64bit Loads */
51695b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion      case 0x035: // ldux (Load DWord, Update Indexed, PPC64 p475)
5170f0de28cf1a762b0d6f74c93d3532c89a230673bbcerion         if (rA_addr == 0 || rA_addr == rD_addr) {
51715b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion            vex_printf("dis_int_load(ppc)(ldux,rA_addr|rD_addr)\n");
5172f0de28cf1a762b0d6f74c93d3532c89a230673bbcerion            return False;
5173f0de28cf1a762b0d6f74c93d3532c89a230673bbcerion         }
5174f0de28cf1a762b0d6f74c93d3532c89a230673bbcerion         DIP("ldux r%u,r%u,r%u\n", rD_addr, rA_addr, rB_addr);
51751f5fe1fc3a37ca729925e8eec25aa1025b4a6cdbcarll         putIReg( rD_addr, load(Ity_I64, mkexpr(EA)) );
5176f0de28cf1a762b0d6f74c93d3532c89a230673bbcerion         putIReg( rA_addr, mkexpr(EA) );
5177f0de28cf1a762b0d6f74c93d3532c89a230673bbcerion         break;
5178f0de28cf1a762b0d6f74c93d3532c89a230673bbcerion
51795b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion      case 0x015: // ldx (Load DWord, Indexed, PPC64 p476)
5180f0de28cf1a762b0d6f74c93d3532c89a230673bbcerion         DIP("ldx r%u,r%u,r%u\n", rD_addr, rA_addr, rB_addr);
51811f5fe1fc3a37ca729925e8eec25aa1025b4a6cdbcarll         putIReg( rD_addr, load(Ity_I64, mkexpr(EA)) );
5182f0de28cf1a762b0d6f74c93d3532c89a230673bbcerion         break;
5183f0de28cf1a762b0d6f74c93d3532c89a230673bbcerion
51845b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion      case 0x175: // lwaux (Load W Alg, Update Indexed, PPC64 p501)
5185f0de28cf1a762b0d6f74c93d3532c89a230673bbcerion         if (rA_addr == 0 || rA_addr == rD_addr) {
51865b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion            vex_printf("dis_int_load(ppc)(lwaux,rA_addr|rD_addr)\n");
5187f0de28cf1a762b0d6f74c93d3532c89a230673bbcerion            return False;
5188f0de28cf1a762b0d6f74c93d3532c89a230673bbcerion         }
5189f0de28cf1a762b0d6f74c93d3532c89a230673bbcerion         DIP("lwaux r%u,r%u,r%u\n", rD_addr, rA_addr, rB_addr);
51905b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion         putIReg( rD_addr,
51911f5fe1fc3a37ca729925e8eec25aa1025b4a6cdbcarll                  unop(Iop_32Sto64, load(Ity_I32, mkexpr(EA))) );
5192f0de28cf1a762b0d6f74c93d3532c89a230673bbcerion         putIReg( rA_addr, mkexpr(EA) );
5193f0de28cf1a762b0d6f74c93d3532c89a230673bbcerion         break;
5194f0de28cf1a762b0d6f74c93d3532c89a230673bbcerion
51955b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion      case 0x155: // lwax (Load W Alg, Indexed, PPC64 p502)
5196f0de28cf1a762b0d6f74c93d3532c89a230673bbcerion         DIP("lwax r%u,r%u,r%u\n", rD_addr, rA_addr, rB_addr);
51975b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion         putIReg( rD_addr,
51981f5fe1fc3a37ca729925e8eec25aa1025b4a6cdbcarll                  unop(Iop_32Sto64, load(Ity_I32, mkexpr(EA))) );
5199f0de28cf1a762b0d6f74c93d3532c89a230673bbcerion         break;
5200f0de28cf1a762b0d6f74c93d3532c89a230673bbcerion
5201b85e8bba97fdae7d892f7bfd12e4601307e4721dcerion      default:
52025b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion         vex_printf("dis_int_load(ppc)(opc2)\n");
5203b85e8bba97fdae7d892f7bfd12e4601307e4721dcerion         return False;
5204b85e8bba97fdae7d892f7bfd12e4601307e4721dcerion      }
5205b85e8bba97fdae7d892f7bfd12e4601307e4721dcerion      break;
5206f0de28cf1a762b0d6f74c93d3532c89a230673bbcerion
52076d83422ba5b685adc40fdc97651bcca4ecd47d1dsewardj   /* DS Form - 64bit Loads.  In each case EA will have been formed
52086d83422ba5b685adc40fdc97651bcca4ecd47d1dsewardj      with the lowest 2 bits masked off the immediate offset. */
5209f0de28cf1a762b0d6f74c93d3532c89a230673bbcerion   case 0x3A:
52106d83422ba5b685adc40fdc97651bcca4ecd47d1dsewardj      switch ((b1<<1) | b0) {
52115b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion      case 0x0: // ld (Load DWord, PPC64 p472)
5212f0de28cf1a762b0d6f74c93d3532c89a230673bbcerion         DIP("ld r%u,%d(r%u)\n", rD_addr, simm16, rA_addr);
52131f5fe1fc3a37ca729925e8eec25aa1025b4a6cdbcarll         putIReg( rD_addr, load(Ity_I64, mkexpr(EA)) );
5214f0de28cf1a762b0d6f74c93d3532c89a230673bbcerion         break;
5215f0de28cf1a762b0d6f74c93d3532c89a230673bbcerion
52165b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion      case 0x1: // ldu (Load DWord, Update, PPC64 p474)
5217f0de28cf1a762b0d6f74c93d3532c89a230673bbcerion         if (rA_addr == 0 || rA_addr == rD_addr) {
52185b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion            vex_printf("dis_int_load(ppc)(ldu,rA_addr|rD_addr)\n");
5219f0de28cf1a762b0d6f74c93d3532c89a230673bbcerion            return False;
5220f0de28cf1a762b0d6f74c93d3532c89a230673bbcerion         }
5221f0de28cf1a762b0d6f74c93d3532c89a230673bbcerion         DIP("ldu r%u,%d(r%u)\n", rD_addr, simm16, rA_addr);
52221f5fe1fc3a37ca729925e8eec25aa1025b4a6cdbcarll         putIReg( rD_addr, load(Ity_I64, mkexpr(EA)) );
5223f0de28cf1a762b0d6f74c93d3532c89a230673bbcerion         putIReg( rA_addr, mkexpr(EA) );
5224f0de28cf1a762b0d6f74c93d3532c89a230673bbcerion         break;
5225f0de28cf1a762b0d6f74c93d3532c89a230673bbcerion
52265b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion      case 0x2: // lwa (Load Word Alg, PPC64 p499)
5227f0de28cf1a762b0d6f74c93d3532c89a230673bbcerion         DIP("lwa r%u,%d(r%u)\n", rD_addr, simm16, rA_addr);
52285b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion         putIReg( rD_addr,
52291f5fe1fc3a37ca729925e8eec25aa1025b4a6cdbcarll                  unop(Iop_32Sto64, load(Ity_I32, mkexpr(EA))) );
5230f0de28cf1a762b0d6f74c93d3532c89a230673bbcerion         break;
5231f0de28cf1a762b0d6f74c93d3532c89a230673bbcerion
5232f0de28cf1a762b0d6f74c93d3532c89a230673bbcerion      default:
52335b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion         vex_printf("dis_int_load(ppc)(0x3A, opc2)\n");
5234f0de28cf1a762b0d6f74c93d3532c89a230673bbcerion         return False;
5235f0de28cf1a762b0d6f74c93d3532c89a230673bbcerion      }
5236f0de28cf1a762b0d6f74c93d3532c89a230673bbcerion      break;
5237f0de28cf1a762b0d6f74c93d3532c89a230673bbcerion
523878850ae9874a90ea625fcee1fd4c359375b7b538carll   case 0x38: {
523978850ae9874a90ea625fcee1fd4c359375b7b538carll      IRTemp  high = newTemp(ty);
524078850ae9874a90ea625fcee1fd4c359375b7b538carll      IRTemp  low  = newTemp(ty);
524178850ae9874a90ea625fcee1fd4c359375b7b538carll      /* DQ Form - 128bit Loads. Lowest bits [1:0] are the PT field. */
524278850ae9874a90ea625fcee1fd4c359375b7b538carll      DIP("lq r%u,%d(r%u)\n", rD_addr, simm16, rA_addr);
524378850ae9874a90ea625fcee1fd4c359375b7b538carll      /* NOTE: there are some changes to XER[41:42] that have not been
524478850ae9874a90ea625fcee1fd4c359375b7b538carll       * implemented.
524578850ae9874a90ea625fcee1fd4c359375b7b538carll       */
524678850ae9874a90ea625fcee1fd4c359375b7b538carll      // trap if EA misaligned on 16 byte address
524778850ae9874a90ea625fcee1fd4c359375b7b538carll      if (mode64) {
5248999ef56da3e4426c5f6bf74de40d23ff02dafb34carll         if (host_endness == VexEndnessBE) {
5249999ef56da3e4426c5f6bf74de40d23ff02dafb34carll            assign(high, load(ty, mkexpr( EA ) ) );
5250999ef56da3e4426c5f6bf74de40d23ff02dafb34carll            assign(low, load(ty, binop( Iop_Add64,
5251999ef56da3e4426c5f6bf74de40d23ff02dafb34carll                                        mkexpr( EA ),
5252999ef56da3e4426c5f6bf74de40d23ff02dafb34carll                                        mkU64( 8 ) ) ) );
5253999ef56da3e4426c5f6bf74de40d23ff02dafb34carll	 } else {
5254999ef56da3e4426c5f6bf74de40d23ff02dafb34carll            assign(low, load(ty, mkexpr( EA ) ) );
5255999ef56da3e4426c5f6bf74de40d23ff02dafb34carll            assign(high, load(ty, binop( Iop_Add64,
5256999ef56da3e4426c5f6bf74de40d23ff02dafb34carll                                         mkexpr( EA ),
5257999ef56da3e4426c5f6bf74de40d23ff02dafb34carll                                         mkU64( 8 ) ) ) );
5258999ef56da3e4426c5f6bf74de40d23ff02dafb34carll	 }
525978850ae9874a90ea625fcee1fd4c359375b7b538carll      } else {
52601f5fe1fc3a37ca729925e8eec25aa1025b4a6cdbcarll         assign(high, load(ty, binop( Iop_Add32,
52611f5fe1fc3a37ca729925e8eec25aa1025b4a6cdbcarll                                      mkexpr( EA ),
52621f5fe1fc3a37ca729925e8eec25aa1025b4a6cdbcarll                                      mkU32( 4 ) ) ) );
52631f5fe1fc3a37ca729925e8eec25aa1025b4a6cdbcarll         assign(low, load(ty, binop( Iop_Add32,
52641f5fe1fc3a37ca729925e8eec25aa1025b4a6cdbcarll                                      mkexpr( EA ),
52651f5fe1fc3a37ca729925e8eec25aa1025b4a6cdbcarll                                      mkU32( 12 ) ) ) );
526678850ae9874a90ea625fcee1fd4c359375b7b538carll      }
526778850ae9874a90ea625fcee1fd4c359375b7b538carll      gen_SIGBUS_if_misaligned( EA, 16 );
526878850ae9874a90ea625fcee1fd4c359375b7b538carll      putIReg( rD_addr,  mkexpr( high) );
526978850ae9874a90ea625fcee1fd4c359375b7b538carll      putIReg( rD_addr+1,  mkexpr( low) );
527078850ae9874a90ea625fcee1fd4c359375b7b538carll      break;
527178850ae9874a90ea625fcee1fd4c359375b7b538carll   }
5272b85e8bba97fdae7d892f7bfd12e4601307e4721dcerion   default:
52735b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion      vex_printf("dis_int_load(ppc)(opc1)\n");
5274b85e8bba97fdae7d892f7bfd12e4601307e4721dcerion      return False;
5275b85e8bba97fdae7d892f7bfd12e4601307e4721dcerion   }
5276b85e8bba97fdae7d892f7bfd12e4601307e4721dcerion   return True;
52777aa4bbc850d2978cccd8e12cd7c4cfeaa5ab3e4dcerion}
52787aa4bbc850d2978cccd8e12cd7c4cfeaa5ab3e4dcerion
52797aa4bbc850d2978cccd8e12cd7c4cfeaa5ab3e4dcerion
52807aa4bbc850d2978cccd8e12cd7c4cfeaa5ab3e4dcerion
52813d870a39e4d145e2f3d9f9a0eeed3475ec934ac1cerion/*
52823d870a39e4d145e2f3d9f9a0eeed3475ec934ac1cerion  Integer Store Instructions
52833d870a39e4d145e2f3d9f9a0eeed3475ec934ac1cerion*/
5284cacba8e675988fbf21b08feea1f317a9c896c053florianstatic Bool dis_int_store ( UInt theInstr, const VexAbiInfo* vbi )
5285d23be4e26c2d35c60cdf2fce0dfe0e9b1fa6d008cerion{
5286f0de28cf1a762b0d6f74c93d3532c89a230673bbcerion   /* D-Form, X-Form, DS-Form */
5287edf7fc572e2decb93e9143961e8739c8fe18899dcerion   UChar opc1    = ifieldOPC(theInstr);
528876de5cf615380b23b4b5bcced6541233cd4a93a0cerion   UInt  rS_addr = ifieldRegDS(theInstr);
528976de5cf615380b23b4b5bcced6541233cd4a93a0cerion   UInt  rA_addr = ifieldRegA(theInstr);
5290d953ebb9b04cbad6891676df597bf0c542b1ec89cerion   UInt  uimm16  = ifieldUIMM16(theInstr);
529176de5cf615380b23b4b5bcced6541233cd4a93a0cerion   UInt  rB_addr = ifieldRegB(theInstr);
529276de5cf615380b23b4b5bcced6541233cd4a93a0cerion   UInt  opc2    = ifieldOPClo10(theInstr);
5293f0de28cf1a762b0d6f74c93d3532c89a230673bbcerion   UChar b1      = ifieldBIT1(theInstr);
529476de5cf615380b23b4b5bcced6541233cd4a93a0cerion   UChar b0      = ifieldBIT0(theInstr);
529576de5cf615380b23b4b5bcced6541233cd4a93a0cerion
5296d953ebb9b04cbad6891676df597bf0c542b1ec89cerion   Int    simm16 = extend_s_16to32(uimm16);
5297d953ebb9b04cbad6891676df597bf0c542b1ec89cerion   IRType ty     = mode64 ? Ity_I64 : Ity_I32;
5298d953ebb9b04cbad6891676df597bf0c542b1ec89cerion   IRTemp rS     = newTemp(ty);
5299d953ebb9b04cbad6891676df597bf0c542b1ec89cerion   IRTemp rB     = newTemp(ty);
5300d953ebb9b04cbad6891676df597bf0c542b1ec89cerion   IRTemp EA     = newTemp(ty);
5301b85e8bba97fdae7d892f7bfd12e4601307e4721dcerion
530276de5cf615380b23b4b5bcced6541233cd4a93a0cerion   assign( rB, getIReg(rB_addr) );
530376de5cf615380b23b4b5bcced6541233cd4a93a0cerion   assign( rS, getIReg(rS_addr) );
5304b85e8bba97fdae7d892f7bfd12e4601307e4721dcerion
5305f0de28cf1a762b0d6f74c93d3532c89a230673bbcerion   switch (opc1) {
5306f0de28cf1a762b0d6f74c93d3532c89a230673bbcerion   case 0x1F: // register offset
5307d953ebb9b04cbad6891676df597bf0c542b1ec89cerion      assign( EA, ea_rAor0_idxd( rA_addr, rB_addr ) );
5308f0de28cf1a762b0d6f74c93d3532c89a230673bbcerion      break;
530978850ae9874a90ea625fcee1fd4c359375b7b538carll   case 0x3E: // immediate offset: 64bit: std/stdu/stq: mask off
53106d83422ba5b685adc40fdc97651bcca4ecd47d1dsewardj              // lowest 2 bits of immediate before forming EA
5311f0de28cf1a762b0d6f74c93d3532c89a230673bbcerion      simm16 = simm16 & 0xFFFFFFFC;
5312f0de28cf1a762b0d6f74c93d3532c89a230673bbcerion   default:   // immediate offset
5313f0de28cf1a762b0d6f74c93d3532c89a230673bbcerion      assign( EA, ea_rAor0_simm( rA_addr, simm16  ) );
5314f0de28cf1a762b0d6f74c93d3532c89a230673bbcerion      break;
5315d953ebb9b04cbad6891676df597bf0c542b1ec89cerion   }
5316d953ebb9b04cbad6891676df597bf0c542b1ec89cerion
5317b85e8bba97fdae7d892f7bfd12e4601307e4721dcerion   switch (opc1) {
5318afe85831d73e546e483dfc51964409b7ecd7c5fesewardj   case 0x26: // stb (Store B, PPC32 p509)
531976de5cf615380b23b4b5bcced6541233cd4a93a0cerion      DIP("stb r%u,%d(r%u)\n", rS_addr, simm16, rA_addr);
53201f5fe1fc3a37ca729925e8eec25aa1025b4a6cdbcarll      store( mkexpr(EA), mkNarrowTo8(ty, mkexpr(rS)) );
5321afe85831d73e546e483dfc51964409b7ecd7c5fesewardj      break;
5322b51f0f4f33256638ed953156a2635aa739b232f1sewardj
53235b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion   case 0x27: // stbu (Store B, Update, PPC32 p510)
532476de5cf615380b23b4b5bcced6541233cd4a93a0cerion      if (rA_addr == 0 ) {
53255b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion         vex_printf("dis_int_store(ppc)(stbu,rA_addr)\n");
5326b85e8bba97fdae7d892f7bfd12e4601307e4721dcerion         return False;
5327b85e8bba97fdae7d892f7bfd12e4601307e4721dcerion      }
532876de5cf615380b23b4b5bcced6541233cd4a93a0cerion      DIP("stbu r%u,%d(r%u)\n", rS_addr, simm16, rA_addr);
5329d953ebb9b04cbad6891676df597bf0c542b1ec89cerion      putIReg( rA_addr, mkexpr(EA) );
53301f5fe1fc3a37ca729925e8eec25aa1025b4a6cdbcarll      store( mkexpr(EA), mkNarrowTo8(ty, mkexpr(rS)) );
5331b85e8bba97fdae7d892f7bfd12e4601307e4721dcerion      break;
5332b85e8bba97fdae7d892f7bfd12e4601307e4721dcerion
5333e9d361ab43518b6dfbd3d846f48859534659dee0cerion   case 0x2C: // sth (Store HW, PPC32 p522)
533476de5cf615380b23b4b5bcced6541233cd4a93a0cerion      DIP("sth r%u,%d(r%u)\n", rS_addr, simm16, rA_addr);
53351f5fe1fc3a37ca729925e8eec25aa1025b4a6cdbcarll      store( mkexpr(EA), mkNarrowTo16(ty, mkexpr(rS)) );
5336b85e8bba97fdae7d892f7bfd12e4601307e4721dcerion      break;
5337b85e8bba97fdae7d892f7bfd12e4601307e4721dcerion
53385b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion   case 0x2D: // sthu (Store HW, Update, PPC32 p524)
533976de5cf615380b23b4b5bcced6541233cd4a93a0cerion      if (rA_addr == 0) {
53405b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion         vex_printf("dis_int_store(ppc)(sthu,rA_addr)\n");
5341b85e8bba97fdae7d892f7bfd12e4601307e4721dcerion         return False;
5342b85e8bba97fdae7d892f7bfd12e4601307e4721dcerion      }
534376de5cf615380b23b4b5bcced6541233cd4a93a0cerion      DIP("sthu r%u,%d(r%u)\n", rS_addr, simm16, rA_addr);
5344d953ebb9b04cbad6891676df597bf0c542b1ec89cerion      putIReg( rA_addr, mkexpr(EA) );
53451f5fe1fc3a37ca729925e8eec25aa1025b4a6cdbcarll      store( mkexpr(EA), mkNarrowTo16(ty, mkexpr(rS)) );
5346b85e8bba97fdae7d892f7bfd12e4601307e4721dcerion      break;
5347b85e8bba97fdae7d892f7bfd12e4601307e4721dcerion
5348e9d361ab43518b6dfbd3d846f48859534659dee0cerion   case 0x24: // stw (Store W, PPC32 p530)
534976de5cf615380b23b4b5bcced6541233cd4a93a0cerion      DIP("stw r%u,%d(r%u)\n", rS_addr, simm16, rA_addr);
53501f5fe1fc3a37ca729925e8eec25aa1025b4a6cdbcarll      store( mkexpr(EA), mkNarrowTo32(ty, mkexpr(rS)) );
5351b85e8bba97fdae7d892f7bfd12e4601307e4721dcerion      break;
5352b85e8bba97fdae7d892f7bfd12e4601307e4721dcerion
53535b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion   case 0x25: // stwu (Store W, Update, PPC32 p534)
535476de5cf615380b23b4b5bcced6541233cd4a93a0cerion      if (rA_addr == 0) {
53555b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion         vex_printf("dis_int_store(ppc)(stwu,rA_addr)\n");
5356b85e8bba97fdae7d892f7bfd12e4601307e4721dcerion         return False;
5357b85e8bba97fdae7d892f7bfd12e4601307e4721dcerion      }
535876de5cf615380b23b4b5bcced6541233cd4a93a0cerion      DIP("stwu r%u,%d(r%u)\n", rS_addr, simm16, rA_addr);
5359d953ebb9b04cbad6891676df597bf0c542b1ec89cerion      putIReg( rA_addr, mkexpr(EA) );
53601f5fe1fc3a37ca729925e8eec25aa1025b4a6cdbcarll      store( mkexpr(EA), mkNarrowTo32(ty, mkexpr(rS)) );
5361b85e8bba97fdae7d892f7bfd12e4601307e4721dcerion      break;
5362b85e8bba97fdae7d892f7bfd12e4601307e4721dcerion
5363f0de28cf1a762b0d6f74c93d3532c89a230673bbcerion   /* X Form : all these use EA_indexed */
5364b85e8bba97fdae7d892f7bfd12e4601307e4721dcerion   case 0x1F:
5365b85e8bba97fdae7d892f7bfd12e4601307e4721dcerion      if (b0 != 0) {
53665b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion         vex_printf("dis_int_store(ppc)(0x1F,b0)\n");
5367b85e8bba97fdae7d892f7bfd12e4601307e4721dcerion         return False;
5368b85e8bba97fdae7d892f7bfd12e4601307e4721dcerion      }
5369b85e8bba97fdae7d892f7bfd12e4601307e4721dcerion
5370b85e8bba97fdae7d892f7bfd12e4601307e4721dcerion      switch (opc2) {
53715b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion      case 0x0F7: // stbux (Store B, Update Indexed, PPC32 p511)
537276de5cf615380b23b4b5bcced6541233cd4a93a0cerion         if (rA_addr == 0) {
53735b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion            vex_printf("dis_int_store(ppc)(stbux,rA_addr)\n");
5374b85e8bba97fdae7d892f7bfd12e4601307e4721dcerion            return False;
5375b85e8bba97fdae7d892f7bfd12e4601307e4721dcerion         }
537676de5cf615380b23b4b5bcced6541233cd4a93a0cerion         DIP("stbux r%u,r%u,r%u\n", rS_addr, rA_addr, rB_addr);
5377d953ebb9b04cbad6891676df597bf0c542b1ec89cerion         putIReg( rA_addr, mkexpr(EA) );
53781f5fe1fc3a37ca729925e8eec25aa1025b4a6cdbcarll         store( mkexpr(EA), mkNarrowTo8(ty, mkexpr(rS)) );
5379b85e8bba97fdae7d892f7bfd12e4601307e4721dcerion         break;
5380b85e8bba97fdae7d892f7bfd12e4601307e4721dcerion
5381e9d361ab43518b6dfbd3d846f48859534659dee0cerion      case 0x0D7: // stbx (Store B Indexed, PPC32 p512)
538276de5cf615380b23b4b5bcced6541233cd4a93a0cerion         DIP("stbx r%u,r%u,r%u\n", rS_addr, rA_addr, rB_addr);
53831f5fe1fc3a37ca729925e8eec25aa1025b4a6cdbcarll         store( mkexpr(EA), mkNarrowTo8(ty, mkexpr(rS)) );
5384b85e8bba97fdae7d892f7bfd12e4601307e4721dcerion         break;
5385b85e8bba97fdae7d892f7bfd12e4601307e4721dcerion
53865b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion      case 0x1B7: // sthux (Store HW, Update Indexed, PPC32 p525)
538776de5cf615380b23b4b5bcced6541233cd4a93a0cerion         if (rA_addr == 0) {
53885b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion            vex_printf("dis_int_store(ppc)(sthux,rA_addr)\n");
5389cb14e73e1556145a29ae2c8f4f7ab73cf2963864cerion            return False;
5390cb14e73e1556145a29ae2c8f4f7ab73cf2963864cerion         }
539176de5cf615380b23b4b5bcced6541233cd4a93a0cerion         DIP("sthux r%u,r%u,r%u\n", rS_addr, rA_addr, rB_addr);
5392d953ebb9b04cbad6891676df597bf0c542b1ec89cerion         putIReg( rA_addr, mkexpr(EA) );
53931f5fe1fc3a37ca729925e8eec25aa1025b4a6cdbcarll         store( mkexpr(EA), mkNarrowTo16(ty, mkexpr(rS)) );
5394cb14e73e1556145a29ae2c8f4f7ab73cf2963864cerion         break;
5395b85e8bba97fdae7d892f7bfd12e4601307e4721dcerion
5396e9d361ab43518b6dfbd3d846f48859534659dee0cerion      case 0x197: // sthx (Store HW Indexed, PPC32 p526)
539776de5cf615380b23b4b5bcced6541233cd4a93a0cerion         DIP("sthx r%u,r%u,r%u\n", rS_addr, rA_addr, rB_addr);
53981f5fe1fc3a37ca729925e8eec25aa1025b4a6cdbcarll         store( mkexpr(EA), mkNarrowTo16(ty, mkexpr(rS)) );
5399b85e8bba97fdae7d892f7bfd12e4601307e4721dcerion         break;
5400b85e8bba97fdae7d892f7bfd12e4601307e4721dcerion
54015b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion      case 0x0B7: // stwux (Store W, Update Indexed, PPC32 p535)
540276de5cf615380b23b4b5bcced6541233cd4a93a0cerion         if (rA_addr == 0) {
54035b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion            vex_printf("dis_int_store(ppc)(stwux,rA_addr)\n");
5404b85e8bba97fdae7d892f7bfd12e4601307e4721dcerion            return False;
5405b85e8bba97fdae7d892f7bfd12e4601307e4721dcerion         }
540676de5cf615380b23b4b5bcced6541233cd4a93a0cerion         DIP("stwux r%u,r%u,r%u\n", rS_addr, rA_addr, rB_addr);
5407d953ebb9b04cbad6891676df597bf0c542b1ec89cerion         putIReg( rA_addr, mkexpr(EA) );
54081f5fe1fc3a37ca729925e8eec25aa1025b4a6cdbcarll         store( mkexpr(EA), mkNarrowTo32(ty, mkexpr(rS)) );
5409b85e8bba97fdae7d892f7bfd12e4601307e4721dcerion         break;
5410b85e8bba97fdae7d892f7bfd12e4601307e4721dcerion
5411e9d361ab43518b6dfbd3d846f48859534659dee0cerion      case 0x097: // stwx (Store W Indexed, PPC32 p536)
541276de5cf615380b23b4b5bcced6541233cd4a93a0cerion         DIP("stwx r%u,r%u,r%u\n", rS_addr, rA_addr, rB_addr);
54131f5fe1fc3a37ca729925e8eec25aa1025b4a6cdbcarll         store( mkexpr(EA), mkNarrowTo32(ty, mkexpr(rS)) );
5414b85e8bba97fdae7d892f7bfd12e4601307e4721dcerion         break;
5415b85e8bba97fdae7d892f7bfd12e4601307e4721dcerion
5416f0de28cf1a762b0d6f74c93d3532c89a230673bbcerion
5417f0de28cf1a762b0d6f74c93d3532c89a230673bbcerion      /* 64bit Stores */
54185b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion      case 0x0B5: // stdux (Store DWord, Update Indexed, PPC64 p584)
5419f0de28cf1a762b0d6f74c93d3532c89a230673bbcerion         if (rA_addr == 0) {
54205b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion            vex_printf("dis_int_store(ppc)(stdux,rA_addr)\n");
5421f0de28cf1a762b0d6f74c93d3532c89a230673bbcerion            return False;
5422f0de28cf1a762b0d6f74c93d3532c89a230673bbcerion         }
5423f0de28cf1a762b0d6f74c93d3532c89a230673bbcerion         DIP("stdux r%u,r%u,r%u\n", rS_addr, rA_addr, rB_addr);
5424f0de28cf1a762b0d6f74c93d3532c89a230673bbcerion         putIReg( rA_addr, mkexpr(EA) );
54251f5fe1fc3a37ca729925e8eec25aa1025b4a6cdbcarll         store( mkexpr(EA), mkexpr(rS) );
5426f0de28cf1a762b0d6f74c93d3532c89a230673bbcerion         break;
5427f0de28cf1a762b0d6f74c93d3532c89a230673bbcerion
54285b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion      case 0x095: // stdx (Store DWord Indexed, PPC64 p585)
5429f0de28cf1a762b0d6f74c93d3532c89a230673bbcerion         DIP("stdx r%u,r%u,r%u\n", rS_addr, rA_addr, rB_addr);
54301f5fe1fc3a37ca729925e8eec25aa1025b4a6cdbcarll         store( mkexpr(EA), mkexpr(rS) );
5431f0de28cf1a762b0d6f74c93d3532c89a230673bbcerion         break;
5432f0de28cf1a762b0d6f74c93d3532c89a230673bbcerion
5433b85e8bba97fdae7d892f7bfd12e4601307e4721dcerion      default:
54345b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion         vex_printf("dis_int_store(ppc)(opc2)\n");
5435b85e8bba97fdae7d892f7bfd12e4601307e4721dcerion         return False;
5436b85e8bba97fdae7d892f7bfd12e4601307e4721dcerion      }
5437b85e8bba97fdae7d892f7bfd12e4601307e4721dcerion      break;
5438f0de28cf1a762b0d6f74c93d3532c89a230673bbcerion
54396d83422ba5b685adc40fdc97651bcca4ecd47d1dsewardj   /* DS Form - 64bit Stores.  In each case EA will have been formed
54406d83422ba5b685adc40fdc97651bcca4ecd47d1dsewardj      with the lowest 2 bits masked off the immediate offset. */
5441f0de28cf1a762b0d6f74c93d3532c89a230673bbcerion   case 0x3E:
54426d83422ba5b685adc40fdc97651bcca4ecd47d1dsewardj      switch ((b1<<1) | b0) {
54435b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion      case 0x0: // std (Store DWord, PPC64 p580)
54440c74bb5aa3240f693df0568d578baabf0c376dc4carll         if (!mode64)
54450c74bb5aa3240f693df0568d578baabf0c376dc4carll            return False;
54460c74bb5aa3240f693df0568d578baabf0c376dc4carll
5447f0de28cf1a762b0d6f74c93d3532c89a230673bbcerion         DIP("std r%u,%d(r%u)\n", rS_addr, simm16, rA_addr);
54481f5fe1fc3a37ca729925e8eec25aa1025b4a6cdbcarll         store( mkexpr(EA), mkexpr(rS) );
5449f0de28cf1a762b0d6f74c93d3532c89a230673bbcerion         break;
5450f0de28cf1a762b0d6f74c93d3532c89a230673bbcerion
54515b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion      case 0x1: // stdu (Store DWord, Update, PPC64 p583)
54520c74bb5aa3240f693df0568d578baabf0c376dc4carll         if (!mode64)
54530c74bb5aa3240f693df0568d578baabf0c376dc4carll            return False;
54540c74bb5aa3240f693df0568d578baabf0c376dc4carll
5455f0de28cf1a762b0d6f74c93d3532c89a230673bbcerion         DIP("stdu r%u,%d(r%u)\n", rS_addr, simm16, rA_addr);
5456f0de28cf1a762b0d6f74c93d3532c89a230673bbcerion         putIReg( rA_addr, mkexpr(EA) );
54571f5fe1fc3a37ca729925e8eec25aa1025b4a6cdbcarll         store( mkexpr(EA), mkexpr(rS) );
5458f0de28cf1a762b0d6f74c93d3532c89a230673bbcerion         break;
5459f0de28cf1a762b0d6f74c93d3532c89a230673bbcerion
546078850ae9874a90ea625fcee1fd4c359375b7b538carll      case 0x2: { // stq (Store QuadWord, Update, PPC64 p583)
546178850ae9874a90ea625fcee1fd4c359375b7b538carll         IRTemp EA_hi = newTemp(ty);
546278850ae9874a90ea625fcee1fd4c359375b7b538carll         IRTemp EA_lo = newTemp(ty);
546378850ae9874a90ea625fcee1fd4c359375b7b538carll         DIP("stq r%u,%d(r%u)\n", rS_addr, simm16, rA_addr);
546478850ae9874a90ea625fcee1fd4c359375b7b538carll
546578850ae9874a90ea625fcee1fd4c359375b7b538carll         if (mode64) {
5466999ef56da3e4426c5f6bf74de40d23ff02dafb34carll            if (host_endness == VexEndnessBE) {
5467999ef56da3e4426c5f6bf74de40d23ff02dafb34carll
5468999ef56da3e4426c5f6bf74de40d23ff02dafb34carll               /* upper 64-bits */
5469999ef56da3e4426c5f6bf74de40d23ff02dafb34carll               assign( EA_hi, ea_rAor0_simm( rA_addr, simm16 ) );
547078850ae9874a90ea625fcee1fd4c359375b7b538carll
5471999ef56da3e4426c5f6bf74de40d23ff02dafb34carll               /* lower 64-bits */
5472999ef56da3e4426c5f6bf74de40d23ff02dafb34carll               assign( EA_lo, ea_rAor0_simm( rA_addr, simm16+8 ) );
5473999ef56da3e4426c5f6bf74de40d23ff02dafb34carll	    } else {
5474999ef56da3e4426c5f6bf74de40d23ff02dafb34carll               /* upper 64-bits */
5475999ef56da3e4426c5f6bf74de40d23ff02dafb34carll               assign( EA_hi, ea_rAor0_simm( rA_addr, simm16+8 ) );
5476999ef56da3e4426c5f6bf74de40d23ff02dafb34carll
5477999ef56da3e4426c5f6bf74de40d23ff02dafb34carll               /* lower 64-bits */
5478999ef56da3e4426c5f6bf74de40d23ff02dafb34carll               assign( EA_lo, ea_rAor0_simm( rA_addr, simm16 ) );
5479999ef56da3e4426c5f6bf74de40d23ff02dafb34carll	    }
548078850ae9874a90ea625fcee1fd4c359375b7b538carll         } else {
548178850ae9874a90ea625fcee1fd4c359375b7b538carll            /* upper half of upper 64-bits */
548278850ae9874a90ea625fcee1fd4c359375b7b538carll            assign( EA_hi, ea_rAor0_simm( rA_addr, simm16+4 ) );
548378850ae9874a90ea625fcee1fd4c359375b7b538carll
548478850ae9874a90ea625fcee1fd4c359375b7b538carll            /* lower half of upper 64-bits */
548578850ae9874a90ea625fcee1fd4c359375b7b538carll            assign( EA_lo, ea_rAor0_simm( rA_addr, simm16+12 ) );
548678850ae9874a90ea625fcee1fd4c359375b7b538carll         }
54871f5fe1fc3a37ca729925e8eec25aa1025b4a6cdbcarll         store( mkexpr(EA_hi), mkexpr(rS) );
54881f5fe1fc3a37ca729925e8eec25aa1025b4a6cdbcarll         store( mkexpr(EA_lo), getIReg( rS_addr+1 ) );
548978850ae9874a90ea625fcee1fd4c359375b7b538carll         break;
549078850ae9874a90ea625fcee1fd4c359375b7b538carll      }
5491f0de28cf1a762b0d6f74c93d3532c89a230673bbcerion      default:
54925b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion         vex_printf("dis_int_load(ppc)(0x3A, opc2)\n");
5493f0de28cf1a762b0d6f74c93d3532c89a230673bbcerion         return False;
5494f0de28cf1a762b0d6f74c93d3532c89a230673bbcerion      }
5495f0de28cf1a762b0d6f74c93d3532c89a230673bbcerion      break;
5496f0de28cf1a762b0d6f74c93d3532c89a230673bbcerion
5497b85e8bba97fdae7d892f7bfd12e4601307e4721dcerion   default:
54985b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion      vex_printf("dis_int_store(ppc)(opc1)\n");
5499b85e8bba97fdae7d892f7bfd12e4601307e4721dcerion      return False;
5500b85e8bba97fdae7d892f7bfd12e4601307e4721dcerion   }
5501b85e8bba97fdae7d892f7bfd12e4601307e4721dcerion   return True;
5502d23be4e26c2d35c60cdf2fce0dfe0e9b1fa6d008cerion}
5503d23be4e26c2d35c60cdf2fce0dfe0e9b1fa6d008cerion
5504d23be4e26c2d35c60cdf2fce0dfe0e9b1fa6d008cerion
5505d23be4e26c2d35c60cdf2fce0dfe0e9b1fa6d008cerion
55067787af415a9104b601c2f0ce5b56749e4fd86691sewardj/*
55077787af415a9104b601c2f0ce5b56749e4fd86691sewardj  Integer Load/Store Multiple Instructions
55087787af415a9104b601c2f0ce5b56749e4fd86691sewardj*/
55097787af415a9104b601c2f0ce5b56749e4fd86691sewardjstatic Bool dis_int_ldst_mult ( UInt theInstr )
55107787af415a9104b601c2f0ce5b56749e4fd86691sewardj{
55117787af415a9104b601c2f0ce5b56749e4fd86691sewardj   /* D-Form */
551276de5cf615380b23b4b5bcced6541233cd4a93a0cerion   UChar opc1     = ifieldOPC(theInstr);
551376de5cf615380b23b4b5bcced6541233cd4a93a0cerion   UChar rD_addr  = ifieldRegDS(theInstr);
551476de5cf615380b23b4b5bcced6541233cd4a93a0cerion   UChar rS_addr  = rD_addr;
551576de5cf615380b23b4b5bcced6541233cd4a93a0cerion   UChar rA_addr  = ifieldRegA(theInstr);
55162831b00c4950d6c2b061def05fd67528fe132ececerion   UInt  uimm16   = ifieldUIMM16(theInstr);
5517edf7fc572e2decb93e9143961e8739c8fe18899dcerion
5518d953ebb9b04cbad6891676df597bf0c542b1ec89cerion   Int     simm16 = extend_s_16to32(uimm16);
5519d953ebb9b04cbad6891676df597bf0c542b1ec89cerion   IRType  ty     = mode64 ? Ity_I64 : Ity_I32;
55209fcbb9a82f6f263626aa5a432ab7e94f37476181carll   IROp    mkAdd  = mode64 ? Iop_Add64 : Iop_Add32;
5521d953ebb9b04cbad6891676df597bf0c542b1ec89cerion   IRTemp  EA     = newTemp(ty);
5522d953ebb9b04cbad6891676df597bf0c542b1ec89cerion   UInt    r      = 0;
5523d953ebb9b04cbad6891676df597bf0c542b1ec89cerion   UInt    ea_off = 0;
55247787af415a9104b601c2f0ce5b56749e4fd86691sewardj   IRExpr* irx_addr;
5525edf7fc572e2decb93e9143961e8739c8fe18899dcerion
5526d953ebb9b04cbad6891676df597bf0c542b1ec89cerion   assign( EA, ea_rAor0_simm( rA_addr, simm16 ) );
5527d953ebb9b04cbad6891676df597bf0c542b1ec89cerion
55287787af415a9104b601c2f0ce5b56749e4fd86691sewardj   switch (opc1) {
5529d953ebb9b04cbad6891676df597bf0c542b1ec89cerion   case 0x2E: // lmw (Load Multiple Word, PPC32 p454)
5530d953ebb9b04cbad6891676df597bf0c542b1ec89cerion      if (rA_addr >= rD_addr) {
55315b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion         vex_printf("dis_int_ldst_mult(ppc)(lmw,rA_addr)\n");
5532d953ebb9b04cbad6891676df597bf0c542b1ec89cerion         return False;
5533d953ebb9b04cbad6891676df597bf0c542b1ec89cerion      }
5534d953ebb9b04cbad6891676df597bf0c542b1ec89cerion      DIP("lmw r%u,%d(r%u)\n", rD_addr, simm16, rA_addr);
5535d953ebb9b04cbad6891676df597bf0c542b1ec89cerion      for (r = rD_addr; r <= 31; r++) {
55369fcbb9a82f6f263626aa5a432ab7e94f37476181carll         irx_addr = binop(mkAdd, mkexpr(EA), mode64 ? mkU64(ea_off) : mkU32(ea_off));
55371f5fe1fc3a37ca729925e8eec25aa1025b4a6cdbcarll         putIReg( r, mkWidenFrom32(ty, load(Ity_I32, irx_addr ),
5538e9d8a26b690c2561ac54ab0cd6ad83ecbadcbe76sewardj                                       False) );
5539d953ebb9b04cbad6891676df597bf0c542b1ec89cerion         ea_off += 4;
5540d953ebb9b04cbad6891676df597bf0c542b1ec89cerion      }
5541d953ebb9b04cbad6891676df597bf0c542b1ec89cerion      break;
55427787af415a9104b601c2f0ce5b56749e4fd86691sewardj
5543d953ebb9b04cbad6891676df597bf0c542b1ec89cerion   case 0x2F: // stmw (Store Multiple Word, PPC32 p527)
5544d953ebb9b04cbad6891676df597bf0c542b1ec89cerion      DIP("stmw r%u,%d(r%u)\n", rS_addr, simm16, rA_addr);
5545d953ebb9b04cbad6891676df597bf0c542b1ec89cerion      for (r = rS_addr; r <= 31; r++) {
55469fcbb9a82f6f263626aa5a432ab7e94f37476181carll         irx_addr = binop(mkAdd, mkexpr(EA), mode64 ? mkU64(ea_off) : mkU32(ea_off));
55471f5fe1fc3a37ca729925e8eec25aa1025b4a6cdbcarll         store( irx_addr, mkNarrowTo32(ty, getIReg(r)) );
5548d953ebb9b04cbad6891676df597bf0c542b1ec89cerion         ea_off += 4;
5549d953ebb9b04cbad6891676df597bf0c542b1ec89cerion      }
5550d953ebb9b04cbad6891676df597bf0c542b1ec89cerion      break;
55517787af415a9104b601c2f0ce5b56749e4fd86691sewardj
5552d953ebb9b04cbad6891676df597bf0c542b1ec89cerion   default:
55535b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion      vex_printf("dis_int_ldst_mult(ppc)(opc1)\n");
5554d953ebb9b04cbad6891676df597bf0c542b1ec89cerion      return False;
55557787af415a9104b601c2f0ce5b56749e4fd86691sewardj   }
55567787af415a9104b601c2f0ce5b56749e4fd86691sewardj   return True;
55577787af415a9104b601c2f0ce5b56749e4fd86691sewardj}
55587787af415a9104b601c2f0ce5b56749e4fd86691sewardj
55597787af415a9104b601c2f0ce5b56749e4fd86691sewardj
55607787af415a9104b601c2f0ce5b56749e4fd86691sewardj
556187e651f40360a8f1c9418710e79c482028759f8csewardj/*
556287e651f40360a8f1c9418710e79c482028759f8csewardj  Integer Load/Store String Instructions
556387e651f40360a8f1c9418710e79c482028759f8csewardj*/
556487e651f40360a8f1c9418710e79c482028759f8csewardjstatic
556587e651f40360a8f1c9418710e79c482028759f8csewardjvoid generate_lsw_sequence ( IRTemp tNBytes,   // # bytes, :: Ity_I32
556687e651f40360a8f1c9418710e79c482028759f8csewardj                             IRTemp EA,        // EA
556787e651f40360a8f1c9418710e79c482028759f8csewardj                             Int    rD,        // first dst register
5568d953ebb9b04cbad6891676df597bf0c542b1ec89cerion                             Int    maxBytes ) // 32 or 128
556987e651f40360a8f1c9418710e79c482028759f8csewardj{
557087e651f40360a8f1c9418710e79c482028759f8csewardj   Int     i, shift = 24;
557187e651f40360a8f1c9418710e79c482028759f8csewardj   IRExpr* e_nbytes = mkexpr(tNBytes);
5572d953ebb9b04cbad6891676df597bf0c542b1ec89cerion   IRExpr* e_EA     = mkexpr(EA);
5573d953ebb9b04cbad6891676df597bf0c542b1ec89cerion   IRType  ty       = mode64 ? Ity_I64 : Ity_I32;
557487e651f40360a8f1c9418710e79c482028759f8csewardj
55755876fa100009ff1179c6e4aae0838176b9685794sewardj   vassert(rD >= 0 && rD < 32);
557687e651f40360a8f1c9418710e79c482028759f8csewardj   rD--; if (rD < 0) rD = 31;
557787e651f40360a8f1c9418710e79c482028759f8csewardj
557887e651f40360a8f1c9418710e79c482028759f8csewardj   for (i = 0; i < maxBytes; i++) {
557987e651f40360a8f1c9418710e79c482028759f8csewardj      /* if (nBytes < (i+1)) goto NIA; */
558087e651f40360a8f1c9418710e79c482028759f8csewardj      stmt( IRStmt_Exit( binop(Iop_CmpLT32U, e_nbytes, mkU32(i+1)),
558187e651f40360a8f1c9418710e79c482028759f8csewardj                         Ijk_Boring,
55823dee849ec7c38746749065e67dc53b75daa7617dsewardj                         mkSzConst( ty, nextInsnAddr()), OFFB_CIA ));
558387e651f40360a8f1c9418710e79c482028759f8csewardj      /* when crossing into a new dest register, set it to zero. */
558487e651f40360a8f1c9418710e79c482028759f8csewardj      if ((i % 4) == 0) {
558587e651f40360a8f1c9418710e79c482028759f8csewardj         rD++; if (rD == 32) rD = 0;
55862831b00c4950d6c2b061def05fd67528fe132ececerion         putIReg(rD, mkSzImm(ty, 0));
558787e651f40360a8f1c9418710e79c482028759f8csewardj         shift = 24;
558887e651f40360a8f1c9418710e79c482028759f8csewardj      }
558987e651f40360a8f1c9418710e79c482028759f8csewardj      /* rD |=  (8Uto32(*(EA+i))) << shift */
559087e651f40360a8f1c9418710e79c482028759f8csewardj      vassert(shift == 0 || shift == 8 || shift == 16 || shift == 24);
55912ef8a37484a9d027b19aa024b8e364645f04c2b8sewardj      putIReg(
55922ef8a37484a9d027b19aa024b8e364645f04c2b8sewardj         rD,
5593e9d8a26b690c2561ac54ab0cd6ad83ecbadcbe76sewardj         mkWidenFrom32(
55942ef8a37484a9d027b19aa024b8e364645f04c2b8sewardj            ty,
55952ef8a37484a9d027b19aa024b8e364645f04c2b8sewardj            binop(
55962ef8a37484a9d027b19aa024b8e364645f04c2b8sewardj               Iop_Or32,
5597e9d8a26b690c2561ac54ab0cd6ad83ecbadcbe76sewardj               mkNarrowTo32(ty, getIReg(rD)),
55982ef8a37484a9d027b19aa024b8e364645f04c2b8sewardj               binop(
55992ef8a37484a9d027b19aa024b8e364645f04c2b8sewardj                  Iop_Shl32,
56002ef8a37484a9d027b19aa024b8e364645f04c2b8sewardj                  unop(
56012ef8a37484a9d027b19aa024b8e364645f04c2b8sewardj                     Iop_8Uto32,
56021f5fe1fc3a37ca729925e8eec25aa1025b4a6cdbcarll                     load( Ity_I8,
56031f5fe1fc3a37ca729925e8eec25aa1025b4a6cdbcarll                           binop( mkSzOp(ty,Iop_Add8),
56041f5fe1fc3a37ca729925e8eec25aa1025b4a6cdbcarll                                  e_EA, mkSzImm(ty,i)))
56052ef8a37484a9d027b19aa024b8e364645f04c2b8sewardj                  ),
56062ef8a37484a9d027b19aa024b8e364645f04c2b8sewardj                  mkU8(toUChar(shift))
56072ef8a37484a9d027b19aa024b8e364645f04c2b8sewardj               )
56082ef8a37484a9d027b19aa024b8e364645f04c2b8sewardj            ),
56092ef8a37484a9d027b19aa024b8e364645f04c2b8sewardj            /*Signed*/False
56102ef8a37484a9d027b19aa024b8e364645f04c2b8sewardj	 )
56112ef8a37484a9d027b19aa024b8e364645f04c2b8sewardj      );
561287e651f40360a8f1c9418710e79c482028759f8csewardj      shift -= 8;
561387e651f40360a8f1c9418710e79c482028759f8csewardj   }
561487e651f40360a8f1c9418710e79c482028759f8csewardj}
561587e651f40360a8f1c9418710e79c482028759f8csewardj
56165876fa100009ff1179c6e4aae0838176b9685794sewardjstatic
56175876fa100009ff1179c6e4aae0838176b9685794sewardjvoid generate_stsw_sequence ( IRTemp tNBytes,   // # bytes, :: Ity_I32
56185876fa100009ff1179c6e4aae0838176b9685794sewardj                              IRTemp EA,        // EA
56195876fa100009ff1179c6e4aae0838176b9685794sewardj                              Int    rS,        // first src register
5620d953ebb9b04cbad6891676df597bf0c542b1ec89cerion                              Int    maxBytes ) // 32 or 128
56215876fa100009ff1179c6e4aae0838176b9685794sewardj{
56225876fa100009ff1179c6e4aae0838176b9685794sewardj   Int     i, shift = 24;
56235876fa100009ff1179c6e4aae0838176b9685794sewardj   IRExpr* e_nbytes = mkexpr(tNBytes);
5624d953ebb9b04cbad6891676df597bf0c542b1ec89cerion   IRExpr* e_EA     = mkexpr(EA);
5625d953ebb9b04cbad6891676df597bf0c542b1ec89cerion   IRType  ty       = mode64 ? Ity_I64 : Ity_I32;
56265876fa100009ff1179c6e4aae0838176b9685794sewardj
56275876fa100009ff1179c6e4aae0838176b9685794sewardj   vassert(rS >= 0 && rS < 32);
56285876fa100009ff1179c6e4aae0838176b9685794sewardj   rS--; if (rS < 0) rS = 31;
56295876fa100009ff1179c6e4aae0838176b9685794sewardj
56305876fa100009ff1179c6e4aae0838176b9685794sewardj   for (i = 0; i < maxBytes; i++) {
56315876fa100009ff1179c6e4aae0838176b9685794sewardj      /* if (nBytes < (i+1)) goto NIA; */
56325876fa100009ff1179c6e4aae0838176b9685794sewardj      stmt( IRStmt_Exit( binop(Iop_CmpLT32U, e_nbytes, mkU32(i+1)),
56335876fa100009ff1179c6e4aae0838176b9685794sewardj                         Ijk_Boring,
56343dee849ec7c38746749065e67dc53b75daa7617dsewardj                         mkSzConst( ty, nextInsnAddr() ), OFFB_CIA ));
56355876fa100009ff1179c6e4aae0838176b9685794sewardj      /* check for crossing into a new src register. */
56365876fa100009ff1179c6e4aae0838176b9685794sewardj      if ((i % 4) == 0) {
56375876fa100009ff1179c6e4aae0838176b9685794sewardj         rS++; if (rS == 32) rS = 0;
56385876fa100009ff1179c6e4aae0838176b9685794sewardj         shift = 24;
56395876fa100009ff1179c6e4aae0838176b9685794sewardj      }
56405876fa100009ff1179c6e4aae0838176b9685794sewardj      /* *(EA+i) = 32to8(rS >> shift) */
56415876fa100009ff1179c6e4aae0838176b9685794sewardj      vassert(shift == 0 || shift == 8 || shift == 16 || shift == 24);
56421f5fe1fc3a37ca729925e8eec25aa1025b4a6cdbcarll      store(
56431f5fe1fc3a37ca729925e8eec25aa1025b4a6cdbcarll            binop( mkSzOp(ty,Iop_Add8), e_EA, mkSzImm(ty,i)),
56441f5fe1fc3a37ca729925e8eec25aa1025b4a6cdbcarll            unop( Iop_32to8,
56451f5fe1fc3a37ca729925e8eec25aa1025b4a6cdbcarll                  binop( Iop_Shr32,
56461f5fe1fc3a37ca729925e8eec25aa1025b4a6cdbcarll                         mkNarrowTo32( ty, getIReg(rS) ),
56471f5fe1fc3a37ca729925e8eec25aa1025b4a6cdbcarll                         mkU8( toUChar(shift) )))
56485876fa100009ff1179c6e4aae0838176b9685794sewardj      );
56495876fa100009ff1179c6e4aae0838176b9685794sewardj      shift -= 8;
56505876fa100009ff1179c6e4aae0838176b9685794sewardj   }
56515876fa100009ff1179c6e4aae0838176b9685794sewardj}
56525876fa100009ff1179c6e4aae0838176b9685794sewardj
565387e651f40360a8f1c9418710e79c482028759f8csewardjstatic Bool dis_int_ldst_str ( UInt theInstr, /*OUT*/Bool* stopHere )
565487e651f40360a8f1c9418710e79c482028759f8csewardj{
565587e651f40360a8f1c9418710e79c482028759f8csewardj   /* X-Form */
565676de5cf615380b23b4b5bcced6541233cd4a93a0cerion   UChar opc1     = ifieldOPC(theInstr);
565776de5cf615380b23b4b5bcced6541233cd4a93a0cerion   UChar rD_addr  = ifieldRegDS(theInstr);
565876de5cf615380b23b4b5bcced6541233cd4a93a0cerion   UChar rS_addr  = rD_addr;
565976de5cf615380b23b4b5bcced6541233cd4a93a0cerion   UChar rA_addr  = ifieldRegA(theInstr);
566076de5cf615380b23b4b5bcced6541233cd4a93a0cerion   UChar rB_addr  = ifieldRegB(theInstr);
566176de5cf615380b23b4b5bcced6541233cd4a93a0cerion   UChar NumBytes = rB_addr;
566276de5cf615380b23b4b5bcced6541233cd4a93a0cerion   UInt  opc2     = ifieldOPClo10(theInstr);
566376de5cf615380b23b4b5bcced6541233cd4a93a0cerion   UChar b0       = ifieldBIT0(theInstr);
5664edf7fc572e2decb93e9143961e8739c8fe18899dcerion
5665d953ebb9b04cbad6891676df597bf0c542b1ec89cerion   IRType ty      = mode64 ? Ity_I64 : Ity_I32;
5666d953ebb9b04cbad6891676df597bf0c542b1ec89cerion   IRTemp t_EA    = newTemp(ty);
566787e651f40360a8f1c9418710e79c482028759f8csewardj   IRTemp t_nbytes = IRTemp_INVALID;
5668edf7fc572e2decb93e9143961e8739c8fe18899dcerion
566987e651f40360a8f1c9418710e79c482028759f8csewardj   *stopHere = False;
5670edf7fc572e2decb93e9143961e8739c8fe18899dcerion
567187e651f40360a8f1c9418710e79c482028759f8csewardj   if (opc1 != 0x1F || b0 != 0) {
56725b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion      vex_printf("dis_int_ldst_str(ppc)(opc1)\n");
567387e651f40360a8f1c9418710e79c482028759f8csewardj      return False;
567487e651f40360a8f1c9418710e79c482028759f8csewardj   }
567587e651f40360a8f1c9418710e79c482028759f8csewardj
567687e651f40360a8f1c9418710e79c482028759f8csewardj   switch (opc2) {
567787e651f40360a8f1c9418710e79c482028759f8csewardj   case 0x255: // lswi (Load String Word Immediate, PPC32 p455)
567887e651f40360a8f1c9418710e79c482028759f8csewardj      /* NB: does not reject the case where RA is in the range of
567987e651f40360a8f1c9418710e79c482028759f8csewardj         registers to be loaded.  It should. */
5680d953ebb9b04cbad6891676df597bf0c542b1ec89cerion      DIP("lswi r%u,r%u,%d\n", rD_addr, rA_addr, NumBytes);
5681d953ebb9b04cbad6891676df597bf0c542b1ec89cerion      assign( t_EA, ea_rAor0(rA_addr) );
56822ef8a37484a9d027b19aa024b8e364645f04c2b8sewardj      if (NumBytes == 8 && !mode64) {
568387e651f40360a8f1c9418710e79c482028759f8csewardj         /* Special case hack */
568476de5cf615380b23b4b5bcced6541233cd4a93a0cerion         /* rD = Mem[EA]; (rD+1)%32 = Mem[EA+4] */
568576de5cf615380b23b4b5bcced6541233cd4a93a0cerion         putIReg( rD_addr,
56861f5fe1fc3a37ca729925e8eec25aa1025b4a6cdbcarll                  load(Ity_I32, mkexpr(t_EA)) );
568776de5cf615380b23b4b5bcced6541233cd4a93a0cerion         putIReg( (rD_addr+1) % 32,
56881f5fe1fc3a37ca729925e8eec25aa1025b4a6cdbcarll                  load(Ity_I32,
56891f5fe1fc3a37ca729925e8eec25aa1025b4a6cdbcarll                       binop(Iop_Add32, mkexpr(t_EA), mkU32(4))) );
569087e651f40360a8f1c9418710e79c482028759f8csewardj      } else {
569187e651f40360a8f1c9418710e79c482028759f8csewardj         t_nbytes = newTemp(Ity_I32);
569276de5cf615380b23b4b5bcced6541233cd4a93a0cerion         assign( t_nbytes, mkU32(NumBytes==0 ? 32 : NumBytes) );
5693d953ebb9b04cbad6891676df597bf0c542b1ec89cerion         generate_lsw_sequence( t_nbytes, t_EA, rD_addr, 32 );
569487e651f40360a8f1c9418710e79c482028759f8csewardj         *stopHere = True;
569587e651f40360a8f1c9418710e79c482028759f8csewardj      }
569687e651f40360a8f1c9418710e79c482028759f8csewardj      return True;
569787e651f40360a8f1c9418710e79c482028759f8csewardj
569887e651f40360a8f1c9418710e79c482028759f8csewardj   case 0x215: // lswx (Load String Word Indexed, PPC32 p456)
569987e651f40360a8f1c9418710e79c482028759f8csewardj      /* NB: does not reject the case where RA is in the range of
570087e651f40360a8f1c9418710e79c482028759f8csewardj         registers to be loaded.  It should.  Although considering
570187e651f40360a8f1c9418710e79c482028759f8csewardj         that that can only be detected at run time, it's not easy to
570287e651f40360a8f1c9418710e79c482028759f8csewardj         do so. */
570376de5cf615380b23b4b5bcced6541233cd4a93a0cerion      if (rD_addr == rA_addr || rD_addr == rB_addr)
570487e651f40360a8f1c9418710e79c482028759f8csewardj         return False;
570576de5cf615380b23b4b5bcced6541233cd4a93a0cerion      if (rD_addr == 0 && rA_addr == 0)
570687e651f40360a8f1c9418710e79c482028759f8csewardj         return False;
5707d953ebb9b04cbad6891676df597bf0c542b1ec89cerion      DIP("lswx r%u,r%u,r%u\n", rD_addr, rA_addr, rB_addr);
570887e651f40360a8f1c9418710e79c482028759f8csewardj      t_nbytes = newTemp(Ity_I32);
5709d953ebb9b04cbad6891676df597bf0c542b1ec89cerion      assign( t_EA, ea_rAor0_idxd(rA_addr,rB_addr) );
5710edf7fc572e2decb93e9143961e8739c8fe18899dcerion      assign( t_nbytes, unop( Iop_8Uto32, getXER_BC() ) );
5711d953ebb9b04cbad6891676df597bf0c542b1ec89cerion      generate_lsw_sequence( t_nbytes, t_EA, rD_addr, 128 );
571287e651f40360a8f1c9418710e79c482028759f8csewardj      *stopHere = True;
571387e651f40360a8f1c9418710e79c482028759f8csewardj      return True;
571487e651f40360a8f1c9418710e79c482028759f8csewardj
57155876fa100009ff1179c6e4aae0838176b9685794sewardj   case 0x2D5: // stswi (Store String Word Immediate, PPC32 p528)
5716d953ebb9b04cbad6891676df597bf0c542b1ec89cerion      DIP("stswi r%u,r%u,%d\n", rS_addr, rA_addr, NumBytes);
5717d953ebb9b04cbad6891676df597bf0c542b1ec89cerion      assign( t_EA, ea_rAor0(rA_addr) );
57182ef8a37484a9d027b19aa024b8e364645f04c2b8sewardj      if (NumBytes == 8 && !mode64) {
57195876fa100009ff1179c6e4aae0838176b9685794sewardj         /* Special case hack */
572076de5cf615380b23b4b5bcced6541233cd4a93a0cerion         /* Mem[EA] = rD; Mem[EA+4] = (rD+1)%32 */
57211f5fe1fc3a37ca729925e8eec25aa1025b4a6cdbcarll         store( mkexpr(t_EA),
57221f5fe1fc3a37ca729925e8eec25aa1025b4a6cdbcarll                getIReg(rD_addr) );
57231f5fe1fc3a37ca729925e8eec25aa1025b4a6cdbcarll         store( binop(Iop_Add32, mkexpr(t_EA), mkU32(4)),
57241f5fe1fc3a37ca729925e8eec25aa1025b4a6cdbcarll                getIReg((rD_addr+1) % 32) );
57255876fa100009ff1179c6e4aae0838176b9685794sewardj      } else {
57265876fa100009ff1179c6e4aae0838176b9685794sewardj         t_nbytes = newTemp(Ity_I32);
572776de5cf615380b23b4b5bcced6541233cd4a93a0cerion         assign( t_nbytes, mkU32(NumBytes==0 ? 32 : NumBytes) );
5728d953ebb9b04cbad6891676df597bf0c542b1ec89cerion         generate_stsw_sequence( t_nbytes, t_EA, rD_addr, 32 );
57295876fa100009ff1179c6e4aae0838176b9685794sewardj         *stopHere = True;
57305876fa100009ff1179c6e4aae0838176b9685794sewardj      }
57315876fa100009ff1179c6e4aae0838176b9685794sewardj      return True;
57325876fa100009ff1179c6e4aae0838176b9685794sewardj
57335876fa100009ff1179c6e4aae0838176b9685794sewardj   case 0x295: // stswx (Store String Word Indexed, PPC32 p529)
5734d953ebb9b04cbad6891676df597bf0c542b1ec89cerion      DIP("stswx r%u,r%u,r%u\n", rS_addr, rA_addr, rB_addr);
57355876fa100009ff1179c6e4aae0838176b9685794sewardj      t_nbytes = newTemp(Ity_I32);
5736d953ebb9b04cbad6891676df597bf0c542b1ec89cerion      assign( t_EA, ea_rAor0_idxd(rA_addr,rB_addr) );
5737edf7fc572e2decb93e9143961e8739c8fe18899dcerion      assign( t_nbytes, unop( Iop_8Uto32, getXER_BC() ) );
5738d953ebb9b04cbad6891676df597bf0c542b1ec89cerion      generate_stsw_sequence( t_nbytes, t_EA, rS_addr, 128 );
57395876fa100009ff1179c6e4aae0838176b9685794sewardj      *stopHere = True;
57405876fa100009ff1179c6e4aae0838176b9685794sewardj      return True;
574187e651f40360a8f1c9418710e79c482028759f8csewardj
574287e651f40360a8f1c9418710e79c482028759f8csewardj   default:
57435b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion      vex_printf("dis_int_ldst_str(ppc)(opc2)\n");
574487e651f40360a8f1c9418710e79c482028759f8csewardj      return False;
574587e651f40360a8f1c9418710e79c482028759f8csewardj   }
574687e651f40360a8f1c9418710e79c482028759f8csewardj   return True;
574787e651f40360a8f1c9418710e79c482028759f8csewardj}
574887e651f40360a8f1c9418710e79c482028759f8csewardj
5749b51f0f4f33256638ed953156a2635aa739b232f1sewardj
5750b51f0f4f33256638ed953156a2635aa739b232f1sewardj/* ------------------------------------------------------------------
5751b51f0f4f33256638ed953156a2635aa739b232f1sewardj   Integer Branch Instructions
5752b51f0f4f33256638ed953156a2635aa739b232f1sewardj   ------------------------------------------------------------------ */
5753b51f0f4f33256638ed953156a2635aa739b232f1sewardj
57543d870a39e4d145e2f3d9f9a0eeed3475ec934ac1cerion/*
5755b51f0f4f33256638ed953156a2635aa739b232f1sewardj  Branch helper function
5756b51f0f4f33256638ed953156a2635aa739b232f1sewardj  ok = BO[2] | ((CTR[0] != 0) ^ BO[1])
5757b51f0f4f33256638ed953156a2635aa739b232f1sewardj  Returns an I32 which is 0x00000000 if the ctr condition failed
5758b51f0f4f33256638ed953156a2635aa739b232f1sewardj  and 0xFFFFFFFF otherwise.
57593d870a39e4d145e2f3d9f9a0eeed3475ec934ac1cerion*/
5760b51f0f4f33256638ed953156a2635aa739b232f1sewardjstatic IRExpr* /* :: Ity_I32 */ branch_ctr_ok( UInt BO )
5761645c930b1a61f4493ee2d472b34fbb439233a874cerion{
5762d953ebb9b04cbad6891676df597bf0c542b1ec89cerion   IRType ty = mode64 ? Ity_I64 : Ity_I32;
5763b51f0f4f33256638ed953156a2635aa739b232f1sewardj   IRTemp ok = newTemp(Ity_I32);
5764b51f0f4f33256638ed953156a2635aa739b232f1sewardj
5765f0de28cf1a762b0d6f74c93d3532c89a230673bbcerion   if ((BO >> 2) & 1) {     // independent of ctr
5766b51f0f4f33256638ed953156a2635aa739b232f1sewardj      assign( ok, mkU32(0xFFFFFFFF) );
5767b85e8bba97fdae7d892f7bfd12e4601307e4721dcerion   } else {
5768f0de28cf1a762b0d6f74c93d3532c89a230673bbcerion      if ((BO >> 1) & 1) {  // ctr == 0 ?
5769d953ebb9b04cbad6891676df597bf0c542b1ec89cerion         assign( ok, unop( Iop_1Sto32,
57704e2c2b3cacdc79a993f4cec9249d9bffd82e4978cerion                           binop( mkSzOp(ty, Iop_CmpEQ8),
57714e2c2b3cacdc79a993f4cec9249d9bffd82e4978cerion                                  getGST( PPC_GST_CTR ),
57724e2c2b3cacdc79a993f4cec9249d9bffd82e4978cerion                                  mkSzImm(ty,0))) );
5773f0de28cf1a762b0d6f74c93d3532c89a230673bbcerion      } else {              // ctr != 0 ?
5774b51f0f4f33256638ed953156a2635aa739b232f1sewardj         assign( ok, unop( Iop_1Sto32,
57754e2c2b3cacdc79a993f4cec9249d9bffd82e4978cerion                           binop( mkSzOp(ty, Iop_CmpNE8),
57764e2c2b3cacdc79a993f4cec9249d9bffd82e4978cerion                                  getGST( PPC_GST_CTR ),
57774e2c2b3cacdc79a993f4cec9249d9bffd82e4978cerion                                  mkSzImm(ty,0))) );
5778b51f0f4f33256638ed953156a2635aa739b232f1sewardj      }
5779b85e8bba97fdae7d892f7bfd12e4601307e4721dcerion   }
5780b51f0f4f33256638ed953156a2635aa739b232f1sewardj   return mkexpr(ok);
5781b51f0f4f33256638ed953156a2635aa739b232f1sewardj}
5782b51f0f4f33256638ed953156a2635aa739b232f1sewardj
5783b51f0f4f33256638ed953156a2635aa739b232f1sewardj
5784b51f0f4f33256638ed953156a2635aa739b232f1sewardj/*
5785b51f0f4f33256638ed953156a2635aa739b232f1sewardj  Branch helper function cond_ok = BO[4] | (CR[BI] == BO[3])
5786b51f0f4f33256638ed953156a2635aa739b232f1sewardj  Returns an I32 which is either 0 if the condition failed or
5787b51f0f4f33256638ed953156a2635aa739b232f1sewardj  some arbitrary nonzero value otherwise. */
5788b51f0f4f33256638ed953156a2635aa739b232f1sewardj
5789b51f0f4f33256638ed953156a2635aa739b232f1sewardjstatic IRExpr* /* :: Ity_I32 */ branch_cond_ok( UInt BO, UInt BI )
5790b51f0f4f33256638ed953156a2635aa739b232f1sewardj{
5791b51f0f4f33256638ed953156a2635aa739b232f1sewardj   Int where;
5792b51f0f4f33256638ed953156a2635aa739b232f1sewardj   IRTemp res   = newTemp(Ity_I32);
5793b51f0f4f33256638ed953156a2635aa739b232f1sewardj   IRTemp cr_bi = newTemp(Ity_I32);
5794b85e8bba97fdae7d892f7bfd12e4601307e4721dcerion
5795b51f0f4f33256638ed953156a2635aa739b232f1sewardj   if ((BO >> 4) & 1) {
5796b51f0f4f33256638ed953156a2635aa739b232f1sewardj      assign( res, mkU32(1) );
5797b51f0f4f33256638ed953156a2635aa739b232f1sewardj   } else {
5798b51f0f4f33256638ed953156a2635aa739b232f1sewardj      // ok = (CR[BI] == BO[3]) Note, the following relies on
5799b51f0f4f33256638ed953156a2635aa739b232f1sewardj      // getCRbit_anywhere returning a value which
5800b51f0f4f33256638ed953156a2635aa739b232f1sewardj      // is either zero or has exactly 1 bit set.
5801b51f0f4f33256638ed953156a2635aa739b232f1sewardj      assign( cr_bi, getCRbit_anywhere( BI, &where ) );
5802094d1397b3f69b1a538e80ab509ea8cd75f4be3bcerion
5803b51f0f4f33256638ed953156a2635aa739b232f1sewardj      if ((BO >> 3) & 1) {
5804b51f0f4f33256638ed953156a2635aa739b232f1sewardj         /* We can use cr_bi as-is. */
5805b51f0f4f33256638ed953156a2635aa739b232f1sewardj         assign( res, mkexpr(cr_bi) );
5806b51f0f4f33256638ed953156a2635aa739b232f1sewardj      } else {
5807b51f0f4f33256638ed953156a2635aa739b232f1sewardj         /* We have to invert the sense of the information held in
5808b51f0f4f33256638ed953156a2635aa739b232f1sewardj            cr_bi.  For that we need to know which bit
580976de5cf615380b23b4b5bcced6541233cd4a93a0cerion            getCRbit_anywhere regards as significant. */
58105b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion         assign( res, binop(Iop_Xor32, mkexpr(cr_bi),
58115b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion                                       mkU32(1<<where)) );
5812b85e8bba97fdae7d892f7bfd12e4601307e4721dcerion      }
5813b85e8bba97fdae7d892f7bfd12e4601307e4721dcerion   }
5814b51f0f4f33256638ed953156a2635aa739b232f1sewardj   return mkexpr(res);
5815645c930b1a61f4493ee2d472b34fbb439233a874cerion}
5816645c930b1a61f4493ee2d472b34fbb439233a874cerion
5817645c930b1a61f4493ee2d472b34fbb439233a874cerion
58183d870a39e4d145e2f3d9f9a0eeed3475ec934ac1cerion/*
5819b51f0f4f33256638ed953156a2635aa739b232f1sewardj  Integer Branch Instructions
58203d870a39e4d145e2f3d9f9a0eeed3475ec934ac1cerion*/
58219d540e52976d5b6afac33b276e13c5c40f81db90sewardjstatic Bool dis_branch ( UInt theInstr,
5822cacba8e675988fbf21b08feea1f317a9c896c053florian                         const VexAbiInfo* vbi,
58239d540e52976d5b6afac33b276e13c5c40f81db90sewardj                         /*OUT*/DisResult* dres,
5824beac530a718fcc646bc61fe60a86f599df54e1d7florian                         Bool (*resteerOkFn)(void*,Addr),
5825c716aea1cafe66ee431dc7d6909c98f18788a028sewardj                         void* callback_opaque )
5826645c930b1a61f4493ee2d472b34fbb439233a874cerion{
5827d953ebb9b04cbad6891676df597bf0c542b1ec89cerion   UChar opc1    = ifieldOPC(theInstr);
5828d953ebb9b04cbad6891676df597bf0c542b1ec89cerion   UChar BO      = ifieldRegDS(theInstr);
5829d953ebb9b04cbad6891676df597bf0c542b1ec89cerion   UChar BI      = ifieldRegA(theInstr);
5830d953ebb9b04cbad6891676df597bf0c542b1ec89cerion   UInt  BD_u16  = ifieldUIMM16(theInstr) & 0xFFFFFFFC; /* mask off */
5831d953ebb9b04cbad6891676df597bf0c542b1ec89cerion   UChar b11to15 = ifieldRegB(theInstr);
5832d953ebb9b04cbad6891676df597bf0c542b1ec89cerion   UInt  opc2    = ifieldOPClo10(theInstr);
5833d953ebb9b04cbad6891676df597bf0c542b1ec89cerion   UInt  LI_u26  = ifieldUIMM26(theInstr) & 0xFFFFFFFC; /* mask off */
5834d953ebb9b04cbad6891676df597bf0c542b1ec89cerion   UChar flag_AA = ifieldBIT1(theInstr);
5835d953ebb9b04cbad6891676df597bf0c542b1ec89cerion   UChar flag_LK = ifieldBIT0(theInstr);
5836d953ebb9b04cbad6891676df597bf0c542b1ec89cerion
58372831b00c4950d6c2b061def05fd67528fe132ececerion   IRType   ty        = mode64 ? Ity_I64 : Ity_I32;
5838d953ebb9b04cbad6891676df597bf0c542b1ec89cerion   Addr64   tgt       = 0;
5839b173774421d015736c2316b5e6e998e7de545a5cflorian   UInt     BD        = extend_s_16to32(BD_u16);
58402831b00c4950d6c2b061def05fd67528fe132ececerion   IRTemp   do_branch = newTemp(Ity_I32);
58412831b00c4950d6c2b061def05fd67528fe132ececerion   IRTemp   ctr_ok    = newTemp(Ity_I32);
58422831b00c4950d6c2b061def05fd67528fe132ececerion   IRTemp   cond_ok   = newTemp(Ity_I32);
58432831b00c4950d6c2b061def05fd67528fe132ececerion   IRExpr*  e_nia     = mkSzImm(ty, nextInsnAddr());
58442831b00c4950d6c2b061def05fd67528fe132ececerion   IRConst* c_nia     = mkSzConst(ty, nextInsnAddr());
5845df07b8888302214ac6c647dca016417a2388f0c3sewardj   IRTemp   lr_old    = newTemp(ty);
5846d953ebb9b04cbad6891676df597bf0c542b1ec89cerion
5847b51f0f4f33256638ed953156a2635aa739b232f1sewardj   /* Hack to pass through code that just wants to read the PC */
5848b51f0f4f33256638ed953156a2635aa739b232f1sewardj   if (theInstr == 0x429F0005) {
5849b51f0f4f33256638ed953156a2635aa739b232f1sewardj      DIP("bcl 0x%x, 0x%x (a.k.a mr lr,cia+4)\n", BO, BI);
5850d953ebb9b04cbad6891676df597bf0c542b1ec89cerion      putGST( PPC_GST_LR, e_nia );
5851b51f0f4f33256638ed953156a2635aa739b232f1sewardj      return True;
5852b51f0f4f33256638ed953156a2635aa739b232f1sewardj   }
58539d540e52976d5b6afac33b276e13c5c40f81db90sewardj
58549d540e52976d5b6afac33b276e13c5c40f81db90sewardj   /* The default what-next.  Individual cases can override it. */
58559d540e52976d5b6afac33b276e13c5c40f81db90sewardj   dres->whatNext = Dis_StopHere;
58563dee849ec7c38746749065e67dc53b75daa7617dsewardj   vassert(dres->jk_StopHere == Ijk_INVALID);
58579d540e52976d5b6afac33b276e13c5c40f81db90sewardj
5858b51f0f4f33256638ed953156a2635aa739b232f1sewardj   switch (opc1) {
5859b51f0f4f33256638ed953156a2635aa739b232f1sewardj   case 0x12: // b     (Branch, PPC32 p360)
5860b51f0f4f33256638ed953156a2635aa739b232f1sewardj      if (flag_AA) {
58612831b00c4950d6c2b061def05fd67528fe132ececerion         tgt = mkSzAddr( ty, extend_s_26to64(LI_u26) );
5862b51f0f4f33256638ed953156a2635aa739b232f1sewardj      } else {
58632831b00c4950d6c2b061def05fd67528fe132ececerion         tgt = mkSzAddr( ty, guest_CIA_curr_instr +
58642831b00c4950d6c2b061def05fd67528fe132ececerion                             (Long)extend_s_26to64(LI_u26) );
58658ea677178e964717135e7c2b039af26875276e84sewardj      }
5866d953ebb9b04cbad6891676df597bf0c542b1ec89cerion      if (mode64) {
5867d953ebb9b04cbad6891676df597bf0c542b1ec89cerion         DIP("b%s%s 0x%llx\n",
5868d953ebb9b04cbad6891676df597bf0c542b1ec89cerion             flag_LK ? "l" : "", flag_AA ? "a" : "", tgt);
5869d953ebb9b04cbad6891676df597bf0c542b1ec89cerion      } else {
5870d953ebb9b04cbad6891676df597bf0c542b1ec89cerion         DIP("b%s%s 0x%x\n",
5871d953ebb9b04cbad6891676df597bf0c542b1ec89cerion             flag_LK ? "l" : "", flag_AA ? "a" : "", (Addr32)tgt);
58729d540e52976d5b6afac33b276e13c5c40f81db90sewardj      }
58739d540e52976d5b6afac33b276e13c5c40f81db90sewardj
5874cf8986c47a4c8c810566bb5b7b3da7a16a17dfe2sewardj      if (flag_LK) {
5875d953ebb9b04cbad6891676df597bf0c542b1ec89cerion         putGST( PPC_GST_LR, e_nia );
5876dd40fdf58cc8a6fe9466c4f00bdfc9fe9bf00449sewardj         if (vbi->guest_ppc_zap_RZ_at_bl
5877478646f54befaba01cbceb40fd5e46cdf562fdb5sewardj             && vbi->guest_ppc_zap_RZ_at_bl( (ULong)tgt) ) {
5878478646f54befaba01cbceb40fd5e46cdf562fdb5sewardj            IRTemp t_tgt = newTemp(ty);
5879478646f54befaba01cbceb40fd5e46cdf562fdb5sewardj            assign(t_tgt, mode64 ? mkU64(tgt) : mkU32(tgt) );
5880478646f54befaba01cbceb40fd5e46cdf562fdb5sewardj            make_redzone_AbiHint( vbi, t_tgt,
5881aca070a5b3418a6a9b01e3c57a7eb0fbb5050908sewardj                                  "branch-and-link (unconditional call)" );
5882478646f54befaba01cbceb40fd5e46cdf562fdb5sewardj         }
5883cf8986c47a4c8c810566bb5b7b3da7a16a17dfe2sewardj      }
5884d953ebb9b04cbad6891676df597bf0c542b1ec89cerion
5885c716aea1cafe66ee431dc7d6909c98f18788a028sewardj      if (resteerOkFn( callback_opaque, tgt )) {
5886984d9b164dd17f07e603c41fe1e506e641e57d18sewardj         dres->whatNext   = Dis_ResteerU;
5887d953ebb9b04cbad6891676df597bf0c542b1ec89cerion         dres->continueAt = tgt;
58889d540e52976d5b6afac33b276e13c5c40f81db90sewardj      } else {
58893dee849ec7c38746749065e67dc53b75daa7617dsewardj         dres->jk_StopHere = flag_LK ? Ijk_Call : Ijk_Boring; ;
58903dee849ec7c38746749065e67dc53b75daa7617dsewardj         putGST( PPC_GST_CIA, mkSzImm(ty, tgt) );
58919d540e52976d5b6afac33b276e13c5c40f81db90sewardj      }
5892b51f0f4f33256638ed953156a2635aa739b232f1sewardj      break;
5893b85e8bba97fdae7d892f7bfd12e4601307e4721dcerion
5894e9d361ab43518b6dfbd3d846f48859534659dee0cerion   case 0x10: // bc    (Branch Conditional, PPC32 p361)
5895b85e8bba97fdae7d892f7bfd12e4601307e4721dcerion      DIP("bc%s%s 0x%x, 0x%x, 0x%x\n",
5896d953ebb9b04cbad6891676df597bf0c542b1ec89cerion          flag_LK ? "l" : "", flag_AA ? "a" : "", BO, BI, BD);
5897b85e8bba97fdae7d892f7bfd12e4601307e4721dcerion
5898b85e8bba97fdae7d892f7bfd12e4601307e4721dcerion      if (!(BO & 0x4)) {
5899d953ebb9b04cbad6891676df597bf0c542b1ec89cerion         putGST( PPC_GST_CTR,
59002831b00c4950d6c2b061def05fd67528fe132ececerion                 binop(mkSzOp(ty, Iop_Sub8),
59012831b00c4950d6c2b061def05fd67528fe132ececerion                       getGST( PPC_GST_CTR ), mkSzImm(ty, 1)) );
5902b85e8bba97fdae7d892f7bfd12e4601307e4721dcerion      }
5903b51f0f4f33256638ed953156a2635aa739b232f1sewardj
5904b51f0f4f33256638ed953156a2635aa739b232f1sewardj      /* This is a bit subtle.  ctr_ok is either all 0s or all 1s.
590576de5cf615380b23b4b5bcced6541233cd4a93a0cerion         cond_ok is either zero or nonzero, since that's the cheapest
590676de5cf615380b23b4b5bcced6541233cd4a93a0cerion         way to compute it.  Anding them together gives a value which
590776de5cf615380b23b4b5bcced6541233cd4a93a0cerion         is either zero or non zero and so that's what we must test
590876de5cf615380b23b4b5bcced6541233cd4a93a0cerion         for in the IRStmt_Exit. */
5909b51f0f4f33256638ed953156a2635aa739b232f1sewardj      assign( ctr_ok,  branch_ctr_ok( BO ) );
5910b85e8bba97fdae7d892f7bfd12e4601307e4721dcerion      assign( cond_ok, branch_cond_ok( BO, BI ) );
5911b51f0f4f33256638ed953156a2635aa739b232f1sewardj      assign( do_branch,
5912b51f0f4f33256638ed953156a2635aa739b232f1sewardj              binop(Iop_And32, mkexpr(cond_ok), mkexpr(ctr_ok)) );
5913b51f0f4f33256638ed953156a2635aa739b232f1sewardj
59144561acb2fed3ea11b7b1f95a373da8ec62e6d483cerion      if (flag_AA) {
59152831b00c4950d6c2b061def05fd67528fe132ececerion         tgt = mkSzAddr(ty, extend_s_16to64(BD_u16));
59164561acb2fed3ea11b7b1f95a373da8ec62e6d483cerion      } else {
59172831b00c4950d6c2b061def05fd67528fe132ececerion         tgt = mkSzAddr(ty, guest_CIA_curr_instr +
59182831b00c4950d6c2b061def05fd67528fe132ececerion                            (Long)extend_s_16to64(BD_u16));
5919b85e8bba97fdae7d892f7bfd12e4601307e4721dcerion      }
5920d953ebb9b04cbad6891676df597bf0c542b1ec89cerion      if (flag_LK)
5921d953ebb9b04cbad6891676df597bf0c542b1ec89cerion         putGST( PPC_GST_LR, e_nia );
5922b85e8bba97fdae7d892f7bfd12e4601307e4721dcerion
5923d953ebb9b04cbad6891676df597bf0c542b1ec89cerion      stmt( IRStmt_Exit(
5924d953ebb9b04cbad6891676df597bf0c542b1ec89cerion               binop(Iop_CmpNE32, mkexpr(do_branch), mkU32(0)),
5925d953ebb9b04cbad6891676df597bf0c542b1ec89cerion               flag_LK ? Ijk_Call : Ijk_Boring,
59263dee849ec7c38746749065e67dc53b75daa7617dsewardj               mkSzConst(ty, tgt), OFFB_CIA ) );
59273dee849ec7c38746749065e67dc53b75daa7617dsewardj
59283dee849ec7c38746749065e67dc53b75daa7617dsewardj      dres->jk_StopHere = Ijk_Boring;
59293dee849ec7c38746749065e67dc53b75daa7617dsewardj      putGST( PPC_GST_CIA, e_nia );
5930b85e8bba97fdae7d892f7bfd12e4601307e4721dcerion      break;
5931b85e8bba97fdae7d892f7bfd12e4601307e4721dcerion
5932b85e8bba97fdae7d892f7bfd12e4601307e4721dcerion   case 0x13:
59336be67235ba2829b0bc34c3a0876cee4eac340d95sewardj      /* For bclr and bcctr, it appears that the lowest two bits of
59346be67235ba2829b0bc34c3a0876cee4eac340d95sewardj         b11to15 are a branch hint, and so we only need to ensure it's
59356be67235ba2829b0bc34c3a0876cee4eac340d95sewardj         of the form 000XX. */
59366be67235ba2829b0bc34c3a0876cee4eac340d95sewardj      if ((b11to15 & ~3) != 0) {
5937b173774421d015736c2316b5e6e998e7de545a5cflorian         vex_printf("dis_int_branch(ppc)(0x13,b11to15)(%d)\n", b11to15);
5938b85e8bba97fdae7d892f7bfd12e4601307e4721dcerion         return False;
5939b85e8bba97fdae7d892f7bfd12e4601307e4721dcerion      }
5940b85e8bba97fdae7d892f7bfd12e4601307e4721dcerion
5941b85e8bba97fdae7d892f7bfd12e4601307e4721dcerion      switch (opc2) {
5942e9d361ab43518b6dfbd3d846f48859534659dee0cerion      case 0x210: // bcctr (Branch Cond. to Count Register, PPC32 p363)
59435b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion         if ((BO & 0x4) == 0) { // "decr and test CTR" option invalid
59445b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion            vex_printf("dis_int_branch(ppc)(bcctr,BO)\n");
5945b85e8bba97fdae7d892f7bfd12e4601307e4721dcerion            return False;
5946b85e8bba97fdae7d892f7bfd12e4601307e4721dcerion         }
5947a31e8b578565058187814bcb2d1bb77c09da6adccerion         DIP("bcctr%s 0x%x, 0x%x\n", flag_LK ? "l" : "", BO, BI);
5948b85e8bba97fdae7d892f7bfd12e4601307e4721dcerion
5949b85e8bba97fdae7d892f7bfd12e4601307e4721dcerion         assign( cond_ok, branch_cond_ok( BO, BI ) );
5950d953ebb9b04cbad6891676df597bf0c542b1ec89cerion
5951478646f54befaba01cbceb40fd5e46cdf562fdb5sewardj         /* FIXME: this is confusing.  lr_old holds the old value
5952478646f54befaba01cbceb40fd5e46cdf562fdb5sewardj            of ctr, not lr :-) */
59532831b00c4950d6c2b061def05fd67528fe132ececerion         assign( lr_old, addr_align( getGST( PPC_GST_CTR ), 4 ));
5954df07b8888302214ac6c647dca016417a2388f0c3sewardj
5955d953ebb9b04cbad6891676df597bf0c542b1ec89cerion         if (flag_LK)
5956d953ebb9b04cbad6891676df597bf0c542b1ec89cerion            putGST( PPC_GST_LR, e_nia );
5957b85e8bba97fdae7d892f7bfd12e4601307e4721dcerion
5958b51f0f4f33256638ed953156a2635aa739b232f1sewardj         stmt( IRStmt_Exit(
5959b51f0f4f33256638ed953156a2635aa739b232f1sewardj                  binop(Iop_CmpEQ32, mkexpr(cond_ok), mkU32(0)),
5960b51f0f4f33256638ed953156a2635aa739b232f1sewardj                  Ijk_Boring,
59613dee849ec7c38746749065e67dc53b75daa7617dsewardj                  c_nia, OFFB_CIA ));
5962478646f54befaba01cbceb40fd5e46cdf562fdb5sewardj
5963478646f54befaba01cbceb40fd5e46cdf562fdb5sewardj         if (flag_LK && vbi->guest_ppc_zap_RZ_at_bl) {
5964478646f54befaba01cbceb40fd5e46cdf562fdb5sewardj            make_redzone_AbiHint( vbi, lr_old,
5965478646f54befaba01cbceb40fd5e46cdf562fdb5sewardj                                  "b-ctr-l (indirect call)" );
5966478646f54befaba01cbceb40fd5e46cdf562fdb5sewardj	 }
5967478646f54befaba01cbceb40fd5e46cdf562fdb5sewardj
59683dee849ec7c38746749065e67dc53b75daa7617dsewardj         dres->jk_StopHere = flag_LK ? Ijk_Call : Ijk_Boring;;
59693dee849ec7c38746749065e67dc53b75daa7617dsewardj         putGST( PPC_GST_CIA, mkexpr(lr_old) );
5970b85e8bba97fdae7d892f7bfd12e4601307e4721dcerion         break;
5971b85e8bba97fdae7d892f7bfd12e4601307e4721dcerion
5972cf8986c47a4c8c810566bb5b7b3da7a16a17dfe2sewardj      case 0x010: { // bclr (Branch Cond. to Link Register, PPC32 p365)
5973cf8986c47a4c8c810566bb5b7b3da7a16a17dfe2sewardj         Bool vanilla_return = False;
5974b51f0f4f33256638ed953156a2635aa739b232f1sewardj         if ((BO & 0x14 /* 1z1zz */) == 0x14 && flag_LK == 0) {
5975225a034683024109da729a4d2f080364b9485007cerion            DIP("blr\n");
5976cf8986c47a4c8c810566bb5b7b3da7a16a17dfe2sewardj            vanilla_return = True;
5977b51f0f4f33256638ed953156a2635aa739b232f1sewardj         } else {
5978b51f0f4f33256638ed953156a2635aa739b232f1sewardj            DIP("bclr%s 0x%x, 0x%x\n", flag_LK ? "l" : "", BO, BI);
5979b51f0f4f33256638ed953156a2635aa739b232f1sewardj         }
5980b85e8bba97fdae7d892f7bfd12e4601307e4721dcerion
5981b85e8bba97fdae7d892f7bfd12e4601307e4721dcerion         if (!(BO & 0x4)) {
5982d953ebb9b04cbad6891676df597bf0c542b1ec89cerion            putGST( PPC_GST_CTR,
59832831b00c4950d6c2b061def05fd67528fe132ececerion                    binop(mkSzOp(ty, Iop_Sub8),
59842831b00c4950d6c2b061def05fd67528fe132ececerion                          getGST( PPC_GST_CTR ), mkSzImm(ty, 1)) );
5985b85e8bba97fdae7d892f7bfd12e4601307e4721dcerion         }
5986b85e8bba97fdae7d892f7bfd12e4601307e4721dcerion
5987b51f0f4f33256638ed953156a2635aa739b232f1sewardj         /* See comments above for 'bc' about this */
5988b51f0f4f33256638ed953156a2635aa739b232f1sewardj         assign( ctr_ok,  branch_ctr_ok( BO ) );
5989b51f0f4f33256638ed953156a2635aa739b232f1sewardj         assign( cond_ok, branch_cond_ok( BO, BI ) );
5990b51f0f4f33256638ed953156a2635aa739b232f1sewardj         assign( do_branch,
5991b51f0f4f33256638ed953156a2635aa739b232f1sewardj                 binop(Iop_And32, mkexpr(cond_ok), mkexpr(ctr_ok)) );
59922831b00c4950d6c2b061def05fd67528fe132ececerion
5993df07b8888302214ac6c647dca016417a2388f0c3sewardj         assign( lr_old, addr_align( getGST( PPC_GST_LR ), 4 ));
5994df07b8888302214ac6c647dca016417a2388f0c3sewardj
5995d953ebb9b04cbad6891676df597bf0c542b1ec89cerion         if (flag_LK)
5996d953ebb9b04cbad6891676df597bf0c542b1ec89cerion            putGST( PPC_GST_LR,  e_nia );
5997b51f0f4f33256638ed953156a2635aa739b232f1sewardj
5998b51f0f4f33256638ed953156a2635aa739b232f1sewardj         stmt( IRStmt_Exit(
5999b51f0f4f33256638ed953156a2635aa739b232f1sewardj                  binop(Iop_CmpEQ32, mkexpr(do_branch), mkU32(0)),
6000b51f0f4f33256638ed953156a2635aa739b232f1sewardj                  Ijk_Boring,
60013dee849ec7c38746749065e67dc53b75daa7617dsewardj                  c_nia, OFFB_CIA ));
6002b51f0f4f33256638ed953156a2635aa739b232f1sewardj
6003478646f54befaba01cbceb40fd5e46cdf562fdb5sewardj         if (vanilla_return && vbi->guest_ppc_zap_RZ_at_blr) {
6004478646f54befaba01cbceb40fd5e46cdf562fdb5sewardj            make_redzone_AbiHint( vbi, lr_old,
6005478646f54befaba01cbceb40fd5e46cdf562fdb5sewardj                                  "branch-to-lr (unconditional return)" );
6006478646f54befaba01cbceb40fd5e46cdf562fdb5sewardj         }
6007cf8986c47a4c8c810566bb5b7b3da7a16a17dfe2sewardj
6008d37be0323036e01ffafa3286d893aa953f109191sewardj         /* blrl is pretty strange; it's like a return that sets the
6009d37be0323036e01ffafa3286d893aa953f109191sewardj            return address of its caller to the insn following this
6010d37be0323036e01ffafa3286d893aa953f109191sewardj            one.  Mark it as a return. */
60113dee849ec7c38746749065e67dc53b75daa7617dsewardj         dres->jk_StopHere = Ijk_Ret;  /* was flag_LK ? Ijk_Call : Ijk_Ret; */
60123dee849ec7c38746749065e67dc53b75daa7617dsewardj         putGST( PPC_GST_CIA, mkexpr(lr_old) );
6013b85e8bba97fdae7d892f7bfd12e4601307e4721dcerion         break;
6014cf8986c47a4c8c810566bb5b7b3da7a16a17dfe2sewardj      }
6015b85e8bba97fdae7d892f7bfd12e4601307e4721dcerion      default:
60165b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion         vex_printf("dis_int_branch(ppc)(opc2)\n");
6017b85e8bba97fdae7d892f7bfd12e4601307e4721dcerion         return False;
6018b85e8bba97fdae7d892f7bfd12e4601307e4721dcerion      }
6019b85e8bba97fdae7d892f7bfd12e4601307e4721dcerion      break;
60202831b00c4950d6c2b061def05fd67528fe132ececerion
6021b85e8bba97fdae7d892f7bfd12e4601307e4721dcerion   default:
60225b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion      vex_printf("dis_int_branch(ppc)(opc1)\n");
6023b85e8bba97fdae7d892f7bfd12e4601307e4721dcerion      return False;
6024b85e8bba97fdae7d892f7bfd12e4601307e4721dcerion   }
60252831b00c4950d6c2b061def05fd67528fe132ececerion
6026b85e8bba97fdae7d892f7bfd12e4601307e4721dcerion   return True;
602791ad5368eb6354ad4fabc86f2b2e641736997a38cerion}
6028896a1373cfdbaa25f4ab73ed4f27554016defecccerion
6029896a1373cfdbaa25f4ab73ed4f27554016defecccerion
6030896a1373cfdbaa25f4ab73ed4f27554016defecccerion
60313d870a39e4d145e2f3d9f9a0eeed3475ec934ac1cerion/*
60323d870a39e4d145e2f3d9f9a0eeed3475ec934ac1cerion  Condition Register Logical Instructions
60333d870a39e4d145e2f3d9f9a0eeed3475ec934ac1cerion*/
60343007c7fb4f226f2db7e250b0ebb114618ab1980ccerionstatic Bool dis_cond_logic ( UInt theInstr )
60353007c7fb4f226f2db7e250b0ebb114618ab1980ccerion{
60363007c7fb4f226f2db7e250b0ebb114618ab1980ccerion   /* XL-Form */
603776de5cf615380b23b4b5bcced6541233cd4a93a0cerion   UChar opc1      = ifieldOPC(theInstr);
603876de5cf615380b23b4b5bcced6541233cd4a93a0cerion   UChar crbD_addr = ifieldRegDS(theInstr);
603976de5cf615380b23b4b5bcced6541233cd4a93a0cerion   UChar crfD_addr = toUChar( IFIELD(theInstr, 23, 3) );
604076de5cf615380b23b4b5bcced6541233cd4a93a0cerion   UChar crbA_addr = ifieldRegA(theInstr);
604176de5cf615380b23b4b5bcced6541233cd4a93a0cerion   UChar crfS_addr = toUChar( IFIELD(theInstr, 18, 3) );
604276de5cf615380b23b4b5bcced6541233cd4a93a0cerion   UChar crbB_addr = ifieldRegB(theInstr);
604376de5cf615380b23b4b5bcced6541233cd4a93a0cerion   UInt  opc2      = ifieldOPClo10(theInstr);
604476de5cf615380b23b4b5bcced6541233cd4a93a0cerion   UChar b0        = ifieldBIT0(theInstr);
60453007c7fb4f226f2db7e250b0ebb114618ab1980ccerion
6046f0de28cf1a762b0d6f74c93d3532c89a230673bbcerion   IRTemp crbD     = newTemp(Ity_I32);
6047f0de28cf1a762b0d6f74c93d3532c89a230673bbcerion   IRTemp crbA     = newTemp(Ity_I32);
6048f0de28cf1a762b0d6f74c93d3532c89a230673bbcerion   IRTemp crbB     = newTemp(Ity_I32);
60493007c7fb4f226f2db7e250b0ebb114618ab1980ccerion
60503007c7fb4f226f2db7e250b0ebb114618ab1980ccerion   if (opc1 != 19 || b0 != 0) {
60515b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion      vex_printf("dis_cond_logic(ppc)(opc1)\n");
60523007c7fb4f226f2db7e250b0ebb114618ab1980ccerion      return False;
60533007c7fb4f226f2db7e250b0ebb114618ab1980ccerion   }
60543007c7fb4f226f2db7e250b0ebb114618ab1980ccerion
6055e9d361ab43518b6dfbd3d846f48859534659dee0cerion   if (opc2 == 0) {  // mcrf    (Move Cond Reg Field, PPC32 p464)
60563007c7fb4f226f2db7e250b0ebb114618ab1980ccerion      if (((crbD_addr & 0x3) != 0) ||
605776de5cf615380b23b4b5bcced6541233cd4a93a0cerion          ((crbA_addr & 0x3) != 0) || (crbB_addr != 0)) {
60585b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion         vex_printf("dis_cond_logic(ppc)(crbD|crbA|crbB != 0)\n");
60593007c7fb4f226f2db7e250b0ebb114618ab1980ccerion         return False;
606076de5cf615380b23b4b5bcced6541233cd4a93a0cerion      }
6061d953ebb9b04cbad6891676df597bf0c542b1ec89cerion      DIP("mcrf cr%u,cr%u\n", crfD_addr, crfS_addr);
6062b51f0f4f33256638ed953156a2635aa739b232f1sewardj      putCR0(   crfD_addr, getCR0(  crfS_addr) );
6063b51f0f4f33256638ed953156a2635aa739b232f1sewardj      putCR321( crfD_addr, getCR321(crfS_addr) );
60643007c7fb4f226f2db7e250b0ebb114618ab1980ccerion   } else {
6065b51f0f4f33256638ed953156a2635aa739b232f1sewardj      assign( crbA, getCRbit(crbA_addr) );
6066a50fde5504e829e5154113d7e507f12707089f48cerion      if (crbA_addr == crbB_addr)
6067b51f0f4f33256638ed953156a2635aa739b232f1sewardj         crbB = crbA;
6068a50fde5504e829e5154113d7e507f12707089f48cerion      else
6069b51f0f4f33256638ed953156a2635aa739b232f1sewardj         assign( crbB, getCRbit(crbB_addr) );
60703007c7fb4f226f2db7e250b0ebb114618ab1980ccerion
60713007c7fb4f226f2db7e250b0ebb114618ab1980ccerion      switch (opc2) {
60727c2dc7122cd7767e59112254183cf9babd4a1cb3sewardj      case 0x101: // crand   (Cond Reg AND, PPC32 p372)
60737c2dc7122cd7767e59112254183cf9babd4a1cb3sewardj         DIP("crand crb%d,crb%d,crb%d\n", crbD_addr, crbA_addr, crbB_addr);
60747c2dc7122cd7767e59112254183cf9babd4a1cb3sewardj         assign( crbD, binop(Iop_And32, mkexpr(crbA), mkexpr(crbB)) );
60757c2dc7122cd7767e59112254183cf9babd4a1cb3sewardj         break;
60767787af415a9104b601c2f0ce5b56749e4fd86691sewardj      case 0x081: // crandc  (Cond Reg AND w. Complement, PPC32 p373)
60777787af415a9104b601c2f0ce5b56749e4fd86691sewardj         DIP("crandc crb%d,crb%d,crb%d\n", crbD_addr, crbA_addr, crbB_addr);
60787787af415a9104b601c2f0ce5b56749e4fd86691sewardj         assign( crbD, binop(Iop_And32,
60797787af415a9104b601c2f0ce5b56749e4fd86691sewardj                             mkexpr(crbA),
60807787af415a9104b601c2f0ce5b56749e4fd86691sewardj                             unop(Iop_Not32, mkexpr(crbB))) );
60817787af415a9104b601c2f0ce5b56749e4fd86691sewardj         break;
6082e14bb9f862843c6b804097c124961b5567ded4f1sewardj      case 0x121: // creqv   (Cond Reg Equivalent, PPC32 p374)
6083e14bb9f862843c6b804097c124961b5567ded4f1sewardj         DIP("creqv crb%d,crb%d,crb%d\n", crbD_addr, crbA_addr, crbB_addr);
6084e14bb9f862843c6b804097c124961b5567ded4f1sewardj         assign( crbD, unop(Iop_Not32,
6085e14bb9f862843c6b804097c124961b5567ded4f1sewardj                            binop(Iop_Xor32, mkexpr(crbA), mkexpr(crbB))) );
6086e14bb9f862843c6b804097c124961b5567ded4f1sewardj         break;
60877c2dc7122cd7767e59112254183cf9babd4a1cb3sewardj      case 0x0E1: // crnand  (Cond Reg NAND, PPC32 p375)
60887c2dc7122cd7767e59112254183cf9babd4a1cb3sewardj         DIP("crnand crb%d,crb%d,crb%d\n", crbD_addr, crbA_addr, crbB_addr);
60897c2dc7122cd7767e59112254183cf9babd4a1cb3sewardj         assign( crbD, unop(Iop_Not32,
60907c2dc7122cd7767e59112254183cf9babd4a1cb3sewardj                            binop(Iop_And32, mkexpr(crbA), mkexpr(crbB))) );
60917c2dc7122cd7767e59112254183cf9babd4a1cb3sewardj         break;
6092e9d361ab43518b6dfbd3d846f48859534659dee0cerion      case 0x021: // crnor   (Cond Reg NOR, PPC32 p376)
60933007c7fb4f226f2db7e250b0ebb114618ab1980ccerion         DIP("crnor crb%d,crb%d,crb%d\n", crbD_addr, crbA_addr, crbB_addr);
60943007c7fb4f226f2db7e250b0ebb114618ab1980ccerion         assign( crbD, unop(Iop_Not32,
60953007c7fb4f226f2db7e250b0ebb114618ab1980ccerion                            binop(Iop_Or32, mkexpr(crbA), mkexpr(crbB))) );
60963007c7fb4f226f2db7e250b0ebb114618ab1980ccerion         break;
6097e9d361ab43518b6dfbd3d846f48859534659dee0cerion      case 0x1C1: // cror    (Cond Reg OR, PPC32 p377)
60983007c7fb4f226f2db7e250b0ebb114618ab1980ccerion         DIP("cror crb%d,crb%d,crb%d\n", crbD_addr, crbA_addr, crbB_addr);
60993007c7fb4f226f2db7e250b0ebb114618ab1980ccerion         assign( crbD, binop(Iop_Or32, mkexpr(crbA), mkexpr(crbB)) );
61003007c7fb4f226f2db7e250b0ebb114618ab1980ccerion         break;
61017c2dc7122cd7767e59112254183cf9babd4a1cb3sewardj      case 0x1A1: // crorc   (Cond Reg OR w. Complement, PPC32 p378)
61027c2dc7122cd7767e59112254183cf9babd4a1cb3sewardj         DIP("crorc crb%d,crb%d,crb%d\n", crbD_addr, crbA_addr, crbB_addr);
61037c2dc7122cd7767e59112254183cf9babd4a1cb3sewardj         assign( crbD, binop(Iop_Or32,
61047c2dc7122cd7767e59112254183cf9babd4a1cb3sewardj                             mkexpr(crbA),
61057c2dc7122cd7767e59112254183cf9babd4a1cb3sewardj                             unop(Iop_Not32, mkexpr(crbB))) );
61067c2dc7122cd7767e59112254183cf9babd4a1cb3sewardj         break;
6107e9d361ab43518b6dfbd3d846f48859534659dee0cerion      case 0x0C1: // crxor   (Cond Reg XOR, PPC32 p379)
61083007c7fb4f226f2db7e250b0ebb114618ab1980ccerion         DIP("crxor crb%d,crb%d,crb%d\n", crbD_addr, crbA_addr, crbB_addr);
61093007c7fb4f226f2db7e250b0ebb114618ab1980ccerion         assign( crbD, binop(Iop_Xor32, mkexpr(crbA), mkexpr(crbB)) );
61103007c7fb4f226f2db7e250b0ebb114618ab1980ccerion         break;
61113007c7fb4f226f2db7e250b0ebb114618ab1980ccerion      default:
61125b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion         vex_printf("dis_cond_logic(ppc)(opc2)\n");
61133007c7fb4f226f2db7e250b0ebb114618ab1980ccerion         return False;
61143007c7fb4f226f2db7e250b0ebb114618ab1980ccerion      }
61153007c7fb4f226f2db7e250b0ebb114618ab1980ccerion
6116b51f0f4f33256638ed953156a2635aa739b232f1sewardj      putCRbit( crbD_addr, mkexpr(crbD) );
61173007c7fb4f226f2db7e250b0ebb114618ab1980ccerion   }
61183007c7fb4f226f2db7e250b0ebb114618ab1980ccerion   return True;
61193007c7fb4f226f2db7e250b0ebb114618ab1980ccerion}
61203007c7fb4f226f2db7e250b0ebb114618ab1980ccerion
61213007c7fb4f226f2db7e250b0ebb114618ab1980ccerion
6122334870db22c2eadcaaa48ef8e47337134d150efdsewardj/*
6123334870db22c2eadcaaa48ef8e47337134d150efdsewardj  Trap instructions
6124334870db22c2eadcaaa48ef8e47337134d150efdsewardj*/
6125334870db22c2eadcaaa48ef8e47337134d150efdsewardj
6126334870db22c2eadcaaa48ef8e47337134d150efdsewardj/* Do the code generation for a trap.  Returned Bool is true iff
612759c0d8f0997bd03e0f8d90b9144dc0aeb6fe9a3asewardj   this is an unconditional trap.  If the two arg IRExpr*s are
612859c0d8f0997bd03e0f8d90b9144dc0aeb6fe9a3asewardj   Ity_I32s then the comparison is 32-bit.  If they are Ity_I64s
612959c0d8f0997bd03e0f8d90b9144dc0aeb6fe9a3asewardj   then they are 64-bit, and we must be disassembling 64-bit
613059c0d8f0997bd03e0f8d90b9144dc0aeb6fe9a3asewardj   instructions. */
613159c0d8f0997bd03e0f8d90b9144dc0aeb6fe9a3asewardjstatic Bool do_trap ( UChar TO,
613259c0d8f0997bd03e0f8d90b9144dc0aeb6fe9a3asewardj                      IRExpr* argL0, IRExpr* argR0, Addr64 cia )
6133334870db22c2eadcaaa48ef8e47337134d150efdsewardj{
6134334870db22c2eadcaaa48ef8e47337134d150efdsewardj   IRTemp argL, argR;
6135334870db22c2eadcaaa48ef8e47337134d150efdsewardj   IRExpr *argLe, *argRe, *cond, *tmp;
6136334870db22c2eadcaaa48ef8e47337134d150efdsewardj
613759c0d8f0997bd03e0f8d90b9144dc0aeb6fe9a3asewardj   Bool    is32bit = typeOfIRExpr(irsb->tyenv, argL0 ) == Ity_I32;
613859c0d8f0997bd03e0f8d90b9144dc0aeb6fe9a3asewardj
613959c0d8f0997bd03e0f8d90b9144dc0aeb6fe9a3asewardj   IROp    opAND     = is32bit ? Iop_And32     : Iop_And64;
614059c0d8f0997bd03e0f8d90b9144dc0aeb6fe9a3asewardj   IROp    opOR      = is32bit ? Iop_Or32      : Iop_Or64;
614159c0d8f0997bd03e0f8d90b9144dc0aeb6fe9a3asewardj   IROp    opCMPORDS = is32bit ? Iop_CmpORD32S : Iop_CmpORD64S;
614259c0d8f0997bd03e0f8d90b9144dc0aeb6fe9a3asewardj   IROp    opCMPORDU = is32bit ? Iop_CmpORD32U : Iop_CmpORD64U;
614359c0d8f0997bd03e0f8d90b9144dc0aeb6fe9a3asewardj   IROp    opCMPNE   = is32bit ? Iop_CmpNE32   : Iop_CmpNE64;
614459c0d8f0997bd03e0f8d90b9144dc0aeb6fe9a3asewardj   IROp    opCMPEQ   = is32bit ? Iop_CmpEQ32   : Iop_CmpEQ64;
614559c0d8f0997bd03e0f8d90b9144dc0aeb6fe9a3asewardj   IRExpr* const0    = is32bit ? mkU32(0)      : mkU64(0);
614659c0d8f0997bd03e0f8d90b9144dc0aeb6fe9a3asewardj   IRExpr* const2    = is32bit ? mkU32(2)      : mkU64(2);
614759c0d8f0997bd03e0f8d90b9144dc0aeb6fe9a3asewardj   IRExpr* const4    = is32bit ? mkU32(4)      : mkU64(4);
614859c0d8f0997bd03e0f8d90b9144dc0aeb6fe9a3asewardj   IRExpr* const8    = is32bit ? mkU32(8)      : mkU64(8);
6149334870db22c2eadcaaa48ef8e47337134d150efdsewardj
6150334870db22c2eadcaaa48ef8e47337134d150efdsewardj   const UChar b11100 = 0x1C;
6151334870db22c2eadcaaa48ef8e47337134d150efdsewardj   const UChar b00111 = 0x07;
6152334870db22c2eadcaaa48ef8e47337134d150efdsewardj
615359c0d8f0997bd03e0f8d90b9144dc0aeb6fe9a3asewardj   if (is32bit) {
615459c0d8f0997bd03e0f8d90b9144dc0aeb6fe9a3asewardj      vassert( typeOfIRExpr(irsb->tyenv, argL0) == Ity_I32 );
615559c0d8f0997bd03e0f8d90b9144dc0aeb6fe9a3asewardj      vassert( typeOfIRExpr(irsb->tyenv, argR0) == Ity_I32 );
615659c0d8f0997bd03e0f8d90b9144dc0aeb6fe9a3asewardj   } else {
615759c0d8f0997bd03e0f8d90b9144dc0aeb6fe9a3asewardj      vassert( typeOfIRExpr(irsb->tyenv, argL0) == Ity_I64 );
615859c0d8f0997bd03e0f8d90b9144dc0aeb6fe9a3asewardj      vassert( typeOfIRExpr(irsb->tyenv, argR0) == Ity_I64 );
615959c0d8f0997bd03e0f8d90b9144dc0aeb6fe9a3asewardj      vassert( mode64 );
616059c0d8f0997bd03e0f8d90b9144dc0aeb6fe9a3asewardj   }
616159c0d8f0997bd03e0f8d90b9144dc0aeb6fe9a3asewardj
6162334870db22c2eadcaaa48ef8e47337134d150efdsewardj   if ((TO & b11100) == b11100 || (TO & b00111) == b00111) {
6163334870db22c2eadcaaa48ef8e47337134d150efdsewardj      /* Unconditional trap.  Just do the exit without
6164334870db22c2eadcaaa48ef8e47337134d150efdsewardj         testing the arguments. */
6165334870db22c2eadcaaa48ef8e47337134d150efdsewardj      stmt( IRStmt_Exit(
6166334870db22c2eadcaaa48ef8e47337134d150efdsewardj               binop(opCMPEQ, const0, const0),
61670f50004eefdf1066682a016efb4a57c092ae2da2sewardj               Ijk_SigTRAP,
61683dee849ec7c38746749065e67dc53b75daa7617dsewardj               mode64 ? IRConst_U64(cia) : IRConst_U32((UInt)cia),
61693dee849ec7c38746749065e67dc53b75daa7617dsewardj               OFFB_CIA
6170334870db22c2eadcaaa48ef8e47337134d150efdsewardj      ));
6171334870db22c2eadcaaa48ef8e47337134d150efdsewardj      return True; /* unconditional trap */
6172334870db22c2eadcaaa48ef8e47337134d150efdsewardj   }
6173334870db22c2eadcaaa48ef8e47337134d150efdsewardj
617459c0d8f0997bd03e0f8d90b9144dc0aeb6fe9a3asewardj   if (is32bit) {
61752d19fe35849aa0acb74ee30836b9566999fb53e0sewardj      argL = newTemp(Ity_I32);
61762d19fe35849aa0acb74ee30836b9566999fb53e0sewardj      argR = newTemp(Ity_I32);
6177334870db22c2eadcaaa48ef8e47337134d150efdsewardj   } else {
61782d19fe35849aa0acb74ee30836b9566999fb53e0sewardj      argL = newTemp(Ity_I64);
61792d19fe35849aa0acb74ee30836b9566999fb53e0sewardj      argR = newTemp(Ity_I64);
6180334870db22c2eadcaaa48ef8e47337134d150efdsewardj   }
618159c0d8f0997bd03e0f8d90b9144dc0aeb6fe9a3asewardj
618259c0d8f0997bd03e0f8d90b9144dc0aeb6fe9a3asewardj   assign( argL, argL0 );
618359c0d8f0997bd03e0f8d90b9144dc0aeb6fe9a3asewardj   assign( argR, argR0 );
618459c0d8f0997bd03e0f8d90b9144dc0aeb6fe9a3asewardj
6185334870db22c2eadcaaa48ef8e47337134d150efdsewardj   argLe = mkexpr(argL);
6186334870db22c2eadcaaa48ef8e47337134d150efdsewardj   argRe = mkexpr(argR);
618759c0d8f0997bd03e0f8d90b9144dc0aeb6fe9a3asewardj
6188334870db22c2eadcaaa48ef8e47337134d150efdsewardj   cond = const0;
6189334870db22c2eadcaaa48ef8e47337134d150efdsewardj   if (TO & 16) { // L <s R
6190334870db22c2eadcaaa48ef8e47337134d150efdsewardj      tmp = binop(opAND, binop(opCMPORDS, argLe, argRe), const8);
6191334870db22c2eadcaaa48ef8e47337134d150efdsewardj      cond = binop(opOR, tmp, cond);
6192334870db22c2eadcaaa48ef8e47337134d150efdsewardj   }
6193334870db22c2eadcaaa48ef8e47337134d150efdsewardj   if (TO & 8) { // L >s R
6194334870db22c2eadcaaa48ef8e47337134d150efdsewardj      tmp = binop(opAND, binop(opCMPORDS, argLe, argRe), const4);
6195334870db22c2eadcaaa48ef8e47337134d150efdsewardj      cond = binop(opOR, tmp, cond);
6196334870db22c2eadcaaa48ef8e47337134d150efdsewardj   }
6197334870db22c2eadcaaa48ef8e47337134d150efdsewardj   if (TO & 4) { // L == R
6198334870db22c2eadcaaa48ef8e47337134d150efdsewardj      tmp = binop(opAND, binop(opCMPORDS, argLe, argRe), const2);
6199334870db22c2eadcaaa48ef8e47337134d150efdsewardj      cond = binop(opOR, tmp, cond);
6200334870db22c2eadcaaa48ef8e47337134d150efdsewardj   }
6201334870db22c2eadcaaa48ef8e47337134d150efdsewardj   if (TO & 2) { // L <u R
6202334870db22c2eadcaaa48ef8e47337134d150efdsewardj      tmp = binop(opAND, binop(opCMPORDU, argLe, argRe), const8);
6203334870db22c2eadcaaa48ef8e47337134d150efdsewardj      cond = binop(opOR, tmp, cond);
6204334870db22c2eadcaaa48ef8e47337134d150efdsewardj   }
6205334870db22c2eadcaaa48ef8e47337134d150efdsewardj   if (TO & 1) { // L >u R
6206334870db22c2eadcaaa48ef8e47337134d150efdsewardj      tmp = binop(opAND, binop(opCMPORDU, argLe, argRe), const4);
6207334870db22c2eadcaaa48ef8e47337134d150efdsewardj      cond = binop(opOR, tmp, cond);
6208334870db22c2eadcaaa48ef8e47337134d150efdsewardj   }
6209334870db22c2eadcaaa48ef8e47337134d150efdsewardj   stmt( IRStmt_Exit(
6210334870db22c2eadcaaa48ef8e47337134d150efdsewardj            binop(opCMPNE, cond, const0),
62110f50004eefdf1066682a016efb4a57c092ae2da2sewardj            Ijk_SigTRAP,
62123dee849ec7c38746749065e67dc53b75daa7617dsewardj            mode64 ? IRConst_U64(cia) : IRConst_U32((UInt)cia),
62133dee849ec7c38746749065e67dc53b75daa7617dsewardj            OFFB_CIA
6214334870db22c2eadcaaa48ef8e47337134d150efdsewardj   ));
6215334870db22c2eadcaaa48ef8e47337134d150efdsewardj   return False; /* not an unconditional trap */
6216334870db22c2eadcaaa48ef8e47337134d150efdsewardj}
6217334870db22c2eadcaaa48ef8e47337134d150efdsewardj
6218334870db22c2eadcaaa48ef8e47337134d150efdsewardjstatic Bool dis_trapi ( UInt theInstr,
6219334870db22c2eadcaaa48ef8e47337134d150efdsewardj                        /*OUT*/DisResult* dres )
6220334870db22c2eadcaaa48ef8e47337134d150efdsewardj{
6221334870db22c2eadcaaa48ef8e47337134d150efdsewardj   /* D-Form */
6222334870db22c2eadcaaa48ef8e47337134d150efdsewardj   UChar  opc1    = ifieldOPC(theInstr);
6223334870db22c2eadcaaa48ef8e47337134d150efdsewardj   UChar  TO      = ifieldRegDS(theInstr);
6224334870db22c2eadcaaa48ef8e47337134d150efdsewardj   UChar  rA_addr = ifieldRegA(theInstr);
6225334870db22c2eadcaaa48ef8e47337134d150efdsewardj   UInt   uimm16  = ifieldUIMM16(theInstr);
6226334870db22c2eadcaaa48ef8e47337134d150efdsewardj   ULong  simm16  = extend_s_16to64(uimm16);
6227334870db22c2eadcaaa48ef8e47337134d150efdsewardj   Addr64 cia     = guest_CIA_curr_instr;
6228334870db22c2eadcaaa48ef8e47337134d150efdsewardj   IRType ty      = mode64 ? Ity_I64 : Ity_I32;
6229334870db22c2eadcaaa48ef8e47337134d150efdsewardj   Bool   uncond  = False;
6230334870db22c2eadcaaa48ef8e47337134d150efdsewardj
6231334870db22c2eadcaaa48ef8e47337134d150efdsewardj   switch (opc1) {
6232334870db22c2eadcaaa48ef8e47337134d150efdsewardj   case 0x03: // twi  (Trap Word Immediate, PPC32 p548)
623359c0d8f0997bd03e0f8d90b9144dc0aeb6fe9a3asewardj      uncond = do_trap( TO,
623459c0d8f0997bd03e0f8d90b9144dc0aeb6fe9a3asewardj                        mode64 ? unop(Iop_64to32, getIReg(rA_addr))
623559c0d8f0997bd03e0f8d90b9144dc0aeb6fe9a3asewardj                               : getIReg(rA_addr),
6236b4f6d6b956f46b7aad27a0ff694d17ae9f34a2f0sewardj                        mkU32( (UInt)simm16 ),
623759c0d8f0997bd03e0f8d90b9144dc0aeb6fe9a3asewardj                        cia );
6238334870db22c2eadcaaa48ef8e47337134d150efdsewardj      if (TO == 4) {
6239b173774421d015736c2316b5e6e998e7de545a5cflorian         DIP("tweqi r%u,%d\n", rA_addr, (Int)simm16);
6240334870db22c2eadcaaa48ef8e47337134d150efdsewardj      } else {
6241b173774421d015736c2316b5e6e998e7de545a5cflorian         DIP("tw%di r%u,%d\n", TO, rA_addr, (Int)simm16);
6242334870db22c2eadcaaa48ef8e47337134d150efdsewardj      }
6243334870db22c2eadcaaa48ef8e47337134d150efdsewardj      break;
6244334870db22c2eadcaaa48ef8e47337134d150efdsewardj   case 0x02: // tdi
6245334870db22c2eadcaaa48ef8e47337134d150efdsewardj      if (!mode64)
6246334870db22c2eadcaaa48ef8e47337134d150efdsewardj         return False;
624759c0d8f0997bd03e0f8d90b9144dc0aeb6fe9a3asewardj      uncond = do_trap( TO, getIReg(rA_addr), mkU64( (ULong)simm16 ), cia );
62482d19fe35849aa0acb74ee30836b9566999fb53e0sewardj      if (TO == 4) {
6249b173774421d015736c2316b5e6e998e7de545a5cflorian         DIP("tdeqi r%u,%d\n", rA_addr, (Int)simm16);
62502d19fe35849aa0acb74ee30836b9566999fb53e0sewardj      } else {
6251b173774421d015736c2316b5e6e998e7de545a5cflorian         DIP("td%di r%u,%d\n", TO, rA_addr, (Int)simm16);
62522d19fe35849aa0acb74ee30836b9566999fb53e0sewardj      }
6253334870db22c2eadcaaa48ef8e47337134d150efdsewardj      break;
6254334870db22c2eadcaaa48ef8e47337134d150efdsewardj   default:
6255334870db22c2eadcaaa48ef8e47337134d150efdsewardj      return False;
6256334870db22c2eadcaaa48ef8e47337134d150efdsewardj   }
6257334870db22c2eadcaaa48ef8e47337134d150efdsewardj
6258334870db22c2eadcaaa48ef8e47337134d150efdsewardj   if (uncond) {
6259334870db22c2eadcaaa48ef8e47337134d150efdsewardj      /* If the trap shows signs of being unconditional, don't
6260334870db22c2eadcaaa48ef8e47337134d150efdsewardj         continue decoding past it. */
62613dee849ec7c38746749065e67dc53b75daa7617dsewardj      putGST( PPC_GST_CIA, mkSzImm( ty, nextInsnAddr() ));
62623dee849ec7c38746749065e67dc53b75daa7617dsewardj      dres->jk_StopHere = Ijk_Boring;
62633dee849ec7c38746749065e67dc53b75daa7617dsewardj      dres->whatNext    = Dis_StopHere;
6264334870db22c2eadcaaa48ef8e47337134d150efdsewardj   }
6265334870db22c2eadcaaa48ef8e47337134d150efdsewardj
6266334870db22c2eadcaaa48ef8e47337134d150efdsewardj   return True;
6267334870db22c2eadcaaa48ef8e47337134d150efdsewardj}
6268334870db22c2eadcaaa48ef8e47337134d150efdsewardj
626959c0d8f0997bd03e0f8d90b9144dc0aeb6fe9a3asewardjstatic Bool dis_trap ( UInt theInstr,
627059c0d8f0997bd03e0f8d90b9144dc0aeb6fe9a3asewardj                        /*OUT*/DisResult* dres )
627159c0d8f0997bd03e0f8d90b9144dc0aeb6fe9a3asewardj{
627259c0d8f0997bd03e0f8d90b9144dc0aeb6fe9a3asewardj   /* X-Form */
627359c0d8f0997bd03e0f8d90b9144dc0aeb6fe9a3asewardj   UInt   opc2    = ifieldOPClo10(theInstr);
627459c0d8f0997bd03e0f8d90b9144dc0aeb6fe9a3asewardj   UChar  TO      = ifieldRegDS(theInstr);
627559c0d8f0997bd03e0f8d90b9144dc0aeb6fe9a3asewardj   UChar  rA_addr = ifieldRegA(theInstr);
627659c0d8f0997bd03e0f8d90b9144dc0aeb6fe9a3asewardj   UChar  rB_addr = ifieldRegB(theInstr);
627759c0d8f0997bd03e0f8d90b9144dc0aeb6fe9a3asewardj   Addr64 cia     = guest_CIA_curr_instr;
627859c0d8f0997bd03e0f8d90b9144dc0aeb6fe9a3asewardj   IRType ty      = mode64 ? Ity_I64 : Ity_I32;
627959c0d8f0997bd03e0f8d90b9144dc0aeb6fe9a3asewardj   Bool   uncond  = False;
628059c0d8f0997bd03e0f8d90b9144dc0aeb6fe9a3asewardj
628159c0d8f0997bd03e0f8d90b9144dc0aeb6fe9a3asewardj   if (ifieldBIT0(theInstr) != 0)
628259c0d8f0997bd03e0f8d90b9144dc0aeb6fe9a3asewardj      return False;
628359c0d8f0997bd03e0f8d90b9144dc0aeb6fe9a3asewardj
628459c0d8f0997bd03e0f8d90b9144dc0aeb6fe9a3asewardj   switch (opc2) {
628559c0d8f0997bd03e0f8d90b9144dc0aeb6fe9a3asewardj   case 0x004: // tw  (Trap Word, PPC64 p540)
628659c0d8f0997bd03e0f8d90b9144dc0aeb6fe9a3asewardj      uncond = do_trap( TO,
628759c0d8f0997bd03e0f8d90b9144dc0aeb6fe9a3asewardj                        mode64 ? unop(Iop_64to32, getIReg(rA_addr))
628859c0d8f0997bd03e0f8d90b9144dc0aeb6fe9a3asewardj                               : getIReg(rA_addr),
628959c0d8f0997bd03e0f8d90b9144dc0aeb6fe9a3asewardj                        mode64 ? unop(Iop_64to32, getIReg(rB_addr))
629059c0d8f0997bd03e0f8d90b9144dc0aeb6fe9a3asewardj                               : getIReg(rB_addr),
629159c0d8f0997bd03e0f8d90b9144dc0aeb6fe9a3asewardj                        cia );
629259c0d8f0997bd03e0f8d90b9144dc0aeb6fe9a3asewardj      if (TO == 4) {
6293b173774421d015736c2316b5e6e998e7de545a5cflorian         DIP("tweq r%u,r%u\n", rA_addr, rB_addr);
629459c0d8f0997bd03e0f8d90b9144dc0aeb6fe9a3asewardj      } else {
6295b173774421d015736c2316b5e6e998e7de545a5cflorian         DIP("tw%d r%u,r%u\n", TO, rA_addr, rB_addr);
629659c0d8f0997bd03e0f8d90b9144dc0aeb6fe9a3asewardj      }
629759c0d8f0997bd03e0f8d90b9144dc0aeb6fe9a3asewardj      break;
6298b4f6d6b956f46b7aad27a0ff694d17ae9f34a2f0sewardj   case 0x044: // td (Trap Doubleword, PPC64 p534)
6299b4f6d6b956f46b7aad27a0ff694d17ae9f34a2f0sewardj      if (!mode64)
6300b4f6d6b956f46b7aad27a0ff694d17ae9f34a2f0sewardj         return False;
6301b4f6d6b956f46b7aad27a0ff694d17ae9f34a2f0sewardj      uncond = do_trap( TO, getIReg(rA_addr), getIReg(rB_addr), cia );
6302b4f6d6b956f46b7aad27a0ff694d17ae9f34a2f0sewardj      if (TO == 4) {
6303b173774421d015736c2316b5e6e998e7de545a5cflorian         DIP("tdeq r%u,r%u\n", rA_addr, rB_addr);
6304b4f6d6b956f46b7aad27a0ff694d17ae9f34a2f0sewardj      } else {
6305b173774421d015736c2316b5e6e998e7de545a5cflorian         DIP("td%d r%u,r%u\n", TO, rA_addr, rB_addr);
6306b4f6d6b956f46b7aad27a0ff694d17ae9f34a2f0sewardj      }
6307b4f6d6b956f46b7aad27a0ff694d17ae9f34a2f0sewardj      break;
630859c0d8f0997bd03e0f8d90b9144dc0aeb6fe9a3asewardj   default:
630959c0d8f0997bd03e0f8d90b9144dc0aeb6fe9a3asewardj      return False;
631059c0d8f0997bd03e0f8d90b9144dc0aeb6fe9a3asewardj   }
631159c0d8f0997bd03e0f8d90b9144dc0aeb6fe9a3asewardj
631259c0d8f0997bd03e0f8d90b9144dc0aeb6fe9a3asewardj   if (uncond) {
631359c0d8f0997bd03e0f8d90b9144dc0aeb6fe9a3asewardj      /* If the trap shows signs of being unconditional, don't
631459c0d8f0997bd03e0f8d90b9144dc0aeb6fe9a3asewardj         continue decoding past it. */
63153dee849ec7c38746749065e67dc53b75daa7617dsewardj      putGST( PPC_GST_CIA, mkSzImm( ty, nextInsnAddr() ));
63163dee849ec7c38746749065e67dc53b75daa7617dsewardj      dres->jk_StopHere = Ijk_Boring;
63173dee849ec7c38746749065e67dc53b75daa7617dsewardj      dres->whatNext    = Dis_StopHere;
631859c0d8f0997bd03e0f8d90b9144dc0aeb6fe9a3asewardj   }
631959c0d8f0997bd03e0f8d90b9144dc0aeb6fe9a3asewardj
632059c0d8f0997bd03e0f8d90b9144dc0aeb6fe9a3asewardj   return True;
632159c0d8f0997bd03e0f8d90b9144dc0aeb6fe9a3asewardj}
632259c0d8f0997bd03e0f8d90b9144dc0aeb6fe9a3asewardj
6323334870db22c2eadcaaa48ef8e47337134d150efdsewardj
63243d870a39e4d145e2f3d9f9a0eeed3475ec934ac1cerion/*
63253d870a39e4d145e2f3d9f9a0eeed3475ec934ac1cerion  System Linkage Instructions
63263d870a39e4d145e2f3d9f9a0eeed3475ec934ac1cerion*/
6327aca070a5b3418a6a9b01e3c57a7eb0fbb5050908sewardjstatic Bool dis_syslink ( UInt theInstr,
6328cacba8e675988fbf21b08feea1f317a9c896c053florian                          const VexAbiInfo* abiinfo, DisResult* dres )
63298c3addacc8343f5d1504379e303934f8ed88903ecerion{
6330d953ebb9b04cbad6891676df597bf0c542b1ec89cerion   IRType ty = mode64 ? Ity_I64 : Ity_I32;
6331d953ebb9b04cbad6891676df597bf0c542b1ec89cerion
6332b85e8bba97fdae7d892f7bfd12e4601307e4721dcerion   if (theInstr != 0x44000002) {
63335b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion      vex_printf("dis_syslink(ppc)(theInstr)\n");
6334b85e8bba97fdae7d892f7bfd12e4601307e4721dcerion      return False;
6335b85e8bba97fdae7d892f7bfd12e4601307e4721dcerion   }
633626d07b26a184d98e37e872f129f0755567f5a966cerion
6337e9d361ab43518b6dfbd3d846f48859534659dee0cerion   // sc  (System Call, PPC32 p504)
6338b85e8bba97fdae7d892f7bfd12e4601307e4721dcerion   DIP("sc\n");
6339aca070a5b3418a6a9b01e3c57a7eb0fbb5050908sewardj
63402322360949754bdcaa87e5ea704480e0b267b09aflorian   /* Copy CIA into the IP_AT_SYSCALL pseudo-register, so that on Darwin
6341aca070a5b3418a6a9b01e3c57a7eb0fbb5050908sewardj      Valgrind can back the guest up to this instruction if it needs
6342aca070a5b3418a6a9b01e3c57a7eb0fbb5050908sewardj      to restart the syscall. */
6343e86310f555a233cc2ca02e1a5d0adb555f12bdcdsewardj   putGST( PPC_GST_IP_AT_SYSCALL, getGST( PPC_GST_CIA ) );
6344aca070a5b3418a6a9b01e3c57a7eb0fbb5050908sewardj
6345b85e8bba97fdae7d892f7bfd12e4601307e4721dcerion   /* It's important that all ArchRegs carry their up-to-date value
6346b85e8bba97fdae7d892f7bfd12e4601307e4721dcerion      at this point.  So we declare an end-of-block here, which
6347b85e8bba97fdae7d892f7bfd12e4601307e4721dcerion      forces any TempRegs caching ArchRegs to be flushed. */
6348d1526f226f529c916d2868d10d52194f7e6b7235sewardj   putGST( PPC_GST_CIA, mkSzImm( ty, nextInsnAddr() ));
6349d953ebb9b04cbad6891676df597bf0c542b1ec89cerion
63503dee849ec7c38746749065e67dc53b75daa7617dsewardj   dres->whatNext    = Dis_StopHere;
63513dee849ec7c38746749065e67dc53b75daa7617dsewardj   dres->jk_StopHere = Ijk_Sys_syscall;
6352b85e8bba97fdae7d892f7bfd12e4601307e4721dcerion   return True;
635326d07b26a184d98e37e872f129f0755567f5a966cerion}
63548c3addacc8343f5d1504379e303934f8ed88903ecerion
63553d870a39e4d145e2f3d9f9a0eeed3475ec934ac1cerion
63563d870a39e4d145e2f3d9f9a0eeed3475ec934ac1cerion/*
63573d870a39e4d145e2f3d9f9a0eeed3475ec934ac1cerion  Memory Synchronization Instructions
635807b07a966a2fdbcf621251a0c1a8ab84807fb120cerion
635907b07a966a2fdbcf621251a0c1a8ab84807fb120cerion  Note on Reservations:
636007b07a966a2fdbcf621251a0c1a8ab84807fb120cerion  We rely on the assumption that V will in fact only allow one thread at
636107b07a966a2fdbcf621251a0c1a8ab84807fb120cerion  once to run.  In effect, a thread can make a reservation, but we don't
636207b07a966a2fdbcf621251a0c1a8ab84807fb120cerion  check any stores it does.  Instead, the reservation is cancelled when
636307b07a966a2fdbcf621251a0c1a8ab84807fb120cerion  the scheduler switches to another thread (run_thread_for_a_while()).
63643d870a39e4d145e2f3d9f9a0eeed3475ec934ac1cerion*/
63658c3addacc8343f5d1504379e303934f8ed88903ecerionstatic Bool dis_memsync ( UInt theInstr )
63668c3addacc8343f5d1504379e303934f8ed88903ecerion{
6367b85e8bba97fdae7d892f7bfd12e4601307e4721dcerion   /* X-Form, XL-Form */
6368d953ebb9b04cbad6891676df597bf0c542b1ec89cerion   UChar opc1    = ifieldOPC(theInstr);
6369d953ebb9b04cbad6891676df597bf0c542b1ec89cerion   UInt  b11to25 = IFIELD(theInstr, 11, 15);
6370e43bc8814b02d099f5758845b9ce10049b14dab3cerion   UChar flag_L  = ifieldRegDS(theInstr);
6371e43bc8814b02d099f5758845b9ce10049b14dab3cerion   UInt  b11to20 = IFIELD(theInstr, 11, 10);
6372ae34a19cda45bacc79ceed5e3018787f9e40be58carll   UInt  M0      = IFIELD(theInstr, 11, 5);
6373d953ebb9b04cbad6891676df597bf0c542b1ec89cerion   UChar rD_addr = ifieldRegDS(theInstr);
6374d953ebb9b04cbad6891676df597bf0c542b1ec89cerion   UChar rS_addr = rD_addr;
6375d953ebb9b04cbad6891676df597bf0c542b1ec89cerion   UChar rA_addr = ifieldRegA(theInstr);
6376d953ebb9b04cbad6891676df597bf0c542b1ec89cerion   UChar rB_addr = ifieldRegB(theInstr);
6377d953ebb9b04cbad6891676df597bf0c542b1ec89cerion   UInt  opc2    = ifieldOPClo10(theInstr);
6378d953ebb9b04cbad6891676df597bf0c542b1ec89cerion   UChar b0      = ifieldBIT0(theInstr);
6379d953ebb9b04cbad6891676df597bf0c542b1ec89cerion
6380d953ebb9b04cbad6891676df597bf0c542b1ec89cerion   IRType ty     = mode64 ? Ity_I64 : Ity_I32;
6381d953ebb9b04cbad6891676df597bf0c542b1ec89cerion   IRTemp EA     = newTemp(ty);
6382d953ebb9b04cbad6891676df597bf0c542b1ec89cerion
6383d953ebb9b04cbad6891676df597bf0c542b1ec89cerion   assign( EA, ea_rAor0_idxd( rA_addr, rB_addr ) );
6384edf7fc572e2decb93e9143961e8739c8fe18899dcerion
6385b85e8bba97fdae7d892f7bfd12e4601307e4721dcerion   switch (opc1) {
6386afe85831d73e546e483dfc51964409b7ecd7c5fesewardj   /* XL-Form */
6387e9d361ab43518b6dfbd3d846f48859534659dee0cerion   case 0x13:   // isync (Instruction Synchronize, PPC32 p432)
6388b85e8bba97fdae7d892f7bfd12e4601307e4721dcerion      if (opc2 != 0x096) {
63895b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion         vex_printf("dis_memsync(ppc)(0x13,opc2)\n");
6390b85e8bba97fdae7d892f7bfd12e4601307e4721dcerion         return False;
6391b85e8bba97fdae7d892f7bfd12e4601307e4721dcerion      }
6392b85e8bba97fdae7d892f7bfd12e4601307e4721dcerion      if (b11to25 != 0 || b0 != 0) {
63935b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion         vex_printf("dis_memsync(ppc)(0x13,b11to25|b0)\n");
6394b85e8bba97fdae7d892f7bfd12e4601307e4721dcerion         return False;
6395b85e8bba97fdae7d892f7bfd12e4601307e4721dcerion      }
6396b85e8bba97fdae7d892f7bfd12e4601307e4721dcerion      DIP("isync\n");
6397c4356f0d3c74fc2622dbeed79c6c1045fc519f72sewardj      stmt( IRStmt_MBE(Imbe_Fence) );
6398b85e8bba97fdae7d892f7bfd12e4601307e4721dcerion      break;
6399b85e8bba97fdae7d892f7bfd12e4601307e4721dcerion
6400b85e8bba97fdae7d892f7bfd12e4601307e4721dcerion   /* X-Form */
6401b85e8bba97fdae7d892f7bfd12e4601307e4721dcerion   case 0x1F:
6402b85e8bba97fdae7d892f7bfd12e4601307e4721dcerion      switch (opc2) {
6403ae34a19cda45bacc79ceed5e3018787f9e40be58carll      case 0x356: // eieio or mbar (Enforce In-Order Exec of I/O, PPC32 p394)
6404ae34a19cda45bacc79ceed5e3018787f9e40be58carll         if (M0 == 0) {
6405ae34a19cda45bacc79ceed5e3018787f9e40be58carll            if (b11to20 != 0 || b0 != 0) {
6406ae34a19cda45bacc79ceed5e3018787f9e40be58carll               vex_printf("dis_memsync(ppc)(eieio,b11to20|b0)\n");
6407ae34a19cda45bacc79ceed5e3018787f9e40be58carll               return False;
6408ae34a19cda45bacc79ceed5e3018787f9e40be58carll            }
6409ae34a19cda45bacc79ceed5e3018787f9e40be58carll            DIP("eieio\n");
6410ae34a19cda45bacc79ceed5e3018787f9e40be58carll         } else {
6411ae34a19cda45bacc79ceed5e3018787f9e40be58carll            if (b11to20 != 0 || b0 != 0) {
6412ae34a19cda45bacc79ceed5e3018787f9e40be58carll               vex_printf("dis_memsync(ppc)(mbar,b11to20|b0)\n");
6413ae34a19cda45bacc79ceed5e3018787f9e40be58carll               return False;
6414ae34a19cda45bacc79ceed5e3018787f9e40be58carll            }
6415ae34a19cda45bacc79ceed5e3018787f9e40be58carll            DIP("mbar %d\n", M0);
64167787af415a9104b601c2f0ce5b56749e4fd86691sewardj         }
64177787af415a9104b601c2f0ce5b56749e4fd86691sewardj         /* Insert a memory fence, just to be on the safe side. */
6418c4356f0d3c74fc2622dbeed79c6c1045fc519f72sewardj         stmt( IRStmt_MBE(Imbe_Fence) );
64197787af415a9104b601c2f0ce5b56749e4fd86691sewardj         break;
6420b85e8bba97fdae7d892f7bfd12e4601307e4721dcerion
6421e768e92e054cde495849a5c842a477d287677f78sewardj      case 0x014: { // lwarx (Load Word and Reserve Indexed, PPC32 p458)
6422e768e92e054cde495849a5c842a477d287677f78sewardj         IRTemp res;
6423fe397a2c1c7f6594f305a90c51f9859778348760sewardj         /* According to the PowerPC ISA version 2.05, b0 (called EH
6424fe397a2c1c7f6594f305a90c51f9859778348760sewardj            in the documentation) is merely a hint bit to the
6425fe397a2c1c7f6594f305a90c51f9859778348760sewardj            hardware, I think as to whether or not contention is
6426fe397a2c1c7f6594f305a90c51f9859778348760sewardj            likely.  So we can just ignore it. */
6427b173774421d015736c2316b5e6e998e7de545a5cflorian         DIP("lwarx r%u,r%u,r%u,EH=%u\n", rD_addr, rA_addr, rB_addr, b0);
6428e9d8a26b690c2561ac54ab0cd6ad83ecbadcbe76sewardj
6429e9d8a26b690c2561ac54ab0cd6ad83ecbadcbe76sewardj         // trap if misaligned
6430e9d8a26b690c2561ac54ab0cd6ad83ecbadcbe76sewardj         gen_SIGBUS_if_misaligned( EA, 4 );
6431e9d8a26b690c2561ac54ab0cd6ad83ecbadcbe76sewardj
6432e9d8a26b690c2561ac54ab0cd6ad83ecbadcbe76sewardj         // and actually do the load
6433e768e92e054cde495849a5c842a477d287677f78sewardj         res = newTemp(Ity_I32);
64341f5fe1fc3a37ca729925e8eec25aa1025b4a6cdbcarll         stmt( stmt_load(res, mkexpr(EA), NULL/*this is a load*/) );
6435e768e92e054cde495849a5c842a477d287677f78sewardj
6436e768e92e054cde495849a5c842a477d287677f78sewardj         putIReg( rD_addr, mkWidenFrom32(ty, mkexpr(res), False) );
6437b85e8bba97fdae7d892f7bfd12e4601307e4721dcerion         break;
6438e768e92e054cde495849a5c842a477d287677f78sewardj      }
6439e768e92e054cde495849a5c842a477d287677f78sewardj
6440d826889bd512ded2fbbc4781c595ecf0513f46f6carll      case 0x034: { // lbarx (Load Word and Reserve Indexed)
6441d826889bd512ded2fbbc4781c595ecf0513f46f6carll         IRTemp res;
6442d826889bd512ded2fbbc4781c595ecf0513f46f6carll         /* According to the PowerPC ISA version 2.05, b0 (called EH
6443d826889bd512ded2fbbc4781c595ecf0513f46f6carll            in the documentation) is merely a hint bit to the
6444d826889bd512ded2fbbc4781c595ecf0513f46f6carll            hardware, I think as to whether or not contention is
6445d826889bd512ded2fbbc4781c595ecf0513f46f6carll            likely.  So we can just ignore it. */
6446b173774421d015736c2316b5e6e998e7de545a5cflorian         DIP("lbarx r%u,r%u,r%u,EH=%u\n", rD_addr, rA_addr, rB_addr, b0);
6447d826889bd512ded2fbbc4781c595ecf0513f46f6carll
6448d826889bd512ded2fbbc4781c595ecf0513f46f6carll         // and actually do the load
6449d826889bd512ded2fbbc4781c595ecf0513f46f6carll         res = newTemp(Ity_I8);
6450d826889bd512ded2fbbc4781c595ecf0513f46f6carll         stmt( stmt_load(res, mkexpr(EA), NULL/*this is a load*/) );
6451d826889bd512ded2fbbc4781c595ecf0513f46f6carll
6452d826889bd512ded2fbbc4781c595ecf0513f46f6carll         putIReg( rD_addr, mkWidenFrom8(ty, mkexpr(res), False) );
6453d826889bd512ded2fbbc4781c595ecf0513f46f6carll         break;
6454d826889bd512ded2fbbc4781c595ecf0513f46f6carll     }
6455d826889bd512ded2fbbc4781c595ecf0513f46f6carll
6456d826889bd512ded2fbbc4781c595ecf0513f46f6carll      case 0x074: { // lharx (Load Word and Reserve Indexed)
6457d826889bd512ded2fbbc4781c595ecf0513f46f6carll         IRTemp res;
6458d826889bd512ded2fbbc4781c595ecf0513f46f6carll         /* According to the PowerPC ISA version 2.05, b0 (called EH
6459d826889bd512ded2fbbc4781c595ecf0513f46f6carll            in the documentation) is merely a hint bit to the
6460d826889bd512ded2fbbc4781c595ecf0513f46f6carll            hardware, I think as to whether or not contention is
6461d826889bd512ded2fbbc4781c595ecf0513f46f6carll            likely.  So we can just ignore it. */
6462b173774421d015736c2316b5e6e998e7de545a5cflorian         DIP("lharx r%u,r%u,r%u,EH=%u\n", rD_addr, rA_addr, rB_addr, b0);
6463d826889bd512ded2fbbc4781c595ecf0513f46f6carll
6464d826889bd512ded2fbbc4781c595ecf0513f46f6carll         // trap if misaligned
6465d826889bd512ded2fbbc4781c595ecf0513f46f6carll         gen_SIGBUS_if_misaligned( EA, 2 );
6466d826889bd512ded2fbbc4781c595ecf0513f46f6carll
6467d826889bd512ded2fbbc4781c595ecf0513f46f6carll         // and actually do the load
6468d826889bd512ded2fbbc4781c595ecf0513f46f6carll         res = newTemp(Ity_I16);
6469d826889bd512ded2fbbc4781c595ecf0513f46f6carll         stmt( stmt_load(res, mkexpr(EA), NULL/*this is a load*/) );
6470d826889bd512ded2fbbc4781c595ecf0513f46f6carll
6471d826889bd512ded2fbbc4781c595ecf0513f46f6carll         putIReg( rD_addr, mkWidenFrom16(ty, mkexpr(res), False) );
6472d826889bd512ded2fbbc4781c595ecf0513f46f6carll         break;
6473d826889bd512ded2fbbc4781c595ecf0513f46f6carll      }
6474d826889bd512ded2fbbc4781c595ecf0513f46f6carll
64757787af415a9104b601c2f0ce5b56749e4fd86691sewardj      case 0x096: {
64767787af415a9104b601c2f0ce5b56749e4fd86691sewardj         // stwcx. (Store Word Conditional Indexed, PPC32 p532)
6477e9d8a26b690c2561ac54ab0cd6ad83ecbadcbe76sewardj         // Note this has to handle stwcx. in both 32- and 64-bit modes,
6478e9d8a26b690c2561ac54ab0cd6ad83ecbadcbe76sewardj         // so isn't quite as straightforward as it might otherwise be.
6479e9d8a26b690c2561ac54ab0cd6ad83ecbadcbe76sewardj         IRTemp rS = newTemp(Ity_I32);
6480e9d8a26b690c2561ac54ab0cd6ad83ecbadcbe76sewardj         IRTemp resSC;
6481b85e8bba97fdae7d892f7bfd12e4601307e4721dcerion         if (b0 != 1) {
64825b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion            vex_printf("dis_memsync(ppc)(stwcx.,b0)\n");
6483b85e8bba97fdae7d892f7bfd12e4601307e4721dcerion            return False;
6484b85e8bba97fdae7d892f7bfd12e4601307e4721dcerion         }
6485d953ebb9b04cbad6891676df597bf0c542b1ec89cerion         DIP("stwcx. r%u,r%u,r%u\n", rS_addr, rA_addr, rB_addr);
6486afe85831d73e546e483dfc51964409b7ecd7c5fesewardj
6487e9d8a26b690c2561ac54ab0cd6ad83ecbadcbe76sewardj         // trap if misaligned
6488e9d8a26b690c2561ac54ab0cd6ad83ecbadcbe76sewardj         gen_SIGBUS_if_misaligned( EA, 4 );
64897787af415a9104b601c2f0ce5b56749e4fd86691sewardj
6490e9d8a26b690c2561ac54ab0cd6ad83ecbadcbe76sewardj         // Get the data to be stored, and narrow to 32 bits if necessary
6491e9d8a26b690c2561ac54ab0cd6ad83ecbadcbe76sewardj         assign( rS, mkNarrowTo32(ty, getIReg(rS_addr)) );
64927787af415a9104b601c2f0ce5b56749e4fd86691sewardj
6493e9d8a26b690c2561ac54ab0cd6ad83ecbadcbe76sewardj         // Do the store, and get success/failure bit into resSC
6494e9d8a26b690c2561ac54ab0cd6ad83ecbadcbe76sewardj         resSC = newTemp(Ity_I1);
64951f5fe1fc3a37ca729925e8eec25aa1025b4a6cdbcarll         stmt( stmt_load( resSC, mkexpr(EA), mkexpr(rS)) );
6496e9d8a26b690c2561ac54ab0cd6ad83ecbadcbe76sewardj
6497e9d8a26b690c2561ac54ab0cd6ad83ecbadcbe76sewardj         // Set CR0[LT GT EQ S0] = 0b000 || XER[SO]  on failure
6498e9d8a26b690c2561ac54ab0cd6ad83ecbadcbe76sewardj         // Set CR0[LT GT EQ S0] = 0b001 || XER[SO]  on success
6499e9d8a26b690c2561ac54ab0cd6ad83ecbadcbe76sewardj         putCR321(0, binop(Iop_Shl8, unop(Iop_1Uto8, mkexpr(resSC)), mkU8(1)));
6500e9d8a26b690c2561ac54ab0cd6ad83ecbadcbe76sewardj         putCR0(0, getXER_SO());
6501d953ebb9b04cbad6891676df597bf0c542b1ec89cerion
6502e9d8a26b690c2561ac54ab0cd6ad83ecbadcbe76sewardj         /* Note:
6503d953ebb9b04cbad6891676df597bf0c542b1ec89cerion            If resaddr != lwarx_resaddr, CR0[EQ] is undefined, and
6504d953ebb9b04cbad6891676df597bf0c542b1ec89cerion            whether rS is stored is dependent on that value. */
6505e9d8a26b690c2561ac54ab0cd6ad83ecbadcbe76sewardj         /* So I guess we can just ignore this case? */
6506b85e8bba97fdae7d892f7bfd12e4601307e4721dcerion         break;
65077787af415a9104b601c2f0ce5b56749e4fd86691sewardj      }
65087787af415a9104b601c2f0ce5b56749e4fd86691sewardj
6509d826889bd512ded2fbbc4781c595ecf0513f46f6carll      case 0x2B6: {
6510d826889bd512ded2fbbc4781c595ecf0513f46f6carll         // stbcx. (Store Byte Conditional Indexed)
6511d826889bd512ded2fbbc4781c595ecf0513f46f6carll         // Note this has to handle stbcx. in both 32- and 64-bit modes,
6512d826889bd512ded2fbbc4781c595ecf0513f46f6carll         // so isn't quite as straightforward as it might otherwise be.
6513d826889bd512ded2fbbc4781c595ecf0513f46f6carll         IRTemp rS = newTemp(Ity_I8);
6514d826889bd512ded2fbbc4781c595ecf0513f46f6carll         IRTemp resSC;
6515d826889bd512ded2fbbc4781c595ecf0513f46f6carll         if (b0 != 1) {
6516d826889bd512ded2fbbc4781c595ecf0513f46f6carll            vex_printf("dis_memsync(ppc)(stbcx.,b0)\n");
6517d826889bd512ded2fbbc4781c595ecf0513f46f6carll            return False;
6518d826889bd512ded2fbbc4781c595ecf0513f46f6carll         }
6519d826889bd512ded2fbbc4781c595ecf0513f46f6carll         DIP("stbcx. r%u,r%u,r%u\n", rS_addr, rA_addr, rB_addr);
6520d826889bd512ded2fbbc4781c595ecf0513f46f6carll
6521d826889bd512ded2fbbc4781c595ecf0513f46f6carll         // Get the data to be stored, and narrow to 32 bits if necessary
6522d826889bd512ded2fbbc4781c595ecf0513f46f6carll         assign( rS, mkNarrowTo8(ty, getIReg(rS_addr)) );
6523d826889bd512ded2fbbc4781c595ecf0513f46f6carll
6524d826889bd512ded2fbbc4781c595ecf0513f46f6carll         // Do the store, and get success/failure bit into resSC
6525d826889bd512ded2fbbc4781c595ecf0513f46f6carll         resSC = newTemp(Ity_I1);
6526d826889bd512ded2fbbc4781c595ecf0513f46f6carll         stmt( stmt_load( resSC, mkexpr(EA), mkexpr(rS)) );
6527d826889bd512ded2fbbc4781c595ecf0513f46f6carll
6528d826889bd512ded2fbbc4781c595ecf0513f46f6carll         // Set CR0[LT GT EQ S0] = 0b000 || XER[SO]  on failure
6529d826889bd512ded2fbbc4781c595ecf0513f46f6carll         // Set CR0[LT GT EQ S0] = 0b001 || XER[SO]  on success
6530d826889bd512ded2fbbc4781c595ecf0513f46f6carll         putCR321(0, binop(Iop_Shl8, unop(Iop_1Uto8, mkexpr(resSC)), mkU8(1)));
6531d826889bd512ded2fbbc4781c595ecf0513f46f6carll         putCR0(0, getXER_SO());
6532d826889bd512ded2fbbc4781c595ecf0513f46f6carll
6533d826889bd512ded2fbbc4781c595ecf0513f46f6carll         /* Note:
6534d826889bd512ded2fbbc4781c595ecf0513f46f6carll            If resaddr != lbarx_resaddr, CR0[EQ] is undefined, and
6535d826889bd512ded2fbbc4781c595ecf0513f46f6carll            whether rS is stored is dependent on that value. */
6536d826889bd512ded2fbbc4781c595ecf0513f46f6carll         /* So I guess we can just ignore this case? */
6537d826889bd512ded2fbbc4781c595ecf0513f46f6carll         break;
6538d826889bd512ded2fbbc4781c595ecf0513f46f6carll      }
6539d826889bd512ded2fbbc4781c595ecf0513f46f6carll
6540d826889bd512ded2fbbc4781c595ecf0513f46f6carll      case 0x2D6: {
6541d826889bd512ded2fbbc4781c595ecf0513f46f6carll         // sthcx. (Store Word Conditional Indexed, PPC32 p532)
6542d826889bd512ded2fbbc4781c595ecf0513f46f6carll         // Note this has to handle sthcx. in both 32- and 64-bit modes,
6543d826889bd512ded2fbbc4781c595ecf0513f46f6carll         // so isn't quite as straightforward as it might otherwise be.
6544d826889bd512ded2fbbc4781c595ecf0513f46f6carll         IRTemp rS = newTemp(Ity_I16);
6545d826889bd512ded2fbbc4781c595ecf0513f46f6carll         IRTemp resSC;
6546d826889bd512ded2fbbc4781c595ecf0513f46f6carll         if (b0 != 1) {
6547d826889bd512ded2fbbc4781c595ecf0513f46f6carll            vex_printf("dis_memsync(ppc)(stwcx.,b0)\n");
6548d826889bd512ded2fbbc4781c595ecf0513f46f6carll            return False;
6549d826889bd512ded2fbbc4781c595ecf0513f46f6carll         }
6550d826889bd512ded2fbbc4781c595ecf0513f46f6carll         DIP("sthcx. r%u,r%u,r%u\n", rS_addr, rA_addr, rB_addr);
6551d826889bd512ded2fbbc4781c595ecf0513f46f6carll
6552d826889bd512ded2fbbc4781c595ecf0513f46f6carll         // trap if misaligned
6553d826889bd512ded2fbbc4781c595ecf0513f46f6carll         gen_SIGBUS_if_misaligned( EA, 2 );
6554d826889bd512ded2fbbc4781c595ecf0513f46f6carll
6555d826889bd512ded2fbbc4781c595ecf0513f46f6carll         // Get the data to be stored, and narrow to 16 bits if necessary
6556d826889bd512ded2fbbc4781c595ecf0513f46f6carll         assign( rS, mkNarrowTo16(ty, getIReg(rS_addr)) );
6557d826889bd512ded2fbbc4781c595ecf0513f46f6carll
6558d826889bd512ded2fbbc4781c595ecf0513f46f6carll         // Do the store, and get success/failure bit into resSC
6559d826889bd512ded2fbbc4781c595ecf0513f46f6carll         resSC = newTemp(Ity_I1);
6560d826889bd512ded2fbbc4781c595ecf0513f46f6carll         stmt( stmt_load( resSC, mkexpr(EA), mkexpr(rS)) );
6561d826889bd512ded2fbbc4781c595ecf0513f46f6carll
6562d826889bd512ded2fbbc4781c595ecf0513f46f6carll         // Set CR0[LT GT EQ S0] = 0b000 || XER[SO]  on failure
6563d826889bd512ded2fbbc4781c595ecf0513f46f6carll         // Set CR0[LT GT EQ S0] = 0b001 || XER[SO]  on success
6564d826889bd512ded2fbbc4781c595ecf0513f46f6carll         putCR321(0, binop(Iop_Shl8, unop(Iop_1Uto8, mkexpr(resSC)), mkU8(1)));
6565d826889bd512ded2fbbc4781c595ecf0513f46f6carll         putCR0(0, getXER_SO());
6566d826889bd512ded2fbbc4781c595ecf0513f46f6carll
6567d826889bd512ded2fbbc4781c595ecf0513f46f6carll         /* Note:
6568d826889bd512ded2fbbc4781c595ecf0513f46f6carll            If resaddr != lharx_resaddr, CR0[EQ] is undefined, and
6569d826889bd512ded2fbbc4781c595ecf0513f46f6carll            whether rS is stored is dependent on that value. */
6570d826889bd512ded2fbbc4781c595ecf0513f46f6carll         /* So I guess we can just ignore this case? */
6571d826889bd512ded2fbbc4781c595ecf0513f46f6carll         break;
6572d826889bd512ded2fbbc4781c595ecf0513f46f6carll      }
6573d826889bd512ded2fbbc4781c595ecf0513f46f6carll
6574b029a61119a84c9a7e32443f14c051c705cc73a0sewardj      case 0x256: // sync (Synchronize, PPC32 p543),
6575e43bc8814b02d099f5758845b9ce10049b14dab3cerion                  // also lwsync (L==1), ptesync (L==2)
6576b029a61119a84c9a7e32443f14c051c705cc73a0sewardj         /* http://sources.redhat.com/ml/binutils/2000-12/msg00311.html
6577b029a61119a84c9a7e32443f14c051c705cc73a0sewardj
6578b029a61119a84c9a7e32443f14c051c705cc73a0sewardj            The PowerPC architecture used in IBM chips has expanded
6579b029a61119a84c9a7e32443f14c051c705cc73a0sewardj            the sync instruction into two variants: lightweight sync
6580b029a61119a84c9a7e32443f14c051c705cc73a0sewardj            and heavyweight sync.  The original sync instruction is
6581b029a61119a84c9a7e32443f14c051c705cc73a0sewardj            the new heavyweight sync and lightweight sync is a strict
6582b029a61119a84c9a7e32443f14c051c705cc73a0sewardj            subset of the heavyweight sync functionality. This allows
6583b029a61119a84c9a7e32443f14c051c705cc73a0sewardj            the programmer to specify a less expensive operation on
6584b029a61119a84c9a7e32443f14c051c705cc73a0sewardj            high-end systems when the full sync functionality is not
6585b029a61119a84c9a7e32443f14c051c705cc73a0sewardj            necessary.
6586b029a61119a84c9a7e32443f14c051c705cc73a0sewardj
6587b029a61119a84c9a7e32443f14c051c705cc73a0sewardj            The basic "sync" mnemonic now utilizes an operand. "sync"
6588b029a61119a84c9a7e32443f14c051c705cc73a0sewardj            without an operand now becomes a extended mnemonic for
6589b029a61119a84c9a7e32443f14c051c705cc73a0sewardj            heavyweight sync.  Processors without the lwsync
6590b029a61119a84c9a7e32443f14c051c705cc73a0sewardj            instruction will not decode the L field and will perform a
6591b029a61119a84c9a7e32443f14c051c705cc73a0sewardj            heavyweight sync.  Everything is backward compatible.
6592b029a61119a84c9a7e32443f14c051c705cc73a0sewardj
6593b029a61119a84c9a7e32443f14c051c705cc73a0sewardj            sync    =       sync 0
6594b029a61119a84c9a7e32443f14c051c705cc73a0sewardj            lwsync  =       sync 1
6595e43bc8814b02d099f5758845b9ce10049b14dab3cerion            ptesync =       sync 2    *** TODO - not implemented ***
65964e2c2b3cacdc79a993f4cec9249d9bffd82e4978cerion         */
6597e43bc8814b02d099f5758845b9ce10049b14dab3cerion         if (b11to20 != 0 || b0 != 0) {
6598e43bc8814b02d099f5758845b9ce10049b14dab3cerion            vex_printf("dis_memsync(ppc)(sync/lwsync,b11to20|b0)\n");
6599b85e8bba97fdae7d892f7bfd12e4601307e4721dcerion            return False;
6600b85e8bba97fdae7d892f7bfd12e4601307e4721dcerion         }
6601e43bc8814b02d099f5758845b9ce10049b14dab3cerion         if (flag_L != 0/*sync*/ && flag_L != 1/*lwsync*/) {
6602e43bc8814b02d099f5758845b9ce10049b14dab3cerion            vex_printf("dis_memsync(ppc)(sync/lwsync,flag_L)\n");
6603e43bc8814b02d099f5758845b9ce10049b14dab3cerion            return False;
6604e43bc8814b02d099f5758845b9ce10049b14dab3cerion         }
6605e43bc8814b02d099f5758845b9ce10049b14dab3cerion         DIP("%ssync\n", flag_L == 1 ? "lw" : "");
6606b85e8bba97fdae7d892f7bfd12e4601307e4721dcerion         /* Insert a memory fence.  It's sometimes important that these
6607b85e8bba97fdae7d892f7bfd12e4601307e4721dcerion            are carried through to the generated code. */
6608c4356f0d3c74fc2622dbeed79c6c1045fc519f72sewardj         stmt( IRStmt_MBE(Imbe_Fence) );
6609b85e8bba97fdae7d892f7bfd12e4601307e4721dcerion         break;
6610f0de28cf1a762b0d6f74c93d3532c89a230673bbcerion
6611f0de28cf1a762b0d6f74c93d3532c89a230673bbcerion      /* 64bit Memsync */
6612e768e92e054cde495849a5c842a477d287677f78sewardj      case 0x054: { // ldarx (Load DWord and Reserve Indexed, PPC64 p473)
6613e768e92e054cde495849a5c842a477d287677f78sewardj         IRTemp res;
6614fe397a2c1c7f6594f305a90c51f9859778348760sewardj         /* According to the PowerPC ISA version 2.05, b0 (called EH
6615fe397a2c1c7f6594f305a90c51f9859778348760sewardj            in the documentation) is merely a hint bit to the
6616fe397a2c1c7f6594f305a90c51f9859778348760sewardj            hardware, I think as to whether or not contention is
6617fe397a2c1c7f6594f305a90c51f9859778348760sewardj            likely.  So we can just ignore it. */
6618e9d8a26b690c2561ac54ab0cd6ad83ecbadcbe76sewardj         if (!mode64)
6619e9d8a26b690c2561ac54ab0cd6ad83ecbadcbe76sewardj            return False;
6620b173774421d015736c2316b5e6e998e7de545a5cflorian         DIP("ldarx r%u,r%u,r%u,EH=%u\n", rD_addr, rA_addr, rB_addr, b0);
6621e9d8a26b690c2561ac54ab0cd6ad83ecbadcbe76sewardj
6622e9d8a26b690c2561ac54ab0cd6ad83ecbadcbe76sewardj         // trap if misaligned
6623e9d8a26b690c2561ac54ab0cd6ad83ecbadcbe76sewardj         gen_SIGBUS_if_misaligned( EA, 8 );
6624e9d8a26b690c2561ac54ab0cd6ad83ecbadcbe76sewardj
6625e9d8a26b690c2561ac54ab0cd6ad83ecbadcbe76sewardj         // and actually do the load
6626e768e92e054cde495849a5c842a477d287677f78sewardj         res = newTemp(Ity_I64);
66271f5fe1fc3a37ca729925e8eec25aa1025b4a6cdbcarll         stmt( stmt_load( res, mkexpr(EA), NULL/*this is a load*/) );
6628e768e92e054cde495849a5c842a477d287677f78sewardj
6629e768e92e054cde495849a5c842a477d287677f78sewardj         putIReg( rD_addr, mkexpr(res) );
663007b07a966a2fdbcf621251a0c1a8ab84807fb120cerion         break;
6631e768e92e054cde495849a5c842a477d287677f78sewardj      }
6632e768e92e054cde495849a5c842a477d287677f78sewardj
66335b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion      case 0x0D6: { // stdcx. (Store DWord Condition Indexd, PPC64 p581)
6634e9d8a26b690c2561ac54ab0cd6ad83ecbadcbe76sewardj         // A marginally simplified version of the stwcx. case
6635e9d8a26b690c2561ac54ab0cd6ad83ecbadcbe76sewardj         IRTemp rS = newTemp(Ity_I64);
6636e9d8a26b690c2561ac54ab0cd6ad83ecbadcbe76sewardj         IRTemp resSC;
6637f0de28cf1a762b0d6f74c93d3532c89a230673bbcerion         if (b0 != 1) {
66385b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion            vex_printf("dis_memsync(ppc)(stdcx.,b0)\n");
6639f0de28cf1a762b0d6f74c93d3532c89a230673bbcerion            return False;
6640f0de28cf1a762b0d6f74c93d3532c89a230673bbcerion         }
6641e9d8a26b690c2561ac54ab0cd6ad83ecbadcbe76sewardj         if (!mode64)
6642e9d8a26b690c2561ac54ab0cd6ad83ecbadcbe76sewardj            return False;
6643f0de28cf1a762b0d6f74c93d3532c89a230673bbcerion         DIP("stdcx. r%u,r%u,r%u\n", rS_addr, rA_addr, rB_addr);
6644e9d8a26b690c2561ac54ab0cd6ad83ecbadcbe76sewardj
6645e9d8a26b690c2561ac54ab0cd6ad83ecbadcbe76sewardj         // trap if misaligned
6646e9d8a26b690c2561ac54ab0cd6ad83ecbadcbe76sewardj         gen_SIGBUS_if_misaligned( EA, 8 );
6647e9d8a26b690c2561ac54ab0cd6ad83ecbadcbe76sewardj
6648e9d8a26b690c2561ac54ab0cd6ad83ecbadcbe76sewardj         // Get the data to be stored
664907b07a966a2fdbcf621251a0c1a8ab84807fb120cerion         assign( rS, getIReg(rS_addr) );
6650f0de28cf1a762b0d6f74c93d3532c89a230673bbcerion
6651e9d8a26b690c2561ac54ab0cd6ad83ecbadcbe76sewardj         // Do the store, and get success/failure bit into resSC
6652e9d8a26b690c2561ac54ab0cd6ad83ecbadcbe76sewardj         resSC = newTemp(Ity_I1);
66531f5fe1fc3a37ca729925e8eec25aa1025b4a6cdbcarll         stmt( stmt_load( resSC, mkexpr(EA), mkexpr(rS)) );
6654e9d8a26b690c2561ac54ab0cd6ad83ecbadcbe76sewardj
6655e9d8a26b690c2561ac54ab0cd6ad83ecbadcbe76sewardj         // Set CR0[LT GT EQ S0] = 0b000 || XER[SO]  on failure
6656e9d8a26b690c2561ac54ab0cd6ad83ecbadcbe76sewardj         // Set CR0[LT GT EQ S0] = 0b001 || XER[SO]  on success
6657e9d8a26b690c2561ac54ab0cd6ad83ecbadcbe76sewardj         putCR321(0, binop(Iop_Shl8, unop(Iop_1Uto8, mkexpr(resSC)), mkU8(1)));
665807b07a966a2fdbcf621251a0c1a8ab84807fb120cerion         putCR0(0, getXER_SO());
6659e9d8a26b690c2561ac54ab0cd6ad83ecbadcbe76sewardj
6660e9d8a26b690c2561ac54ab0cd6ad83ecbadcbe76sewardj         /* Note:
6661e9d8a26b690c2561ac54ab0cd6ad83ecbadcbe76sewardj            If resaddr != lwarx_resaddr, CR0[EQ] is undefined, and
6662e9d8a26b690c2561ac54ab0cd6ad83ecbadcbe76sewardj            whether rS is stored is dependent on that value. */
6663e9d8a26b690c2561ac54ab0cd6ad83ecbadcbe76sewardj         /* So I guess we can just ignore this case? */
666407b07a966a2fdbcf621251a0c1a8ab84807fb120cerion         break;
666507b07a966a2fdbcf621251a0c1a8ab84807fb120cerion      }
666607b07a966a2fdbcf621251a0c1a8ab84807fb120cerion
666778850ae9874a90ea625fcee1fd4c359375b7b538carll      /* 128bit Memsync */
666878850ae9874a90ea625fcee1fd4c359375b7b538carll      case 0x114: { // lqarx (Load QuadWord and Reserve Indexed)
666978850ae9874a90ea625fcee1fd4c359375b7b538carll         IRTemp res_hi = newTemp(ty);
667078850ae9874a90ea625fcee1fd4c359375b7b538carll         IRTemp res_lo = newTemp(ty);
667178850ae9874a90ea625fcee1fd4c359375b7b538carll
667278850ae9874a90ea625fcee1fd4c359375b7b538carll         /* According to the PowerPC ISA version 2.07, b0 (called EH
667378850ae9874a90ea625fcee1fd4c359375b7b538carll            in the documentation) is merely a hint bit to the
667478850ae9874a90ea625fcee1fd4c359375b7b538carll            hardware, I think as to whether or not contention is
667578850ae9874a90ea625fcee1fd4c359375b7b538carll            likely.  So we can just ignore it. */
6676b173774421d015736c2316b5e6e998e7de545a5cflorian         DIP("lqarx r%u,r%u,r%u,EH=%u\n", rD_addr, rA_addr, rB_addr, b0);
667778850ae9874a90ea625fcee1fd4c359375b7b538carll
667878850ae9874a90ea625fcee1fd4c359375b7b538carll         // trap if misaligned
667978850ae9874a90ea625fcee1fd4c359375b7b538carll         gen_SIGBUS_if_misaligned( EA, 16 );
668078850ae9874a90ea625fcee1fd4c359375b7b538carll
668178850ae9874a90ea625fcee1fd4c359375b7b538carll         // and actually do the load
668278850ae9874a90ea625fcee1fd4c359375b7b538carll         if (mode64) {
6683999ef56da3e4426c5f6bf74de40d23ff02dafb34carll            if (host_endness == VexEndnessBE) {
6684999ef56da3e4426c5f6bf74de40d23ff02dafb34carll               stmt( stmt_load( res_hi,
6685999ef56da3e4426c5f6bf74de40d23ff02dafb34carll                                mkexpr(EA), NULL/*this is a load*/) );
6686999ef56da3e4426c5f6bf74de40d23ff02dafb34carll               stmt( stmt_load( res_lo,
6687999ef56da3e4426c5f6bf74de40d23ff02dafb34carll                                binop(Iop_Add64, mkexpr(EA), mkU64(8) ),
6688999ef56da3e4426c5f6bf74de40d23ff02dafb34carll                                NULL/*this is a load*/) );
6689999ef56da3e4426c5f6bf74de40d23ff02dafb34carll	    } else {
6690999ef56da3e4426c5f6bf74de40d23ff02dafb34carll               stmt( stmt_load( res_lo,
6691999ef56da3e4426c5f6bf74de40d23ff02dafb34carll                                mkexpr(EA), NULL/*this is a load*/) );
6692999ef56da3e4426c5f6bf74de40d23ff02dafb34carll               stmt( stmt_load( res_hi,
6693999ef56da3e4426c5f6bf74de40d23ff02dafb34carll                                binop(Iop_Add64, mkexpr(EA), mkU64(8) ),
6694999ef56da3e4426c5f6bf74de40d23ff02dafb34carll                                NULL/*this is a load*/) );
6695999ef56da3e4426c5f6bf74de40d23ff02dafb34carll            }
669678850ae9874a90ea625fcee1fd4c359375b7b538carll         } else {
66971f5fe1fc3a37ca729925e8eec25aa1025b4a6cdbcarll            stmt( stmt_load( res_hi,
66981f5fe1fc3a37ca729925e8eec25aa1025b4a6cdbcarll                             binop( Iop_Add32, mkexpr(EA), mkU32(4) ),
66991f5fe1fc3a37ca729925e8eec25aa1025b4a6cdbcarll                             NULL/*this is a load*/) );
67001f5fe1fc3a37ca729925e8eec25aa1025b4a6cdbcarll            stmt( stmt_load( res_lo,
67011f5fe1fc3a37ca729925e8eec25aa1025b4a6cdbcarll                             binop( Iop_Add32, mkexpr(EA), mkU32(12) ),
67021f5fe1fc3a37ca729925e8eec25aa1025b4a6cdbcarll                             NULL/*this is a load*/) );
670378850ae9874a90ea625fcee1fd4c359375b7b538carll         }
670478850ae9874a90ea625fcee1fd4c359375b7b538carll         putIReg( rD_addr,   mkexpr(res_hi) );
670578850ae9874a90ea625fcee1fd4c359375b7b538carll         putIReg( rD_addr+1, mkexpr(res_lo) );
670678850ae9874a90ea625fcee1fd4c359375b7b538carll         break;
670778850ae9874a90ea625fcee1fd4c359375b7b538carll      }
670878850ae9874a90ea625fcee1fd4c359375b7b538carll
670978850ae9874a90ea625fcee1fd4c359375b7b538carll      case 0x0B6: { // stqcx. (Store QuadWord Condition Indexd, PPC64)
671078850ae9874a90ea625fcee1fd4c359375b7b538carll         // A marginally simplified version of the stwcx. case
671178850ae9874a90ea625fcee1fd4c359375b7b538carll         IRTemp rS_hi = newTemp(ty);
671278850ae9874a90ea625fcee1fd4c359375b7b538carll         IRTemp rS_lo = newTemp(ty);
671378850ae9874a90ea625fcee1fd4c359375b7b538carll         IRTemp resSC;
671478850ae9874a90ea625fcee1fd4c359375b7b538carll         if (b0 != 1) {
671578850ae9874a90ea625fcee1fd4c359375b7b538carll            vex_printf("dis_memsync(ppc)(stqcx.,b0)\n");
671678850ae9874a90ea625fcee1fd4c359375b7b538carll            return False;
671778850ae9874a90ea625fcee1fd4c359375b7b538carll         }
671878850ae9874a90ea625fcee1fd4c359375b7b538carll
671978850ae9874a90ea625fcee1fd4c359375b7b538carll         DIP("stqcx. r%u,r%u,r%u\n", rS_addr, rA_addr, rB_addr);
672078850ae9874a90ea625fcee1fd4c359375b7b538carll
672178850ae9874a90ea625fcee1fd4c359375b7b538carll         // trap if misaligned
672278850ae9874a90ea625fcee1fd4c359375b7b538carll         gen_SIGBUS_if_misaligned( EA, 16 );
672378850ae9874a90ea625fcee1fd4c359375b7b538carll         // Get the data to be stored
672478850ae9874a90ea625fcee1fd4c359375b7b538carll         assign( rS_hi, getIReg(rS_addr) );
672578850ae9874a90ea625fcee1fd4c359375b7b538carll         assign( rS_lo, getIReg(rS_addr+1) );
672678850ae9874a90ea625fcee1fd4c359375b7b538carll
672778850ae9874a90ea625fcee1fd4c359375b7b538carll         // Do the store, and get success/failure bit into resSC
672878850ae9874a90ea625fcee1fd4c359375b7b538carll         resSC = newTemp(Ity_I1);
672978850ae9874a90ea625fcee1fd4c359375b7b538carll
673078850ae9874a90ea625fcee1fd4c359375b7b538carll         if (mode64) {
6731999ef56da3e4426c5f6bf74de40d23ff02dafb34carll            if (host_endness == VexEndnessBE) {
6732999ef56da3e4426c5f6bf74de40d23ff02dafb34carll               stmt( stmt_load( resSC, mkexpr(EA), mkexpr(rS_hi) ) );
6733999ef56da3e4426c5f6bf74de40d23ff02dafb34carll               store( binop( Iop_Add64, mkexpr(EA), mkU64(8) ),
6734999ef56da3e4426c5f6bf74de40d23ff02dafb34carll                      mkexpr(rS_lo) );
6735999ef56da3e4426c5f6bf74de40d23ff02dafb34carll	    } else {
6736999ef56da3e4426c5f6bf74de40d23ff02dafb34carll               stmt( stmt_load( resSC, mkexpr(EA), mkexpr(rS_lo) ) );
6737999ef56da3e4426c5f6bf74de40d23ff02dafb34carll               store( binop( Iop_Add64, mkexpr(EA), mkU64(8) ),
6738999ef56da3e4426c5f6bf74de40d23ff02dafb34carll                      mkexpr(rS_hi) );
6739999ef56da3e4426c5f6bf74de40d23ff02dafb34carll	    }
674078850ae9874a90ea625fcee1fd4c359375b7b538carll         } else {
67411f5fe1fc3a37ca729925e8eec25aa1025b4a6cdbcarll            stmt( stmt_load( resSC, binop( Iop_Add32,
67421f5fe1fc3a37ca729925e8eec25aa1025b4a6cdbcarll                                           mkexpr(EA),
67431f5fe1fc3a37ca729925e8eec25aa1025b4a6cdbcarll                                           mkU32(4) ),
67441f5fe1fc3a37ca729925e8eec25aa1025b4a6cdbcarll                                           mkexpr(rS_hi) ) );
67451f5fe1fc3a37ca729925e8eec25aa1025b4a6cdbcarll            store( binop(Iop_Add32, mkexpr(EA), mkU32(12) ), mkexpr(rS_lo) );
674678850ae9874a90ea625fcee1fd4c359375b7b538carll         }
674778850ae9874a90ea625fcee1fd4c359375b7b538carll
674878850ae9874a90ea625fcee1fd4c359375b7b538carll         // Set CR0[LT GT EQ S0] = 0b000 || XER[SO]  on failure
674978850ae9874a90ea625fcee1fd4c359375b7b538carll         // Set CR0[LT GT EQ S0] = 0b001 || XER[SO]  on success
675078850ae9874a90ea625fcee1fd4c359375b7b538carll         putCR321(0, binop( Iop_Shl8,
675178850ae9874a90ea625fcee1fd4c359375b7b538carll                            unop(Iop_1Uto8, mkexpr(resSC) ),
675278850ae9874a90ea625fcee1fd4c359375b7b538carll                            mkU8(1)));
675378850ae9874a90ea625fcee1fd4c359375b7b538carll         putCR0(0, getXER_SO());
675478850ae9874a90ea625fcee1fd4c359375b7b538carll         break;
675578850ae9874a90ea625fcee1fd4c359375b7b538carll      }
675678850ae9874a90ea625fcee1fd4c359375b7b538carll
6757b85e8bba97fdae7d892f7bfd12e4601307e4721dcerion      default:
67585b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion         vex_printf("dis_memsync(ppc)(opc2)\n");
6759b85e8bba97fdae7d892f7bfd12e4601307e4721dcerion         return False;
6760b85e8bba97fdae7d892f7bfd12e4601307e4721dcerion      }
6761b85e8bba97fdae7d892f7bfd12e4601307e4721dcerion      break;
6762995bc3600091747f64a3ac2d9a7fed6b41c3c88dcerion
6763b85e8bba97fdae7d892f7bfd12e4601307e4721dcerion   default:
67645b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion      vex_printf("dis_memsync(ppc)(opc1)\n");
6765b85e8bba97fdae7d892f7bfd12e4601307e4721dcerion      return False;
6766b85e8bba97fdae7d892f7bfd12e4601307e4721dcerion   }
6767b85e8bba97fdae7d892f7bfd12e4601307e4721dcerion   return True;
67688c3addacc8343f5d1504379e303934f8ed88903ecerion}
67698c3addacc8343f5d1504379e303934f8ed88903ecerion
67708c3addacc8343f5d1504379e303934f8ed88903ecerion
67718c3addacc8343f5d1504379e303934f8ed88903ecerion
67723d870a39e4d145e2f3d9f9a0eeed3475ec934ac1cerion/*
67733d870a39e4d145e2f3d9f9a0eeed3475ec934ac1cerion  Integer Shift Instructions
67743d870a39e4d145e2f3d9f9a0eeed3475ec934ac1cerion*/
6775645c930b1a61f4493ee2d472b34fbb439233a874cerionstatic Bool dis_int_shift ( UInt theInstr )
6776645c930b1a61f4493ee2d472b34fbb439233a874cerion{
6777f0de28cf1a762b0d6f74c93d3532c89a230673bbcerion   /* X-Form, XS-Form */
677876de5cf615380b23b4b5bcced6541233cd4a93a0cerion   UChar opc1    = ifieldOPC(theInstr);
677976de5cf615380b23b4b5bcced6541233cd4a93a0cerion   UChar rS_addr = ifieldRegDS(theInstr);
678076de5cf615380b23b4b5bcced6541233cd4a93a0cerion   UChar rA_addr = ifieldRegA(theInstr);
678176de5cf615380b23b4b5bcced6541233cd4a93a0cerion   UChar rB_addr = ifieldRegB(theInstr);
678276de5cf615380b23b4b5bcced6541233cd4a93a0cerion   UChar sh_imm  = rB_addr;
678376de5cf615380b23b4b5bcced6541233cd4a93a0cerion   UInt  opc2    = ifieldOPClo10(theInstr);
6784f0de28cf1a762b0d6f74c93d3532c89a230673bbcerion   UChar b1      = ifieldBIT1(theInstr);
678576de5cf615380b23b4b5bcced6541233cd4a93a0cerion   UChar flag_rC = ifieldBIT0(theInstr);
678676de5cf615380b23b4b5bcced6541233cd4a93a0cerion
6787d953ebb9b04cbad6891676df597bf0c542b1ec89cerion   IRType  ty         = mode64 ? Ity_I64 : Ity_I32;
6788d953ebb9b04cbad6891676df597bf0c542b1ec89cerion   IRTemp  rA         = newTemp(ty);
678907b07a966a2fdbcf621251a0c1a8ab84807fb120cerion   IRTemp  rS         = newTemp(ty);
679007b07a966a2fdbcf621251a0c1a8ab84807fb120cerion   IRTemp  rB         = newTemp(ty);
6791009230b9758291b594e60d7c0243a73d53e81854sewardj   IRTemp  outofrange = newTemp(Ity_I1);
6792d953ebb9b04cbad6891676df597bf0c542b1ec89cerion   IRTemp  rS_lo32    = newTemp(Ity_I32);
6793d953ebb9b04cbad6891676df597bf0c542b1ec89cerion   IRTemp  rB_lo32    = newTemp(Ity_I32);
6794d953ebb9b04cbad6891676df597bf0c542b1ec89cerion   IRExpr* e_tmp;
6795d953ebb9b04cbad6891676df597bf0c542b1ec89cerion
679607b07a966a2fdbcf621251a0c1a8ab84807fb120cerion   assign( rS, getIReg(rS_addr) );
679707b07a966a2fdbcf621251a0c1a8ab84807fb120cerion   assign( rB, getIReg(rB_addr) );
6798e9d8a26b690c2561ac54ab0cd6ad83ecbadcbe76sewardj   assign( rS_lo32, mkNarrowTo32(ty, mkexpr(rS)) );
6799e9d8a26b690c2561ac54ab0cd6ad83ecbadcbe76sewardj   assign( rB_lo32, mkNarrowTo32(ty, mkexpr(rB)) );
6800b85e8bba97fdae7d892f7bfd12e4601307e4721dcerion
6801b85e8bba97fdae7d892f7bfd12e4601307e4721dcerion   if (opc1 == 0x1F) {
6802b85e8bba97fdae7d892f7bfd12e4601307e4721dcerion      switch (opc2) {
6803d953ebb9b04cbad6891676df597bf0c542b1ec89cerion      case 0x018: { // slw (Shift Left Word, PPC32 p505)
68045b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion         DIP("slw%s r%u,r%u,r%u\n", flag_rC ? ".":"",
680576de5cf615380b23b4b5bcced6541233cd4a93a0cerion             rA_addr, rS_addr, rB_addr);
680676de5cf615380b23b4b5bcced6541233cd4a93a0cerion         /* rA = rS << rB */
680776de5cf615380b23b4b5bcced6541233cd4a93a0cerion         /* ppc32 semantics are:
6808dfb1144e36547976f6493d761051dd4a9e1cf6bfsewardj            slw(x,y) = (x << (y & 31))         -- primary result
6809dfb1144e36547976f6493d761051dd4a9e1cf6bfsewardj                       & ~((y << 26) >>s 31)   -- make result 0
6810dfb1144e36547976f6493d761051dd4a9e1cf6bfsewardj                                                  for y in 32 .. 63
6811dfb1144e36547976f6493d761051dd4a9e1cf6bfsewardj         */
6812d953ebb9b04cbad6891676df597bf0c542b1ec89cerion         e_tmp =
6813d953ebb9b04cbad6891676df597bf0c542b1ec89cerion            binop( Iop_And32,
6814d953ebb9b04cbad6891676df597bf0c542b1ec89cerion               binop( Iop_Shl32,
6815d953ebb9b04cbad6891676df597bf0c542b1ec89cerion                      mkexpr(rS_lo32),
6816d953ebb9b04cbad6891676df597bf0c542b1ec89cerion                      unop( Iop_32to8,
6817d953ebb9b04cbad6891676df597bf0c542b1ec89cerion                            binop(Iop_And32,
6818d953ebb9b04cbad6891676df597bf0c542b1ec89cerion                                  mkexpr(rB_lo32), mkU32(31)))),
6819d953ebb9b04cbad6891676df597bf0c542b1ec89cerion               unop( Iop_Not32,
6820d953ebb9b04cbad6891676df597bf0c542b1ec89cerion                     binop( Iop_Sar32,
6821d953ebb9b04cbad6891676df597bf0c542b1ec89cerion                            binop(Iop_Shl32, mkexpr(rB_lo32), mkU8(26)),
6822d953ebb9b04cbad6891676df597bf0c542b1ec89cerion                            mkU8(31))) );
6823e9d8a26b690c2561ac54ab0cd6ad83ecbadcbe76sewardj         assign( rA, mkWidenFrom32(ty, e_tmp, /* Signed */False) );
6824b85e8bba97fdae7d892f7bfd12e4601307e4721dcerion         break;
6825d953ebb9b04cbad6891676df597bf0c542b1ec89cerion      }
6826d953ebb9b04cbad6891676df597bf0c542b1ec89cerion
68275b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion      case 0x318: { // sraw (Shift Right Alg Word, PPC32 p506)
682807b07a966a2fdbcf621251a0c1a8ab84807fb120cerion         IRTemp sh_amt = newTemp(Ity_I32);
68295b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion         DIP("sraw%s r%u,r%u,r%u\n", flag_rC ? ".":"",
683076de5cf615380b23b4b5bcced6541233cd4a93a0cerion             rA_addr, rS_addr, rB_addr);
683176de5cf615380b23b4b5bcced6541233cd4a93a0cerion         /* JRS: my reading of the (poorly worded) PPC32 doc p506 is:
683276de5cf615380b23b4b5bcced6541233cd4a93a0cerion            amt = rB & 63
683376de5cf615380b23b4b5bcced6541233cd4a93a0cerion            rA = Sar32( rS, amt > 31 ? 31 : amt )
683476de5cf615380b23b4b5bcced6541233cd4a93a0cerion            XER.CA = amt > 31 ? sign-of-rS : (computation as per srawi)
683576de5cf615380b23b4b5bcced6541233cd4a93a0cerion         */
68365b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion         assign( sh_amt, binop(Iop_And32, mkU32(0x3F),
68375b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion                                          mkexpr(rB_lo32)) );
683876de5cf615380b23b4b5bcced6541233cd4a93a0cerion         assign( outofrange,
6839009230b9758291b594e60d7c0243a73d53e81854sewardj                 binop(Iop_CmpLT32U, mkU32(31), mkexpr(sh_amt)) );
6840d953ebb9b04cbad6891676df597bf0c542b1ec89cerion         e_tmp = binop( Iop_Sar32,
6841d953ebb9b04cbad6891676df597bf0c542b1ec89cerion                        mkexpr(rS_lo32),
684220ef5472eac767474c93b7835364a23f24c0ec5dsewardj                        unop( Iop_32to8,
684399dd03e04a6914d90d5fee727d61d76905334becflorian                              IRExpr_ITE( mkexpr(outofrange),
684499dd03e04a6914d90d5fee727d61d76905334becflorian                                          mkU32(31),
684599dd03e04a6914d90d5fee727d61d76905334becflorian                                          mkexpr(sh_amt)) ) );
6846e9d8a26b690c2561ac54ab0cd6ad83ecbadcbe76sewardj         assign( rA, mkWidenFrom32(ty, e_tmp, /* Signed */True) );
68472831b00c4950d6c2b061def05fd67528fe132ececerion
68485b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion         set_XER_CA( ty, PPCG_FLAG_OP_SRAW,
6849f0de28cf1a762b0d6f74c93d3532c89a230673bbcerion                     mkexpr(rA),
6850e9d8a26b690c2561ac54ab0cd6ad83ecbadcbe76sewardj                     mkWidenFrom32(ty, mkexpr(rS_lo32), True),
6851e9d8a26b690c2561ac54ab0cd6ad83ecbadcbe76sewardj                     mkWidenFrom32(ty, mkexpr(sh_amt), True ),
6852e9d8a26b690c2561ac54ab0cd6ad83ecbadcbe76sewardj                     mkWidenFrom32(ty, getXER_CA32(), True) );
6853b85e8bba97fdae7d892f7bfd12e4601307e4721dcerion         break;
685407b07a966a2fdbcf621251a0c1a8ab84807fb120cerion      }
6855b85e8bba97fdae7d892f7bfd12e4601307e4721dcerion
68565b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion      case 0x338: // srawi (Shift Right Alg Word Immediate, PPC32 p507)
68575b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion         DIP("srawi%s r%u,r%u,%d\n", flag_rC ? ".":"",
685876de5cf615380b23b4b5bcced6541233cd4a93a0cerion             rA_addr, rS_addr, sh_imm);
685976de5cf615380b23b4b5bcced6541233cd4a93a0cerion         vassert(sh_imm < 32);
6860f0de28cf1a762b0d6f74c93d3532c89a230673bbcerion         if (mode64) {
6861f0de28cf1a762b0d6f74c93d3532c89a230673bbcerion            assign( rA, binop(Iop_Sar64,
68625b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion                              binop(Iop_Shl64, getIReg(rS_addr),
68635b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion                                               mkU8(32)),
6864f0de28cf1a762b0d6f74c93d3532c89a230673bbcerion                              mkU8(32 + sh_imm)) );
6865f0de28cf1a762b0d6f74c93d3532c89a230673bbcerion         } else {
68665b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion            assign( rA, binop(Iop_Sar32, mkexpr(rS_lo32),
68675b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion                                         mkU8(sh_imm)) );
6868f0de28cf1a762b0d6f74c93d3532c89a230673bbcerion         }
68692831b00c4950d6c2b061def05fd67528fe132ececerion
68705b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion         set_XER_CA( ty, PPCG_FLAG_OP_SRAWI,
6871f0de28cf1a762b0d6f74c93d3532c89a230673bbcerion                     mkexpr(rA),
6872e9d8a26b690c2561ac54ab0cd6ad83ecbadcbe76sewardj                     mkWidenFrom32(ty, mkexpr(rS_lo32), /* Syned */True),
6873f0de28cf1a762b0d6f74c93d3532c89a230673bbcerion                     mkSzImm(ty, sh_imm),
6874e9d8a26b690c2561ac54ab0cd6ad83ecbadcbe76sewardj                     mkWidenFrom32(ty, getXER_CA32(), /* Syned */False) );
6875b85e8bba97fdae7d892f7bfd12e4601307e4721dcerion         break;
6876b85e8bba97fdae7d892f7bfd12e4601307e4721dcerion
6877e9d361ab43518b6dfbd3d846f48859534659dee0cerion      case 0x218: // srw (Shift Right Word, PPC32 p508)
68785b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion         DIP("srw%s r%u,r%u,r%u\n", flag_rC ? ".":"",
687976de5cf615380b23b4b5bcced6541233cd4a93a0cerion             rA_addr, rS_addr, rB_addr);
688076de5cf615380b23b4b5bcced6541233cd4a93a0cerion         /* rA = rS >>u rB */
688176de5cf615380b23b4b5bcced6541233cd4a93a0cerion         /* ppc32 semantics are:
6882f0de28cf1a762b0d6f74c93d3532c89a230673bbcerion            srw(x,y) = (x >>u (y & 31))        -- primary result
6883dfb1144e36547976f6493d761051dd4a9e1cf6bfsewardj                       & ~((y << 26) >>s 31)   -- make result 0
6884dfb1144e36547976f6493d761051dd4a9e1cf6bfsewardj                                                  for y in 32 .. 63
6885dfb1144e36547976f6493d761051dd4a9e1cf6bfsewardj         */
6886d953ebb9b04cbad6891676df597bf0c542b1ec89cerion         e_tmp =
6887dfb1144e36547976f6493d761051dd4a9e1cf6bfsewardj            binop(
6888dfb1144e36547976f6493d761051dd4a9e1cf6bfsewardj               Iop_And32,
6889dfb1144e36547976f6493d761051dd4a9e1cf6bfsewardj               binop( Iop_Shr32,
6890d953ebb9b04cbad6891676df597bf0c542b1ec89cerion                      mkexpr(rS_lo32),
6891dfb1144e36547976f6493d761051dd4a9e1cf6bfsewardj                      unop( Iop_32to8,
68925b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion                            binop(Iop_And32, mkexpr(rB_lo32),
68935b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion                                             mkU32(31)))),
6894dfb1144e36547976f6493d761051dd4a9e1cf6bfsewardj               unop( Iop_Not32,
6895dfb1144e36547976f6493d761051dd4a9e1cf6bfsewardj                     binop( Iop_Sar32,
68965b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion                            binop(Iop_Shl32, mkexpr(rB_lo32),
68975b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion                                             mkU8(26)),
6898d953ebb9b04cbad6891676df597bf0c542b1ec89cerion                            mkU8(31))));
6899e9d8a26b690c2561ac54ab0cd6ad83ecbadcbe76sewardj         assign( rA, mkWidenFrom32(ty, e_tmp, /* Signed */False) );
6900b85e8bba97fdae7d892f7bfd12e4601307e4721dcerion         break;
6901f0de28cf1a762b0d6f74c93d3532c89a230673bbcerion
6902f0de28cf1a762b0d6f74c93d3532c89a230673bbcerion
6903f0de28cf1a762b0d6f74c93d3532c89a230673bbcerion      /* 64bit Shifts */
69045b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion      case 0x01B: // sld (Shift Left DWord, PPC64 p568)
69055b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion         DIP("sld%s r%u,r%u,r%u\n",
69065b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion             flag_rC ? ".":"", rA_addr, rS_addr, rB_addr);
6907f0de28cf1a762b0d6f74c93d3532c89a230673bbcerion         /* rA = rS << rB */
690807b07a966a2fdbcf621251a0c1a8ab84807fb120cerion         /* ppc64 semantics are:
6909f0de28cf1a762b0d6f74c93d3532c89a230673bbcerion            slw(x,y) = (x << (y & 63))         -- primary result
6910f0de28cf1a762b0d6f74c93d3532c89a230673bbcerion                       & ~((y << 57) >>s 63)   -- make result 0
6911f0de28cf1a762b0d6f74c93d3532c89a230673bbcerion                                                  for y in 64 ..
6912f0de28cf1a762b0d6f74c93d3532c89a230673bbcerion         */
6913f0de28cf1a762b0d6f74c93d3532c89a230673bbcerion         assign( rA,
6914f0de28cf1a762b0d6f74c93d3532c89a230673bbcerion            binop(
6915f0de28cf1a762b0d6f74c93d3532c89a230673bbcerion               Iop_And64,
6916f0de28cf1a762b0d6f74c93d3532c89a230673bbcerion               binop( Iop_Shl64,
6917f0de28cf1a762b0d6f74c93d3532c89a230673bbcerion                      mkexpr(rS),
6918f0de28cf1a762b0d6f74c93d3532c89a230673bbcerion                      unop( Iop_64to8,
6919f0de28cf1a762b0d6f74c93d3532c89a230673bbcerion                            binop(Iop_And64, mkexpr(rB), mkU64(63)))),
6920f0de28cf1a762b0d6f74c93d3532c89a230673bbcerion               unop( Iop_Not64,
6921f0de28cf1a762b0d6f74c93d3532c89a230673bbcerion                     binop( Iop_Sar64,
6922f0de28cf1a762b0d6f74c93d3532c89a230673bbcerion                            binop(Iop_Shl64, mkexpr(rB), mkU8(57)),
6923f0de28cf1a762b0d6f74c93d3532c89a230673bbcerion                            mkU8(63)))) );
692407b07a966a2fdbcf621251a0c1a8ab84807fb120cerion         break;
6925f0de28cf1a762b0d6f74c93d3532c89a230673bbcerion
69265b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion      case 0x31A: { // srad (Shift Right Alg DWord, PPC64 p570)
692707b07a966a2fdbcf621251a0c1a8ab84807fb120cerion         IRTemp sh_amt = newTemp(Ity_I64);
69285b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion         DIP("srad%s r%u,r%u,r%u\n",
69295b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion             flag_rC ? ".":"", rA_addr, rS_addr, rB_addr);
6930f0de28cf1a762b0d6f74c93d3532c89a230673bbcerion         /* amt = rB & 127
6931f0de28cf1a762b0d6f74c93d3532c89a230673bbcerion            rA = Sar64( rS, amt > 63 ? 63 : amt )
6932f0de28cf1a762b0d6f74c93d3532c89a230673bbcerion            XER.CA = amt > 63 ? sign-of-rS : (computation as per srawi)
6933f0de28cf1a762b0d6f74c93d3532c89a230673bbcerion         */
693407b07a966a2fdbcf621251a0c1a8ab84807fb120cerion         assign( sh_amt, binop(Iop_And64, mkU64(0x7F), mkexpr(rB)) );
6935f0de28cf1a762b0d6f74c93d3532c89a230673bbcerion         assign( outofrange,
6936009230b9758291b594e60d7c0243a73d53e81854sewardj                 binop(Iop_CmpLT64U, mkU64(63), mkexpr(sh_amt)) );
6937f0de28cf1a762b0d6f74c93d3532c89a230673bbcerion         assign( rA,
6938f0de28cf1a762b0d6f74c93d3532c89a230673bbcerion                 binop( Iop_Sar64,
6939f0de28cf1a762b0d6f74c93d3532c89a230673bbcerion                        mkexpr(rS),
6940f0de28cf1a762b0d6f74c93d3532c89a230673bbcerion                        unop( Iop_64to8,
694199dd03e04a6914d90d5fee727d61d76905334becflorian                              IRExpr_ITE( mkexpr(outofrange),
694299dd03e04a6914d90d5fee727d61d76905334becflorian                                          mkU64(63),
694399dd03e04a6914d90d5fee727d61d76905334becflorian                                          mkexpr(sh_amt)) ))
6944f0de28cf1a762b0d6f74c93d3532c89a230673bbcerion               );
69455b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion         set_XER_CA( ty, PPCG_FLAG_OP_SRAD,
694607b07a966a2fdbcf621251a0c1a8ab84807fb120cerion                     mkexpr(rA), mkexpr(rS), mkexpr(sh_amt),
6947e9d8a26b690c2561ac54ab0cd6ad83ecbadcbe76sewardj                     mkWidenFrom32(ty, getXER_CA32(), /* Syned */False) );
694807b07a966a2fdbcf621251a0c1a8ab84807fb120cerion         break;
694907b07a966a2fdbcf621251a0c1a8ab84807fb120cerion      }
695007b07a966a2fdbcf621251a0c1a8ab84807fb120cerion
69515b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion      case 0x33A: case 0x33B: // sradi (Shr Alg DWord Imm, PPC64 p571)
6952f0de28cf1a762b0d6f74c93d3532c89a230673bbcerion         sh_imm |= b1<<5;
6953f0de28cf1a762b0d6f74c93d3532c89a230673bbcerion         vassert(sh_imm < 64);
69545b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion         DIP("sradi%s r%u,r%u,%u\n",
69555b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion             flag_rC ? ".":"", rA_addr, rS_addr, sh_imm);
6956f0de28cf1a762b0d6f74c93d3532c89a230673bbcerion         assign( rA, binop(Iop_Sar64, getIReg(rS_addr), mkU8(sh_imm)) );
6957f0de28cf1a762b0d6f74c93d3532c89a230673bbcerion
69585b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion         set_XER_CA( ty, PPCG_FLAG_OP_SRADI,
6959f0de28cf1a762b0d6f74c93d3532c89a230673bbcerion                     mkexpr(rA),
6960f0de28cf1a762b0d6f74c93d3532c89a230673bbcerion                     getIReg(rS_addr),
6961f0de28cf1a762b0d6f74c93d3532c89a230673bbcerion                     mkU64(sh_imm),
6962e9d8a26b690c2561ac54ab0cd6ad83ecbadcbe76sewardj                     mkWidenFrom32(ty, getXER_CA32(), /* Syned */False) );
6963f0de28cf1a762b0d6f74c93d3532c89a230673bbcerion         break;
6964f0de28cf1a762b0d6f74c93d3532c89a230673bbcerion
69655b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion      case 0x21B: // srd (Shift Right DWord, PPC64 p574)
69665b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion         DIP("srd%s r%u,r%u,r%u\n",
69675b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion             flag_rC ? ".":"", rA_addr, rS_addr, rB_addr);
6968f0de28cf1a762b0d6f74c93d3532c89a230673bbcerion         /* rA = rS >>u rB */
696907b07a966a2fdbcf621251a0c1a8ab84807fb120cerion         /* ppc semantics are:
6970f0de28cf1a762b0d6f74c93d3532c89a230673bbcerion            srw(x,y) = (x >>u (y & 63))        -- primary result
6971f0de28cf1a762b0d6f74c93d3532c89a230673bbcerion                       & ~((y << 57) >>s 63)   -- make result 0
6972f0de28cf1a762b0d6f74c93d3532c89a230673bbcerion                                                  for y in 64 .. 127
6973f0de28cf1a762b0d6f74c93d3532c89a230673bbcerion         */
6974f0de28cf1a762b0d6f74c93d3532c89a230673bbcerion         assign( rA,
6975f0de28cf1a762b0d6f74c93d3532c89a230673bbcerion            binop(
6976f0de28cf1a762b0d6f74c93d3532c89a230673bbcerion               Iop_And64,
6977f0de28cf1a762b0d6f74c93d3532c89a230673bbcerion               binop( Iop_Shr64,
6978f0de28cf1a762b0d6f74c93d3532c89a230673bbcerion                      mkexpr(rS),
6979f0de28cf1a762b0d6f74c93d3532c89a230673bbcerion                      unop( Iop_64to8,
6980f0de28cf1a762b0d6f74c93d3532c89a230673bbcerion                            binop(Iop_And64, mkexpr(rB), mkU64(63)))),
6981f0de28cf1a762b0d6f74c93d3532c89a230673bbcerion               unop( Iop_Not64,
6982f0de28cf1a762b0d6f74c93d3532c89a230673bbcerion                     binop( Iop_Sar64,
6983f0de28cf1a762b0d6f74c93d3532c89a230673bbcerion                            binop(Iop_Shl64, mkexpr(rB), mkU8(57)),
6984f0de28cf1a762b0d6f74c93d3532c89a230673bbcerion                            mkU8(63)))) );
698507b07a966a2fdbcf621251a0c1a8ab84807fb120cerion         break;
6986f0de28cf1a762b0d6f74c93d3532c89a230673bbcerion
6987b85e8bba97fdae7d892f7bfd12e4601307e4721dcerion      default:
69885b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion         vex_printf("dis_int_shift(ppc)(opc2)\n");
6989b85e8bba97fdae7d892f7bfd12e4601307e4721dcerion         return False;
6990b85e8bba97fdae7d892f7bfd12e4601307e4721dcerion      }
6991b85e8bba97fdae7d892f7bfd12e4601307e4721dcerion   } else {
69925b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion      vex_printf("dis_int_shift(ppc)(opc1)\n");
6993b85e8bba97fdae7d892f7bfd12e4601307e4721dcerion      return False;
6994b85e8bba97fdae7d892f7bfd12e4601307e4721dcerion   }
69950d330c5a910b71c8f4b2ec149d1a88a06acd784bcerion
699676de5cf615380b23b4b5bcced6541233cd4a93a0cerion   putIReg( rA_addr, mkexpr(rA) );
6997b85e8bba97fdae7d892f7bfd12e4601307e4721dcerion
699876de5cf615380b23b4b5bcced6541233cd4a93a0cerion   if (flag_rC) {
699976de5cf615380b23b4b5bcced6541233cd4a93a0cerion      set_CR0( mkexpr(rA) );
7000b85e8bba97fdae7d892f7bfd12e4601307e4721dcerion   }
7001b85e8bba97fdae7d892f7bfd12e4601307e4721dcerion   return True;
7002645c930b1a61f4493ee2d472b34fbb439233a874cerion}
7003645c930b1a61f4493ee2d472b34fbb439233a874cerion
7004645c930b1a61f4493ee2d472b34fbb439233a874cerion
7005645c930b1a61f4493ee2d472b34fbb439233a874cerion
7006602857d30b8aa87c202517e2be6c7df6d40ee922sewardj/*
7007602857d30b8aa87c202517e2be6c7df6d40ee922sewardj  Integer Load/Store Reverse Instructions
7008602857d30b8aa87c202517e2be6c7df6d40ee922sewardj*/
700940d8c09304469b6d1a03c7840d5c33d174b64c1csewardj/* Generates code to swap the byte order in an Ity_I32. */
7010fb957970740ff6c1a21020e6716ab9e25852fec2sewardjstatic IRExpr* /* :: Ity_I32 */ gen_byterev32 ( IRTemp t )
7011fb957970740ff6c1a21020e6716ab9e25852fec2sewardj{
7012dd40fdf58cc8a6fe9466c4f00bdfc9fe9bf00449sewardj   vassert(typeOfIRTemp(irsb->tyenv, t) == Ity_I32);
7013fb957970740ff6c1a21020e6716ab9e25852fec2sewardj   return
7014fb957970740ff6c1a21020e6716ab9e25852fec2sewardj      binop(Iop_Or32,
7015fb957970740ff6c1a21020e6716ab9e25852fec2sewardj         binop(Iop_Shl32, mkexpr(t), mkU8(24)),
7016fb957970740ff6c1a21020e6716ab9e25852fec2sewardj      binop(Iop_Or32,
7017fb957970740ff6c1a21020e6716ab9e25852fec2sewardj         binop(Iop_And32, binop(Iop_Shl32, mkexpr(t), mkU8(8)),
7018fb957970740ff6c1a21020e6716ab9e25852fec2sewardj                          mkU32(0x00FF0000)),
7019fb957970740ff6c1a21020e6716ab9e25852fec2sewardj      binop(Iop_Or32,
7020fb957970740ff6c1a21020e6716ab9e25852fec2sewardj         binop(Iop_And32, binop(Iop_Shr32, mkexpr(t), mkU8(8)),
7021fb957970740ff6c1a21020e6716ab9e25852fec2sewardj                          mkU32(0x0000FF00)),
7022fb957970740ff6c1a21020e6716ab9e25852fec2sewardj         binop(Iop_And32, binop(Iop_Shr32, mkexpr(t), mkU8(24)),
7023fb957970740ff6c1a21020e6716ab9e25852fec2sewardj                          mkU32(0x000000FF) )
7024fb957970740ff6c1a21020e6716ab9e25852fec2sewardj      )));
7025fb957970740ff6c1a21020e6716ab9e25852fec2sewardj}
7026fb957970740ff6c1a21020e6716ab9e25852fec2sewardj
702740d8c09304469b6d1a03c7840d5c33d174b64c1csewardj/* Generates code to swap the byte order in the lower half of an Ity_I32,
702840d8c09304469b6d1a03c7840d5c33d174b64c1csewardj   and zeroes the upper half. */
702940d8c09304469b6d1a03c7840d5c33d174b64c1csewardjstatic IRExpr* /* :: Ity_I32 */ gen_byterev16 ( IRTemp t )
703040d8c09304469b6d1a03c7840d5c33d174b64c1csewardj{
7031dd40fdf58cc8a6fe9466c4f00bdfc9fe9bf00449sewardj   vassert(typeOfIRTemp(irsb->tyenv, t) == Ity_I32);
703240d8c09304469b6d1a03c7840d5c33d174b64c1csewardj   return
703340d8c09304469b6d1a03c7840d5c33d174b64c1csewardj      binop(Iop_Or32,
703440d8c09304469b6d1a03c7840d5c33d174b64c1csewardj         binop(Iop_And32, binop(Iop_Shl32, mkexpr(t), mkU8(8)),
703540d8c09304469b6d1a03c7840d5c33d174b64c1csewardj                          mkU32(0x0000FF00)),
703640d8c09304469b6d1a03c7840d5c33d174b64c1csewardj         binop(Iop_And32, binop(Iop_Shr32, mkexpr(t), mkU8(8)),
703740d8c09304469b6d1a03c7840d5c33d174b64c1csewardj                          mkU32(0x000000FF))
703840d8c09304469b6d1a03c7840d5c33d174b64c1csewardj      );
703940d8c09304469b6d1a03c7840d5c33d174b64c1csewardj}
704040d8c09304469b6d1a03c7840d5c33d174b64c1csewardj
7041602857d30b8aa87c202517e2be6c7df6d40ee922sewardjstatic Bool dis_int_ldst_rev ( UInt theInstr )
7042602857d30b8aa87c202517e2be6c7df6d40ee922sewardj{
7043602857d30b8aa87c202517e2be6c7df6d40ee922sewardj   /* X-Form */
704476de5cf615380b23b4b5bcced6541233cd4a93a0cerion   UChar opc1    = ifieldOPC(theInstr);
704576de5cf615380b23b4b5bcced6541233cd4a93a0cerion   UChar rD_addr = ifieldRegDS(theInstr);
704676de5cf615380b23b4b5bcced6541233cd4a93a0cerion   UChar rS_addr = rD_addr;
704776de5cf615380b23b4b5bcced6541233cd4a93a0cerion   UChar rA_addr = ifieldRegA(theInstr);
704876de5cf615380b23b4b5bcced6541233cd4a93a0cerion   UChar rB_addr = ifieldRegB(theInstr);
704976de5cf615380b23b4b5bcced6541233cd4a93a0cerion   UInt  opc2    = ifieldOPClo10(theInstr);
705076de5cf615380b23b4b5bcced6541233cd4a93a0cerion   UChar b0      = ifieldBIT0(theInstr);
7051edf7fc572e2decb93e9143961e8739c8fe18899dcerion
7052d953ebb9b04cbad6891676df597bf0c542b1ec89cerion   IRType ty = mode64 ? Ity_I64 : Ity_I32;
7053d953ebb9b04cbad6891676df597bf0c542b1ec89cerion   IRTemp EA = newTemp(ty);
7054edf7fc572e2decb93e9143961e8739c8fe18899dcerion   IRTemp w1 = newTemp(Ity_I32);
7055edf7fc572e2decb93e9143961e8739c8fe18899dcerion   IRTemp w2 = newTemp(Ity_I32);
7056602857d30b8aa87c202517e2be6c7df6d40ee922sewardj
7057602857d30b8aa87c202517e2be6c7df6d40ee922sewardj   if (opc1 != 0x1F || b0 != 0) {
70585b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion      vex_printf("dis_int_ldst_rev(ppc)(opc1|b0)\n");
7059602857d30b8aa87c202517e2be6c7df6d40ee922sewardj      return False;
7060602857d30b8aa87c202517e2be6c7df6d40ee922sewardj   }
7061afe85831d73e546e483dfc51964409b7ecd7c5fesewardj
7062d953ebb9b04cbad6891676df597bf0c542b1ec89cerion   assign( EA, ea_rAor0_idxd( rA_addr, rB_addr ) );
7063602857d30b8aa87c202517e2be6c7df6d40ee922sewardj
7064602857d30b8aa87c202517e2be6c7df6d40ee922sewardj   switch (opc2) {
706540d8c09304469b6d1a03c7840d5c33d174b64c1csewardj
706640d8c09304469b6d1a03c7840d5c33d174b64c1csewardj      case 0x316: // lhbrx (Load Halfword Byte-Reverse Indexed, PPC32 p449)
706740d8c09304469b6d1a03c7840d5c33d174b64c1csewardj         DIP("lhbrx r%u,r%u,r%u\n", rD_addr, rA_addr, rB_addr);
70681f5fe1fc3a37ca729925e8eec25aa1025b4a6cdbcarll         assign( w1, unop(Iop_16Uto32, load(Ity_I16, mkexpr(EA))) );
706940d8c09304469b6d1a03c7840d5c33d174b64c1csewardj         assign( w2, gen_byterev16(w1) );
7070e9d8a26b690c2561ac54ab0cd6ad83ecbadcbe76sewardj         putIReg( rD_addr, mkWidenFrom32(ty, mkexpr(w2),
7071e9d8a26b690c2561ac54ab0cd6ad83ecbadcbe76sewardj                                         /* Signed */False) );
707240d8c09304469b6d1a03c7840d5c33d174b64c1csewardj         break;
707340d8c09304469b6d1a03c7840d5c33d174b64c1csewardj
7074fb957970740ff6c1a21020e6716ab9e25852fec2sewardj      case 0x216: // lwbrx (Load Word Byte-Reverse Indexed, PPC32 p459)
7075d953ebb9b04cbad6891676df597bf0c542b1ec89cerion         DIP("lwbrx r%u,r%u,r%u\n", rD_addr, rA_addr, rB_addr);
70761f5fe1fc3a37ca729925e8eec25aa1025b4a6cdbcarll         assign( w1, load(Ity_I32, mkexpr(EA)) );
7077fb957970740ff6c1a21020e6716ab9e25852fec2sewardj         assign( w2, gen_byterev32(w1) );
7078e9d8a26b690c2561ac54ab0cd6ad83ecbadcbe76sewardj         putIReg( rD_addr, mkWidenFrom32(ty, mkexpr(w2),
7079e9d8a26b690c2561ac54ab0cd6ad83ecbadcbe76sewardj                                         /* Signed */False) );
7080fb957970740ff6c1a21020e6716ab9e25852fec2sewardj         break;
708166d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj
708266d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj      case 0x214: // ldbrx (Load Doubleword Byte-Reverse Indexed)
708366d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj      {
708466d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj         IRExpr * nextAddr;
708566d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj         IRTemp w3 = newTemp( Ity_I32 );
708666d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj         IRTemp w4 = newTemp( Ity_I32 );
708766d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj         DIP("ldbrx r%u,r%u,r%u\n", rD_addr, rA_addr, rB_addr);
70881f5fe1fc3a37ca729925e8eec25aa1025b4a6cdbcarll         assign( w1, load( Ity_I32, mkexpr( EA ) ) );
708966d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj         assign( w2, gen_byterev32( w1 ) );
709066d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj         nextAddr = binop( mkSzOp( ty, Iop_Add8 ), mkexpr( EA ),
709166d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj                           ty == Ity_I64 ? mkU64( 4 ) : mkU32( 4 ) );
70921f5fe1fc3a37ca729925e8eec25aa1025b4a6cdbcarll         assign( w3, load( Ity_I32, nextAddr ) );
709366d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj         assign( w4, gen_byterev32( w3 ) );
70941f5fe1fc3a37ca729925e8eec25aa1025b4a6cdbcarll         if (host_endness == VexEndnessLE)
70951f5fe1fc3a37ca729925e8eec25aa1025b4a6cdbcarll            putIReg( rD_addr, binop( Iop_32HLto64, mkexpr( w2 ), mkexpr( w4 ) ) );
70961f5fe1fc3a37ca729925e8eec25aa1025b4a6cdbcarll         else
70971f5fe1fc3a37ca729925e8eec25aa1025b4a6cdbcarll            putIReg( rD_addr, binop( Iop_32HLto64, mkexpr( w4 ), mkexpr( w2 ) ) );
709866d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj         break;
709966d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj      }
710066d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj
7101413a468a761b63846e805c0987b07c4d7a28cf12sewardj      case 0x396: // sthbrx (Store Half Word Byte-Reverse Indexed, PPC32 p523)
7102413a468a761b63846e805c0987b07c4d7a28cf12sewardj         DIP("sthbrx r%u,r%u,r%u\n", rS_addr, rA_addr, rB_addr);
7103e9d8a26b690c2561ac54ab0cd6ad83ecbadcbe76sewardj         assign( w1, mkNarrowTo32(ty, getIReg(rS_addr)) );
71041f5fe1fc3a37ca729925e8eec25aa1025b4a6cdbcarll         store( mkexpr(EA), unop(Iop_32to16, gen_byterev16(w1)) );
7105413a468a761b63846e805c0987b07c4d7a28cf12sewardj         break;
7106602857d30b8aa87c202517e2be6c7df6d40ee922sewardj
71075b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion      case 0x296: // stwbrx (Store Word Byte-Reverse Indxd, PPC32 p531)
7108d953ebb9b04cbad6891676df597bf0c542b1ec89cerion         DIP("stwbrx r%u,r%u,r%u\n", rS_addr, rA_addr, rB_addr);
7109e9d8a26b690c2561ac54ab0cd6ad83ecbadcbe76sewardj         assign( w1, mkNarrowTo32(ty, getIReg(rS_addr)) );
71101f5fe1fc3a37ca729925e8eec25aa1025b4a6cdbcarll         store( mkexpr(EA), gen_byterev32(w1) );
7111fb957970740ff6c1a21020e6716ab9e25852fec2sewardj         break;
71124aa412af1d8166cc11f39a6e721df49431d23618sewardj
71134aa412af1d8166cc11f39a6e721df49431d23618sewardj      case 0x294: // stdbrx (Store Doubleword Byte-Reverse Indexed)
71144aa412af1d8166cc11f39a6e721df49431d23618sewardj      {
71154aa412af1d8166cc11f39a6e721df49431d23618sewardj         IRTemp lo = newTemp(Ity_I32);
71164aa412af1d8166cc11f39a6e721df49431d23618sewardj         IRTemp hi = newTemp(Ity_I32);
71174aa412af1d8166cc11f39a6e721df49431d23618sewardj         IRTemp rS = newTemp(Ity_I64);
71184aa412af1d8166cc11f39a6e721df49431d23618sewardj         assign( rS, getIReg( rS_addr ) );
71194aa412af1d8166cc11f39a6e721df49431d23618sewardj         DIP("stdbrx r%u,r%u,r%u\n", rS_addr, rA_addr, rB_addr);
71204aa412af1d8166cc11f39a6e721df49431d23618sewardj         assign(lo, unop(Iop_64HIto32, mkexpr(rS)));
71214aa412af1d8166cc11f39a6e721df49431d23618sewardj         assign(hi, unop(Iop_64to32, mkexpr(rS)));
71221f5fe1fc3a37ca729925e8eec25aa1025b4a6cdbcarll         store( mkexpr( EA ),
71231f5fe1fc3a37ca729925e8eec25aa1025b4a6cdbcarll                binop( Iop_32HLto64, gen_byterev32( hi ),
71241f5fe1fc3a37ca729925e8eec25aa1025b4a6cdbcarll                       gen_byterev32( lo ) ) );
71254aa412af1d8166cc11f39a6e721df49431d23618sewardj         break;
71264aa412af1d8166cc11f39a6e721df49431d23618sewardj      }
71274aa412af1d8166cc11f39a6e721df49431d23618sewardj
7128fb957970740ff6c1a21020e6716ab9e25852fec2sewardj      default:
71295b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion         vex_printf("dis_int_ldst_rev(ppc)(opc2)\n");
7130fb957970740ff6c1a21020e6716ab9e25852fec2sewardj         return False;
7131602857d30b8aa87c202517e2be6c7df6d40ee922sewardj   }
7132602857d30b8aa87c202517e2be6c7df6d40ee922sewardj   return True;
7133602857d30b8aa87c202517e2be6c7df6d40ee922sewardj}
7134645c930b1a61f4493ee2d472b34fbb439233a874cerion
7135645c930b1a61f4493ee2d472b34fbb439233a874cerion
7136645c930b1a61f4493ee2d472b34fbb439233a874cerion
71373d870a39e4d145e2f3d9f9a0eeed3475ec934ac1cerion/*
71383d870a39e4d145e2f3d9f9a0eeed3475ec934ac1cerion  Processor Control Instructions
71393d870a39e4d145e2f3d9f9a0eeed3475ec934ac1cerion*/
7140cacba8e675988fbf21b08feea1f317a9c896c053florianstatic Bool dis_proc_ctl ( const VexAbiInfo* vbi, UInt theInstr )
71418c3addacc8343f5d1504379e303934f8ed88903ecerion{
714276de5cf615380b23b4b5bcced6541233cd4a93a0cerion   UChar opc1     = ifieldOPC(theInstr);
7143b85e8bba97fdae7d892f7bfd12e4601307e4721dcerion
7144b85e8bba97fdae7d892f7bfd12e4601307e4721dcerion   /* X-Form */
714576de5cf615380b23b4b5bcced6541233cd4a93a0cerion   UChar crfD     = toUChar( IFIELD( theInstr, 23, 3 ) );
714676de5cf615380b23b4b5bcced6541233cd4a93a0cerion   UChar b21to22  = toUChar( IFIELD( theInstr, 21, 2 ) );
714776de5cf615380b23b4b5bcced6541233cd4a93a0cerion   UChar rD_addr  = ifieldRegDS(theInstr);
714876de5cf615380b23b4b5bcced6541233cd4a93a0cerion   UInt  b11to20  = IFIELD( theInstr, 11, 10 );
714976de5cf615380b23b4b5bcced6541233cd4a93a0cerion
7150b85e8bba97fdae7d892f7bfd12e4601307e4721dcerion   /* XFX-Form */
715176de5cf615380b23b4b5bcced6541233cd4a93a0cerion   UChar rS_addr  = rD_addr;
715276de5cf615380b23b4b5bcced6541233cd4a93a0cerion   UInt  SPR      = b11to20;
7153edf7fc572e2decb93e9143961e8739c8fe18899dcerion   UInt  TBR      = b11to20;
715476de5cf615380b23b4b5bcced6541233cd4a93a0cerion   UChar b20      = toUChar( IFIELD( theInstr, 20, 1 ) );
715576de5cf615380b23b4b5bcced6541233cd4a93a0cerion   UInt  CRM      = IFIELD( theInstr, 12, 8 );
715676de5cf615380b23b4b5bcced6541233cd4a93a0cerion   UChar b11      = toUChar( IFIELD( theInstr, 11, 1 ) );
7157e9d361ab43518b6dfbd3d846f48859534659dee0cerion
715876de5cf615380b23b4b5bcced6541233cd4a93a0cerion   UInt  opc2     = ifieldOPClo10(theInstr);
715976de5cf615380b23b4b5bcced6541233cd4a93a0cerion   UChar b0       = ifieldBIT0(theInstr);
716076de5cf615380b23b4b5bcced6541233cd4a93a0cerion
71612831b00c4950d6c2b061def05fd67528fe132ececerion   IRType ty = mode64 ? Ity_I64 : Ity_I32;
7162f0de28cf1a762b0d6f74c93d3532c89a230673bbcerion   IRTemp rS = newTemp(ty);
7163d953ebb9b04cbad6891676df597bf0c542b1ec89cerion   assign( rS, getIReg(rS_addr) );
716441a7b70f888cf73cf3da6a53b31937ce0d26e8f4sewardj
716576de5cf615380b23b4b5bcced6541233cd4a93a0cerion   /* Reorder SPR field as per PPC32 p470 */
716676de5cf615380b23b4b5bcced6541233cd4a93a0cerion   SPR = ((SPR & 0x1F) << 5) | ((SPR >> 5) & 0x1F);
716773a9197285975856fd3cc577216237afb3612b09sewardj   /* Reorder TBR field as per PPC32 p475 */
716873a9197285975856fd3cc577216237afb3612b09sewardj   TBR = ((TBR & 31) << 5) | ((TBR >> 5) & 31);
7169b85e8bba97fdae7d892f7bfd12e4601307e4721dcerion
717048ae46b56cef87c90638b25d6b2462c475033da8carll   /* b0 = 0, inst is treated as floating point inst for reservation purposes
717148ae46b56cef87c90638b25d6b2462c475033da8carll    * b0 = 1, inst is treated as vector inst for reservation purposes
717248ae46b56cef87c90638b25d6b2462c475033da8carll    */
717348ae46b56cef87c90638b25d6b2462c475033da8carll   if (opc1 != 0x1F) {
717448ae46b56cef87c90638b25d6b2462c475033da8carll      vex_printf("dis_proc_ctl(ppc)(opc1|b%d)\n", b0);
7175b85e8bba97fdae7d892f7bfd12e4601307e4721dcerion      return False;
7176b85e8bba97fdae7d892f7bfd12e4601307e4721dcerion   }
7177b85e8bba97fdae7d892f7bfd12e4601307e4721dcerion
7178b85e8bba97fdae7d892f7bfd12e4601307e4721dcerion   switch (opc2) {
7179cb14e73e1556145a29ae2c8f4f7ab73cf2963864cerion   /* X-Form */
71805b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion   case 0x200: { // mcrxr (Move to Cond Register from XER, PPC32 p466)
7181cb14e73e1556145a29ae2c8f4f7ab73cf2963864cerion      if (b21to22 != 0 || b11to20 != 0) {
71825b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion         vex_printf("dis_proc_ctl(ppc)(mcrxr,b21to22|b11to20)\n");
7183cb14e73e1556145a29ae2c8f4f7ab73cf2963864cerion         return False;
7184cb14e73e1556145a29ae2c8f4f7ab73cf2963864cerion      }
7185cb14e73e1556145a29ae2c8f4f7ab73cf2963864cerion      DIP("mcrxr crf%d\n", crfD);
7186edf7fc572e2decb93e9143961e8739c8fe18899dcerion      /* Move XER[0-3] (the top 4 bits of XER) to CR[crfD] */
7187d953ebb9b04cbad6891676df597bf0c542b1ec89cerion      putGST_field( PPC_GST_CR,
7188d953ebb9b04cbad6891676df597bf0c542b1ec89cerion                    getGST_field( PPC_GST_XER, 7 ),
7189edf7fc572e2decb93e9143961e8739c8fe18899dcerion                    crfD );
719055ccc3ea848c351639321085df6a41cf6149d030sewardj
719155ccc3ea848c351639321085df6a41cf6149d030sewardj      // Clear XER[0-3]
7192edf7fc572e2decb93e9143961e8739c8fe18899dcerion      putXER_SO( mkU8(0) );
7193edf7fc572e2decb93e9143961e8739c8fe18899dcerion      putXER_OV( mkU8(0) );
7194edf7fc572e2decb93e9143961e8739c8fe18899dcerion      putXER_CA( mkU8(0) );
7195cb14e73e1556145a29ae2c8f4f7ab73cf2963864cerion      break;
719655ccc3ea848c351639321085df6a41cf6149d030sewardj   }
7197b85e8bba97fdae7d892f7bfd12e4601307e4721dcerion
719872aefb29456a7a9c10f943f9557347d93b778530sewardj   case 0x013:
719972aefb29456a7a9c10f943f9557347d93b778530sewardj      // b11to20==0:      mfcr (Move from Cond Register, PPC32 p467)
720072aefb29456a7a9c10f943f9557347d93b778530sewardj      // b20==1 & b11==0: mfocrf (Move from One CR Field)
720172aefb29456a7a9c10f943f9557347d93b778530sewardj      // However it seems that the 'mfcr' behaviour is an acceptable
720272aefb29456a7a9c10f943f9557347d93b778530sewardj      // implementation of mfocr (from the 2.02 arch spec)
720372aefb29456a7a9c10f943f9557347d93b778530sewardj      if (b11to20 == 0) {
720472aefb29456a7a9c10f943f9557347d93b778530sewardj         DIP("mfcr r%u\n", rD_addr);
7205e9d8a26b690c2561ac54ab0cd6ad83ecbadcbe76sewardj         putIReg( rD_addr, mkWidenFrom32(ty, getGST( PPC_GST_CR ),
7206e9d8a26b690c2561ac54ab0cd6ad83ecbadcbe76sewardj                                         /* Signed */False) );
720772aefb29456a7a9c10f943f9557347d93b778530sewardj         break;
7208b85e8bba97fdae7d892f7bfd12e4601307e4721dcerion      }
720972aefb29456a7a9c10f943f9557347d93b778530sewardj      if (b20 == 1 && b11 == 0) {
721072aefb29456a7a9c10f943f9557347d93b778530sewardj         DIP("mfocrf r%u,%u\n", rD_addr, CRM);
7211e9d8a26b690c2561ac54ab0cd6ad83ecbadcbe76sewardj         putIReg( rD_addr, mkWidenFrom32(ty, getGST( PPC_GST_CR ),
7212e9d8a26b690c2561ac54ab0cd6ad83ecbadcbe76sewardj                                         /* Signed */False) );
721372aefb29456a7a9c10f943f9557347d93b778530sewardj         break;
721472aefb29456a7a9c10f943f9557347d93b778530sewardj      }
721572aefb29456a7a9c10f943f9557347d93b778530sewardj      /* not decodable */
721672aefb29456a7a9c10f943f9557347d93b778530sewardj      return False;
72170c74bb5aa3240f693df0568d578baabf0c376dc4carll
7218b85e8bba97fdae7d892f7bfd12e4601307e4721dcerion   /* XFX-Form */
7219e9d361ab43518b6dfbd3d846f48859534659dee0cerion   case 0x153: // mfspr (Move from Special-Purpose Register, PPC32 p470)
7220b85e8bba97fdae7d892f7bfd12e4601307e4721dcerion
722176de5cf615380b23b4b5bcced6541233cd4a93a0cerion      switch (SPR) {  // Choose a register...
7222d953ebb9b04cbad6891676df597bf0c542b1ec89cerion      case 0x1:
7223d953ebb9b04cbad6891676df597bf0c542b1ec89cerion         DIP("mfxer r%u\n", rD_addr);
7224e9d8a26b690c2561ac54ab0cd6ad83ecbadcbe76sewardj         putIReg( rD_addr, mkWidenFrom32(ty, getGST( PPC_GST_XER ),
7225e9d8a26b690c2561ac54ab0cd6ad83ecbadcbe76sewardj                                         /* Signed */False) );
7226d953ebb9b04cbad6891676df597bf0c542b1ec89cerion         break;
7227d953ebb9b04cbad6891676df597bf0c542b1ec89cerion      case 0x8:
7228d953ebb9b04cbad6891676df597bf0c542b1ec89cerion         DIP("mflr r%u\n", rD_addr);
7229d953ebb9b04cbad6891676df597bf0c542b1ec89cerion         putIReg( rD_addr, getGST( PPC_GST_LR ) );
7230d953ebb9b04cbad6891676df597bf0c542b1ec89cerion         break;
7231d953ebb9b04cbad6891676df597bf0c542b1ec89cerion      case 0x9:
7232d953ebb9b04cbad6891676df597bf0c542b1ec89cerion         DIP("mfctr r%u\n", rD_addr);
7233d953ebb9b04cbad6891676df597bf0c542b1ec89cerion         putIReg( rD_addr, getGST( PPC_GST_CTR ) );
7234d953ebb9b04cbad6891676df597bf0c542b1ec89cerion         break;
72358943d02aa373f45c6e5fdcbe5947620285d442b1carll      case 0x80:  // 128
72368943d02aa373f45c6e5fdcbe5947620285d442b1carll         DIP("mfspr r%u (TFHAR)\n", rD_addr);
72378943d02aa373f45c6e5fdcbe5947620285d442b1carll         putIReg( rD_addr, getGST( PPC_GST_TFHAR) );
72388943d02aa373f45c6e5fdcbe5947620285d442b1carll         break;
72398943d02aa373f45c6e5fdcbe5947620285d442b1carll      case 0x81:  // 129
72408943d02aa373f45c6e5fdcbe5947620285d442b1carll         DIP("mfspr r%u (TFIAR)\n", rD_addr);
72418943d02aa373f45c6e5fdcbe5947620285d442b1carll         putIReg( rD_addr, getGST( PPC_GST_TFIAR) );
72428943d02aa373f45c6e5fdcbe5947620285d442b1carll         break;
72438943d02aa373f45c6e5fdcbe5947620285d442b1carll      case 0x82:  // 130
72448943d02aa373f45c6e5fdcbe5947620285d442b1carll         DIP("mfspr r%u (TEXASR)\n", rD_addr);
72458943d02aa373f45c6e5fdcbe5947620285d442b1carll         putIReg( rD_addr, getGST( PPC_GST_TEXASR) );
72468943d02aa373f45c6e5fdcbe5947620285d442b1carll         break;
7247486db12d4767b5c2cc5ae764616e758f30ce21f5carll      case 0x83:  // 131
7248486db12d4767b5c2cc5ae764616e758f30ce21f5carll         DIP("mfspr r%u (TEXASRU)\n", rD_addr);
7249486db12d4767b5c2cc5ae764616e758f30ce21f5carll         putIReg( rD_addr, getGST( PPC_GST_TEXASRU) );
7250486db12d4767b5c2cc5ae764616e758f30ce21f5carll         break;
7251ed013fe8f56c070823d15f31ec010093f5de00dacarll      case 0x9F:  // 159
7252ed013fe8f56c070823d15f31ec010093f5de00dacarll         DIP("mfspr r%u (PSPB)\n", rD_addr);
7253ed013fe8f56c070823d15f31ec010093f5de00dacarll         putIReg( rD_addr, getGST( PPC_GST_PSPB) );
7254ed013fe8f56c070823d15f31ec010093f5de00dacarll         break;
7255ed013fe8f56c070823d15f31ec010093f5de00dacarll      case 0x380:  // 896
7256ed013fe8f56c070823d15f31ec010093f5de00dacarll         DIP("mfspr r%u (PPR)\n", rD_addr);
7257ed013fe8f56c070823d15f31ec010093f5de00dacarll         putIReg( rD_addr, getGST( PPC_GST_PPR) );
7258ed013fe8f56c070823d15f31ec010093f5de00dacarll         break;
7259ed013fe8f56c070823d15f31ec010093f5de00dacarll      case 0x382:  // 898
7260ed013fe8f56c070823d15f31ec010093f5de00dacarll         DIP("mfspr r%u (PPR)32\n", rD_addr);
7261ed013fe8f56c070823d15f31ec010093f5de00dacarll         putIReg( rD_addr, getGST( PPC_GST_PPR32) );
7262ed013fe8f56c070823d15f31ec010093f5de00dacarll         break;
7263d953ebb9b04cbad6891676df597bf0c542b1ec89cerion      case 0x100:
7264d953ebb9b04cbad6891676df597bf0c542b1ec89cerion         DIP("mfvrsave r%u\n", rD_addr);
7265e9d8a26b690c2561ac54ab0cd6ad83ecbadcbe76sewardj         putIReg( rD_addr, mkWidenFrom32(ty, getGST( PPC_GST_VRSAVE ),
7266e9d8a26b690c2561ac54ab0cd6ad83ecbadcbe76sewardj                                         /* Signed */False) );
7267d953ebb9b04cbad6891676df597bf0c542b1ec89cerion         break;
7268aca070a5b3418a6a9b01e3c57a7eb0fbb5050908sewardj
7269aca070a5b3418a6a9b01e3c57a7eb0fbb5050908sewardj      case 0x103:
7270aca070a5b3418a6a9b01e3c57a7eb0fbb5050908sewardj         DIP("mfspr r%u, SPRG3(readonly)\n", rD_addr);
7271aca070a5b3418a6a9b01e3c57a7eb0fbb5050908sewardj         putIReg( rD_addr, getGST( PPC_GST_SPRG3_RO ) );
7272aca070a5b3418a6a9b01e3c57a7eb0fbb5050908sewardj         break;
7273aca070a5b3418a6a9b01e3c57a7eb0fbb5050908sewardj
7274abb321cf9ad44ad0ac445250c31128452e316547sewardj      /* Even a lowly PPC7400 can run the associated helper, so no
7275abb321cf9ad44ad0ac445250c31128452e316547sewardj         obvious need for feature testing at this point. */
7276abb321cf9ad44ad0ac445250c31128452e316547sewardj      case 268 /* 0x10C */:
7277abb321cf9ad44ad0ac445250c31128452e316547sewardj      case 269 /* 0x10D */: {
7278abb321cf9ad44ad0ac445250c31128452e316547sewardj         UInt     arg  = SPR==268 ? 0 : 1;
7279abb321cf9ad44ad0ac445250c31128452e316547sewardj         IRTemp   val  = newTemp(Ity_I32);
7280abb321cf9ad44ad0ac445250c31128452e316547sewardj         IRExpr** args = mkIRExprVec_1( mkU32(arg) );
7281abb321cf9ad44ad0ac445250c31128452e316547sewardj         IRDirty* d    = unsafeIRDirty_1_N(
7282abb321cf9ad44ad0ac445250c31128452e316547sewardj                            val,
7283abb321cf9ad44ad0ac445250c31128452e316547sewardj                            0/*regparms*/,
7284abb321cf9ad44ad0ac445250c31128452e316547sewardj                            "ppc32g_dirtyhelper_MFSPR_268_269",
7285abb321cf9ad44ad0ac445250c31128452e316547sewardj                            fnptr_to_fnentry
7286abb321cf9ad44ad0ac445250c31128452e316547sewardj                               (vbi, &ppc32g_dirtyhelper_MFSPR_268_269),
7287abb321cf9ad44ad0ac445250c31128452e316547sewardj                            args
7288abb321cf9ad44ad0ac445250c31128452e316547sewardj                         );
7289abb321cf9ad44ad0ac445250c31128452e316547sewardj         /* execute the dirty call, dumping the result in val. */
7290abb321cf9ad44ad0ac445250c31128452e316547sewardj         stmt( IRStmt_Dirty(d) );
729137b2ee8724691d97860726ea2c59005b6b654892sewardj         putIReg( rD_addr,
729237b2ee8724691d97860726ea2c59005b6b654892sewardj                  mkWidenFrom32(ty, mkexpr(val), False/*unsigned*/) );
7293b173774421d015736c2316b5e6e998e7de545a5cflorian         DIP("mfspr r%u,%u", rD_addr, SPR);
729437b2ee8724691d97860726ea2c59005b6b654892sewardj         break;
729537b2ee8724691d97860726ea2c59005b6b654892sewardj      }
729637b2ee8724691d97860726ea2c59005b6b654892sewardj
729737b2ee8724691d97860726ea2c59005b6b654892sewardj      /* Again, runs natively on PPC7400 (7447, really).  Not
729837b2ee8724691d97860726ea2c59005b6b654892sewardj         bothering with a feature test. */
729937b2ee8724691d97860726ea2c59005b6b654892sewardj      case 287: /* 0x11F */ {
730037b2ee8724691d97860726ea2c59005b6b654892sewardj         IRTemp   val  = newTemp(Ity_I32);
730137b2ee8724691d97860726ea2c59005b6b654892sewardj         IRExpr** args = mkIRExprVec_0();
730237b2ee8724691d97860726ea2c59005b6b654892sewardj         IRDirty* d    = unsafeIRDirty_1_N(
730337b2ee8724691d97860726ea2c59005b6b654892sewardj                            val,
730437b2ee8724691d97860726ea2c59005b6b654892sewardj                            0/*regparms*/,
730537b2ee8724691d97860726ea2c59005b6b654892sewardj                            "ppc32g_dirtyhelper_MFSPR_287",
730637b2ee8724691d97860726ea2c59005b6b654892sewardj                            fnptr_to_fnentry
730737b2ee8724691d97860726ea2c59005b6b654892sewardj                               (vbi, &ppc32g_dirtyhelper_MFSPR_287),
730837b2ee8724691d97860726ea2c59005b6b654892sewardj                            args
730937b2ee8724691d97860726ea2c59005b6b654892sewardj                         );
731037b2ee8724691d97860726ea2c59005b6b654892sewardj         /* execute the dirty call, dumping the result in val. */
731137b2ee8724691d97860726ea2c59005b6b654892sewardj         stmt( IRStmt_Dirty(d) );
731237b2ee8724691d97860726ea2c59005b6b654892sewardj         putIReg( rD_addr,
731337b2ee8724691d97860726ea2c59005b6b654892sewardj                  mkWidenFrom32(ty, mkexpr(val), False/*unsigned*/) );
7314b173774421d015736c2316b5e6e998e7de545a5cflorian         DIP("mfspr r%u,%u", rD_addr, SPR);
7315abb321cf9ad44ad0ac445250c31128452e316547sewardj         break;
7316abb321cf9ad44ad0ac445250c31128452e316547sewardj      }
7317abb321cf9ad44ad0ac445250c31128452e316547sewardj
7318d953ebb9b04cbad6891676df597bf0c542b1ec89cerion      default:
73195b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion         vex_printf("dis_proc_ctl(ppc)(mfspr,SPR)(0x%x)\n", SPR);
7320d953ebb9b04cbad6891676df597bf0c542b1ec89cerion         return False;
7321b85e8bba97fdae7d892f7bfd12e4601307e4721dcerion      }
7322b85e8bba97fdae7d892f7bfd12e4601307e4721dcerion      break;
7323b85e8bba97fdae7d892f7bfd12e4601307e4721dcerion
732473a9197285975856fd3cc577216237afb3612b09sewardj   case 0x173: { // mftb (Move from Time Base, PPC32 p475)
732573a9197285975856fd3cc577216237afb3612b09sewardj      IRTemp   val  = newTemp(Ity_I64);
732673a9197285975856fd3cc577216237afb3612b09sewardj      IRExpr** args = mkIRExprVec_0();
73274c4f5ef69f89a19844a22a34b7a0cb717f83f033cerion      IRDirty* d    = unsafeIRDirty_1_N(
73284c4f5ef69f89a19844a22a34b7a0cb717f83f033cerion                              val,
73294c4f5ef69f89a19844a22a34b7a0cb717f83f033cerion                              0/*regparms*/,
73304c4f5ef69f89a19844a22a34b7a0cb717f83f033cerion                              "ppcg_dirtyhelper_MFTB",
7331dd40fdf58cc8a6fe9466c4f00bdfc9fe9bf00449sewardj                              fnptr_to_fnentry(vbi, &ppcg_dirtyhelper_MFTB),
73324c4f5ef69f89a19844a22a34b7a0cb717f83f033cerion                              args );
733373a9197285975856fd3cc577216237afb3612b09sewardj      /* execute the dirty call, dumping the result in val. */
733473a9197285975856fd3cc577216237afb3612b09sewardj      stmt( IRStmt_Dirty(d) );
733573a9197285975856fd3cc577216237afb3612b09sewardj
733673a9197285975856fd3cc577216237afb3612b09sewardj      switch (TBR) {
7337d953ebb9b04cbad6891676df597bf0c542b1ec89cerion      case 269:
7338d953ebb9b04cbad6891676df597bf0c542b1ec89cerion         DIP("mftbu r%u", rD_addr);
73392831b00c4950d6c2b061def05fd67528fe132ececerion         putIReg( rD_addr,
7340e9d8a26b690c2561ac54ab0cd6ad83ecbadcbe76sewardj                  mkWidenFrom32(ty, unop(Iop_64HIto32, mkexpr(val)),
7341e9d8a26b690c2561ac54ab0cd6ad83ecbadcbe76sewardj                                /* Signed */False) );
7342d953ebb9b04cbad6891676df597bf0c542b1ec89cerion         break;
7343d953ebb9b04cbad6891676df597bf0c542b1ec89cerion      case 268:
7344d953ebb9b04cbad6891676df597bf0c542b1ec89cerion         DIP("mftb r%u", rD_addr);
73452831b00c4950d6c2b061def05fd67528fe132ececerion         putIReg( rD_addr, (mode64) ? mkexpr(val) :
73462831b00c4950d6c2b061def05fd67528fe132ececerion                                      unop(Iop_64to32, mkexpr(val)) );
7347d953ebb9b04cbad6891676df597bf0c542b1ec89cerion         break;
7348d953ebb9b04cbad6891676df597bf0c542b1ec89cerion      default:
7349d953ebb9b04cbad6891676df597bf0c542b1ec89cerion         return False; /* illegal instruction */
735073a9197285975856fd3cc577216237afb3612b09sewardj      }
735173a9197285975856fd3cc577216237afb3612b09sewardj      break;
735273a9197285975856fd3cc577216237afb3612b09sewardj   }
735373a9197285975856fd3cc577216237afb3612b09sewardj
735472aefb29456a7a9c10f943f9557347d93b778530sewardj   case 0x090: {
735572aefb29456a7a9c10f943f9557347d93b778530sewardj      // b20==0: mtcrf (Move to Cond Register Fields, PPC32 p477)
735672aefb29456a7a9c10f943f9557347d93b778530sewardj      // b20==1: mtocrf (Move to One Cond Reg Field)
7357edf7fc572e2decb93e9143961e8739c8fe18899dcerion      Int   cr;
7358edf7fc572e2decb93e9143961e8739c8fe18899dcerion      UChar shft;
735972aefb29456a7a9c10f943f9557347d93b778530sewardj      if (b11 != 0)
7360b85e8bba97fdae7d892f7bfd12e4601307e4721dcerion         return False;
736172aefb29456a7a9c10f943f9557347d93b778530sewardj      if (b20 == 1) {
736272aefb29456a7a9c10f943f9557347d93b778530sewardj         /* ppc64 v2.02 spec says mtocrf gives undefined outcome if >
736372aefb29456a7a9c10f943f9557347d93b778530sewardj            1 field is written.  It seems more robust to decline to
736472aefb29456a7a9c10f943f9557347d93b778530sewardj            decode the insn if so. */
736572aefb29456a7a9c10f943f9557347d93b778530sewardj         switch (CRM) {
736672aefb29456a7a9c10f943f9557347d93b778530sewardj            case 0x01: case 0x02: case 0x04: case 0x08:
736772aefb29456a7a9c10f943f9557347d93b778530sewardj            case 0x10: case 0x20: case 0x40: case 0x80:
736872aefb29456a7a9c10f943f9557347d93b778530sewardj               break;
736972aefb29456a7a9c10f943f9557347d93b778530sewardj            default:
737072aefb29456a7a9c10f943f9557347d93b778530sewardj               return False;
737172aefb29456a7a9c10f943f9557347d93b778530sewardj         }
7372b85e8bba97fdae7d892f7bfd12e4601307e4721dcerion      }
737372aefb29456a7a9c10f943f9557347d93b778530sewardj      DIP("%s 0x%x,r%u\n", b20==1 ? "mtocrf" : "mtcrf",
737472aefb29456a7a9c10f943f9557347d93b778530sewardj                           CRM, rS_addr);
7375edf7fc572e2decb93e9143961e8739c8fe18899dcerion      /* Write to each field specified by CRM */
7376edf7fc572e2decb93e9143961e8739c8fe18899dcerion      for (cr = 0; cr < 8; cr++) {
7377edf7fc572e2decb93e9143961e8739c8fe18899dcerion         if ((CRM & (1 << (7-cr))) == 0)
7378edf7fc572e2decb93e9143961e8739c8fe18899dcerion            continue;
7379edf7fc572e2decb93e9143961e8739c8fe18899dcerion         shft = 4*(7-cr);
7380d953ebb9b04cbad6891676df597bf0c542b1ec89cerion         putGST_field( PPC_GST_CR,
73812831b00c4950d6c2b061def05fd67528fe132ececerion                       binop(Iop_Shr32,
7382e9d8a26b690c2561ac54ab0cd6ad83ecbadcbe76sewardj                             mkNarrowTo32(ty, mkexpr(rS)),
73832831b00c4950d6c2b061def05fd67528fe132ececerion                             mkU8(shft)), cr );
7384edf7fc572e2decb93e9143961e8739c8fe18899dcerion      }
7385b85e8bba97fdae7d892f7bfd12e4601307e4721dcerion      break;
7386edf7fc572e2decb93e9143961e8739c8fe18899dcerion   }
7387e9d361ab43518b6dfbd3d846f48859534659dee0cerion
7388e9d361ab43518b6dfbd3d846f48859534659dee0cerion   case 0x1D3: // mtspr (Move to Special-Purpose Register, PPC32 p483)
7389b85e8bba97fdae7d892f7bfd12e4601307e4721dcerion
739076de5cf615380b23b4b5bcced6541233cd4a93a0cerion      switch (SPR) {  // Choose a register...
7391d953ebb9b04cbad6891676df597bf0c542b1ec89cerion      case 0x1:
7392d953ebb9b04cbad6891676df597bf0c542b1ec89cerion         DIP("mtxer r%u\n", rS_addr);
7393e9d8a26b690c2561ac54ab0cd6ad83ecbadcbe76sewardj         putGST( PPC_GST_XER, mkNarrowTo32(ty, mkexpr(rS)) );
7394d953ebb9b04cbad6891676df597bf0c542b1ec89cerion         break;
7395d953ebb9b04cbad6891676df597bf0c542b1ec89cerion      case 0x8:
7396d953ebb9b04cbad6891676df597bf0c542b1ec89cerion         DIP("mtlr r%u\n", rS_addr);
7397d953ebb9b04cbad6891676df597bf0c542b1ec89cerion         putGST( PPC_GST_LR, mkexpr(rS) );
7398d953ebb9b04cbad6891676df597bf0c542b1ec89cerion         break;
7399d953ebb9b04cbad6891676df597bf0c542b1ec89cerion      case 0x9:
7400d953ebb9b04cbad6891676df597bf0c542b1ec89cerion         DIP("mtctr r%u\n", rS_addr);
7401d953ebb9b04cbad6891676df597bf0c542b1ec89cerion         putGST( PPC_GST_CTR, mkexpr(rS) );
7402d953ebb9b04cbad6891676df597bf0c542b1ec89cerion         break;
7403d953ebb9b04cbad6891676df597bf0c542b1ec89cerion      case 0x100:
7404d953ebb9b04cbad6891676df597bf0c542b1ec89cerion         DIP("mtvrsave r%u\n", rS_addr);
7405e9d8a26b690c2561ac54ab0cd6ad83ecbadcbe76sewardj         putGST( PPC_GST_VRSAVE, mkNarrowTo32(ty, mkexpr(rS)) );
7406d953ebb9b04cbad6891676df597bf0c542b1ec89cerion         break;
74078943d02aa373f45c6e5fdcbe5947620285d442b1carll      case 0x80:  // 128
74088943d02aa373f45c6e5fdcbe5947620285d442b1carll         DIP("mtspr r%u (TFHAR)\n", rS_addr);
74098943d02aa373f45c6e5fdcbe5947620285d442b1carll         putGST( PPC_GST_TFHAR, mkexpr(rS) );
74108943d02aa373f45c6e5fdcbe5947620285d442b1carll         break;
74118943d02aa373f45c6e5fdcbe5947620285d442b1carll      case 0x81:  // 129
74128943d02aa373f45c6e5fdcbe5947620285d442b1carll         DIP("mtspr r%u (TFIAR)\n", rS_addr);
74138943d02aa373f45c6e5fdcbe5947620285d442b1carll         putGST( PPC_GST_TFIAR, mkexpr(rS) );
74148943d02aa373f45c6e5fdcbe5947620285d442b1carll         break;
74158943d02aa373f45c6e5fdcbe5947620285d442b1carll      case 0x82:  // 130
74168943d02aa373f45c6e5fdcbe5947620285d442b1carll         DIP("mtspr r%u (TEXASR)\n", rS_addr);
74178943d02aa373f45c6e5fdcbe5947620285d442b1carll         putGST( PPC_GST_TEXASR, mkexpr(rS) );
74188943d02aa373f45c6e5fdcbe5947620285d442b1carll         break;
7419ed013fe8f56c070823d15f31ec010093f5de00dacarll      case 0x9F:  // 159
7420ed013fe8f56c070823d15f31ec010093f5de00dacarll         DIP("mtspr r%u (PSPB)\n", rS_addr);
7421ed013fe8f56c070823d15f31ec010093f5de00dacarll         putGST( PPC_GST_PSPB, mkexpr(rS) );
7422ed013fe8f56c070823d15f31ec010093f5de00dacarll         break;
7423ed013fe8f56c070823d15f31ec010093f5de00dacarll      case 0x380:  // 896
7424ed013fe8f56c070823d15f31ec010093f5de00dacarll         DIP("mtspr r%u (PPR)\n", rS_addr);
7425ed013fe8f56c070823d15f31ec010093f5de00dacarll         putGST( PPC_GST_PPR, mkexpr(rS) );
7426ed013fe8f56c070823d15f31ec010093f5de00dacarll         break;
7427ed013fe8f56c070823d15f31ec010093f5de00dacarll      case 0x382:  // 898
7428ed013fe8f56c070823d15f31ec010093f5de00dacarll         DIP("mtspr r%u (PPR32)\n", rS_addr);
7429ed013fe8f56c070823d15f31ec010093f5de00dacarll         putGST( PPC_GST_PPR32, mkexpr(rS) );
7430ed013fe8f56c070823d15f31ec010093f5de00dacarll         break;
7431d953ebb9b04cbad6891676df597bf0c542b1ec89cerion      default:
74325b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion         vex_printf("dis_proc_ctl(ppc)(mtspr,SPR)(%u)\n", SPR);
7433d953ebb9b04cbad6891676df597bf0c542b1ec89cerion         return False;
7434b85e8bba97fdae7d892f7bfd12e4601307e4721dcerion      }
7435b85e8bba97fdae7d892f7bfd12e4601307e4721dcerion      break;
74360c74bb5aa3240f693df0568d578baabf0c376dc4carll
74370c74bb5aa3240f693df0568d578baabf0c376dc4carll   case 0x33:                // mfvsrd
74380c74bb5aa3240f693df0568d578baabf0c376dc4carll   {
74390c74bb5aa3240f693df0568d578baabf0c376dc4carll      UChar XS = ifieldRegXS( theInstr );
74400c74bb5aa3240f693df0568d578baabf0c376dc4carll      UChar rA_addr = ifieldRegA(theInstr);
74410c74bb5aa3240f693df0568d578baabf0c376dc4carll      IRExpr * high64;
74420c74bb5aa3240f693df0568d578baabf0c376dc4carll      IRTemp vS = newTemp( Ity_V128 );
7443b173774421d015736c2316b5e6e998e7de545a5cflorian      DIP("mfvsrd r%u,vsr%d\n", rA_addr, XS);
74440c74bb5aa3240f693df0568d578baabf0c376dc4carll
74450c74bb5aa3240f693df0568d578baabf0c376dc4carll      /*  XS = SX || S
74460c74bb5aa3240f693df0568d578baabf0c376dc4carll       *  For SX=0, mfvsrd is treated as a Floating-Point
74470c74bb5aa3240f693df0568d578baabf0c376dc4carll       *            instruction in terms of resource availability.
74480c74bb5aa3240f693df0568d578baabf0c376dc4carll       *  For SX=1, mfvsrd is treated as a Vector instruction in
74490c74bb5aa3240f693df0568d578baabf0c376dc4carll       *            terms of resource availability.
745078850ae9874a90ea625fcee1fd4c359375b7b538carll       * FIXME: NEED TO FIGURE OUT HOW TO IMPLEMENT THE RESOURCE AVAILABILITY PART
74510c74bb5aa3240f693df0568d578baabf0c376dc4carll       */
74520c74bb5aa3240f693df0568d578baabf0c376dc4carll      assign( vS, getVSReg( XS ) );
74530c74bb5aa3240f693df0568d578baabf0c376dc4carll      high64 = unop( Iop_V128HIto64, mkexpr( vS ) );
74540c74bb5aa3240f693df0568d578baabf0c376dc4carll      putIReg( rA_addr, (mode64) ? high64 :
74550c74bb5aa3240f693df0568d578baabf0c376dc4carll      unop( Iop_64to32, high64 ) );
74560c74bb5aa3240f693df0568d578baabf0c376dc4carll      break;
74570c74bb5aa3240f693df0568d578baabf0c376dc4carll   }
74580c74bb5aa3240f693df0568d578baabf0c376dc4carll
745978850ae9874a90ea625fcee1fd4c359375b7b538carll   case 0x73:                // mfvsrwz
746078850ae9874a90ea625fcee1fd4c359375b7b538carll   {
746178850ae9874a90ea625fcee1fd4c359375b7b538carll      UChar XS = ifieldRegXS( theInstr );
746278850ae9874a90ea625fcee1fd4c359375b7b538carll      UChar rA_addr = ifieldRegA(theInstr);
746378850ae9874a90ea625fcee1fd4c359375b7b538carll      IRExpr * high64;
746478850ae9874a90ea625fcee1fd4c359375b7b538carll      IRTemp vS = newTemp( Ity_V128 );
7465b173774421d015736c2316b5e6e998e7de545a5cflorian      DIP("mfvsrwz r%u,vsr%d\n", rA_addr, XS);
746678850ae9874a90ea625fcee1fd4c359375b7b538carll      /*  XS = SX || S
746778850ae9874a90ea625fcee1fd4c359375b7b538carll       *  For SX=0, mfvsrwz is treated as a Floating-Point
746878850ae9874a90ea625fcee1fd4c359375b7b538carll       *            instruction in terms of resource availability.
746978850ae9874a90ea625fcee1fd4c359375b7b538carll       *  For SX=1, mfvsrwz is treated as a Vector instruction in
747078850ae9874a90ea625fcee1fd4c359375b7b538carll       *            terms of resource availability.
747178850ae9874a90ea625fcee1fd4c359375b7b538carll       * FIXME: NEED TO FIGURE OUT HOW TO IMPLEMENT THE RESOURCE AVAILABILITY PART
747278850ae9874a90ea625fcee1fd4c359375b7b538carll       */
747378850ae9874a90ea625fcee1fd4c359375b7b538carll
747478850ae9874a90ea625fcee1fd4c359375b7b538carll      assign( vS, getVSReg( XS ) );
747578850ae9874a90ea625fcee1fd4c359375b7b538carll      high64 = unop( Iop_V128HIto64, mkexpr( vS ) );
747678850ae9874a90ea625fcee1fd4c359375b7b538carll      /* move value to the destination setting the upper 32-bits to zero */
747778850ae9874a90ea625fcee1fd4c359375b7b538carll      putIReg( rA_addr, (mode64) ?
747878850ae9874a90ea625fcee1fd4c359375b7b538carll                                  binop( Iop_And64, high64, mkU64( 0xFFFFFFFF ) ) :
747978850ae9874a90ea625fcee1fd4c359375b7b538carll                                  unop(  Iop_64to32,
748078850ae9874a90ea625fcee1fd4c359375b7b538carll                                         binop( Iop_And64, high64, mkU64( 0xFFFFFFFF ) ) ) );
748178850ae9874a90ea625fcee1fd4c359375b7b538carll      break;
748278850ae9874a90ea625fcee1fd4c359375b7b538carll   }
748378850ae9874a90ea625fcee1fd4c359375b7b538carll
74840c74bb5aa3240f693df0568d578baabf0c376dc4carll   case 0xB3:                // mtvsrd
74850c74bb5aa3240f693df0568d578baabf0c376dc4carll   {
74860c74bb5aa3240f693df0568d578baabf0c376dc4carll      UChar XT = ifieldRegXT( theInstr );
74870c74bb5aa3240f693df0568d578baabf0c376dc4carll      UChar rA_addr = ifieldRegA(theInstr);
74880c74bb5aa3240f693df0568d578baabf0c376dc4carll      IRTemp rA = newTemp(ty);
7489b173774421d015736c2316b5e6e998e7de545a5cflorian      DIP("mtvsrd vsr%d,r%u\n", XT, rA_addr);
74900c74bb5aa3240f693df0568d578baabf0c376dc4carll      /*  XS = SX || S
74910c74bb5aa3240f693df0568d578baabf0c376dc4carll       *  For SX=0, mfvsrd is treated as a Floating-Point
74920c74bb5aa3240f693df0568d578baabf0c376dc4carll       *            instruction in terms of resource availability.
74930c74bb5aa3240f693df0568d578baabf0c376dc4carll       *  For SX=1, mfvsrd is treated as a Vector instruction in
74940c74bb5aa3240f693df0568d578baabf0c376dc4carll       *            terms of resource availability.
749578850ae9874a90ea625fcee1fd4c359375b7b538carll       * FIXME: NEED TO FIGURE OUT HOW TO IMPLEMENT THE RESOURCE AVAILABILITY PART
74960c74bb5aa3240f693df0568d578baabf0c376dc4carll       */
74970c74bb5aa3240f693df0568d578baabf0c376dc4carll      assign( rA, getIReg(rA_addr) );
74980c74bb5aa3240f693df0568d578baabf0c376dc4carll
74990c74bb5aa3240f693df0568d578baabf0c376dc4carll      if (mode64)
75000c74bb5aa3240f693df0568d578baabf0c376dc4carll         putVSReg( XT, binop( Iop_64HLtoV128, mkexpr( rA ), mkU64( 0 ) ) );
75010c74bb5aa3240f693df0568d578baabf0c376dc4carll      else
75020c74bb5aa3240f693df0568d578baabf0c376dc4carll         putVSReg( XT, binop( Iop_64HLtoV128,
75030c74bb5aa3240f693df0568d578baabf0c376dc4carll                              binop( Iop_32HLto64,
75040c74bb5aa3240f693df0568d578baabf0c376dc4carll                                     mkU32( 0 ),
75050c74bb5aa3240f693df0568d578baabf0c376dc4carll                                     mkexpr( rA ) ),
75060c74bb5aa3240f693df0568d578baabf0c376dc4carll                                     mkU64( 0 ) ) );
75070c74bb5aa3240f693df0568d578baabf0c376dc4carll      break;
75080c74bb5aa3240f693df0568d578baabf0c376dc4carll   }
75090c74bb5aa3240f693df0568d578baabf0c376dc4carll
75100c74bb5aa3240f693df0568d578baabf0c376dc4carll   case 0xD3:                // mtvsrwa
75110c74bb5aa3240f693df0568d578baabf0c376dc4carll   {
75120c74bb5aa3240f693df0568d578baabf0c376dc4carll      UChar XT = ifieldRegXT( theInstr );
75130c74bb5aa3240f693df0568d578baabf0c376dc4carll      UChar rA_addr = ifieldRegA(theInstr);
75140c74bb5aa3240f693df0568d578baabf0c376dc4carll      IRTemp rA = newTemp( Ity_I32 );
7515b173774421d015736c2316b5e6e998e7de545a5cflorian      DIP("mtvsrwa vsr%d,r%u\n", XT, rA_addr);
75160c74bb5aa3240f693df0568d578baabf0c376dc4carll      /*  XS = SX || S
75170c74bb5aa3240f693df0568d578baabf0c376dc4carll       *  For SX=0, mtvsrwa is treated as a Floating-Point
75180c74bb5aa3240f693df0568d578baabf0c376dc4carll       *            instruction in terms of resource availability.
75190c74bb5aa3240f693df0568d578baabf0c376dc4carll       *  For SX=1, mtvsrwa is treated as a Vector instruction in
75200c74bb5aa3240f693df0568d578baabf0c376dc4carll       *            terms of resource availability.
752178850ae9874a90ea625fcee1fd4c359375b7b538carll       * FIXME: NEED TO FIGURE OUT HOW TO IMPLEMENT THE RESOURCE AVAILABILITY PART
75220c74bb5aa3240f693df0568d578baabf0c376dc4carll       */
75230c74bb5aa3240f693df0568d578baabf0c376dc4carll      if (mode64)
75240c74bb5aa3240f693df0568d578baabf0c376dc4carll         assign( rA, unop( Iop_64to32, getIReg( rA_addr ) ) );
75250c74bb5aa3240f693df0568d578baabf0c376dc4carll      else
75260c74bb5aa3240f693df0568d578baabf0c376dc4carll         assign( rA, getIReg(rA_addr) );
75270c74bb5aa3240f693df0568d578baabf0c376dc4carll
75280c74bb5aa3240f693df0568d578baabf0c376dc4carll      putVSReg( XT, binop( Iop_64HLtoV128,
75290c74bb5aa3240f693df0568d578baabf0c376dc4carll                           unop( Iop_32Sto64, mkexpr( rA ) ),
75300c74bb5aa3240f693df0568d578baabf0c376dc4carll                           mkU64( 0 ) ) );
75310c74bb5aa3240f693df0568d578baabf0c376dc4carll      break;
75320c74bb5aa3240f693df0568d578baabf0c376dc4carll   }
75330c74bb5aa3240f693df0568d578baabf0c376dc4carll
753478850ae9874a90ea625fcee1fd4c359375b7b538carll   case 0xF3:                // mtvsrwz
753578850ae9874a90ea625fcee1fd4c359375b7b538carll      {
753678850ae9874a90ea625fcee1fd4c359375b7b538carll         UChar XT = ifieldRegXT( theInstr );
753778850ae9874a90ea625fcee1fd4c359375b7b538carll         UChar rA_addr = ifieldRegA(theInstr);
753878850ae9874a90ea625fcee1fd4c359375b7b538carll         IRTemp rA = newTemp( Ity_I32 );
7539b173774421d015736c2316b5e6e998e7de545a5cflorian         DIP("mtvsrwz vsr%d,r%u\n", rA_addr, XT);
754078850ae9874a90ea625fcee1fd4c359375b7b538carll         /*  XS = SX || S
754178850ae9874a90ea625fcee1fd4c359375b7b538carll          *  For SX=0, mtvsrwz is treated as a Floating-Point
754278850ae9874a90ea625fcee1fd4c359375b7b538carll          *            instruction in terms of resource availability.
754378850ae9874a90ea625fcee1fd4c359375b7b538carll          *  For SX=1, mtvsrwz is treated as a Vector instruction in
754478850ae9874a90ea625fcee1fd4c359375b7b538carll          *            terms of resource availability.
754578850ae9874a90ea625fcee1fd4c359375b7b538carll          * FIXME: NEED TO FIGURE OUT HOW TO IMPLEMENT THE RESOURCE AVAILABILITY PART
754678850ae9874a90ea625fcee1fd4c359375b7b538carll          */
754778850ae9874a90ea625fcee1fd4c359375b7b538carll         if (mode64)
754878850ae9874a90ea625fcee1fd4c359375b7b538carll             assign( rA, unop( Iop_64to32, getIReg( rA_addr ) ) );
754978850ae9874a90ea625fcee1fd4c359375b7b538carll         else
755078850ae9874a90ea625fcee1fd4c359375b7b538carll             assign( rA, getIReg(rA_addr) );
755178850ae9874a90ea625fcee1fd4c359375b7b538carll
755278850ae9874a90ea625fcee1fd4c359375b7b538carll         putVSReg( XT, binop( Iop_64HLtoV128,
755378850ae9874a90ea625fcee1fd4c359375b7b538carll                              binop( Iop_32HLto64, mkU32( 0 ), mkexpr ( rA ) ),
755478850ae9874a90ea625fcee1fd4c359375b7b538carll                              mkU64( 0 ) ) );
755578850ae9874a90ea625fcee1fd4c359375b7b538carll         break;
755678850ae9874a90ea625fcee1fd4c359375b7b538carll      }
755778850ae9874a90ea625fcee1fd4c359375b7b538carll
7558b85e8bba97fdae7d892f7bfd12e4601307e4721dcerion   default:
75595b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion      vex_printf("dis_proc_ctl(ppc)(opc2)\n");
7560b85e8bba97fdae7d892f7bfd12e4601307e4721dcerion      return False;
7561b85e8bba97fdae7d892f7bfd12e4601307e4721dcerion   }
7562b85e8bba97fdae7d892f7bfd12e4601307e4721dcerion   return True;
75638c3addacc8343f5d1504379e303934f8ed88903ecerion}
75648c3addacc8343f5d1504379e303934f8ed88903ecerion
75658c3addacc8343f5d1504379e303934f8ed88903ecerion
75663d870a39e4d145e2f3d9f9a0eeed3475ec934ac1cerion/*
75673d870a39e4d145e2f3d9f9a0eeed3475ec934ac1cerion  Cache Management Instructions
75683d870a39e4d145e2f3d9f9a0eeed3475ec934ac1cerion*/
7569d94b73a4ece194130f7a59cca9262d44cf9dbb91sewardjstatic Bool dis_cache_manage ( UInt         theInstr,
75709e6491ab55324b8e45e187b1e1e9632ac3cb3e27sewardj                               DisResult*   dres,
7571cacba8e675988fbf21b08feea1f317a9c896c053florian                               const VexArchInfo* guest_archinfo )
75728c3addacc8343f5d1504379e303934f8ed88903ecerion{
7573b85e8bba97fdae7d892f7bfd12e4601307e4721dcerion   /* X-Form */
757476de5cf615380b23b4b5bcced6541233cd4a93a0cerion   UChar opc1    = ifieldOPC(theInstr);
757576de5cf615380b23b4b5bcced6541233cd4a93a0cerion   UChar b21to25 = ifieldRegDS(theInstr);
757676de5cf615380b23b4b5bcced6541233cd4a93a0cerion   UChar rA_addr = ifieldRegA(theInstr);
757776de5cf615380b23b4b5bcced6541233cd4a93a0cerion   UChar rB_addr = ifieldRegB(theInstr);
757876de5cf615380b23b4b5bcced6541233cd4a93a0cerion   UInt  opc2    = ifieldOPClo10(theInstr);
757976de5cf615380b23b4b5bcced6541233cd4a93a0cerion   UChar b0      = ifieldBIT0(theInstr);
75809138b1779efcff4b12896ccd10744d8118e89a70florian   UInt  lineszB = guest_archinfo->ppc_icache_line_szB;
7581e971c6a8b613ab2ea92a34f802a0e39c01e84b19sewardj   Bool  is_dcbzl = False;
7582d953ebb9b04cbad6891676df597bf0c542b1ec89cerion
7583d953ebb9b04cbad6891676df597bf0c542b1ec89cerion   IRType ty     = mode64 ? Ity_I64 : Ity_I32;
7584094d1397b3f69b1a538e80ab509ea8cd75f4be3bcerion
7585b77db0e0f00084ea3437887f835f502ef0dcbc88carll   // Check for valid hint values for dcbt and dcbtst as currently described in
7586b77db0e0f00084ea3437887f835f502ef0dcbc88carll   // ISA 2.07.  If valid, then we simply set b21to25 to zero since we have no
7587b77db0e0f00084ea3437887f835f502ef0dcbc88carll   // means of modeling the hint anyway.
7588b77db0e0f00084ea3437887f835f502ef0dcbc88carll   if (opc1 == 0x1F && ((opc2 == 0x116) || (opc2 == 0xF6))) {
75899708b6ac7026b33277e01044d6ab82666048eedacarll      if (b21to25 == 0x10 || b21to25 < 0x10)
7590b77db0e0f00084ea3437887f835f502ef0dcbc88carll         b21to25 = 0;
75916be67235ba2829b0bc34c3a0876cee4eac340d95sewardj   }
75929708b6ac7026b33277e01044d6ab82666048eedacarll   if (opc1 == 0x1F && opc2 == 0x116 && b21to25 == 0x11)
7593b77db0e0f00084ea3437887f835f502ef0dcbc88carll      b21to25 = 0;
7594b77db0e0f00084ea3437887f835f502ef0dcbc88carll
7595e971c6a8b613ab2ea92a34f802a0e39c01e84b19sewardj   if (opc1 == 0x1F && opc2 == 0x3F6) { // dcbz
7596e971c6a8b613ab2ea92a34f802a0e39c01e84b19sewardj      if (b21to25 == 1) {
7597e971c6a8b613ab2ea92a34f802a0e39c01e84b19sewardj         is_dcbzl = True;
7598e971c6a8b613ab2ea92a34f802a0e39c01e84b19sewardj         b21to25 = 0;
7599e971c6a8b613ab2ea92a34f802a0e39c01e84b19sewardj         if (!(guest_archinfo->ppc_dcbzl_szB)) {
7600e971c6a8b613ab2ea92a34f802a0e39c01e84b19sewardj            vex_printf("dis_cache_manage(ppc)(dcbzl not supported by host)\n");
7601e971c6a8b613ab2ea92a34f802a0e39c01e84b19sewardj            return False;
7602e971c6a8b613ab2ea92a34f802a0e39c01e84b19sewardj         }
7603e971c6a8b613ab2ea92a34f802a0e39c01e84b19sewardj      }
7604e971c6a8b613ab2ea92a34f802a0e39c01e84b19sewardj   }
76056be67235ba2829b0bc34c3a0876cee4eac340d95sewardj
7606646a4fa91089f1c560a697faa850f54ca988c1a6carll   if (opc1 != 0x1F || b0 != 0) {
7607b6bea7d1595cf0e9d9f8d2ad2695ddace8a5d844carll      if (0) vex_printf("dis_cache_manage %d %d\n",
7608b173774421d015736c2316b5e6e998e7de545a5cflorian                        opc1, b0);
7609646a4fa91089f1c560a697faa850f54ca988c1a6carll      vex_printf("dis_cache_manage(ppc)(opc1|b0)\n");
7610b85e8bba97fdae7d892f7bfd12e4601307e4721dcerion      return False;
7611b85e8bba97fdae7d892f7bfd12e4601307e4721dcerion   }
7612d94b73a4ece194130f7a59cca9262d44cf9dbb91sewardj
7613d94b73a4ece194130f7a59cca9262d44cf9dbb91sewardj   /* stay sane .. */
76142691a61715853cb3e3ca7b4a1abb0e986ced5e66sewardj   vassert(lineszB == 16 || lineszB == 32 || lineszB == 64 || lineszB == 128);
7615b85e8bba97fdae7d892f7bfd12e4601307e4721dcerion
7616b85e8bba97fdae7d892f7bfd12e4601307e4721dcerion   switch (opc2) {
7617b51f0f4f33256638ed953156a2635aa739b232f1sewardj//zz    case 0x2F6: // dcba (Data Cache Block Allocate, PPC32 p380)
7618b51f0f4f33256638ed953156a2635aa739b232f1sewardj//zz       vassert(0); /* AWAITING TEST CASE */
7619d953ebb9b04cbad6891676df597bf0c542b1ec89cerion//zz       DIP("dcba r%u,r%u\n", rA_addr, rB_addr);
76205b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion//zz       if (0) vex_printf("vex ppc->IR: kludged dcba\n");
7621b51f0f4f33256638ed953156a2635aa739b232f1sewardj//zz       break;
762220ef5472eac767474c93b7835364a23f24c0ec5dsewardj
762320ef5472eac767474c93b7835364a23f24c0ec5dsewardj   case 0x056: // dcbf (Data Cache Block Flush, PPC32 p382)
7624d953ebb9b04cbad6891676df597bf0c542b1ec89cerion      DIP("dcbf r%u,r%u\n", rA_addr, rB_addr);
762520ef5472eac767474c93b7835364a23f24c0ec5dsewardj      /* nop as far as vex is concerned */
762620ef5472eac767474c93b7835364a23f24c0ec5dsewardj      break;
7627b85e8bba97fdae7d892f7bfd12e4601307e4721dcerion
7628e9d361ab43518b6dfbd3d846f48859534659dee0cerion   case 0x036: // dcbst (Data Cache Block Store, PPC32 p384)
7629d953ebb9b04cbad6891676df597bf0c542b1ec89cerion      DIP("dcbst r%u,r%u\n", rA_addr, rB_addr);
7630b51f0f4f33256638ed953156a2635aa739b232f1sewardj      /* nop as far as vex is concerned */
7631b85e8bba97fdae7d892f7bfd12e4601307e4721dcerion      break;
7632b85e8bba97fdae7d892f7bfd12e4601307e4721dcerion
7633e9d361ab43518b6dfbd3d846f48859534659dee0cerion   case 0x116: // dcbt (Data Cache Block Touch, PPC32 p385)
7634d953ebb9b04cbad6891676df597bf0c542b1ec89cerion      DIP("dcbt r%u,r%u\n", rA_addr, rB_addr);
7635b51f0f4f33256638ed953156a2635aa739b232f1sewardj      /* nop as far as vex is concerned */
7636b85e8bba97fdae7d892f7bfd12e4601307e4721dcerion      break;
7637b85e8bba97fdae7d892f7bfd12e4601307e4721dcerion
7638e9d361ab43518b6dfbd3d846f48859534659dee0cerion   case 0x0F6: // dcbtst (Data Cache Block Touch for Store, PPC32 p386)
7639d953ebb9b04cbad6891676df597bf0c542b1ec89cerion      DIP("dcbtst r%u,r%u\n", rA_addr, rB_addr);
7640b51f0f4f33256638ed953156a2635aa739b232f1sewardj      /* nop as far as vex is concerned */
7641b85e8bba97fdae7d892f7bfd12e4601307e4721dcerion      break;
7642b85e8bba97fdae7d892f7bfd12e4601307e4721dcerion
7643094d1397b3f69b1a538e80ab509ea8cd75f4be3bcerion   case 0x3F6: { // dcbz (Data Cache Block Clear to Zero, PPC32 p387)
7644e971c6a8b613ab2ea92a34f802a0e39c01e84b19sewardj                 // dcbzl (Data Cache Block Clear to Zero Long, bug#135264)
7645d94b73a4ece194130f7a59cca9262d44cf9dbb91sewardj      /* Clear all bytes in cache block at (rA|0) + rB. */
76462831b00c4950d6c2b061def05fd67528fe132ececerion      IRTemp  EA   = newTemp(ty);
76472831b00c4950d6c2b061def05fd67528fe132ececerion      IRTemp  addr = newTemp(ty);
7648094d1397b3f69b1a538e80ab509ea8cd75f4be3bcerion      IRExpr* irx_addr;
7649094d1397b3f69b1a538e80ab509ea8cd75f4be3bcerion      UInt    i;
7650e971c6a8b613ab2ea92a34f802a0e39c01e84b19sewardj      UInt clearszB;
7651e971c6a8b613ab2ea92a34f802a0e39c01e84b19sewardj      if (is_dcbzl) {
7652e971c6a8b613ab2ea92a34f802a0e39c01e84b19sewardj          clearszB = guest_archinfo->ppc_dcbzl_szB;
7653e971c6a8b613ab2ea92a34f802a0e39c01e84b19sewardj          DIP("dcbzl r%u,r%u\n", rA_addr, rB_addr);
7654e971c6a8b613ab2ea92a34f802a0e39c01e84b19sewardj      }
7655e971c6a8b613ab2ea92a34f802a0e39c01e84b19sewardj      else {
7656e971c6a8b613ab2ea92a34f802a0e39c01e84b19sewardj          clearszB = guest_archinfo->ppc_dcbz_szB;
7657e971c6a8b613ab2ea92a34f802a0e39c01e84b19sewardj          DIP("dcbz r%u,r%u\n", rA_addr, rB_addr);
7658e971c6a8b613ab2ea92a34f802a0e39c01e84b19sewardj      }
7659cb1f68e013416507adf513072d602f747773e3d7sewardj
7660d953ebb9b04cbad6891676df597bf0c542b1ec89cerion      assign( EA, ea_rAor0_idxd(rA_addr, rB_addr) );
7661094d1397b3f69b1a538e80ab509ea8cd75f4be3bcerion
76622831b00c4950d6c2b061def05fd67528fe132ececerion      if (mode64) {
76632831b00c4950d6c2b061def05fd67528fe132ececerion         /* Round EA down to the start of the containing block. */
76642831b00c4950d6c2b061def05fd67528fe132ececerion         assign( addr, binop( Iop_And64,
76652831b00c4950d6c2b061def05fd67528fe132ececerion                              mkexpr(EA),
7666e971c6a8b613ab2ea92a34f802a0e39c01e84b19sewardj                              mkU64( ~((ULong)clearszB-1) )) );
76672831b00c4950d6c2b061def05fd67528fe132ececerion
7668e971c6a8b613ab2ea92a34f802a0e39c01e84b19sewardj         for (i = 0; i < clearszB / 8; i++) {
76692831b00c4950d6c2b061def05fd67528fe132ececerion            irx_addr = binop( Iop_Add64, mkexpr(addr), mkU64(i*8) );
76701f5fe1fc3a37ca729925e8eec25aa1025b4a6cdbcarll            store( irx_addr, mkU64(0) );
76712831b00c4950d6c2b061def05fd67528fe132ececerion         }
76722831b00c4950d6c2b061def05fd67528fe132ececerion      } else {
76732831b00c4950d6c2b061def05fd67528fe132ececerion         /* Round EA down to the start of the containing block. */
76742831b00c4950d6c2b061def05fd67528fe132ececerion         assign( addr, binop( Iop_And32,
76752831b00c4950d6c2b061def05fd67528fe132ececerion                              mkexpr(EA),
7676e971c6a8b613ab2ea92a34f802a0e39c01e84b19sewardj                              mkU32( ~(clearszB-1) )) );
76772831b00c4950d6c2b061def05fd67528fe132ececerion
7678e971c6a8b613ab2ea92a34f802a0e39c01e84b19sewardj         for (i = 0; i < clearszB / 4; i++) {
76792831b00c4950d6c2b061def05fd67528fe132ececerion            irx_addr = binop( Iop_Add32, mkexpr(addr), mkU32(i*4) );
76801f5fe1fc3a37ca729925e8eec25aa1025b4a6cdbcarll            store( irx_addr, mkU32(0) );
76812831b00c4950d6c2b061def05fd67528fe132ececerion         }
7682094d1397b3f69b1a538e80ab509ea8cd75f4be3bcerion      }
7683b85e8bba97fdae7d892f7bfd12e4601307e4721dcerion      break;
7684094d1397b3f69b1a538e80ab509ea8cd75f4be3bcerion   }
7685b85e8bba97fdae7d892f7bfd12e4601307e4721dcerion
76867ce9d15f4208aa08dfb1e605b3cad53ff03a84e4sewardj   case 0x3D6: {
76877ce9d15f4208aa08dfb1e605b3cad53ff03a84e4sewardj      // icbi (Instruction Cache Block Invalidate, PPC32 p431)
76887ce9d15f4208aa08dfb1e605b3cad53ff03a84e4sewardj      /* Invalidate all translations containing code from the cache
7689d94b73a4ece194130f7a59cca9262d44cf9dbb91sewardj         block at (rA|0) + rB. */
7690d953ebb9b04cbad6891676df597bf0c542b1ec89cerion      IRTemp EA   = newTemp(ty);
7691d953ebb9b04cbad6891676df597bf0c542b1ec89cerion      IRTemp addr = newTemp(ty);
7692d953ebb9b04cbad6891676df597bf0c542b1ec89cerion      DIP("icbi r%u,r%u\n", rA_addr, rB_addr);
7693d953ebb9b04cbad6891676df597bf0c542b1ec89cerion      assign( EA, ea_rAor0_idxd(rA_addr, rB_addr) );
76947ce9d15f4208aa08dfb1e605b3cad53ff03a84e4sewardj
76952831b00c4950d6c2b061def05fd67528fe132ececerion      /* Round EA down to the start of the containing block. */
76962831b00c4950d6c2b061def05fd67528fe132ececerion      assign( addr, binop( mkSzOp(ty, Iop_And8),
7697d953ebb9b04cbad6891676df597bf0c542b1ec89cerion                           mkexpr(EA),
76982831b00c4950d6c2b061def05fd67528fe132ececerion                           mkSzImm(ty, ~(((ULong)lineszB)-1) )) );
769905f5e0172384dd2983fb16fbb7deebd74d71cd35sewardj      putGST( PPC_GST_CMSTART, mkexpr(addr) );
770005f5e0172384dd2983fb16fbb7deebd74d71cd35sewardj      putGST( PPC_GST_CMLEN, mkSzImm(ty, lineszB) );
77017ce9d15f4208aa08dfb1e605b3cad53ff03a84e4sewardj
7702a8078f66b2c4043e5f099cfeb3ebf01e4cc21953sewardj      /* be paranoid ... */
7703c4356f0d3c74fc2622dbeed79c6c1045fc519f72sewardj      stmt( IRStmt_MBE(Imbe_Fence) );
7704a8078f66b2c4043e5f099cfeb3ebf01e4cc21953sewardj
77053dee849ec7c38746749065e67dc53b75daa7617dsewardj      putGST( PPC_GST_CIA, mkSzImm(ty, nextInsnAddr()));
770605f5e0172384dd2983fb16fbb7deebd74d71cd35sewardj      dres->jk_StopHere = Ijk_InvalICache;
77073dee849ec7c38746749065e67dc53b75daa7617dsewardj      dres->whatNext    = Dis_StopHere;
7708b85e8bba97fdae7d892f7bfd12e4601307e4721dcerion      break;
77097ce9d15f4208aa08dfb1e605b3cad53ff03a84e4sewardj   }
77108c3addacc8343f5d1504379e303934f8ed88903ecerion
7711b85e8bba97fdae7d892f7bfd12e4601307e4721dcerion   default:
77125b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion      vex_printf("dis_cache_manage(ppc)(opc2)\n");
7713b85e8bba97fdae7d892f7bfd12e4601307e4721dcerion      return False;
7714b85e8bba97fdae7d892f7bfd12e4601307e4721dcerion   }
7715b85e8bba97fdae7d892f7bfd12e4601307e4721dcerion   return True;
77168c3addacc8343f5d1504379e303934f8ed88903ecerion}
77178c3addacc8343f5d1504379e303934f8ed88903ecerion
77188c3addacc8343f5d1504379e303934f8ed88903ecerion
7719e14bb9f862843c6b804097c124961b5567ded4f1sewardj/*------------------------------------------------------------*/
7720e14bb9f862843c6b804097c124961b5567ded4f1sewardj/*--- Floating Point Helpers                               ---*/
7721e14bb9f862843c6b804097c124961b5567ded4f1sewardj/*------------------------------------------------------------*/
7722e14bb9f862843c6b804097c124961b5567ded4f1sewardj
7723e14bb9f862843c6b804097c124961b5567ded4f1sewardj/* --------- Synthesise a 2-bit FPU rounding mode. --------- */
7724e14bb9f862843c6b804097c124961b5567ded4f1sewardj/* Produces a value in 0 .. 3, which is encoded as per the type
77255b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion   IRRoundingMode.  PPCRoundingMode encoding is different to
7726e14bb9f862843c6b804097c124961b5567ded4f1sewardj   IRRoundingMode, so need to map it.
7727e14bb9f862843c6b804097c124961b5567ded4f1sewardj*/
7728b183b8571b4ec98866ce2b3653a9d066cf5f16f4sewardjstatic IRExpr* /* :: Ity_I32 */ get_IR_roundingmode ( void )
7729e14bb9f862843c6b804097c124961b5567ded4f1sewardj{
7730e14bb9f862843c6b804097c124961b5567ded4f1sewardj/*
7731e14bb9f862843c6b804097c124961b5567ded4f1sewardj   rounding mode | PPC | IR
7732e14bb9f862843c6b804097c124961b5567ded4f1sewardj   ------------------------
7733e14bb9f862843c6b804097c124961b5567ded4f1sewardj   to nearest    | 00  | 00
7734e14bb9f862843c6b804097c124961b5567ded4f1sewardj   to zero       | 01  | 11
7735e14bb9f862843c6b804097c124961b5567ded4f1sewardj   to +infinity  | 10  | 10
7736e14bb9f862843c6b804097c124961b5567ded4f1sewardj   to -infinity  | 11  | 01
7737e14bb9f862843c6b804097c124961b5567ded4f1sewardj*/
7738e14bb9f862843c6b804097c124961b5567ded4f1sewardj   IRTemp rm_PPC32 = newTemp(Ity_I32);
7739d953ebb9b04cbad6891676df597bf0c542b1ec89cerion   assign( rm_PPC32, getGST_masked( PPC_GST_FPSCR, MASK_FPSCR_RN ) );
7740e14bb9f862843c6b804097c124961b5567ded4f1sewardj
7741e14bb9f862843c6b804097c124961b5567ded4f1sewardj   // rm_IR = XOR( rm_PPC32, (rm_PPC32 << 1) & 2)
7742b183b8571b4ec98866ce2b3653a9d066cf5f16f4sewardj   return binop( Iop_Xor32,
7743b183b8571b4ec98866ce2b3653a9d066cf5f16f4sewardj                 mkexpr(rm_PPC32),
7744b183b8571b4ec98866ce2b3653a9d066cf5f16f4sewardj                 binop( Iop_And32,
7745b183b8571b4ec98866ce2b3653a9d066cf5f16f4sewardj                        binop(Iop_Shl32, mkexpr(rm_PPC32), mkU8(1)),
7746b183b8571b4ec98866ce2b3653a9d066cf5f16f4sewardj                        mkU32(2) ));
7747e14bb9f862843c6b804097c124961b5567ded4f1sewardj}
7748094d1397b3f69b1a538e80ab509ea8cd75f4be3bcerion
7749c6bbd470e9bd9898b84959227a406d3972d95f3bsewardj/* The DFP IR rounding modes were chosen such that the existing PPC to IR
7750c6bbd470e9bd9898b84959227a406d3972d95f3bsewardj * mapping would still work with the extended three bit DFP rounding
7751c6bbd470e9bd9898b84959227a406d3972d95f3bsewardj * mode designator.
7752c6bbd470e9bd9898b84959227a406d3972d95f3bsewardj
7753c6bbd470e9bd9898b84959227a406d3972d95f3bsewardj *  rounding mode                     | PPC  |  IR
7754c6bbd470e9bd9898b84959227a406d3972d95f3bsewardj *  -----------------------------------------------
7755c6bbd470e9bd9898b84959227a406d3972d95f3bsewardj *  to nearest, ties to even          | 000  | 000
7756c6bbd470e9bd9898b84959227a406d3972d95f3bsewardj *  to zero                           | 001  | 011
7757c6bbd470e9bd9898b84959227a406d3972d95f3bsewardj *  to +infinity                      | 010  | 010
7758c6bbd470e9bd9898b84959227a406d3972d95f3bsewardj *  to -infinity                      | 011  | 001
7759c6bbd470e9bd9898b84959227a406d3972d95f3bsewardj *  to nearest, ties away from 0      | 100  | 100
7760c6bbd470e9bd9898b84959227a406d3972d95f3bsewardj *  to nearest, ties toward 0         | 101  | 111
7761c6bbd470e9bd9898b84959227a406d3972d95f3bsewardj *  to away from 0                    | 110  | 110
7762c6bbd470e9bd9898b84959227a406d3972d95f3bsewardj *  to prepare for shorter precision  | 111  | 101
7763c6bbd470e9bd9898b84959227a406d3972d95f3bsewardj */
7764c6bbd470e9bd9898b84959227a406d3972d95f3bsewardjstatic IRExpr* /* :: Ity_I32 */ get_IR_roundingmode_DFP( void )
7765c6bbd470e9bd9898b84959227a406d3972d95f3bsewardj{
7766c6bbd470e9bd9898b84959227a406d3972d95f3bsewardj   IRTemp rm_PPC32 = newTemp( Ity_I32 );
7767c6bbd470e9bd9898b84959227a406d3972d95f3bsewardj   assign( rm_PPC32, getGST_masked_upper( PPC_GST_FPSCR, MASK_FPSCR_DRN ) );
7768c6bbd470e9bd9898b84959227a406d3972d95f3bsewardj
7769c6bbd470e9bd9898b84959227a406d3972d95f3bsewardj   // rm_IR = XOR( rm_PPC32, (rm_PPC32 << 1) & 2)
7770c6bbd470e9bd9898b84959227a406d3972d95f3bsewardj   return binop( Iop_Xor32,
7771c6bbd470e9bd9898b84959227a406d3972d95f3bsewardj                 mkexpr( rm_PPC32 ),
7772c6bbd470e9bd9898b84959227a406d3972d95f3bsewardj                 binop( Iop_And32,
7773c6bbd470e9bd9898b84959227a406d3972d95f3bsewardj                        binop( Iop_Shl32, mkexpr( rm_PPC32 ), mkU8( 1 ) ),
7774c6bbd470e9bd9898b84959227a406d3972d95f3bsewardj                        mkU32( 2 ) ) );
7775c6bbd470e9bd9898b84959227a406d3972d95f3bsewardj}
7776094d1397b3f69b1a538e80ab509ea8cd75f4be3bcerion
77772bcdd653612c726da0b7203b579b8f6114703be4sewardj#define NANmaskSingle   0x7F800000
77782bcdd653612c726da0b7203b579b8f6114703be4sewardj#define NANmaskDouble   0x7FF00000
77792bcdd653612c726da0b7203b579b8f6114703be4sewardj
77802bcdd653612c726da0b7203b579b8f6114703be4sewardjstatic IRExpr * Check_NaN( IRExpr * value, IRExpr * Hi32Mask )
77812bcdd653612c726da0b7203b579b8f6114703be4sewardj{
77822bcdd653612c726da0b7203b579b8f6114703be4sewardj   IRTemp exp_zero  = newTemp(Ity_I8);
77832bcdd653612c726da0b7203b579b8f6114703be4sewardj   IRTemp frac_mask = newTemp(Ity_I32);
77842bcdd653612c726da0b7203b579b8f6114703be4sewardj   IRTemp frac_not_zero = newTemp(Ity_I8);
77852bcdd653612c726da0b7203b579b8f6114703be4sewardj
77862bcdd653612c726da0b7203b579b8f6114703be4sewardj   /* Check if the result is QNAN or SNAN and not +infinity or -infinity.
77872bcdd653612c726da0b7203b579b8f6114703be4sewardj    * The input value is always 64-bits, for single precision values, the
77882bcdd653612c726da0b7203b579b8f6114703be4sewardj    * lower 32 bits must be zero.
77892bcdd653612c726da0b7203b579b8f6114703be4sewardj    *
77902bcdd653612c726da0b7203b579b8f6114703be4sewardj    * Single Pricision
77912bcdd653612c726da0b7203b579b8f6114703be4sewardj    *  [62:54] exponent field is equal to 0xFF for NAN and Infinity.
77922bcdd653612c726da0b7203b579b8f6114703be4sewardj    *  [53:32] fraction field is zero for Infinity and non-zero for NAN
77932bcdd653612c726da0b7203b579b8f6114703be4sewardj    *  [31:0]  unused for single precision representation
77942bcdd653612c726da0b7203b579b8f6114703be4sewardj    *
77952bcdd653612c726da0b7203b579b8f6114703be4sewardj    * Double Pricision
77962bcdd653612c726da0b7203b579b8f6114703be4sewardj    *  [62:51] exponent field is equal to 0xFF for NAN and Infinity.
77972bcdd653612c726da0b7203b579b8f6114703be4sewardj    *  [50:0]  fraction field is zero for Infinity and non-zero for NAN
77982bcdd653612c726da0b7203b579b8f6114703be4sewardj    *
77992bcdd653612c726da0b7203b579b8f6114703be4sewardj    * Returned result is a U32 value of 0xFFFFFFFF for NaN and 0 otherwise.
78002bcdd653612c726da0b7203b579b8f6114703be4sewardj    */
78012bcdd653612c726da0b7203b579b8f6114703be4sewardj   assign( frac_mask, unop( Iop_Not32,
78022bcdd653612c726da0b7203b579b8f6114703be4sewardj                            binop( Iop_Or32,
78032bcdd653612c726da0b7203b579b8f6114703be4sewardj                                   mkU32( 0x80000000ULL ), Hi32Mask) ) );
78042bcdd653612c726da0b7203b579b8f6114703be4sewardj
78052bcdd653612c726da0b7203b579b8f6114703be4sewardj   assign( exp_zero,
78062bcdd653612c726da0b7203b579b8f6114703be4sewardj           unop( Iop_1Sto8,
78072bcdd653612c726da0b7203b579b8f6114703be4sewardj                 binop( Iop_CmpEQ32,
78082bcdd653612c726da0b7203b579b8f6114703be4sewardj                        binop( Iop_And32,
78092bcdd653612c726da0b7203b579b8f6114703be4sewardj                               unop( Iop_64HIto32,
78102bcdd653612c726da0b7203b579b8f6114703be4sewardj                                     unop( Iop_ReinterpF64asI64,
78112bcdd653612c726da0b7203b579b8f6114703be4sewardj                                           value ) ),
78122bcdd653612c726da0b7203b579b8f6114703be4sewardj                               Hi32Mask ),
78132bcdd653612c726da0b7203b579b8f6114703be4sewardj                        Hi32Mask ) ) );
78142bcdd653612c726da0b7203b579b8f6114703be4sewardj   assign( frac_not_zero,
78152bcdd653612c726da0b7203b579b8f6114703be4sewardj           binop( Iop_Or8,
78162bcdd653612c726da0b7203b579b8f6114703be4sewardj                  unop( Iop_1Sto8,
78172bcdd653612c726da0b7203b579b8f6114703be4sewardj                        binop( Iop_CmpNE32,
78182bcdd653612c726da0b7203b579b8f6114703be4sewardj                               binop( Iop_And32,
78192bcdd653612c726da0b7203b579b8f6114703be4sewardj                                      unop( Iop_64HIto32,
78202bcdd653612c726da0b7203b579b8f6114703be4sewardj                                            unop( Iop_ReinterpF64asI64,
78212bcdd653612c726da0b7203b579b8f6114703be4sewardj                                                  value ) ),
78222bcdd653612c726da0b7203b579b8f6114703be4sewardj                                      mkexpr( frac_mask ) ),
78232bcdd653612c726da0b7203b579b8f6114703be4sewardj                               mkU32( 0x0 ) ) ),
78242bcdd653612c726da0b7203b579b8f6114703be4sewardj                  unop( Iop_1Sto8,
78252bcdd653612c726da0b7203b579b8f6114703be4sewardj                        binop( Iop_CmpNE32,
78262bcdd653612c726da0b7203b579b8f6114703be4sewardj                               binop( Iop_And32,
78272bcdd653612c726da0b7203b579b8f6114703be4sewardj                                      unop( Iop_64to32,
78282bcdd653612c726da0b7203b579b8f6114703be4sewardj                                            unop( Iop_ReinterpF64asI64,
78292bcdd653612c726da0b7203b579b8f6114703be4sewardj                                                  value ) ),
78302bcdd653612c726da0b7203b579b8f6114703be4sewardj                                      mkU32( 0xFFFFFFFF ) ),
78312bcdd653612c726da0b7203b579b8f6114703be4sewardj                               mkU32( 0x0 ) ) ) ) );
78322bcdd653612c726da0b7203b579b8f6114703be4sewardj   return unop( Iop_8Sto32,
78332bcdd653612c726da0b7203b579b8f6114703be4sewardj                binop( Iop_And8,
78342bcdd653612c726da0b7203b579b8f6114703be4sewardj                       mkexpr( exp_zero ),
78352bcdd653612c726da0b7203b579b8f6114703be4sewardj                       mkexpr( frac_not_zero ) ) );
78362bcdd653612c726da0b7203b579b8f6114703be4sewardj}
78372bcdd653612c726da0b7203b579b8f6114703be4sewardj
78382bcdd653612c726da0b7203b579b8f6114703be4sewardjstatic IRExpr * Complement_non_NaN( IRExpr * value, IRExpr * nan_mask )
78392bcdd653612c726da0b7203b579b8f6114703be4sewardj{
78402bcdd653612c726da0b7203b579b8f6114703be4sewardj   /* This function will only complement the 64-bit floating point value if it
78412bcdd653612c726da0b7203b579b8f6114703be4sewardj    * is not Nan.  NaN is not a signed value.  Need to do computations using
78422bcdd653612c726da0b7203b579b8f6114703be4sewardj    * 32-bit operands to ensure it will run in 32-bit mode.
78432bcdd653612c726da0b7203b579b8f6114703be4sewardj    */
78442bcdd653612c726da0b7203b579b8f6114703be4sewardj   return  binop( Iop_32HLto64,
78452bcdd653612c726da0b7203b579b8f6114703be4sewardj                  binop( Iop_Or32,
78462bcdd653612c726da0b7203b579b8f6114703be4sewardj                         binop( Iop_And32,
78472bcdd653612c726da0b7203b579b8f6114703be4sewardj                                nan_mask,
78482bcdd653612c726da0b7203b579b8f6114703be4sewardj                                unop( Iop_64HIto32,
78492bcdd653612c726da0b7203b579b8f6114703be4sewardj                                      unop( Iop_ReinterpF64asI64,
78502bcdd653612c726da0b7203b579b8f6114703be4sewardj                                            value ) ) ),
78512bcdd653612c726da0b7203b579b8f6114703be4sewardj                         binop( Iop_And32,
78522bcdd653612c726da0b7203b579b8f6114703be4sewardj                                unop( Iop_Not32,
78532bcdd653612c726da0b7203b579b8f6114703be4sewardj                                      nan_mask ),
78542bcdd653612c726da0b7203b579b8f6114703be4sewardj                                unop( Iop_64HIto32,
78552bcdd653612c726da0b7203b579b8f6114703be4sewardj                                      unop( Iop_ReinterpF64asI64,
78562bcdd653612c726da0b7203b579b8f6114703be4sewardj                                            unop( Iop_NegF64,
78572bcdd653612c726da0b7203b579b8f6114703be4sewardj                                                  value ) ) ) ) ),
78582bcdd653612c726da0b7203b579b8f6114703be4sewardj                  unop( Iop_64to32,
78592bcdd653612c726da0b7203b579b8f6114703be4sewardj                        unop( Iop_ReinterpF64asI64, value ) ) );
78602bcdd653612c726da0b7203b579b8f6114703be4sewardj}
78612bcdd653612c726da0b7203b579b8f6114703be4sewardj
78623d870a39e4d145e2f3d9f9a0eeed3475ec934ac1cerion/*------------------------------------------------------------*/
78633d870a39e4d145e2f3d9f9a0eeed3475ec934ac1cerion/*--- Floating Point Instruction Translation               ---*/
78643d870a39e4d145e2f3d9f9a0eeed3475ec934ac1cerion/*------------------------------------------------------------*/
78653d870a39e4d145e2f3d9f9a0eeed3475ec934ac1cerion
78663d870a39e4d145e2f3d9f9a0eeed3475ec934ac1cerion/*
78673d870a39e4d145e2f3d9f9a0eeed3475ec934ac1cerion  Floating Point Load Instructions
78683d870a39e4d145e2f3d9f9a0eeed3475ec934ac1cerion*/
78693d870a39e4d145e2f3d9f9a0eeed3475ec934ac1cerionstatic Bool dis_fp_load ( UInt theInstr )
78703d870a39e4d145e2f3d9f9a0eeed3475ec934ac1cerion{
787176de5cf615380b23b4b5bcced6541233cd4a93a0cerion   /* X-Form, D-Form */
787276de5cf615380b23b4b5bcced6541233cd4a93a0cerion   UChar opc1      = ifieldOPC(theInstr);
787376de5cf615380b23b4b5bcced6541233cd4a93a0cerion   UChar frD_addr  = ifieldRegDS(theInstr);
787476de5cf615380b23b4b5bcced6541233cd4a93a0cerion   UChar rA_addr   = ifieldRegA(theInstr);
787576de5cf615380b23b4b5bcced6541233cd4a93a0cerion   UChar rB_addr   = ifieldRegB(theInstr);
787676de5cf615380b23b4b5bcced6541233cd4a93a0cerion   UInt  opc2      = ifieldOPClo10(theInstr);
787776de5cf615380b23b4b5bcced6541233cd4a93a0cerion   UChar b0        = ifieldBIT0(theInstr);
78782831b00c4950d6c2b061def05fd67528fe132ececerion   UInt  uimm16    = ifieldUIMM16(theInstr);
7879d953ebb9b04cbad6891676df597bf0c542b1ec89cerion
78802831b00c4950d6c2b061def05fd67528fe132ececerion   Int    simm16 = extend_s_16to32(uimm16);
78812831b00c4950d6c2b061def05fd67528fe132ececerion   IRType ty     = mode64 ? Ity_I64 : Ity_I32;
78822831b00c4950d6c2b061def05fd67528fe132ececerion   IRTemp EA     = newTemp(ty);
78832831b00c4950d6c2b061def05fd67528fe132ececerion   IRTemp rA     = newTemp(ty);
78842831b00c4950d6c2b061def05fd67528fe132ececerion   IRTemp rB     = newTemp(ty);
78857e84630580f89c1022dde97007bffbf6aef81814sewardj   IRTemp iHi    = newTemp(Ity_I32);
78867e84630580f89c1022dde97007bffbf6aef81814sewardj   IRTemp iLo    = newTemp(Ity_I32);
7887094d1397b3f69b1a538e80ab509ea8cd75f4be3bcerion
7888094d1397b3f69b1a538e80ab509ea8cd75f4be3bcerion   assign( rA, getIReg(rA_addr) );
7889094d1397b3f69b1a538e80ab509ea8cd75f4be3bcerion   assign( rB, getIReg(rB_addr) );
7890d953ebb9b04cbad6891676df597bf0c542b1ec89cerion
7891b183b8571b4ec98866ce2b3653a9d066cf5f16f4sewardj   /* These are completely straightforward from a rounding and status
7892b183b8571b4ec98866ce2b3653a9d066cf5f16f4sewardj      bits perspective: no rounding involved and no funny status or CR
7893b183b8571b4ec98866ce2b3653a9d066cf5f16f4sewardj      bits affected. */
78943d870a39e4d145e2f3d9f9a0eeed3475ec934ac1cerion
7895b183b8571b4ec98866ce2b3653a9d066cf5f16f4sewardj   switch (opc1) {
7896e14bb9f862843c6b804097c124961b5567ded4f1sewardj   case 0x30: // lfs (Load Float Single, PPC32 p441)
7897d953ebb9b04cbad6891676df597bf0c542b1ec89cerion      DIP("lfs fr%u,%d(r%u)\n", frD_addr, simm16, rA_addr);
7898d953ebb9b04cbad6891676df597bf0c542b1ec89cerion      assign( EA, ea_rAor0_simm(rA_addr, simm16) );
78995b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion      putFReg( frD_addr,
79001f5fe1fc3a37ca729925e8eec25aa1025b4a6cdbcarll               unop(Iop_F32toF64, load(Ity_F32, mkexpr(EA))) );
7901e14bb9f862843c6b804097c124961b5567ded4f1sewardj      break;
7902e14bb9f862843c6b804097c124961b5567ded4f1sewardj
79035b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion   case 0x31: // lfsu (Load Float Single, Update, PPC32 p442)
7904b183b8571b4ec98866ce2b3653a9d066cf5f16f4sewardj      if (rA_addr == 0)
7905729edb7804bac750fe5fb0ce079e8fb965653e67cerion         return False;
7906729edb7804bac750fe5fb0ce079e8fb965653e67cerion      DIP("lfsu fr%u,%d(r%u)\n", frD_addr, simm16, rA_addr);
7907729edb7804bac750fe5fb0ce079e8fb965653e67cerion      assign( EA, ea_rA_simm(rA_addr, simm16) );
79085b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion      putFReg( frD_addr,
79091f5fe1fc3a37ca729925e8eec25aa1025b4a6cdbcarll               unop(Iop_F32toF64, load(Ity_F32, mkexpr(EA))) );
7910729edb7804bac750fe5fb0ce079e8fb965653e67cerion      putIReg( rA_addr, mkexpr(EA) );
7911729edb7804bac750fe5fb0ce079e8fb965653e67cerion      break;
7912094d1397b3f69b1a538e80ab509ea8cd75f4be3bcerion
7913094d1397b3f69b1a538e80ab509ea8cd75f4be3bcerion   case 0x32: // lfd (Load Float Double, PPC32 p437)
7914d953ebb9b04cbad6891676df597bf0c542b1ec89cerion      DIP("lfd fr%u,%d(r%u)\n", frD_addr, simm16, rA_addr);
7915d953ebb9b04cbad6891676df597bf0c542b1ec89cerion      assign( EA, ea_rAor0_simm(rA_addr, simm16) );
79161f5fe1fc3a37ca729925e8eec25aa1025b4a6cdbcarll      putFReg( frD_addr, load(Ity_F64, mkexpr(EA)) );
7917094d1397b3f69b1a538e80ab509ea8cd75f4be3bcerion      break;
79183d870a39e4d145e2f3d9f9a0eeed3475ec934ac1cerion
79195b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion   case 0x33: // lfdu (Load Float Double, Update, PPC32 p438)
7920b183b8571b4ec98866ce2b3653a9d066cf5f16f4sewardj      if (rA_addr == 0)
79210e2cc67b30d1bb4d0515a1e09d944143becb3881sewardj         return False;
7922d953ebb9b04cbad6891676df597bf0c542b1ec89cerion      DIP("lfdu fr%u,%d(r%u)\n", frD_addr, simm16, rA_addr);
7923d953ebb9b04cbad6891676df597bf0c542b1ec89cerion      assign( EA, ea_rA_simm(rA_addr, simm16) );
79241f5fe1fc3a37ca729925e8eec25aa1025b4a6cdbcarll      putFReg( frD_addr, load(Ity_F64, mkexpr(EA)) );
79250e2cc67b30d1bb4d0515a1e09d944143becb3881sewardj      putIReg( rA_addr, mkexpr(EA) );
79260e2cc67b30d1bb4d0515a1e09d944143becb3881sewardj      break;
7927e14bb9f862843c6b804097c124961b5567ded4f1sewardj
7928e14bb9f862843c6b804097c124961b5567ded4f1sewardj   case 0x1F:
7929e14bb9f862843c6b804097c124961b5567ded4f1sewardj      if (b0 != 0) {
79305b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion         vex_printf("dis_fp_load(ppc)(instr,b0)\n");
7931e14bb9f862843c6b804097c124961b5567ded4f1sewardj         return False;
7932e14bb9f862843c6b804097c124961b5567ded4f1sewardj      }
7933e14bb9f862843c6b804097c124961b5567ded4f1sewardj
7934e14bb9f862843c6b804097c124961b5567ded4f1sewardj      switch(opc2) {
7935d953ebb9b04cbad6891676df597bf0c542b1ec89cerion      case 0x217: // lfsx (Load Float Single Indexed, PPC32 p444)
7936d953ebb9b04cbad6891676df597bf0c542b1ec89cerion         DIP("lfsx fr%u,r%u,r%u\n", frD_addr, rA_addr, rB_addr);
7937d953ebb9b04cbad6891676df597bf0c542b1ec89cerion         assign( EA, ea_rAor0_idxd(rA_addr, rB_addr) );
7938d953ebb9b04cbad6891676df597bf0c542b1ec89cerion         putFReg( frD_addr, unop( Iop_F32toF64,
79391f5fe1fc3a37ca729925e8eec25aa1025b4a6cdbcarll                                  load(Ity_F32, mkexpr(EA))) );
7940d953ebb9b04cbad6891676df597bf0c542b1ec89cerion         break;
7941d953ebb9b04cbad6891676df597bf0c542b1ec89cerion
79425b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion      case 0x237: // lfsux (Load Float Single, Update Indxd, PPC32 p443)
7943b183b8571b4ec98866ce2b3653a9d066cf5f16f4sewardj         if (rA_addr == 0)
7944d953ebb9b04cbad6891676df597bf0c542b1ec89cerion            return False;
7945d953ebb9b04cbad6891676df597bf0c542b1ec89cerion         DIP("lfsux fr%u,r%u,r%u\n", frD_addr, rA_addr, rB_addr);
7946d953ebb9b04cbad6891676df597bf0c542b1ec89cerion         assign( EA, ea_rA_idxd(rA_addr, rB_addr) );
79475b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion         putFReg( frD_addr,
79481f5fe1fc3a37ca729925e8eec25aa1025b4a6cdbcarll                  unop(Iop_F32toF64, load(Ity_F32, mkexpr(EA))) );
7949d953ebb9b04cbad6891676df597bf0c542b1ec89cerion         putIReg( rA_addr, mkexpr(EA) );
7950d953ebb9b04cbad6891676df597bf0c542b1ec89cerion         break;
7951d953ebb9b04cbad6891676df597bf0c542b1ec89cerion
7952d953ebb9b04cbad6891676df597bf0c542b1ec89cerion      case 0x257: // lfdx (Load Float Double Indexed, PPC32 p440)
7953d953ebb9b04cbad6891676df597bf0c542b1ec89cerion         DIP("lfdx fr%u,r%u,r%u\n", frD_addr, rA_addr, rB_addr);
7954d953ebb9b04cbad6891676df597bf0c542b1ec89cerion         assign( EA, ea_rAor0_idxd(rA_addr, rB_addr) );
79551f5fe1fc3a37ca729925e8eec25aa1025b4a6cdbcarll         putFReg( frD_addr, load(Ity_F64, mkexpr(EA)) );
7956d953ebb9b04cbad6891676df597bf0c542b1ec89cerion         break;
7957d953ebb9b04cbad6891676df597bf0c542b1ec89cerion
79585b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion      case 0x277: // lfdux (Load Float Double, Update Indxd, PPC32 p439)
7959b183b8571b4ec98866ce2b3653a9d066cf5f16f4sewardj         if (rA_addr == 0)
7960e14bb9f862843c6b804097c124961b5567ded4f1sewardj            return False;
7961d953ebb9b04cbad6891676df597bf0c542b1ec89cerion         DIP("lfdux fr%u,r%u,r%u\n", frD_addr, rA_addr, rB_addr);
7962d953ebb9b04cbad6891676df597bf0c542b1ec89cerion         assign( EA, ea_rA_idxd(rA_addr, rB_addr) );
79631f5fe1fc3a37ca729925e8eec25aa1025b4a6cdbcarll         putFReg( frD_addr, load(Ity_F64, mkexpr(EA)) );
7964d953ebb9b04cbad6891676df597bf0c542b1ec89cerion         putIReg( rA_addr, mkexpr(EA) );
7965d953ebb9b04cbad6891676df597bf0c542b1ec89cerion         break;
7966d953ebb9b04cbad6891676df597bf0c542b1ec89cerion
79677e84630580f89c1022dde97007bffbf6aef81814sewardj      case 0x357: // lfiwax (Load Float As Integer, Indxd, ISA 2.05 p120)
79687e84630580f89c1022dde97007bffbf6aef81814sewardj         DIP("lfiwax fr%u,r%u,r%u\n", frD_addr, rA_addr, rB_addr);
79697e84630580f89c1022dde97007bffbf6aef81814sewardj         assign( EA, ea_rAor0_idxd( rA_addr, rB_addr ) );
79701f5fe1fc3a37ca729925e8eec25aa1025b4a6cdbcarll         assign( iLo, load(Ity_I32, mkexpr(EA)) );
79717e84630580f89c1022dde97007bffbf6aef81814sewardj         assign( iHi, binop(Iop_Sub32,
79727e84630580f89c1022dde97007bffbf6aef81814sewardj                            mkU32(0),
79737e84630580f89c1022dde97007bffbf6aef81814sewardj                            binop(Iop_Shr32, mkexpr(iLo), mkU8(31)))  );
79747e84630580f89c1022dde97007bffbf6aef81814sewardj         putFReg( frD_addr, unop(Iop_ReinterpI64asF64,
79757e84630580f89c1022dde97007bffbf6aef81814sewardj                                 binop(Iop_32HLto64, mkexpr(iHi), mkexpr(iLo))) );
79767e84630580f89c1022dde97007bffbf6aef81814sewardj         break;
79777e84630580f89c1022dde97007bffbf6aef81814sewardj
797866d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj      case 0x377: // lfiwzx (Load floating-point as integer word, zero indexed
797966d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj      {
798066d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj         IRTemp dw = newTemp( Ity_I64 );
798166d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj         DIP("lfiwzx fr%u,r%u,r%u\n", frD_addr, rA_addr, rB_addr);
798266d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj         assign( EA, ea_rAor0_idxd( rA_addr, rB_addr ) );
79831f5fe1fc3a37ca729925e8eec25aa1025b4a6cdbcarll         assign( iLo, load(Ity_I32, mkexpr(EA)) );
798466d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj         assign( dw, binop( Iop_32HLto64, mkU32( 0 ), mkexpr( iLo ) ) );
798566d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj         putFReg( frD_addr, unop( Iop_ReinterpI64asF64, mkexpr( dw ) ) );
798666d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj         break;
798766d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj      }
798866d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj
7989d953ebb9b04cbad6891676df597bf0c542b1ec89cerion      default:
79905b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion         vex_printf("dis_fp_load(ppc)(opc2)\n");
7991d953ebb9b04cbad6891676df597bf0c542b1ec89cerion         return False;
7992e14bb9f862843c6b804097c124961b5567ded4f1sewardj      }
7993e14bb9f862843c6b804097c124961b5567ded4f1sewardj      break;
79943d870a39e4d145e2f3d9f9a0eeed3475ec934ac1cerion
79953d870a39e4d145e2f3d9f9a0eeed3475ec934ac1cerion   default:
79965b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion      vex_printf("dis_fp_load(ppc)(opc1)\n");
79973d870a39e4d145e2f3d9f9a0eeed3475ec934ac1cerion      return False;
79983d870a39e4d145e2f3d9f9a0eeed3475ec934ac1cerion   }
79993d870a39e4d145e2f3d9f9a0eeed3475ec934ac1cerion   return True;
80003d870a39e4d145e2f3d9f9a0eeed3475ec934ac1cerion}
80013d870a39e4d145e2f3d9f9a0eeed3475ec934ac1cerion
80023d870a39e4d145e2f3d9f9a0eeed3475ec934ac1cerion
80033d870a39e4d145e2f3d9f9a0eeed3475ec934ac1cerion
80043d870a39e4d145e2f3d9f9a0eeed3475ec934ac1cerion/*
80053d870a39e4d145e2f3d9f9a0eeed3475ec934ac1cerion  Floating Point Store Instructions
80063d870a39e4d145e2f3d9f9a0eeed3475ec934ac1cerion*/
80073d870a39e4d145e2f3d9f9a0eeed3475ec934ac1cerionstatic Bool dis_fp_store ( UInt theInstr )
80083d870a39e4d145e2f3d9f9a0eeed3475ec934ac1cerion{
800976de5cf615380b23b4b5bcced6541233cd4a93a0cerion   /* X-Form, D-Form */
801076de5cf615380b23b4b5bcced6541233cd4a93a0cerion   UChar opc1      = ifieldOPC(theInstr);
801176de5cf615380b23b4b5bcced6541233cd4a93a0cerion   UChar frS_addr  = ifieldRegDS(theInstr);
801276de5cf615380b23b4b5bcced6541233cd4a93a0cerion   UChar rA_addr   = ifieldRegA(theInstr);
801376de5cf615380b23b4b5bcced6541233cd4a93a0cerion   UChar rB_addr   = ifieldRegB(theInstr);
801476de5cf615380b23b4b5bcced6541233cd4a93a0cerion   UInt  opc2      = ifieldOPClo10(theInstr);
801576de5cf615380b23b4b5bcced6541233cd4a93a0cerion   UChar b0        = ifieldBIT0(theInstr);
8016d953ebb9b04cbad6891676df597bf0c542b1ec89cerion   Int   uimm16    = ifieldUIMM16(theInstr);
8017094d1397b3f69b1a538e80ab509ea8cd75f4be3bcerion
80182831b00c4950d6c2b061def05fd67528fe132ececerion   Int    simm16 = extend_s_16to32(uimm16);
80192831b00c4950d6c2b061def05fd67528fe132ececerion   IRTemp frS    = newTemp(Ity_F64);
80202831b00c4950d6c2b061def05fd67528fe132ececerion   IRType ty     = mode64 ? Ity_I64 : Ity_I32;
80212831b00c4950d6c2b061def05fd67528fe132ececerion   IRTemp EA     = newTemp(ty);
80222831b00c4950d6c2b061def05fd67528fe132ececerion   IRTemp rA     = newTemp(ty);
80232831b00c4950d6c2b061def05fd67528fe132ececerion   IRTemp rB     = newTemp(ty);
8024a982c0503d8c0c6069ae453bfe70657bd2c134aecerion
8025b51f0f4f33256638ed953156a2635aa739b232f1sewardj   assign( frS, getFReg(frS_addr) );
8026edf7fc572e2decb93e9143961e8739c8fe18899dcerion   assign( rA,  getIReg(rA_addr) );
8027edf7fc572e2decb93e9143961e8739c8fe18899dcerion   assign( rB,  getIReg(rB_addr) );
8028a982c0503d8c0c6069ae453bfe70657bd2c134aecerion
8029b183b8571b4ec98866ce2b3653a9d066cf5f16f4sewardj   /* These are straightforward from a status bits perspective: no
8030b183b8571b4ec98866ce2b3653a9d066cf5f16f4sewardj      funny status or CR bits affected.  For single precision stores,
8031b183b8571b4ec98866ce2b3653a9d066cf5f16f4sewardj      the values are truncated and denormalised (not rounded) to turn
8032b183b8571b4ec98866ce2b3653a9d066cf5f16f4sewardj      them into single precision values. */
8033b183b8571b4ec98866ce2b3653a9d066cf5f16f4sewardj
8034b183b8571b4ec98866ce2b3653a9d066cf5f16f4sewardj   switch (opc1) {
8035e14bb9f862843c6b804097c124961b5567ded4f1sewardj
8036e14bb9f862843c6b804097c124961b5567ded4f1sewardj   case 0x34: // stfs (Store Float Single, PPC32 p518)
8037d953ebb9b04cbad6891676df597bf0c542b1ec89cerion      DIP("stfs fr%u,%d(r%u)\n", frS_addr, simm16, rA_addr);
8038d953ebb9b04cbad6891676df597bf0c542b1ec89cerion      assign( EA, ea_rAor0_simm(rA_addr, simm16) );
8039b183b8571b4ec98866ce2b3653a9d066cf5f16f4sewardj      /* Use Iop_TruncF64asF32 to truncate and possible denormalise
8040b183b8571b4ec98866ce2b3653a9d066cf5f16f4sewardj         the value to be stored in the correct way, without any
8041b183b8571b4ec98866ce2b3653a9d066cf5f16f4sewardj         rounding. */
80421f5fe1fc3a37ca729925e8eec25aa1025b4a6cdbcarll      store( mkexpr(EA), unop(Iop_TruncF64asF32, mkexpr(frS)) );
8043e14bb9f862843c6b804097c124961b5567ded4f1sewardj      break;
8044e14bb9f862843c6b804097c124961b5567ded4f1sewardj
80455b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion   case 0x35: // stfsu (Store Float Single, Update, PPC32 p519)
8046b183b8571b4ec98866ce2b3653a9d066cf5f16f4sewardj      if (rA_addr == 0)
8047729edb7804bac750fe5fb0ce079e8fb965653e67cerion         return False;
8048729edb7804bac750fe5fb0ce079e8fb965653e67cerion      DIP("stfsu fr%u,%d(r%u)\n", frS_addr, simm16, rA_addr);
8049729edb7804bac750fe5fb0ce079e8fb965653e67cerion      assign( EA, ea_rA_simm(rA_addr, simm16) );
8050b183b8571b4ec98866ce2b3653a9d066cf5f16f4sewardj      /* See comment for stfs */
80511f5fe1fc3a37ca729925e8eec25aa1025b4a6cdbcarll      store( mkexpr(EA), unop(Iop_TruncF64asF32, mkexpr(frS)) );
8052729edb7804bac750fe5fb0ce079e8fb965653e67cerion      putIReg( rA_addr, mkexpr(EA) );
8053729edb7804bac750fe5fb0ce079e8fb965653e67cerion      break;
8054a982c0503d8c0c6069ae453bfe70657bd2c134aecerion
8055b51f0f4f33256638ed953156a2635aa739b232f1sewardj   case 0x36: // stfd (Store Float Double, PPC32 p513)
8056d953ebb9b04cbad6891676df597bf0c542b1ec89cerion      DIP("stfd fr%u,%d(r%u)\n", frS_addr, simm16, rA_addr);
8057d953ebb9b04cbad6891676df597bf0c542b1ec89cerion      assign( EA, ea_rAor0_simm(rA_addr, simm16) );
80581f5fe1fc3a37ca729925e8eec25aa1025b4a6cdbcarll      store( mkexpr(EA), mkexpr(frS) );
8059b51f0f4f33256638ed953156a2635aa739b232f1sewardj      break;
8060a982c0503d8c0c6069ae453bfe70657bd2c134aecerion
80615b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion   case 0x37: // stfdu (Store Float Double, Update, PPC32 p514)
8062b183b8571b4ec98866ce2b3653a9d066cf5f16f4sewardj      if (rA_addr == 0)
8063e14bb9f862843c6b804097c124961b5567ded4f1sewardj         return False;
8064d953ebb9b04cbad6891676df597bf0c542b1ec89cerion      DIP("stfdu fr%u,%d(r%u)\n", frS_addr, simm16, rA_addr);
8065d953ebb9b04cbad6891676df597bf0c542b1ec89cerion      assign( EA, ea_rA_simm(rA_addr, simm16) );
80661f5fe1fc3a37ca729925e8eec25aa1025b4a6cdbcarll      store( mkexpr(EA), mkexpr(frS) );
8067e14bb9f862843c6b804097c124961b5567ded4f1sewardj      putIReg( rA_addr, mkexpr(EA) );
8068e14bb9f862843c6b804097c124961b5567ded4f1sewardj      break;
8069e14bb9f862843c6b804097c124961b5567ded4f1sewardj
8070e14bb9f862843c6b804097c124961b5567ded4f1sewardj   case 0x1F:
8071e14bb9f862843c6b804097c124961b5567ded4f1sewardj      if (b0 != 0) {
80725b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion         vex_printf("dis_fp_store(ppc)(instr,b0)\n");
8073e14bb9f862843c6b804097c124961b5567ded4f1sewardj         return False;
8074e14bb9f862843c6b804097c124961b5567ded4f1sewardj      }
8075e14bb9f862843c6b804097c124961b5567ded4f1sewardj      switch(opc2) {
8076d953ebb9b04cbad6891676df597bf0c542b1ec89cerion      case 0x297: // stfsx (Store Float Single Indexed, PPC32 p521)
8077d953ebb9b04cbad6891676df597bf0c542b1ec89cerion         DIP("stfsx fr%u,r%u,r%u\n", frS_addr, rA_addr, rB_addr);
8078d953ebb9b04cbad6891676df597bf0c542b1ec89cerion         assign( EA, ea_rAor0_idxd(rA_addr, rB_addr) );
8079b183b8571b4ec98866ce2b3653a9d066cf5f16f4sewardj         /* See note for stfs */
80801f5fe1fc3a37ca729925e8eec25aa1025b4a6cdbcarll         store( mkexpr(EA),
80811f5fe1fc3a37ca729925e8eec25aa1025b4a6cdbcarll                unop(Iop_TruncF64asF32, mkexpr(frS)) );
8082d953ebb9b04cbad6891676df597bf0c542b1ec89cerion         break;
8083d953ebb9b04cbad6891676df597bf0c542b1ec89cerion
80845b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion      case 0x2B7: // stfsux (Store Float Sgl, Update Indxd, PPC32 p520)
8085b183b8571b4ec98866ce2b3653a9d066cf5f16f4sewardj         if (rA_addr == 0)
8086729edb7804bac750fe5fb0ce079e8fb965653e67cerion            return False;
8087729edb7804bac750fe5fb0ce079e8fb965653e67cerion         DIP("stfsux fr%u,r%u,r%u\n", frS_addr, rA_addr, rB_addr);
8088729edb7804bac750fe5fb0ce079e8fb965653e67cerion         assign( EA, ea_rA_idxd(rA_addr, rB_addr) );
8089b183b8571b4ec98866ce2b3653a9d066cf5f16f4sewardj         /* See note for stfs */
80901f5fe1fc3a37ca729925e8eec25aa1025b4a6cdbcarll         store( mkexpr(EA), unop(Iop_TruncF64asF32, mkexpr(frS)) );
8091729edb7804bac750fe5fb0ce079e8fb965653e67cerion         putIReg( rA_addr, mkexpr(EA) );
8092729edb7804bac750fe5fb0ce079e8fb965653e67cerion         break;
8093e14bb9f862843c6b804097c124961b5567ded4f1sewardj
8094d953ebb9b04cbad6891676df597bf0c542b1ec89cerion      case 0x2D7: // stfdx (Store Float Double Indexed, PPC32 p516)
8095d953ebb9b04cbad6891676df597bf0c542b1ec89cerion         DIP("stfdx fr%u,r%u,r%u\n", frS_addr, rA_addr, rB_addr);
8096d953ebb9b04cbad6891676df597bf0c542b1ec89cerion         assign( EA, ea_rAor0_idxd(rA_addr, rB_addr) );
80971f5fe1fc3a37ca729925e8eec25aa1025b4a6cdbcarll         store( mkexpr(EA), mkexpr(frS) );
8098d953ebb9b04cbad6891676df597bf0c542b1ec89cerion         break;
8099e14bb9f862843c6b804097c124961b5567ded4f1sewardj
81005b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion      case 0x2F7: // stfdux (Store Float Dbl, Update Indxd, PPC32 p515)
8101b183b8571b4ec98866ce2b3653a9d066cf5f16f4sewardj         if (rA_addr == 0)
8102d953ebb9b04cbad6891676df597bf0c542b1ec89cerion            return False;
8103d953ebb9b04cbad6891676df597bf0c542b1ec89cerion         DIP("stfdux fr%u,r%u,r%u\n", frS_addr, rA_addr, rB_addr);
8104d953ebb9b04cbad6891676df597bf0c542b1ec89cerion         assign( EA, ea_rA_idxd(rA_addr, rB_addr) );
81051f5fe1fc3a37ca729925e8eec25aa1025b4a6cdbcarll         store( mkexpr(EA), mkexpr(frS) );
8106d953ebb9b04cbad6891676df597bf0c542b1ec89cerion         putIReg( rA_addr, mkexpr(EA) );
8107d953ebb9b04cbad6891676df597bf0c542b1ec89cerion         break;
81085f63c0ca784e4d23aca807ebd967ca46bdf95132sewardj
810909e88d11fceef4483f7803414b939e4173fe7f54sewardj      case 0x3D7: // stfiwx (Store Float as Int, Indexed, PPC32 p517)
81105117ce116f47141cb23d1b49cc826e19323add97sewardj         // NOTE: POWERPC OPTIONAL, "Graphics Group" (PPC32_GX)
811109e88d11fceef4483f7803414b939e4173fe7f54sewardj         DIP("stfiwx fr%u,r%u,r%u\n", frS_addr, rA_addr, rB_addr);
811209e88d11fceef4483f7803414b939e4173fe7f54sewardj         assign( EA, ea_rAor0_idxd(rA_addr, rB_addr) );
81131f5fe1fc3a37ca729925e8eec25aa1025b4a6cdbcarll         store( mkexpr(EA),
81141f5fe1fc3a37ca729925e8eec25aa1025b4a6cdbcarll                unop(Iop_64to32, unop(Iop_ReinterpF64asI64, mkexpr(frS))) );
811509e88d11fceef4483f7803414b939e4173fe7f54sewardj         break;
8116e14bb9f862843c6b804097c124961b5567ded4f1sewardj
8117d953ebb9b04cbad6891676df597bf0c542b1ec89cerion      default:
81185b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion         vex_printf("dis_fp_store(ppc)(opc2)\n");
8119d953ebb9b04cbad6891676df597bf0c542b1ec89cerion         return False;
8120e14bb9f862843c6b804097c124961b5567ded4f1sewardj      }
8121e14bb9f862843c6b804097c124961b5567ded4f1sewardj      break;
8122a982c0503d8c0c6069ae453bfe70657bd2c134aecerion
8123a982c0503d8c0c6069ae453bfe70657bd2c134aecerion   default:
81245b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion      vex_printf("dis_fp_store(ppc)(opc1)\n");
8125a982c0503d8c0c6069ae453bfe70657bd2c134aecerion      return False;
8126a982c0503d8c0c6069ae453bfe70657bd2c134aecerion   }
8127a982c0503d8c0c6069ae453bfe70657bd2c134aecerion   return True;
8128a982c0503d8c0c6069ae453bfe70657bd2c134aecerion}
8129a982c0503d8c0c6069ae453bfe70657bd2c134aecerion
8130a982c0503d8c0c6069ae453bfe70657bd2c134aecerion
8131b51f0f4f33256638ed953156a2635aa739b232f1sewardj
8132a982c0503d8c0c6069ae453bfe70657bd2c134aecerion/*
8133b51f0f4f33256638ed953156a2635aa739b232f1sewardj  Floating Point Arith Instructions
8134a982c0503d8c0c6069ae453bfe70657bd2c134aecerion*/
8135b51f0f4f33256638ed953156a2635aa739b232f1sewardjstatic Bool dis_fp_arith ( UInt theInstr )
8136a982c0503d8c0c6069ae453bfe70657bd2c134aecerion{
8137b51f0f4f33256638ed953156a2635aa739b232f1sewardj   /* A-Form */
813876de5cf615380b23b4b5bcced6541233cd4a93a0cerion   UChar opc1     = ifieldOPC(theInstr);
813976de5cf615380b23b4b5bcced6541233cd4a93a0cerion   UChar frD_addr = ifieldRegDS(theInstr);
814076de5cf615380b23b4b5bcced6541233cd4a93a0cerion   UChar frA_addr = ifieldRegA(theInstr);
814176de5cf615380b23b4b5bcced6541233cd4a93a0cerion   UChar frB_addr = ifieldRegB(theInstr);
814276de5cf615380b23b4b5bcced6541233cd4a93a0cerion   UChar frC_addr = ifieldRegC(theInstr);
814376de5cf615380b23b4b5bcced6541233cd4a93a0cerion   UChar opc2     = ifieldOPClo5(theInstr);
814476de5cf615380b23b4b5bcced6541233cd4a93a0cerion   UChar flag_rC  = ifieldBIT0(theInstr);
8145a982c0503d8c0c6069ae453bfe70657bd2c134aecerion
8146b183b8571b4ec98866ce2b3653a9d066cf5f16f4sewardj   IRTemp  frD = newTemp(Ity_F64);
8147b183b8571b4ec98866ce2b3653a9d066cf5f16f4sewardj   IRTemp  frA = newTemp(Ity_F64);
8148b183b8571b4ec98866ce2b3653a9d066cf5f16f4sewardj   IRTemp  frB = newTemp(Ity_F64);
8149b183b8571b4ec98866ce2b3653a9d066cf5f16f4sewardj   IRTemp  frC = newTemp(Ity_F64);
8150b183b8571b4ec98866ce2b3653a9d066cf5f16f4sewardj   IRExpr* rm  = get_IR_roundingmode();
8151b183b8571b4ec98866ce2b3653a9d066cf5f16f4sewardj
8152b183b8571b4ec98866ce2b3653a9d066cf5f16f4sewardj   /* By default, we will examine the results of the operation and set
8153b183b8571b4ec98866ce2b3653a9d066cf5f16f4sewardj      fpscr[FPRF] accordingly. */
8154b183b8571b4ec98866ce2b3653a9d066cf5f16f4sewardj   Bool set_FPRF = True;
8155b183b8571b4ec98866ce2b3653a9d066cf5f16f4sewardj
8156b183b8571b4ec98866ce2b3653a9d066cf5f16f4sewardj   /* By default, if flag_RC is set, we will clear cr1 after the
8157b183b8571b4ec98866ce2b3653a9d066cf5f16f4sewardj      operation.  In reality we should set cr1 to indicate the
8158b183b8571b4ec98866ce2b3653a9d066cf5f16f4sewardj      exception status of the operation, but since we're not
8159b183b8571b4ec98866ce2b3653a9d066cf5f16f4sewardj      simulating exceptions, the exception status will appear to be
8160b183b8571b4ec98866ce2b3653a9d066cf5f16f4sewardj      zero.  Hence cr1 should be cleared if this is a . form insn. */
8161b183b8571b4ec98866ce2b3653a9d066cf5f16f4sewardj   Bool clear_CR1 = True;
8162a982c0503d8c0c6069ae453bfe70657bd2c134aecerion
8163b51f0f4f33256638ed953156a2635aa739b232f1sewardj   assign( frA, getFReg(frA_addr));
8164b51f0f4f33256638ed953156a2635aa739b232f1sewardj   assign( frB, getFReg(frB_addr));
8165b51f0f4f33256638ed953156a2635aa739b232f1sewardj   assign( frC, getFReg(frC_addr));
8166a982c0503d8c0c6069ae453bfe70657bd2c134aecerion
8167b51f0f4f33256638ed953156a2635aa739b232f1sewardj   switch (opc1) {
8168e14bb9f862843c6b804097c124961b5567ded4f1sewardj   case 0x3B:
8169e14bb9f862843c6b804097c124961b5567ded4f1sewardj      switch (opc2) {
8170e14bb9f862843c6b804097c124961b5567ded4f1sewardj      case 0x12: // fdivs (Floating Divide Single, PPC32 p407)
8171b183b8571b4ec98866ce2b3653a9d066cf5f16f4sewardj         if (frC_addr != 0)
8172e14bb9f862843c6b804097c124961b5567ded4f1sewardj            return False;
81735b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion         DIP("fdivs%s fr%u,fr%u,fr%u\n", flag_rC ? ".":"",
8174e14bb9f862843c6b804097c124961b5567ded4f1sewardj             frD_addr, frA_addr, frB_addr);
8175b183b8571b4ec98866ce2b3653a9d066cf5f16f4sewardj         assign( frD, triop( Iop_DivF64r32,
8176b183b8571b4ec98866ce2b3653a9d066cf5f16f4sewardj                             rm, mkexpr(frA), mkexpr(frB) ));
8177e14bb9f862843c6b804097c124961b5567ded4f1sewardj         break;
8178e14bb9f862843c6b804097c124961b5567ded4f1sewardj
8179e14bb9f862843c6b804097c124961b5567ded4f1sewardj      case 0x14: // fsubs (Floating Subtract Single, PPC32 p430)
8180b183b8571b4ec98866ce2b3653a9d066cf5f16f4sewardj         if (frC_addr != 0)
8181e14bb9f862843c6b804097c124961b5567ded4f1sewardj            return False;
81825b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion         DIP("fsubs%s fr%u,fr%u,fr%u\n", flag_rC ? ".":"",
8183e14bb9f862843c6b804097c124961b5567ded4f1sewardj             frD_addr, frA_addr, frB_addr);
8184b183b8571b4ec98866ce2b3653a9d066cf5f16f4sewardj         assign( frD, triop( Iop_SubF64r32,
8185b183b8571b4ec98866ce2b3653a9d066cf5f16f4sewardj                             rm, mkexpr(frA), mkexpr(frB) ));
8186e14bb9f862843c6b804097c124961b5567ded4f1sewardj         break;
8187e14bb9f862843c6b804097c124961b5567ded4f1sewardj
8188e14bb9f862843c6b804097c124961b5567ded4f1sewardj      case 0x15: // fadds (Floating Add Single, PPC32 p401)
8189b183b8571b4ec98866ce2b3653a9d066cf5f16f4sewardj         if (frC_addr != 0)
8190e14bb9f862843c6b804097c124961b5567ded4f1sewardj            return False;
81915b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion         DIP("fadds%s fr%u,fr%u,fr%u\n", flag_rC ? ".":"",
8192e14bb9f862843c6b804097c124961b5567ded4f1sewardj             frD_addr, frA_addr, frB_addr);
8193b183b8571b4ec98866ce2b3653a9d066cf5f16f4sewardj         assign( frD, triop( Iop_AddF64r32,
8194b183b8571b4ec98866ce2b3653a9d066cf5f16f4sewardj                             rm, mkexpr(frA), mkexpr(frB) ));
8195e14bb9f862843c6b804097c124961b5567ded4f1sewardj         break;
8196e14bb9f862843c6b804097c124961b5567ded4f1sewardj
8197870c84bfeeda8ee31755e04ba548136d36dd3941sewardj      case 0x16: // fsqrts (Floating SqRt (Single-Precision), PPC32 p428)
81985117ce116f47141cb23d1b49cc826e19323add97sewardj         // NOTE: POWERPC OPTIONAL, "General-Purpose Group" (PPC32_FX)
8199b183b8571b4ec98866ce2b3653a9d066cf5f16f4sewardj         if (frA_addr != 0 || frC_addr != 0)
8200870c84bfeeda8ee31755e04ba548136d36dd3941sewardj            return False;
8201870c84bfeeda8ee31755e04ba548136d36dd3941sewardj         DIP("fsqrts%s fr%u,fr%u\n", flag_rC ? ".":"",
8202870c84bfeeda8ee31755e04ba548136d36dd3941sewardj             frD_addr, frB_addr);
820379fd33f4e243276b8109fe56c3eb1d4c9ccea7ccsewardj         // however illogically, on ppc970 this insn behaves identically
8204b183b8571b4ec98866ce2b3653a9d066cf5f16f4sewardj         // to fsqrt (double-precision).  So use SqrtF64, not SqrtF64r32.
8205b183b8571b4ec98866ce2b3653a9d066cf5f16f4sewardj         assign( frD, binop( Iop_SqrtF64, rm, mkexpr(frB) ));
8206870c84bfeeda8ee31755e04ba548136d36dd3941sewardj         break;
8207e14bb9f862843c6b804097c124961b5567ded4f1sewardj
8208baf971ad7f6e005109f3301ec9d19c98066b3840sewardj      case 0x18: // fres (Floating Reciprocal Estimate Single, PPC32 p421)
82095117ce116f47141cb23d1b49cc826e19323add97sewardj         // NOTE: POWERPC OPTIONAL, "Graphics Group" (PPC32_GX)
8210b183b8571b4ec98866ce2b3653a9d066cf5f16f4sewardj         if (frA_addr != 0 || frC_addr != 0)
8211baf971ad7f6e005109f3301ec9d19c98066b3840sewardj            return False;
8212baf971ad7f6e005109f3301ec9d19c98066b3840sewardj         DIP("fres%s fr%u,fr%u\n", flag_rC ? ".":"",
8213baf971ad7f6e005109f3301ec9d19c98066b3840sewardj             frD_addr, frB_addr);
8214157b19b5ad19287b29939250c00765a426070174sewardj         { IRExpr* ieee_one
8215157b19b5ad19287b29939250c00765a426070174sewardj              = IRExpr_Const(IRConst_F64i(0x3ff0000000000000ULL));
8216b183b8571b4ec98866ce2b3653a9d066cf5f16f4sewardj           assign( frD, triop( Iop_DivF64r32,
8217b183b8571b4ec98866ce2b3653a9d066cf5f16f4sewardj                               rm,
8218b183b8571b4ec98866ce2b3653a9d066cf5f16f4sewardj                               ieee_one, mkexpr(frB) ));
8219157b19b5ad19287b29939250c00765a426070174sewardj         }
8220baf971ad7f6e005109f3301ec9d19c98066b3840sewardj         break;
8221e14bb9f862843c6b804097c124961b5567ded4f1sewardj
8222e14bb9f862843c6b804097c124961b5567ded4f1sewardj      case 0x19: // fmuls (Floating Multiply Single, PPC32 p414)
8223b183b8571b4ec98866ce2b3653a9d066cf5f16f4sewardj         if (frB_addr != 0)
8224e14bb9f862843c6b804097c124961b5567ded4f1sewardj            return False;
82255b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion         DIP("fmuls%s fr%u,fr%u,fr%u\n", flag_rC ? ".":"",
8226e14bb9f862843c6b804097c124961b5567ded4f1sewardj             frD_addr, frA_addr, frC_addr);
8227b183b8571b4ec98866ce2b3653a9d066cf5f16f4sewardj         assign( frD, triop( Iop_MulF64r32,
8228b183b8571b4ec98866ce2b3653a9d066cf5f16f4sewardj                             rm, mkexpr(frA), mkexpr(frC) ));
8229e14bb9f862843c6b804097c124961b5567ded4f1sewardj         break;
8230e14bb9f862843c6b804097c124961b5567ded4f1sewardj
823179fd33f4e243276b8109fe56c3eb1d4c9ccea7ccsewardj      case 0x1A: // frsqrtes (Floating Recip SqRt Est Single)
823279fd33f4e243276b8109fe56c3eb1d4c9ccea7ccsewardj         // NOTE: POWERPC OPTIONAL, "Graphics Group" (PPC32_GX)
823379fd33f4e243276b8109fe56c3eb1d4c9ccea7ccsewardj         // Undocumented instruction?
8234b183b8571b4ec98866ce2b3653a9d066cf5f16f4sewardj         if (frA_addr != 0 || frC_addr != 0)
823579fd33f4e243276b8109fe56c3eb1d4c9ccea7ccsewardj            return False;
823679fd33f4e243276b8109fe56c3eb1d4c9ccea7ccsewardj         DIP("frsqrtes%s fr%u,fr%u\n", flag_rC ? ".":"",
823779fd33f4e243276b8109fe56c3eb1d4c9ccea7ccsewardj             frD_addr, frB_addr);
82381ddee21008ffdb2ac7f8e6a73445f150f753606fsewardj         assign( frD, unop(Iop_RSqrtEst5GoodF64, mkexpr(frB)) );
823979fd33f4e243276b8109fe56c3eb1d4c9ccea7ccsewardj         break;
824079fd33f4e243276b8109fe56c3eb1d4c9ccea7ccsewardj
8241e14bb9f862843c6b804097c124961b5567ded4f1sewardj      default:
82425b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion         vex_printf("dis_fp_arith(ppc)(3B: opc2)\n");
8243e14bb9f862843c6b804097c124961b5567ded4f1sewardj         return False;
8244e14bb9f862843c6b804097c124961b5567ded4f1sewardj      }
8245e14bb9f862843c6b804097c124961b5567ded4f1sewardj      break;
8246a982c0503d8c0c6069ae453bfe70657bd2c134aecerion
8247b51f0f4f33256638ed953156a2635aa739b232f1sewardj   case 0x3F:
8248b51f0f4f33256638ed953156a2635aa739b232f1sewardj      switch (opc2) {
82495b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion      case 0x12: // fdiv (Floating Div (Double-Precision), PPC32 p406)
8250b183b8571b4ec98866ce2b3653a9d066cf5f16f4sewardj         if (frC_addr != 0)
8251e14bb9f862843c6b804097c124961b5567ded4f1sewardj            return False;
82525b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion         DIP("fdiv%s fr%u,fr%u,fr%u\n", flag_rC ? ".":"",
8253e14bb9f862843c6b804097c124961b5567ded4f1sewardj             frD_addr, frA_addr, frB_addr);
8254b183b8571b4ec98866ce2b3653a9d066cf5f16f4sewardj         assign( frD, triop(Iop_DivF64, rm, mkexpr(frA), mkexpr(frB)) );
8255e14bb9f862843c6b804097c124961b5567ded4f1sewardj         break;
8256e14bb9f862843c6b804097c124961b5567ded4f1sewardj
82575b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion      case 0x14: // fsub (Floating Sub (Double-Precision), PPC32 p429)
8258b183b8571b4ec98866ce2b3653a9d066cf5f16f4sewardj         if (frC_addr != 0)
8259e14bb9f862843c6b804097c124961b5567ded4f1sewardj            return False;
82605b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion         DIP("fsub%s fr%u,fr%u,fr%u\n", flag_rC ? ".":"",
8261e14bb9f862843c6b804097c124961b5567ded4f1sewardj             frD_addr, frA_addr, frB_addr);
8262b183b8571b4ec98866ce2b3653a9d066cf5f16f4sewardj         assign( frD, triop(Iop_SubF64, rm, mkexpr(frA), mkexpr(frB)) );
8263e14bb9f862843c6b804097c124961b5567ded4f1sewardj         break;
8264a982c0503d8c0c6069ae453bfe70657bd2c134aecerion
8265b51f0f4f33256638ed953156a2635aa739b232f1sewardj      case 0x15: // fadd (Floating Add (Double-Precision), PPC32 p400)
8266b183b8571b4ec98866ce2b3653a9d066cf5f16f4sewardj         if (frC_addr != 0)
8267b51f0f4f33256638ed953156a2635aa739b232f1sewardj            return False;
82685b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion         DIP("fadd%s fr%u,fr%u,fr%u\n", flag_rC ? ".":"",
8269b51f0f4f33256638ed953156a2635aa739b232f1sewardj             frD_addr, frA_addr, frB_addr);
8270b183b8571b4ec98866ce2b3653a9d066cf5f16f4sewardj         assign( frD, triop(Iop_AddF64, rm, mkexpr(frA), mkexpr(frB)) );
8271b51f0f4f33256638ed953156a2635aa739b232f1sewardj         break;
8272a982c0503d8c0c6069ae453bfe70657bd2c134aecerion
8273876ef41aec4bba650f92c4601c26d8f76738e26acerion      case 0x16: // fsqrt (Floating SqRt (Double-Precision), PPC32 p427)
82745117ce116f47141cb23d1b49cc826e19323add97sewardj         // NOTE: POWERPC OPTIONAL, "General-Purpose Group" (PPC32_FX)
8275b183b8571b4ec98866ce2b3653a9d066cf5f16f4sewardj         if (frA_addr != 0 || frC_addr != 0)
8276876ef41aec4bba650f92c4601c26d8f76738e26acerion            return False;
82775b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion         DIP("fsqrt%s fr%u,fr%u\n", flag_rC ? ".":"",
8278876ef41aec4bba650f92c4601c26d8f76738e26acerion             frD_addr, frB_addr);
8279b183b8571b4ec98866ce2b3653a9d066cf5f16f4sewardj         assign( frD, binop(Iop_SqrtF64, rm, mkexpr(frB)) );
8280876ef41aec4bba650f92c4601c26d8f76738e26acerion         break;
8281e14bb9f862843c6b804097c124961b5567ded4f1sewardj
8282e14bb9f862843c6b804097c124961b5567ded4f1sewardj      case 0x17: { // fsel (Floating Select, PPC32 p426)
82835117ce116f47141cb23d1b49cc826e19323add97sewardj         // NOTE: POWERPC OPTIONAL, "Graphics Group" (PPC32_GX)
8284e14bb9f862843c6b804097c124961b5567ded4f1sewardj         IRTemp cc    = newTemp(Ity_I32);
8285e14bb9f862843c6b804097c124961b5567ded4f1sewardj         IRTemp cc_b0 = newTemp(Ity_I32);
8286e14bb9f862843c6b804097c124961b5567ded4f1sewardj
82875b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion         DIP("fsel%s fr%u,fr%u,fr%u,fr%u\n", flag_rC ? ".":"",
8288e14bb9f862843c6b804097c124961b5567ded4f1sewardj             frD_addr, frA_addr, frC_addr, frB_addr);
8289e14bb9f862843c6b804097c124961b5567ded4f1sewardj
8290e14bb9f862843c6b804097c124961b5567ded4f1sewardj         // cc: UN == 0x41, LT == 0x01, GT == 0x00, EQ == 0x40
8291e14bb9f862843c6b804097c124961b5567ded4f1sewardj         // => GT|EQ == (cc & 0x1 == 0)
82925b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion         assign( cc, binop(Iop_CmpF64, mkexpr(frA),
82935b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion                                       IRExpr_Const(IRConst_F64(0))) );
8294e14bb9f862843c6b804097c124961b5567ded4f1sewardj         assign( cc_b0, binop(Iop_And32, mkexpr(cc), mkU32(1)) );
8295e14bb9f862843c6b804097c124961b5567ded4f1sewardj
8296e14bb9f862843c6b804097c124961b5567ded4f1sewardj         // frD = (frA >= 0.0) ? frC : frB
8297e14bb9f862843c6b804097c124961b5567ded4f1sewardj         //     = (cc_b0 == 0) ? frC : frB
8298e14bb9f862843c6b804097c124961b5567ded4f1sewardj         assign( frD,
829999dd03e04a6914d90d5fee727d61d76905334becflorian                 IRExpr_ITE(
8300009230b9758291b594e60d7c0243a73d53e81854sewardj                    binop(Iop_CmpEQ32, mkexpr(cc_b0), mkU32(0)),
830199dd03e04a6914d90d5fee727d61d76905334becflorian                    mkexpr(frC),
830299dd03e04a6914d90d5fee727d61d76905334becflorian                    mkexpr(frB) ));
8303b183b8571b4ec98866ce2b3653a9d066cf5f16f4sewardj
8304b183b8571b4ec98866ce2b3653a9d066cf5f16f4sewardj         /* One of the rare ones which don't mess with FPRF */
8305b183b8571b4ec98866ce2b3653a9d066cf5f16f4sewardj         set_FPRF = False;
8306e14bb9f862843c6b804097c124961b5567ded4f1sewardj         break;
8307e14bb9f862843c6b804097c124961b5567ded4f1sewardj      }
8308e14bb9f862843c6b804097c124961b5567ded4f1sewardj
830979fd33f4e243276b8109fe56c3eb1d4c9ccea7ccsewardj      case 0x18: // fre (Floating Reciprocal Estimate)
831079fd33f4e243276b8109fe56c3eb1d4c9ccea7ccsewardj         // NOTE: POWERPC OPTIONAL, "Graphics Group" (PPC32_GX)
831179fd33f4e243276b8109fe56c3eb1d4c9ccea7ccsewardj         // Note: unclear whether this insn really exists or not
831279fd33f4e243276b8109fe56c3eb1d4c9ccea7ccsewardj         // ppc970 doesn't have it, but POWER5 does
8313b183b8571b4ec98866ce2b3653a9d066cf5f16f4sewardj         if (frA_addr != 0 || frC_addr != 0)
831479fd33f4e243276b8109fe56c3eb1d4c9ccea7ccsewardj            return False;
831579fd33f4e243276b8109fe56c3eb1d4c9ccea7ccsewardj         DIP("fre%s fr%u,fr%u\n", flag_rC ? ".":"",
831679fd33f4e243276b8109fe56c3eb1d4c9ccea7ccsewardj             frD_addr, frB_addr);
8317157b19b5ad19287b29939250c00765a426070174sewardj         { IRExpr* ieee_one
8318157b19b5ad19287b29939250c00765a426070174sewardj              = IRExpr_Const(IRConst_F64i(0x3ff0000000000000ULL));
8319b183b8571b4ec98866ce2b3653a9d066cf5f16f4sewardj           assign( frD, triop( Iop_DivF64,
832056de421a90e9b68ad96894e731932d10aaf0636dsewardj                               rm,
8321b183b8571b4ec98866ce2b3653a9d066cf5f16f4sewardj                               ieee_one, mkexpr(frB) ));
8322157b19b5ad19287b29939250c00765a426070174sewardj         }
832379fd33f4e243276b8109fe56c3eb1d4c9ccea7ccsewardj         break;
832479fd33f4e243276b8109fe56c3eb1d4c9ccea7ccsewardj
83255b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion      case 0x19: // fmul (Floating Mult (Double Precision), PPC32 p413)
8326b183b8571b4ec98866ce2b3653a9d066cf5f16f4sewardj         if (frB_addr != 0)
83275b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion            vex_printf("dis_fp_arith(ppc)(instr,fmul)\n");
83285b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion         DIP("fmul%s fr%u,fr%u,fr%u\n", flag_rC ? ".":"",
8329e14bb9f862843c6b804097c124961b5567ded4f1sewardj             frD_addr, frA_addr, frC_addr);
8330b183b8571b4ec98866ce2b3653a9d066cf5f16f4sewardj         assign( frD, triop(Iop_MulF64, rm, mkexpr(frA), mkexpr(frC)) );
8331e14bb9f862843c6b804097c124961b5567ded4f1sewardj         break;
8332e14bb9f862843c6b804097c124961b5567ded4f1sewardj
8333baf971ad7f6e005109f3301ec9d19c98066b3840sewardj      case 0x1A: // frsqrte (Floating Recip SqRt Est., PPC32 p424)
83345117ce116f47141cb23d1b49cc826e19323add97sewardj         // NOTE: POWERPC OPTIONAL, "Graphics Group" (PPC32_GX)
8335b183b8571b4ec98866ce2b3653a9d066cf5f16f4sewardj         if (frA_addr != 0 || frC_addr != 0)
8336baf971ad7f6e005109f3301ec9d19c98066b3840sewardj            return False;
8337baf971ad7f6e005109f3301ec9d19c98066b3840sewardj         DIP("frsqrte%s fr%u,fr%u\n", flag_rC ? ".":"",
8338baf971ad7f6e005109f3301ec9d19c98066b3840sewardj             frD_addr, frB_addr);
83391ddee21008ffdb2ac7f8e6a73445f150f753606fsewardj         assign( frD, unop(Iop_RSqrtEst5GoodF64, mkexpr(frB)) );
8340baf971ad7f6e005109f3301ec9d19c98066b3840sewardj         break;
8341a982c0503d8c0c6069ae453bfe70657bd2c134aecerion
8342b51f0f4f33256638ed953156a2635aa739b232f1sewardj      default:
83435b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion         vex_printf("dis_fp_arith(ppc)(3F: opc2)\n");
8344b51f0f4f33256638ed953156a2635aa739b232f1sewardj         return False;
8345b51f0f4f33256638ed953156a2635aa739b232f1sewardj      }
8346b51f0f4f33256638ed953156a2635aa739b232f1sewardj      break;
8347a982c0503d8c0c6069ae453bfe70657bd2c134aecerion
8348a982c0503d8c0c6069ae453bfe70657bd2c134aecerion   default:
83495b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion      vex_printf("dis_fp_arith(ppc)(opc1)\n");
8350a982c0503d8c0c6069ae453bfe70657bd2c134aecerion      return False;
8351a982c0503d8c0c6069ae453bfe70657bd2c134aecerion   }
8352a982c0503d8c0c6069ae453bfe70657bd2c134aecerion
8353b51f0f4f33256638ed953156a2635aa739b232f1sewardj   putFReg( frD_addr, mkexpr(frD) );
8354b183b8571b4ec98866ce2b3653a9d066cf5f16f4sewardj
8355b183b8571b4ec98866ce2b3653a9d066cf5f16f4sewardj   if (set_FPRF) {
8356b183b8571b4ec98866ce2b3653a9d066cf5f16f4sewardj      // XXX XXX XXX FIXME
8357b183b8571b4ec98866ce2b3653a9d066cf5f16f4sewardj      // set FPRF from frD
8358b183b8571b4ec98866ce2b3653a9d066cf5f16f4sewardj   }
8359b183b8571b4ec98866ce2b3653a9d066cf5f16f4sewardj
8360b183b8571b4ec98866ce2b3653a9d066cf5f16f4sewardj   if (flag_rC && clear_CR1) {
8361b183b8571b4ec98866ce2b3653a9d066cf5f16f4sewardj      putCR321( 1, mkU8(0) );
8362b183b8571b4ec98866ce2b3653a9d066cf5f16f4sewardj      putCR0( 1, mkU8(0) );
8363b183b8571b4ec98866ce2b3653a9d066cf5f16f4sewardj   }
8364b183b8571b4ec98866ce2b3653a9d066cf5f16f4sewardj
8365b51f0f4f33256638ed953156a2635aa739b232f1sewardj   return True;
8366b51f0f4f33256638ed953156a2635aa739b232f1sewardj}
8367a982c0503d8c0c6069ae453bfe70657bd2c134aecerion
8368a982c0503d8c0c6069ae453bfe70657bd2c134aecerion
8369a982c0503d8c0c6069ae453bfe70657bd2c134aecerion
8370e14bb9f862843c6b804097c124961b5567ded4f1sewardj/*
8371e14bb9f862843c6b804097c124961b5567ded4f1sewardj  Floating Point Mult-Add Instructions
8372e14bb9f862843c6b804097c124961b5567ded4f1sewardj*/
8373e14bb9f862843c6b804097c124961b5567ded4f1sewardjstatic Bool dis_fp_multadd ( UInt theInstr )
8374e14bb9f862843c6b804097c124961b5567ded4f1sewardj{
8375e14bb9f862843c6b804097c124961b5567ded4f1sewardj   /* A-Form */
837676de5cf615380b23b4b5bcced6541233cd4a93a0cerion   UChar opc1     = ifieldOPC(theInstr);
837776de5cf615380b23b4b5bcced6541233cd4a93a0cerion   UChar frD_addr = ifieldRegDS(theInstr);
837876de5cf615380b23b4b5bcced6541233cd4a93a0cerion   UChar frA_addr = ifieldRegA(theInstr);
837976de5cf615380b23b4b5bcced6541233cd4a93a0cerion   UChar frB_addr = ifieldRegB(theInstr);
838076de5cf615380b23b4b5bcced6541233cd4a93a0cerion   UChar frC_addr = ifieldRegC(theInstr);
838176de5cf615380b23b4b5bcced6541233cd4a93a0cerion   UChar opc2     = ifieldOPClo5(theInstr);
838276de5cf615380b23b4b5bcced6541233cd4a93a0cerion   UChar flag_rC  = ifieldBIT0(theInstr);
8383e14bb9f862843c6b804097c124961b5567ded4f1sewardj
8384b183b8571b4ec98866ce2b3653a9d066cf5f16f4sewardj   IRTemp  frD = newTemp(Ity_F64);
8385b183b8571b4ec98866ce2b3653a9d066cf5f16f4sewardj   IRTemp  frA = newTemp(Ity_F64);
8386b183b8571b4ec98866ce2b3653a9d066cf5f16f4sewardj   IRTemp  frB = newTemp(Ity_F64);
8387b183b8571b4ec98866ce2b3653a9d066cf5f16f4sewardj   IRTemp  frC = newTemp(Ity_F64);
8388b183b8571b4ec98866ce2b3653a9d066cf5f16f4sewardj   IRTemp  rmt = newTemp(Ity_I32);
83892bcdd653612c726da0b7203b579b8f6114703be4sewardj   IRTemp  tmp = newTemp(Ity_F64);
83902bcdd653612c726da0b7203b579b8f6114703be4sewardj   IRTemp  sign_tmp = newTemp(Ity_I64);
83912bcdd653612c726da0b7203b579b8f6114703be4sewardj   IRTemp  nan_mask = newTemp(Ity_I32);
8392b183b8571b4ec98866ce2b3653a9d066cf5f16f4sewardj   IRExpr* rm;
8393b183b8571b4ec98866ce2b3653a9d066cf5f16f4sewardj
8394b183b8571b4ec98866ce2b3653a9d066cf5f16f4sewardj   /* By default, we will examine the results of the operation and set
8395b183b8571b4ec98866ce2b3653a9d066cf5f16f4sewardj      fpscr[FPRF] accordingly. */
8396b183b8571b4ec98866ce2b3653a9d066cf5f16f4sewardj   Bool set_FPRF = True;
8397b183b8571b4ec98866ce2b3653a9d066cf5f16f4sewardj
8398b183b8571b4ec98866ce2b3653a9d066cf5f16f4sewardj   /* By default, if flag_RC is set, we will clear cr1 after the
8399b183b8571b4ec98866ce2b3653a9d066cf5f16f4sewardj      operation.  In reality we should set cr1 to indicate the
8400b183b8571b4ec98866ce2b3653a9d066cf5f16f4sewardj      exception status of the operation, but since we're not
8401b183b8571b4ec98866ce2b3653a9d066cf5f16f4sewardj      simulating exceptions, the exception status will appear to be
8402b183b8571b4ec98866ce2b3653a9d066cf5f16f4sewardj      zero.  Hence cr1 should be cleared if this is a . form insn. */
8403b183b8571b4ec98866ce2b3653a9d066cf5f16f4sewardj   Bool clear_CR1 = True;
8404b183b8571b4ec98866ce2b3653a9d066cf5f16f4sewardj
8405b183b8571b4ec98866ce2b3653a9d066cf5f16f4sewardj   /* Bind the rounding mode expression to a temp; there's no
8406b183b8571b4ec98866ce2b3653a9d066cf5f16f4sewardj      point in creating gratuitous CSEs, as we know we'll need
8407b183b8571b4ec98866ce2b3653a9d066cf5f16f4sewardj      to use it twice. */
8408b183b8571b4ec98866ce2b3653a9d066cf5f16f4sewardj   assign( rmt, get_IR_roundingmode() );
8409b183b8571b4ec98866ce2b3653a9d066cf5f16f4sewardj   rm = mkexpr(rmt);
8410e14bb9f862843c6b804097c124961b5567ded4f1sewardj
8411e14bb9f862843c6b804097c124961b5567ded4f1sewardj   assign( frA, getFReg(frA_addr));
8412e14bb9f862843c6b804097c124961b5567ded4f1sewardj   assign( frB, getFReg(frB_addr));
8413e14bb9f862843c6b804097c124961b5567ded4f1sewardj   assign( frC, getFReg(frC_addr));
8414e14bb9f862843c6b804097c124961b5567ded4f1sewardj
8415b183b8571b4ec98866ce2b3653a9d066cf5f16f4sewardj   /* The rounding in this is all a bit dodgy.  The idea is to only do
8416b183b8571b4ec98866ce2b3653a9d066cf5f16f4sewardj      one rounding.  That clearly isn't achieveable without dedicated
8417b183b8571b4ec98866ce2b3653a9d066cf5f16f4sewardj      four-input IR primops, although in the single precision case we
8418b183b8571b4ec98866ce2b3653a9d066cf5f16f4sewardj      can sort-of simulate it by doing the inner multiply in double
8419b183b8571b4ec98866ce2b3653a9d066cf5f16f4sewardj      precision.
8420b183b8571b4ec98866ce2b3653a9d066cf5f16f4sewardj
8421b183b8571b4ec98866ce2b3653a9d066cf5f16f4sewardj      In the negated cases, the negation happens after rounding. */
8422b183b8571b4ec98866ce2b3653a9d066cf5f16f4sewardj
8423e14bb9f862843c6b804097c124961b5567ded4f1sewardj   switch (opc1) {
8424e14bb9f862843c6b804097c124961b5567ded4f1sewardj   case 0x3B:
8425e14bb9f862843c6b804097c124961b5567ded4f1sewardj      switch (opc2) {
8426e14bb9f862843c6b804097c124961b5567ded4f1sewardj      case 0x1C: // fmsubs (Floating Mult-Subtr Single, PPC32 p412)
84275b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion         DIP("fmsubs%s fr%u,fr%u,fr%u,fr%u\n", flag_rC ? ".":"",
8428e14bb9f862843c6b804097c124961b5567ded4f1sewardj             frD_addr, frA_addr, frC_addr, frB_addr);
842940c802659108a96bb87cbc1a30b7b77e2abd0829sewardj         assign( frD, qop( Iop_MSubF64r32, rm,
843040c802659108a96bb87cbc1a30b7b77e2abd0829sewardj                           mkexpr(frA), mkexpr(frC), mkexpr(frB) ));
8431b183b8571b4ec98866ce2b3653a9d066cf5f16f4sewardj         break;
8432e14bb9f862843c6b804097c124961b5567ded4f1sewardj
8433e14bb9f862843c6b804097c124961b5567ded4f1sewardj      case 0x1D: // fmadds (Floating Mult-Add Single, PPC32 p409)
84345b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion         DIP("fmadds%s fr%u,fr%u,fr%u,fr%u\n", flag_rC ? ".":"",
8435e14bb9f862843c6b804097c124961b5567ded4f1sewardj             frD_addr, frA_addr, frC_addr, frB_addr);
843640c802659108a96bb87cbc1a30b7b77e2abd0829sewardj         assign( frD, qop( Iop_MAddF64r32, rm,
843740c802659108a96bb87cbc1a30b7b77e2abd0829sewardj                           mkexpr(frA), mkexpr(frC), mkexpr(frB) ));
8438e14bb9f862843c6b804097c124961b5567ded4f1sewardj         break;
8439e14bb9f862843c6b804097c124961b5567ded4f1sewardj
8440e14bb9f862843c6b804097c124961b5567ded4f1sewardj      case 0x1E: // fnmsubs (Float Neg Mult-Subtr Single, PPC32 p420)
8441e14bb9f862843c6b804097c124961b5567ded4f1sewardj      case 0x1F: // fnmadds (Floating Negative Multiply-Add Single, PPC32 p418)
84422bcdd653612c726da0b7203b579b8f6114703be4sewardj
84432bcdd653612c726da0b7203b579b8f6114703be4sewardj         if (opc2 == 0x1E) {
84442bcdd653612c726da0b7203b579b8f6114703be4sewardj            DIP("fnmsubs%s fr%u,fr%u,fr%u,fr%u\n", flag_rC ? ".":"",
84452bcdd653612c726da0b7203b579b8f6114703be4sewardj                     frD_addr, frA_addr, frC_addr, frB_addr);
84462bcdd653612c726da0b7203b579b8f6114703be4sewardj            assign( tmp, qop( Iop_MSubF64r32, rm,
84472bcdd653612c726da0b7203b579b8f6114703be4sewardj                              mkexpr(frA), mkexpr(frC), mkexpr(frB) ) );
84482bcdd653612c726da0b7203b579b8f6114703be4sewardj         } else {
84492bcdd653612c726da0b7203b579b8f6114703be4sewardj            DIP("fnmadds%s fr%u,fr%u,fr%u,fr%u\n", flag_rC ? ".":"",
84502bcdd653612c726da0b7203b579b8f6114703be4sewardj                     frD_addr, frA_addr, frC_addr, frB_addr);
84512bcdd653612c726da0b7203b579b8f6114703be4sewardj            assign( tmp, qop( Iop_MAddF64r32, rm,
84522bcdd653612c726da0b7203b579b8f6114703be4sewardj                              mkexpr(frA), mkexpr(frC), mkexpr(frB) ) );
84532bcdd653612c726da0b7203b579b8f6114703be4sewardj         }
84542bcdd653612c726da0b7203b579b8f6114703be4sewardj
84552bcdd653612c726da0b7203b579b8f6114703be4sewardj         assign( nan_mask, Check_NaN( mkexpr( tmp ),
84562bcdd653612c726da0b7203b579b8f6114703be4sewardj                                      mkU32( NANmaskSingle ) ) );
84572bcdd653612c726da0b7203b579b8f6114703be4sewardj         assign( sign_tmp, Complement_non_NaN( mkexpr( tmp ),
84582bcdd653612c726da0b7203b579b8f6114703be4sewardj                                               mkexpr( nan_mask ) ) );
84592bcdd653612c726da0b7203b579b8f6114703be4sewardj         assign( frD, unop( Iop_ReinterpI64asF64, mkexpr( sign_tmp ) ) );
8460e14bb9f862843c6b804097c124961b5567ded4f1sewardj         break;
8461e14bb9f862843c6b804097c124961b5567ded4f1sewardj
8462e14bb9f862843c6b804097c124961b5567ded4f1sewardj      default:
84635b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion         vex_printf("dis_fp_multadd(ppc)(3B: opc2)\n");
8464e14bb9f862843c6b804097c124961b5567ded4f1sewardj         return False;
8465e14bb9f862843c6b804097c124961b5567ded4f1sewardj      }
8466e14bb9f862843c6b804097c124961b5567ded4f1sewardj      break;
8467e14bb9f862843c6b804097c124961b5567ded4f1sewardj
8468e14bb9f862843c6b804097c124961b5567ded4f1sewardj   case 0x3F:
8469e14bb9f862843c6b804097c124961b5567ded4f1sewardj      switch (opc2) {
84705b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion      case 0x1C: // fmsub (Float Mult-Sub (Dbl Precision), PPC32 p411)
84715b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion         DIP("fmsub%s fr%u,fr%u,fr%u,fr%u\n", flag_rC ? ".":"",
8472e14bb9f862843c6b804097c124961b5567ded4f1sewardj             frD_addr, frA_addr, frC_addr, frB_addr);
847340c802659108a96bb87cbc1a30b7b77e2abd0829sewardj         assign( frD, qop( Iop_MSubF64, rm,
847440c802659108a96bb87cbc1a30b7b77e2abd0829sewardj                           mkexpr(frA), mkexpr(frC), mkexpr(frB) ));
8475e14bb9f862843c6b804097c124961b5567ded4f1sewardj         break;
8476e14bb9f862843c6b804097c124961b5567ded4f1sewardj
84775b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion      case 0x1D: // fmadd (Float Mult-Add (Dbl Precision), PPC32 p408)
84785b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion         DIP("fmadd%s fr%u,fr%u,fr%u,fr%u\n", flag_rC ? ".":"",
8479e14bb9f862843c6b804097c124961b5567ded4f1sewardj             frD_addr, frA_addr, frC_addr, frB_addr);
848040c802659108a96bb87cbc1a30b7b77e2abd0829sewardj         assign( frD, qop( Iop_MAddF64, rm,
848140c802659108a96bb87cbc1a30b7b77e2abd0829sewardj                           mkexpr(frA), mkexpr(frC), mkexpr(frB) ));
8482e14bb9f862843c6b804097c124961b5567ded4f1sewardj         break;
8483e14bb9f862843c6b804097c124961b5567ded4f1sewardj
84845b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion      case 0x1E: // fnmsub (Float Neg Mult-Subtr (Dbl Precision), PPC32 p419)
84855b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion      case 0x1F: // fnmadd (Float Neg Mult-Add (Dbl Precision), PPC32 p417)
84862bcdd653612c726da0b7203b579b8f6114703be4sewardj
84872bcdd653612c726da0b7203b579b8f6114703be4sewardj         if (opc2 == 0x1E) {
84882bcdd653612c726da0b7203b579b8f6114703be4sewardj            DIP("fnmsub%s fr%u,fr%u,fr%u,fr%u\n", flag_rC ? ".":"",
84892bcdd653612c726da0b7203b579b8f6114703be4sewardj                     frD_addr, frA_addr, frC_addr, frB_addr);
84902bcdd653612c726da0b7203b579b8f6114703be4sewardj            assign( tmp, qop( Iop_MSubF64, rm,
84912bcdd653612c726da0b7203b579b8f6114703be4sewardj                              mkexpr(frA), mkexpr(frC), mkexpr(frB) ) );
84922bcdd653612c726da0b7203b579b8f6114703be4sewardj         } else {
84932bcdd653612c726da0b7203b579b8f6114703be4sewardj            DIP("fnmadd%s fr%u,fr%u,fr%u,fr%u\n", flag_rC ? ".":"",
84942bcdd653612c726da0b7203b579b8f6114703be4sewardj                     frD_addr, frA_addr, frC_addr, frB_addr);
84952bcdd653612c726da0b7203b579b8f6114703be4sewardj            assign( tmp, qop( Iop_MAddF64, rm,
84962bcdd653612c726da0b7203b579b8f6114703be4sewardj                              mkexpr(frA), mkexpr(frC), mkexpr(frB) ));
84972bcdd653612c726da0b7203b579b8f6114703be4sewardj         }
84982bcdd653612c726da0b7203b579b8f6114703be4sewardj
84992bcdd653612c726da0b7203b579b8f6114703be4sewardj         assign( nan_mask, Check_NaN( mkexpr( tmp ),
85002bcdd653612c726da0b7203b579b8f6114703be4sewardj                                      mkU32( NANmaskDouble ) ) );
85012bcdd653612c726da0b7203b579b8f6114703be4sewardj         assign( sign_tmp, Complement_non_NaN( mkexpr( tmp ),
85022bcdd653612c726da0b7203b579b8f6114703be4sewardj                                               mkexpr( nan_mask ) ) );
85032bcdd653612c726da0b7203b579b8f6114703be4sewardj         assign( frD, unop( Iop_ReinterpI64asF64, mkexpr( sign_tmp ) ) );
85040e2cc67b30d1bb4d0515a1e09d944143becb3881sewardj         break;
8505e14bb9f862843c6b804097c124961b5567ded4f1sewardj
8506e14bb9f862843c6b804097c124961b5567ded4f1sewardj      default:
85075b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion         vex_printf("dis_fp_multadd(ppc)(3F: opc2)\n");
8508e14bb9f862843c6b804097c124961b5567ded4f1sewardj         return False;
8509e14bb9f862843c6b804097c124961b5567ded4f1sewardj      }
8510e14bb9f862843c6b804097c124961b5567ded4f1sewardj      break;
8511e14bb9f862843c6b804097c124961b5567ded4f1sewardj
8512e14bb9f862843c6b804097c124961b5567ded4f1sewardj   default:
85135b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion      vex_printf("dis_fp_multadd(ppc)(opc1)\n");
8514e14bb9f862843c6b804097c124961b5567ded4f1sewardj      return False;
8515e14bb9f862843c6b804097c124961b5567ded4f1sewardj   }
8516e14bb9f862843c6b804097c124961b5567ded4f1sewardj
8517e14bb9f862843c6b804097c124961b5567ded4f1sewardj   putFReg( frD_addr, mkexpr(frD) );
8518b183b8571b4ec98866ce2b3653a9d066cf5f16f4sewardj
8519b183b8571b4ec98866ce2b3653a9d066cf5f16f4sewardj   if (set_FPRF) {
8520b183b8571b4ec98866ce2b3653a9d066cf5f16f4sewardj      // XXX XXX XXX FIXME
8521b183b8571b4ec98866ce2b3653a9d066cf5f16f4sewardj      // set FPRF from frD
8522b183b8571b4ec98866ce2b3653a9d066cf5f16f4sewardj   }
8523b183b8571b4ec98866ce2b3653a9d066cf5f16f4sewardj
8524b183b8571b4ec98866ce2b3653a9d066cf5f16f4sewardj   if (flag_rC && clear_CR1) {
8525b183b8571b4ec98866ce2b3653a9d066cf5f16f4sewardj      putCR321( 1, mkU8(0) );
8526b183b8571b4ec98866ce2b3653a9d066cf5f16f4sewardj      putCR0( 1, mkU8(0) );
8527b183b8571b4ec98866ce2b3653a9d066cf5f16f4sewardj   }
8528b183b8571b4ec98866ce2b3653a9d066cf5f16f4sewardj
8529e14bb9f862843c6b804097c124961b5567ded4f1sewardj   return True;
8530e14bb9f862843c6b804097c124961b5567ded4f1sewardj}
8531e14bb9f862843c6b804097c124961b5567ded4f1sewardj
853266d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj/*
853366d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj * fe_flag is set to 1 if any of the following conditions occurs:
8534e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj *  - The floating-point operand in register FRB is a Zero, a
8535e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj *    NaN, an Infinity, or a negative value.
8536e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj *  - e_b is less than or equal to: -970 for double precision; -103 for single precision
8537e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj *  Otherwise fe_flag is set to 0.
8538e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj *
8539e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj * fg_flag is set to 1 if either of the following conditions occurs.
8540e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj *   - The floating-point operand in register FRB is a Zero, an
8541e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj *     Infinity, or a denormalized value.
8542e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj *  Otherwise fg_flag is set to 0.
8543e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj *
8544e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj */
8545e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardjstatic void do_fp_tsqrt(IRTemp frB_Int, Bool sp, IRTemp * fe_flag_tmp, IRTemp * fg_flag_tmp)
8546e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj{
8547e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj   // The following temps are for holding intermediate results
8548e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj   IRTemp e_b = newTemp(Ity_I32);
8549e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj   IRExpr * fe_flag,  * fg_flag;
8550e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj   IRTemp frB_exp_shR = newTemp(Ity_I32);
8551e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj   UInt bias = sp? 127 : 1023;
8552e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj   IRExpr * frbNaN, * frbDenorm, * frBNeg;
8553e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj   IRExpr * eb_LTE;
8554e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj   IRTemp  frbZero_tmp = newTemp(Ity_I1);
8555e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj   IRTemp  frbInf_tmp = newTemp(Ity_I1);
8556e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj   *fe_flag_tmp = newTemp(Ity_I32);
8557e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj   *fg_flag_tmp = newTemp(Ity_I32);
8558e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj   assign( frB_exp_shR, fp_exp_part( frB_Int, sp ) );
8559e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj   assign(e_b, binop( Iop_Sub32, mkexpr(frB_exp_shR), mkU32( bias ) ));
8560e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj
8561e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj   //////////////////  fe_flag tests BEGIN //////////////////////
8562e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj   /* We first do all tests that may result in setting fe_flag to '1'.
8563e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj    * (NOTE: These tests are similar to those used for ftdiv.  See do_fp_tdiv()
8564e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj    * for details.)
8565e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj    */
8566e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj   frbNaN = sp ? is_NaN_32(frB_Int) : is_NaN(frB_Int);
8567e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj   assign( frbInf_tmp, is_Inf(frB_Int, sp) );
8568e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj   assign( frbZero_tmp, is_Zero(frB_Int, sp ) );
8569e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj   {
8570e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj      // Test_value = -970 for double precision
8571e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj      UInt test_value = sp ? 0xffffff99 : 0xfffffc36;
8572e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj      eb_LTE = binop( Iop_CmpLE32S, mkexpr( e_b ), mkU32( test_value ) );
8573e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj   }
8574e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj   frBNeg = binop( Iop_CmpEQ32,
8575e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj                   binop( Iop_Shr32,
8576e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj                          sp ? mkexpr( frB_Int ) : unop( Iop_64HIto32, mkexpr( frB_Int ) ),
8577e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj                          mkU8( 31 ) ),
8578e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj                   mkU32( 1 ) );
8579e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj   //////////////////  fe_flag tests END //////////////////////
8580e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj
8581e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj   //////////////////  fg_flag tests BEGIN //////////////////////
8582e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj   /*
8583e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj    * The following tests were already performed above in the fe_flag
8584e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj    * tests.  So these conditions will result in both fe_ and fg_ flags
8585e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj    * being set.
8586e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj    *   - Test if FRB is Zero
8587e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj    *   - Test if FRB is an Infinity
8588e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj    */
8589e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj
8590e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj   /*
8591e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj    * Test if FRB holds a denormalized value.  A denormalized value is one where
8592e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj    * the exp is 0 and the fraction is non-zero.
8593e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj    */
8594e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj   if (sp) {
8595e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj      IRTemp frac_part = newTemp(Ity_I32);
8596e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj      assign( frac_part, binop( Iop_And32, mkexpr(frB_Int), mkU32(0x007fffff)) );
8597e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj      frbDenorm
8598e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj               = mkAND1( binop( Iop_CmpEQ32, mkexpr( frB_exp_shR ), mkU32( 0 ) ),
8599e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj                         binop( Iop_CmpNE32, mkexpr( frac_part ), mkU32( 0 ) ) );
8600e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj   } else {
8601e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj      IRExpr * hi32, * low32, * fraction_is_nonzero;
8602e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj      IRTemp frac_part = newTemp(Ity_I64);
8603e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj
8604e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj      assign( frac_part, FP_FRAC_PART(frB_Int) );
8605e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj      hi32 = unop( Iop_64HIto32, mkexpr( frac_part ) );
8606e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj      low32 = unop( Iop_64to32, mkexpr( frac_part ) );
8607e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj      fraction_is_nonzero = binop( Iop_CmpNE32, binop( Iop_Or32, low32, hi32 ),
8608e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj                                                mkU32( 0 ) );
8609e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj      frbDenorm
8610e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj               = mkAND1( binop( Iop_CmpEQ32, mkexpr( frB_exp_shR ), mkU32( 0 ) ),
8611e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj                         fraction_is_nonzero );
8612e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj   }
8613e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj   //////////////////  fg_flag tests END //////////////////////
8614e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj
8615e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj   /////////////////////////
8616e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj   fe_flag = mkOR1( mkexpr( frbZero_tmp ),
8617e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj                    mkOR1( frbNaN,
8618e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj                           mkOR1( mkexpr( frbInf_tmp ),
8619e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj                                  mkOR1( frBNeg, eb_LTE ) ) ) );
8620e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj
8621e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj   fe_flag = unop(Iop_1Uto32, fe_flag);
8622e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj
8623e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj   fg_flag = mkOR1( mkexpr( frbZero_tmp ),
8624e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj                    mkOR1( mkexpr( frbInf_tmp ), frbDenorm ) );
8625e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj   fg_flag = unop(Iop_1Uto32, fg_flag);
8626e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj   assign (*fg_flag_tmp, fg_flag);
8627e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj   assign (*fe_flag_tmp, fe_flag);
8628e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj}
8629e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj/*
8630e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj * fe_flag is set to 1 if any of the following conditions occurs:
863166d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj *  - The double-precision floating-point operand in register FRA is a NaN or an
863266d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj *    Infinity.
863366d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj *  - The double-precision floating-point operand in register FRB is a Zero, a
863466d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj *    NaN, or an Infinity.
863566d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj *  - e_b is less than or equal to -1022.
863666d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj *  - e_b is greater than or equal to 1021.
863766d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj *  - The double-precision floating-point operand in register FRA is not a zero
863866d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj *    and the difference, e_a - e_b, is greater than or equal to 1023.
863966d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj *  - The double-precision floating-point operand in register FRA is not a zero
864066d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj *    and the difference, e_a - e_b, is less than or equal to -1021.
864166d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj *  - The double-precision floating-point operand in register FRA is not a zero
864266d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj *    and e_a is less than or equal to -970
864366d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj *  Otherwise fe_flag is set to 0.
864466d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj *
864566d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj * fg_flag is set to 1 if either of the following conditions occurs.
864666d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj *   - The double-precision floating-point operand in register FRA is an Infinity.
864766d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj *   - The double-precision floating-point operand in register FRB is a Zero, an
864866d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj *     Infinity, or a denormalized value.
864966d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj *  Otherwise fg_flag is set to 0.
865066d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj *
865166d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj */
8652e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardjstatic void _do_fp_tdiv(IRTemp frA_int, IRTemp frB_int, Bool sp, IRTemp * fe_flag_tmp, IRTemp * fg_flag_tmp)
865366d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj{
865466d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj   // The following temps are for holding intermediate results
865566d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj   IRTemp e_a = newTemp(Ity_I32);
865666d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj   IRTemp e_b = newTemp(Ity_I32);
865766d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj   IRTemp frA_exp_shR = newTemp(Ity_I32);
865866d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj   IRTemp frB_exp_shR = newTemp(Ity_I32);
865966d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj
8660e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj   UInt bias = sp? 127 : 1023;
8661e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj   *fe_flag_tmp = newTemp(Ity_I32);
8662e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj   *fg_flag_tmp = newTemp(Ity_I32);
866366d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj
866466d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj   /* The following variables hold boolean results from tests
866566d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj    * that are OR'ed together for setting the fe_ and fg_ flags.
866666d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj    * For some cases, the booleans are used more than once, so
866766d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj    * I make those IRTemp's instead of IRExpr's.
866866d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj    */
866966d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj   IRExpr * fraNaN, * frbNaN, * frbDenorm;
867066d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj   IRExpr * eb_LTE, * eb_GTE, * ea_eb_GTE, * ea_eb_LTE, * ea_LTE;
867166d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj   IRTemp  fraInf_tmp = newTemp(Ity_I1);
867266d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj   IRTemp  frbZero_tmp = newTemp(Ity_I1);
867366d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj   IRTemp  frbInf_tmp = newTemp(Ity_I1);
867466d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj   IRTemp  fraNotZero_tmp = newTemp(Ity_I1);
867566d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj
867666d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj/* The following are the flags that are set by OR'ing the results of
86774aa412af1d8166cc11f39a6e721df49431d23618sewardj * all the tests done for tdiv.  These flags are the input to the specified CR.
867866d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj */
8679e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj   IRExpr * fe_flag, * fg_flag;
868066d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj
868166d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj   // Create temps that will be used throughout the following tests.
8682e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj   assign( frA_exp_shR, fp_exp_part( frA_int, sp ) );
8683e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj   assign( frB_exp_shR, fp_exp_part( frB_int, sp ) );
868466d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj   /* Let e_[a|b] be the unbiased exponent: i.e. exp - 1023. */
868566d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj   assign(e_a, binop( Iop_Sub32, mkexpr(frA_exp_shR), mkU32( bias ) ));
868666d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj   assign(e_b, binop( Iop_Sub32, mkexpr(frB_exp_shR), mkU32( bias ) ));
868766d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj
868866d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj
868966d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj   //////////////////  fe_flag tests BEGIN //////////////////////
869066d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj   /* We first do all tests that may result in setting fe_flag to '1'. */
869166d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj
869266d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj   /*
869366d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj    * Test if the double-precision floating-point operand in register FRA is
869466d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj    * a NaN:
869566d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj    */
8696e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj   fraNaN = sp ? is_NaN_32(frA_int) : is_NaN(frA_int);
869766d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj   /*
869866d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj    * Test if the double-precision floating-point operand in register FRA is
869966d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj    * an Infinity.
870066d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj    */
8701e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj   assign(fraInf_tmp, is_Inf(frA_int, sp));
870266d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj
870366d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj   /*
870466d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj    * Test if the double-precision floating-point operand in register FRB is
870566d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj    * a NaN:
870666d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj    */
8707e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj   frbNaN = sp ? is_NaN_32(frB_int) : is_NaN(frB_int);
870866d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj   /*
870966d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj    * Test if the double-precision floating-point operand in register FRB is
871066d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj    * an Infinity.
871166d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj    */
8712e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj   assign( frbInf_tmp, is_Inf(frB_int, sp) );
871366d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj   /*
871466d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj    * Test if the double-precision floating-point operand in register FRB is
871566d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj    * a Zero.
871666d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj    */
8717e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj   assign( frbZero_tmp, is_Zero(frB_int, sp) );
871866d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj
871966d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj   /*
8720e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj    * Test if e_b <= -1022 for double precision;
8721e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj    * or e_b <= -126 for single precision
872266d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj    */
872366d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj   {
8724e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj      UInt test_value = sp ? 0xffffff82 : 0xfffffc02;
872566d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj      eb_LTE = binop(Iop_CmpLE32S, mkexpr(e_b), mkU32(test_value));
872666d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj   }
872766d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj
872866d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj   /*
8729e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj    * Test if e_b >= 1021 (i.e., 1021 < e_b) for double precision;
8730e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj    * or e_b >= -125 (125 < e_b) for single precision
873166d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj    */
873266d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj   {
8733e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj      Int test_value = sp ? 125 : 1021;
873466d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj      eb_GTE = binop(Iop_CmpLT32S, mkU32(test_value), mkexpr(e_b));
873566d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj   }
8736e14bb9f862843c6b804097c124961b5567ded4f1sewardj
873766d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj   /*
8738e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj    * Test if FRA != Zero and (e_a - e_b) >= bias
873966d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj    */
8740e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj   assign( fraNotZero_tmp, unop( Iop_Not1, is_Zero( frA_int, sp ) ) );
874166d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj   ea_eb_GTE = mkAND1( mkexpr( fraNotZero_tmp ),
874266d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj                       binop( Iop_CmpLT32S, mkU32( bias ),
874366d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj                              binop( Iop_Sub32, mkexpr( e_a ),
874466d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj                                     mkexpr( e_b ) ) ) );
874566d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj
874666d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj   /*
8747e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj    * Test if FRA != Zero and (e_a - e_b) <= [-1021 (double precision) or -125 (single precision)]
874866d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj    */
874966d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj   {
8750e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj      UInt test_value = sp ? 0xffffff83 : 0xfffffc03;
875166d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj
875266d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj      ea_eb_LTE = mkAND1( mkexpr( fraNotZero_tmp ),
875366d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj                          binop( Iop_CmpLE32S,
875466d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj                                 binop( Iop_Sub32,
875566d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj                                        mkexpr( e_a ),
875666d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj                                        mkexpr( e_b ) ),
875766d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj                                        mkU32( test_value ) ) );
875866d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj   }
875966d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj
876066d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj   /*
8761e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj    * Test if FRA != Zero and e_a <= [-970 (double precision) or -103 (single precision)]
876266d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj    */
876366d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj   {
876466d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj      UInt test_value = 0xfffffc36;  //Int test_value = -970;
876566d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj
876666d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj      ea_LTE = mkAND1( mkexpr( fraNotZero_tmp ), binop( Iop_CmpLE32S,
876766d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj                                                        mkexpr( e_a ),
876866d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj                                                        mkU32( test_value ) ) );
876966d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj   }
877066d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj   //////////////////  fe_flag tests END //////////////////////
877166d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj
877266d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj   //////////////////  fg_flag tests BEGIN //////////////////////
877366d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj   /*
877466d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj    * The following tests were already performed above in the fe_flag
877566d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj    * tests.  So these conditions will result in both fe_ and fg_ flags
877666d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj    * being set.
877766d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj    *   - Test if FRA is an Infinity
877866d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj    *   - Test if FRB ix Zero
877966d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj    *   - Test if FRB is an Infinity
878066d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj    */
878166d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj
878266d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj   /*
878366d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj    * Test if FRB holds a denormalized value.  A denormalized value is one where
878466d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj    * the exp is 0 and the fraction is non-zero.
878566d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj    */
878666d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj   {
8787e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj      IRExpr * fraction_is_nonzero;
878866d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj
8789e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj      if (sp) {
8790e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj         fraction_is_nonzero = binop( Iop_CmpNE32, FP_FRAC_PART32(frB_int),
8791e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj                                      mkU32( 0 ) );
8792e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj      } else {
8793e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj         IRExpr * hi32, * low32;
8794e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj         IRTemp frac_part = newTemp(Ity_I64);
8795e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj         assign( frac_part, FP_FRAC_PART(frB_int) );
8796e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj
8797e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj         hi32 = unop( Iop_64HIto32, mkexpr( frac_part ) );
8798e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj         low32 = unop( Iop_64to32, mkexpr( frac_part ) );
8799e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj         fraction_is_nonzero = binop( Iop_CmpNE32, binop( Iop_Or32, low32, hi32 ),
8800e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj                                      mkU32( 0 ) );
8801e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj      }
880266d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj      frbDenorm = mkAND1( binop( Iop_CmpEQ32, mkexpr( frB_exp_shR ),
8803e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj                                 mkU32( 0x0 ) ), fraction_is_nonzero );
880466d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj
880566d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj   }
880666d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj   //////////////////  fg_flag tests END //////////////////////
880766d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj
880866d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj   fe_flag
880966d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj   = mkOR1(
881066d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj            fraNaN,
881166d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj            mkOR1(
881266d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj                   mkexpr( fraInf_tmp ),
881366d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj                   mkOR1(
881466d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj                          mkexpr( frbZero_tmp ),
881566d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj                          mkOR1(
881666d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj                                 frbNaN,
881766d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj                                 mkOR1(
881866d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj                                        mkexpr( frbInf_tmp ),
881966d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj                                        mkOR1( eb_LTE,
882066d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj                                               mkOR1( eb_GTE,
882166d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj                                                      mkOR1( ea_eb_GTE,
882266d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj                                                             mkOR1( ea_eb_LTE,
882366d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj                                                                    ea_LTE ) ) ) ) ) ) ) ) );
882466d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj
882566d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj   fe_flag = unop(Iop_1Uto32, fe_flag);
882666d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj
882766d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj   fg_flag = mkOR1( mkexpr( fraInf_tmp ), mkOR1( mkexpr( frbZero_tmp ),
882866d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj                                                 mkOR1( mkexpr( frbInf_tmp ),
882966d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj                                                        frbDenorm ) ) );
883066d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj   fg_flag = unop(Iop_1Uto32, fg_flag);
8831e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj   assign(*fe_flag_tmp, fe_flag);
8832e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj   assign(*fg_flag_tmp, fg_flag);
8833e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj}
883466d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj
8835e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj/* See description for _do_fp_tdiv() above. */
8836e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardjstatic IRExpr * do_fp_tdiv(IRTemp frA_int, IRTemp frB_int)
8837e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj{
8838e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj   IRTemp  fe_flag, fg_flag;
8839e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj   /////////////////////////
8840e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj   /* The CR field consists of fl_flag || fg_flag || fe_flag || 0b0
8841e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj    * where fl_flag == 1 on ppc64.
8842e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj    */
8843e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj   IRExpr * fl_flag = unop(Iop_Not32, mkU32(0xFFFFFE));
8844e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj   fe_flag = fg_flag = IRTemp_INVALID;
8845e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj   _do_fp_tdiv(frA_int, frB_int, False/*not single precision*/, &fe_flag, &fg_flag);
88464aa412af1d8166cc11f39a6e721df49431d23618sewardj   return binop( Iop_Or32,
88474aa412af1d8166cc11f39a6e721df49431d23618sewardj                 binop( Iop_Or32,
88484aa412af1d8166cc11f39a6e721df49431d23618sewardj                        binop( Iop_Shl32, fl_flag, mkU8( 3 ) ),
8849e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj                        binop( Iop_Shl32, mkexpr(fg_flag), mkU8( 2 ) ) ),
8850e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj                 binop( Iop_Shl32, mkexpr(fe_flag), mkU8( 1 ) ) );
88514aa412af1d8166cc11f39a6e721df49431d23618sewardj}
88524aa412af1d8166cc11f39a6e721df49431d23618sewardj
8853e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardjstatic Bool dis_fp_tests ( UInt theInstr )
88544aa412af1d8166cc11f39a6e721df49431d23618sewardj{
88554aa412af1d8166cc11f39a6e721df49431d23618sewardj   UChar opc1     = ifieldOPC(theInstr);
88564aa412af1d8166cc11f39a6e721df49431d23618sewardj   UChar crfD     = toUChar( IFIELD( theInstr, 23, 3 ) );
88574aa412af1d8166cc11f39a6e721df49431d23618sewardj   UChar frB_addr = ifieldRegB(theInstr);
88584aa412af1d8166cc11f39a6e721df49431d23618sewardj   UChar b0       = ifieldBIT0(theInstr);
8859e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj   UInt  opc2     = ifieldOPClo10(theInstr);
88604aa412af1d8166cc11f39a6e721df49431d23618sewardj   IRTemp frB_I64     = newTemp(Ity_I64);
88614aa412af1d8166cc11f39a6e721df49431d23618sewardj
8862e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj   if (opc1 != 0x3F || b0 != 0 ){
8863e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj      vex_printf("dis_fp_tests(ppc)(ftdiv)\n");
88644aa412af1d8166cc11f39a6e721df49431d23618sewardj      return False;
88654aa412af1d8166cc11f39a6e721df49431d23618sewardj   }
88664aa412af1d8166cc11f39a6e721df49431d23618sewardj   assign( frB_I64, unop( Iop_ReinterpF64asI64, getFReg( frB_addr ) ) );
88674aa412af1d8166cc11f39a6e721df49431d23618sewardj
8868e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj   switch (opc2) {
8869e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj      case 0x080: // ftdiv
8870e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj      {
8871e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj         UChar frA_addr = ifieldRegA(theInstr);
8872e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj         IRTemp frA_I64     = newTemp(Ity_I64);
8873e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj         UChar b21to22  = toUChar( IFIELD( theInstr, 21, 2 ) );
8874e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj         if (b21to22 != 0 ) {
8875e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj            vex_printf("dis_fp_tests(ppc)(ftdiv)\n");
8876e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj            return False;
8877e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj         }
8878e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj
8879e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj         assign( frA_I64, unop( Iop_ReinterpF64asI64, getFReg( frA_addr ) ) );
8880e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj         putGST_field( PPC_GST_CR, do_fp_tdiv(frA_I64, frB_I64), crfD );
888166d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj
8882e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj         DIP("ftdiv crf%d,fr%u,fr%u\n", crfD, frA_addr, frB_addr);
8883e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj         break;
8884e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj      }
8885e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj      case 0x0A0: // ftsqrt
8886e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj      {
8887e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj         IRTemp flags = newTemp(Ity_I32);
8888e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj         IRTemp  fe_flag, fg_flag;
8889e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj         fe_flag = fg_flag = IRTemp_INVALID;
8890e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj         UChar b18to22  = toUChar( IFIELD( theInstr, 18, 5 ) );
8891e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj         if ( b18to22 != 0) {
8892e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj            vex_printf("dis_fp_tests(ppc)(ftsqrt)\n");
8893e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj            return False;
8894e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj         }
8895e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj         DIP("ftsqrt crf%d,fr%u\n", crfD, frB_addr);
8896e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj         do_fp_tsqrt(frB_I64, False /* not single precision*/, &fe_flag, &fg_flag);
8897e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj         /* The CR field consists of fl_flag || fg_flag || fe_flag || 0b0
8898e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj          * where fl_flag == 1 on ppc64.
8899e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj          */
8900e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj         assign( flags,
8901e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj                 binop( Iop_Or32,
8902e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj                        binop( Iop_Or32, mkU32( 8 ), // fl_flag
8903e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj                               binop( Iop_Shl32, mkexpr(fg_flag), mkU8( 2 ) ) ),
8904e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj                        binop( Iop_Shl32, mkexpr(fe_flag), mkU8( 1 ) ) ) );
8905e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj         putGST_field( PPC_GST_CR, mkexpr(flags), crfD );
8906e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj         break;
8907e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj      }
8908e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj
8909e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj      default:
8910e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj         vex_printf("dis_fp_tests(ppc)(opc2)\n");
8911e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj         return False;
8912e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj
8913e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj   }
891466d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj   return True;
891566d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj}
8916e14bb9f862843c6b804097c124961b5567ded4f1sewardj
8917e14bb9f862843c6b804097c124961b5567ded4f1sewardj/*
8918e14bb9f862843c6b804097c124961b5567ded4f1sewardj  Floating Point Compare Instructions
8919e14bb9f862843c6b804097c124961b5567ded4f1sewardj*/
8920e14bb9f862843c6b804097c124961b5567ded4f1sewardjstatic Bool dis_fp_cmp ( UInt theInstr )
8921e14bb9f862843c6b804097c124961b5567ded4f1sewardj{
8922e14bb9f862843c6b804097c124961b5567ded4f1sewardj   /* X-Form */
892376de5cf615380b23b4b5bcced6541233cd4a93a0cerion   UChar opc1     = ifieldOPC(theInstr);
892476de5cf615380b23b4b5bcced6541233cd4a93a0cerion   UChar crfD     = toUChar( IFIELD( theInstr, 23, 3 ) );
892576de5cf615380b23b4b5bcced6541233cd4a93a0cerion   UChar b21to22  = toUChar( IFIELD( theInstr, 21, 2 ) );
892676de5cf615380b23b4b5bcced6541233cd4a93a0cerion   UChar frA_addr = ifieldRegA(theInstr);
892776de5cf615380b23b4b5bcced6541233cd4a93a0cerion   UChar frB_addr = ifieldRegB(theInstr);
892876de5cf615380b23b4b5bcced6541233cd4a93a0cerion   UInt  opc2     = ifieldOPClo10(theInstr);
892976de5cf615380b23b4b5bcced6541233cd4a93a0cerion   UChar b0       = ifieldBIT0(theInstr);
8930e14bb9f862843c6b804097c124961b5567ded4f1sewardj
8931e14bb9f862843c6b804097c124961b5567ded4f1sewardj   IRTemp ccIR    = newTemp(Ity_I32);
8932e14bb9f862843c6b804097c124961b5567ded4f1sewardj   IRTemp ccPPC32 = newTemp(Ity_I32);
8933e14bb9f862843c6b804097c124961b5567ded4f1sewardj
8934e14bb9f862843c6b804097c124961b5567ded4f1sewardj   IRTemp frA     = newTemp(Ity_F64);
8935e14bb9f862843c6b804097c124961b5567ded4f1sewardj   IRTemp frB     = newTemp(Ity_F64);
8936e14bb9f862843c6b804097c124961b5567ded4f1sewardj
8937e14bb9f862843c6b804097c124961b5567ded4f1sewardj   if (opc1 != 0x3F || b21to22 != 0 || b0 != 0) {
89385b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion      vex_printf("dis_fp_cmp(ppc)(instr)\n");
8939e14bb9f862843c6b804097c124961b5567ded4f1sewardj      return False;
8940e14bb9f862843c6b804097c124961b5567ded4f1sewardj   }
8941e14bb9f862843c6b804097c124961b5567ded4f1sewardj
8942e14bb9f862843c6b804097c124961b5567ded4f1sewardj   assign( frA, getFReg(frA_addr));
8943e14bb9f862843c6b804097c124961b5567ded4f1sewardj   assign( frB, getFReg(frB_addr));
8944e14bb9f862843c6b804097c124961b5567ded4f1sewardj
8945e14bb9f862843c6b804097c124961b5567ded4f1sewardj   assign( ccIR, binop(Iop_CmpF64, mkexpr(frA), mkexpr(frB)) );
8946e14bb9f862843c6b804097c124961b5567ded4f1sewardj
8947e14bb9f862843c6b804097c124961b5567ded4f1sewardj   /* Map compare result from IR to PPC32 */
8948e14bb9f862843c6b804097c124961b5567ded4f1sewardj   /*
8949e14bb9f862843c6b804097c124961b5567ded4f1sewardj     FP cmp result | PPC | IR
8950e14bb9f862843c6b804097c124961b5567ded4f1sewardj     --------------------------
8951e14bb9f862843c6b804097c124961b5567ded4f1sewardj     UN            | 0x1 | 0x45
8952e14bb9f862843c6b804097c124961b5567ded4f1sewardj     EQ            | 0x2 | 0x40
8953e14bb9f862843c6b804097c124961b5567ded4f1sewardj     GT            | 0x4 | 0x00
8954e14bb9f862843c6b804097c124961b5567ded4f1sewardj     LT            | 0x8 | 0x01
8955e14bb9f862843c6b804097c124961b5567ded4f1sewardj   */
8956e14bb9f862843c6b804097c124961b5567ded4f1sewardj
8957b183b8571b4ec98866ce2b3653a9d066cf5f16f4sewardj   // ccPPC32 = Shl(1, (~(ccIR>>5) & 2)
8958b183b8571b4ec98866ce2b3653a9d066cf5f16f4sewardj   //                    | ((ccIR ^ (ccIR>>6)) & 1)
8959e14bb9f862843c6b804097c124961b5567ded4f1sewardj   assign(
8960e14bb9f862843c6b804097c124961b5567ded4f1sewardj      ccPPC32,
8961b183b8571b4ec98866ce2b3653a9d066cf5f16f4sewardj      binop(
8962b183b8571b4ec98866ce2b3653a9d066cf5f16f4sewardj         Iop_Shl32,
8963b183b8571b4ec98866ce2b3653a9d066cf5f16f4sewardj         mkU32(1),
8964b183b8571b4ec98866ce2b3653a9d066cf5f16f4sewardj         unop(
8965b183b8571b4ec98866ce2b3653a9d066cf5f16f4sewardj            Iop_32to8,
8966b183b8571b4ec98866ce2b3653a9d066cf5f16f4sewardj            binop(
8967b183b8571b4ec98866ce2b3653a9d066cf5f16f4sewardj               Iop_Or32,
8968b183b8571b4ec98866ce2b3653a9d066cf5f16f4sewardj               binop(
8969b183b8571b4ec98866ce2b3653a9d066cf5f16f4sewardj                  Iop_And32,
8970b183b8571b4ec98866ce2b3653a9d066cf5f16f4sewardj                  unop(
8971b183b8571b4ec98866ce2b3653a9d066cf5f16f4sewardj                     Iop_Not32,
8972b183b8571b4ec98866ce2b3653a9d066cf5f16f4sewardj                     binop(Iop_Shr32, mkexpr(ccIR), mkU8(5))
8973b183b8571b4ec98866ce2b3653a9d066cf5f16f4sewardj                  ),
8974b183b8571b4ec98866ce2b3653a9d066cf5f16f4sewardj                  mkU32(2)
8975b183b8571b4ec98866ce2b3653a9d066cf5f16f4sewardj               ),
8976b183b8571b4ec98866ce2b3653a9d066cf5f16f4sewardj               binop(
8977b183b8571b4ec98866ce2b3653a9d066cf5f16f4sewardj                  Iop_And32,
8978b183b8571b4ec98866ce2b3653a9d066cf5f16f4sewardj                  binop(
8979b183b8571b4ec98866ce2b3653a9d066cf5f16f4sewardj                     Iop_Xor32,
8980b183b8571b4ec98866ce2b3653a9d066cf5f16f4sewardj                     mkexpr(ccIR),
8981b183b8571b4ec98866ce2b3653a9d066cf5f16f4sewardj                     binop(Iop_Shr32, mkexpr(ccIR), mkU8(6))
8982b183b8571b4ec98866ce2b3653a9d066cf5f16f4sewardj                  ),
8983b183b8571b4ec98866ce2b3653a9d066cf5f16f4sewardj                  mkU32(1)
8984b183b8571b4ec98866ce2b3653a9d066cf5f16f4sewardj               )
8985b183b8571b4ec98866ce2b3653a9d066cf5f16f4sewardj            )
8986b183b8571b4ec98866ce2b3653a9d066cf5f16f4sewardj         )
8987b183b8571b4ec98866ce2b3653a9d066cf5f16f4sewardj      )
8988e14bb9f862843c6b804097c124961b5567ded4f1sewardj   );
8989e14bb9f862843c6b804097c124961b5567ded4f1sewardj
8990d953ebb9b04cbad6891676df597bf0c542b1ec89cerion   putGST_field( PPC_GST_CR, mkexpr(ccPPC32), crfD );
8991e14bb9f862843c6b804097c124961b5567ded4f1sewardj
8992edf7fc572e2decb93e9143961e8739c8fe18899dcerion   /* CAB: TODO?: Support writing cc to FPSCR->FPCC ?
8993d953ebb9b04cbad6891676df597bf0c542b1ec89cerion      putGST_field( PPC_GST_FPSCR, mkexpr(ccPPC32), 4 );
8994edf7fc572e2decb93e9143961e8739c8fe18899dcerion   */
8995b183b8571b4ec98866ce2b3653a9d066cf5f16f4sewardj   // XXX XXX XXX FIXME
8996b183b8571b4ec98866ce2b3653a9d066cf5f16f4sewardj   // Also write the result into FPRF (it's not entirely clear how)
8997e14bb9f862843c6b804097c124961b5567ded4f1sewardj
8998edf7fc572e2decb93e9143961e8739c8fe18899dcerion   /* Note: Differences between fcmpu and fcmpo are only in exception
8999edf7fc572e2decb93e9143961e8739c8fe18899dcerion      flag settings, which aren't supported anyway. */
9000e14bb9f862843c6b804097c124961b5567ded4f1sewardj   switch (opc2) {
9001d953ebb9b04cbad6891676df597bf0c542b1ec89cerion   case 0x000: // fcmpu (Floating Compare Unordered, PPC32 p403)
9002d953ebb9b04cbad6891676df597bf0c542b1ec89cerion      DIP("fcmpu crf%d,fr%u,fr%u\n", crfD, frA_addr, frB_addr);
9003d953ebb9b04cbad6891676df597bf0c542b1ec89cerion      break;
9004d953ebb9b04cbad6891676df597bf0c542b1ec89cerion   case 0x020: // fcmpo (Floating Compare Ordered, PPC32 p402)
9005d953ebb9b04cbad6891676df597bf0c542b1ec89cerion      DIP("fcmpo crf%d,fr%u,fr%u\n", crfD, frA_addr, frB_addr);
9006d953ebb9b04cbad6891676df597bf0c542b1ec89cerion      break;
9007d953ebb9b04cbad6891676df597bf0c542b1ec89cerion   default:
90085b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion      vex_printf("dis_fp_cmp(ppc)(opc2)\n");
9009d953ebb9b04cbad6891676df597bf0c542b1ec89cerion      return False;
9010e14bb9f862843c6b804097c124961b5567ded4f1sewardj   }
9011e14bb9f862843c6b804097c124961b5567ded4f1sewardj   return True;
9012e14bb9f862843c6b804097c124961b5567ded4f1sewardj}
9013e14bb9f862843c6b804097c124961b5567ded4f1sewardj
9014e14bb9f862843c6b804097c124961b5567ded4f1sewardj
9015e14bb9f862843c6b804097c124961b5567ded4f1sewardj
9016e14bb9f862843c6b804097c124961b5567ded4f1sewardj/*
9017e14bb9f862843c6b804097c124961b5567ded4f1sewardj  Floating Point Rounding/Conversion Instructions
9018e14bb9f862843c6b804097c124961b5567ded4f1sewardj*/
9019e14bb9f862843c6b804097c124961b5567ded4f1sewardjstatic Bool dis_fp_round ( UInt theInstr )
9020e14bb9f862843c6b804097c124961b5567ded4f1sewardj{
9021e14bb9f862843c6b804097c124961b5567ded4f1sewardj   /* X-Form */
902276de5cf615380b23b4b5bcced6541233cd4a93a0cerion   UChar opc1     = ifieldOPC(theInstr);
902376de5cf615380b23b4b5bcced6541233cd4a93a0cerion   UChar b16to20  = ifieldRegA(theInstr);
90247e84630580f89c1022dde97007bffbf6aef81814sewardj   UChar frD_addr = ifieldRegDS(theInstr);
902576de5cf615380b23b4b5bcced6541233cd4a93a0cerion   UChar frB_addr = ifieldRegB(theInstr);
902676de5cf615380b23b4b5bcced6541233cd4a93a0cerion   UInt  opc2     = ifieldOPClo10(theInstr);
902776de5cf615380b23b4b5bcced6541233cd4a93a0cerion   UChar flag_rC  = ifieldBIT0(theInstr);
9028e14bb9f862843c6b804097c124961b5567ded4f1sewardj
9029b183b8571b4ec98866ce2b3653a9d066cf5f16f4sewardj   IRTemp  frD     = newTemp(Ity_F64);
9030b183b8571b4ec98866ce2b3653a9d066cf5f16f4sewardj   IRTemp  frB     = newTemp(Ity_F64);
9031b183b8571b4ec98866ce2b3653a9d066cf5f16f4sewardj   IRTemp  r_tmp32 = newTemp(Ity_I32);
9032b183b8571b4ec98866ce2b3653a9d066cf5f16f4sewardj   IRTemp  r_tmp64 = newTemp(Ity_I64);
9033b183b8571b4ec98866ce2b3653a9d066cf5f16f4sewardj   IRExpr* rm      = get_IR_roundingmode();
9034b183b8571b4ec98866ce2b3653a9d066cf5f16f4sewardj
9035b183b8571b4ec98866ce2b3653a9d066cf5f16f4sewardj   /* By default, we will examine the results of the operation and set
9036b183b8571b4ec98866ce2b3653a9d066cf5f16f4sewardj      fpscr[FPRF] accordingly. */
9037b183b8571b4ec98866ce2b3653a9d066cf5f16f4sewardj   Bool set_FPRF = True;
9038b183b8571b4ec98866ce2b3653a9d066cf5f16f4sewardj
9039b183b8571b4ec98866ce2b3653a9d066cf5f16f4sewardj   /* By default, if flag_RC is set, we will clear cr1 after the
9040b183b8571b4ec98866ce2b3653a9d066cf5f16f4sewardj      operation.  In reality we should set cr1 to indicate the
9041b183b8571b4ec98866ce2b3653a9d066cf5f16f4sewardj      exception status of the operation, but since we're not
9042b183b8571b4ec98866ce2b3653a9d066cf5f16f4sewardj      simulating exceptions, the exception status will appear to be
9043b183b8571b4ec98866ce2b3653a9d066cf5f16f4sewardj      zero.  Hence cr1 should be cleared if this is a . form insn. */
9044b183b8571b4ec98866ce2b3653a9d066cf5f16f4sewardj   Bool clear_CR1 = True;
904566d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj   if ((!(opc1 == 0x3F || opc1 == 0x3B)) || b16to20 != 0) {
90465b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion      vex_printf("dis_fp_round(ppc)(instr)\n");
9047e14bb9f862843c6b804097c124961b5567ded4f1sewardj      return False;
9048e14bb9f862843c6b804097c124961b5567ded4f1sewardj   }
9049e14bb9f862843c6b804097c124961b5567ded4f1sewardj
9050e14bb9f862843c6b804097c124961b5567ded4f1sewardj   assign( frB, getFReg(frB_addr));
905166d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj   if (opc1 == 0x3B) {
905266d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj      /* The fcfid[u]s instructions (from ISA 2.06) are a bit odd because
905366d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj       * they're very similar to the other instructions handled here, but have
905466d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj       * a different primary opcode.
905566d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj       */
905666d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj      switch (opc2) {
905766d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj         case 0x34E: // fcfids (Float convert from signed DWord to single precision)
905866d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj            DIP("fcfids%s fr%u,fr%u\n", flag_rC ? ".":"", frD_addr, frB_addr);
905966d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj            assign( r_tmp64, unop( Iop_ReinterpF64asI64, mkexpr(frB)) );
906066d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj            assign( frD, binop( Iop_RoundF64toF32, rm, binop( Iop_I64StoF64, rm,
906166d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj                                                              mkexpr( r_tmp64 ) ) ) );
906266d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj            goto putFR;
906366d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj
906466d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj         case 0x3Ce: // fcfidus (Float convert from unsigned DWord to single precision)
906566d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj            DIP("fcfidus%s fr%u,fr%u\n", flag_rC ? ".":"", frD_addr, frB_addr);
906666d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj            assign( r_tmp64, unop( Iop_ReinterpF64asI64, mkexpr(frB)) );
906795d6f3a3957232f97e6c680dd49de38cdeb9a1ffsewardj            assign( frD, unop( Iop_F32toF64, binop( Iop_I64UtoF32, rm, mkexpr( r_tmp64 ) ) ) );
906866d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj            goto putFR;
906966d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj      }
907066d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj   }
907166d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj
9072e14bb9f862843c6b804097c124961b5567ded4f1sewardj
9073e14bb9f862843c6b804097c124961b5567ded4f1sewardj   switch (opc2) {
9074f0de28cf1a762b0d6f74c93d3532c89a230673bbcerion   case 0x00C: // frsp (Float Round to Single, PPC32 p423)
90755b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion      DIP("frsp%s fr%u,fr%u\n", flag_rC ? ".":"", frD_addr, frB_addr);
9076b183b8571b4ec98866ce2b3653a9d066cf5f16f4sewardj      assign( frD, binop( Iop_RoundF64toF32, rm, mkexpr(frB) ));
9077d953ebb9b04cbad6891676df597bf0c542b1ec89cerion      break;
9078d953ebb9b04cbad6891676df597bf0c542b1ec89cerion
9079f0de28cf1a762b0d6f74c93d3532c89a230673bbcerion   case 0x00E: // fctiw (Float Conv to Int, PPC32 p404)
90805b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion      DIP("fctiw%s fr%u,fr%u\n", flag_rC ? ".":"", frD_addr, frB_addr);
90815b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion      assign( r_tmp32,
90826c299f3acab617581ea504e45fbb6cab24c2b29fsewardj              binop(Iop_F64toI32S, rm, mkexpr(frB)) );
9083d953ebb9b04cbad6891676df597bf0c542b1ec89cerion      assign( frD, unop( Iop_ReinterpI64asF64,
908407b07a966a2fdbcf621251a0c1a8ab84807fb120cerion                         unop( Iop_32Uto64, mkexpr(r_tmp32))));
9085b183b8571b4ec98866ce2b3653a9d066cf5f16f4sewardj      /* FPRF is undefined after fctiw.  Leave unchanged. */
9086b183b8571b4ec98866ce2b3653a9d066cf5f16f4sewardj      set_FPRF = False;
9087d953ebb9b04cbad6891676df597bf0c542b1ec89cerion      break;
9088d953ebb9b04cbad6891676df597bf0c542b1ec89cerion
9089f0de28cf1a762b0d6f74c93d3532c89a230673bbcerion   case 0x00F: // fctiwz (Float Conv to Int, Round to Zero, PPC32 p405)
90905b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion      DIP("fctiwz%s fr%u,fr%u\n", flag_rC ? ".":"", frD_addr, frB_addr);
9091b183b8571b4ec98866ce2b3653a9d066cf5f16f4sewardj      assign( r_tmp32,
90926c299f3acab617581ea504e45fbb6cab24c2b29fsewardj              binop(Iop_F64toI32S, mkU32(Irrm_ZERO), mkexpr(frB) ));
9093d953ebb9b04cbad6891676df597bf0c542b1ec89cerion      assign( frD, unop( Iop_ReinterpI64asF64,
909407b07a966a2fdbcf621251a0c1a8ab84807fb120cerion                         unop( Iop_32Uto64, mkexpr(r_tmp32))));
9095b183b8571b4ec98866ce2b3653a9d066cf5f16f4sewardj      /* FPRF is undefined after fctiwz.  Leave unchanged. */
9096b183b8571b4ec98866ce2b3653a9d066cf5f16f4sewardj      set_FPRF = False;
9097d953ebb9b04cbad6891676df597bf0c542b1ec89cerion      break;
9098f0de28cf1a762b0d6f74c93d3532c89a230673bbcerion
90994aa412af1d8166cc11f39a6e721df49431d23618sewardj   case 0x08F: case 0x08E: // fctiwu[z]
91004aa412af1d8166cc11f39a6e721df49431d23618sewardj      DIP("fctiwu%s%s fr%u,fr%u\n", opc2 == 0x08F ? "z" : "",
91014aa412af1d8166cc11f39a6e721df49431d23618sewardj               flag_rC ? ".":"", frD_addr, frB_addr);
91024aa412af1d8166cc11f39a6e721df49431d23618sewardj      assign( r_tmp32,
91034aa412af1d8166cc11f39a6e721df49431d23618sewardj              binop( Iop_F64toI32U,
91044aa412af1d8166cc11f39a6e721df49431d23618sewardj                     opc2 == 0x08F ? mkU32( Irrm_ZERO ) : rm,
91054aa412af1d8166cc11f39a6e721df49431d23618sewardj                     mkexpr( frB ) ) );
91064aa412af1d8166cc11f39a6e721df49431d23618sewardj      assign( frD, unop( Iop_ReinterpI64asF64,
91074aa412af1d8166cc11f39a6e721df49431d23618sewardj                         unop( Iop_32Uto64, mkexpr(r_tmp32))));
91084aa412af1d8166cc11f39a6e721df49431d23618sewardj      /* FPRF is undefined after fctiwz.  Leave unchanged. */
91094aa412af1d8166cc11f39a6e721df49431d23618sewardj      set_FPRF = False;
91104aa412af1d8166cc11f39a6e721df49431d23618sewardj      break;
91114aa412af1d8166cc11f39a6e721df49431d23618sewardj
91124aa412af1d8166cc11f39a6e721df49431d23618sewardj
91135b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion   case 0x32E: // fctid (Float Conv to Int DWord, PPC64 p437)
91145b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion      DIP("fctid%s fr%u,fr%u\n", flag_rC ? ".":"", frD_addr, frB_addr);
91155b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion      assign( r_tmp64,
91166c299f3acab617581ea504e45fbb6cab24c2b29fsewardj              binop(Iop_F64toI64S, rm, mkexpr(frB)) );
911707b07a966a2fdbcf621251a0c1a8ab84807fb120cerion      assign( frD, unop( Iop_ReinterpI64asF64, mkexpr(r_tmp64)) );
9118b183b8571b4ec98866ce2b3653a9d066cf5f16f4sewardj      /* FPRF is undefined after fctid.  Leave unchanged. */
9119b183b8571b4ec98866ce2b3653a9d066cf5f16f4sewardj      set_FPRF = False;
912007b07a966a2fdbcf621251a0c1a8ab84807fb120cerion      break;
9121f0de28cf1a762b0d6f74c93d3532c89a230673bbcerion
91225b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion   case 0x32F: // fctidz (Float Conv to Int DWord, Round to Zero, PPC64 p437)
91235b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion      DIP("fctidz%s fr%u,fr%u\n", flag_rC ? ".":"", frD_addr, frB_addr);
9124b183b8571b4ec98866ce2b3653a9d066cf5f16f4sewardj      assign( r_tmp64,
91256c299f3acab617581ea504e45fbb6cab24c2b29fsewardj              binop(Iop_F64toI64S, mkU32(Irrm_ZERO), mkexpr(frB)) );
912607b07a966a2fdbcf621251a0c1a8ab84807fb120cerion      assign( frD, unop( Iop_ReinterpI64asF64, mkexpr(r_tmp64)) );
9127b183b8571b4ec98866ce2b3653a9d066cf5f16f4sewardj      /* FPRF is undefined after fctidz.  Leave unchanged. */
9128b183b8571b4ec98866ce2b3653a9d066cf5f16f4sewardj      set_FPRF = False;
912907b07a966a2fdbcf621251a0c1a8ab84807fb120cerion      break;
9130f0de28cf1a762b0d6f74c93d3532c89a230673bbcerion
91314aa412af1d8166cc11f39a6e721df49431d23618sewardj   case 0x3AE: case 0x3AF: // fctidu[z] (Float Conv to Int DWord Unsigned [Round to Zero])
91324aa412af1d8166cc11f39a6e721df49431d23618sewardj   {
91334aa412af1d8166cc11f39a6e721df49431d23618sewardj      DIP("fctidu%s%s fr%u,fr%u\n", opc2 == 0x3AE ? "" : "z",
91344aa412af1d8166cc11f39a6e721df49431d23618sewardj               flag_rC ? ".":"", frD_addr, frB_addr);
91354aa412af1d8166cc11f39a6e721df49431d23618sewardj      assign( r_tmp64,
91364aa412af1d8166cc11f39a6e721df49431d23618sewardj              binop(Iop_F64toI64U, opc2 == 0x3AE ? rm : mkU32(Irrm_ZERO), mkexpr(frB)) );
91374aa412af1d8166cc11f39a6e721df49431d23618sewardj      assign( frD, unop( Iop_ReinterpI64asF64, mkexpr(r_tmp64)) );
91384aa412af1d8166cc11f39a6e721df49431d23618sewardj      /* FPRF is undefined after fctidz.  Leave unchanged. */
91394aa412af1d8166cc11f39a6e721df49431d23618sewardj      set_FPRF = False;
91404aa412af1d8166cc11f39a6e721df49431d23618sewardj      break;
91414aa412af1d8166cc11f39a6e721df49431d23618sewardj   }
91425b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion   case 0x34E: // fcfid (Float Conv from Int DWord, PPC64 p434)
91435b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion      DIP("fcfid%s fr%u,fr%u\n", flag_rC ? ".":"", frD_addr, frB_addr);
914407b07a966a2fdbcf621251a0c1a8ab84807fb120cerion      assign( r_tmp64, unop( Iop_ReinterpF64asI64, mkexpr(frB)) );
9145b183b8571b4ec98866ce2b3653a9d066cf5f16f4sewardj      assign( frD,
91466c299f3acab617581ea504e45fbb6cab24c2b29fsewardj              binop(Iop_I64StoF64, rm, mkexpr(r_tmp64)) );
914707b07a966a2fdbcf621251a0c1a8ab84807fb120cerion      break;
9148f0de28cf1a762b0d6f74c93d3532c89a230673bbcerion
914966d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj   case 0x3CE: // fcfidu (Float convert from unsigned DWord)
915066d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj      DIP("fcfidu%s fr%u,fr%u\n", flag_rC ? ".":"", frD_addr, frB_addr);
915166d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj      assign( r_tmp64, unop( Iop_ReinterpF64asI64, mkexpr(frB)) );
915266d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj      assign( frD, binop( Iop_I64UtoF64, rm, mkexpr( r_tmp64 ) ) );
915366d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj      break;
915466d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj
91557e84630580f89c1022dde97007bffbf6aef81814sewardj   case 0x188: case 0x1A8: case 0x1C8: case 0x1E8: // frin, friz, frip, frim
91567e84630580f89c1022dde97007bffbf6aef81814sewardj      switch(opc2) {
91577e84630580f89c1022dde97007bffbf6aef81814sewardj      case 0x188: // frin (Floating Round to Integer Nearest)
91587e84630580f89c1022dde97007bffbf6aef81814sewardj         DIP("frin%s fr%u,fr%u\n", flag_rC ? ".":"", frD_addr, frB_addr);
91597e84630580f89c1022dde97007bffbf6aef81814sewardj         assign( r_tmp64,
91607e84630580f89c1022dde97007bffbf6aef81814sewardj                 binop(Iop_F64toI64S, mkU32(Irrm_NEAREST), mkexpr(frB)) );
91617e84630580f89c1022dde97007bffbf6aef81814sewardj         break;
91627e84630580f89c1022dde97007bffbf6aef81814sewardj      case 0x1A8: // friz (Floating Round to Integer Toward Zero)
91637e84630580f89c1022dde97007bffbf6aef81814sewardj         DIP("friz%s fr%u,fr%u\n", flag_rC ? ".":"", frD_addr, frB_addr);
91647e84630580f89c1022dde97007bffbf6aef81814sewardj         assign( r_tmp64,
91657e84630580f89c1022dde97007bffbf6aef81814sewardj                 binop(Iop_F64toI64S, mkU32(Irrm_ZERO), mkexpr(frB)) );
91667e84630580f89c1022dde97007bffbf6aef81814sewardj         break;
91677e84630580f89c1022dde97007bffbf6aef81814sewardj      case 0x1C8: // frip (Floating Round to Integer Plus)
91687e84630580f89c1022dde97007bffbf6aef81814sewardj         DIP("frip%s fr%u,fr%u\n", flag_rC ? ".":"", frD_addr, frB_addr);
91697e84630580f89c1022dde97007bffbf6aef81814sewardj         assign( r_tmp64,
91707e84630580f89c1022dde97007bffbf6aef81814sewardj                 binop(Iop_F64toI64S, mkU32(Irrm_PosINF), mkexpr(frB)) );
91717e84630580f89c1022dde97007bffbf6aef81814sewardj         break;
91727e84630580f89c1022dde97007bffbf6aef81814sewardj      case 0x1E8: // frim (Floating Round to Integer Minus)
91737e84630580f89c1022dde97007bffbf6aef81814sewardj         DIP("frim%s fr%u,fr%u\n", flag_rC ? ".":"", frD_addr, frB_addr);
91747e84630580f89c1022dde97007bffbf6aef81814sewardj         assign( r_tmp64,
91757e84630580f89c1022dde97007bffbf6aef81814sewardj                 binop(Iop_F64toI64S, mkU32(Irrm_NegINF), mkexpr(frB)) );
91767e84630580f89c1022dde97007bffbf6aef81814sewardj         break;
91777e84630580f89c1022dde97007bffbf6aef81814sewardj      }
91787e84630580f89c1022dde97007bffbf6aef81814sewardj
91797e84630580f89c1022dde97007bffbf6aef81814sewardj      /* don't use the rounded integer if frB is outside -9e18..9e18 */
91807e84630580f89c1022dde97007bffbf6aef81814sewardj      /* F64 has only log10(2**52) significant digits anyway */
91817e84630580f89c1022dde97007bffbf6aef81814sewardj      /* need to preserve sign of zero */
91827e84630580f89c1022dde97007bffbf6aef81814sewardj      /*   frD = (fabs(frB) > 9e18) ? frB :
91837e84630580f89c1022dde97007bffbf6aef81814sewardj               (sign(frB)) ? -fabs((double)r_tmp64) : (double)r_tmp64  */
918499dd03e04a6914d90d5fee727d61d76905334becflorian      assign(frD, IRExpr_ITE(
9185009230b9758291b594e60d7c0243a73d53e81854sewardj                     binop(Iop_CmpNE8,
9186009230b9758291b594e60d7c0243a73d53e81854sewardj                           unop(Iop_32to8,
9187009230b9758291b594e60d7c0243a73d53e81854sewardj                                binop(Iop_CmpF64,
9188009230b9758291b594e60d7c0243a73d53e81854sewardj                                      IRExpr_Const(IRConst_F64(9e18)),
9189009230b9758291b594e60d7c0243a73d53e81854sewardj                                      unop(Iop_AbsF64, mkexpr(frB)))),
9190009230b9758291b594e60d7c0243a73d53e81854sewardj                           mkU8(0)),
919199dd03e04a6914d90d5fee727d61d76905334becflorian                     mkexpr(frB),
919299dd03e04a6914d90d5fee727d61d76905334becflorian                     IRExpr_ITE(
9193009230b9758291b594e60d7c0243a73d53e81854sewardj                        binop(Iop_CmpNE32,
9194009230b9758291b594e60d7c0243a73d53e81854sewardj                              binop(Iop_Shr32,
9195009230b9758291b594e60d7c0243a73d53e81854sewardj                                    unop(Iop_64HIto32,
9196009230b9758291b594e60d7c0243a73d53e81854sewardj                                         unop(Iop_ReinterpF64asI64,
9197009230b9758291b594e60d7c0243a73d53e81854sewardj                                              mkexpr(frB))),
9198009230b9758291b594e60d7c0243a73d53e81854sewardj                                    mkU8(31)),
9199009230b9758291b594e60d7c0243a73d53e81854sewardj                              mkU32(0)),
9200009230b9758291b594e60d7c0243a73d53e81854sewardj                        unop(Iop_NegF64,
9201009230b9758291b594e60d7c0243a73d53e81854sewardj                             unop( Iop_AbsF64,
9202009230b9758291b594e60d7c0243a73d53e81854sewardj                                   binop(Iop_I64StoF64, mkU32(0),
920399dd03e04a6914d90d5fee727d61d76905334becflorian                                         mkexpr(r_tmp64)) )),
920499dd03e04a6914d90d5fee727d61d76905334becflorian                        binop(Iop_I64StoF64, mkU32(0), mkexpr(r_tmp64) )
920599dd03e04a6914d90d5fee727d61d76905334becflorian                     )
9206009230b9758291b594e60d7c0243a73d53e81854sewardj      ));
92077e84630580f89c1022dde97007bffbf6aef81814sewardj      break;
92087e84630580f89c1022dde97007bffbf6aef81814sewardj
9209d953ebb9b04cbad6891676df597bf0c542b1ec89cerion   default:
92105b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion      vex_printf("dis_fp_round(ppc)(opc2)\n");
9211d953ebb9b04cbad6891676df597bf0c542b1ec89cerion      return False;
9212e14bb9f862843c6b804097c124961b5567ded4f1sewardj   }
921366d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardjputFR:
9214e14bb9f862843c6b804097c124961b5567ded4f1sewardj   putFReg( frD_addr, mkexpr(frD) );
9215b183b8571b4ec98866ce2b3653a9d066cf5f16f4sewardj
9216b183b8571b4ec98866ce2b3653a9d066cf5f16f4sewardj   if (set_FPRF) {
9217b183b8571b4ec98866ce2b3653a9d066cf5f16f4sewardj      // XXX XXX XXX FIXME
9218b183b8571b4ec98866ce2b3653a9d066cf5f16f4sewardj      // set FPRF from frD
9219b183b8571b4ec98866ce2b3653a9d066cf5f16f4sewardj   }
9220b183b8571b4ec98866ce2b3653a9d066cf5f16f4sewardj
9221b183b8571b4ec98866ce2b3653a9d066cf5f16f4sewardj   if (flag_rC && clear_CR1) {
9222b183b8571b4ec98866ce2b3653a9d066cf5f16f4sewardj      putCR321( 1, mkU8(0) );
9223b183b8571b4ec98866ce2b3653a9d066cf5f16f4sewardj      putCR0( 1, mkU8(0) );
9224b183b8571b4ec98866ce2b3653a9d066cf5f16f4sewardj   }
9225b183b8571b4ec98866ce2b3653a9d066cf5f16f4sewardj
9226e14bb9f862843c6b804097c124961b5567ded4f1sewardj   return True;
9227e14bb9f862843c6b804097c124961b5567ded4f1sewardj}
9228e14bb9f862843c6b804097c124961b5567ded4f1sewardj
92297e84630580f89c1022dde97007bffbf6aef81814sewardj/*
92307e84630580f89c1022dde97007bffbf6aef81814sewardj  Floating Point Pair Instructions
92317e84630580f89c1022dde97007bffbf6aef81814sewardj*/
92327e84630580f89c1022dde97007bffbf6aef81814sewardjstatic Bool dis_fp_pair ( UInt theInstr )
92337e84630580f89c1022dde97007bffbf6aef81814sewardj{
92347e84630580f89c1022dde97007bffbf6aef81814sewardj   /* X-Form/DS-Form */
92357e84630580f89c1022dde97007bffbf6aef81814sewardj   UChar  opc1         = ifieldOPC(theInstr);
92367e84630580f89c1022dde97007bffbf6aef81814sewardj   UChar  frT_hi_addr  = ifieldRegDS(theInstr);
92377e84630580f89c1022dde97007bffbf6aef81814sewardj   UChar  frT_lo_addr  = frT_hi_addr + 1;
92387e84630580f89c1022dde97007bffbf6aef81814sewardj   UChar  rA_addr      = ifieldRegA(theInstr);
92397e84630580f89c1022dde97007bffbf6aef81814sewardj   UChar  rB_addr      = ifieldRegB(theInstr);
92407e84630580f89c1022dde97007bffbf6aef81814sewardj   UInt  uimm16        = ifieldUIMM16(theInstr);
92417e84630580f89c1022dde97007bffbf6aef81814sewardj   Int    simm16       = extend_s_16to32(uimm16);
92427e84630580f89c1022dde97007bffbf6aef81814sewardj   UInt   opc2         = ifieldOPClo10(theInstr);
92437e84630580f89c1022dde97007bffbf6aef81814sewardj   IRType ty           = mode64 ? Ity_I64 : Ity_I32;
92447e84630580f89c1022dde97007bffbf6aef81814sewardj   IRTemp EA_hi        = newTemp(ty);
92457e84630580f89c1022dde97007bffbf6aef81814sewardj   IRTemp EA_lo        = newTemp(ty);
92467e84630580f89c1022dde97007bffbf6aef81814sewardj   IRTemp frT_hi       = newTemp(Ity_F64);
92477e84630580f89c1022dde97007bffbf6aef81814sewardj   IRTemp frT_lo       = newTemp(Ity_F64);
92487e84630580f89c1022dde97007bffbf6aef81814sewardj   UChar b0            = ifieldBIT0(theInstr);
92497e84630580f89c1022dde97007bffbf6aef81814sewardj   Bool is_load        = 0;
92507e84630580f89c1022dde97007bffbf6aef81814sewardj
92517e84630580f89c1022dde97007bffbf6aef81814sewardj   if ((frT_hi_addr %2) != 0) {
92527e84630580f89c1022dde97007bffbf6aef81814sewardj      vex_printf("dis_fp_pair(ppc) : odd frT register\n");
92537e84630580f89c1022dde97007bffbf6aef81814sewardj      return False;
92547e84630580f89c1022dde97007bffbf6aef81814sewardj   }
92557e84630580f89c1022dde97007bffbf6aef81814sewardj
92567e84630580f89c1022dde97007bffbf6aef81814sewardj   switch (opc1) {
92577e84630580f89c1022dde97007bffbf6aef81814sewardj   case 0x1F: // register offset
92587e84630580f89c1022dde97007bffbf6aef81814sewardj      switch(opc2) {
92597e84630580f89c1022dde97007bffbf6aef81814sewardj      case 0x317:     // lfdpx (FP Load Double Pair X-form, ISA 2.05  p125)
92607e84630580f89c1022dde97007bffbf6aef81814sewardj         DIP("ldpx fr%u,r%u,r%u\n", frT_hi_addr, rA_addr, rB_addr);
92617e84630580f89c1022dde97007bffbf6aef81814sewardj         is_load = 1;
92627e84630580f89c1022dde97007bffbf6aef81814sewardj         break;
92637e84630580f89c1022dde97007bffbf6aef81814sewardj      case 0x397:     // stfdpx (FP STORE Double Pair X-form, ISA 2.05  p125)
92647e84630580f89c1022dde97007bffbf6aef81814sewardj         DIP("stdpx fr%u,r%u,r%u\n", frT_hi_addr, rA_addr, rB_addr);
92657e84630580f89c1022dde97007bffbf6aef81814sewardj         break;
92667e84630580f89c1022dde97007bffbf6aef81814sewardj      default:
92677e84630580f89c1022dde97007bffbf6aef81814sewardj         vex_printf("dis_fp_pair(ppc) : X-form wrong opc2\n");
92687e84630580f89c1022dde97007bffbf6aef81814sewardj         return False;
92697e84630580f89c1022dde97007bffbf6aef81814sewardj      }
92707e84630580f89c1022dde97007bffbf6aef81814sewardj
92717e84630580f89c1022dde97007bffbf6aef81814sewardj      if (b0 != 0) {
92727e84630580f89c1022dde97007bffbf6aef81814sewardj         vex_printf("dis_fp_pair(ppc)(0x1F,b0)\n");
92737e84630580f89c1022dde97007bffbf6aef81814sewardj         return False;
92747e84630580f89c1022dde97007bffbf6aef81814sewardj      }
92757e84630580f89c1022dde97007bffbf6aef81814sewardj      assign( EA_hi, ea_rAor0_idxd( rA_addr, rB_addr ) );
92767e84630580f89c1022dde97007bffbf6aef81814sewardj      break;
92777e84630580f89c1022dde97007bffbf6aef81814sewardj   case 0x39: // lfdp (FP Load Double Pair DS-form, ISA 2.05  p125)
92787e84630580f89c1022dde97007bffbf6aef81814sewardj      DIP("lfdp fr%u,%d(r%u)\n", frT_hi_addr, simm16, rA_addr);
92797e84630580f89c1022dde97007bffbf6aef81814sewardj      assign( EA_hi, ea_rAor0_simm( rA_addr, simm16  ) );
92807e84630580f89c1022dde97007bffbf6aef81814sewardj      is_load = 1;
92817e84630580f89c1022dde97007bffbf6aef81814sewardj      break;
92827e84630580f89c1022dde97007bffbf6aef81814sewardj   case 0x3d: // stfdp (FP Store Double Pair DS-form, ISA 2.05  p125)
92837e84630580f89c1022dde97007bffbf6aef81814sewardj      DIP("stfdp fr%u,%d(r%u)\n", frT_hi_addr, simm16, rA_addr);
92847e84630580f89c1022dde97007bffbf6aef81814sewardj      assign( EA_hi, ea_rAor0_simm( rA_addr, simm16  ) );
92857e84630580f89c1022dde97007bffbf6aef81814sewardj      break;
92867e84630580f89c1022dde97007bffbf6aef81814sewardj   default:   // immediate offset
92877e84630580f89c1022dde97007bffbf6aef81814sewardj      vex_printf("dis_fp_pair(ppc)(instr)\n");
92887e84630580f89c1022dde97007bffbf6aef81814sewardj      return False;
92897e84630580f89c1022dde97007bffbf6aef81814sewardj   }
92907e84630580f89c1022dde97007bffbf6aef81814sewardj
92917e84630580f89c1022dde97007bffbf6aef81814sewardj   if (mode64)
92927e84630580f89c1022dde97007bffbf6aef81814sewardj      assign( EA_lo, binop(Iop_Add64, mkexpr(EA_hi), mkU64(8)) );
92937e84630580f89c1022dde97007bffbf6aef81814sewardj   else
92947e84630580f89c1022dde97007bffbf6aef81814sewardj      assign( EA_lo, binop(Iop_Add32, mkexpr(EA_hi), mkU32(8)) );
92957e84630580f89c1022dde97007bffbf6aef81814sewardj
92967e84630580f89c1022dde97007bffbf6aef81814sewardj   assign( frT_hi, getFReg(frT_hi_addr) );
92977e84630580f89c1022dde97007bffbf6aef81814sewardj   assign( frT_lo, getFReg(frT_lo_addr) );
92987e84630580f89c1022dde97007bffbf6aef81814sewardj
92997e84630580f89c1022dde97007bffbf6aef81814sewardj   if (is_load) {
93001f5fe1fc3a37ca729925e8eec25aa1025b4a6cdbcarll      putFReg( frT_hi_addr, load(Ity_F64, mkexpr(EA_hi)) );
93011f5fe1fc3a37ca729925e8eec25aa1025b4a6cdbcarll      putFReg( frT_lo_addr, load(Ity_F64, mkexpr(EA_lo)) );
93027e84630580f89c1022dde97007bffbf6aef81814sewardj   } else {
93031f5fe1fc3a37ca729925e8eec25aa1025b4a6cdbcarll      store( mkexpr(EA_hi), mkexpr(frT_hi) );
93041f5fe1fc3a37ca729925e8eec25aa1025b4a6cdbcarll      store( mkexpr(EA_lo), mkexpr(frT_lo) );
93057e84630580f89c1022dde97007bffbf6aef81814sewardj   }
93067e84630580f89c1022dde97007bffbf6aef81814sewardj
93077e84630580f89c1022dde97007bffbf6aef81814sewardj   return True;
93087e84630580f89c1022dde97007bffbf6aef81814sewardj}
9309e14bb9f862843c6b804097c124961b5567ded4f1sewardj
9310e14bb9f862843c6b804097c124961b5567ded4f1sewardj
9311e14bb9f862843c6b804097c124961b5567ded4f1sewardj/*
931278850ae9874a90ea625fcee1fd4c359375b7b538carll  Floating Point Merge Instructions
931378850ae9874a90ea625fcee1fd4c359375b7b538carll*/
931478850ae9874a90ea625fcee1fd4c359375b7b538carllstatic Bool dis_fp_merge ( UInt theInstr )
931578850ae9874a90ea625fcee1fd4c359375b7b538carll{
931678850ae9874a90ea625fcee1fd4c359375b7b538carll   /* X-Form */
931778850ae9874a90ea625fcee1fd4c359375b7b538carll   UInt  opc2     = ifieldOPClo10(theInstr);
931878850ae9874a90ea625fcee1fd4c359375b7b538carll   UChar frD_addr = ifieldRegDS(theInstr);
931978850ae9874a90ea625fcee1fd4c359375b7b538carll   UChar frA_addr = ifieldRegA(theInstr);
932078850ae9874a90ea625fcee1fd4c359375b7b538carll   UChar frB_addr = ifieldRegB(theInstr);
932178850ae9874a90ea625fcee1fd4c359375b7b538carll
932278850ae9874a90ea625fcee1fd4c359375b7b538carll   IRTemp frD = newTemp(Ity_F64);
932378850ae9874a90ea625fcee1fd4c359375b7b538carll   IRTemp frA = newTemp(Ity_F64);
932478850ae9874a90ea625fcee1fd4c359375b7b538carll   IRTemp frB = newTemp(Ity_F64);
932578850ae9874a90ea625fcee1fd4c359375b7b538carll
932678850ae9874a90ea625fcee1fd4c359375b7b538carll   assign( frA, getFReg(frA_addr));
932778850ae9874a90ea625fcee1fd4c359375b7b538carll   assign( frB, getFReg(frB_addr));
932878850ae9874a90ea625fcee1fd4c359375b7b538carll
932978850ae9874a90ea625fcee1fd4c359375b7b538carll   switch (opc2) {
933078850ae9874a90ea625fcee1fd4c359375b7b538carll   case 0x3c6: // fmrgew floating merge even word
933178850ae9874a90ea625fcee1fd4c359375b7b538carll      DIP("fmrgew fr%u,fr%u,fr%u\n", frD_addr, frA_addr, frB_addr);
933278850ae9874a90ea625fcee1fd4c359375b7b538carll
933378850ae9874a90ea625fcee1fd4c359375b7b538carll      assign( frD, unop( Iop_ReinterpI64asF64,
933478850ae9874a90ea625fcee1fd4c359375b7b538carll                         binop( Iop_32HLto64,
933578850ae9874a90ea625fcee1fd4c359375b7b538carll                                unop( Iop_64HIto32,
933678850ae9874a90ea625fcee1fd4c359375b7b538carll                                      unop( Iop_ReinterpF64asI64,
933778850ae9874a90ea625fcee1fd4c359375b7b538carll                                            mkexpr(frA) ) ),
933878850ae9874a90ea625fcee1fd4c359375b7b538carll                                unop( Iop_64HIto32,
933978850ae9874a90ea625fcee1fd4c359375b7b538carll                                      unop( Iop_ReinterpF64asI64,
934078850ae9874a90ea625fcee1fd4c359375b7b538carll                                            mkexpr(frB) ) ) ) ) );
934178850ae9874a90ea625fcee1fd4c359375b7b538carll   break;
934278850ae9874a90ea625fcee1fd4c359375b7b538carll
934378850ae9874a90ea625fcee1fd4c359375b7b538carll   case 0x346: // fmrgow floating merge odd word
934478850ae9874a90ea625fcee1fd4c359375b7b538carll      DIP("fmrgow fr%u,fr%u,fr%u\n", frD_addr, frA_addr, frB_addr);
934578850ae9874a90ea625fcee1fd4c359375b7b538carll
934678850ae9874a90ea625fcee1fd4c359375b7b538carll      assign( frD, unop( Iop_ReinterpI64asF64,
934778850ae9874a90ea625fcee1fd4c359375b7b538carll                         binop( Iop_32HLto64,
934878850ae9874a90ea625fcee1fd4c359375b7b538carll                                unop( Iop_64to32,
934978850ae9874a90ea625fcee1fd4c359375b7b538carll                                      unop( Iop_ReinterpF64asI64,
935078850ae9874a90ea625fcee1fd4c359375b7b538carll                                            mkexpr(frA) ) ),
935178850ae9874a90ea625fcee1fd4c359375b7b538carll                                unop( Iop_64to32,
935278850ae9874a90ea625fcee1fd4c359375b7b538carll                                      unop( Iop_ReinterpF64asI64,
935378850ae9874a90ea625fcee1fd4c359375b7b538carll                                            mkexpr(frB) ) ) ) ) );
935478850ae9874a90ea625fcee1fd4c359375b7b538carll   break;
935578850ae9874a90ea625fcee1fd4c359375b7b538carll
935678850ae9874a90ea625fcee1fd4c359375b7b538carll   default:
935778850ae9874a90ea625fcee1fd4c359375b7b538carll      vex_printf("dis_fp_merge(ppc)(opc2)\n");
935878850ae9874a90ea625fcee1fd4c359375b7b538carll      return False;
935978850ae9874a90ea625fcee1fd4c359375b7b538carll   }
936078850ae9874a90ea625fcee1fd4c359375b7b538carll
936178850ae9874a90ea625fcee1fd4c359375b7b538carll   putFReg( frD_addr, mkexpr(frD) );
936278850ae9874a90ea625fcee1fd4c359375b7b538carll   return True;
936378850ae9874a90ea625fcee1fd4c359375b7b538carll}
936478850ae9874a90ea625fcee1fd4c359375b7b538carll
936578850ae9874a90ea625fcee1fd4c359375b7b538carll/*
9366e14bb9f862843c6b804097c124961b5567ded4f1sewardj  Floating Point Move Instructions
9367e14bb9f862843c6b804097c124961b5567ded4f1sewardj*/
9368e14bb9f862843c6b804097c124961b5567ded4f1sewardjstatic Bool dis_fp_move ( UInt theInstr )
9369e14bb9f862843c6b804097c124961b5567ded4f1sewardj{
9370e14bb9f862843c6b804097c124961b5567ded4f1sewardj   /* X-Form */
937176de5cf615380b23b4b5bcced6541233cd4a93a0cerion   UChar opc1     = ifieldOPC(theInstr);
937276de5cf615380b23b4b5bcced6541233cd4a93a0cerion   UChar frD_addr = ifieldRegDS(theInstr);
93737e84630580f89c1022dde97007bffbf6aef81814sewardj   UChar frA_addr = ifieldRegA(theInstr);
937476de5cf615380b23b4b5bcced6541233cd4a93a0cerion   UChar frB_addr = ifieldRegB(theInstr);
937576de5cf615380b23b4b5bcced6541233cd4a93a0cerion   UInt  opc2     = ifieldOPClo10(theInstr);
937676de5cf615380b23b4b5bcced6541233cd4a93a0cerion   UChar flag_rC  = ifieldBIT0(theInstr);
9377e14bb9f862843c6b804097c124961b5567ded4f1sewardj
9378e14bb9f862843c6b804097c124961b5567ded4f1sewardj   IRTemp frD = newTemp(Ity_F64);
9379e14bb9f862843c6b804097c124961b5567ded4f1sewardj   IRTemp frB = newTemp(Ity_F64);
93807e84630580f89c1022dde97007bffbf6aef81814sewardj   IRTemp itmpB = newTemp(Ity_F64);
93817e84630580f89c1022dde97007bffbf6aef81814sewardj   IRTemp frA;
93827e84630580f89c1022dde97007bffbf6aef81814sewardj   IRTemp signA;
93837e84630580f89c1022dde97007bffbf6aef81814sewardj   IRTemp hiD;
9384e14bb9f862843c6b804097c124961b5567ded4f1sewardj
93857e84630580f89c1022dde97007bffbf6aef81814sewardj   if (opc1 != 0x3F || (frA_addr != 0 && opc2 != 0x008)) {
93865b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion      vex_printf("dis_fp_move(ppc)(instr)\n");
9387e14bb9f862843c6b804097c124961b5567ded4f1sewardj      return False;
9388e14bb9f862843c6b804097c124961b5567ded4f1sewardj   }
9389e14bb9f862843c6b804097c124961b5567ded4f1sewardj
9390e14bb9f862843c6b804097c124961b5567ded4f1sewardj   assign( frB, getFReg(frB_addr));
9391e14bb9f862843c6b804097c124961b5567ded4f1sewardj
9392e14bb9f862843c6b804097c124961b5567ded4f1sewardj   switch (opc2) {
93937e84630580f89c1022dde97007bffbf6aef81814sewardj   case 0x008: // fcpsgn (Floating Copy Sign, ISA_V2.05 p126)
93947e84630580f89c1022dde97007bffbf6aef81814sewardj      DIP("fcpsgn%s fr%u,fr%u,fr%u\n", flag_rC ? ".":"", frD_addr, frA_addr,
93957e84630580f89c1022dde97007bffbf6aef81814sewardj          frB_addr);
93967e84630580f89c1022dde97007bffbf6aef81814sewardj      signA = newTemp(Ity_I32);
93977e84630580f89c1022dde97007bffbf6aef81814sewardj      hiD = newTemp(Ity_I32);
93987e84630580f89c1022dde97007bffbf6aef81814sewardj      itmpB = newTemp(Ity_I64);
93997e84630580f89c1022dde97007bffbf6aef81814sewardj      frA = newTemp(Ity_F64);
94007e84630580f89c1022dde97007bffbf6aef81814sewardj      assign( frA, getFReg(frA_addr) );
94017e84630580f89c1022dde97007bffbf6aef81814sewardj
94027e84630580f89c1022dde97007bffbf6aef81814sewardj      /* get A's sign bit */
94037e84630580f89c1022dde97007bffbf6aef81814sewardj      assign(signA, binop(Iop_And32,
94047e84630580f89c1022dde97007bffbf6aef81814sewardj                          unop(Iop_64HIto32, unop(Iop_ReinterpF64asI64,
94057e84630580f89c1022dde97007bffbf6aef81814sewardj                                                  mkexpr(frA))),
94067e84630580f89c1022dde97007bffbf6aef81814sewardj                          mkU32(0x80000000)) );
94077e84630580f89c1022dde97007bffbf6aef81814sewardj
94087e84630580f89c1022dde97007bffbf6aef81814sewardj      assign( itmpB, unop(Iop_ReinterpF64asI64, mkexpr(frB)) );
94097e84630580f89c1022dde97007bffbf6aef81814sewardj
94107e84630580f89c1022dde97007bffbf6aef81814sewardj      /* mask off B's sign bit and or in A's sign bit */
94117e84630580f89c1022dde97007bffbf6aef81814sewardj      assign(hiD, binop(Iop_Or32,
94127e84630580f89c1022dde97007bffbf6aef81814sewardj                        binop(Iop_And32,
94137e84630580f89c1022dde97007bffbf6aef81814sewardj                              unop(Iop_64HIto32,
94147e84630580f89c1022dde97007bffbf6aef81814sewardj                                   mkexpr(itmpB)),  /* frB's high 32 bits */
94157e84630580f89c1022dde97007bffbf6aef81814sewardj                              mkU32(0x7fffffff)),
94167e84630580f89c1022dde97007bffbf6aef81814sewardj                        mkexpr(signA)) );
94177e84630580f89c1022dde97007bffbf6aef81814sewardj
94187e84630580f89c1022dde97007bffbf6aef81814sewardj      /* combine hiD/loB into frD */
94197e84630580f89c1022dde97007bffbf6aef81814sewardj      assign( frD, unop(Iop_ReinterpI64asF64,
94207e84630580f89c1022dde97007bffbf6aef81814sewardj                        binop(Iop_32HLto64,
94217e84630580f89c1022dde97007bffbf6aef81814sewardj                              mkexpr(hiD),
94227e84630580f89c1022dde97007bffbf6aef81814sewardj                              unop(Iop_64to32,
94237e84630580f89c1022dde97007bffbf6aef81814sewardj                                   mkexpr(itmpB)))) );   /* frB's low 32 bits */
94247e84630580f89c1022dde97007bffbf6aef81814sewardj      break;
94257e84630580f89c1022dde97007bffbf6aef81814sewardj
9426d953ebb9b04cbad6891676df597bf0c542b1ec89cerion   case 0x028: // fneg (Floating Negate, PPC32 p416)
94275b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion      DIP("fneg%s fr%u,fr%u\n", flag_rC ? ".":"", frD_addr, frB_addr);
9428d953ebb9b04cbad6891676df597bf0c542b1ec89cerion      assign( frD, unop( Iop_NegF64, mkexpr(frB) ));
9429d953ebb9b04cbad6891676df597bf0c542b1ec89cerion      break;
9430d953ebb9b04cbad6891676df597bf0c542b1ec89cerion
9431d953ebb9b04cbad6891676df597bf0c542b1ec89cerion   case 0x048: // fmr (Floating Move Register, PPC32 p410)
94325b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion      DIP("fmr%s fr%u,fr%u\n", flag_rC ? ".":"", frD_addr, frB_addr);
9433d953ebb9b04cbad6891676df597bf0c542b1ec89cerion      assign( frD, mkexpr(frB) );
9434d953ebb9b04cbad6891676df597bf0c542b1ec89cerion      break;
9435d953ebb9b04cbad6891676df597bf0c542b1ec89cerion
9436d953ebb9b04cbad6891676df597bf0c542b1ec89cerion   case 0x088: // fnabs (Floating Negative Absolute Value, PPC32 p415)
94375b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion      DIP("fnabs%s fr%u,fr%u\n", flag_rC ? ".":"", frD_addr, frB_addr);
9438d953ebb9b04cbad6891676df597bf0c542b1ec89cerion      assign( frD, unop( Iop_NegF64, unop( Iop_AbsF64, mkexpr(frB) )));
9439d953ebb9b04cbad6891676df597bf0c542b1ec89cerion      break;
9440d953ebb9b04cbad6891676df597bf0c542b1ec89cerion
9441d953ebb9b04cbad6891676df597bf0c542b1ec89cerion   case 0x108: // fabs (Floating Absolute Value, PPC32 p399)
94425b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion      DIP("fabs%s fr%u,fr%u\n", flag_rC ? ".":"", frD_addr, frB_addr);
9443d953ebb9b04cbad6891676df597bf0c542b1ec89cerion      assign( frD, unop( Iop_AbsF64, mkexpr(frB) ));
9444d953ebb9b04cbad6891676df597bf0c542b1ec89cerion      break;
9445d953ebb9b04cbad6891676df597bf0c542b1ec89cerion
9446d953ebb9b04cbad6891676df597bf0c542b1ec89cerion   default:
94475b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion      vex_printf("dis_fp_move(ppc)(opc2)\n");
9448d953ebb9b04cbad6891676df597bf0c542b1ec89cerion      return False;
9449e14bb9f862843c6b804097c124961b5567ded4f1sewardj   }
9450e14bb9f862843c6b804097c124961b5567ded4f1sewardj
9451e14bb9f862843c6b804097c124961b5567ded4f1sewardj   putFReg( frD_addr, mkexpr(frD) );
9452b183b8571b4ec98866ce2b3653a9d066cf5f16f4sewardj
9453b183b8571b4ec98866ce2b3653a9d066cf5f16f4sewardj   /* None of these change FPRF.  cr1 is set in the usual way though,
9454b183b8571b4ec98866ce2b3653a9d066cf5f16f4sewardj      if flag_rC is set. */
9455b183b8571b4ec98866ce2b3653a9d066cf5f16f4sewardj
9456b183b8571b4ec98866ce2b3653a9d066cf5f16f4sewardj   if (flag_rC) {
9457b183b8571b4ec98866ce2b3653a9d066cf5f16f4sewardj      putCR321( 1, mkU8(0) );
9458b183b8571b4ec98866ce2b3653a9d066cf5f16f4sewardj      putCR0( 1, mkU8(0) );
9459b183b8571b4ec98866ce2b3653a9d066cf5f16f4sewardj   }
9460b183b8571b4ec98866ce2b3653a9d066cf5f16f4sewardj
9461e14bb9f862843c6b804097c124961b5567ded4f1sewardj   return True;
9462e14bb9f862843c6b804097c124961b5567ded4f1sewardj}
9463e14bb9f862843c6b804097c124961b5567ded4f1sewardj
9464e14bb9f862843c6b804097c124961b5567ded4f1sewardj
9465e14bb9f862843c6b804097c124961b5567ded4f1sewardj
9466e14bb9f862843c6b804097c124961b5567ded4f1sewardj/*
9467e14bb9f862843c6b804097c124961b5567ded4f1sewardj  Floating Point Status/Control Register Instructions
9468e14bb9f862843c6b804097c124961b5567ded4f1sewardj*/
9469c6bbd470e9bd9898b84959227a406d3972d95f3bsewardjstatic Bool dis_fp_scr ( UInt theInstr, Bool GX_level )
9470e14bb9f862843c6b804097c124961b5567ded4f1sewardj{
947176de5cf615380b23b4b5bcced6541233cd4a93a0cerion   /* Many forms - see each switch case */
947276de5cf615380b23b4b5bcced6541233cd4a93a0cerion   UChar opc1    = ifieldOPC(theInstr);
947376de5cf615380b23b4b5bcced6541233cd4a93a0cerion   UInt  opc2    = ifieldOPClo10(theInstr);
947476de5cf615380b23b4b5bcced6541233cd4a93a0cerion   UChar flag_rC = ifieldBIT0(theInstr);
9475e14bb9f862843c6b804097c124961b5567ded4f1sewardj
9476e14bb9f862843c6b804097c124961b5567ded4f1sewardj   if (opc1 != 0x3F) {
94775b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion      vex_printf("dis_fp_scr(ppc)(instr)\n");
9478e14bb9f862843c6b804097c124961b5567ded4f1sewardj      return False;
9479e14bb9f862843c6b804097c124961b5567ded4f1sewardj   }
9480e14bb9f862843c6b804097c124961b5567ded4f1sewardj
9481e14bb9f862843c6b804097c124961b5567ded4f1sewardj   switch (opc2) {
94823ea49ee14d8c061bc0e7c3e90a22849de1c59d73cerion   case 0x026: { // mtfsb1 (Move to FPSCR Bit 1, PPC32 p479)
94833ea49ee14d8c061bc0e7c3e90a22849de1c59d73cerion      // Bit crbD of the FPSCR is set.
94843ea49ee14d8c061bc0e7c3e90a22849de1c59d73cerion      UChar crbD    = ifieldRegDS(theInstr);
94853ea49ee14d8c061bc0e7c3e90a22849de1c59d73cerion      UInt  b11to20 = IFIELD(theInstr, 11, 10);
94863ea49ee14d8c061bc0e7c3e90a22849de1c59d73cerion
94873ea49ee14d8c061bc0e7c3e90a22849de1c59d73cerion      if (b11to20 != 0) {
94883ea49ee14d8c061bc0e7c3e90a22849de1c59d73cerion         vex_printf("dis_fp_scr(ppc)(instr,mtfsb1)\n");
94893ea49ee14d8c061bc0e7c3e90a22849de1c59d73cerion         return False;
94903ea49ee14d8c061bc0e7c3e90a22849de1c59d73cerion      }
94913ea49ee14d8c061bc0e7c3e90a22849de1c59d73cerion      DIP("mtfsb1%s crb%d \n", flag_rC ? ".":"", crbD);
9492c6bbd470e9bd9898b84959227a406d3972d95f3bsewardj      putGST_masked( PPC_GST_FPSCR, mkU64( 1 <<( 31 - crbD ) ),
9493c6bbd470e9bd9898b84959227a406d3972d95f3bsewardj		     1ULL << ( 31 - crbD ) );
94943ea49ee14d8c061bc0e7c3e90a22849de1c59d73cerion      break;
94953ea49ee14d8c061bc0e7c3e90a22849de1c59d73cerion   }
94963ea49ee14d8c061bc0e7c3e90a22849de1c59d73cerion
9497496b88f208ea5cca7b03d41209fba7f4e1ae9c9bsewardj   case 0x040: { // mcrfs (Move to Condition Register from FPSCR, PPC32 p465)
9498496b88f208ea5cca7b03d41209fba7f4e1ae9c9bsewardj      UChar   crfD    = toUChar( IFIELD( theInstr, 23, 3 ) );
9499496b88f208ea5cca7b03d41209fba7f4e1ae9c9bsewardj      UChar   b21to22 = toUChar( IFIELD( theInstr, 21, 2 ) );
9500496b88f208ea5cca7b03d41209fba7f4e1ae9c9bsewardj      UChar   crfS    = toUChar( IFIELD( theInstr, 18, 3 ) );
9501496b88f208ea5cca7b03d41209fba7f4e1ae9c9bsewardj      UChar   b11to17 = toUChar( IFIELD( theInstr, 11, 7 ) );
9502496b88f208ea5cca7b03d41209fba7f4e1ae9c9bsewardj      IRTemp  tmp     = newTemp(Ity_I32);
9503496b88f208ea5cca7b03d41209fba7f4e1ae9c9bsewardj      IRExpr* fpscr_all;
9504496b88f208ea5cca7b03d41209fba7f4e1ae9c9bsewardj      if (b21to22 != 0 || b11to17 != 0 || flag_rC != 0) {
9505496b88f208ea5cca7b03d41209fba7f4e1ae9c9bsewardj         vex_printf("dis_fp_scr(ppc)(instr,mcrfs)\n");
9506496b88f208ea5cca7b03d41209fba7f4e1ae9c9bsewardj         return False;
9507496b88f208ea5cca7b03d41209fba7f4e1ae9c9bsewardj      }
9508496b88f208ea5cca7b03d41209fba7f4e1ae9c9bsewardj      DIP("mcrfs crf%d,crf%d\n", crfD, crfS);
9509496b88f208ea5cca7b03d41209fba7f4e1ae9c9bsewardj      vassert(crfD < 8);
9510496b88f208ea5cca7b03d41209fba7f4e1ae9c9bsewardj      vassert(crfS < 8);
9511496b88f208ea5cca7b03d41209fba7f4e1ae9c9bsewardj      fpscr_all = getGST_masked( PPC_GST_FPSCR, MASK_FPSCR_RN );
9512496b88f208ea5cca7b03d41209fba7f4e1ae9c9bsewardj      assign( tmp, binop(Iop_And32,
9513496b88f208ea5cca7b03d41209fba7f4e1ae9c9bsewardj                         binop(Iop_Shr32,fpscr_all,mkU8(4 * (7-crfS))),
9514496b88f208ea5cca7b03d41209fba7f4e1ae9c9bsewardj                        mkU32(0xF)) );
9515496b88f208ea5cca7b03d41209fba7f4e1ae9c9bsewardj      putGST_field( PPC_GST_CR, mkexpr(tmp), crfD );
9516496b88f208ea5cca7b03d41209fba7f4e1ae9c9bsewardj      break;
9517496b88f208ea5cca7b03d41209fba7f4e1ae9c9bsewardj   }
95180e2cc67b30d1bb4d0515a1e09d944143becb3881sewardj
95190e2cc67b30d1bb4d0515a1e09d944143becb3881sewardj   case 0x046: { // mtfsb0 (Move to FPSCR Bit 0, PPC32 p478)
95200e2cc67b30d1bb4d0515a1e09d944143becb3881sewardj      // Bit crbD of the FPSCR is cleared.
952176de5cf615380b23b4b5bcced6541233cd4a93a0cerion      UChar crbD    = ifieldRegDS(theInstr);
952276de5cf615380b23b4b5bcced6541233cd4a93a0cerion      UInt  b11to20 = IFIELD(theInstr, 11, 10);
95230e2cc67b30d1bb4d0515a1e09d944143becb3881sewardj
95240e2cc67b30d1bb4d0515a1e09d944143becb3881sewardj      if (b11to20 != 0) {
95255b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion         vex_printf("dis_fp_scr(ppc)(instr,mtfsb0)\n");
95260e2cc67b30d1bb4d0515a1e09d944143becb3881sewardj         return False;
95270e2cc67b30d1bb4d0515a1e09d944143becb3881sewardj      }
95285b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion      DIP("mtfsb0%s crb%d\n", flag_rC ? ".":"", crbD);
9529c6bbd470e9bd9898b84959227a406d3972d95f3bsewardj      putGST_masked( PPC_GST_FPSCR, mkU64( 0 ), 1ULL << ( 31 - crbD ) );
95300e2cc67b30d1bb4d0515a1e09d944143becb3881sewardj      break;
95310e2cc67b30d1bb4d0515a1e09d944143becb3881sewardj   }
95320e2cc67b30d1bb4d0515a1e09d944143becb3881sewardj
95330e2cc67b30d1bb4d0515a1e09d944143becb3881sewardj   case 0x086: { // mtfsfi (Move to FPSCR Field Immediate, PPC32 p481)
9534c6bbd470e9bd9898b84959227a406d3972d95f3bsewardj      UInt crfD     = IFIELD( theInstr, 23, 3 );
953576de5cf615380b23b4b5bcced6541233cd4a93a0cerion      UChar b16to22 = toUChar( IFIELD( theInstr, 16, 7 ) );
953676de5cf615380b23b4b5bcced6541233cd4a93a0cerion      UChar IMM     = toUChar( IFIELD( theInstr, 12, 4 ) );
953776de5cf615380b23b4b5bcced6541233cd4a93a0cerion      UChar b11     = toUChar( IFIELD( theInstr, 11, 1 ) );
9538c6bbd470e9bd9898b84959227a406d3972d95f3bsewardj      UChar Wbit;
95390e2cc67b30d1bb4d0515a1e09d944143becb3881sewardj
95400e2cc67b30d1bb4d0515a1e09d944143becb3881sewardj      if (b16to22 != 0 || b11 != 0) {
95415b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion         vex_printf("dis_fp_scr(ppc)(instr,mtfsfi)\n");
95420e2cc67b30d1bb4d0515a1e09d944143becb3881sewardj         return False;
95430e2cc67b30d1bb4d0515a1e09d944143becb3881sewardj      }
9544b173774421d015736c2316b5e6e998e7de545a5cflorian      DIP("mtfsfi%s crf%u,%d\n", flag_rC ? ".":"", crfD, IMM);
9545c6bbd470e9bd9898b84959227a406d3972d95f3bsewardj      if (GX_level) {
9546c6bbd470e9bd9898b84959227a406d3972d95f3bsewardj         /* This implies that Decimal Floating Point is supported, and the
9547c6bbd470e9bd9898b84959227a406d3972d95f3bsewardj          * FPSCR must be managed as a 64-bit register.
9548c6bbd470e9bd9898b84959227a406d3972d95f3bsewardj          */
9549c6bbd470e9bd9898b84959227a406d3972d95f3bsewardj         Wbit = toUChar( IFIELD(theInstr, 16, 1) );
9550c6bbd470e9bd9898b84959227a406d3972d95f3bsewardj      } else {
9551c6bbd470e9bd9898b84959227a406d3972d95f3bsewardj         Wbit = 0;
9552c6bbd470e9bd9898b84959227a406d3972d95f3bsewardj      }
9553c6bbd470e9bd9898b84959227a406d3972d95f3bsewardj      crfD = crfD + (8 * (1 - Wbit) );
9554c6bbd470e9bd9898b84959227a406d3972d95f3bsewardj      putGST_field( PPC_GST_FPSCR, mkU32( IMM ), crfD );
95550e2cc67b30d1bb4d0515a1e09d944143becb3881sewardj      break;
95560e2cc67b30d1bb4d0515a1e09d944143becb3881sewardj   }
9557e14bb9f862843c6b804097c124961b5567ded4f1sewardj
9558e14bb9f862843c6b804097c124961b5567ded4f1sewardj   case 0x247: { // mffs (Move from FPSCR, PPC32 p468)
9559496b88f208ea5cca7b03d41209fba7f4e1ae9c9bsewardj      UChar   frD_addr  = ifieldRegDS(theInstr);
9560496b88f208ea5cca7b03d41209fba7f4e1ae9c9bsewardj      UInt    b11to20   = IFIELD(theInstr, 11, 10);
9561c6bbd470e9bd9898b84959227a406d3972d95f3bsewardj      IRExpr* fpscr_lower = getGST_masked( PPC_GST_FPSCR, MASK_FPSCR_RN );
9562c6bbd470e9bd9898b84959227a406d3972d95f3bsewardj      IRExpr* fpscr_upper = getGST_masked_upper( PPC_GST_FPSCR,
9563c6bbd470e9bd9898b84959227a406d3972d95f3bsewardj                                                 MASK_FPSCR_DRN );
9564e14bb9f862843c6b804097c124961b5567ded4f1sewardj
9565e14bb9f862843c6b804097c124961b5567ded4f1sewardj      if (b11to20 != 0) {
95665b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion         vex_printf("dis_fp_scr(ppc)(instr,mffs)\n");
9567e14bb9f862843c6b804097c124961b5567ded4f1sewardj         return False;
9568e14bb9f862843c6b804097c124961b5567ded4f1sewardj      }
95695b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion      DIP("mffs%s fr%u\n", flag_rC ? ".":"", frD_addr);
95705b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion      putFReg( frD_addr,
95715b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion          unop( Iop_ReinterpI64asF64,
9572c6bbd470e9bd9898b84959227a406d3972d95f3bsewardj                binop( Iop_32HLto64, fpscr_upper, fpscr_lower ) ) );
9573e14bb9f862843c6b804097c124961b5567ded4f1sewardj      break;
9574e14bb9f862843c6b804097c124961b5567ded4f1sewardj   }
9575e14bb9f862843c6b804097c124961b5567ded4f1sewardj
9576e14bb9f862843c6b804097c124961b5567ded4f1sewardj   case 0x2C7: { // mtfsf (Move to FPSCR Fields, PPC32 p480)
957776de5cf615380b23b4b5bcced6541233cd4a93a0cerion      UChar b25      = toUChar( IFIELD(theInstr, 25, 1) );
957876de5cf615380b23b4b5bcced6541233cd4a93a0cerion      UChar FM       = toUChar( IFIELD(theInstr, 17, 8) );
957976de5cf615380b23b4b5bcced6541233cd4a93a0cerion      UChar frB_addr = ifieldRegB(theInstr);
958076de5cf615380b23b4b5bcced6541233cd4a93a0cerion      IRTemp frB   = newTemp(Ity_F64);
9581c6bbd470e9bd9898b84959227a406d3972d95f3bsewardj      IRTemp rB_64 = newTemp( Ity_I64 );
9582c6bbd470e9bd9898b84959227a406d3972d95f3bsewardj      Int i;
9583c6bbd470e9bd9898b84959227a406d3972d95f3bsewardj      ULong mask;
9584c6bbd470e9bd9898b84959227a406d3972d95f3bsewardj      UChar Wbit;
9585c6bbd470e9bd9898b84959227a406d3972d95f3bsewardj#define BFP_MASK_SEED 0x3000000000000000ULL
9586c6bbd470e9bd9898b84959227a406d3972d95f3bsewardj#define DFP_MASK_SEED 0x7000000000000000ULL
9587c6bbd470e9bd9898b84959227a406d3972d95f3bsewardj
9588c6bbd470e9bd9898b84959227a406d3972d95f3bsewardj      if (GX_level) {
9589c6bbd470e9bd9898b84959227a406d3972d95f3bsewardj         /* This implies that Decimal Floating Point is supported, and the
9590c6bbd470e9bd9898b84959227a406d3972d95f3bsewardj          * FPSCR must be managed as a 64-bit register.
9591c6bbd470e9bd9898b84959227a406d3972d95f3bsewardj          */
9592c6bbd470e9bd9898b84959227a406d3972d95f3bsewardj         Wbit = toUChar( IFIELD(theInstr, 16, 1) );
9593c6bbd470e9bd9898b84959227a406d3972d95f3bsewardj      } else {
9594c6bbd470e9bd9898b84959227a406d3972d95f3bsewardj         Wbit = 0;
9595c6bbd470e9bd9898b84959227a406d3972d95f3bsewardj      }
9596e14bb9f862843c6b804097c124961b5567ded4f1sewardj
95977e84630580f89c1022dde97007bffbf6aef81814sewardj      if (b25 == 1) {
95987e84630580f89c1022dde97007bffbf6aef81814sewardj         /* new 64 bit move variant for power 6.  If L field (bit 25) is
95997e84630580f89c1022dde97007bffbf6aef81814sewardj          * a one do a full 64 bit move.  Note, the FPSCR is not really
96007e84630580f89c1022dde97007bffbf6aef81814sewardj          * properly modeled.  This instruciton only changes the value of
96017e84630580f89c1022dde97007bffbf6aef81814sewardj          * the rounding mode.  The HW exception bits do not get set in
96027e84630580f89c1022dde97007bffbf6aef81814sewardj          * the simulator.  1/12/09
96037e84630580f89c1022dde97007bffbf6aef81814sewardj          */
96047e84630580f89c1022dde97007bffbf6aef81814sewardj         DIP("mtfsf%s %d,fr%u (L=1)\n", flag_rC ? ".":"", FM, frB_addr);
96057e84630580f89c1022dde97007bffbf6aef81814sewardj         mask = 0xFF;
96067e84630580f89c1022dde97007bffbf6aef81814sewardj
96077e84630580f89c1022dde97007bffbf6aef81814sewardj      } else {
96087e84630580f89c1022dde97007bffbf6aef81814sewardj         DIP("mtfsf%s %d,fr%u\n", flag_rC ? ".":"", FM, frB_addr);
96097e84630580f89c1022dde97007bffbf6aef81814sewardj         // Build 32bit mask from FM:
96107e84630580f89c1022dde97007bffbf6aef81814sewardj         mask = 0;
96117e84630580f89c1022dde97007bffbf6aef81814sewardj         for (i=0; i<8; i++) {
96127e84630580f89c1022dde97007bffbf6aef81814sewardj            if ((FM & (1<<(7-i))) == 1) {
9613c6bbd470e9bd9898b84959227a406d3972d95f3bsewardj               /* FPSCR field k is set to the contents of the corresponding
9614c6bbd470e9bd9898b84959227a406d3972d95f3bsewardj                * field of register FRB, where k = i+8x(1-W).  In the Power
9615c6bbd470e9bd9898b84959227a406d3972d95f3bsewardj                * ISA, register field numbering is from left to right, so field
9616c6bbd470e9bd9898b84959227a406d3972d95f3bsewardj                * 15 is the least significant field in a 64-bit register.  To
9617c6bbd470e9bd9898b84959227a406d3972d95f3bsewardj                * generate the mask, we set all the appropriate rounding mode
9618c6bbd470e9bd9898b84959227a406d3972d95f3bsewardj                * bits in the highest order nibble (field 0) and shift right
9619c6bbd470e9bd9898b84959227a406d3972d95f3bsewardj                * 'k x nibble length'.
9620c6bbd470e9bd9898b84959227a406d3972d95f3bsewardj                */
9621c6bbd470e9bd9898b84959227a406d3972d95f3bsewardj               if (Wbit)
9622c6bbd470e9bd9898b84959227a406d3972d95f3bsewardj                  mask |= DFP_MASK_SEED >> ( 4 * ( i + 8 * ( 1 - Wbit ) ) );
9623c6bbd470e9bd9898b84959227a406d3972d95f3bsewardj               else
9624c6bbd470e9bd9898b84959227a406d3972d95f3bsewardj                  mask |= BFP_MASK_SEED >> ( 4 * ( i + 8 * ( 1 - Wbit ) ) );
96257e84630580f89c1022dde97007bffbf6aef81814sewardj            }
96267e84630580f89c1022dde97007bffbf6aef81814sewardj         }
96277e84630580f89c1022dde97007bffbf6aef81814sewardj      }
9628e14bb9f862843c6b804097c124961b5567ded4f1sewardj      assign( frB, getFReg(frB_addr));
9629c6bbd470e9bd9898b84959227a406d3972d95f3bsewardj      assign( rB_64, unop( Iop_ReinterpF64asI64, mkexpr( frB ) ) );
9630c6bbd470e9bd9898b84959227a406d3972d95f3bsewardj      putGST_masked( PPC_GST_FPSCR, mkexpr( rB_64 ), mask );
9631e14bb9f862843c6b804097c124961b5567ded4f1sewardj      break;
9632e14bb9f862843c6b804097c124961b5567ded4f1sewardj   }
9633e14bb9f862843c6b804097c124961b5567ded4f1sewardj
9634e14bb9f862843c6b804097c124961b5567ded4f1sewardj   default:
96355b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion      vex_printf("dis_fp_scr(ppc)(opc2)\n");
9636e14bb9f862843c6b804097c124961b5567ded4f1sewardj      return False;
9637e14bb9f862843c6b804097c124961b5567ded4f1sewardj   }
9638e14bb9f862843c6b804097c124961b5567ded4f1sewardj   return True;
9639e14bb9f862843c6b804097c124961b5567ded4f1sewardj}
9640e14bb9f862843c6b804097c124961b5567ded4f1sewardj
9641c6bbd470e9bd9898b84959227a406d3972d95f3bsewardj/*------------------------------------------------------------*/
96425eff1c502e995d1f9668cc9def72d5db59f21b13sewardj/*--- Decimal Floating Point (DFP)  Helper functions       ---*/
96435eff1c502e995d1f9668cc9def72d5db59f21b13sewardj/*------------------------------------------------------------*/
96445eff1c502e995d1f9668cc9def72d5db59f21b13sewardj#define DFP_LONG  1
96455eff1c502e995d1f9668cc9def72d5db59f21b13sewardj#define DFP_EXTND 2
96464c96e61dd85c172b999d6afc88ce6640aeba9962sewardj#define DFP_LONG_BIAS   398
96475eff1c502e995d1f9668cc9def72d5db59f21b13sewardj#define DFP_LONG_ENCODED_FIELD_MASK  0x1F00
96484c96e61dd85c172b999d6afc88ce6640aeba9962sewardj#define DFP_EXTND_BIAS  6176
96495eff1c502e995d1f9668cc9def72d5db59f21b13sewardj#define DFP_EXTND_ENCODED_FIELD_MASK 0x1F000
96505eff1c502e995d1f9668cc9def72d5db59f21b13sewardj#define DFP_LONG_EXP_MSK   0XFF
96515eff1c502e995d1f9668cc9def72d5db59f21b13sewardj#define DFP_EXTND_EXP_MSK  0XFFF
96525eff1c502e995d1f9668cc9def72d5db59f21b13sewardj
96535eff1c502e995d1f9668cc9def72d5db59f21b13sewardj#define DFP_G_FIELD_LONG_MASK     0x7FFC0000  // upper 32-bits only
96545eff1c502e995d1f9668cc9def72d5db59f21b13sewardj#define DFP_LONG_GFIELD_RT_SHIFT  (63 - 13 - 32) // adj for upper 32-bits
96555eff1c502e995d1f9668cc9def72d5db59f21b13sewardj#define DFP_G_FIELD_EXTND_MASK    0x7FFFC000  // upper 32-bits only
96565eff1c502e995d1f9668cc9def72d5db59f21b13sewardj#define DFP_EXTND_GFIELD_RT_SHIFT (63 - 17 - 32) //adj for upper 32 bits
96575eff1c502e995d1f9668cc9def72d5db59f21b13sewardj#define DFP_T_FIELD_LONG_MASK     0x3FFFF  // mask for upper 32-bits
96585eff1c502e995d1f9668cc9def72d5db59f21b13sewardj#define DFP_T_FIELD_EXTND_MASK    0x03FFFF // mask for upper 32-bits
96595eff1c502e995d1f9668cc9def72d5db59f21b13sewardj#define DFP_LONG_EXP_MAX          369      // biased max
96605eff1c502e995d1f9668cc9def72d5db59f21b13sewardj#define DFP_LONG_EXP_MIN          0        // biased min
96615eff1c502e995d1f9668cc9def72d5db59f21b13sewardj#define DFP_EXTND_EXP_MAX         6111     // biased max
96625eff1c502e995d1f9668cc9def72d5db59f21b13sewardj#define DFP_EXTND_EXP_MIN         0        // biased min
96634c96e61dd85c172b999d6afc88ce6640aeba9962sewardj#define DFP_LONG_MAX_SIG_DIGITS   16
96644c96e61dd85c172b999d6afc88ce6640aeba9962sewardj#define DFP_EXTND_MAX_SIG_DIGITS  34
96654c96e61dd85c172b999d6afc88ce6640aeba9962sewardj#define MAX_DIGITS_IN_STRING      8
96664c96e61dd85c172b999d6afc88ce6640aeba9962sewardj
96675eff1c502e995d1f9668cc9def72d5db59f21b13sewardj
96685eff1c502e995d1f9668cc9def72d5db59f21b13sewardj#define  AND(x, y) binop( Iop_And32, x, y )
96695eff1c502e995d1f9668cc9def72d5db59f21b13sewardj#define AND4(w, x, y, z) AND( AND( w, x ), AND( y, z ) )
96704c96e61dd85c172b999d6afc88ce6640aeba9962sewardj#define   OR(x, y) binop( Iop_Or32,  x, y )
96715eff1c502e995d1f9668cc9def72d5db59f21b13sewardj#define  OR3(x, y, z)    OR( x, OR( y, z ) )
96725eff1c502e995d1f9668cc9def72d5db59f21b13sewardj#define  OR4(w, x, y, z) OR( OR( w, x ), OR( y, z ) )
96734c96e61dd85c172b999d6afc88ce6640aeba9962sewardj#define  NOT(x) unop( Iop_1Uto32, unop( Iop_Not1, unop( Iop_32to1,  mkexpr( x ) ) ) )
96744c96e61dd85c172b999d6afc88ce6640aeba9962sewardj
96755eff1c502e995d1f9668cc9def72d5db59f21b13sewardj#define  SHL(value, by) binop( Iop_Shl32, value, mkU8( by ) )
96764c96e61dd85c172b999d6afc88ce6640aeba9962sewardj#define  SHR(value, by) binop( Iop_Shr32, value, mkU8( by ) )
96774c96e61dd85c172b999d6afc88ce6640aeba9962sewardj
9678cb06d5e50876ee734e09a5fa0d5f300014e13852sewardj#define BITS5(_b4,_b3,_b2,_b1,_b0) \
9679cb06d5e50876ee734e09a5fa0d5f300014e13852sewardj   (((_b4) << 4) | ((_b3) << 3) | ((_b2) << 2) | \
9680cb06d5e50876ee734e09a5fa0d5f300014e13852sewardj    ((_b1) << 1) | ((_b0) << 0))
96815eff1c502e995d1f9668cc9def72d5db59f21b13sewardj
96824c96e61dd85c172b999d6afc88ce6640aeba9962sewardjstatic IRExpr * Gfield_encoding( IRExpr * lmexp, IRExpr * lmd32 )
96835eff1c502e995d1f9668cc9def72d5db59f21b13sewardj{
96844c96e61dd85c172b999d6afc88ce6640aeba9962sewardj   IRTemp lmd_07_mask   = newTemp( Ity_I32 );
96854c96e61dd85c172b999d6afc88ce6640aeba9962sewardj   IRTemp lmd_8_mask    = newTemp( Ity_I32 );
96864c96e61dd85c172b999d6afc88ce6640aeba9962sewardj   IRTemp lmd_9_mask    = newTemp( Ity_I32 );
96874c96e61dd85c172b999d6afc88ce6640aeba9962sewardj   IRTemp lmexp_00_mask = newTemp( Ity_I32 );
96884c96e61dd85c172b999d6afc88ce6640aeba9962sewardj   IRTemp lmexp_01_mask = newTemp( Ity_I32 );
96894c96e61dd85c172b999d6afc88ce6640aeba9962sewardj   IRTemp lmexp_10_mask = newTemp( Ity_I32 );
96904c96e61dd85c172b999d6afc88ce6640aeba9962sewardj   IRTemp lmd_07_val    = newTemp( Ity_I32 );
96914c96e61dd85c172b999d6afc88ce6640aeba9962sewardj   IRTemp lmd_8_val     = newTemp( Ity_I32 );
96924c96e61dd85c172b999d6afc88ce6640aeba9962sewardj   IRTemp lmd_9_val     = newTemp( Ity_I32 );
96934c96e61dd85c172b999d6afc88ce6640aeba9962sewardj
96944c96e61dd85c172b999d6afc88ce6640aeba9962sewardj   /* The encodig is as follows:
96954c96e61dd85c172b999d6afc88ce6640aeba9962sewardj    * lmd - left most digit
96964c96e61dd85c172b999d6afc88ce6640aeba9962sewardj    * lme - left most 2-bits of the exponent
96974c96e61dd85c172b999d6afc88ce6640aeba9962sewardj    *
96984c96e61dd85c172b999d6afc88ce6640aeba9962sewardj    *    lmd
96994c96e61dd85c172b999d6afc88ce6640aeba9962sewardj    *   0 - 7    (lmexp << 3) | lmd
97004c96e61dd85c172b999d6afc88ce6640aeba9962sewardj    *     8      0b11000 (24 decimal) if lme=0b00;
97014c96e61dd85c172b999d6afc88ce6640aeba9962sewardj    *            0b11010 (26 decimal) if lme=0b01;
97024c96e61dd85c172b999d6afc88ce6640aeba9962sewardj    *            0b11100 (28 decimal) if lme=0b10;
97034c96e61dd85c172b999d6afc88ce6640aeba9962sewardj    *     9      0b11001 (25 decimal) if lme=0b00;
97044c96e61dd85c172b999d6afc88ce6640aeba9962sewardj    *            0b11011 (27 decimal) if lme=0b01;
97054c96e61dd85c172b999d6afc88ce6640aeba9962sewardj    *            0b11101 (29 decimal) if lme=0b10;
97064c96e61dd85c172b999d6afc88ce6640aeba9962sewardj    */
97074c96e61dd85c172b999d6afc88ce6640aeba9962sewardj
97084c96e61dd85c172b999d6afc88ce6640aeba9962sewardj   /* Generate the masks for each condition */
97094c96e61dd85c172b999d6afc88ce6640aeba9962sewardj   assign( lmd_07_mask,
97104c96e61dd85c172b999d6afc88ce6640aeba9962sewardj           unop( Iop_1Sto32, binop( Iop_CmpLE32U, lmd32, mkU32( 7 ) ) ) );
97114c96e61dd85c172b999d6afc88ce6640aeba9962sewardj   assign( lmd_8_mask,
97124c96e61dd85c172b999d6afc88ce6640aeba9962sewardj           unop( Iop_1Sto32, binop( Iop_CmpEQ32, lmd32, mkU32( 8 ) ) ) );
97134c96e61dd85c172b999d6afc88ce6640aeba9962sewardj   assign( lmd_9_mask,
97144c96e61dd85c172b999d6afc88ce6640aeba9962sewardj           unop( Iop_1Sto32, binop( Iop_CmpEQ32, lmd32, mkU32( 9 ) ) ) );
97154c96e61dd85c172b999d6afc88ce6640aeba9962sewardj   assign( lmexp_00_mask,
97164c96e61dd85c172b999d6afc88ce6640aeba9962sewardj           unop( Iop_1Sto32, binop( Iop_CmpEQ32, lmexp, mkU32( 0 ) ) ) );
97174c96e61dd85c172b999d6afc88ce6640aeba9962sewardj   assign( lmexp_01_mask,
97184c96e61dd85c172b999d6afc88ce6640aeba9962sewardj           unop( Iop_1Sto32, binop( Iop_CmpEQ32, lmexp, mkU32( 1 ) ) ) );
97194c96e61dd85c172b999d6afc88ce6640aeba9962sewardj   assign( lmexp_10_mask,
97204c96e61dd85c172b999d6afc88ce6640aeba9962sewardj           unop( Iop_1Sto32, binop( Iop_CmpEQ32, lmexp, mkU32( 2 ) ) ) );
97215eff1c502e995d1f9668cc9def72d5db59f21b13sewardj
97224c96e61dd85c172b999d6afc88ce6640aeba9962sewardj   /* Generate the values for each LMD condition, assuming the condition
97234c96e61dd85c172b999d6afc88ce6640aeba9962sewardj    * is TRUE.
97244c96e61dd85c172b999d6afc88ce6640aeba9962sewardj    */
97254c96e61dd85c172b999d6afc88ce6640aeba9962sewardj   assign( lmd_07_val,
97264c96e61dd85c172b999d6afc88ce6640aeba9962sewardj           binop( Iop_Or32, binop( Iop_Shl32, lmexp, mkU8( 3 ) ), lmd32 ) );
97274c96e61dd85c172b999d6afc88ce6640aeba9962sewardj   assign( lmd_8_val,
97284c96e61dd85c172b999d6afc88ce6640aeba9962sewardj           binop( Iop_Or32,
97294c96e61dd85c172b999d6afc88ce6640aeba9962sewardj                  binop( Iop_Or32,
97304c96e61dd85c172b999d6afc88ce6640aeba9962sewardj                         binop( Iop_And32,
97314c96e61dd85c172b999d6afc88ce6640aeba9962sewardj                                mkexpr( lmexp_00_mask ),
97324c96e61dd85c172b999d6afc88ce6640aeba9962sewardj                                mkU32( 24 ) ),
97334c96e61dd85c172b999d6afc88ce6640aeba9962sewardj                         binop( Iop_And32,
97344c96e61dd85c172b999d6afc88ce6640aeba9962sewardj                                mkexpr( lmexp_01_mask ),
97354c96e61dd85c172b999d6afc88ce6640aeba9962sewardj                                mkU32( 26 ) ) ),
97364c96e61dd85c172b999d6afc88ce6640aeba9962sewardj                  binop( Iop_And32, mkexpr( lmexp_10_mask ), mkU32( 28 ) ) ) );
97374c96e61dd85c172b999d6afc88ce6640aeba9962sewardj   assign( lmd_9_val,
97384c96e61dd85c172b999d6afc88ce6640aeba9962sewardj           binop( Iop_Or32,
97394c96e61dd85c172b999d6afc88ce6640aeba9962sewardj                  binop( Iop_Or32,
97404c96e61dd85c172b999d6afc88ce6640aeba9962sewardj                         binop( Iop_And32,
97414c96e61dd85c172b999d6afc88ce6640aeba9962sewardj                                mkexpr( lmexp_00_mask ),
97424c96e61dd85c172b999d6afc88ce6640aeba9962sewardj                                mkU32( 25 ) ),
97434c96e61dd85c172b999d6afc88ce6640aeba9962sewardj                         binop( Iop_And32,
97444c96e61dd85c172b999d6afc88ce6640aeba9962sewardj                                mkexpr( lmexp_01_mask ),
97454c96e61dd85c172b999d6afc88ce6640aeba9962sewardj                                mkU32( 27 ) ) ),
97464c96e61dd85c172b999d6afc88ce6640aeba9962sewardj                  binop( Iop_And32, mkexpr( lmexp_10_mask ), mkU32( 29 ) ) ) );
97474c96e61dd85c172b999d6afc88ce6640aeba9962sewardj
97484c96e61dd85c172b999d6afc88ce6640aeba9962sewardj   /* generate the result from the possible LMD values */
97494c96e61dd85c172b999d6afc88ce6640aeba9962sewardj   return binop( Iop_Or32,
97504c96e61dd85c172b999d6afc88ce6640aeba9962sewardj                 binop( Iop_Or32,
97514c96e61dd85c172b999d6afc88ce6640aeba9962sewardj                        binop( Iop_And32,
97524c96e61dd85c172b999d6afc88ce6640aeba9962sewardj                               mkexpr( lmd_07_mask ),
97534c96e61dd85c172b999d6afc88ce6640aeba9962sewardj                               mkexpr( lmd_07_val ) ),
97544c96e61dd85c172b999d6afc88ce6640aeba9962sewardj                        binop( Iop_And32,
97554c96e61dd85c172b999d6afc88ce6640aeba9962sewardj                               mkexpr( lmd_8_mask ),
97564c96e61dd85c172b999d6afc88ce6640aeba9962sewardj                               mkexpr( lmd_8_val ) ) ),
97574c96e61dd85c172b999d6afc88ce6640aeba9962sewardj                 binop( Iop_And32, mkexpr( lmd_9_mask ), mkexpr( lmd_9_val ) ) );
97584c96e61dd85c172b999d6afc88ce6640aeba9962sewardj}
97594c96e61dd85c172b999d6afc88ce6640aeba9962sewardj
97604c96e61dd85c172b999d6afc88ce6640aeba9962sewardjstatic void Get_lmd( IRTemp * lmd, IRExpr * gfield_0_4 )
97614c96e61dd85c172b999d6afc88ce6640aeba9962sewardj{
97625eff1c502e995d1f9668cc9def72d5db59f21b13sewardj   /* Extract the exponent and the left most digit of the mantissa
97635eff1c502e995d1f9668cc9def72d5db59f21b13sewardj    * from the G field bits [0:4].
97645eff1c502e995d1f9668cc9def72d5db59f21b13sewardj    */
97655eff1c502e995d1f9668cc9def72d5db59f21b13sewardj   IRTemp lmd_07_mask   = newTemp( Ity_I32 );
97665eff1c502e995d1f9668cc9def72d5db59f21b13sewardj   IRTemp lmd_8_00_mask = newTemp( Ity_I32 );
97675eff1c502e995d1f9668cc9def72d5db59f21b13sewardj   IRTemp lmd_8_01_mask = newTemp( Ity_I32 );
97685eff1c502e995d1f9668cc9def72d5db59f21b13sewardj   IRTemp lmd_8_10_mask = newTemp( Ity_I32 );
97695eff1c502e995d1f9668cc9def72d5db59f21b13sewardj   IRTemp lmd_9_00_mask = newTemp( Ity_I32 );
97705eff1c502e995d1f9668cc9def72d5db59f21b13sewardj   IRTemp lmd_9_01_mask = newTemp( Ity_I32 );
97715eff1c502e995d1f9668cc9def72d5db59f21b13sewardj   IRTemp lmd_9_10_mask = newTemp( Ity_I32 );
97725eff1c502e995d1f9668cc9def72d5db59f21b13sewardj
97735eff1c502e995d1f9668cc9def72d5db59f21b13sewardj   IRTemp lmd_07_val = newTemp( Ity_I32 );
97745eff1c502e995d1f9668cc9def72d5db59f21b13sewardj   IRTemp lmd_8_val  = newTemp( Ity_I32 );
97755eff1c502e995d1f9668cc9def72d5db59f21b13sewardj   IRTemp lmd_9_val  = newTemp( Ity_I32 );
97765eff1c502e995d1f9668cc9def72d5db59f21b13sewardj
97775eff1c502e995d1f9668cc9def72d5db59f21b13sewardj   /* The left most digit (LMD) encoding is as follows:
97785eff1c502e995d1f9668cc9def72d5db59f21b13sewardj    *    lmd
97795eff1c502e995d1f9668cc9def72d5db59f21b13sewardj    *   0 - 7    (lmexp << 3) | lmd
97805eff1c502e995d1f9668cc9def72d5db59f21b13sewardj    *     8      0b11000 (24 decimal) if lme=0b00;
97815eff1c502e995d1f9668cc9def72d5db59f21b13sewardj    *            0b11010 (26 decimal) if lme=0b01;
97825eff1c502e995d1f9668cc9def72d5db59f21b13sewardj    *            0b11100 (28 decimal) if lme=0b10
97835eff1c502e995d1f9668cc9def72d5db59f21b13sewardj    *     9      0b11001 (25 decimal) if lme=0b00;
97845eff1c502e995d1f9668cc9def72d5db59f21b13sewardj    *            0b11011 (27 decimal) if lme=0b01;
97855eff1c502e995d1f9668cc9def72d5db59f21b13sewardj    *            0b11101 (29 decimal) if lme=0b10;
97865eff1c502e995d1f9668cc9def72d5db59f21b13sewardj    */
97875eff1c502e995d1f9668cc9def72d5db59f21b13sewardj
97885eff1c502e995d1f9668cc9def72d5db59f21b13sewardj   /* Generate the masks for each condition of LMD and exponent bits */
9789cb06d5e50876ee734e09a5fa0d5f300014e13852sewardj   assign( lmd_07_mask,
9790cb06d5e50876ee734e09a5fa0d5f300014e13852sewardj           unop( Iop_1Sto32, binop( Iop_CmpLE32U,
9791cb06d5e50876ee734e09a5fa0d5f300014e13852sewardj                                    gfield_0_4,
9792cb06d5e50876ee734e09a5fa0d5f300014e13852sewardj                                    mkU32( BITS5(1,0,1,1,1) ) ) ) );
9793cb06d5e50876ee734e09a5fa0d5f300014e13852sewardj   assign( lmd_8_00_mask,
9794cb06d5e50876ee734e09a5fa0d5f300014e13852sewardj           unop( Iop_1Sto32, binop( Iop_CmpEQ32,
9795cb06d5e50876ee734e09a5fa0d5f300014e13852sewardj                                    gfield_0_4,
9796cb06d5e50876ee734e09a5fa0d5f300014e13852sewardj                                    mkU32( BITS5(1,1,0,0,0) ) ) ) );
9797cb06d5e50876ee734e09a5fa0d5f300014e13852sewardj   assign( lmd_8_01_mask,
9798cb06d5e50876ee734e09a5fa0d5f300014e13852sewardj           unop( Iop_1Sto32, binop( Iop_CmpEQ32,
9799cb06d5e50876ee734e09a5fa0d5f300014e13852sewardj                                    gfield_0_4,
9800cb06d5e50876ee734e09a5fa0d5f300014e13852sewardj                                    mkU32( BITS5(1,1,0,1,0) ) ) ) );
9801cb06d5e50876ee734e09a5fa0d5f300014e13852sewardj   assign( lmd_8_10_mask,
9802cb06d5e50876ee734e09a5fa0d5f300014e13852sewardj           unop( Iop_1Sto32, binop( Iop_CmpEQ32,
9803cb06d5e50876ee734e09a5fa0d5f300014e13852sewardj                                    gfield_0_4,
9804cb06d5e50876ee734e09a5fa0d5f300014e13852sewardj                                    mkU32( BITS5(1,1,1,0,0) ) ) ) );
9805cb06d5e50876ee734e09a5fa0d5f300014e13852sewardj   assign( lmd_9_00_mask,
9806cb06d5e50876ee734e09a5fa0d5f300014e13852sewardj           unop( Iop_1Sto32, binop( Iop_CmpEQ32,
9807cb06d5e50876ee734e09a5fa0d5f300014e13852sewardj                                    gfield_0_4,
9808cb06d5e50876ee734e09a5fa0d5f300014e13852sewardj                                    mkU32( BITS5(1,1,0,0,1) ) ) ) );
9809cb06d5e50876ee734e09a5fa0d5f300014e13852sewardj   assign( lmd_9_01_mask,
9810cb06d5e50876ee734e09a5fa0d5f300014e13852sewardj           unop( Iop_1Sto32, binop( Iop_CmpEQ32,
9811cb06d5e50876ee734e09a5fa0d5f300014e13852sewardj                                    gfield_0_4,
9812cb06d5e50876ee734e09a5fa0d5f300014e13852sewardj                                    mkU32( BITS5(1,1,0,1,1) ) ) ) );
9813cb06d5e50876ee734e09a5fa0d5f300014e13852sewardj   assign( lmd_9_10_mask,
9814cb06d5e50876ee734e09a5fa0d5f300014e13852sewardj           unop( Iop_1Sto32, binop( Iop_CmpEQ32,
9815cb06d5e50876ee734e09a5fa0d5f300014e13852sewardj                                    gfield_0_4,
9816cb06d5e50876ee734e09a5fa0d5f300014e13852sewardj                                    mkU32( BITS5(1,1,1,0,1) ) ) ) );
98175eff1c502e995d1f9668cc9def72d5db59f21b13sewardj
98185eff1c502e995d1f9668cc9def72d5db59f21b13sewardj   /* Generate the values for each LMD condition, assuming the condition
98195eff1c502e995d1f9668cc9def72d5db59f21b13sewardj    * is TRUE.
98205eff1c502e995d1f9668cc9def72d5db59f21b13sewardj    */
98215eff1c502e995d1f9668cc9def72d5db59f21b13sewardj   assign( lmd_07_val, binop( Iop_And32, gfield_0_4, mkU32( 0x7 ) ) );
98225eff1c502e995d1f9668cc9def72d5db59f21b13sewardj   assign( lmd_8_val, mkU32( 0x8 ) );
98235eff1c502e995d1f9668cc9def72d5db59f21b13sewardj   assign( lmd_9_val, mkU32( 0x9 ) );
98245eff1c502e995d1f9668cc9def72d5db59f21b13sewardj
98255eff1c502e995d1f9668cc9def72d5db59f21b13sewardj   assign( *lmd,
98265eff1c502e995d1f9668cc9def72d5db59f21b13sewardj           OR( OR3 ( AND( mkexpr( lmd_07_mask ), mkexpr( lmd_07_val ) ),
98275eff1c502e995d1f9668cc9def72d5db59f21b13sewardj                     AND( mkexpr( lmd_8_00_mask ), mkexpr( lmd_8_val ) ),
98285eff1c502e995d1f9668cc9def72d5db59f21b13sewardj                     AND( mkexpr( lmd_8_01_mask ), mkexpr( lmd_8_val ) )),
98295eff1c502e995d1f9668cc9def72d5db59f21b13sewardj                     OR4( AND( mkexpr( lmd_8_10_mask ), mkexpr( lmd_8_val ) ),
98305eff1c502e995d1f9668cc9def72d5db59f21b13sewardj                          AND( mkexpr( lmd_9_00_mask ), mkexpr( lmd_9_val ) ),
98315eff1c502e995d1f9668cc9def72d5db59f21b13sewardj                          AND( mkexpr( lmd_9_01_mask ), mkexpr( lmd_9_val ) ),
98325eff1c502e995d1f9668cc9def72d5db59f21b13sewardj                          AND( mkexpr( lmd_9_10_mask ), mkexpr( lmd_9_val ) )
98335eff1c502e995d1f9668cc9def72d5db59f21b13sewardj                     ) ) );
98345eff1c502e995d1f9668cc9def72d5db59f21b13sewardj}
98355eff1c502e995d1f9668cc9def72d5db59f21b13sewardj
98364c96e61dd85c172b999d6afc88ce6640aeba9962sewardj#define DIGIT1_SHR 4    // shift digit 1 to bottom 4 bits
98374c96e61dd85c172b999d6afc88ce6640aeba9962sewardj#define DIGIT2_SHR 8    // shift digit 2 to bottom 4 bits
98384c96e61dd85c172b999d6afc88ce6640aeba9962sewardj#define DIGIT3_SHR 12
98394c96e61dd85c172b999d6afc88ce6640aeba9962sewardj#define DIGIT4_SHR 16
98404c96e61dd85c172b999d6afc88ce6640aeba9962sewardj#define DIGIT5_SHR 20
98414c96e61dd85c172b999d6afc88ce6640aeba9962sewardj#define DIGIT6_SHR 24
98424c96e61dd85c172b999d6afc88ce6640aeba9962sewardj#define DIGIT7_SHR 28
98434c96e61dd85c172b999d6afc88ce6640aeba9962sewardj
98444c96e61dd85c172b999d6afc88ce6640aeba9962sewardjstatic IRExpr * bcd_digit_inval( IRExpr * bcd_u, IRExpr * bcd_l )
98454c96e61dd85c172b999d6afc88ce6640aeba9962sewardj{
98464c96e61dd85c172b999d6afc88ce6640aeba9962sewardj   /* 60-bit BCD string stored in two 32-bit values.  Check that each,
98474c96e61dd85c172b999d6afc88ce6640aeba9962sewardj    * digit is a valid BCD number, i.e. less then 9.
98484c96e61dd85c172b999d6afc88ce6640aeba9962sewardj    */
98494c96e61dd85c172b999d6afc88ce6640aeba9962sewardj   IRTemp valid = newTemp( Ity_I32 );
98504c96e61dd85c172b999d6afc88ce6640aeba9962sewardj
98514c96e61dd85c172b999d6afc88ce6640aeba9962sewardj   assign( valid,
98524c96e61dd85c172b999d6afc88ce6640aeba9962sewardj           AND4( AND4 ( unop( Iop_1Sto32,
98534c96e61dd85c172b999d6afc88ce6640aeba9962sewardj                              binop( Iop_CmpLE32U,
98544c96e61dd85c172b999d6afc88ce6640aeba9962sewardj                                     binop( Iop_And32,
98554c96e61dd85c172b999d6afc88ce6640aeba9962sewardj                                            bcd_l,
98564c96e61dd85c172b999d6afc88ce6640aeba9962sewardj                                            mkU32 ( 0xF ) ),
98574c96e61dd85c172b999d6afc88ce6640aeba9962sewardj                                      mkU32( 0x9 ) ) ),
98584c96e61dd85c172b999d6afc88ce6640aeba9962sewardj                        unop( Iop_1Sto32,
98594c96e61dd85c172b999d6afc88ce6640aeba9962sewardj                              binop( Iop_CmpLE32U,
98604c96e61dd85c172b999d6afc88ce6640aeba9962sewardj                                     binop( Iop_And32,
98614c96e61dd85c172b999d6afc88ce6640aeba9962sewardj                                            binop( Iop_Shr32,
98624c96e61dd85c172b999d6afc88ce6640aeba9962sewardj                                                   bcd_l,
98634c96e61dd85c172b999d6afc88ce6640aeba9962sewardj                                                   mkU8 ( DIGIT1_SHR ) ),
98644c96e61dd85c172b999d6afc88ce6640aeba9962sewardj                                             mkU32 ( 0xF ) ),
98654c96e61dd85c172b999d6afc88ce6640aeba9962sewardj                                      mkU32( 0x9 ) ) ),
98664c96e61dd85c172b999d6afc88ce6640aeba9962sewardj                        unop( Iop_1Sto32,
98674c96e61dd85c172b999d6afc88ce6640aeba9962sewardj                              binop( Iop_CmpLE32U,
98684c96e61dd85c172b999d6afc88ce6640aeba9962sewardj                                     binop( Iop_And32,
98694c96e61dd85c172b999d6afc88ce6640aeba9962sewardj                                            binop( Iop_Shr32,
98704c96e61dd85c172b999d6afc88ce6640aeba9962sewardj                                                   bcd_l,
98714c96e61dd85c172b999d6afc88ce6640aeba9962sewardj                                                   mkU8 ( DIGIT2_SHR ) ),
98724c96e61dd85c172b999d6afc88ce6640aeba9962sewardj                                            mkU32 ( 0xF ) ),
98734c96e61dd85c172b999d6afc88ce6640aeba9962sewardj                                      mkU32( 0x9 ) ) ),
98744c96e61dd85c172b999d6afc88ce6640aeba9962sewardj                        unop( Iop_1Sto32,
98754c96e61dd85c172b999d6afc88ce6640aeba9962sewardj                              binop( Iop_CmpLE32U,
98764c96e61dd85c172b999d6afc88ce6640aeba9962sewardj                                     binop( Iop_And32,
98774c96e61dd85c172b999d6afc88ce6640aeba9962sewardj                                            binop( Iop_Shr32,
98784c96e61dd85c172b999d6afc88ce6640aeba9962sewardj                                                   bcd_l,
98794c96e61dd85c172b999d6afc88ce6640aeba9962sewardj                                                   mkU8 ( DIGIT3_SHR ) ),
98804c96e61dd85c172b999d6afc88ce6640aeba9962sewardj                                             mkU32 ( 0xF ) ),
98814c96e61dd85c172b999d6afc88ce6640aeba9962sewardj                                      mkU32( 0x9 ) ) ) ),
98824c96e61dd85c172b999d6afc88ce6640aeba9962sewardj                 AND4 ( unop( Iop_1Sto32,
98834c96e61dd85c172b999d6afc88ce6640aeba9962sewardj                              binop( Iop_CmpLE32U,
98844c96e61dd85c172b999d6afc88ce6640aeba9962sewardj                                     binop( Iop_And32,
98854c96e61dd85c172b999d6afc88ce6640aeba9962sewardj                                            binop( Iop_Shr32,
98864c96e61dd85c172b999d6afc88ce6640aeba9962sewardj                                                   bcd_l,
98874c96e61dd85c172b999d6afc88ce6640aeba9962sewardj                                                   mkU8 ( DIGIT4_SHR ) ),
98884c96e61dd85c172b999d6afc88ce6640aeba9962sewardj                                            mkU32 ( 0xF ) ),
98894c96e61dd85c172b999d6afc88ce6640aeba9962sewardj                                     mkU32( 0x9 ) ) ),
98904c96e61dd85c172b999d6afc88ce6640aeba9962sewardj                        unop( Iop_1Sto32,
98914c96e61dd85c172b999d6afc88ce6640aeba9962sewardj                              binop( Iop_CmpLE32U,
98924c96e61dd85c172b999d6afc88ce6640aeba9962sewardj                                     binop( Iop_And32,
98934c96e61dd85c172b999d6afc88ce6640aeba9962sewardj                                            binop( Iop_Shr32,
98944c96e61dd85c172b999d6afc88ce6640aeba9962sewardj                                                   bcd_l,
98954c96e61dd85c172b999d6afc88ce6640aeba9962sewardj                                                   mkU8 ( DIGIT5_SHR ) ),
98964c96e61dd85c172b999d6afc88ce6640aeba9962sewardj                                            mkU32 ( 0xF ) ),
98974c96e61dd85c172b999d6afc88ce6640aeba9962sewardj                                     mkU32( 0x9 ) ) ),
98984c96e61dd85c172b999d6afc88ce6640aeba9962sewardj                        unop( Iop_1Sto32,
98994c96e61dd85c172b999d6afc88ce6640aeba9962sewardj                              binop( Iop_CmpLE32U,
99004c96e61dd85c172b999d6afc88ce6640aeba9962sewardj                                     binop( Iop_And32,
99014c96e61dd85c172b999d6afc88ce6640aeba9962sewardj                                            binop( Iop_Shr32,
99024c96e61dd85c172b999d6afc88ce6640aeba9962sewardj                                                   bcd_l,
99034c96e61dd85c172b999d6afc88ce6640aeba9962sewardj                                                   mkU8 ( DIGIT6_SHR ) ),
99044c96e61dd85c172b999d6afc88ce6640aeba9962sewardj                                            mkU32 ( 0xF ) ),
99054c96e61dd85c172b999d6afc88ce6640aeba9962sewardj                                     mkU32( 0x9 ) ) ),
99064c96e61dd85c172b999d6afc88ce6640aeba9962sewardj                        unop( Iop_1Sto32,
99074c96e61dd85c172b999d6afc88ce6640aeba9962sewardj                              binop( Iop_CmpLE32U,
99084c96e61dd85c172b999d6afc88ce6640aeba9962sewardj                                     binop( Iop_And32,
99094c96e61dd85c172b999d6afc88ce6640aeba9962sewardj                                            binop( Iop_Shr32,
99104c96e61dd85c172b999d6afc88ce6640aeba9962sewardj                                                   bcd_l,
99114c96e61dd85c172b999d6afc88ce6640aeba9962sewardj                                                   mkU8 ( DIGIT7_SHR ) ),
99124c96e61dd85c172b999d6afc88ce6640aeba9962sewardj                                            mkU32 ( 0xF ) ),
99134c96e61dd85c172b999d6afc88ce6640aeba9962sewardj                                     mkU32( 0x9 ) ) ) ),
99144c96e61dd85c172b999d6afc88ce6640aeba9962sewardj                 AND4( unop( Iop_1Sto32,
99154c96e61dd85c172b999d6afc88ce6640aeba9962sewardj                             binop( Iop_CmpLE32U,
99164c96e61dd85c172b999d6afc88ce6640aeba9962sewardj                                    binop( Iop_And32,
99174c96e61dd85c172b999d6afc88ce6640aeba9962sewardj                                           bcd_u,
99184c96e61dd85c172b999d6afc88ce6640aeba9962sewardj                                           mkU32 ( 0xF ) ),
99194c96e61dd85c172b999d6afc88ce6640aeba9962sewardj                                    mkU32( 0x9 ) ) ),
99204c96e61dd85c172b999d6afc88ce6640aeba9962sewardj                       unop( Iop_1Sto32,
99214c96e61dd85c172b999d6afc88ce6640aeba9962sewardj                             binop( Iop_CmpLE32U,
99224c96e61dd85c172b999d6afc88ce6640aeba9962sewardj                                    binop( Iop_And32,
99234c96e61dd85c172b999d6afc88ce6640aeba9962sewardj                                           binop( Iop_Shr32,
99244c96e61dd85c172b999d6afc88ce6640aeba9962sewardj                                                  bcd_u,
99254c96e61dd85c172b999d6afc88ce6640aeba9962sewardj                                                  mkU8 ( DIGIT1_SHR ) ),
99264c96e61dd85c172b999d6afc88ce6640aeba9962sewardj                                           mkU32 ( 0xF ) ),
99274c96e61dd85c172b999d6afc88ce6640aeba9962sewardj                                    mkU32( 0x9 ) ) ),
99284c96e61dd85c172b999d6afc88ce6640aeba9962sewardj                       unop( Iop_1Sto32,
99294c96e61dd85c172b999d6afc88ce6640aeba9962sewardj                             binop( Iop_CmpLE32U,
99304c96e61dd85c172b999d6afc88ce6640aeba9962sewardj                                    binop( Iop_And32,
99314c96e61dd85c172b999d6afc88ce6640aeba9962sewardj                                           binop( Iop_Shr32,
99324c96e61dd85c172b999d6afc88ce6640aeba9962sewardj                                                  bcd_u,
99334c96e61dd85c172b999d6afc88ce6640aeba9962sewardj                                                  mkU8 ( DIGIT2_SHR ) ),
99344c96e61dd85c172b999d6afc88ce6640aeba9962sewardj                                           mkU32 ( 0xF ) ),
99354c96e61dd85c172b999d6afc88ce6640aeba9962sewardj                                    mkU32( 0x9 ) ) ),
99364c96e61dd85c172b999d6afc88ce6640aeba9962sewardj                       unop( Iop_1Sto32,
99374c96e61dd85c172b999d6afc88ce6640aeba9962sewardj                             binop( Iop_CmpLE32U,
99384c96e61dd85c172b999d6afc88ce6640aeba9962sewardj                                    binop( Iop_And32,
99394c96e61dd85c172b999d6afc88ce6640aeba9962sewardj                                           binop( Iop_Shr32,
99404c96e61dd85c172b999d6afc88ce6640aeba9962sewardj                                                  bcd_u,
99414c96e61dd85c172b999d6afc88ce6640aeba9962sewardj                                                  mkU8 ( DIGIT3_SHR ) ),
99424c96e61dd85c172b999d6afc88ce6640aeba9962sewardj                                           mkU32 ( 0xF ) ),
99434c96e61dd85c172b999d6afc88ce6640aeba9962sewardj                                    mkU32( 0x9 ) ) ) ),
99444c96e61dd85c172b999d6afc88ce6640aeba9962sewardj                 AND4( unop( Iop_1Sto32,
99454c96e61dd85c172b999d6afc88ce6640aeba9962sewardj                             binop( Iop_CmpLE32U,
99464c96e61dd85c172b999d6afc88ce6640aeba9962sewardj                                    binop( Iop_And32,
99474c96e61dd85c172b999d6afc88ce6640aeba9962sewardj                                           binop( Iop_Shr32,
99484c96e61dd85c172b999d6afc88ce6640aeba9962sewardj                                                  bcd_u,
99494c96e61dd85c172b999d6afc88ce6640aeba9962sewardj                                                  mkU8 ( DIGIT4_SHR ) ),
99504c96e61dd85c172b999d6afc88ce6640aeba9962sewardj                                           mkU32 ( 0xF ) ),
99514c96e61dd85c172b999d6afc88ce6640aeba9962sewardj                                    mkU32( 0x9 ) ) ),
99524c96e61dd85c172b999d6afc88ce6640aeba9962sewardj                       unop( Iop_1Sto32,
99534c96e61dd85c172b999d6afc88ce6640aeba9962sewardj                             binop( Iop_CmpLE32U,
99544c96e61dd85c172b999d6afc88ce6640aeba9962sewardj                                    binop( Iop_And32,
99554c96e61dd85c172b999d6afc88ce6640aeba9962sewardj                                           binop( Iop_Shr32,
99564c96e61dd85c172b999d6afc88ce6640aeba9962sewardj                                                  bcd_u,
99574c96e61dd85c172b999d6afc88ce6640aeba9962sewardj                                                  mkU8 ( DIGIT5_SHR ) ),
99584c96e61dd85c172b999d6afc88ce6640aeba9962sewardj                                           mkU32 ( 0xF ) ),
99594c96e61dd85c172b999d6afc88ce6640aeba9962sewardj                                    mkU32( 0x9 ) ) ),
99604c96e61dd85c172b999d6afc88ce6640aeba9962sewardj                       unop( Iop_1Sto32,
99614c96e61dd85c172b999d6afc88ce6640aeba9962sewardj                             binop( Iop_CmpLE32U,
99624c96e61dd85c172b999d6afc88ce6640aeba9962sewardj                                    binop( Iop_And32,
99634c96e61dd85c172b999d6afc88ce6640aeba9962sewardj                                           binop( Iop_Shr32,
99644c96e61dd85c172b999d6afc88ce6640aeba9962sewardj                                                  bcd_u,
99654c96e61dd85c172b999d6afc88ce6640aeba9962sewardj                                                  mkU8 ( DIGIT6_SHR ) ),
99664c96e61dd85c172b999d6afc88ce6640aeba9962sewardj                                           mkU32 ( 0xF ) ),
99674c96e61dd85c172b999d6afc88ce6640aeba9962sewardj                                    mkU32( 0x9 ) ) ),
99684c96e61dd85c172b999d6afc88ce6640aeba9962sewardj                       unop( Iop_1Sto32,
99694c96e61dd85c172b999d6afc88ce6640aeba9962sewardj                             binop( Iop_CmpLE32U,
99704c96e61dd85c172b999d6afc88ce6640aeba9962sewardj                                    binop( Iop_And32,
99714c96e61dd85c172b999d6afc88ce6640aeba9962sewardj                                           binop( Iop_Shr32,
99724c96e61dd85c172b999d6afc88ce6640aeba9962sewardj                                                  bcd_u,
99734c96e61dd85c172b999d6afc88ce6640aeba9962sewardj                                                  mkU8 ( DIGIT7_SHR ) ),
99744c96e61dd85c172b999d6afc88ce6640aeba9962sewardj                                           mkU32 ( 0xF ) ),
99754c96e61dd85c172b999d6afc88ce6640aeba9962sewardj                                    mkU32( 0x9 ) ) ) ) ) );
99764c96e61dd85c172b999d6afc88ce6640aeba9962sewardj
99774c96e61dd85c172b999d6afc88ce6640aeba9962sewardj   return unop( Iop_Not32, mkexpr( valid ) );
99784c96e61dd85c172b999d6afc88ce6640aeba9962sewardj}
99794c96e61dd85c172b999d6afc88ce6640aeba9962sewardj#undef DIGIT1_SHR
99804c96e61dd85c172b999d6afc88ce6640aeba9962sewardj#undef DIGIT2_SHR
99814c96e61dd85c172b999d6afc88ce6640aeba9962sewardj#undef DIGIT3_SHR
99824c96e61dd85c172b999d6afc88ce6640aeba9962sewardj#undef DIGIT4_SHR
99834c96e61dd85c172b999d6afc88ce6640aeba9962sewardj#undef DIGIT5_SHR
99844c96e61dd85c172b999d6afc88ce6640aeba9962sewardj#undef DIGIT6_SHR
99854c96e61dd85c172b999d6afc88ce6640aeba9962sewardj#undef DIGIT7_SHR
99864c96e61dd85c172b999d6afc88ce6640aeba9962sewardj
99874c96e61dd85c172b999d6afc88ce6640aeba9962sewardjstatic IRExpr * Generate_neg_sign_mask( IRExpr * sign )
99884c96e61dd85c172b999d6afc88ce6640aeba9962sewardj{
99894c96e61dd85c172b999d6afc88ce6640aeba9962sewardj   return binop( Iop_Or32,
99904c96e61dd85c172b999d6afc88ce6640aeba9962sewardj                 unop( Iop_1Sto32, binop( Iop_CmpEQ32, sign, mkU32( 0xB ) ) ),
99914c96e61dd85c172b999d6afc88ce6640aeba9962sewardj                 unop( Iop_1Sto32, binop( Iop_CmpEQ32, sign, mkU32( 0xD ) ) )
99924c96e61dd85c172b999d6afc88ce6640aeba9962sewardj               );
99934c96e61dd85c172b999d6afc88ce6640aeba9962sewardj}
99944c96e61dd85c172b999d6afc88ce6640aeba9962sewardj
99954c96e61dd85c172b999d6afc88ce6640aeba9962sewardjstatic IRExpr * Generate_pos_sign_mask( IRExpr * sign )
99964c96e61dd85c172b999d6afc88ce6640aeba9962sewardj{
99974c96e61dd85c172b999d6afc88ce6640aeba9962sewardj   return binop( Iop_Or32,
99984c96e61dd85c172b999d6afc88ce6640aeba9962sewardj                 binop( Iop_Or32,
99994c96e61dd85c172b999d6afc88ce6640aeba9962sewardj                        unop( Iop_1Sto32,
100004c96e61dd85c172b999d6afc88ce6640aeba9962sewardj                              binop( Iop_CmpEQ32, sign, mkU32( 0xA ) ) ),
100014c96e61dd85c172b999d6afc88ce6640aeba9962sewardj                        unop( Iop_1Sto32,
100024c96e61dd85c172b999d6afc88ce6640aeba9962sewardj                              binop( Iop_CmpEQ32, sign, mkU32( 0xC ) ) ) ),
100034c96e61dd85c172b999d6afc88ce6640aeba9962sewardj                 binop( Iop_Or32,
100044c96e61dd85c172b999d6afc88ce6640aeba9962sewardj                        unop( Iop_1Sto32,
100054c96e61dd85c172b999d6afc88ce6640aeba9962sewardj                              binop( Iop_CmpEQ32, sign, mkU32( 0xE ) ) ),
100064c96e61dd85c172b999d6afc88ce6640aeba9962sewardj                        unop( Iop_1Sto32,
100074c96e61dd85c172b999d6afc88ce6640aeba9962sewardj                              binop( Iop_CmpEQ32, sign, mkU32( 0xF ) ) ) ) );
100084c96e61dd85c172b999d6afc88ce6640aeba9962sewardj}
100094c96e61dd85c172b999d6afc88ce6640aeba9962sewardj
100104c96e61dd85c172b999d6afc88ce6640aeba9962sewardjstatic IRExpr * Generate_sign_bit( IRExpr * pos_sign_mask,
100114c96e61dd85c172b999d6afc88ce6640aeba9962sewardj                                   IRExpr * neg_sign_mask )
100124c96e61dd85c172b999d6afc88ce6640aeba9962sewardj{
100134c96e61dd85c172b999d6afc88ce6640aeba9962sewardj   return binop( Iop_Or32,
100144c96e61dd85c172b999d6afc88ce6640aeba9962sewardj                 binop( Iop_And32, neg_sign_mask, mkU32( 0x80000000 ) ),
100154c96e61dd85c172b999d6afc88ce6640aeba9962sewardj                 binop( Iop_And32, pos_sign_mask, mkU32( 0x00000000 ) ) );
100164c96e61dd85c172b999d6afc88ce6640aeba9962sewardj}
100174c96e61dd85c172b999d6afc88ce6640aeba9962sewardj
100184c96e61dd85c172b999d6afc88ce6640aeba9962sewardjstatic IRExpr * Generate_inv_mask( IRExpr * invalid_bcd_mask,
100194c96e61dd85c172b999d6afc88ce6640aeba9962sewardj                                   IRExpr * pos_sign_mask,
100204c96e61dd85c172b999d6afc88ce6640aeba9962sewardj                                   IRExpr * neg_sign_mask )
100214c96e61dd85c172b999d6afc88ce6640aeba9962sewardj/* first argument is all 1's if the BCD string had an invalid digit in it. */
100224c96e61dd85c172b999d6afc88ce6640aeba9962sewardj{
100234c96e61dd85c172b999d6afc88ce6640aeba9962sewardj   return binop( Iop_Or32,
100244c96e61dd85c172b999d6afc88ce6640aeba9962sewardj                 invalid_bcd_mask,
100254c96e61dd85c172b999d6afc88ce6640aeba9962sewardj                 unop( Iop_1Sto32,
100264c96e61dd85c172b999d6afc88ce6640aeba9962sewardj                       binop( Iop_CmpEQ32,
100274c96e61dd85c172b999d6afc88ce6640aeba9962sewardj                              binop( Iop_Or32, pos_sign_mask, neg_sign_mask ),
100284c96e61dd85c172b999d6afc88ce6640aeba9962sewardj                              mkU32( 0x0 ) ) ) );
100294c96e61dd85c172b999d6afc88ce6640aeba9962sewardj}
100304c96e61dd85c172b999d6afc88ce6640aeba9962sewardj
100314c96e61dd85c172b999d6afc88ce6640aeba9962sewardjstatic void Generate_132_bit_bcd_string( IRExpr * frBI64_hi, IRExpr * frBI64_lo,
100324c96e61dd85c172b999d6afc88ce6640aeba9962sewardj                                         IRTemp * top_12_l, IRTemp * mid_60_u,
100334c96e61dd85c172b999d6afc88ce6640aeba9962sewardj                                         IRTemp * mid_60_l, IRTemp * low_60_u,
100344c96e61dd85c172b999d6afc88ce6640aeba9962sewardj                                         IRTemp * low_60_l)
100354c96e61dd85c172b999d6afc88ce6640aeba9962sewardj{
100364c96e61dd85c172b999d6afc88ce6640aeba9962sewardj   IRTemp tmplow60 = newTemp( Ity_I64 );
100374c96e61dd85c172b999d6afc88ce6640aeba9962sewardj   IRTemp tmpmid60 = newTemp( Ity_I64 );
100384c96e61dd85c172b999d6afc88ce6640aeba9962sewardj   IRTemp tmptop12 = newTemp( Ity_I64 );
100394c96e61dd85c172b999d6afc88ce6640aeba9962sewardj   IRTemp low_50   = newTemp( Ity_I64 );
100404c96e61dd85c172b999d6afc88ce6640aeba9962sewardj   IRTemp mid_50   = newTemp( Ity_I64 );
100414c96e61dd85c172b999d6afc88ce6640aeba9962sewardj   IRTemp top_10   = newTemp( Ity_I64 );
100424c96e61dd85c172b999d6afc88ce6640aeba9962sewardj   IRTemp top_12_u = newTemp( Ity_I32 ); // only needed for a dummy arg
100434c96e61dd85c172b999d6afc88ce6640aeba9962sewardj
100444c96e61dd85c172b999d6afc88ce6640aeba9962sewardj   /* Convert the 110-bit densely packed BCD string to a 128-bit BCD string */
100454c96e61dd85c172b999d6afc88ce6640aeba9962sewardj
100464c96e61dd85c172b999d6afc88ce6640aeba9962sewardj   /* low_50[49:0] = ((frBI64_lo[49:32]  << 14) | frBI64_lo[31:0]) */
100474c96e61dd85c172b999d6afc88ce6640aeba9962sewardj   assign( low_50,
100484c96e61dd85c172b999d6afc88ce6640aeba9962sewardj           binop( Iop_32HLto64,
100494c96e61dd85c172b999d6afc88ce6640aeba9962sewardj                  binop( Iop_And32,
100504c96e61dd85c172b999d6afc88ce6640aeba9962sewardj                         unop( Iop_64HIto32, frBI64_lo ),
100514c96e61dd85c172b999d6afc88ce6640aeba9962sewardj                         mkU32( 0x3FFFF ) ),
100524c96e61dd85c172b999d6afc88ce6640aeba9962sewardj                         unop( Iop_64to32, frBI64_lo ) ) );
100534c96e61dd85c172b999d6afc88ce6640aeba9962sewardj
100544c96e61dd85c172b999d6afc88ce6640aeba9962sewardj   /* Convert the 50 bit densely packed BCD string to a 60 bit
100554c96e61dd85c172b999d6afc88ce6640aeba9962sewardj    * BCD string.
100564c96e61dd85c172b999d6afc88ce6640aeba9962sewardj    */
100574c96e61dd85c172b999d6afc88ce6640aeba9962sewardj   assign( tmplow60, unop( Iop_DPBtoBCD, mkexpr( low_50 ) ) );
100584c96e61dd85c172b999d6afc88ce6640aeba9962sewardj   assign( *low_60_u, unop( Iop_64HIto32, mkexpr( tmplow60 ) ) );
100594c96e61dd85c172b999d6afc88ce6640aeba9962sewardj   assign( *low_60_l, unop( Iop_64to32, mkexpr( tmplow60 ) ) );
100604c96e61dd85c172b999d6afc88ce6640aeba9962sewardj
100614c96e61dd85c172b999d6afc88ce6640aeba9962sewardj   /* mid_50[49:0] =  ((frBI64_hi[35:32] << 14) | frBI64_hi[31:18]) |
100624c96e61dd85c172b999d6afc88ce6640aeba9962sewardj    *                 ((frBI64_hi[17:0]  << 14) | frBI64_lo[63:50])
100634c96e61dd85c172b999d6afc88ce6640aeba9962sewardj    */
100644c96e61dd85c172b999d6afc88ce6640aeba9962sewardj   assign( mid_50,
100654c96e61dd85c172b999d6afc88ce6640aeba9962sewardj           binop( Iop_32HLto64,
100664c96e61dd85c172b999d6afc88ce6640aeba9962sewardj                  binop( Iop_Or32,
100674c96e61dd85c172b999d6afc88ce6640aeba9962sewardj                         binop( Iop_Shl32,
100684c96e61dd85c172b999d6afc88ce6640aeba9962sewardj                                binop( Iop_And32,
100694c96e61dd85c172b999d6afc88ce6640aeba9962sewardj                                       unop( Iop_64HIto32, frBI64_hi ),
100704c96e61dd85c172b999d6afc88ce6640aeba9962sewardj                                       mkU32( 0xF ) ),
100714c96e61dd85c172b999d6afc88ce6640aeba9962sewardj                                mkU8( 14 ) ),
100724c96e61dd85c172b999d6afc88ce6640aeba9962sewardj                         binop( Iop_Shr32,
100734c96e61dd85c172b999d6afc88ce6640aeba9962sewardj                                unop( Iop_64to32, frBI64_hi ),
100744c96e61dd85c172b999d6afc88ce6640aeba9962sewardj                                mkU8( 18 ) ) ),
100754c96e61dd85c172b999d6afc88ce6640aeba9962sewardj                  binop( Iop_Or32,
100764c96e61dd85c172b999d6afc88ce6640aeba9962sewardj                         binop( Iop_Shl32,
100774c96e61dd85c172b999d6afc88ce6640aeba9962sewardj                                unop( Iop_64to32, frBI64_hi ),
100784c96e61dd85c172b999d6afc88ce6640aeba9962sewardj                                mkU8( 14 ) ),
100794c96e61dd85c172b999d6afc88ce6640aeba9962sewardj                         binop( Iop_Shr32,
100804c96e61dd85c172b999d6afc88ce6640aeba9962sewardj                                unop( Iop_64HIto32, frBI64_lo ),
100814c96e61dd85c172b999d6afc88ce6640aeba9962sewardj                                mkU8( 18 ) ) ) ) );
100824c96e61dd85c172b999d6afc88ce6640aeba9962sewardj
100834c96e61dd85c172b999d6afc88ce6640aeba9962sewardj   /* Convert the 50 bit densely packed BCD string to a 60 bit
100844c96e61dd85c172b999d6afc88ce6640aeba9962sewardj    * BCD string.
100854c96e61dd85c172b999d6afc88ce6640aeba9962sewardj    */
100864c96e61dd85c172b999d6afc88ce6640aeba9962sewardj   assign( tmpmid60, unop( Iop_DPBtoBCD, mkexpr( mid_50 ) ) );
100874c96e61dd85c172b999d6afc88ce6640aeba9962sewardj   assign( *mid_60_u, unop( Iop_64HIto32, mkexpr( tmpmid60 ) ) );
100884c96e61dd85c172b999d6afc88ce6640aeba9962sewardj   assign( *mid_60_l, unop( Iop_64to32, mkexpr( tmpmid60 ) ) );
100894c96e61dd85c172b999d6afc88ce6640aeba9962sewardj
100904c96e61dd85c172b999d6afc88ce6640aeba9962sewardj   /* top_10[49:0] = frBI64_hi[45:36]) |  */
100914c96e61dd85c172b999d6afc88ce6640aeba9962sewardj   assign( top_10,
100924c96e61dd85c172b999d6afc88ce6640aeba9962sewardj           binop( Iop_32HLto64,
100934c96e61dd85c172b999d6afc88ce6640aeba9962sewardj                  mkU32( 0 ),
100944c96e61dd85c172b999d6afc88ce6640aeba9962sewardj                  binop( Iop_And32,
100954c96e61dd85c172b999d6afc88ce6640aeba9962sewardj                         binop( Iop_Shr32,
100964c96e61dd85c172b999d6afc88ce6640aeba9962sewardj                                unop( Iop_64HIto32, frBI64_hi ),
100974c96e61dd85c172b999d6afc88ce6640aeba9962sewardj                                mkU8( 4 ) ),
100984c96e61dd85c172b999d6afc88ce6640aeba9962sewardj                         mkU32( 0x3FF ) ) ) );
100994c96e61dd85c172b999d6afc88ce6640aeba9962sewardj
101004c96e61dd85c172b999d6afc88ce6640aeba9962sewardj   /* Convert the 10 bit densely packed BCD string to a 12 bit
101014c96e61dd85c172b999d6afc88ce6640aeba9962sewardj    * BCD string.
101024c96e61dd85c172b999d6afc88ce6640aeba9962sewardj    */
101034c96e61dd85c172b999d6afc88ce6640aeba9962sewardj   assign( tmptop12, unop( Iop_DPBtoBCD, mkexpr( top_10 ) ) );
101044c96e61dd85c172b999d6afc88ce6640aeba9962sewardj   assign( top_12_u, unop( Iop_64HIto32, mkexpr( tmptop12 ) ) );
101054c96e61dd85c172b999d6afc88ce6640aeba9962sewardj   assign( *top_12_l, unop( Iop_64to32, mkexpr( tmptop12 ) ) );
101064c96e61dd85c172b999d6afc88ce6640aeba9962sewardj}
101074c96e61dd85c172b999d6afc88ce6640aeba9962sewardj
101084c96e61dd85c172b999d6afc88ce6640aeba9962sewardjstatic void Count_zeros( int start, IRExpr * init_cnt, IRExpr * init_flag,
101094c96e61dd85c172b999d6afc88ce6640aeba9962sewardj                         IRTemp * final_cnt, IRTemp * final_flag,
101104c96e61dd85c172b999d6afc88ce6640aeba9962sewardj                         IRExpr * string )
101114c96e61dd85c172b999d6afc88ce6640aeba9962sewardj{
101124c96e61dd85c172b999d6afc88ce6640aeba9962sewardj   IRTemp cnt[MAX_DIGITS_IN_STRING + 1];IRTemp flag[MAX_DIGITS_IN_STRING+1];
101134c96e61dd85c172b999d6afc88ce6640aeba9962sewardj   int digits = MAX_DIGITS_IN_STRING;
101144c96e61dd85c172b999d6afc88ce6640aeba9962sewardj   int i;
101154c96e61dd85c172b999d6afc88ce6640aeba9962sewardj
101164c96e61dd85c172b999d6afc88ce6640aeba9962sewardj   cnt[start-1] = newTemp( Ity_I8 );
101174c96e61dd85c172b999d6afc88ce6640aeba9962sewardj   flag[start-1] = newTemp( Ity_I8 );
101184c96e61dd85c172b999d6afc88ce6640aeba9962sewardj   assign( cnt[start-1], init_cnt);
101194c96e61dd85c172b999d6afc88ce6640aeba9962sewardj   assign( flag[start-1], init_flag);
101204c96e61dd85c172b999d6afc88ce6640aeba9962sewardj
101214c96e61dd85c172b999d6afc88ce6640aeba9962sewardj   for ( i = start; i <= digits; i++) {
101224c96e61dd85c172b999d6afc88ce6640aeba9962sewardj      cnt[i] = newTemp( Ity_I8 );
101234c96e61dd85c172b999d6afc88ce6640aeba9962sewardj      flag[i] = newTemp( Ity_I8 );
101244c96e61dd85c172b999d6afc88ce6640aeba9962sewardj      assign( cnt[i],
101254c96e61dd85c172b999d6afc88ce6640aeba9962sewardj              binop( Iop_Add8,
101264c96e61dd85c172b999d6afc88ce6640aeba9962sewardj                     mkexpr( cnt[i-1] ),
101274c96e61dd85c172b999d6afc88ce6640aeba9962sewardj                     binop(Iop_And8,
101284c96e61dd85c172b999d6afc88ce6640aeba9962sewardj                           unop( Iop_1Uto8,
101294c96e61dd85c172b999d6afc88ce6640aeba9962sewardj                                 binop(Iop_CmpEQ32,
101304c96e61dd85c172b999d6afc88ce6640aeba9962sewardj                                       binop(Iop_And32,
101314c96e61dd85c172b999d6afc88ce6640aeba9962sewardj                                             string,
101324c96e61dd85c172b999d6afc88ce6640aeba9962sewardj                                             mkU32( 0xF <<
101334c96e61dd85c172b999d6afc88ce6640aeba9962sewardj                                                    ( ( digits - i ) * 4) ) ),
101344c96e61dd85c172b999d6afc88ce6640aeba9962sewardj                                       mkU32( 0 ) ) ),
101354c96e61dd85c172b999d6afc88ce6640aeba9962sewardj                           binop( Iop_Xor8, /* complement flag */
101364c96e61dd85c172b999d6afc88ce6640aeba9962sewardj                                  mkexpr( flag[i - 1] ),
101374c96e61dd85c172b999d6afc88ce6640aeba9962sewardj                                  mkU8( 0xFF ) ) ) ) );
101384c96e61dd85c172b999d6afc88ce6640aeba9962sewardj
101394c96e61dd85c172b999d6afc88ce6640aeba9962sewardj      /* set flag to 1 if digit was not a zero */
101404c96e61dd85c172b999d6afc88ce6640aeba9962sewardj      assign( flag[i],
101414c96e61dd85c172b999d6afc88ce6640aeba9962sewardj              binop(Iop_Or8,
101424c96e61dd85c172b999d6afc88ce6640aeba9962sewardj                    unop( Iop_1Sto8,
101434c96e61dd85c172b999d6afc88ce6640aeba9962sewardj                          binop(Iop_CmpNE32,
101444c96e61dd85c172b999d6afc88ce6640aeba9962sewardj                                binop(Iop_And32,
101454c96e61dd85c172b999d6afc88ce6640aeba9962sewardj                                      string,
101464c96e61dd85c172b999d6afc88ce6640aeba9962sewardj                                      mkU32( 0xF <<
101474c96e61dd85c172b999d6afc88ce6640aeba9962sewardj                                             ( (digits - i) * 4) ) ),
101484c96e61dd85c172b999d6afc88ce6640aeba9962sewardj                                mkU32( 0 ) ) ),
101494c96e61dd85c172b999d6afc88ce6640aeba9962sewardj                    mkexpr( flag[i - 1] ) ) );
101504c96e61dd85c172b999d6afc88ce6640aeba9962sewardj   }
101514c96e61dd85c172b999d6afc88ce6640aeba9962sewardj
101524c96e61dd85c172b999d6afc88ce6640aeba9962sewardj   *final_cnt = cnt[digits];
101534c96e61dd85c172b999d6afc88ce6640aeba9962sewardj   *final_flag = flag[digits];
101544c96e61dd85c172b999d6afc88ce6640aeba9962sewardj}
101554c96e61dd85c172b999d6afc88ce6640aeba9962sewardj
101564c96e61dd85c172b999d6afc88ce6640aeba9962sewardjstatic IRExpr * Count_leading_zeros_60( IRExpr * lmd, IRExpr * upper_28,
101574c96e61dd85c172b999d6afc88ce6640aeba9962sewardj                                        IRExpr * low_32 )
101584c96e61dd85c172b999d6afc88ce6640aeba9962sewardj{
101594c96e61dd85c172b999d6afc88ce6640aeba9962sewardj   IRTemp num_lmd    = newTemp( Ity_I8 );
101604c96e61dd85c172b999d6afc88ce6640aeba9962sewardj   IRTemp num_upper  = newTemp( Ity_I8 );
101614c96e61dd85c172b999d6afc88ce6640aeba9962sewardj   IRTemp num_low    = newTemp( Ity_I8 );
101624c96e61dd85c172b999d6afc88ce6640aeba9962sewardj   IRTemp lmd_flag   = newTemp( Ity_I8 );
101634c96e61dd85c172b999d6afc88ce6640aeba9962sewardj   IRTemp upper_flag = newTemp( Ity_I8 );
101644c96e61dd85c172b999d6afc88ce6640aeba9962sewardj   IRTemp low_flag   = newTemp( Ity_I8 );
101654c96e61dd85c172b999d6afc88ce6640aeba9962sewardj
101664c96e61dd85c172b999d6afc88ce6640aeba9962sewardj   assign( num_lmd, unop( Iop_1Uto8, binop( Iop_CmpEQ32, lmd, mkU32( 0 ) ) ) );
101674c96e61dd85c172b999d6afc88ce6640aeba9962sewardj   assign( lmd_flag, unop( Iop_Not8, mkexpr( num_lmd ) ) );
101684c96e61dd85c172b999d6afc88ce6640aeba9962sewardj
101694c96e61dd85c172b999d6afc88ce6640aeba9962sewardj   Count_zeros( 2,
101704c96e61dd85c172b999d6afc88ce6640aeba9962sewardj                mkexpr( num_lmd ),
101714c96e61dd85c172b999d6afc88ce6640aeba9962sewardj                mkexpr( lmd_flag ),
101724c96e61dd85c172b999d6afc88ce6640aeba9962sewardj                &num_upper,
101734c96e61dd85c172b999d6afc88ce6640aeba9962sewardj                &upper_flag,
101744c96e61dd85c172b999d6afc88ce6640aeba9962sewardj                upper_28 );
101754c96e61dd85c172b999d6afc88ce6640aeba9962sewardj
101764c96e61dd85c172b999d6afc88ce6640aeba9962sewardj   Count_zeros( 1,
101774c96e61dd85c172b999d6afc88ce6640aeba9962sewardj                mkexpr( num_upper ),
101784c96e61dd85c172b999d6afc88ce6640aeba9962sewardj                mkexpr( upper_flag ),
101794c96e61dd85c172b999d6afc88ce6640aeba9962sewardj                &num_low,
101804c96e61dd85c172b999d6afc88ce6640aeba9962sewardj                &low_flag,
101814c96e61dd85c172b999d6afc88ce6640aeba9962sewardj                low_32 );
101824c96e61dd85c172b999d6afc88ce6640aeba9962sewardj
101834c96e61dd85c172b999d6afc88ce6640aeba9962sewardj   return mkexpr( num_low );
101844c96e61dd85c172b999d6afc88ce6640aeba9962sewardj}
101854c96e61dd85c172b999d6afc88ce6640aeba9962sewardj
101864c96e61dd85c172b999d6afc88ce6640aeba9962sewardjstatic IRExpr * Count_leading_zeros_128( IRExpr * lmd, IRExpr * top_12_l,
101874c96e61dd85c172b999d6afc88ce6640aeba9962sewardj                                         IRExpr * mid_60_u, IRExpr * mid_60_l,
101884c96e61dd85c172b999d6afc88ce6640aeba9962sewardj                                         IRExpr * low_60_u, IRExpr * low_60_l)
101894c96e61dd85c172b999d6afc88ce6640aeba9962sewardj{
101904c96e61dd85c172b999d6afc88ce6640aeba9962sewardj   IRTemp num_lmd   = newTemp( Ity_I8 );
101914c96e61dd85c172b999d6afc88ce6640aeba9962sewardj   IRTemp num_top   = newTemp( Ity_I8 );
101924c96e61dd85c172b999d6afc88ce6640aeba9962sewardj   IRTemp num_mid_u = newTemp( Ity_I8 );
101934c96e61dd85c172b999d6afc88ce6640aeba9962sewardj   IRTemp num_mid_l = newTemp( Ity_I8 );
101944c96e61dd85c172b999d6afc88ce6640aeba9962sewardj   IRTemp num_low_u = newTemp( Ity_I8 );
101954c96e61dd85c172b999d6afc88ce6640aeba9962sewardj   IRTemp num_low_l = newTemp( Ity_I8 );
101964c96e61dd85c172b999d6afc88ce6640aeba9962sewardj
101974c96e61dd85c172b999d6afc88ce6640aeba9962sewardj   IRTemp lmd_flag   = newTemp( Ity_I8 );
101984c96e61dd85c172b999d6afc88ce6640aeba9962sewardj   IRTemp top_flag   = newTemp( Ity_I8 );
101994c96e61dd85c172b999d6afc88ce6640aeba9962sewardj   IRTemp mid_u_flag = newTemp( Ity_I8 );
102004c96e61dd85c172b999d6afc88ce6640aeba9962sewardj   IRTemp mid_l_flag = newTemp( Ity_I8 );
102014c96e61dd85c172b999d6afc88ce6640aeba9962sewardj   IRTemp low_u_flag = newTemp( Ity_I8 );
102024c96e61dd85c172b999d6afc88ce6640aeba9962sewardj   IRTemp low_l_flag = newTemp( Ity_I8 );
102034c96e61dd85c172b999d6afc88ce6640aeba9962sewardj
102044c96e61dd85c172b999d6afc88ce6640aeba9962sewardj   /* Check the LMD, digit 16, to see if it is zero. */
102054c96e61dd85c172b999d6afc88ce6640aeba9962sewardj   assign( num_lmd, unop( Iop_1Uto8, binop( Iop_CmpEQ32, lmd, mkU32( 0 ) ) ) );
102064c96e61dd85c172b999d6afc88ce6640aeba9962sewardj
102074c96e61dd85c172b999d6afc88ce6640aeba9962sewardj   assign( lmd_flag, unop( Iop_Not8, mkexpr( num_lmd ) ) );
102084c96e61dd85c172b999d6afc88ce6640aeba9962sewardj
102094c96e61dd85c172b999d6afc88ce6640aeba9962sewardj   Count_zeros( 6,
102104c96e61dd85c172b999d6afc88ce6640aeba9962sewardj                mkexpr( num_lmd ),
102114c96e61dd85c172b999d6afc88ce6640aeba9962sewardj                mkexpr( lmd_flag ),
102124c96e61dd85c172b999d6afc88ce6640aeba9962sewardj                &num_top,
102134c96e61dd85c172b999d6afc88ce6640aeba9962sewardj                &top_flag,
102144c96e61dd85c172b999d6afc88ce6640aeba9962sewardj                top_12_l );
102154c96e61dd85c172b999d6afc88ce6640aeba9962sewardj
102164c96e61dd85c172b999d6afc88ce6640aeba9962sewardj   Count_zeros( 1,
102174c96e61dd85c172b999d6afc88ce6640aeba9962sewardj                mkexpr( num_top ),
102184c96e61dd85c172b999d6afc88ce6640aeba9962sewardj                mkexpr( top_flag ),
102194c96e61dd85c172b999d6afc88ce6640aeba9962sewardj                &num_mid_u,
102204c96e61dd85c172b999d6afc88ce6640aeba9962sewardj                &mid_u_flag,
102214c96e61dd85c172b999d6afc88ce6640aeba9962sewardj                binop( Iop_Or32,
102224c96e61dd85c172b999d6afc88ce6640aeba9962sewardj                       binop( Iop_Shl32, mid_60_u, mkU8( 2 ) ),
102234c96e61dd85c172b999d6afc88ce6640aeba9962sewardj                       binop( Iop_Shr32, mid_60_l, mkU8( 30 ) ) ) );
102244c96e61dd85c172b999d6afc88ce6640aeba9962sewardj
102254c96e61dd85c172b999d6afc88ce6640aeba9962sewardj   Count_zeros( 2,
102264c96e61dd85c172b999d6afc88ce6640aeba9962sewardj                mkexpr( num_mid_u ),
102274c96e61dd85c172b999d6afc88ce6640aeba9962sewardj                mkexpr( mid_u_flag ),
102284c96e61dd85c172b999d6afc88ce6640aeba9962sewardj                &num_mid_l,
102294c96e61dd85c172b999d6afc88ce6640aeba9962sewardj                &mid_l_flag,
102304c96e61dd85c172b999d6afc88ce6640aeba9962sewardj                mid_60_l );
102314c96e61dd85c172b999d6afc88ce6640aeba9962sewardj
102324c96e61dd85c172b999d6afc88ce6640aeba9962sewardj   Count_zeros( 1,
102334c96e61dd85c172b999d6afc88ce6640aeba9962sewardj                mkexpr( num_mid_l ),
102344c96e61dd85c172b999d6afc88ce6640aeba9962sewardj                mkexpr( mid_l_flag ),
102354c96e61dd85c172b999d6afc88ce6640aeba9962sewardj                &num_low_u,
102364c96e61dd85c172b999d6afc88ce6640aeba9962sewardj                &low_u_flag,
102374c96e61dd85c172b999d6afc88ce6640aeba9962sewardj                binop( Iop_Or32,
102384c96e61dd85c172b999d6afc88ce6640aeba9962sewardj                       binop( Iop_Shl32, low_60_u, mkU8( 2 ) ),
102394c96e61dd85c172b999d6afc88ce6640aeba9962sewardj                       binop( Iop_Shr32, low_60_l, mkU8( 30 ) ) ) );
102404c96e61dd85c172b999d6afc88ce6640aeba9962sewardj
102414c96e61dd85c172b999d6afc88ce6640aeba9962sewardj   Count_zeros( 2,
102424c96e61dd85c172b999d6afc88ce6640aeba9962sewardj                mkexpr( num_low_u ),
102434c96e61dd85c172b999d6afc88ce6640aeba9962sewardj                mkexpr( low_u_flag ),
102444c96e61dd85c172b999d6afc88ce6640aeba9962sewardj                &num_low_l,
102454c96e61dd85c172b999d6afc88ce6640aeba9962sewardj                &low_l_flag,
102464c96e61dd85c172b999d6afc88ce6640aeba9962sewardj                low_60_l );
102474c96e61dd85c172b999d6afc88ce6640aeba9962sewardj
102484c96e61dd85c172b999d6afc88ce6640aeba9962sewardj   return mkexpr( num_low_l );
102494c96e61dd85c172b999d6afc88ce6640aeba9962sewardj}
102504c96e61dd85c172b999d6afc88ce6640aeba9962sewardj
102514c96e61dd85c172b999d6afc88ce6640aeba9962sewardjstatic IRExpr * Check_unordered(IRExpr * val)
102524c96e61dd85c172b999d6afc88ce6640aeba9962sewardj{
102534c96e61dd85c172b999d6afc88ce6640aeba9962sewardj   IRTemp gfield0to5 = newTemp( Ity_I32 );
102544c96e61dd85c172b999d6afc88ce6640aeba9962sewardj
102554c96e61dd85c172b999d6afc88ce6640aeba9962sewardj   /* Extract G[0:4] */
102564c96e61dd85c172b999d6afc88ce6640aeba9962sewardj   assign( gfield0to5,
102574c96e61dd85c172b999d6afc88ce6640aeba9962sewardj           binop( Iop_And32,
102584c96e61dd85c172b999d6afc88ce6640aeba9962sewardj                  binop( Iop_Shr32, unop( Iop_64HIto32, val ), mkU8( 26 ) ),
102594c96e61dd85c172b999d6afc88ce6640aeba9962sewardj                  mkU32( 0x1F ) ) );
102604c96e61dd85c172b999d6afc88ce6640aeba9962sewardj
102614c96e61dd85c172b999d6afc88ce6640aeba9962sewardj   /* Check for unordered, return all 1'x if true */
102624c96e61dd85c172b999d6afc88ce6640aeba9962sewardj   return binop( Iop_Or32, /* QNaN check */
102634c96e61dd85c172b999d6afc88ce6640aeba9962sewardj                 unop( Iop_1Sto32,
102644c96e61dd85c172b999d6afc88ce6640aeba9962sewardj                       binop( Iop_CmpEQ32,
102654c96e61dd85c172b999d6afc88ce6640aeba9962sewardj                              mkexpr( gfield0to5 ),
102664c96e61dd85c172b999d6afc88ce6640aeba9962sewardj                              mkU32( 0x1E ) ) ),
102674c96e61dd85c172b999d6afc88ce6640aeba9962sewardj                              unop( Iop_1Sto32, /* SNaN check */
102684c96e61dd85c172b999d6afc88ce6640aeba9962sewardj                                    binop( Iop_CmpEQ32,
102694c96e61dd85c172b999d6afc88ce6640aeba9962sewardj                                           mkexpr( gfield0to5 ),
102704c96e61dd85c172b999d6afc88ce6640aeba9962sewardj                                           mkU32( 0x1F ) ) ) );
102714c96e61dd85c172b999d6afc88ce6640aeba9962sewardj}
102724c96e61dd85c172b999d6afc88ce6640aeba9962sewardj
102735eff1c502e995d1f9668cc9def72d5db59f21b13sewardj#undef AND
102745eff1c502e995d1f9668cc9def72d5db59f21b13sewardj#undef AND4
102754c96e61dd85c172b999d6afc88ce6640aeba9962sewardj#undef OR
102765eff1c502e995d1f9668cc9def72d5db59f21b13sewardj#undef OR3
102775eff1c502e995d1f9668cc9def72d5db59f21b13sewardj#undef OR4
102784c96e61dd85c172b999d6afc88ce6640aeba9962sewardj#undef NOT
102794c96e61dd85c172b999d6afc88ce6640aeba9962sewardj#undef SHR
102805eff1c502e995d1f9668cc9def72d5db59f21b13sewardj#undef SHL
10281cb06d5e50876ee734e09a5fa0d5f300014e13852sewardj#undef BITS5
102825eff1c502e995d1f9668cc9def72d5db59f21b13sewardj
102835eff1c502e995d1f9668cc9def72d5db59f21b13sewardj/*------------------------------------------------------------*/
10284c6bbd470e9bd9898b84959227a406d3972d95f3bsewardj/*--- Decimal Floating Point (DFP) instruction translation ---*/
10285c6bbd470e9bd9898b84959227a406d3972d95f3bsewardj/*------------------------------------------------------------*/
102865eff1c502e995d1f9668cc9def72d5db59f21b13sewardj
10287c6bbd470e9bd9898b84959227a406d3972d95f3bsewardj/* DFP Arithmetic instructions */
10288c6bbd470e9bd9898b84959227a406d3972d95f3bsewardjstatic Bool dis_dfp_arith(UInt theInstr)
10289c6bbd470e9bd9898b84959227a406d3972d95f3bsewardj{
10290c6bbd470e9bd9898b84959227a406d3972d95f3bsewardj   UInt opc2 = ifieldOPClo10( theInstr );
10291c6bbd470e9bd9898b84959227a406d3972d95f3bsewardj   UChar frS_addr = ifieldRegDS( theInstr );
10292c6bbd470e9bd9898b84959227a406d3972d95f3bsewardj   UChar frA_addr = ifieldRegA( theInstr );
10293c6bbd470e9bd9898b84959227a406d3972d95f3bsewardj   UChar frB_addr = ifieldRegB( theInstr );
10294c6bbd470e9bd9898b84959227a406d3972d95f3bsewardj   UChar flag_rC = ifieldBIT0( theInstr );
10295c6bbd470e9bd9898b84959227a406d3972d95f3bsewardj
10296c6bbd470e9bd9898b84959227a406d3972d95f3bsewardj   IRTemp frA = newTemp( Ity_D64 );
10297c6bbd470e9bd9898b84959227a406d3972d95f3bsewardj   IRTemp frB = newTemp( Ity_D64 );
10298c6bbd470e9bd9898b84959227a406d3972d95f3bsewardj   IRTemp frS = newTemp( Ity_D64 );
10299c6bbd470e9bd9898b84959227a406d3972d95f3bsewardj   IRExpr* round = get_IR_roundingmode_DFP();
10300c6bbd470e9bd9898b84959227a406d3972d95f3bsewardj
10301c6bbd470e9bd9898b84959227a406d3972d95f3bsewardj   /* By default, if flag_RC is set, we will clear cr1 after the
10302c6bbd470e9bd9898b84959227a406d3972d95f3bsewardj    * operation.  In reality we should set cr1 to indicate the
10303c6bbd470e9bd9898b84959227a406d3972d95f3bsewardj    * exception status of the operation, but since we're not
10304c6bbd470e9bd9898b84959227a406d3972d95f3bsewardj    * simulating exceptions, the exception status will appear to be
10305c6bbd470e9bd9898b84959227a406d3972d95f3bsewardj    * zero.  Hence cr1 should be cleared if this is a . form insn.
10306c6bbd470e9bd9898b84959227a406d3972d95f3bsewardj    */
10307c6bbd470e9bd9898b84959227a406d3972d95f3bsewardj   Bool clear_CR1 = True;
10308c6bbd470e9bd9898b84959227a406d3972d95f3bsewardj
10309c6bbd470e9bd9898b84959227a406d3972d95f3bsewardj   assign( frA, getDReg( frA_addr ) );
10310c6bbd470e9bd9898b84959227a406d3972d95f3bsewardj   assign( frB, getDReg( frB_addr ) );
10311e14bb9f862843c6b804097c124961b5567ded4f1sewardj
10312c6bbd470e9bd9898b84959227a406d3972d95f3bsewardj   switch (opc2) {
10313c6bbd470e9bd9898b84959227a406d3972d95f3bsewardj   case 0x2: // dadd
10314c6bbd470e9bd9898b84959227a406d3972d95f3bsewardj      DIP( "dadd%s fr%u,fr%u,fr%u\n",
10315c6bbd470e9bd9898b84959227a406d3972d95f3bsewardj           flag_rC ? ".":"", frS_addr, frA_addr, frB_addr );
10316c6bbd470e9bd9898b84959227a406d3972d95f3bsewardj      assign( frS, triop( Iop_AddD64, round, mkexpr( frA ), mkexpr( frB ) ) );
10317c6bbd470e9bd9898b84959227a406d3972d95f3bsewardj      break;
10318c6bbd470e9bd9898b84959227a406d3972d95f3bsewardj   case 0x202: // dsub
10319c6bbd470e9bd9898b84959227a406d3972d95f3bsewardj      DIP( "dsub%s fr%u,fr%u,fr%u\n",
10320c6bbd470e9bd9898b84959227a406d3972d95f3bsewardj           flag_rC ? ".":"", frS_addr, frA_addr, frB_addr );
10321c6bbd470e9bd9898b84959227a406d3972d95f3bsewardj      assign( frS, triop( Iop_SubD64, round, mkexpr( frA ), mkexpr( frB ) ) );
10322c6bbd470e9bd9898b84959227a406d3972d95f3bsewardj      break;
10323c6bbd470e9bd9898b84959227a406d3972d95f3bsewardj   case 0x22: // dmul
10324c6bbd470e9bd9898b84959227a406d3972d95f3bsewardj      DIP( "dmul%s fr%u,fr%u,fr%u\n",
10325c6bbd470e9bd9898b84959227a406d3972d95f3bsewardj           flag_rC ? ".":"", frS_addr, frA_addr, frB_addr );
10326c6bbd470e9bd9898b84959227a406d3972d95f3bsewardj      assign( frS, triop( Iop_MulD64, round, mkexpr( frA ), mkexpr( frB ) ) );
10327c6bbd470e9bd9898b84959227a406d3972d95f3bsewardj      break;
10328c6bbd470e9bd9898b84959227a406d3972d95f3bsewardj   case 0x222: // ddiv
10329c6bbd470e9bd9898b84959227a406d3972d95f3bsewardj      DIP( "ddiv%s fr%u,fr%u,fr%u\n",
10330c6bbd470e9bd9898b84959227a406d3972d95f3bsewardj           flag_rC ? ".":"", frS_addr, frA_addr, frB_addr );
10331c6bbd470e9bd9898b84959227a406d3972d95f3bsewardj      assign( frS, triop( Iop_DivD64, round, mkexpr( frA ), mkexpr( frB ) ) );
10332c6bbd470e9bd9898b84959227a406d3972d95f3bsewardj      break;
10333c6bbd470e9bd9898b84959227a406d3972d95f3bsewardj   }
10334c6bbd470e9bd9898b84959227a406d3972d95f3bsewardj
10335c6bbd470e9bd9898b84959227a406d3972d95f3bsewardj   putDReg( frS_addr, mkexpr( frS ) );
10336c6bbd470e9bd9898b84959227a406d3972d95f3bsewardj
10337c6bbd470e9bd9898b84959227a406d3972d95f3bsewardj   if (flag_rC && clear_CR1) {
10338c6bbd470e9bd9898b84959227a406d3972d95f3bsewardj      putCR321( 1, mkU8( 0 ) );
10339c6bbd470e9bd9898b84959227a406d3972d95f3bsewardj      putCR0( 1, mkU8( 0 ) );
10340c6bbd470e9bd9898b84959227a406d3972d95f3bsewardj   }
10341c6bbd470e9bd9898b84959227a406d3972d95f3bsewardj
10342c6bbd470e9bd9898b84959227a406d3972d95f3bsewardj   return True;
10343c6bbd470e9bd9898b84959227a406d3972d95f3bsewardj}
10344c6bbd470e9bd9898b84959227a406d3972d95f3bsewardj
10345c6bbd470e9bd9898b84959227a406d3972d95f3bsewardj/* Quad DFP Arithmetic instructions */
10346c6bbd470e9bd9898b84959227a406d3972d95f3bsewardjstatic Bool dis_dfp_arithq(UInt theInstr)
10347c6bbd470e9bd9898b84959227a406d3972d95f3bsewardj{
10348c6bbd470e9bd9898b84959227a406d3972d95f3bsewardj   UInt opc2 = ifieldOPClo10( theInstr );
10349c6bbd470e9bd9898b84959227a406d3972d95f3bsewardj   UChar frS_addr = ifieldRegDS( theInstr );
10350c6bbd470e9bd9898b84959227a406d3972d95f3bsewardj   UChar frA_addr = ifieldRegA( theInstr );
10351c6bbd470e9bd9898b84959227a406d3972d95f3bsewardj   UChar frB_addr = ifieldRegB( theInstr );
10352c6bbd470e9bd9898b84959227a406d3972d95f3bsewardj   UChar flag_rC = ifieldBIT0( theInstr );
10353c6bbd470e9bd9898b84959227a406d3972d95f3bsewardj
10354c6bbd470e9bd9898b84959227a406d3972d95f3bsewardj   IRTemp frA = newTemp( Ity_D128 );
10355c6bbd470e9bd9898b84959227a406d3972d95f3bsewardj   IRTemp frB = newTemp( Ity_D128 );
10356c6bbd470e9bd9898b84959227a406d3972d95f3bsewardj   IRTemp frS = newTemp( Ity_D128 );
10357c6bbd470e9bd9898b84959227a406d3972d95f3bsewardj   IRExpr* round = get_IR_roundingmode_DFP();
10358c6bbd470e9bd9898b84959227a406d3972d95f3bsewardj
10359c6bbd470e9bd9898b84959227a406d3972d95f3bsewardj   /* By default, if flag_RC is set, we will clear cr1 after the
10360c6bbd470e9bd9898b84959227a406d3972d95f3bsewardj    * operation.  In reality we should set cr1 to indicate the
10361c6bbd470e9bd9898b84959227a406d3972d95f3bsewardj    * exception status of the operation, but since we're not
10362c6bbd470e9bd9898b84959227a406d3972d95f3bsewardj    * simulating exceptions, the exception status will appear to be
10363c6bbd470e9bd9898b84959227a406d3972d95f3bsewardj    * zero.  Hence cr1 should be cleared if this is a . form insn.
10364c6bbd470e9bd9898b84959227a406d3972d95f3bsewardj    */
10365c6bbd470e9bd9898b84959227a406d3972d95f3bsewardj   Bool clear_CR1 = True;
10366c6bbd470e9bd9898b84959227a406d3972d95f3bsewardj
10367c6bbd470e9bd9898b84959227a406d3972d95f3bsewardj   assign( frA, getDReg_pair( frA_addr ) );
10368c6bbd470e9bd9898b84959227a406d3972d95f3bsewardj   assign( frB, getDReg_pair( frB_addr ) );
10369c6bbd470e9bd9898b84959227a406d3972d95f3bsewardj
10370c6bbd470e9bd9898b84959227a406d3972d95f3bsewardj   switch (opc2) {
10371c6bbd470e9bd9898b84959227a406d3972d95f3bsewardj   case 0x2: // daddq
10372c6bbd470e9bd9898b84959227a406d3972d95f3bsewardj      DIP( "daddq%s fr%u,fr%u,fr%u\n",
10373c6bbd470e9bd9898b84959227a406d3972d95f3bsewardj           flag_rC ? ".":"", frS_addr, frA_addr, frB_addr );
10374c6bbd470e9bd9898b84959227a406d3972d95f3bsewardj      assign( frS, triop( Iop_AddD128, round, mkexpr( frA ), mkexpr( frB ) ) );
10375c6bbd470e9bd9898b84959227a406d3972d95f3bsewardj      break;
10376c6bbd470e9bd9898b84959227a406d3972d95f3bsewardj   case 0x202: // dsubq
10377c6bbd470e9bd9898b84959227a406d3972d95f3bsewardj      DIP( "dsubq%s fr%u,fr%u,fr%u\n",
10378c6bbd470e9bd9898b84959227a406d3972d95f3bsewardj           flag_rC ? ".":"", frS_addr, frA_addr, frB_addr );
10379c6bbd470e9bd9898b84959227a406d3972d95f3bsewardj      assign( frS, triop( Iop_SubD128, round, mkexpr( frA ), mkexpr( frB ) ) );
10380c6bbd470e9bd9898b84959227a406d3972d95f3bsewardj      break;
10381c6bbd470e9bd9898b84959227a406d3972d95f3bsewardj   case 0x22: // dmulq
10382c6bbd470e9bd9898b84959227a406d3972d95f3bsewardj      DIP( "dmulq%s fr%u,fr%u,fr%u\n",
10383c6bbd470e9bd9898b84959227a406d3972d95f3bsewardj           flag_rC ? ".":"", frS_addr, frA_addr, frB_addr );
10384c6bbd470e9bd9898b84959227a406d3972d95f3bsewardj      assign( frS, triop( Iop_MulD128, round, mkexpr( frA ), mkexpr( frB ) ) );
10385c6bbd470e9bd9898b84959227a406d3972d95f3bsewardj      break;
10386c6bbd470e9bd9898b84959227a406d3972d95f3bsewardj   case 0x222: // ddivq
10387c6bbd470e9bd9898b84959227a406d3972d95f3bsewardj      DIP( "ddivq%s fr%u,fr%u,fr%u\n",
10388c6bbd470e9bd9898b84959227a406d3972d95f3bsewardj           flag_rC ? ".":"", frS_addr, frA_addr, frB_addr );
10389c6bbd470e9bd9898b84959227a406d3972d95f3bsewardj      assign( frS, triop( Iop_DivD128, round, mkexpr( frA ), mkexpr( frB ) ) );
10390c6bbd470e9bd9898b84959227a406d3972d95f3bsewardj      break;
10391c6bbd470e9bd9898b84959227a406d3972d95f3bsewardj   }
10392c6bbd470e9bd9898b84959227a406d3972d95f3bsewardj
10393c6bbd470e9bd9898b84959227a406d3972d95f3bsewardj   putDReg_pair( frS_addr, mkexpr( frS ) );
10394c6bbd470e9bd9898b84959227a406d3972d95f3bsewardj
10395c6bbd470e9bd9898b84959227a406d3972d95f3bsewardj   if (flag_rC && clear_CR1) {
10396c6bbd470e9bd9898b84959227a406d3972d95f3bsewardj      putCR321( 1, mkU8( 0 ) );
10397c6bbd470e9bd9898b84959227a406d3972d95f3bsewardj      putCR0( 1, mkU8( 0 ) );
10398c6bbd470e9bd9898b84959227a406d3972d95f3bsewardj   }
10399c6bbd470e9bd9898b84959227a406d3972d95f3bsewardj
10400c6bbd470e9bd9898b84959227a406d3972d95f3bsewardj   return True;
10401c6bbd470e9bd9898b84959227a406d3972d95f3bsewardj}
10402e14bb9f862843c6b804097c124961b5567ded4f1sewardj
1040326217b09205cc1801b842ba5ba8f0d83aabca1b4sewardj/* DFP 64-bit logical shift instructions  */
1040426217b09205cc1801b842ba5ba8f0d83aabca1b4sewardjstatic Bool dis_dfp_shift(UInt theInstr) {
1040526217b09205cc1801b842ba5ba8f0d83aabca1b4sewardj   UInt opc2       = ifieldOPClo9( theInstr );
1040626217b09205cc1801b842ba5ba8f0d83aabca1b4sewardj   UChar frS_addr  = ifieldRegDS( theInstr );
1040726217b09205cc1801b842ba5ba8f0d83aabca1b4sewardj   UChar frA_addr  = ifieldRegA( theInstr );
1040826217b09205cc1801b842ba5ba8f0d83aabca1b4sewardj   UChar shift_val = IFIELD(theInstr, 10, 6);
1040926217b09205cc1801b842ba5ba8f0d83aabca1b4sewardj   UChar flag_rC   = ifieldBIT0( theInstr );
1041026217b09205cc1801b842ba5ba8f0d83aabca1b4sewardj
1041126217b09205cc1801b842ba5ba8f0d83aabca1b4sewardj   IRTemp frA = newTemp( Ity_D64 );
1041226217b09205cc1801b842ba5ba8f0d83aabca1b4sewardj   IRTemp frS = newTemp( Ity_D64 );
1041326217b09205cc1801b842ba5ba8f0d83aabca1b4sewardj   Bool clear_CR1 = True;
1041426217b09205cc1801b842ba5ba8f0d83aabca1b4sewardj
1041526217b09205cc1801b842ba5ba8f0d83aabca1b4sewardj   assign( frA, getDReg( frA_addr ) );
1041626217b09205cc1801b842ba5ba8f0d83aabca1b4sewardj
1041726217b09205cc1801b842ba5ba8f0d83aabca1b4sewardj   switch (opc2) {
1041826217b09205cc1801b842ba5ba8f0d83aabca1b4sewardj   case 0x42: // dscli
1041926217b09205cc1801b842ba5ba8f0d83aabca1b4sewardj      DIP( "dscli%s fr%u,fr%u,%u\n",
1042026217b09205cc1801b842ba5ba8f0d83aabca1b4sewardj           flag_rC ? ".":"", frS_addr, frA_addr, shift_val );
1042126217b09205cc1801b842ba5ba8f0d83aabca1b4sewardj      assign( frS, binop( Iop_ShlD64, mkexpr( frA ), mkU8( shift_val ) ) );
1042226217b09205cc1801b842ba5ba8f0d83aabca1b4sewardj      break;
1042326217b09205cc1801b842ba5ba8f0d83aabca1b4sewardj   case 0x62: // dscri
1042426217b09205cc1801b842ba5ba8f0d83aabca1b4sewardj      DIP( "dscri%s fr%u,fr%u,%u\n",
1042526217b09205cc1801b842ba5ba8f0d83aabca1b4sewardj           flag_rC ? ".":"", frS_addr, frA_addr, shift_val );
1042626217b09205cc1801b842ba5ba8f0d83aabca1b4sewardj      assign( frS, binop( Iop_ShrD64, mkexpr( frA ), mkU8( shift_val ) ) );
1042726217b09205cc1801b842ba5ba8f0d83aabca1b4sewardj      break;
1042826217b09205cc1801b842ba5ba8f0d83aabca1b4sewardj   }
1042926217b09205cc1801b842ba5ba8f0d83aabca1b4sewardj
1043026217b09205cc1801b842ba5ba8f0d83aabca1b4sewardj   putDReg( frS_addr, mkexpr( frS ) );
1043126217b09205cc1801b842ba5ba8f0d83aabca1b4sewardj
1043226217b09205cc1801b842ba5ba8f0d83aabca1b4sewardj   if (flag_rC && clear_CR1) {
1043326217b09205cc1801b842ba5ba8f0d83aabca1b4sewardj      putCR321( 1, mkU8( 0 ) );
1043426217b09205cc1801b842ba5ba8f0d83aabca1b4sewardj      putCR0( 1, mkU8( 0 ) );
1043526217b09205cc1801b842ba5ba8f0d83aabca1b4sewardj   }
1043626217b09205cc1801b842ba5ba8f0d83aabca1b4sewardj
1043726217b09205cc1801b842ba5ba8f0d83aabca1b4sewardj   return True;
1043826217b09205cc1801b842ba5ba8f0d83aabca1b4sewardj}
1043926217b09205cc1801b842ba5ba8f0d83aabca1b4sewardj
1044026217b09205cc1801b842ba5ba8f0d83aabca1b4sewardj/* Quad DFP  logical shift instructions  */
1044126217b09205cc1801b842ba5ba8f0d83aabca1b4sewardjstatic Bool dis_dfp_shiftq(UInt theInstr) {
1044226217b09205cc1801b842ba5ba8f0d83aabca1b4sewardj   UInt opc2       = ifieldOPClo9( theInstr );
1044326217b09205cc1801b842ba5ba8f0d83aabca1b4sewardj   UChar frS_addr  = ifieldRegDS( theInstr );
1044426217b09205cc1801b842ba5ba8f0d83aabca1b4sewardj   UChar frA_addr  = ifieldRegA( theInstr );
1044526217b09205cc1801b842ba5ba8f0d83aabca1b4sewardj   UChar shift_val = IFIELD(theInstr, 10, 6);
1044626217b09205cc1801b842ba5ba8f0d83aabca1b4sewardj   UChar flag_rC   = ifieldBIT0( theInstr );
1044726217b09205cc1801b842ba5ba8f0d83aabca1b4sewardj
1044826217b09205cc1801b842ba5ba8f0d83aabca1b4sewardj   IRTemp frA = newTemp( Ity_D128 );
1044926217b09205cc1801b842ba5ba8f0d83aabca1b4sewardj   IRTemp frS = newTemp( Ity_D128 );
1045026217b09205cc1801b842ba5ba8f0d83aabca1b4sewardj   Bool clear_CR1 = True;
1045126217b09205cc1801b842ba5ba8f0d83aabca1b4sewardj
1045226217b09205cc1801b842ba5ba8f0d83aabca1b4sewardj   assign( frA, getDReg_pair( frA_addr ) );
1045326217b09205cc1801b842ba5ba8f0d83aabca1b4sewardj
1045426217b09205cc1801b842ba5ba8f0d83aabca1b4sewardj   switch (opc2) {
1045526217b09205cc1801b842ba5ba8f0d83aabca1b4sewardj   case 0x42: // dscliq
1045626217b09205cc1801b842ba5ba8f0d83aabca1b4sewardj      DIP( "dscliq%s fr%u,fr%u,%u\n",
1045726217b09205cc1801b842ba5ba8f0d83aabca1b4sewardj           flag_rC ? ".":"", frS_addr, frA_addr, shift_val );
1045826217b09205cc1801b842ba5ba8f0d83aabca1b4sewardj      assign( frS, binop( Iop_ShlD128, mkexpr( frA ), mkU8( shift_val ) ) );
1045926217b09205cc1801b842ba5ba8f0d83aabca1b4sewardj      break;
1046026217b09205cc1801b842ba5ba8f0d83aabca1b4sewardj   case 0x62: // dscriq
1046126217b09205cc1801b842ba5ba8f0d83aabca1b4sewardj      DIP( "dscriq%s fr%u,fr%u,%u\n",
1046226217b09205cc1801b842ba5ba8f0d83aabca1b4sewardj           flag_rC ? ".":"", frS_addr, frA_addr, shift_val );
1046326217b09205cc1801b842ba5ba8f0d83aabca1b4sewardj      assign( frS, binop( Iop_ShrD128, mkexpr( frA ), mkU8( shift_val ) ) );
1046426217b09205cc1801b842ba5ba8f0d83aabca1b4sewardj      break;
1046526217b09205cc1801b842ba5ba8f0d83aabca1b4sewardj   }
1046626217b09205cc1801b842ba5ba8f0d83aabca1b4sewardj
1046726217b09205cc1801b842ba5ba8f0d83aabca1b4sewardj   putDReg_pair( frS_addr, mkexpr( frS ) );
1046826217b09205cc1801b842ba5ba8f0d83aabca1b4sewardj
1046926217b09205cc1801b842ba5ba8f0d83aabca1b4sewardj   if (flag_rC && clear_CR1) {
1047026217b09205cc1801b842ba5ba8f0d83aabca1b4sewardj      putCR321( 1, mkU8( 0 ) );
1047126217b09205cc1801b842ba5ba8f0d83aabca1b4sewardj      putCR0( 1, mkU8( 0 ) );
1047226217b09205cc1801b842ba5ba8f0d83aabca1b4sewardj   }
1047326217b09205cc1801b842ba5ba8f0d83aabca1b4sewardj
1047426217b09205cc1801b842ba5ba8f0d83aabca1b4sewardj   return True;
1047526217b09205cc1801b842ba5ba8f0d83aabca1b4sewardj}
1047626217b09205cc1801b842ba5ba8f0d83aabca1b4sewardj
1047726217b09205cc1801b842ba5ba8f0d83aabca1b4sewardj/* DFP 64-bit format conversion instructions */
1047826217b09205cc1801b842ba5ba8f0d83aabca1b4sewardjstatic Bool dis_dfp_fmt_conv(UInt theInstr) {
1047926217b09205cc1801b842ba5ba8f0d83aabca1b4sewardj   UInt opc2      = ifieldOPClo10( theInstr );
1048026217b09205cc1801b842ba5ba8f0d83aabca1b4sewardj   UChar frS_addr = ifieldRegDS( theInstr );
1048126217b09205cc1801b842ba5ba8f0d83aabca1b4sewardj   UChar frB_addr = ifieldRegB( theInstr );
1048226217b09205cc1801b842ba5ba8f0d83aabca1b4sewardj   IRExpr* round  = get_IR_roundingmode_DFP();
1048326217b09205cc1801b842ba5ba8f0d83aabca1b4sewardj   UChar flag_rC  = ifieldBIT0( theInstr );
1048426217b09205cc1801b842ba5ba8f0d83aabca1b4sewardj   IRTemp frB;
1048526217b09205cc1801b842ba5ba8f0d83aabca1b4sewardj   IRTemp frS;
1048626217b09205cc1801b842ba5ba8f0d83aabca1b4sewardj   Bool clear_CR1 = True;
1048726217b09205cc1801b842ba5ba8f0d83aabca1b4sewardj
1048826217b09205cc1801b842ba5ba8f0d83aabca1b4sewardj   switch (opc2) {
1048926217b09205cc1801b842ba5ba8f0d83aabca1b4sewardj   case 0x102: //dctdp
1049026217b09205cc1801b842ba5ba8f0d83aabca1b4sewardj      DIP( "dctdp%s fr%u,fr%u\n",
1049126217b09205cc1801b842ba5ba8f0d83aabca1b4sewardj           flag_rC ? ".":"", frS_addr, frB_addr );
1049226217b09205cc1801b842ba5ba8f0d83aabca1b4sewardj
10493f704eb2bab3d06d983c850b0bcf243e178060f75carll      frB = newTemp( Ity_D32 );
1049426217b09205cc1801b842ba5ba8f0d83aabca1b4sewardj      frS = newTemp( Ity_D64 );
10495f704eb2bab3d06d983c850b0bcf243e178060f75carll      assign( frB, getDReg32( frB_addr ) );
1049626217b09205cc1801b842ba5ba8f0d83aabca1b4sewardj      assign( frS, unop( Iop_D32toD64, mkexpr( frB ) ) );
1049726217b09205cc1801b842ba5ba8f0d83aabca1b4sewardj      putDReg( frS_addr, mkexpr( frS ) );
1049826217b09205cc1801b842ba5ba8f0d83aabca1b4sewardj      break;
1049926217b09205cc1801b842ba5ba8f0d83aabca1b4sewardj   case 0x302: // drsp
1050026217b09205cc1801b842ba5ba8f0d83aabca1b4sewardj      DIP( "drsp%s fr%u,fr%u\n",
1050126217b09205cc1801b842ba5ba8f0d83aabca1b4sewardj           flag_rC ? ".":"", frS_addr, frB_addr );
1050226217b09205cc1801b842ba5ba8f0d83aabca1b4sewardj      frB = newTemp( Ity_D64 );
10503f704eb2bab3d06d983c850b0bcf243e178060f75carll      frS = newTemp( Ity_D32 );
1050426217b09205cc1801b842ba5ba8f0d83aabca1b4sewardj      assign( frB, getDReg( frB_addr ) );
1050526217b09205cc1801b842ba5ba8f0d83aabca1b4sewardj      assign( frS, binop( Iop_D64toD32, round, mkexpr( frB ) ) );
10506f704eb2bab3d06d983c850b0bcf243e178060f75carll      putDReg32( frS_addr, mkexpr( frS ) );
1050726217b09205cc1801b842ba5ba8f0d83aabca1b4sewardj      break;
1050826217b09205cc1801b842ba5ba8f0d83aabca1b4sewardj   case 0x122: // dctfix
10509cea07ccbe9aa9b5fd8e9b318471c6c74aa147acbcarll      {
10510cea07ccbe9aa9b5fd8e9b318471c6c74aa147acbcarll         IRTemp tmp = newTemp( Ity_I64 );
10511cea07ccbe9aa9b5fd8e9b318471c6c74aa147acbcarll
10512cea07ccbe9aa9b5fd8e9b318471c6c74aa147acbcarll         DIP( "dctfix%s fr%u,fr%u\n",
10513cea07ccbe9aa9b5fd8e9b318471c6c74aa147acbcarll              flag_rC ? ".":"", frS_addr, frB_addr );
10514cea07ccbe9aa9b5fd8e9b318471c6c74aa147acbcarll         frB = newTemp( Ity_D64 );
10515cea07ccbe9aa9b5fd8e9b318471c6c74aa147acbcarll         frS = newTemp( Ity_D64 );
10516cea07ccbe9aa9b5fd8e9b318471c6c74aa147acbcarll         assign( frB, getDReg( frB_addr ) );
10517cea07ccbe9aa9b5fd8e9b318471c6c74aa147acbcarll         assign( tmp, binop( Iop_D64toI64S, round, mkexpr( frB ) ) );
10518cea07ccbe9aa9b5fd8e9b318471c6c74aa147acbcarll         assign( frS, unop( Iop_ReinterpI64asD64, mkexpr( tmp ) ) );
10519cea07ccbe9aa9b5fd8e9b318471c6c74aa147acbcarll         putDReg( frS_addr, mkexpr( frS ) );
10520cea07ccbe9aa9b5fd8e9b318471c6c74aa147acbcarll      }
1052126217b09205cc1801b842ba5ba8f0d83aabca1b4sewardj      break;
1052226217b09205cc1801b842ba5ba8f0d83aabca1b4sewardj   case 0x322: // dcffix
1052326217b09205cc1801b842ba5ba8f0d83aabca1b4sewardj      DIP( "dcffix%s fr%u,fr%u\n",
1052426217b09205cc1801b842ba5ba8f0d83aabca1b4sewardj           flag_rC ? ".":"", frS_addr, frB_addr );
1052526217b09205cc1801b842ba5ba8f0d83aabca1b4sewardj      frB = newTemp( Ity_D64 );
1052626217b09205cc1801b842ba5ba8f0d83aabca1b4sewardj      frS = newTemp( Ity_D64 );
1052726217b09205cc1801b842ba5ba8f0d83aabca1b4sewardj      assign( frB, getDReg( frB_addr ) );
10528cea07ccbe9aa9b5fd8e9b318471c6c74aa147acbcarll      assign( frS, binop( Iop_I64StoD64,
10529cea07ccbe9aa9b5fd8e9b318471c6c74aa147acbcarll                          round,
10530cea07ccbe9aa9b5fd8e9b318471c6c74aa147acbcarll                          unop( Iop_ReinterpD64asI64, mkexpr( frB ) ) ) );
1053126217b09205cc1801b842ba5ba8f0d83aabca1b4sewardj      putDReg( frS_addr, mkexpr( frS ) );
1053226217b09205cc1801b842ba5ba8f0d83aabca1b4sewardj      break;
1053326217b09205cc1801b842ba5ba8f0d83aabca1b4sewardj   }
1053426217b09205cc1801b842ba5ba8f0d83aabca1b4sewardj
1053526217b09205cc1801b842ba5ba8f0d83aabca1b4sewardj   if (flag_rC && clear_CR1) {
1053626217b09205cc1801b842ba5ba8f0d83aabca1b4sewardj      putCR321( 1, mkU8( 0 ) );
1053726217b09205cc1801b842ba5ba8f0d83aabca1b4sewardj      putCR0( 1, mkU8( 0 ) );
1053826217b09205cc1801b842ba5ba8f0d83aabca1b4sewardj   }
1053926217b09205cc1801b842ba5ba8f0d83aabca1b4sewardj
1054026217b09205cc1801b842ba5ba8f0d83aabca1b4sewardj   return True;
1054126217b09205cc1801b842ba5ba8f0d83aabca1b4sewardj}
1054226217b09205cc1801b842ba5ba8f0d83aabca1b4sewardj
1054326217b09205cc1801b842ba5ba8f0d83aabca1b4sewardj/* Quad DFP format conversion instructions */
1054426217b09205cc1801b842ba5ba8f0d83aabca1b4sewardjstatic Bool dis_dfp_fmt_convq(UInt theInstr) {
1054526217b09205cc1801b842ba5ba8f0d83aabca1b4sewardj   UInt opc2      = ifieldOPClo10( theInstr );
1054626217b09205cc1801b842ba5ba8f0d83aabca1b4sewardj   UChar frS_addr = ifieldRegDS( theInstr );
1054726217b09205cc1801b842ba5ba8f0d83aabca1b4sewardj   UChar frB_addr = ifieldRegB( theInstr );
1054826217b09205cc1801b842ba5ba8f0d83aabca1b4sewardj   IRExpr* round  = get_IR_roundingmode_DFP();
1054926217b09205cc1801b842ba5ba8f0d83aabca1b4sewardj   IRTemp frB64   = newTemp( Ity_D64 );
1055026217b09205cc1801b842ba5ba8f0d83aabca1b4sewardj   IRTemp frB128  = newTemp( Ity_D128 );
1055126217b09205cc1801b842ba5ba8f0d83aabca1b4sewardj   IRTemp frS64   = newTemp( Ity_D64 );
1055226217b09205cc1801b842ba5ba8f0d83aabca1b4sewardj   IRTemp frS128  = newTemp( Ity_D128 );
1055326217b09205cc1801b842ba5ba8f0d83aabca1b4sewardj   UChar flag_rC  = ifieldBIT0( theInstr );
1055426217b09205cc1801b842ba5ba8f0d83aabca1b4sewardj   Bool clear_CR1 = True;
1055526217b09205cc1801b842ba5ba8f0d83aabca1b4sewardj
1055626217b09205cc1801b842ba5ba8f0d83aabca1b4sewardj   switch (opc2) {
1055726217b09205cc1801b842ba5ba8f0d83aabca1b4sewardj   case 0x102: // dctqpq
1055826217b09205cc1801b842ba5ba8f0d83aabca1b4sewardj      DIP( "dctqpq%s fr%u,fr%u\n",
1055926217b09205cc1801b842ba5ba8f0d83aabca1b4sewardj           flag_rC ? ".":"", frS_addr, frB_addr );
1056026217b09205cc1801b842ba5ba8f0d83aabca1b4sewardj      assign( frB64, getDReg( frB_addr ) );
1056126217b09205cc1801b842ba5ba8f0d83aabca1b4sewardj      assign( frS128, unop( Iop_D64toD128, mkexpr( frB64 ) ) );
1056226217b09205cc1801b842ba5ba8f0d83aabca1b4sewardj      putDReg_pair( frS_addr, mkexpr( frS128 ) );
1056326217b09205cc1801b842ba5ba8f0d83aabca1b4sewardj      break;
1056426217b09205cc1801b842ba5ba8f0d83aabca1b4sewardj   case 0x122: // dctfixq
10565cea07ccbe9aa9b5fd8e9b318471c6c74aa147acbcarll      {
10566cea07ccbe9aa9b5fd8e9b318471c6c74aa147acbcarll         IRTemp tmp = newTemp( Ity_I64 );
10567cea07ccbe9aa9b5fd8e9b318471c6c74aa147acbcarll
10568cea07ccbe9aa9b5fd8e9b318471c6c74aa147acbcarll         DIP( "dctfixq%s fr%u,fr%u\n",
10569cea07ccbe9aa9b5fd8e9b318471c6c74aa147acbcarll              flag_rC ? ".":"", frS_addr, frB_addr );
10570cea07ccbe9aa9b5fd8e9b318471c6c74aa147acbcarll         assign( frB128, getDReg_pair( frB_addr ) );
10571cea07ccbe9aa9b5fd8e9b318471c6c74aa147acbcarll         assign( tmp, binop( Iop_D128toI64S, round, mkexpr( frB128 ) ) );
10572cea07ccbe9aa9b5fd8e9b318471c6c74aa147acbcarll         assign( frS64, unop( Iop_ReinterpI64asD64, mkexpr( tmp ) ) );
10573cea07ccbe9aa9b5fd8e9b318471c6c74aa147acbcarll         putDReg( frS_addr, mkexpr( frS64 ) );
10574cea07ccbe9aa9b5fd8e9b318471c6c74aa147acbcarll      }
1057526217b09205cc1801b842ba5ba8f0d83aabca1b4sewardj      break;
1057626217b09205cc1801b842ba5ba8f0d83aabca1b4sewardj   case 0x302: //drdpq
1057726217b09205cc1801b842ba5ba8f0d83aabca1b4sewardj      DIP( "drdpq%s fr%u,fr%u\n",
1057826217b09205cc1801b842ba5ba8f0d83aabca1b4sewardj           flag_rC ? ".":"", frS_addr, frB_addr );
1057926217b09205cc1801b842ba5ba8f0d83aabca1b4sewardj      assign( frB128, getDReg_pair( frB_addr ) );
1058026217b09205cc1801b842ba5ba8f0d83aabca1b4sewardj      assign( frS64, binop( Iop_D128toD64, round, mkexpr( frB128 ) ) );
1058126217b09205cc1801b842ba5ba8f0d83aabca1b4sewardj      putDReg( frS_addr, mkexpr( frS64 ) );
1058226217b09205cc1801b842ba5ba8f0d83aabca1b4sewardj      break;
1058326217b09205cc1801b842ba5ba8f0d83aabca1b4sewardj   case 0x322: // dcffixq
10584cea07ccbe9aa9b5fd8e9b318471c6c74aa147acbcarll     {
1058526217b09205cc1801b842ba5ba8f0d83aabca1b4sewardj      /* Have to introduce an IOP for this instruction so it will work
1058626217b09205cc1801b842ba5ba8f0d83aabca1b4sewardj       * on POWER 6 because emulating the instruction requires a POWER 7
1058726217b09205cc1801b842ba5ba8f0d83aabca1b4sewardj       * DFP instruction in the emulation code.
1058826217b09205cc1801b842ba5ba8f0d83aabca1b4sewardj       */
1058926217b09205cc1801b842ba5ba8f0d83aabca1b4sewardj      DIP( "dcffixq%s fr%u,fr%u\n",
1059026217b09205cc1801b842ba5ba8f0d83aabca1b4sewardj           flag_rC ? ".":"", frS_addr, frB_addr );
1059126217b09205cc1801b842ba5ba8f0d83aabca1b4sewardj      assign( frB64, getDReg( frB_addr ) );
10592cea07ccbe9aa9b5fd8e9b318471c6c74aa147acbcarll      assign( frS128, unop( Iop_I64StoD128,
10593cea07ccbe9aa9b5fd8e9b318471c6c74aa147acbcarll                            unop( Iop_ReinterpD64asI64,
10594cea07ccbe9aa9b5fd8e9b318471c6c74aa147acbcarll                                  mkexpr( frB64 ) ) ) );
1059526217b09205cc1801b842ba5ba8f0d83aabca1b4sewardj      putDReg_pair( frS_addr, mkexpr( frS128 ) );
1059626217b09205cc1801b842ba5ba8f0d83aabca1b4sewardj      break;
10597cea07ccbe9aa9b5fd8e9b318471c6c74aa147acbcarll     }
1059826217b09205cc1801b842ba5ba8f0d83aabca1b4sewardj   }
1059926217b09205cc1801b842ba5ba8f0d83aabca1b4sewardj
1060026217b09205cc1801b842ba5ba8f0d83aabca1b4sewardj   if (flag_rC && clear_CR1) {
1060126217b09205cc1801b842ba5ba8f0d83aabca1b4sewardj      putCR321( 1, mkU8( 0 ) );
1060226217b09205cc1801b842ba5ba8f0d83aabca1b4sewardj      putCR0( 1, mkU8( 0 ) );
1060326217b09205cc1801b842ba5ba8f0d83aabca1b4sewardj   }
1060426217b09205cc1801b842ba5ba8f0d83aabca1b4sewardj
1060526217b09205cc1801b842ba5ba8f0d83aabca1b4sewardj   return True;
1060626217b09205cc1801b842ba5ba8f0d83aabca1b4sewardj}
1060726217b09205cc1801b842ba5ba8f0d83aabca1b4sewardj
10608cdc376dcb5a4560b0a35d4abcb2146c499756f0dsewardjstatic Bool dis_dfp_round( UInt theInstr ) {
10609cdc376dcb5a4560b0a35d4abcb2146c499756f0dsewardj   UChar frS_addr = ifieldRegDS(theInstr);
10610cdc376dcb5a4560b0a35d4abcb2146c499756f0dsewardj   UChar R        = IFIELD(theInstr, 16, 1);
10611cdc376dcb5a4560b0a35d4abcb2146c499756f0dsewardj   UChar RMC      = IFIELD(theInstr, 9, 2);
10612cdc376dcb5a4560b0a35d4abcb2146c499756f0dsewardj   UChar frB_addr = ifieldRegB( theInstr );
10613cdc376dcb5a4560b0a35d4abcb2146c499756f0dsewardj   UChar flag_rC  = ifieldBIT0( theInstr );
10614cdc376dcb5a4560b0a35d4abcb2146c499756f0dsewardj   IRTemp frB     = newTemp( Ity_D64 );
10615cdc376dcb5a4560b0a35d4abcb2146c499756f0dsewardj   IRTemp frS     = newTemp( Ity_D64 );
10616cdc376dcb5a4560b0a35d4abcb2146c499756f0dsewardj   UInt opc2      = ifieldOPClo8( theInstr );
10617cdc376dcb5a4560b0a35d4abcb2146c499756f0dsewardj   Bool clear_CR1 = True;
10618cdc376dcb5a4560b0a35d4abcb2146c499756f0dsewardj
10619cdc376dcb5a4560b0a35d4abcb2146c499756f0dsewardj   switch (opc2) {
10620cdc376dcb5a4560b0a35d4abcb2146c499756f0dsewardj   /* drintn, is the same as drintx.  The only difference is this
10621cdc376dcb5a4560b0a35d4abcb2146c499756f0dsewardj    * instruction does not generate an exception for an inexact operation.
10622cdc376dcb5a4560b0a35d4abcb2146c499756f0dsewardj    * Currently not supporting inexact exceptions.
10623cdc376dcb5a4560b0a35d4abcb2146c499756f0dsewardj    */
10624cdc376dcb5a4560b0a35d4abcb2146c499756f0dsewardj   case 0x63: // drintx
10625cdc376dcb5a4560b0a35d4abcb2146c499756f0dsewardj   case 0xE3: // drintn
10626cdc376dcb5a4560b0a35d4abcb2146c499756f0dsewardj      DIP( "drintx/drintn%s fr%u,fr%u\n",
10627cdc376dcb5a4560b0a35d4abcb2146c499756f0dsewardj           flag_rC ? ".":"", frS_addr, frB_addr );
10628cdc376dcb5a4560b0a35d4abcb2146c499756f0dsewardj
10629cea07ccbe9aa9b5fd8e9b318471c6c74aa147acbcarll      /* NOTE, this instruction takes a DFP value and rounds to the
10630cea07ccbe9aa9b5fd8e9b318471c6c74aa147acbcarll       * neares floating point integer value, i.e. fractional part
10631cea07ccbe9aa9b5fd8e9b318471c6c74aa147acbcarll       * is zero.  The result is a floating point number.
10632cea07ccbe9aa9b5fd8e9b318471c6c74aa147acbcarll       */
10633cdc376dcb5a4560b0a35d4abcb2146c499756f0dsewardj      /* pass the value of R and RMC in the same field */
10634cdc376dcb5a4560b0a35d4abcb2146c499756f0dsewardj      assign( frB, getDReg( frB_addr ) );
10635cdc376dcb5a4560b0a35d4abcb2146c499756f0dsewardj      assign( frS, binop( Iop_RoundD64toInt,
10636cdc376dcb5a4560b0a35d4abcb2146c499756f0dsewardj                          mkU32( ( R << 3 ) | RMC ),
10637cdc376dcb5a4560b0a35d4abcb2146c499756f0dsewardj                          mkexpr( frB ) ) );
10638cdc376dcb5a4560b0a35d4abcb2146c499756f0dsewardj      putDReg( frS_addr, mkexpr( frS ) );
10639cdc376dcb5a4560b0a35d4abcb2146c499756f0dsewardj      break;
10640cdc376dcb5a4560b0a35d4abcb2146c499756f0dsewardj   default:
10641cdc376dcb5a4560b0a35d4abcb2146c499756f0dsewardj      vex_printf("dis_dfp_round(ppc)(opc2)\n");
10642cdc376dcb5a4560b0a35d4abcb2146c499756f0dsewardj      return False;
10643cdc376dcb5a4560b0a35d4abcb2146c499756f0dsewardj   }
10644cdc376dcb5a4560b0a35d4abcb2146c499756f0dsewardj
10645cdc376dcb5a4560b0a35d4abcb2146c499756f0dsewardj   if (flag_rC && clear_CR1) {
10646cdc376dcb5a4560b0a35d4abcb2146c499756f0dsewardj      putCR321( 1, mkU8( 0 ) );
10647cdc376dcb5a4560b0a35d4abcb2146c499756f0dsewardj      putCR0( 1, mkU8( 0 ) );
10648cdc376dcb5a4560b0a35d4abcb2146c499756f0dsewardj   }
10649cdc376dcb5a4560b0a35d4abcb2146c499756f0dsewardj
10650cdc376dcb5a4560b0a35d4abcb2146c499756f0dsewardj   return True;
10651cdc376dcb5a4560b0a35d4abcb2146c499756f0dsewardj}
10652cdc376dcb5a4560b0a35d4abcb2146c499756f0dsewardj
10653cdc376dcb5a4560b0a35d4abcb2146c499756f0dsewardjstatic Bool dis_dfp_roundq(UInt theInstr) {
10654cdc376dcb5a4560b0a35d4abcb2146c499756f0dsewardj   UChar frS_addr = ifieldRegDS( theInstr );
10655cdc376dcb5a4560b0a35d4abcb2146c499756f0dsewardj   UChar frB_addr = ifieldRegB( theInstr );
10656cdc376dcb5a4560b0a35d4abcb2146c499756f0dsewardj   UChar R = IFIELD(theInstr, 16, 1);
10657cdc376dcb5a4560b0a35d4abcb2146c499756f0dsewardj   UChar RMC = IFIELD(theInstr, 9, 2);
10658cdc376dcb5a4560b0a35d4abcb2146c499756f0dsewardj   UChar flag_rC = ifieldBIT0( theInstr );
10659cdc376dcb5a4560b0a35d4abcb2146c499756f0dsewardj   IRTemp frB = newTemp( Ity_D128 );
10660cdc376dcb5a4560b0a35d4abcb2146c499756f0dsewardj   IRTemp frS = newTemp( Ity_D128 );
10661cdc376dcb5a4560b0a35d4abcb2146c499756f0dsewardj   Bool clear_CR1 = True;
10662cdc376dcb5a4560b0a35d4abcb2146c499756f0dsewardj   UInt opc2 = ifieldOPClo8( theInstr );
10663cdc376dcb5a4560b0a35d4abcb2146c499756f0dsewardj
10664cdc376dcb5a4560b0a35d4abcb2146c499756f0dsewardj   switch (opc2) {
10665cdc376dcb5a4560b0a35d4abcb2146c499756f0dsewardj   /* drintnq, is the same as drintxq.  The only difference is this
10666cdc376dcb5a4560b0a35d4abcb2146c499756f0dsewardj    * instruction does not generate an exception for an inexact operation.
10667cdc376dcb5a4560b0a35d4abcb2146c499756f0dsewardj    * Currently not supporting inexact exceptions.
10668cdc376dcb5a4560b0a35d4abcb2146c499756f0dsewardj    */
10669cdc376dcb5a4560b0a35d4abcb2146c499756f0dsewardj   case 0x63: // drintxq
10670cdc376dcb5a4560b0a35d4abcb2146c499756f0dsewardj   case 0xE3: // drintnq
10671cdc376dcb5a4560b0a35d4abcb2146c499756f0dsewardj      DIP( "drintxq/drintnq%s fr%u,fr%u\n",
10672cdc376dcb5a4560b0a35d4abcb2146c499756f0dsewardj           flag_rC ? ".":"", frS_addr, frB_addr );
10673cdc376dcb5a4560b0a35d4abcb2146c499756f0dsewardj
10674cdc376dcb5a4560b0a35d4abcb2146c499756f0dsewardj      /* pass the value of R and RMC in the same field */
10675cdc376dcb5a4560b0a35d4abcb2146c499756f0dsewardj      assign( frB, getDReg_pair( frB_addr ) );
10676cdc376dcb5a4560b0a35d4abcb2146c499756f0dsewardj      assign( frS, binop( Iop_RoundD128toInt,
10677cdc376dcb5a4560b0a35d4abcb2146c499756f0dsewardj                          mkU32( ( R << 3 ) | RMC ),
10678cdc376dcb5a4560b0a35d4abcb2146c499756f0dsewardj                          mkexpr( frB ) ) );
10679cdc376dcb5a4560b0a35d4abcb2146c499756f0dsewardj      putDReg_pair( frS_addr, mkexpr( frS ) );
10680cdc376dcb5a4560b0a35d4abcb2146c499756f0dsewardj      break;
10681cdc376dcb5a4560b0a35d4abcb2146c499756f0dsewardj   default:
10682cdc376dcb5a4560b0a35d4abcb2146c499756f0dsewardj      vex_printf("dis_dfp_roundq(ppc)(opc2)\n");
10683cdc376dcb5a4560b0a35d4abcb2146c499756f0dsewardj      return False;
10684cdc376dcb5a4560b0a35d4abcb2146c499756f0dsewardj   }
10685cdc376dcb5a4560b0a35d4abcb2146c499756f0dsewardj
10686cdc376dcb5a4560b0a35d4abcb2146c499756f0dsewardj   if (flag_rC && clear_CR1) {
10687cdc376dcb5a4560b0a35d4abcb2146c499756f0dsewardj      putCR321( 1, mkU8( 0 ) );
10688cdc376dcb5a4560b0a35d4abcb2146c499756f0dsewardj      putCR0( 1, mkU8( 0 ) );
10689cdc376dcb5a4560b0a35d4abcb2146c499756f0dsewardj   }
10690cdc376dcb5a4560b0a35d4abcb2146c499756f0dsewardj
10691cdc376dcb5a4560b0a35d4abcb2146c499756f0dsewardj   return True;
10692cdc376dcb5a4560b0a35d4abcb2146c499756f0dsewardj}
10693cdc376dcb5a4560b0a35d4abcb2146c499756f0dsewardj
10694cdc376dcb5a4560b0a35d4abcb2146c499756f0dsewardjstatic Bool dis_dfp_quantize_sig_rrnd(UInt theInstr) {
10695cdc376dcb5a4560b0a35d4abcb2146c499756f0dsewardj   UInt opc2 = ifieldOPClo8( theInstr );
10696cdc376dcb5a4560b0a35d4abcb2146c499756f0dsewardj   UChar frS_addr = ifieldRegDS( theInstr );
10697cdc376dcb5a4560b0a35d4abcb2146c499756f0dsewardj   UChar frA_addr = ifieldRegA( theInstr );
10698cdc376dcb5a4560b0a35d4abcb2146c499756f0dsewardj   UChar frB_addr = ifieldRegB( theInstr );
10699cdc376dcb5a4560b0a35d4abcb2146c499756f0dsewardj   UChar flag_rC = ifieldBIT0( theInstr );
10700cdc376dcb5a4560b0a35d4abcb2146c499756f0dsewardj   UInt TE_value = IFIELD(theInstr, 16, 4);
10701cdc376dcb5a4560b0a35d4abcb2146c499756f0dsewardj   UInt TE_sign  = IFIELD(theInstr, 20, 1);
10702cdc376dcb5a4560b0a35d4abcb2146c499756f0dsewardj   UInt RMC = IFIELD(theInstr, 9, 2);
10703cdc376dcb5a4560b0a35d4abcb2146c499756f0dsewardj   IRTemp frA = newTemp( Ity_D64 );
10704cdc376dcb5a4560b0a35d4abcb2146c499756f0dsewardj   IRTemp frB = newTemp( Ity_D64 );
10705cdc376dcb5a4560b0a35d4abcb2146c499756f0dsewardj   IRTemp frS = newTemp( Ity_D64 );
10706cdc376dcb5a4560b0a35d4abcb2146c499756f0dsewardj   Bool clear_CR1 = True;
10707cdc376dcb5a4560b0a35d4abcb2146c499756f0dsewardj
10708cdc376dcb5a4560b0a35d4abcb2146c499756f0dsewardj   assign( frB, getDReg( frB_addr ) );
10709cdc376dcb5a4560b0a35d4abcb2146c499756f0dsewardj
10710cdc376dcb5a4560b0a35d4abcb2146c499756f0dsewardj   switch (opc2) {
10711cdc376dcb5a4560b0a35d4abcb2146c499756f0dsewardj   case 0x43: // dquai
10712cdc376dcb5a4560b0a35d4abcb2146c499756f0dsewardj      DIP( "dquai%s fr%u,fr%u,fr%u\n",
10713cdc376dcb5a4560b0a35d4abcb2146c499756f0dsewardj           flag_rC ? ".":"", frS_addr, frA_addr, frB_addr );
10714cea07ccbe9aa9b5fd8e9b318471c6c74aa147acbcarll      IRTemp TE_I64 = newTemp( Ity_I64 );
10715cdc376dcb5a4560b0a35d4abcb2146c499756f0dsewardj
10716cdc376dcb5a4560b0a35d4abcb2146c499756f0dsewardj      /* Generate a reference DFP value frA with the desired exponent
10717cdc376dcb5a4560b0a35d4abcb2146c499756f0dsewardj       * given by TE using significand from frB.  Need to add the bias
10718cdc376dcb5a4560b0a35d4abcb2146c499756f0dsewardj       * 398 to TE.  TE is stored as a 2's complement number.
10719cdc376dcb5a4560b0a35d4abcb2146c499756f0dsewardj       */
10720cdc376dcb5a4560b0a35d4abcb2146c499756f0dsewardj      if (TE_sign == 1) {
10721cdc376dcb5a4560b0a35d4abcb2146c499756f0dsewardj         /* Take 2's complement of the 5-bit value and subtract from bias.
10722cdc376dcb5a4560b0a35d4abcb2146c499756f0dsewardj          *  Bias is adjusted for the +1 required when taking 2's complement.
10723cdc376dcb5a4560b0a35d4abcb2146c499756f0dsewardj          */
10724cea07ccbe9aa9b5fd8e9b318471c6c74aa147acbcarll         assign( TE_I64,
10725cea07ccbe9aa9b5fd8e9b318471c6c74aa147acbcarll                 unop( Iop_32Uto64,
10726cea07ccbe9aa9b5fd8e9b318471c6c74aa147acbcarll                       binop( Iop_Sub32, mkU32( 397 ),
10727cea07ccbe9aa9b5fd8e9b318471c6c74aa147acbcarll                              binop( Iop_And32, mkU32( 0xF ),
10728cea07ccbe9aa9b5fd8e9b318471c6c74aa147acbcarll                                     unop( Iop_Not32, mkU32( TE_value ) )
10729cea07ccbe9aa9b5fd8e9b318471c6c74aa147acbcarll                                     ) ) ) );
10730cdc376dcb5a4560b0a35d4abcb2146c499756f0dsewardj
10731cdc376dcb5a4560b0a35d4abcb2146c499756f0dsewardj      } else {
10732cea07ccbe9aa9b5fd8e9b318471c6c74aa147acbcarll          assign( TE_I64,
10733cea07ccbe9aa9b5fd8e9b318471c6c74aa147acbcarll                  unop( Iop_32Uto64,
10734cea07ccbe9aa9b5fd8e9b318471c6c74aa147acbcarll                        binop( Iop_Add32, mkU32( 398 ), mkU32( TE_value ) )
10735cea07ccbe9aa9b5fd8e9b318471c6c74aa147acbcarll                        ) );
10736cdc376dcb5a4560b0a35d4abcb2146c499756f0dsewardj      }
10737cdc376dcb5a4560b0a35d4abcb2146c499756f0dsewardj
10738cea07ccbe9aa9b5fd8e9b318471c6c74aa147acbcarll      assign( frA, binop( Iop_InsertExpD64, mkexpr( TE_I64 ),
10739cdc376dcb5a4560b0a35d4abcb2146c499756f0dsewardj                          unop( Iop_ReinterpI64asD64, mkU64( 1 ) ) ) );
10740cdc376dcb5a4560b0a35d4abcb2146c499756f0dsewardj
10741cdc376dcb5a4560b0a35d4abcb2146c499756f0dsewardj      assign( frS, triop( Iop_QuantizeD64,
10742cdc376dcb5a4560b0a35d4abcb2146c499756f0dsewardj                          mkU32( RMC ),
10743cdc376dcb5a4560b0a35d4abcb2146c499756f0dsewardj                          mkexpr( frA ),
10744cdc376dcb5a4560b0a35d4abcb2146c499756f0dsewardj                          mkexpr( frB ) ) );
10745cdc376dcb5a4560b0a35d4abcb2146c499756f0dsewardj      break;
10746cdc376dcb5a4560b0a35d4abcb2146c499756f0dsewardj
10747cdc376dcb5a4560b0a35d4abcb2146c499756f0dsewardj   case 0x3: // dqua
10748cdc376dcb5a4560b0a35d4abcb2146c499756f0dsewardj      DIP( "dqua%s fr%u,fr%u,fr%u\n",
10749cdc376dcb5a4560b0a35d4abcb2146c499756f0dsewardj           flag_rC ? ".":"", frS_addr, frA_addr, frB_addr );
10750cdc376dcb5a4560b0a35d4abcb2146c499756f0dsewardj      assign( frA, getDReg( frA_addr ) );
10751cdc376dcb5a4560b0a35d4abcb2146c499756f0dsewardj      assign( frS, triop( Iop_QuantizeD64,
10752cdc376dcb5a4560b0a35d4abcb2146c499756f0dsewardj                          mkU32( RMC ),
10753cdc376dcb5a4560b0a35d4abcb2146c499756f0dsewardj                          mkexpr( frA ),
10754cdc376dcb5a4560b0a35d4abcb2146c499756f0dsewardj                          mkexpr( frB ) ) );
10755cdc376dcb5a4560b0a35d4abcb2146c499756f0dsewardj      break;
10756cdc376dcb5a4560b0a35d4abcb2146c499756f0dsewardj   case 0x23: // drrnd
10757cea07ccbe9aa9b5fd8e9b318471c6c74aa147acbcarll      {
10758cea07ccbe9aa9b5fd8e9b318471c6c74aa147acbcarll         IRTemp tmp = newTemp( Ity_I8 );
10759cea07ccbe9aa9b5fd8e9b318471c6c74aa147acbcarll
10760cea07ccbe9aa9b5fd8e9b318471c6c74aa147acbcarll         DIP( "drrnd%s fr%u,fr%u,fr%u\n",
10761cea07ccbe9aa9b5fd8e9b318471c6c74aa147acbcarll              flag_rC ? ".":"", frS_addr, frA_addr, frB_addr );
10762cea07ccbe9aa9b5fd8e9b318471c6c74aa147acbcarll         assign( frA, getDReg( frA_addr ) );
10763cea07ccbe9aa9b5fd8e9b318471c6c74aa147acbcarll         /* Iop_64to8 not supported in 32 bit mode, do it in two steps. */
10764cea07ccbe9aa9b5fd8e9b318471c6c74aa147acbcarll         assign( tmp, unop( Iop_32to8,
10765cea07ccbe9aa9b5fd8e9b318471c6c74aa147acbcarll                            unop( Iop_64to32,
10766cea07ccbe9aa9b5fd8e9b318471c6c74aa147acbcarll                                  unop( Iop_ReinterpD64asI64,
10767cea07ccbe9aa9b5fd8e9b318471c6c74aa147acbcarll                                        mkexpr( frA ) ) ) ) );
10768cea07ccbe9aa9b5fd8e9b318471c6c74aa147acbcarll         assign( frS, triop( Iop_SignificanceRoundD64,
10769cea07ccbe9aa9b5fd8e9b318471c6c74aa147acbcarll                             mkU32( RMC ),
10770cea07ccbe9aa9b5fd8e9b318471c6c74aa147acbcarll                             mkexpr( tmp ),
10771cea07ccbe9aa9b5fd8e9b318471c6c74aa147acbcarll                             mkexpr( frB ) ) );
10772cea07ccbe9aa9b5fd8e9b318471c6c74aa147acbcarll      }
10773cdc376dcb5a4560b0a35d4abcb2146c499756f0dsewardj      break;
10774cdc376dcb5a4560b0a35d4abcb2146c499756f0dsewardj   default:
10775cdc376dcb5a4560b0a35d4abcb2146c499756f0dsewardj      vex_printf("dis_dfp_quantize_sig_rrnd(ppc)(opc2)\n");
10776cdc376dcb5a4560b0a35d4abcb2146c499756f0dsewardj      return False;
10777cdc376dcb5a4560b0a35d4abcb2146c499756f0dsewardj   }
10778cdc376dcb5a4560b0a35d4abcb2146c499756f0dsewardj   putDReg( frS_addr, mkexpr( frS ) );
10779cdc376dcb5a4560b0a35d4abcb2146c499756f0dsewardj
10780cdc376dcb5a4560b0a35d4abcb2146c499756f0dsewardj   if (flag_rC && clear_CR1) {
10781cdc376dcb5a4560b0a35d4abcb2146c499756f0dsewardj      putCR321( 1, mkU8( 0 ) );
10782cdc376dcb5a4560b0a35d4abcb2146c499756f0dsewardj      putCR0( 1, mkU8( 0 ) );
10783cdc376dcb5a4560b0a35d4abcb2146c499756f0dsewardj   }
10784cdc376dcb5a4560b0a35d4abcb2146c499756f0dsewardj
10785cdc376dcb5a4560b0a35d4abcb2146c499756f0dsewardj   return True;
10786cdc376dcb5a4560b0a35d4abcb2146c499756f0dsewardj}
10787cdc376dcb5a4560b0a35d4abcb2146c499756f0dsewardj
10788cdc376dcb5a4560b0a35d4abcb2146c499756f0dsewardjstatic Bool dis_dfp_quantize_sig_rrndq(UInt theInstr) {
10789cdc376dcb5a4560b0a35d4abcb2146c499756f0dsewardj   UInt opc2 = ifieldOPClo8( theInstr );
10790cdc376dcb5a4560b0a35d4abcb2146c499756f0dsewardj   UChar frS_addr = ifieldRegDS( theInstr );
10791cdc376dcb5a4560b0a35d4abcb2146c499756f0dsewardj   UChar frA_addr = ifieldRegA( theInstr );
10792cdc376dcb5a4560b0a35d4abcb2146c499756f0dsewardj   UChar frB_addr = ifieldRegB( theInstr );
10793cdc376dcb5a4560b0a35d4abcb2146c499756f0dsewardj   UChar flag_rC = ifieldBIT0( theInstr );
10794cdc376dcb5a4560b0a35d4abcb2146c499756f0dsewardj   UInt TE_value = IFIELD(theInstr, 16, 4);
10795cdc376dcb5a4560b0a35d4abcb2146c499756f0dsewardj   UInt TE_sign  = IFIELD(theInstr, 20, 1);
10796cdc376dcb5a4560b0a35d4abcb2146c499756f0dsewardj   UInt RMC = IFIELD(theInstr, 9, 2);
10797cdc376dcb5a4560b0a35d4abcb2146c499756f0dsewardj   IRTemp frA = newTemp( Ity_D128 );
10798cdc376dcb5a4560b0a35d4abcb2146c499756f0dsewardj   IRTemp frB = newTemp( Ity_D128 );
10799cdc376dcb5a4560b0a35d4abcb2146c499756f0dsewardj   IRTemp frS = newTemp( Ity_D128 );
10800cdc376dcb5a4560b0a35d4abcb2146c499756f0dsewardj   Bool clear_CR1 = True;
10801cdc376dcb5a4560b0a35d4abcb2146c499756f0dsewardj
10802cdc376dcb5a4560b0a35d4abcb2146c499756f0dsewardj   assign( frB, getDReg_pair( frB_addr ) );
10803cdc376dcb5a4560b0a35d4abcb2146c499756f0dsewardj
10804cdc376dcb5a4560b0a35d4abcb2146c499756f0dsewardj   switch (opc2) {
10805cdc376dcb5a4560b0a35d4abcb2146c499756f0dsewardj   case 0x43: // dquaiq
10806cdc376dcb5a4560b0a35d4abcb2146c499756f0dsewardj      DIP( "dquaiq%s fr%u,fr%u,fr%u\n",
10807cdc376dcb5a4560b0a35d4abcb2146c499756f0dsewardj           flag_rC ? ".":"", frS_addr, frA_addr, frB_addr );
10808cea07ccbe9aa9b5fd8e9b318471c6c74aa147acbcarll      IRTemp TE_I64 = newTemp( Ity_I64 );
10809cdc376dcb5a4560b0a35d4abcb2146c499756f0dsewardj
10810cdc376dcb5a4560b0a35d4abcb2146c499756f0dsewardj      /* Generate a reference DFP value frA with the desired exponent
10811cdc376dcb5a4560b0a35d4abcb2146c499756f0dsewardj       * given by TE using significand of 1.  Need to add the bias
10812cdc376dcb5a4560b0a35d4abcb2146c499756f0dsewardj       * 6176 to TE.
10813cdc376dcb5a4560b0a35d4abcb2146c499756f0dsewardj       */
10814cdc376dcb5a4560b0a35d4abcb2146c499756f0dsewardj      if (TE_sign == 1) {
10815cdc376dcb5a4560b0a35d4abcb2146c499756f0dsewardj         /* Take 2's complement of the 5-bit value and subtract from bias.
10816cdc376dcb5a4560b0a35d4abcb2146c499756f0dsewardj          *  Bias adjusted for the +1 required when taking 2's complement.
10817cdc376dcb5a4560b0a35d4abcb2146c499756f0dsewardj          */
10818cea07ccbe9aa9b5fd8e9b318471c6c74aa147acbcarll         assign( TE_I64,
10819cea07ccbe9aa9b5fd8e9b318471c6c74aa147acbcarll                 unop( Iop_32Uto64,
10820cea07ccbe9aa9b5fd8e9b318471c6c74aa147acbcarll                       binop( Iop_Sub32, mkU32( 6175 ),
10821cea07ccbe9aa9b5fd8e9b318471c6c74aa147acbcarll                              binop( Iop_And32, mkU32( 0xF ),
10822cea07ccbe9aa9b5fd8e9b318471c6c74aa147acbcarll                                     unop( Iop_Not32, mkU32( TE_value ) )
10823cea07ccbe9aa9b5fd8e9b318471c6c74aa147acbcarll                                     ) ) ) );
10824cdc376dcb5a4560b0a35d4abcb2146c499756f0dsewardj
10825cdc376dcb5a4560b0a35d4abcb2146c499756f0dsewardj      } else {
10826cea07ccbe9aa9b5fd8e9b318471c6c74aa147acbcarll         assign( TE_I64,
10827cea07ccbe9aa9b5fd8e9b318471c6c74aa147acbcarll                 unop( Iop_32Uto64,
10828cea07ccbe9aa9b5fd8e9b318471c6c74aa147acbcarll                       binop( Iop_Add32,
10829cea07ccbe9aa9b5fd8e9b318471c6c74aa147acbcarll                             mkU32( 6176 ),
10830cea07ccbe9aa9b5fd8e9b318471c6c74aa147acbcarll                             mkU32( TE_value ) ) ) );
10831cdc376dcb5a4560b0a35d4abcb2146c499756f0dsewardj      }
10832cdc376dcb5a4560b0a35d4abcb2146c499756f0dsewardj
10833cdc376dcb5a4560b0a35d4abcb2146c499756f0dsewardj      assign( frA,
10834cea07ccbe9aa9b5fd8e9b318471c6c74aa147acbcarll              binop( Iop_InsertExpD128, mkexpr( TE_I64 ),
10835cea07ccbe9aa9b5fd8e9b318471c6c74aa147acbcarll                     unop( Iop_D64toD128,
10836cdc376dcb5a4560b0a35d4abcb2146c499756f0dsewardj                           unop( Iop_ReinterpI64asD64, mkU64( 1 ) ) ) ) );
10837cdc376dcb5a4560b0a35d4abcb2146c499756f0dsewardj      assign( frS, triop( Iop_QuantizeD128,
10838cdc376dcb5a4560b0a35d4abcb2146c499756f0dsewardj                          mkU32( RMC ),
10839cdc376dcb5a4560b0a35d4abcb2146c499756f0dsewardj                          mkexpr( frA ),
10840cdc376dcb5a4560b0a35d4abcb2146c499756f0dsewardj                          mkexpr( frB ) ) );
10841cdc376dcb5a4560b0a35d4abcb2146c499756f0dsewardj      break;
10842cdc376dcb5a4560b0a35d4abcb2146c499756f0dsewardj   case 0x3: // dquaq
10843cdc376dcb5a4560b0a35d4abcb2146c499756f0dsewardj      DIP( "dquaiq%s fr%u,fr%u,fr%u\n",
10844cdc376dcb5a4560b0a35d4abcb2146c499756f0dsewardj           flag_rC ? ".":"", frS_addr, frA_addr, frB_addr );
10845cdc376dcb5a4560b0a35d4abcb2146c499756f0dsewardj      assign( frA, getDReg_pair( frA_addr ) );
10846cdc376dcb5a4560b0a35d4abcb2146c499756f0dsewardj      assign( frS, triop( Iop_QuantizeD128,
10847cdc376dcb5a4560b0a35d4abcb2146c499756f0dsewardj                          mkU32( RMC ),
10848cdc376dcb5a4560b0a35d4abcb2146c499756f0dsewardj                          mkexpr( frA ),
10849cdc376dcb5a4560b0a35d4abcb2146c499756f0dsewardj                          mkexpr( frB ) ) );
10850cdc376dcb5a4560b0a35d4abcb2146c499756f0dsewardj      break;
10851cdc376dcb5a4560b0a35d4abcb2146c499756f0dsewardj   case 0x23: // drrndq
10852cea07ccbe9aa9b5fd8e9b318471c6c74aa147acbcarll      {
10853cea07ccbe9aa9b5fd8e9b318471c6c74aa147acbcarll         IRTemp tmp = newTemp( Ity_I8 );
10854cea07ccbe9aa9b5fd8e9b318471c6c74aa147acbcarll
10855cea07ccbe9aa9b5fd8e9b318471c6c74aa147acbcarll         DIP( "drrndq%s fr%u,fr%u,fr%u\n",
10856cea07ccbe9aa9b5fd8e9b318471c6c74aa147acbcarll              flag_rC ? ".":"", frS_addr, frA_addr, frB_addr );
10857cea07ccbe9aa9b5fd8e9b318471c6c74aa147acbcarll         assign( frA, getDReg_pair( frA_addr ) );
10858cea07ccbe9aa9b5fd8e9b318471c6c74aa147acbcarll         assign( tmp, unop( Iop_32to8,
10859cea07ccbe9aa9b5fd8e9b318471c6c74aa147acbcarll                            unop( Iop_64to32,
10860cea07ccbe9aa9b5fd8e9b318471c6c74aa147acbcarll                                  unop( Iop_ReinterpD64asI64,
10861cea07ccbe9aa9b5fd8e9b318471c6c74aa147acbcarll                                        unop( Iop_D128HItoD64,
10862cea07ccbe9aa9b5fd8e9b318471c6c74aa147acbcarll                                              mkexpr( frA ) ) ) ) ) );
10863cea07ccbe9aa9b5fd8e9b318471c6c74aa147acbcarll         assign( frS, triop( Iop_SignificanceRoundD128,
10864cea07ccbe9aa9b5fd8e9b318471c6c74aa147acbcarll                             mkU32( RMC ),
10865cea07ccbe9aa9b5fd8e9b318471c6c74aa147acbcarll                             mkexpr( tmp ),
10866cea07ccbe9aa9b5fd8e9b318471c6c74aa147acbcarll                             mkexpr( frB ) ) );
10867cea07ccbe9aa9b5fd8e9b318471c6c74aa147acbcarll      }
10868cdc376dcb5a4560b0a35d4abcb2146c499756f0dsewardj      break;
10869cdc376dcb5a4560b0a35d4abcb2146c499756f0dsewardj   default:
10870cdc376dcb5a4560b0a35d4abcb2146c499756f0dsewardj      vex_printf("dis_dfp_quantize_sig_rrndq(ppc)(opc2)\n");
10871cdc376dcb5a4560b0a35d4abcb2146c499756f0dsewardj      return False;
10872cdc376dcb5a4560b0a35d4abcb2146c499756f0dsewardj   }
10873cdc376dcb5a4560b0a35d4abcb2146c499756f0dsewardj   putDReg_pair( frS_addr, mkexpr( frS ) );
10874cdc376dcb5a4560b0a35d4abcb2146c499756f0dsewardj
10875cdc376dcb5a4560b0a35d4abcb2146c499756f0dsewardj   if (flag_rC && clear_CR1) {
10876cdc376dcb5a4560b0a35d4abcb2146c499756f0dsewardj      putCR321( 1, mkU8( 0 ) );
10877cdc376dcb5a4560b0a35d4abcb2146c499756f0dsewardj      putCR0( 1, mkU8( 0 ) );
10878cdc376dcb5a4560b0a35d4abcb2146c499756f0dsewardj   }
10879cdc376dcb5a4560b0a35d4abcb2146c499756f0dsewardj
10880cdc376dcb5a4560b0a35d4abcb2146c499756f0dsewardj   return True;
10881cdc376dcb5a4560b0a35d4abcb2146c499756f0dsewardj}
10882cdc376dcb5a4560b0a35d4abcb2146c499756f0dsewardj
10883cdc376dcb5a4560b0a35d4abcb2146c499756f0dsewardjstatic Bool dis_dfp_extract_insert(UInt theInstr) {
10884cdc376dcb5a4560b0a35d4abcb2146c499756f0dsewardj   UInt opc2 = ifieldOPClo10( theInstr );
10885cdc376dcb5a4560b0a35d4abcb2146c499756f0dsewardj   UChar frS_addr = ifieldRegDS( theInstr );
10886cdc376dcb5a4560b0a35d4abcb2146c499756f0dsewardj   UChar frA_addr = ifieldRegA( theInstr );
10887cdc376dcb5a4560b0a35d4abcb2146c499756f0dsewardj   UChar frB_addr = ifieldRegB( theInstr );
10888cdc376dcb5a4560b0a35d4abcb2146c499756f0dsewardj   UChar flag_rC = ifieldBIT0( theInstr );
10889cdc376dcb5a4560b0a35d4abcb2146c499756f0dsewardj   Bool clear_CR1 = True;
10890cdc376dcb5a4560b0a35d4abcb2146c499756f0dsewardj
10891cdc376dcb5a4560b0a35d4abcb2146c499756f0dsewardj   IRTemp frA = newTemp( Ity_D64 );
10892cdc376dcb5a4560b0a35d4abcb2146c499756f0dsewardj   IRTemp frB = newTemp( Ity_D64 );
10893cdc376dcb5a4560b0a35d4abcb2146c499756f0dsewardj   IRTemp frS = newTemp( Ity_D64 );
10894cea07ccbe9aa9b5fd8e9b318471c6c74aa147acbcarll   IRTemp tmp = newTemp( Ity_I64 );
10895cdc376dcb5a4560b0a35d4abcb2146c499756f0dsewardj
10896cdc376dcb5a4560b0a35d4abcb2146c499756f0dsewardj   assign( frA, getDReg( frA_addr ) );
10897cdc376dcb5a4560b0a35d4abcb2146c499756f0dsewardj   assign( frB, getDReg( frB_addr ) );
10898cdc376dcb5a4560b0a35d4abcb2146c499756f0dsewardj
10899cdc376dcb5a4560b0a35d4abcb2146c499756f0dsewardj   switch (opc2) {
10900cdc376dcb5a4560b0a35d4abcb2146c499756f0dsewardj   case 0x162: // dxex
10901cdc376dcb5a4560b0a35d4abcb2146c499756f0dsewardj      DIP( "dxex%s fr%u,fr%u,fr%u\n",
10902cdc376dcb5a4560b0a35d4abcb2146c499756f0dsewardj           flag_rC ? ".":"", frS_addr, frA_addr, frB_addr );
10903cea07ccbe9aa9b5fd8e9b318471c6c74aa147acbcarll      assign( tmp, unop( Iop_ExtractExpD64, mkexpr( frB ) ) );
10904cea07ccbe9aa9b5fd8e9b318471c6c74aa147acbcarll      assign( frS, unop( Iop_ReinterpI64asD64, mkexpr( tmp ) ) );
10905cdc376dcb5a4560b0a35d4abcb2146c499756f0dsewardj      break;
10906cdc376dcb5a4560b0a35d4abcb2146c499756f0dsewardj   case 0x362: // diex
10907cdc376dcb5a4560b0a35d4abcb2146c499756f0dsewardj      DIP( "diex%s fr%u,fr%u,fr%u\n",
10908cdc376dcb5a4560b0a35d4abcb2146c499756f0dsewardj           flag_rC ? ".":"", frS_addr, frA_addr, frB_addr );
10909cea07ccbe9aa9b5fd8e9b318471c6c74aa147acbcarll      assign( frS, binop( Iop_InsertExpD64,
10910cea07ccbe9aa9b5fd8e9b318471c6c74aa147acbcarll                          unop( Iop_ReinterpD64asI64,
10911cea07ccbe9aa9b5fd8e9b318471c6c74aa147acbcarll                                mkexpr( frA ) ),
10912cea07ccbe9aa9b5fd8e9b318471c6c74aa147acbcarll                          mkexpr( frB ) ) );
10913cdc376dcb5a4560b0a35d4abcb2146c499756f0dsewardj      break;
10914cdc376dcb5a4560b0a35d4abcb2146c499756f0dsewardj   default:
10915cdc376dcb5a4560b0a35d4abcb2146c499756f0dsewardj      vex_printf("dis_dfp_extract_insert(ppc)(opc2)\n");
10916cdc376dcb5a4560b0a35d4abcb2146c499756f0dsewardj      return False;
10917cdc376dcb5a4560b0a35d4abcb2146c499756f0dsewardj   }
10918cdc376dcb5a4560b0a35d4abcb2146c499756f0dsewardj
10919cdc376dcb5a4560b0a35d4abcb2146c499756f0dsewardj   putDReg( frS_addr, mkexpr( frS ) );
10920cdc376dcb5a4560b0a35d4abcb2146c499756f0dsewardj
10921cdc376dcb5a4560b0a35d4abcb2146c499756f0dsewardj   if (flag_rC && clear_CR1) {
10922cdc376dcb5a4560b0a35d4abcb2146c499756f0dsewardj      putCR321( 1, mkU8( 0 ) );
10923cdc376dcb5a4560b0a35d4abcb2146c499756f0dsewardj      putCR0( 1, mkU8( 0 ) );
10924cdc376dcb5a4560b0a35d4abcb2146c499756f0dsewardj   }
10925cdc376dcb5a4560b0a35d4abcb2146c499756f0dsewardj
10926cdc376dcb5a4560b0a35d4abcb2146c499756f0dsewardj   return True;
10927cdc376dcb5a4560b0a35d4abcb2146c499756f0dsewardj}
10928cdc376dcb5a4560b0a35d4abcb2146c499756f0dsewardj
10929cdc376dcb5a4560b0a35d4abcb2146c499756f0dsewardjstatic Bool dis_dfp_extract_insertq(UInt theInstr) {
10930cdc376dcb5a4560b0a35d4abcb2146c499756f0dsewardj   UInt opc2 = ifieldOPClo10( theInstr );
10931cdc376dcb5a4560b0a35d4abcb2146c499756f0dsewardj   UChar frS_addr = ifieldRegDS( theInstr );
10932cdc376dcb5a4560b0a35d4abcb2146c499756f0dsewardj   UChar frA_addr = ifieldRegA( theInstr );
10933cdc376dcb5a4560b0a35d4abcb2146c499756f0dsewardj   UChar frB_addr = ifieldRegB( theInstr );
10934cdc376dcb5a4560b0a35d4abcb2146c499756f0dsewardj   UChar flag_rC = ifieldBIT0( theInstr );
10935cdc376dcb5a4560b0a35d4abcb2146c499756f0dsewardj
10936cdc376dcb5a4560b0a35d4abcb2146c499756f0dsewardj   IRTemp frA   = newTemp( Ity_D64 );
10937cdc376dcb5a4560b0a35d4abcb2146c499756f0dsewardj   IRTemp frB   = newTemp( Ity_D128 );
10938cdc376dcb5a4560b0a35d4abcb2146c499756f0dsewardj   IRTemp frS64 = newTemp( Ity_D64 );
10939cdc376dcb5a4560b0a35d4abcb2146c499756f0dsewardj   IRTemp frS   = newTemp( Ity_D128 );
10940cea07ccbe9aa9b5fd8e9b318471c6c74aa147acbcarll   IRTemp tmp   = newTemp( Ity_I64 );
10941cdc376dcb5a4560b0a35d4abcb2146c499756f0dsewardj   Bool clear_CR1 = True;
10942cdc376dcb5a4560b0a35d4abcb2146c499756f0dsewardj
10943cdc376dcb5a4560b0a35d4abcb2146c499756f0dsewardj   assign( frB, getDReg_pair( frB_addr ) );
10944cdc376dcb5a4560b0a35d4abcb2146c499756f0dsewardj
10945cdc376dcb5a4560b0a35d4abcb2146c499756f0dsewardj   switch (opc2) {
10946cdc376dcb5a4560b0a35d4abcb2146c499756f0dsewardj   case 0x162:  // dxexq
10947cdc376dcb5a4560b0a35d4abcb2146c499756f0dsewardj      DIP( "dxexq%s fr%u,fr%u\n",
10948cdc376dcb5a4560b0a35d4abcb2146c499756f0dsewardj           flag_rC ? ".":"", frS_addr,  frB_addr );
10949cdc376dcb5a4560b0a35d4abcb2146c499756f0dsewardj      /* Instruction actually returns a 64-bit result.  So as to be
10950cdc376dcb5a4560b0a35d4abcb2146c499756f0dsewardj       * consistent and not have to add a new struct, the emulation returns
10951cdc376dcb5a4560b0a35d4abcb2146c499756f0dsewardj       * the 64-bit result in the upper and lower register.
10952cdc376dcb5a4560b0a35d4abcb2146c499756f0dsewardj       */
10953cea07ccbe9aa9b5fd8e9b318471c6c74aa147acbcarll      assign( tmp, unop( Iop_ExtractExpD128, mkexpr( frB ) ) );
10954cea07ccbe9aa9b5fd8e9b318471c6c74aa147acbcarll      assign( frS64, unop( Iop_ReinterpI64asD64, mkexpr( tmp ) ) );
10955cdc376dcb5a4560b0a35d4abcb2146c499756f0dsewardj      putDReg( frS_addr, mkexpr( frS64 ) );
10956cdc376dcb5a4560b0a35d4abcb2146c499756f0dsewardj      break;
10957cdc376dcb5a4560b0a35d4abcb2146c499756f0dsewardj   case 0x362:  // diexq
10958cdc376dcb5a4560b0a35d4abcb2146c499756f0dsewardj      DIP( "diexq%s fr%u,fr%u,fr%u\n",
10959cdc376dcb5a4560b0a35d4abcb2146c499756f0dsewardj           flag_rC ? ".":"", frS_addr, frA_addr, frB_addr );
10960cdc376dcb5a4560b0a35d4abcb2146c499756f0dsewardj      assign( frA, getDReg( frA_addr ) );
10961cea07ccbe9aa9b5fd8e9b318471c6c74aa147acbcarll      assign( frS, binop( Iop_InsertExpD128,
10962cea07ccbe9aa9b5fd8e9b318471c6c74aa147acbcarll                          unop( Iop_ReinterpD64asI64, mkexpr( frA ) ),
10963cea07ccbe9aa9b5fd8e9b318471c6c74aa147acbcarll                          mkexpr( frB ) ) );
10964cdc376dcb5a4560b0a35d4abcb2146c499756f0dsewardj      putDReg_pair( frS_addr, mkexpr( frS ) );
10965cdc376dcb5a4560b0a35d4abcb2146c499756f0dsewardj      break;
10966cdc376dcb5a4560b0a35d4abcb2146c499756f0dsewardj   default:
10967cdc376dcb5a4560b0a35d4abcb2146c499756f0dsewardj      vex_printf("dis_dfp_extract_insertq(ppc)(opc2)\n");
10968cdc376dcb5a4560b0a35d4abcb2146c499756f0dsewardj      return False;
10969cdc376dcb5a4560b0a35d4abcb2146c499756f0dsewardj   }
10970cdc376dcb5a4560b0a35d4abcb2146c499756f0dsewardj
10971cdc376dcb5a4560b0a35d4abcb2146c499756f0dsewardj   if (flag_rC && clear_CR1) {
10972cdc376dcb5a4560b0a35d4abcb2146c499756f0dsewardj      putCR321( 1, mkU8( 0 ) );
10973cdc376dcb5a4560b0a35d4abcb2146c499756f0dsewardj      putCR0( 1, mkU8( 0 ) );
10974cdc376dcb5a4560b0a35d4abcb2146c499756f0dsewardj   }
10975cdc376dcb5a4560b0a35d4abcb2146c499756f0dsewardj
10976cdc376dcb5a4560b0a35d4abcb2146c499756f0dsewardj   return True;
10977cdc376dcb5a4560b0a35d4abcb2146c499756f0dsewardj}
10978cdc376dcb5a4560b0a35d4abcb2146c499756f0dsewardj
10979cdc376dcb5a4560b0a35d4abcb2146c499756f0dsewardj/* DFP 64-bit comparison instructions */
10980cdc376dcb5a4560b0a35d4abcb2146c499756f0dsewardjstatic Bool dis_dfp_compare(UInt theInstr) {
10981cdc376dcb5a4560b0a35d4abcb2146c499756f0dsewardj   /* X-Form */
10982cdc376dcb5a4560b0a35d4abcb2146c499756f0dsewardj   UChar crfD = toUChar( IFIELD( theInstr, 23, 3 ) ); // AKA BF
10983cdc376dcb5a4560b0a35d4abcb2146c499756f0dsewardj   UChar frA_addr = ifieldRegA( theInstr );
10984cdc376dcb5a4560b0a35d4abcb2146c499756f0dsewardj   UChar frB_addr = ifieldRegB( theInstr );
10985cdc376dcb5a4560b0a35d4abcb2146c499756f0dsewardj   UInt opc1 = ifieldOPC( theInstr );
10986cdc376dcb5a4560b0a35d4abcb2146c499756f0dsewardj   IRTemp frA;
10987cdc376dcb5a4560b0a35d4abcb2146c499756f0dsewardj   IRTemp frB;
10988cdc376dcb5a4560b0a35d4abcb2146c499756f0dsewardj
10989cdc376dcb5a4560b0a35d4abcb2146c499756f0dsewardj   IRTemp ccIR = newTemp( Ity_I32 );
10990cdc376dcb5a4560b0a35d4abcb2146c499756f0dsewardj   IRTemp ccPPC32 = newTemp( Ity_I32 );
10991cdc376dcb5a4560b0a35d4abcb2146c499756f0dsewardj
10992cdc376dcb5a4560b0a35d4abcb2146c499756f0dsewardj
10993cdc376dcb5a4560b0a35d4abcb2146c499756f0dsewardj   /* Note: Differences between dcmpu and dcmpo are only in exception
10994cdc376dcb5a4560b0a35d4abcb2146c499756f0dsewardj    flag settings, which aren't supported anyway. */
10995cdc376dcb5a4560b0a35d4abcb2146c499756f0dsewardj   switch (opc1) {
10996cdc376dcb5a4560b0a35d4abcb2146c499756f0dsewardj   case 0x3B: /* dcmpo and dcmpu, DFP 64-bit */
10997cdc376dcb5a4560b0a35d4abcb2146c499756f0dsewardj      DIP( "dcmpo %u,fr%u,fr%u\n", crfD, frA_addr, frB_addr );
10998cdc376dcb5a4560b0a35d4abcb2146c499756f0dsewardj      frA = newTemp( Ity_D64 );
10999cdc376dcb5a4560b0a35d4abcb2146c499756f0dsewardj      frB = newTemp( Ity_D64 );
11000cdc376dcb5a4560b0a35d4abcb2146c499756f0dsewardj
11001cdc376dcb5a4560b0a35d4abcb2146c499756f0dsewardj      assign( frA, getDReg( frA_addr ) );
11002cdc376dcb5a4560b0a35d4abcb2146c499756f0dsewardj      assign( frB, getDReg( frB_addr ) );
11003cdc376dcb5a4560b0a35d4abcb2146c499756f0dsewardj
11004cdc376dcb5a4560b0a35d4abcb2146c499756f0dsewardj      assign( ccIR, binop( Iop_CmpD64, mkexpr( frA ), mkexpr( frB ) ) );
11005cdc376dcb5a4560b0a35d4abcb2146c499756f0dsewardj      break;
11006cdc376dcb5a4560b0a35d4abcb2146c499756f0dsewardj   case 0x3F: /* dcmpoq and dcmpuq,DFP 128-bit */
11007cdc376dcb5a4560b0a35d4abcb2146c499756f0dsewardj      DIP( "dcmpoq %u,fr%u,fr%u\n", crfD, frA_addr, frB_addr );
11008cdc376dcb5a4560b0a35d4abcb2146c499756f0dsewardj      frA = newTemp( Ity_D128 );
11009cdc376dcb5a4560b0a35d4abcb2146c499756f0dsewardj      frB = newTemp( Ity_D128 );
11010cdc376dcb5a4560b0a35d4abcb2146c499756f0dsewardj
11011cdc376dcb5a4560b0a35d4abcb2146c499756f0dsewardj      assign( frA, getDReg_pair( frA_addr ) );
11012cdc376dcb5a4560b0a35d4abcb2146c499756f0dsewardj      assign( frB, getDReg_pair( frB_addr ) );
11013cdc376dcb5a4560b0a35d4abcb2146c499756f0dsewardj      assign( ccIR, binop( Iop_CmpD128, mkexpr( frA ), mkexpr( frB ) ) );
11014cdc376dcb5a4560b0a35d4abcb2146c499756f0dsewardj      break;
11015cdc376dcb5a4560b0a35d4abcb2146c499756f0dsewardj   default:
11016cdc376dcb5a4560b0a35d4abcb2146c499756f0dsewardj      vex_printf("dis_dfp_compare(ppc)(opc2)\n");
11017cdc376dcb5a4560b0a35d4abcb2146c499756f0dsewardj      return False;
11018cdc376dcb5a4560b0a35d4abcb2146c499756f0dsewardj   }
11019cdc376dcb5a4560b0a35d4abcb2146c499756f0dsewardj
11020cdc376dcb5a4560b0a35d4abcb2146c499756f0dsewardj   /* Map compare result from IR to PPC32 */
11021cdc376dcb5a4560b0a35d4abcb2146c499756f0dsewardj   /*
11022cdc376dcb5a4560b0a35d4abcb2146c499756f0dsewardj    FP cmp result | PPC | IR
11023cdc376dcb5a4560b0a35d4abcb2146c499756f0dsewardj    --------------------------
11024cdc376dcb5a4560b0a35d4abcb2146c499756f0dsewardj    UN            | 0x1 | 0x45
11025cdc376dcb5a4560b0a35d4abcb2146c499756f0dsewardj    EQ            | 0x2 | 0x40
11026cdc376dcb5a4560b0a35d4abcb2146c499756f0dsewardj    GT            | 0x4 | 0x00
11027cdc376dcb5a4560b0a35d4abcb2146c499756f0dsewardj    LT            | 0x8 | 0x01
11028cdc376dcb5a4560b0a35d4abcb2146c499756f0dsewardj    */
11029cdc376dcb5a4560b0a35d4abcb2146c499756f0dsewardj
11030cdc376dcb5a4560b0a35d4abcb2146c499756f0dsewardj   assign( ccPPC32,
11031cdc376dcb5a4560b0a35d4abcb2146c499756f0dsewardj           binop( Iop_Shl32,
11032cdc376dcb5a4560b0a35d4abcb2146c499756f0dsewardj                  mkU32( 1 ),
11033cdc376dcb5a4560b0a35d4abcb2146c499756f0dsewardj                  unop( Iop_32to8,
11034cdc376dcb5a4560b0a35d4abcb2146c499756f0dsewardj                        binop( Iop_Or32,
11035cdc376dcb5a4560b0a35d4abcb2146c499756f0dsewardj                               binop( Iop_And32,
11036cdc376dcb5a4560b0a35d4abcb2146c499756f0dsewardj                                      unop( Iop_Not32,
11037cdc376dcb5a4560b0a35d4abcb2146c499756f0dsewardj                                            binop( Iop_Shr32,
11038cdc376dcb5a4560b0a35d4abcb2146c499756f0dsewardj                                                   mkexpr( ccIR ),
11039cdc376dcb5a4560b0a35d4abcb2146c499756f0dsewardj                                                   mkU8( 5 ) ) ),
11040cdc376dcb5a4560b0a35d4abcb2146c499756f0dsewardj                                      mkU32( 2 ) ),
11041cdc376dcb5a4560b0a35d4abcb2146c499756f0dsewardj                               binop( Iop_And32,
11042cdc376dcb5a4560b0a35d4abcb2146c499756f0dsewardj                                      binop( Iop_Xor32,
11043cdc376dcb5a4560b0a35d4abcb2146c499756f0dsewardj                                             mkexpr( ccIR ),
11044cdc376dcb5a4560b0a35d4abcb2146c499756f0dsewardj                                             binop( Iop_Shr32,
11045cdc376dcb5a4560b0a35d4abcb2146c499756f0dsewardj                                                    mkexpr( ccIR ),
11046cdc376dcb5a4560b0a35d4abcb2146c499756f0dsewardj                                                    mkU8( 6 ) ) ),
11047cdc376dcb5a4560b0a35d4abcb2146c499756f0dsewardj                                      mkU32( 1 ) ) ) ) ) );
11048cdc376dcb5a4560b0a35d4abcb2146c499756f0dsewardj
11049cdc376dcb5a4560b0a35d4abcb2146c499756f0dsewardj   putGST_field( PPC_GST_CR, mkexpr( ccPPC32 ), crfD );
11050cdc376dcb5a4560b0a35d4abcb2146c499756f0dsewardj   return True;
11051cdc376dcb5a4560b0a35d4abcb2146c499756f0dsewardj}
11052cdc376dcb5a4560b0a35d4abcb2146c499756f0dsewardj
110535eff1c502e995d1f9668cc9def72d5db59f21b13sewardj/* Test class/group/exponent/significance instructions. */
110545eff1c502e995d1f9668cc9def72d5db59f21b13sewardjstatic Bool dis_dfp_exponent_test ( UInt theInstr )
110555eff1c502e995d1f9668cc9def72d5db59f21b13sewardj{
110565eff1c502e995d1f9668cc9def72d5db59f21b13sewardj   UChar frA_addr   = ifieldRegA( theInstr );
110575eff1c502e995d1f9668cc9def72d5db59f21b13sewardj   UChar frB_addr   = ifieldRegB( theInstr );
110585eff1c502e995d1f9668cc9def72d5db59f21b13sewardj   UChar crfD       = toUChar( IFIELD( theInstr, 23, 3 ) );
110595eff1c502e995d1f9668cc9def72d5db59f21b13sewardj   IRTemp frA       = newTemp( Ity_D64 );
110605eff1c502e995d1f9668cc9def72d5db59f21b13sewardj   IRTemp frB       = newTemp( Ity_D64 );
110615eff1c502e995d1f9668cc9def72d5db59f21b13sewardj   IRTemp frA128    = newTemp( Ity_D128 );
110625eff1c502e995d1f9668cc9def72d5db59f21b13sewardj   IRTemp frB128    = newTemp( Ity_D128 );
110635eff1c502e995d1f9668cc9def72d5db59f21b13sewardj   UInt opc1        = ifieldOPC( theInstr );
110645eff1c502e995d1f9668cc9def72d5db59f21b13sewardj   IRTemp gfield_A  = newTemp( Ity_I32 );
110655eff1c502e995d1f9668cc9def72d5db59f21b13sewardj   IRTemp gfield_B  = newTemp( Ity_I32 );
110665eff1c502e995d1f9668cc9def72d5db59f21b13sewardj   IRTemp gfield_mask   = newTemp( Ity_I32 );
110675eff1c502e995d1f9668cc9def72d5db59f21b13sewardj   IRTemp exponent_A    = newTemp( Ity_I32 );
110685eff1c502e995d1f9668cc9def72d5db59f21b13sewardj   IRTemp exponent_B    = newTemp( Ity_I32 );
110695eff1c502e995d1f9668cc9def72d5db59f21b13sewardj   IRTemp A_NaN_true    = newTemp( Ity_I32 );
110705eff1c502e995d1f9668cc9def72d5db59f21b13sewardj   IRTemp B_NaN_true    = newTemp( Ity_I32 );
110715eff1c502e995d1f9668cc9def72d5db59f21b13sewardj   IRTemp A_inf_true    = newTemp( Ity_I32 );
110725eff1c502e995d1f9668cc9def72d5db59f21b13sewardj   IRTemp B_inf_true    = newTemp( Ity_I32 );
110735eff1c502e995d1f9668cc9def72d5db59f21b13sewardj   IRTemp A_equals_B    = newTemp( Ity_I32 );
110745eff1c502e995d1f9668cc9def72d5db59f21b13sewardj   IRTemp finite_number = newTemp( Ity_I32 );
110755eff1c502e995d1f9668cc9def72d5db59f21b13sewardj   IRTemp cc0 = newTemp( Ity_I32 );
110765eff1c502e995d1f9668cc9def72d5db59f21b13sewardj   IRTemp cc1 = newTemp( Ity_I32 );
110775eff1c502e995d1f9668cc9def72d5db59f21b13sewardj   IRTemp cc2 = newTemp( Ity_I32 );
110785eff1c502e995d1f9668cc9def72d5db59f21b13sewardj   IRTemp cc3 = newTemp( Ity_I32 );
110795eff1c502e995d1f9668cc9def72d5db59f21b13sewardj
110805eff1c502e995d1f9668cc9def72d5db59f21b13sewardj   /* The dtstex and dtstexg instructions only differ in the size of the
110815eff1c502e995d1f9668cc9def72d5db59f21b13sewardj    * exponent field.  The following switch statement takes care of the size
110825eff1c502e995d1f9668cc9def72d5db59f21b13sewardj    * specific setup.  Once the value of the exponents, the G-field shift
110835eff1c502e995d1f9668cc9def72d5db59f21b13sewardj    * and mask is setup the remaining code is identical.
110845eff1c502e995d1f9668cc9def72d5db59f21b13sewardj    */
110855eff1c502e995d1f9668cc9def72d5db59f21b13sewardj   switch (opc1) {
110865eff1c502e995d1f9668cc9def72d5db59f21b13sewardj   case 0x3b: // dtstex       Extended instruction setup
110875eff1c502e995d1f9668cc9def72d5db59f21b13sewardj      DIP("dtstex %u,r%u,r%d\n", crfD, frA_addr, frB_addr);
110885eff1c502e995d1f9668cc9def72d5db59f21b13sewardj      assign( frA, getDReg( frA_addr ) );
110895eff1c502e995d1f9668cc9def72d5db59f21b13sewardj      assign( frB, getDReg( frB_addr ) );
110905eff1c502e995d1f9668cc9def72d5db59f21b13sewardj      assign( gfield_mask, mkU32( DFP_G_FIELD_LONG_MASK ) );
11091cea07ccbe9aa9b5fd8e9b318471c6c74aa147acbcarll      assign(exponent_A, unop( Iop_64to32,
11092cea07ccbe9aa9b5fd8e9b318471c6c74aa147acbcarll                               unop( Iop_ExtractExpD64,
11093cea07ccbe9aa9b5fd8e9b318471c6c74aa147acbcarll                                     mkexpr( frA ) ) ) );
11094cea07ccbe9aa9b5fd8e9b318471c6c74aa147acbcarll      assign(exponent_B, unop( Iop_64to32,
11095cea07ccbe9aa9b5fd8e9b318471c6c74aa147acbcarll                               unop( Iop_ExtractExpD64,
11096cea07ccbe9aa9b5fd8e9b318471c6c74aa147acbcarll                                     mkexpr( frB ) ) ) );
110975eff1c502e995d1f9668cc9def72d5db59f21b13sewardj      break;
110985eff1c502e995d1f9668cc9def72d5db59f21b13sewardj
110995eff1c502e995d1f9668cc9def72d5db59f21b13sewardj   case 0x3F: //  dtstexq      Quad instruction setup
111005eff1c502e995d1f9668cc9def72d5db59f21b13sewardj      DIP("dtstexq %u,r%u,r%d\n", crfD, frA_addr, frB_addr);
111015eff1c502e995d1f9668cc9def72d5db59f21b13sewardj      assign( frA128, getDReg_pair( frA_addr ) );
111025eff1c502e995d1f9668cc9def72d5db59f21b13sewardj      assign( frB128, getDReg_pair( frB_addr ) );
111035eff1c502e995d1f9668cc9def72d5db59f21b13sewardj      assign( frA, unop( Iop_D128HItoD64, mkexpr( frA128 ) ) );
111045eff1c502e995d1f9668cc9def72d5db59f21b13sewardj      assign( frB, unop( Iop_D128HItoD64, mkexpr( frB128 ) ) );
111055eff1c502e995d1f9668cc9def72d5db59f21b13sewardj      assign( gfield_mask, mkU32( DFP_G_FIELD_EXTND_MASK ) );
11106cea07ccbe9aa9b5fd8e9b318471c6c74aa147acbcarll      assign( exponent_A, unop( Iop_64to32,
11107cea07ccbe9aa9b5fd8e9b318471c6c74aa147acbcarll                                unop( Iop_ExtractExpD128,
11108cea07ccbe9aa9b5fd8e9b318471c6c74aa147acbcarll                                      mkexpr( frA128 ) ) ) );
11109cea07ccbe9aa9b5fd8e9b318471c6c74aa147acbcarll      assign( exponent_B, unop( Iop_64to32,
11110cea07ccbe9aa9b5fd8e9b318471c6c74aa147acbcarll                                unop( Iop_ExtractExpD128,
11111cea07ccbe9aa9b5fd8e9b318471c6c74aa147acbcarll                                      mkexpr( frB128 ) ) ) );
111125eff1c502e995d1f9668cc9def72d5db59f21b13sewardj      break;
111135eff1c502e995d1f9668cc9def72d5db59f21b13sewardj   default:
111145eff1c502e995d1f9668cc9def72d5db59f21b13sewardj      vex_printf("dis_dfp_exponent_test(ppc)(opc2)\n");
111155eff1c502e995d1f9668cc9def72d5db59f21b13sewardj      return False;
111165eff1c502e995d1f9668cc9def72d5db59f21b13sewardj   }
111175eff1c502e995d1f9668cc9def72d5db59f21b13sewardj
111185eff1c502e995d1f9668cc9def72d5db59f21b13sewardj   /* Extract the Gfield */
111195eff1c502e995d1f9668cc9def72d5db59f21b13sewardj   assign( gfield_A, binop( Iop_And32,
111205eff1c502e995d1f9668cc9def72d5db59f21b13sewardj                            mkexpr( gfield_mask ),
111215eff1c502e995d1f9668cc9def72d5db59f21b13sewardj                            unop( Iop_64HIto32,
111225eff1c502e995d1f9668cc9def72d5db59f21b13sewardj                                  unop( Iop_ReinterpD64asI64,
111235eff1c502e995d1f9668cc9def72d5db59f21b13sewardj                                        mkexpr(frA) ) ) ) );
111245eff1c502e995d1f9668cc9def72d5db59f21b13sewardj
111255eff1c502e995d1f9668cc9def72d5db59f21b13sewardj   assign( gfield_B, binop( Iop_And32,
111265eff1c502e995d1f9668cc9def72d5db59f21b13sewardj                            mkexpr( gfield_mask ),
111275eff1c502e995d1f9668cc9def72d5db59f21b13sewardj                            unop( Iop_64HIto32,
111285eff1c502e995d1f9668cc9def72d5db59f21b13sewardj                                  unop( Iop_ReinterpD64asI64,
111295eff1c502e995d1f9668cc9def72d5db59f21b13sewardj                                        mkexpr(frB) ) ) ) );
111305eff1c502e995d1f9668cc9def72d5db59f21b13sewardj
111315eff1c502e995d1f9668cc9def72d5db59f21b13sewardj   /* check for NAN */
111325eff1c502e995d1f9668cc9def72d5db59f21b13sewardj   assign( A_NaN_true, binop(Iop_Or32,
111335eff1c502e995d1f9668cc9def72d5db59f21b13sewardj                             unop( Iop_1Sto32,
111345eff1c502e995d1f9668cc9def72d5db59f21b13sewardj                                   binop( Iop_CmpEQ32,
111355eff1c502e995d1f9668cc9def72d5db59f21b13sewardj                                          mkexpr( gfield_A ),
111365eff1c502e995d1f9668cc9def72d5db59f21b13sewardj                                          mkU32( 0x7C000000 ) ) ),
111375eff1c502e995d1f9668cc9def72d5db59f21b13sewardj                             unop( Iop_1Sto32,
111385eff1c502e995d1f9668cc9def72d5db59f21b13sewardj                                   binop( Iop_CmpEQ32,
111395eff1c502e995d1f9668cc9def72d5db59f21b13sewardj                                          mkexpr( gfield_A ),
111405eff1c502e995d1f9668cc9def72d5db59f21b13sewardj                                          mkU32( 0x7E000000 ) )
111415eff1c502e995d1f9668cc9def72d5db59f21b13sewardj                                   ) ) );
111425eff1c502e995d1f9668cc9def72d5db59f21b13sewardj   assign( B_NaN_true, binop(Iop_Or32,
111435eff1c502e995d1f9668cc9def72d5db59f21b13sewardj                             unop( Iop_1Sto32,
111445eff1c502e995d1f9668cc9def72d5db59f21b13sewardj                                   binop( Iop_CmpEQ32,
111455eff1c502e995d1f9668cc9def72d5db59f21b13sewardj                                          mkexpr( gfield_B ),
111465eff1c502e995d1f9668cc9def72d5db59f21b13sewardj                                          mkU32( 0x7C000000 ) ) ),
111475eff1c502e995d1f9668cc9def72d5db59f21b13sewardj                             unop( Iop_1Sto32,
111485eff1c502e995d1f9668cc9def72d5db59f21b13sewardj                                   binop( Iop_CmpEQ32,
111495eff1c502e995d1f9668cc9def72d5db59f21b13sewardj                                          mkexpr( gfield_B ),
111505eff1c502e995d1f9668cc9def72d5db59f21b13sewardj                                          mkU32( 0x7E000000 ) )
111515eff1c502e995d1f9668cc9def72d5db59f21b13sewardj                             ) ) );
111525eff1c502e995d1f9668cc9def72d5db59f21b13sewardj
111535eff1c502e995d1f9668cc9def72d5db59f21b13sewardj   /* check for infinity */
111545eff1c502e995d1f9668cc9def72d5db59f21b13sewardj   assign( A_inf_true,
111555eff1c502e995d1f9668cc9def72d5db59f21b13sewardj           unop( Iop_1Sto32,
111565eff1c502e995d1f9668cc9def72d5db59f21b13sewardj                 binop( Iop_CmpEQ32,
111575eff1c502e995d1f9668cc9def72d5db59f21b13sewardj                        mkexpr( gfield_A ),
111585eff1c502e995d1f9668cc9def72d5db59f21b13sewardj                        mkU32( 0x78000000 ) ) ) );
111595eff1c502e995d1f9668cc9def72d5db59f21b13sewardj
111605eff1c502e995d1f9668cc9def72d5db59f21b13sewardj   assign( B_inf_true,
111615eff1c502e995d1f9668cc9def72d5db59f21b13sewardj           unop( Iop_1Sto32,
111625eff1c502e995d1f9668cc9def72d5db59f21b13sewardj                 binop( Iop_CmpEQ32,
111635eff1c502e995d1f9668cc9def72d5db59f21b13sewardj                        mkexpr( gfield_B ),
111645eff1c502e995d1f9668cc9def72d5db59f21b13sewardj                        mkU32( 0x78000000 ) ) ) );
111655eff1c502e995d1f9668cc9def72d5db59f21b13sewardj
111665eff1c502e995d1f9668cc9def72d5db59f21b13sewardj   assign( finite_number,
111675eff1c502e995d1f9668cc9def72d5db59f21b13sewardj           unop( Iop_Not32,
111685eff1c502e995d1f9668cc9def72d5db59f21b13sewardj                 binop( Iop_Or32,
111695eff1c502e995d1f9668cc9def72d5db59f21b13sewardj                        binop( Iop_Or32,
111705eff1c502e995d1f9668cc9def72d5db59f21b13sewardj                               mkexpr( A_NaN_true ),
111715eff1c502e995d1f9668cc9def72d5db59f21b13sewardj                               mkexpr( B_NaN_true ) ),
111725eff1c502e995d1f9668cc9def72d5db59f21b13sewardj                        binop( Iop_Or32,
111735eff1c502e995d1f9668cc9def72d5db59f21b13sewardj                               mkexpr( A_inf_true ),
111745eff1c502e995d1f9668cc9def72d5db59f21b13sewardj                               mkexpr( B_inf_true ) ) ) ) );
111755eff1c502e995d1f9668cc9def72d5db59f21b13sewardj
111765eff1c502e995d1f9668cc9def72d5db59f21b13sewardj   /* Calculate the condition code bits
111775eff1c502e995d1f9668cc9def72d5db59f21b13sewardj    * If QNaN,SNaN, +infinity, -infinity then cc0, cc1 and cc2 are zero
111785eff1c502e995d1f9668cc9def72d5db59f21b13sewardj    * regardless of the value of the comparisons and cc3 is 1.  Otherwise,
111795eff1c502e995d1f9668cc9def72d5db59f21b13sewardj    * cc0, cc1 and cc0 reflect the results of the comparisons.
111805eff1c502e995d1f9668cc9def72d5db59f21b13sewardj    */
111815eff1c502e995d1f9668cc9def72d5db59f21b13sewardj   assign( A_equals_B,
111825eff1c502e995d1f9668cc9def72d5db59f21b13sewardj           binop( Iop_Or32,
111835eff1c502e995d1f9668cc9def72d5db59f21b13sewardj                  unop( Iop_1Uto32,
111845eff1c502e995d1f9668cc9def72d5db59f21b13sewardj                  binop( Iop_CmpEQ32,
111855eff1c502e995d1f9668cc9def72d5db59f21b13sewardj                         mkexpr( exponent_A ),
111865eff1c502e995d1f9668cc9def72d5db59f21b13sewardj                         mkexpr( exponent_B ) ) ),
111875eff1c502e995d1f9668cc9def72d5db59f21b13sewardj                  binop( Iop_Or32,
111885eff1c502e995d1f9668cc9def72d5db59f21b13sewardj                         binop( Iop_And32,
111895eff1c502e995d1f9668cc9def72d5db59f21b13sewardj                                mkexpr( A_inf_true ),
111905eff1c502e995d1f9668cc9def72d5db59f21b13sewardj                                mkexpr( B_inf_true ) ),
111915eff1c502e995d1f9668cc9def72d5db59f21b13sewardj                         binop( Iop_And32,
111925eff1c502e995d1f9668cc9def72d5db59f21b13sewardj                                mkexpr( A_NaN_true ),
111935eff1c502e995d1f9668cc9def72d5db59f21b13sewardj                                mkexpr( B_NaN_true ) ) ) ) );
111945eff1c502e995d1f9668cc9def72d5db59f21b13sewardj
111955eff1c502e995d1f9668cc9def72d5db59f21b13sewardj   assign( cc0, binop( Iop_And32,
111965eff1c502e995d1f9668cc9def72d5db59f21b13sewardj                       mkexpr( finite_number ),
111975eff1c502e995d1f9668cc9def72d5db59f21b13sewardj                       binop( Iop_Shl32,
111985eff1c502e995d1f9668cc9def72d5db59f21b13sewardj                              unop( Iop_1Uto32,
111995eff1c502e995d1f9668cc9def72d5db59f21b13sewardj                                    binop( Iop_CmpLT32U,
112005eff1c502e995d1f9668cc9def72d5db59f21b13sewardj                                           mkexpr( exponent_A ),
112015eff1c502e995d1f9668cc9def72d5db59f21b13sewardj                                           mkexpr( exponent_B ) ) ),
112025eff1c502e995d1f9668cc9def72d5db59f21b13sewardj                                           mkU8( 3 ) ) ) );
112035eff1c502e995d1f9668cc9def72d5db59f21b13sewardj
112045eff1c502e995d1f9668cc9def72d5db59f21b13sewardj   assign( cc1, binop( Iop_And32,
112055eff1c502e995d1f9668cc9def72d5db59f21b13sewardj                       mkexpr( finite_number ),
112065eff1c502e995d1f9668cc9def72d5db59f21b13sewardj                       binop( Iop_Shl32,
112075eff1c502e995d1f9668cc9def72d5db59f21b13sewardj                              unop( Iop_1Uto32,
112085eff1c502e995d1f9668cc9def72d5db59f21b13sewardj                                    binop( Iop_CmpLT32U,
112095eff1c502e995d1f9668cc9def72d5db59f21b13sewardj                                           mkexpr( exponent_B ),
112105eff1c502e995d1f9668cc9def72d5db59f21b13sewardj                                           mkexpr( exponent_A ) ) ),
112115eff1c502e995d1f9668cc9def72d5db59f21b13sewardj                                           mkU8( 2 ) ) ) );
112125eff1c502e995d1f9668cc9def72d5db59f21b13sewardj
112135eff1c502e995d1f9668cc9def72d5db59f21b13sewardj   assign( cc2, binop( Iop_Shl32,
112145eff1c502e995d1f9668cc9def72d5db59f21b13sewardj                       binop( Iop_And32,
112155eff1c502e995d1f9668cc9def72d5db59f21b13sewardj                              mkexpr( A_equals_B ),
112165eff1c502e995d1f9668cc9def72d5db59f21b13sewardj                              mkU32( 1 ) ),
112175eff1c502e995d1f9668cc9def72d5db59f21b13sewardj                              mkU8( 1 ) ) );
112185eff1c502e995d1f9668cc9def72d5db59f21b13sewardj
112195eff1c502e995d1f9668cc9def72d5db59f21b13sewardj   assign( cc3, binop( Iop_And32,
112205eff1c502e995d1f9668cc9def72d5db59f21b13sewardj                       unop( Iop_Not32, mkexpr( A_equals_B ) ),
112215eff1c502e995d1f9668cc9def72d5db59f21b13sewardj                       binop( Iop_And32,
112225eff1c502e995d1f9668cc9def72d5db59f21b13sewardj                              mkU32( 0x1 ),
112235eff1c502e995d1f9668cc9def72d5db59f21b13sewardj                              binop( Iop_Or32,
112245eff1c502e995d1f9668cc9def72d5db59f21b13sewardj                                     binop( Iop_Or32,
112255eff1c502e995d1f9668cc9def72d5db59f21b13sewardj                                            mkexpr ( A_inf_true ),
112265eff1c502e995d1f9668cc9def72d5db59f21b13sewardj                                            mkexpr ( B_inf_true ) ),
112275eff1c502e995d1f9668cc9def72d5db59f21b13sewardj                                            binop( Iop_Or32,
112285eff1c502e995d1f9668cc9def72d5db59f21b13sewardj                                                   mkexpr ( A_NaN_true ),
112295eff1c502e995d1f9668cc9def72d5db59f21b13sewardj                                                   mkexpr ( B_NaN_true ) ) )
112305eff1c502e995d1f9668cc9def72d5db59f21b13sewardj                              ) ) );
112315eff1c502e995d1f9668cc9def72d5db59f21b13sewardj
112325eff1c502e995d1f9668cc9def72d5db59f21b13sewardj   /* store the condition code */
112335eff1c502e995d1f9668cc9def72d5db59f21b13sewardj   putGST_field( PPC_GST_CR,
112345eff1c502e995d1f9668cc9def72d5db59f21b13sewardj                 binop( Iop_Or32,
112355eff1c502e995d1f9668cc9def72d5db59f21b13sewardj                        mkexpr( cc0 ),
112365eff1c502e995d1f9668cc9def72d5db59f21b13sewardj                        binop( Iop_Or32,
112375eff1c502e995d1f9668cc9def72d5db59f21b13sewardj                               mkexpr( cc1 ),
112385eff1c502e995d1f9668cc9def72d5db59f21b13sewardj                               binop( Iop_Or32,
112395eff1c502e995d1f9668cc9def72d5db59f21b13sewardj                                      mkexpr( cc2 ),
112405eff1c502e995d1f9668cc9def72d5db59f21b13sewardj                                      mkexpr( cc3 ) ) ) ),
112415eff1c502e995d1f9668cc9def72d5db59f21b13sewardj                 crfD );
112425eff1c502e995d1f9668cc9def72d5db59f21b13sewardj   return True;
112435eff1c502e995d1f9668cc9def72d5db59f21b13sewardj}
112445eff1c502e995d1f9668cc9def72d5db59f21b13sewardj
112455eff1c502e995d1f9668cc9def72d5db59f21b13sewardj/* Test class/group/exponent/significance instructions. */
112465eff1c502e995d1f9668cc9def72d5db59f21b13sewardjstatic Bool dis_dfp_class_test ( UInt theInstr )
112475eff1c502e995d1f9668cc9def72d5db59f21b13sewardj{
112485eff1c502e995d1f9668cc9def72d5db59f21b13sewardj   UChar frA_addr   = ifieldRegA( theInstr );
112495eff1c502e995d1f9668cc9def72d5db59f21b13sewardj   IRTemp frA       = newTemp( Ity_D64 );
112505eff1c502e995d1f9668cc9def72d5db59f21b13sewardj   IRTemp abs_frA   = newTemp( Ity_D64 );
112515eff1c502e995d1f9668cc9def72d5db59f21b13sewardj   IRTemp frAI64_hi = newTemp( Ity_I64 );
112525eff1c502e995d1f9668cc9def72d5db59f21b13sewardj   IRTemp frAI64_lo = newTemp( Ity_I64 );
112535eff1c502e995d1f9668cc9def72d5db59f21b13sewardj   UInt opc1        = ifieldOPC( theInstr );
112545eff1c502e995d1f9668cc9def72d5db59f21b13sewardj   UInt opc2        = ifieldOPClo9( theInstr );
112555eff1c502e995d1f9668cc9def72d5db59f21b13sewardj   UChar crfD       = toUChar( IFIELD( theInstr, 23, 3 ) );  // AKA BF
112565eff1c502e995d1f9668cc9def72d5db59f21b13sewardj   UInt DCM         = IFIELD( theInstr, 10, 6 );
112575eff1c502e995d1f9668cc9def72d5db59f21b13sewardj   IRTemp DCM_calc  = newTemp( Ity_I32 );
112585eff1c502e995d1f9668cc9def72d5db59f21b13sewardj   UInt max_exp     = 0;
112595eff1c502e995d1f9668cc9def72d5db59f21b13sewardj   UInt min_exp     = 0;
112605eff1c502e995d1f9668cc9def72d5db59f21b13sewardj   IRTemp min_subnormalD64  = newTemp( Ity_D64 );
112615eff1c502e995d1f9668cc9def72d5db59f21b13sewardj   IRTemp min_subnormalD128 = newTemp( Ity_D128 );
112625eff1c502e995d1f9668cc9def72d5db59f21b13sewardj   IRTemp significand64  = newTemp( Ity_D64 );
112635eff1c502e995d1f9668cc9def72d5db59f21b13sewardj   IRTemp significand128 = newTemp( Ity_D128 );
11264cea07ccbe9aa9b5fd8e9b318471c6c74aa147acbcarll   IRTemp exp_min_normal = newTemp( Ity_I64 );
112655eff1c502e995d1f9668cc9def72d5db59f21b13sewardj   IRTemp exponent       = newTemp( Ity_I32 );
112665eff1c502e995d1f9668cc9def72d5db59f21b13sewardj
112675eff1c502e995d1f9668cc9def72d5db59f21b13sewardj   IRTemp infinity_true  = newTemp( Ity_I32 );
112685eff1c502e995d1f9668cc9def72d5db59f21b13sewardj   IRTemp SNaN_true      = newTemp( Ity_I32 );
112695eff1c502e995d1f9668cc9def72d5db59f21b13sewardj   IRTemp QNaN_true      = newTemp( Ity_I32 );
112705eff1c502e995d1f9668cc9def72d5db59f21b13sewardj   IRTemp subnormal_true = newTemp( Ity_I32 );
112715eff1c502e995d1f9668cc9def72d5db59f21b13sewardj   IRTemp normal_true    = newTemp( Ity_I32 );
112725eff1c502e995d1f9668cc9def72d5db59f21b13sewardj   IRTemp extreme_true   = newTemp( Ity_I32 );
112735eff1c502e995d1f9668cc9def72d5db59f21b13sewardj   IRTemp lmd            = newTemp( Ity_I32 );
112745eff1c502e995d1f9668cc9def72d5db59f21b13sewardj   IRTemp lmd_zero_true  = newTemp( Ity_I32 );
112755eff1c502e995d1f9668cc9def72d5db59f21b13sewardj   IRTemp zero_true      = newTemp( Ity_I32 );
112765eff1c502e995d1f9668cc9def72d5db59f21b13sewardj   IRTemp sign           = newTemp( Ity_I32 );
112775eff1c502e995d1f9668cc9def72d5db59f21b13sewardj   IRTemp field          = newTemp( Ity_I32 );
112785eff1c502e995d1f9668cc9def72d5db59f21b13sewardj   IRTemp ccIR_zero      = newTemp( Ity_I32 );
112795eff1c502e995d1f9668cc9def72d5db59f21b13sewardj   IRTemp ccIR_subnormal = newTemp( Ity_I32 );
112805eff1c502e995d1f9668cc9def72d5db59f21b13sewardj
112815eff1c502e995d1f9668cc9def72d5db59f21b13sewardj   /* UInt size     = DFP_LONG;  JRS:unused */
112825eff1c502e995d1f9668cc9def72d5db59f21b13sewardj   IRTemp gfield = newTemp( Ity_I32 );
112835eff1c502e995d1f9668cc9def72d5db59f21b13sewardj   IRTemp gfield_0_4_shift  = newTemp( Ity_I8 );
112845eff1c502e995d1f9668cc9def72d5db59f21b13sewardj   IRTemp gfield_mask       = newTemp( Ity_I32 );
112855eff1c502e995d1f9668cc9def72d5db59f21b13sewardj   IRTemp dcm0 = newTemp( Ity_I32 );
112865eff1c502e995d1f9668cc9def72d5db59f21b13sewardj   IRTemp dcm1 = newTemp( Ity_I32 );
112875eff1c502e995d1f9668cc9def72d5db59f21b13sewardj   IRTemp dcm2 = newTemp( Ity_I32 );
112885eff1c502e995d1f9668cc9def72d5db59f21b13sewardj   IRTemp dcm3 = newTemp( Ity_I32 );
112895eff1c502e995d1f9668cc9def72d5db59f21b13sewardj   IRTemp dcm4 = newTemp( Ity_I32 );
112905eff1c502e995d1f9668cc9def72d5db59f21b13sewardj   IRTemp dcm5 = newTemp( Ity_I32 );
112915eff1c502e995d1f9668cc9def72d5db59f21b13sewardj
112925eff1c502e995d1f9668cc9def72d5db59f21b13sewardj   /* The only difference between the dtstdc and dtstdcq instructions is
112935eff1c502e995d1f9668cc9def72d5db59f21b13sewardj    * size of the T and G fields.  The calculation of the 4 bit field
112945eff1c502e995d1f9668cc9def72d5db59f21b13sewardj    * is the same.  Setup the parameters and values that are DFP size
112955eff1c502e995d1f9668cc9def72d5db59f21b13sewardj    * specific.  The rest of the code is independent of the DFP size.
112965eff1c502e995d1f9668cc9def72d5db59f21b13sewardj    *
112975eff1c502e995d1f9668cc9def72d5db59f21b13sewardj    * The Io_CmpD64 is used below.  The instruction sets the ccIR values.
112985eff1c502e995d1f9668cc9def72d5db59f21b13sewardj    * The interpretation of the ccIR values is as follows:
112995eff1c502e995d1f9668cc9def72d5db59f21b13sewardj    *
113005eff1c502e995d1f9668cc9def72d5db59f21b13sewardj    *    DFP cmp result | IR
113015eff1c502e995d1f9668cc9def72d5db59f21b13sewardj    * --------------------------
113025eff1c502e995d1f9668cc9def72d5db59f21b13sewardj    *	 UN             | 0x45
113035eff1c502e995d1f9668cc9def72d5db59f21b13sewardj    *	 EQ             | 0x40
113045eff1c502e995d1f9668cc9def72d5db59f21b13sewardj    *	 GT             | 0x00
113055eff1c502e995d1f9668cc9def72d5db59f21b13sewardj    *	 LT             | 0x01
113065eff1c502e995d1f9668cc9def72d5db59f21b13sewardj    */
113075eff1c502e995d1f9668cc9def72d5db59f21b13sewardj
113085eff1c502e995d1f9668cc9def72d5db59f21b13sewardj   assign( frA, getDReg( frA_addr ) );
113095eff1c502e995d1f9668cc9def72d5db59f21b13sewardj   assign( frAI64_hi, unop( Iop_ReinterpD64asI64, mkexpr( frA ) ) );
113105eff1c502e995d1f9668cc9def72d5db59f21b13sewardj
113115eff1c502e995d1f9668cc9def72d5db59f21b13sewardj   assign( abs_frA, unop( Iop_ReinterpI64asD64,
113125eff1c502e995d1f9668cc9def72d5db59f21b13sewardj                          binop( Iop_And64,
113135eff1c502e995d1f9668cc9def72d5db59f21b13sewardj                                 unop( Iop_ReinterpD64asI64,
113145eff1c502e995d1f9668cc9def72d5db59f21b13sewardj                                       mkexpr( frA ) ),
113155eff1c502e995d1f9668cc9def72d5db59f21b13sewardj                                 mkU64( 0x7FFFFFFFFFFFFFFFULL ) ) ) );
113165eff1c502e995d1f9668cc9def72d5db59f21b13sewardj   assign( gfield_0_4_shift, mkU8( 31 - 5 ) );  // G-field[0:4]
113175eff1c502e995d1f9668cc9def72d5db59f21b13sewardj   switch (opc1) {
113185eff1c502e995d1f9668cc9def72d5db59f21b13sewardj   case 0x3b: // dtstdc, dtstdg
11319b173774421d015736c2316b5e6e998e7de545a5cflorian      DIP("dtstd%s %u,r%u,%u\n", opc2 == 0xc2 ? "c" : "g",
113205eff1c502e995d1f9668cc9def72d5db59f21b13sewardj               crfD, frA_addr, DCM);
113215eff1c502e995d1f9668cc9def72d5db59f21b13sewardj      /* setup the parameters for the long format of the two instructions */
113225eff1c502e995d1f9668cc9def72d5db59f21b13sewardj      assign( frAI64_lo, mkU64( 0 ) );
113235eff1c502e995d1f9668cc9def72d5db59f21b13sewardj      assign( gfield_mask, mkU32( DFP_G_FIELD_LONG_MASK ) );
113245eff1c502e995d1f9668cc9def72d5db59f21b13sewardj      max_exp = DFP_LONG_EXP_MAX;
113255eff1c502e995d1f9668cc9def72d5db59f21b13sewardj      min_exp = DFP_LONG_EXP_MIN;
113265eff1c502e995d1f9668cc9def72d5db59f21b13sewardj
11327cea07ccbe9aa9b5fd8e9b318471c6c74aa147acbcarll      assign( exponent, unop( Iop_64to32,
11328cea07ccbe9aa9b5fd8e9b318471c6c74aa147acbcarll                              unop( Iop_ExtractExpD64,
11329cea07ccbe9aa9b5fd8e9b318471c6c74aa147acbcarll                                    mkexpr( frA ) ) ) );
113305eff1c502e995d1f9668cc9def72d5db59f21b13sewardj      assign( significand64,
113315eff1c502e995d1f9668cc9def72d5db59f21b13sewardj              unop( Iop_ReinterpI64asD64,
113325eff1c502e995d1f9668cc9def72d5db59f21b13sewardj                    mkU64( 0x2234000000000001ULL ) ) );  // dfp 1.0
11333cea07ccbe9aa9b5fd8e9b318471c6c74aa147acbcarll      assign( exp_min_normal,mkU64( 398 - 383 ) );
113345eff1c502e995d1f9668cc9def72d5db59f21b13sewardj      assign( min_subnormalD64,
113355eff1c502e995d1f9668cc9def72d5db59f21b13sewardj              binop( Iop_InsertExpD64,
113365eff1c502e995d1f9668cc9def72d5db59f21b13sewardj                     mkexpr( exp_min_normal ),
113375eff1c502e995d1f9668cc9def72d5db59f21b13sewardj                     mkexpr( significand64 ) ) );
113385eff1c502e995d1f9668cc9def72d5db59f21b13sewardj
113395eff1c502e995d1f9668cc9def72d5db59f21b13sewardj      assign( ccIR_subnormal,
113405eff1c502e995d1f9668cc9def72d5db59f21b13sewardj              binop( Iop_CmpD64,
113415eff1c502e995d1f9668cc9def72d5db59f21b13sewardj                     mkexpr( abs_frA ),
113425eff1c502e995d1f9668cc9def72d5db59f21b13sewardj                     mkexpr( min_subnormalD64 ) ) );
113435eff1c502e995d1f9668cc9def72d5db59f21b13sewardj
113445eff1c502e995d1f9668cc9def72d5db59f21b13sewardj      /* compare absolute value of frA with zero */
113455eff1c502e995d1f9668cc9def72d5db59f21b13sewardj      assign( ccIR_zero,
113465eff1c502e995d1f9668cc9def72d5db59f21b13sewardj              binop( Iop_CmpD64,
113475eff1c502e995d1f9668cc9def72d5db59f21b13sewardj                     mkexpr( abs_frA ),
113485eff1c502e995d1f9668cc9def72d5db59f21b13sewardj                     unop( Iop_ReinterpI64asD64,
113495eff1c502e995d1f9668cc9def72d5db59f21b13sewardj                           mkU64( 0x2238000000000000ULL ) ) ) );
113505eff1c502e995d1f9668cc9def72d5db59f21b13sewardj
113515eff1c502e995d1f9668cc9def72d5db59f21b13sewardj      /* size = DFP_LONG; JRS: unused */
113525eff1c502e995d1f9668cc9def72d5db59f21b13sewardj      break;
113535eff1c502e995d1f9668cc9def72d5db59f21b13sewardj
113545eff1c502e995d1f9668cc9def72d5db59f21b13sewardj   case 0x3F:   // dtstdcq, dtstdgq
11355b173774421d015736c2316b5e6e998e7de545a5cflorian      DIP("dtstd%sq %u,r%u,%u\n", opc2 == 0xc2 ? "c" : "g",
113565eff1c502e995d1f9668cc9def72d5db59f21b13sewardj               crfD, frA_addr, DCM);
113575eff1c502e995d1f9668cc9def72d5db59f21b13sewardj      /* setup the parameters for the extended format of the
113585eff1c502e995d1f9668cc9def72d5db59f21b13sewardj       * two instructions
113595eff1c502e995d1f9668cc9def72d5db59f21b13sewardj       */
113605eff1c502e995d1f9668cc9def72d5db59f21b13sewardj      assign( frAI64_lo, unop( Iop_ReinterpD64asI64,
113615eff1c502e995d1f9668cc9def72d5db59f21b13sewardj                               getDReg( frA_addr+1 ) ) );
113625eff1c502e995d1f9668cc9def72d5db59f21b13sewardj
113635eff1c502e995d1f9668cc9def72d5db59f21b13sewardj      assign( gfield_mask, mkU32( DFP_G_FIELD_EXTND_MASK ) );
113645eff1c502e995d1f9668cc9def72d5db59f21b13sewardj      max_exp = DFP_EXTND_EXP_MAX;
113655eff1c502e995d1f9668cc9def72d5db59f21b13sewardj      min_exp = DFP_EXTND_EXP_MIN;
113665eff1c502e995d1f9668cc9def72d5db59f21b13sewardj      assign( exponent, unop( Iop_64to32,
11367cea07ccbe9aa9b5fd8e9b318471c6c74aa147acbcarll                              unop( Iop_ExtractExpD128,
11368cea07ccbe9aa9b5fd8e9b318471c6c74aa147acbcarll                                    getDReg_pair( frA_addr) ) ) );
113695eff1c502e995d1f9668cc9def72d5db59f21b13sewardj
113705eff1c502e995d1f9668cc9def72d5db59f21b13sewardj      /* create quand exponent for minimum normal number */
11371cea07ccbe9aa9b5fd8e9b318471c6c74aa147acbcarll      assign( exp_min_normal, mkU64( 6176 - 6143 ) );
113725eff1c502e995d1f9668cc9def72d5db59f21b13sewardj      assign( significand128,
113735eff1c502e995d1f9668cc9def72d5db59f21b13sewardj              unop( Iop_D64toD128,
113745eff1c502e995d1f9668cc9def72d5db59f21b13sewardj                    unop( Iop_ReinterpI64asD64,
113755eff1c502e995d1f9668cc9def72d5db59f21b13sewardj                          mkU64( 0x2234000000000001ULL ) ) ) );  // dfp 1.0
113765eff1c502e995d1f9668cc9def72d5db59f21b13sewardj
113775eff1c502e995d1f9668cc9def72d5db59f21b13sewardj      assign( min_subnormalD128,
113785eff1c502e995d1f9668cc9def72d5db59f21b13sewardj              binop( Iop_InsertExpD128,
113795eff1c502e995d1f9668cc9def72d5db59f21b13sewardj                     mkexpr( exp_min_normal ),
113805eff1c502e995d1f9668cc9def72d5db59f21b13sewardj                     mkexpr( significand128 ) ) );
113815eff1c502e995d1f9668cc9def72d5db59f21b13sewardj
113825eff1c502e995d1f9668cc9def72d5db59f21b13sewardj      assign( ccIR_subnormal,
113835eff1c502e995d1f9668cc9def72d5db59f21b13sewardj              binop( Iop_CmpD128,
113845eff1c502e995d1f9668cc9def72d5db59f21b13sewardj                     binop( Iop_D64HLtoD128,
113855eff1c502e995d1f9668cc9def72d5db59f21b13sewardj                            unop( Iop_ReinterpI64asD64,
113865eff1c502e995d1f9668cc9def72d5db59f21b13sewardj                                  binop( Iop_And64,
113875eff1c502e995d1f9668cc9def72d5db59f21b13sewardj                                         unop( Iop_ReinterpD64asI64,
113885eff1c502e995d1f9668cc9def72d5db59f21b13sewardj                                               mkexpr( frA ) ),
113895eff1c502e995d1f9668cc9def72d5db59f21b13sewardj                                         mkU64( 0x7FFFFFFFFFFFFFFFULL ) ) ),
113905eff1c502e995d1f9668cc9def72d5db59f21b13sewardj                            getDReg( frA_addr+1 ) ),
113915eff1c502e995d1f9668cc9def72d5db59f21b13sewardj                     mkexpr( min_subnormalD128 ) ) );
113925eff1c502e995d1f9668cc9def72d5db59f21b13sewardj      assign( ccIR_zero,
113935eff1c502e995d1f9668cc9def72d5db59f21b13sewardj              binop( Iop_CmpD128,
113945eff1c502e995d1f9668cc9def72d5db59f21b13sewardj                     binop( Iop_D64HLtoD128,
113955eff1c502e995d1f9668cc9def72d5db59f21b13sewardj                            mkexpr( abs_frA ),
113965eff1c502e995d1f9668cc9def72d5db59f21b13sewardj                            getDReg( frA_addr+1 ) ),
113975eff1c502e995d1f9668cc9def72d5db59f21b13sewardj                     unop( Iop_D64toD128,
113985eff1c502e995d1f9668cc9def72d5db59f21b13sewardj                           unop( Iop_ReinterpI64asD64,
113995eff1c502e995d1f9668cc9def72d5db59f21b13sewardj                                 mkU64( 0x0ULL ) ) ) ) );
114005eff1c502e995d1f9668cc9def72d5db59f21b13sewardj
114015eff1c502e995d1f9668cc9def72d5db59f21b13sewardj      /* size = DFP_EXTND; JRS:unused */
114025eff1c502e995d1f9668cc9def72d5db59f21b13sewardj      break;
114035eff1c502e995d1f9668cc9def72d5db59f21b13sewardj   default:
114045eff1c502e995d1f9668cc9def72d5db59f21b13sewardj      vex_printf("dis_dfp_class_test(ppc)(opc2)\n");
114055eff1c502e995d1f9668cc9def72d5db59f21b13sewardj      return False;
114065eff1c502e995d1f9668cc9def72d5db59f21b13sewardj   }
114075eff1c502e995d1f9668cc9def72d5db59f21b13sewardj
114085eff1c502e995d1f9668cc9def72d5db59f21b13sewardj   /* The G-field is in the upper 32-bits.  The I64 logical operations
114095eff1c502e995d1f9668cc9def72d5db59f21b13sewardj    * do not seem to be supported in 32-bit mode so keep things as 32-bit
114105eff1c502e995d1f9668cc9def72d5db59f21b13sewardj    * operations.
114115eff1c502e995d1f9668cc9def72d5db59f21b13sewardj    */
114125eff1c502e995d1f9668cc9def72d5db59f21b13sewardj   assign( gfield, binop( Iop_And32,
114135eff1c502e995d1f9668cc9def72d5db59f21b13sewardj                          mkexpr( gfield_mask ),
114145eff1c502e995d1f9668cc9def72d5db59f21b13sewardj                          unop( Iop_64HIto32,
114155eff1c502e995d1f9668cc9def72d5db59f21b13sewardj                                mkexpr(frAI64_hi) ) ) );
114165eff1c502e995d1f9668cc9def72d5db59f21b13sewardj
114175eff1c502e995d1f9668cc9def72d5db59f21b13sewardj   /* There is a lot of code that is the same to do the class and group
114185eff1c502e995d1f9668cc9def72d5db59f21b13sewardj    * instructions.  Later there is an if statement to handle the specific
114195eff1c502e995d1f9668cc9def72d5db59f21b13sewardj    * instruction.
114205eff1c502e995d1f9668cc9def72d5db59f21b13sewardj    *
114215eff1c502e995d1f9668cc9def72d5db59f21b13sewardj    * Will be using I32 values, compares, shifts and logical operations for
114225eff1c502e995d1f9668cc9def72d5db59f21b13sewardj    * this code as the 64-bit compare, shifts, logical operations are not
114235eff1c502e995d1f9668cc9def72d5db59f21b13sewardj    * supported in 32-bit mode.
114245eff1c502e995d1f9668cc9def72d5db59f21b13sewardj    */
114255eff1c502e995d1f9668cc9def72d5db59f21b13sewardj
114265eff1c502e995d1f9668cc9def72d5db59f21b13sewardj   /* Check the bits for Infinity, QNaN or Signaling NaN */
114275eff1c502e995d1f9668cc9def72d5db59f21b13sewardj   assign( infinity_true,
114285eff1c502e995d1f9668cc9def72d5db59f21b13sewardj           unop( Iop_1Sto32,
114295eff1c502e995d1f9668cc9def72d5db59f21b13sewardj                 binop( Iop_CmpEQ32,
114305eff1c502e995d1f9668cc9def72d5db59f21b13sewardj                        binop( Iop_And32,
114315eff1c502e995d1f9668cc9def72d5db59f21b13sewardj                               mkU32( 0x7C000000 ),
114325eff1c502e995d1f9668cc9def72d5db59f21b13sewardj                               mkexpr( gfield ) ),
114335eff1c502e995d1f9668cc9def72d5db59f21b13sewardj                        mkU32( 0x78000000 ) ) ) );
114345eff1c502e995d1f9668cc9def72d5db59f21b13sewardj
114355eff1c502e995d1f9668cc9def72d5db59f21b13sewardj   assign( SNaN_true,
114365eff1c502e995d1f9668cc9def72d5db59f21b13sewardj           unop( Iop_1Sto32,
114375eff1c502e995d1f9668cc9def72d5db59f21b13sewardj                 binop( Iop_CmpEQ32,
114385eff1c502e995d1f9668cc9def72d5db59f21b13sewardj                        binop( Iop_And32,
114395eff1c502e995d1f9668cc9def72d5db59f21b13sewardj                               mkU32( 0x7E000000 ),
114405eff1c502e995d1f9668cc9def72d5db59f21b13sewardj                               mkexpr( gfield ) ),
114415eff1c502e995d1f9668cc9def72d5db59f21b13sewardj                        mkU32( 0x7E000000 ) ) ) );
114425eff1c502e995d1f9668cc9def72d5db59f21b13sewardj
114435eff1c502e995d1f9668cc9def72d5db59f21b13sewardj   assign( QNaN_true,
114445eff1c502e995d1f9668cc9def72d5db59f21b13sewardj           binop( Iop_And32,
114455eff1c502e995d1f9668cc9def72d5db59f21b13sewardj                  unop( Iop_1Sto32,
114465eff1c502e995d1f9668cc9def72d5db59f21b13sewardj                       binop( Iop_CmpEQ32,
114475eff1c502e995d1f9668cc9def72d5db59f21b13sewardj                              binop( Iop_And32,
114485eff1c502e995d1f9668cc9def72d5db59f21b13sewardj                                     mkU32( 0x7E000000 ),
114495eff1c502e995d1f9668cc9def72d5db59f21b13sewardj                                     mkexpr( gfield ) ),
114505eff1c502e995d1f9668cc9def72d5db59f21b13sewardj                              mkU32( 0x7C000000 ) ) ),
114515eff1c502e995d1f9668cc9def72d5db59f21b13sewardj                  unop( Iop_Not32,
114525eff1c502e995d1f9668cc9def72d5db59f21b13sewardj                        mkexpr( SNaN_true ) ) ) );
114535eff1c502e995d1f9668cc9def72d5db59f21b13sewardj
114545eff1c502e995d1f9668cc9def72d5db59f21b13sewardj   assign( zero_true,
114555eff1c502e995d1f9668cc9def72d5db59f21b13sewardj           binop( Iop_And32,
114565eff1c502e995d1f9668cc9def72d5db59f21b13sewardj                  unop(Iop_1Sto32,
114575eff1c502e995d1f9668cc9def72d5db59f21b13sewardj                       binop( Iop_CmpEQ32,
114585eff1c502e995d1f9668cc9def72d5db59f21b13sewardj                              mkexpr( ccIR_zero ),
114595eff1c502e995d1f9668cc9def72d5db59f21b13sewardj                              mkU32( 0x40 ) ) ),  // ccIR code for Equal
114605eff1c502e995d1f9668cc9def72d5db59f21b13sewardj                  unop( Iop_Not32,
114615eff1c502e995d1f9668cc9def72d5db59f21b13sewardj                        binop( Iop_Or32,
114625eff1c502e995d1f9668cc9def72d5db59f21b13sewardj                               mkexpr( infinity_true ),
114635eff1c502e995d1f9668cc9def72d5db59f21b13sewardj                               binop( Iop_Or32,
114645eff1c502e995d1f9668cc9def72d5db59f21b13sewardj                                      mkexpr( QNaN_true ),
114655eff1c502e995d1f9668cc9def72d5db59f21b13sewardj                                      mkexpr( SNaN_true ) ) ) ) ) );
114665eff1c502e995d1f9668cc9def72d5db59f21b13sewardj
114675eff1c502e995d1f9668cc9def72d5db59f21b13sewardj   /* Do compare of frA the minimum normal value.  Comparison is size
114685eff1c502e995d1f9668cc9def72d5db59f21b13sewardj    * depenent and was done above to get the ccIR value.
114695eff1c502e995d1f9668cc9def72d5db59f21b13sewardj    */
114705eff1c502e995d1f9668cc9def72d5db59f21b13sewardj   assign( subnormal_true,
114715eff1c502e995d1f9668cc9def72d5db59f21b13sewardj           binop( Iop_And32,
114725eff1c502e995d1f9668cc9def72d5db59f21b13sewardj                  binop( Iop_Or32,
114735eff1c502e995d1f9668cc9def72d5db59f21b13sewardj                         unop( Iop_1Sto32,
114745eff1c502e995d1f9668cc9def72d5db59f21b13sewardj                               binop( Iop_CmpEQ32,
114755eff1c502e995d1f9668cc9def72d5db59f21b13sewardj                                      mkexpr( ccIR_subnormal ),
114765eff1c502e995d1f9668cc9def72d5db59f21b13sewardj                                      mkU32( 0x40 ) ) ), // ccIR code for Equal
114775eff1c502e995d1f9668cc9def72d5db59f21b13sewardj                         unop( Iop_1Sto32,
114785eff1c502e995d1f9668cc9def72d5db59f21b13sewardj                               binop( Iop_CmpEQ32,
114795eff1c502e995d1f9668cc9def72d5db59f21b13sewardj                                      mkexpr( ccIR_subnormal ),
114805eff1c502e995d1f9668cc9def72d5db59f21b13sewardj                                      mkU32( 0x1 ) ) ) ), // ccIR code for LT
114815eff1c502e995d1f9668cc9def72d5db59f21b13sewardj           unop( Iop_Not32,
114825eff1c502e995d1f9668cc9def72d5db59f21b13sewardj                 binop( Iop_Or32,
114835eff1c502e995d1f9668cc9def72d5db59f21b13sewardj                        binop( Iop_Or32,
114845eff1c502e995d1f9668cc9def72d5db59f21b13sewardj                               mkexpr( infinity_true ),
114855eff1c502e995d1f9668cc9def72d5db59f21b13sewardj                               mkexpr( zero_true) ),
114865eff1c502e995d1f9668cc9def72d5db59f21b13sewardj                        binop( Iop_Or32,
114875eff1c502e995d1f9668cc9def72d5db59f21b13sewardj                               mkexpr( QNaN_true ),
114885eff1c502e995d1f9668cc9def72d5db59f21b13sewardj                               mkexpr( SNaN_true ) ) ) ) ) );
114895eff1c502e995d1f9668cc9def72d5db59f21b13sewardj
114905eff1c502e995d1f9668cc9def72d5db59f21b13sewardj   /* Normal number is not subnormal, infinity, NaN or Zero */
114915eff1c502e995d1f9668cc9def72d5db59f21b13sewardj   assign( normal_true,
114925eff1c502e995d1f9668cc9def72d5db59f21b13sewardj           unop( Iop_Not32,
114935eff1c502e995d1f9668cc9def72d5db59f21b13sewardj                 binop( Iop_Or32,
114945eff1c502e995d1f9668cc9def72d5db59f21b13sewardj                        binop( Iop_Or32,
114955eff1c502e995d1f9668cc9def72d5db59f21b13sewardj                               mkexpr( infinity_true ),
114965eff1c502e995d1f9668cc9def72d5db59f21b13sewardj                               mkexpr( zero_true ) ),
114975eff1c502e995d1f9668cc9def72d5db59f21b13sewardj                        binop( Iop_Or32,
114985eff1c502e995d1f9668cc9def72d5db59f21b13sewardj                               mkexpr( subnormal_true ),
114995eff1c502e995d1f9668cc9def72d5db59f21b13sewardj                               binop( Iop_Or32,
115005eff1c502e995d1f9668cc9def72d5db59f21b13sewardj                                      mkexpr( QNaN_true ),
115015eff1c502e995d1f9668cc9def72d5db59f21b13sewardj                                      mkexpr( SNaN_true ) ) ) ) ) );
115025eff1c502e995d1f9668cc9def72d5db59f21b13sewardj
115035eff1c502e995d1f9668cc9def72d5db59f21b13sewardj   /* Calculate the DCM bit field based on the tests for the specific
115045eff1c502e995d1f9668cc9def72d5db59f21b13sewardj    * instruction
115055eff1c502e995d1f9668cc9def72d5db59f21b13sewardj    */
115065eff1c502e995d1f9668cc9def72d5db59f21b13sewardj   if (opc2 == 0xC2) {    // dtstdc, dtstdcq
115075eff1c502e995d1f9668cc9def72d5db59f21b13sewardj      /* DCM[0:5] Bit   Data Class definition
115085eff1c502e995d1f9668cc9def72d5db59f21b13sewardj       *   0   Zero
115095eff1c502e995d1f9668cc9def72d5db59f21b13sewardj       *   1   Subnormal
115105eff1c502e995d1f9668cc9def72d5db59f21b13sewardj       *   2   Normal
115115eff1c502e995d1f9668cc9def72d5db59f21b13sewardj       *   3   Infinity
115125eff1c502e995d1f9668cc9def72d5db59f21b13sewardj       *   4   Quiet NaN
115135eff1c502e995d1f9668cc9def72d5db59f21b13sewardj       *   5   Signaling NaN
115145eff1c502e995d1f9668cc9def72d5db59f21b13sewardj       */
115155eff1c502e995d1f9668cc9def72d5db59f21b13sewardj
115165eff1c502e995d1f9668cc9def72d5db59f21b13sewardj      assign( dcm0, binop( Iop_Shl32,
115175eff1c502e995d1f9668cc9def72d5db59f21b13sewardj                           mkexpr( zero_true ),
115185eff1c502e995d1f9668cc9def72d5db59f21b13sewardj                           mkU8( 5 ) ) );
115195eff1c502e995d1f9668cc9def72d5db59f21b13sewardj      assign( dcm1, binop( Iop_Shl32,
115205eff1c502e995d1f9668cc9def72d5db59f21b13sewardj                           binop( Iop_And32,
115215eff1c502e995d1f9668cc9def72d5db59f21b13sewardj                                  mkexpr( subnormal_true ),
115225eff1c502e995d1f9668cc9def72d5db59f21b13sewardj                                  mkU32( 1 ) ),
115235eff1c502e995d1f9668cc9def72d5db59f21b13sewardj                           mkU8( 4 ) ) );
115245eff1c502e995d1f9668cc9def72d5db59f21b13sewardj      assign( dcm2, binop( Iop_Shl32,
115255eff1c502e995d1f9668cc9def72d5db59f21b13sewardj                           binop( Iop_And32,
115265eff1c502e995d1f9668cc9def72d5db59f21b13sewardj                                  mkexpr( normal_true ),
115275eff1c502e995d1f9668cc9def72d5db59f21b13sewardj                                  mkU32( 1 ) ),
115285eff1c502e995d1f9668cc9def72d5db59f21b13sewardj                           mkU8( 3 ) ) );
115295eff1c502e995d1f9668cc9def72d5db59f21b13sewardj      assign( dcm3, binop( Iop_Shl32,
115305eff1c502e995d1f9668cc9def72d5db59f21b13sewardj                           binop( Iop_And32,
115315eff1c502e995d1f9668cc9def72d5db59f21b13sewardj                                  mkexpr( infinity_true),
115325eff1c502e995d1f9668cc9def72d5db59f21b13sewardj                                  mkU32( 1 ) ),
115335eff1c502e995d1f9668cc9def72d5db59f21b13sewardj                           mkU8( 2 ) ) );
115345eff1c502e995d1f9668cc9def72d5db59f21b13sewardj      assign( dcm4, binop( Iop_Shl32,
115355eff1c502e995d1f9668cc9def72d5db59f21b13sewardj                           binop( Iop_And32,
115365eff1c502e995d1f9668cc9def72d5db59f21b13sewardj                                  mkexpr( QNaN_true ),
115375eff1c502e995d1f9668cc9def72d5db59f21b13sewardj                                  mkU32( 1 ) ),
115385eff1c502e995d1f9668cc9def72d5db59f21b13sewardj                           mkU8( 1 ) ) );
115395eff1c502e995d1f9668cc9def72d5db59f21b13sewardj      assign( dcm5, binop( Iop_And32, mkexpr( SNaN_true), mkU32( 1 ) ) );
115405eff1c502e995d1f9668cc9def72d5db59f21b13sewardj
115415eff1c502e995d1f9668cc9def72d5db59f21b13sewardj   } else if (opc2 == 0xE2) {   // dtstdg, dtstdgq
115425eff1c502e995d1f9668cc9def72d5db59f21b13sewardj      /* check if the exponent is extreme */
115435eff1c502e995d1f9668cc9def72d5db59f21b13sewardj      assign( extreme_true, binop( Iop_Or32,
115445eff1c502e995d1f9668cc9def72d5db59f21b13sewardj                                   unop( Iop_1Sto32,
115455eff1c502e995d1f9668cc9def72d5db59f21b13sewardj                                         binop( Iop_CmpEQ32,
115465eff1c502e995d1f9668cc9def72d5db59f21b13sewardj                                                mkexpr( exponent ),
115475eff1c502e995d1f9668cc9def72d5db59f21b13sewardj                                                mkU32( max_exp ) ) ),
115485eff1c502e995d1f9668cc9def72d5db59f21b13sewardj                                   unop( Iop_1Sto32,
115495eff1c502e995d1f9668cc9def72d5db59f21b13sewardj                                         binop( Iop_CmpEQ32,
115505eff1c502e995d1f9668cc9def72d5db59f21b13sewardj                                                mkexpr( exponent ),
115515eff1c502e995d1f9668cc9def72d5db59f21b13sewardj                                                mkU32( min_exp ) ) ) ) );
115525eff1c502e995d1f9668cc9def72d5db59f21b13sewardj
115535eff1c502e995d1f9668cc9def72d5db59f21b13sewardj      /* Check if LMD is zero */
115545eff1c502e995d1f9668cc9def72d5db59f21b13sewardj      Get_lmd( &lmd, binop( Iop_Shr32,
115555eff1c502e995d1f9668cc9def72d5db59f21b13sewardj                            mkexpr( gfield ), mkU8( 31 - 5 ) ) );
115565eff1c502e995d1f9668cc9def72d5db59f21b13sewardj
115575eff1c502e995d1f9668cc9def72d5db59f21b13sewardj      assign( lmd_zero_true, unop( Iop_1Sto32,
115585eff1c502e995d1f9668cc9def72d5db59f21b13sewardj                                   binop( Iop_CmpEQ32,
115595eff1c502e995d1f9668cc9def72d5db59f21b13sewardj                                          mkexpr( lmd ),
115605eff1c502e995d1f9668cc9def72d5db59f21b13sewardj                                          mkU32( 0 ) ) ) );
115615eff1c502e995d1f9668cc9def72d5db59f21b13sewardj
115625eff1c502e995d1f9668cc9def72d5db59f21b13sewardj      /* DCM[0:5] Bit   Data Class definition
115635eff1c502e995d1f9668cc9def72d5db59f21b13sewardj       *  0   Zero with non-extreme exponent
115645eff1c502e995d1f9668cc9def72d5db59f21b13sewardj       *  1   Zero with extreme exponent
115655eff1c502e995d1f9668cc9def72d5db59f21b13sewardj       *  2   Subnormal or (Normal with extreme exponent)
115665eff1c502e995d1f9668cc9def72d5db59f21b13sewardj       *  3   Normal with non-extreme exponent and
115675eff1c502e995d1f9668cc9def72d5db59f21b13sewardj       *      leftmost zero digit in significand
115685eff1c502e995d1f9668cc9def72d5db59f21b13sewardj       *  4   Normal with non-extreme exponent and
115695eff1c502e995d1f9668cc9def72d5db59f21b13sewardj       *      leftmost nonzero digit in significand
115705eff1c502e995d1f9668cc9def72d5db59f21b13sewardj       *  5   Special symbol (Infinity, QNaN, or SNaN)
115715eff1c502e995d1f9668cc9def72d5db59f21b13sewardj       */
115725eff1c502e995d1f9668cc9def72d5db59f21b13sewardj      assign( dcm0, binop( Iop_Shl32,
115735eff1c502e995d1f9668cc9def72d5db59f21b13sewardj                           binop( Iop_And32,
115745eff1c502e995d1f9668cc9def72d5db59f21b13sewardj                                  binop( Iop_And32,
115755eff1c502e995d1f9668cc9def72d5db59f21b13sewardj                                         unop( Iop_Not32,
115765eff1c502e995d1f9668cc9def72d5db59f21b13sewardj                                               mkexpr( extreme_true ) ),
115775eff1c502e995d1f9668cc9def72d5db59f21b13sewardj                                         mkexpr( zero_true ) ),
115785eff1c502e995d1f9668cc9def72d5db59f21b13sewardj                                  mkU32( 0x1 ) ),
115795eff1c502e995d1f9668cc9def72d5db59f21b13sewardj                           mkU8( 5 ) ) );
115805eff1c502e995d1f9668cc9def72d5db59f21b13sewardj
115815eff1c502e995d1f9668cc9def72d5db59f21b13sewardj      assign( dcm1, binop( Iop_Shl32,
115825eff1c502e995d1f9668cc9def72d5db59f21b13sewardj                           binop( Iop_And32,
115835eff1c502e995d1f9668cc9def72d5db59f21b13sewardj                                  binop( Iop_And32,
115845eff1c502e995d1f9668cc9def72d5db59f21b13sewardj                                         mkexpr( extreme_true ),
115855eff1c502e995d1f9668cc9def72d5db59f21b13sewardj                                         mkexpr( zero_true ) ),
115865eff1c502e995d1f9668cc9def72d5db59f21b13sewardj                                  mkU32( 0x1 ) ),
115875eff1c502e995d1f9668cc9def72d5db59f21b13sewardj                           mkU8( 4 ) ) );
115885eff1c502e995d1f9668cc9def72d5db59f21b13sewardj
115895eff1c502e995d1f9668cc9def72d5db59f21b13sewardj      assign( dcm2, binop( Iop_Shl32,
115905eff1c502e995d1f9668cc9def72d5db59f21b13sewardj                           binop( Iop_And32,
115915eff1c502e995d1f9668cc9def72d5db59f21b13sewardj                                  binop( Iop_Or32,
115925eff1c502e995d1f9668cc9def72d5db59f21b13sewardj                                         binop( Iop_And32,
115935eff1c502e995d1f9668cc9def72d5db59f21b13sewardj                                                mkexpr( extreme_true ),
115945eff1c502e995d1f9668cc9def72d5db59f21b13sewardj                                                mkexpr( normal_true ) ),
115955eff1c502e995d1f9668cc9def72d5db59f21b13sewardj                                         mkexpr( subnormal_true ) ),
115965eff1c502e995d1f9668cc9def72d5db59f21b13sewardj                                  mkU32( 0x1 ) ),
115975eff1c502e995d1f9668cc9def72d5db59f21b13sewardj                           mkU8( 3 ) ) );
115985eff1c502e995d1f9668cc9def72d5db59f21b13sewardj
115995eff1c502e995d1f9668cc9def72d5db59f21b13sewardj      assign( dcm3, binop( Iop_Shl32,
116005eff1c502e995d1f9668cc9def72d5db59f21b13sewardj                           binop( Iop_And32,
116015eff1c502e995d1f9668cc9def72d5db59f21b13sewardj                                  binop( Iop_And32,
116025eff1c502e995d1f9668cc9def72d5db59f21b13sewardj                                         binop( Iop_And32,
116035eff1c502e995d1f9668cc9def72d5db59f21b13sewardj                                                unop( Iop_Not32,
116045eff1c502e995d1f9668cc9def72d5db59f21b13sewardj                                                      mkexpr( extreme_true ) ),
116055eff1c502e995d1f9668cc9def72d5db59f21b13sewardj                                                      mkexpr( normal_true ) ),
116065eff1c502e995d1f9668cc9def72d5db59f21b13sewardj                                         unop( Iop_1Sto32,
116075eff1c502e995d1f9668cc9def72d5db59f21b13sewardj                                               binop( Iop_CmpEQ32,
116085eff1c502e995d1f9668cc9def72d5db59f21b13sewardj                                                      mkexpr( lmd ),
116095eff1c502e995d1f9668cc9def72d5db59f21b13sewardj                                                      mkU32( 0 ) ) ) ),
116105eff1c502e995d1f9668cc9def72d5db59f21b13sewardj                                  mkU32( 0x1 ) ),
116115eff1c502e995d1f9668cc9def72d5db59f21b13sewardj                           mkU8( 2 ) ) );
116125eff1c502e995d1f9668cc9def72d5db59f21b13sewardj
116135eff1c502e995d1f9668cc9def72d5db59f21b13sewardj      assign( dcm4, binop( Iop_Shl32,
116145eff1c502e995d1f9668cc9def72d5db59f21b13sewardj                           binop( Iop_And32,
116155eff1c502e995d1f9668cc9def72d5db59f21b13sewardj                                  binop( Iop_And32,
116165eff1c502e995d1f9668cc9def72d5db59f21b13sewardj                                         binop( Iop_And32,
116175eff1c502e995d1f9668cc9def72d5db59f21b13sewardj                                                unop( Iop_Not32,
116185eff1c502e995d1f9668cc9def72d5db59f21b13sewardj                                                      mkexpr( extreme_true ) ),
116195eff1c502e995d1f9668cc9def72d5db59f21b13sewardj                                                mkexpr( normal_true ) ),
116205eff1c502e995d1f9668cc9def72d5db59f21b13sewardj                                          unop( Iop_1Sto32,
116215eff1c502e995d1f9668cc9def72d5db59f21b13sewardj                                                binop( Iop_CmpNE32,
116225eff1c502e995d1f9668cc9def72d5db59f21b13sewardj                                                       mkexpr( lmd ),
116234c96e61dd85c172b999d6afc88ce6640aeba9962sewardj                                                       mkU32( 0 ) ) ) ),
116245eff1c502e995d1f9668cc9def72d5db59f21b13sewardj                                  mkU32( 0x1 ) ),
116255eff1c502e995d1f9668cc9def72d5db59f21b13sewardj                           mkU8( 1 ) ) );
116265eff1c502e995d1f9668cc9def72d5db59f21b13sewardj
116275eff1c502e995d1f9668cc9def72d5db59f21b13sewardj      assign( dcm5, binop( Iop_And32,
116285eff1c502e995d1f9668cc9def72d5db59f21b13sewardj                           binop( Iop_Or32,
116295eff1c502e995d1f9668cc9def72d5db59f21b13sewardj                                  mkexpr( SNaN_true),
116305eff1c502e995d1f9668cc9def72d5db59f21b13sewardj                                  binop( Iop_Or32,
116315eff1c502e995d1f9668cc9def72d5db59f21b13sewardj                                         mkexpr( QNaN_true),
116325eff1c502e995d1f9668cc9def72d5db59f21b13sewardj                                         mkexpr( infinity_true) ) ),
116335eff1c502e995d1f9668cc9def72d5db59f21b13sewardj                           mkU32( 0x1 ) ) );
116345eff1c502e995d1f9668cc9def72d5db59f21b13sewardj   }
116355eff1c502e995d1f9668cc9def72d5db59f21b13sewardj
116365eff1c502e995d1f9668cc9def72d5db59f21b13sewardj   /* create DCM field */
116375eff1c502e995d1f9668cc9def72d5db59f21b13sewardj   assign( DCM_calc,
116385eff1c502e995d1f9668cc9def72d5db59f21b13sewardj           binop( Iop_Or32,
116395eff1c502e995d1f9668cc9def72d5db59f21b13sewardj                  mkexpr( dcm0 ),
116405eff1c502e995d1f9668cc9def72d5db59f21b13sewardj                  binop( Iop_Or32,
116415eff1c502e995d1f9668cc9def72d5db59f21b13sewardj                         mkexpr( dcm1 ),
116425eff1c502e995d1f9668cc9def72d5db59f21b13sewardj                         binop( Iop_Or32,
116435eff1c502e995d1f9668cc9def72d5db59f21b13sewardj                                mkexpr( dcm2 ),
116445eff1c502e995d1f9668cc9def72d5db59f21b13sewardj                                binop( Iop_Or32,
116455eff1c502e995d1f9668cc9def72d5db59f21b13sewardj                                       mkexpr( dcm3 ),
116465eff1c502e995d1f9668cc9def72d5db59f21b13sewardj                                       binop( Iop_Or32,
116475eff1c502e995d1f9668cc9def72d5db59f21b13sewardj                                              mkexpr( dcm4 ),
116485eff1c502e995d1f9668cc9def72d5db59f21b13sewardj                                              mkexpr( dcm5 ) ) ) ) ) ) );
116495eff1c502e995d1f9668cc9def72d5db59f21b13sewardj
116505eff1c502e995d1f9668cc9def72d5db59f21b13sewardj   /* Get the sign of the DFP number, ignore sign for QNaN */
116515eff1c502e995d1f9668cc9def72d5db59f21b13sewardj   assign( sign,
116525eff1c502e995d1f9668cc9def72d5db59f21b13sewardj           unop( Iop_1Uto32,
116535eff1c502e995d1f9668cc9def72d5db59f21b13sewardj                 binop( Iop_CmpEQ32,
116545eff1c502e995d1f9668cc9def72d5db59f21b13sewardj                        binop( Iop_Shr32,
116555eff1c502e995d1f9668cc9def72d5db59f21b13sewardj                               unop( Iop_64HIto32, mkexpr( frAI64_hi ) ),
116565eff1c502e995d1f9668cc9def72d5db59f21b13sewardj                               mkU8( 63 - 32 ) ),
116575eff1c502e995d1f9668cc9def72d5db59f21b13sewardj                        mkU32( 1 ) ) ) );
116585eff1c502e995d1f9668cc9def72d5db59f21b13sewardj
116595eff1c502e995d1f9668cc9def72d5db59f21b13sewardj   /* This instruction generates a four bit field to be stored in the
116605eff1c502e995d1f9668cc9def72d5db59f21b13sewardj    * condition code register.  The condition code register consists of 7
116615eff1c502e995d1f9668cc9def72d5db59f21b13sewardj    * fields.  The field to be written to is specified by the BF (AKA crfD)
116625eff1c502e995d1f9668cc9def72d5db59f21b13sewardj    * field.
116635eff1c502e995d1f9668cc9def72d5db59f21b13sewardj    *
116645eff1c502e995d1f9668cc9def72d5db59f21b13sewardj    * The field layout is as follows:
116655eff1c502e995d1f9668cc9def72d5db59f21b13sewardj    *
116665eff1c502e995d1f9668cc9def72d5db59f21b13sewardj    *      Field          Meaning
116675eff1c502e995d1f9668cc9def72d5db59f21b13sewardj    *      0000           Operand positive with no match
116685eff1c502e995d1f9668cc9def72d5db59f21b13sewardj    *      0100           Operand positive with at least one match
116695eff1c502e995d1f9668cc9def72d5db59f21b13sewardj    *      0001           Operand negative with no match
116705eff1c502e995d1f9668cc9def72d5db59f21b13sewardj    *      0101           Operand negative with at least one match
116715eff1c502e995d1f9668cc9def72d5db59f21b13sewardj    */
116725eff1c502e995d1f9668cc9def72d5db59f21b13sewardj   assign( field, binop( Iop_Or32,
116735eff1c502e995d1f9668cc9def72d5db59f21b13sewardj                         binop( Iop_Shl32,
116745eff1c502e995d1f9668cc9def72d5db59f21b13sewardj                                mkexpr( sign ),
116755eff1c502e995d1f9668cc9def72d5db59f21b13sewardj                                mkU8( 3 ) ),
116765eff1c502e995d1f9668cc9def72d5db59f21b13sewardj                                binop( Iop_Shl32,
116775eff1c502e995d1f9668cc9def72d5db59f21b13sewardj                                       unop( Iop_1Uto32,
116785eff1c502e995d1f9668cc9def72d5db59f21b13sewardj                                             binop( Iop_CmpNE32,
116795eff1c502e995d1f9668cc9def72d5db59f21b13sewardj                                                    binop( Iop_And32,
116805eff1c502e995d1f9668cc9def72d5db59f21b13sewardj                                                           mkU32( DCM ),
116815eff1c502e995d1f9668cc9def72d5db59f21b13sewardj                                                           mkexpr( DCM_calc ) ),
116825eff1c502e995d1f9668cc9def72d5db59f21b13sewardj                                                     mkU32( 0 ) ) ),
116835eff1c502e995d1f9668cc9def72d5db59f21b13sewardj                                       mkU8( 1 ) ) ) );
116845eff1c502e995d1f9668cc9def72d5db59f21b13sewardj
116855eff1c502e995d1f9668cc9def72d5db59f21b13sewardj   putGST_field( PPC_GST_CR, mkexpr( field ), crfD );
116865eff1c502e995d1f9668cc9def72d5db59f21b13sewardj   return True;
116875eff1c502e995d1f9668cc9def72d5db59f21b13sewardj}
116885eff1c502e995d1f9668cc9def72d5db59f21b13sewardj
116894c96e61dd85c172b999d6afc88ce6640aeba9962sewardjstatic Bool dis_dfp_bcd(UInt theInstr) {
116904c96e61dd85c172b999d6afc88ce6640aeba9962sewardj   UInt opc2        = ifieldOPClo10( theInstr );
116914c96e61dd85c172b999d6afc88ce6640aeba9962sewardj   ULong sp         = IFIELD(theInstr, 19, 2);
116924c96e61dd85c172b999d6afc88ce6640aeba9962sewardj   ULong s          = IFIELD(theInstr, 20, 1);
116934c96e61dd85c172b999d6afc88ce6640aeba9962sewardj   UChar frT_addr   = ifieldRegDS( theInstr );
116944c96e61dd85c172b999d6afc88ce6640aeba9962sewardj   UChar frB_addr   = ifieldRegB( theInstr );
116954c96e61dd85c172b999d6afc88ce6640aeba9962sewardj   IRTemp frB       = newTemp( Ity_D64 );
116964c96e61dd85c172b999d6afc88ce6640aeba9962sewardj   IRTemp frBI64    = newTemp( Ity_I64 );
116974c96e61dd85c172b999d6afc88ce6640aeba9962sewardj   IRTemp result    = newTemp( Ity_I64 );
116984c96e61dd85c172b999d6afc88ce6640aeba9962sewardj   IRTemp resultD64 = newTemp( Ity_D64 );
116994c96e61dd85c172b999d6afc88ce6640aeba9962sewardj   IRTemp bcd64     = newTemp( Ity_I64 );
117004c96e61dd85c172b999d6afc88ce6640aeba9962sewardj   IRTemp bcd_u     = newTemp( Ity_I32 );
117014c96e61dd85c172b999d6afc88ce6640aeba9962sewardj   IRTemp bcd_l     = newTemp( Ity_I32 );
117024c96e61dd85c172b999d6afc88ce6640aeba9962sewardj   IRTemp dbcd_u    = newTemp( Ity_I32 );
117034c96e61dd85c172b999d6afc88ce6640aeba9962sewardj   IRTemp dbcd_l    = newTemp( Ity_I32 );
117044c96e61dd85c172b999d6afc88ce6640aeba9962sewardj   IRTemp lmd       = newTemp( Ity_I32 );
117054c96e61dd85c172b999d6afc88ce6640aeba9962sewardj
117064c96e61dd85c172b999d6afc88ce6640aeba9962sewardj   assign( frB, getDReg( frB_addr ) );
117074c96e61dd85c172b999d6afc88ce6640aeba9962sewardj   assign( frBI64, unop( Iop_ReinterpD64asI64, mkexpr( frB ) ) );
117084c96e61dd85c172b999d6afc88ce6640aeba9962sewardj
117094c96e61dd85c172b999d6afc88ce6640aeba9962sewardj   switch ( opc2 ) {
117104c96e61dd85c172b999d6afc88ce6640aeba9962sewardj   case 0x142: // ddedpd   DFP Decode DPD to BCD
117114c96e61dd85c172b999d6afc88ce6640aeba9962sewardj      DIP( "ddedpd %llu,r%u,r%u\n", sp, frT_addr, frB_addr );
117124c96e61dd85c172b999d6afc88ce6640aeba9962sewardj
117134c96e61dd85c172b999d6afc88ce6640aeba9962sewardj         assign( bcd64, unop( Iop_DPBtoBCD, mkexpr( frBI64 ) ) );
117144c96e61dd85c172b999d6afc88ce6640aeba9962sewardj         assign( bcd_u, unop( Iop_64HIto32, mkexpr( bcd64 ) ) );
117154c96e61dd85c172b999d6afc88ce6640aeba9962sewardj         assign( bcd_l, unop( Iop_64to32, mkexpr( bcd64 ) ) );
117164c96e61dd85c172b999d6afc88ce6640aeba9962sewardj
117174c96e61dd85c172b999d6afc88ce6640aeba9962sewardj      if ( ( sp == 0 ) || ( sp == 1 ) ) {
117184c96e61dd85c172b999d6afc88ce6640aeba9962sewardj         /* Unsigned BCD string */
117194c96e61dd85c172b999d6afc88ce6640aeba9962sewardj         Get_lmd( &lmd,
117204c96e61dd85c172b999d6afc88ce6640aeba9962sewardj                  binop( Iop_Shr32,
117214c96e61dd85c172b999d6afc88ce6640aeba9962sewardj                         unop( Iop_64HIto32, mkexpr( frBI64 ) ),
117224c96e61dd85c172b999d6afc88ce6640aeba9962sewardj                         mkU8( 31 - 5 ) ) ); // G-field[0:4]
117234c96e61dd85c172b999d6afc88ce6640aeba9962sewardj
117244c96e61dd85c172b999d6afc88ce6640aeba9962sewardj         assign( result,
117254c96e61dd85c172b999d6afc88ce6640aeba9962sewardj                 binop( Iop_32HLto64,
117264c96e61dd85c172b999d6afc88ce6640aeba9962sewardj                        binop( Iop_Or32,
117274c96e61dd85c172b999d6afc88ce6640aeba9962sewardj                               binop( Iop_Shl32, mkexpr( lmd ), mkU8( 28 ) ),
117284c96e61dd85c172b999d6afc88ce6640aeba9962sewardj                               mkexpr( bcd_u ) ),
117294c96e61dd85c172b999d6afc88ce6640aeba9962sewardj                        mkexpr( bcd_l ) ) );
117304c96e61dd85c172b999d6afc88ce6640aeba9962sewardj
117314c96e61dd85c172b999d6afc88ce6640aeba9962sewardj      } else {
117324c96e61dd85c172b999d6afc88ce6640aeba9962sewardj         /* Signed BCD string, the cases for sp 2 and 3 only differ in how
117334c96e61dd85c172b999d6afc88ce6640aeba9962sewardj          * the positive and negative values are encoded in the least
117344c96e61dd85c172b999d6afc88ce6640aeba9962sewardj          * significant bits.
117354c96e61dd85c172b999d6afc88ce6640aeba9962sewardj          */
117364c96e61dd85c172b999d6afc88ce6640aeba9962sewardj         IRTemp sign = newTemp( Ity_I32 );
117374c96e61dd85c172b999d6afc88ce6640aeba9962sewardj
117384c96e61dd85c172b999d6afc88ce6640aeba9962sewardj         if (sp == 2) {
117394c96e61dd85c172b999d6afc88ce6640aeba9962sewardj            /* Positive sign = 0xC, negative sign = 0xD */
117404c96e61dd85c172b999d6afc88ce6640aeba9962sewardj
117414c96e61dd85c172b999d6afc88ce6640aeba9962sewardj            assign( sign,
117424c96e61dd85c172b999d6afc88ce6640aeba9962sewardj                    binop( Iop_Or32,
117434c96e61dd85c172b999d6afc88ce6640aeba9962sewardj                           binop( Iop_Shr32,
117444c96e61dd85c172b999d6afc88ce6640aeba9962sewardj                                  unop( Iop_64HIto32, mkexpr( frBI64 ) ),
117454c96e61dd85c172b999d6afc88ce6640aeba9962sewardj                                  mkU8( 31 ) ),
117464c96e61dd85c172b999d6afc88ce6640aeba9962sewardj                           mkU32( 0xC ) ) );
117474c96e61dd85c172b999d6afc88ce6640aeba9962sewardj
117484c96e61dd85c172b999d6afc88ce6640aeba9962sewardj         } else if ( sp == 3 ) {
117494c96e61dd85c172b999d6afc88ce6640aeba9962sewardj            /* Positive sign = 0xF, negative sign = 0xD */
117504c96e61dd85c172b999d6afc88ce6640aeba9962sewardj            IRTemp tmp32 = newTemp( Ity_I32 );
117514c96e61dd85c172b999d6afc88ce6640aeba9962sewardj
117524c96e61dd85c172b999d6afc88ce6640aeba9962sewardj            /* Complement sign bit then OR into bit position 1 */
117534c96e61dd85c172b999d6afc88ce6640aeba9962sewardj            assign( tmp32,
117544c96e61dd85c172b999d6afc88ce6640aeba9962sewardj                    binop( Iop_Xor32,
117554c96e61dd85c172b999d6afc88ce6640aeba9962sewardj                           binop( Iop_Shr32,
117564c96e61dd85c172b999d6afc88ce6640aeba9962sewardj                                  unop( Iop_64HIto32, mkexpr( frBI64 ) ),
117574c96e61dd85c172b999d6afc88ce6640aeba9962sewardj                                  mkU8( 30 ) ),
117584c96e61dd85c172b999d6afc88ce6640aeba9962sewardj                           mkU32( 0x2 ) ) );
117594c96e61dd85c172b999d6afc88ce6640aeba9962sewardj
117604c96e61dd85c172b999d6afc88ce6640aeba9962sewardj            assign( sign, binop( Iop_Or32, mkexpr( tmp32 ), mkU32( 0xD ) ) );
117614c96e61dd85c172b999d6afc88ce6640aeba9962sewardj
117624c96e61dd85c172b999d6afc88ce6640aeba9962sewardj         } else {
117634c96e61dd85c172b999d6afc88ce6640aeba9962sewardj            vpanic( "The impossible happened: dis_dfp_bcd(ppc), undefined SP field" );
117644c96e61dd85c172b999d6afc88ce6640aeba9962sewardj         }
117654c96e61dd85c172b999d6afc88ce6640aeba9962sewardj
117664c96e61dd85c172b999d6afc88ce6640aeba9962sewardj         /* Put sign in bottom 4 bits, move most significant 4-bits from
117674c96e61dd85c172b999d6afc88ce6640aeba9962sewardj          * bcd_l to bcd_u.
117684c96e61dd85c172b999d6afc88ce6640aeba9962sewardj          */
117694c96e61dd85c172b999d6afc88ce6640aeba9962sewardj         assign( result,
117704c96e61dd85c172b999d6afc88ce6640aeba9962sewardj                 binop( Iop_32HLto64,
117714c96e61dd85c172b999d6afc88ce6640aeba9962sewardj                        binop( Iop_Or32,
117724c96e61dd85c172b999d6afc88ce6640aeba9962sewardj                               binop( Iop_Shr32,
117734c96e61dd85c172b999d6afc88ce6640aeba9962sewardj                                      mkexpr( bcd_l ),
117744c96e61dd85c172b999d6afc88ce6640aeba9962sewardj                                      mkU8( 28 ) ),
117754c96e61dd85c172b999d6afc88ce6640aeba9962sewardj                               binop( Iop_Shl32,
117764c96e61dd85c172b999d6afc88ce6640aeba9962sewardj                                      mkexpr( bcd_u ),
117774c96e61dd85c172b999d6afc88ce6640aeba9962sewardj                                      mkU8( 4 ) ) ),
117784c96e61dd85c172b999d6afc88ce6640aeba9962sewardj                        binop( Iop_Or32,
117794c96e61dd85c172b999d6afc88ce6640aeba9962sewardj                                      mkexpr( sign ),
117804c96e61dd85c172b999d6afc88ce6640aeba9962sewardj                               binop( Iop_Shl32,
117814c96e61dd85c172b999d6afc88ce6640aeba9962sewardj                                      mkexpr( bcd_l ),
117824c96e61dd85c172b999d6afc88ce6640aeba9962sewardj                                      mkU8( 4 ) ) ) ) );
117834c96e61dd85c172b999d6afc88ce6640aeba9962sewardj      }
117844c96e61dd85c172b999d6afc88ce6640aeba9962sewardj
117854c96e61dd85c172b999d6afc88ce6640aeba9962sewardj      putDReg( frT_addr, unop( Iop_ReinterpI64asD64, mkexpr( result ) ) );
117864c96e61dd85c172b999d6afc88ce6640aeba9962sewardj      break;
117874c96e61dd85c172b999d6afc88ce6640aeba9962sewardj
117884c96e61dd85c172b999d6afc88ce6640aeba9962sewardj   case 0x342: // denbcd   DFP Encode BCD to DPD
117894c96e61dd85c172b999d6afc88ce6640aeba9962sewardj   {
117904c96e61dd85c172b999d6afc88ce6640aeba9962sewardj      IRTemp valid_mask   = newTemp( Ity_I32 );
117914c96e61dd85c172b999d6afc88ce6640aeba9962sewardj      IRTemp invalid_mask = newTemp( Ity_I32 );
117924c96e61dd85c172b999d6afc88ce6640aeba9962sewardj      IRTemp without_lmd  = newTemp( Ity_I64 );
117934c96e61dd85c172b999d6afc88ce6640aeba9962sewardj      IRTemp tmp64        = newTemp( Ity_I64 );
117944c96e61dd85c172b999d6afc88ce6640aeba9962sewardj      IRTemp dbcd64       = newTemp( Ity_I64 );
117954c96e61dd85c172b999d6afc88ce6640aeba9962sewardj      IRTemp left_exp     = newTemp( Ity_I32 );
117964c96e61dd85c172b999d6afc88ce6640aeba9962sewardj      IRTemp g0_4         = newTemp( Ity_I32 );
117974c96e61dd85c172b999d6afc88ce6640aeba9962sewardj
117984c96e61dd85c172b999d6afc88ce6640aeba9962sewardj      DIP( "denbcd %llu,r%u,r%u\n", s, frT_addr, frB_addr );
117994c96e61dd85c172b999d6afc88ce6640aeba9962sewardj
118004c96e61dd85c172b999d6afc88ce6640aeba9962sewardj      if ( s == 0 ) {
118014c96e61dd85c172b999d6afc88ce6640aeba9962sewardj         /* Unsigned BCD string */
118024c96e61dd85c172b999d6afc88ce6640aeba9962sewardj         assign( dbcd64, unop( Iop_BCDtoDPB, mkexpr(frBI64 ) ) );
118034c96e61dd85c172b999d6afc88ce6640aeba9962sewardj         assign( dbcd_u, unop( Iop_64HIto32, mkexpr( dbcd64 ) ) );
118044c96e61dd85c172b999d6afc88ce6640aeba9962sewardj         assign( dbcd_l, unop( Iop_64to32, mkexpr( dbcd64 ) ) );
118054c96e61dd85c172b999d6afc88ce6640aeba9962sewardj
118064c96e61dd85c172b999d6afc88ce6640aeba9962sewardj         assign( lmd,
118074c96e61dd85c172b999d6afc88ce6640aeba9962sewardj                 binop( Iop_Shr32,
118084c96e61dd85c172b999d6afc88ce6640aeba9962sewardj                        binop( Iop_And32,
118094c96e61dd85c172b999d6afc88ce6640aeba9962sewardj                               unop( Iop_64HIto32, mkexpr( frBI64 ) ),
118104c96e61dd85c172b999d6afc88ce6640aeba9962sewardj                               mkU32( 0xF0000000 ) ),
118114c96e61dd85c172b999d6afc88ce6640aeba9962sewardj                        mkU8( 28 ) ) );
118124c96e61dd85c172b999d6afc88ce6640aeba9962sewardj
118134c96e61dd85c172b999d6afc88ce6640aeba9962sewardj         assign( invalid_mask,
118144c96e61dd85c172b999d6afc88ce6640aeba9962sewardj                 bcd_digit_inval( unop( Iop_64HIto32, mkexpr( frBI64 ) ),
118154c96e61dd85c172b999d6afc88ce6640aeba9962sewardj                                  unop( Iop_64to32, mkexpr( frBI64 ) ) ) );
118164c96e61dd85c172b999d6afc88ce6640aeba9962sewardj         assign( valid_mask, unop( Iop_Not32, mkexpr( invalid_mask ) ) );
118174c96e61dd85c172b999d6afc88ce6640aeba9962sewardj
118184c96e61dd85c172b999d6afc88ce6640aeba9962sewardj         assign( without_lmd,
118194c96e61dd85c172b999d6afc88ce6640aeba9962sewardj                 unop( Iop_ReinterpD64asI64,
118204c96e61dd85c172b999d6afc88ce6640aeba9962sewardj                       binop( Iop_InsertExpD64,
11821cea07ccbe9aa9b5fd8e9b318471c6c74aa147acbcarll                              mkU64( DFP_LONG_BIAS ),
118224c96e61dd85c172b999d6afc88ce6640aeba9962sewardj                              unop( Iop_ReinterpI64asD64,
118234c96e61dd85c172b999d6afc88ce6640aeba9962sewardj                                    binop( Iop_32HLto64,
118244c96e61dd85c172b999d6afc88ce6640aeba9962sewardj                                           mkexpr( dbcd_u ),
118254c96e61dd85c172b999d6afc88ce6640aeba9962sewardj                                           mkexpr( dbcd_l ) ) ) ) ) );
118264c96e61dd85c172b999d6afc88ce6640aeba9962sewardj         assign( left_exp,
118274c96e61dd85c172b999d6afc88ce6640aeba9962sewardj                 binop( Iop_Shr32,
118284c96e61dd85c172b999d6afc88ce6640aeba9962sewardj                        binop( Iop_And32,
118294c96e61dd85c172b999d6afc88ce6640aeba9962sewardj                               unop( Iop_64HIto32, mkexpr( without_lmd ) ),
118304c96e61dd85c172b999d6afc88ce6640aeba9962sewardj                               mkU32( 0x60000000 ) ),
118314c96e61dd85c172b999d6afc88ce6640aeba9962sewardj                        mkU8( 29 ) ) );
118324c96e61dd85c172b999d6afc88ce6640aeba9962sewardj
118334c96e61dd85c172b999d6afc88ce6640aeba9962sewardj         assign( g0_4,
118344c96e61dd85c172b999d6afc88ce6640aeba9962sewardj                 binop( Iop_Shl32,
118354c96e61dd85c172b999d6afc88ce6640aeba9962sewardj                        Gfield_encoding( mkexpr( left_exp ), mkexpr( lmd ) ),
118364c96e61dd85c172b999d6afc88ce6640aeba9962sewardj                        mkU8( 26 ) ) );
118374c96e61dd85c172b999d6afc88ce6640aeba9962sewardj
118384c96e61dd85c172b999d6afc88ce6640aeba9962sewardj         assign( tmp64,
118394c96e61dd85c172b999d6afc88ce6640aeba9962sewardj                 binop( Iop_32HLto64,
118404c96e61dd85c172b999d6afc88ce6640aeba9962sewardj                        binop( Iop_Or32,
118414c96e61dd85c172b999d6afc88ce6640aeba9962sewardj                               binop( Iop_And32,
118424c96e61dd85c172b999d6afc88ce6640aeba9962sewardj                                      unop( Iop_64HIto32,
118434c96e61dd85c172b999d6afc88ce6640aeba9962sewardj                                            mkexpr( without_lmd ) ),
118444c96e61dd85c172b999d6afc88ce6640aeba9962sewardj                                      mkU32( 0x83FFFFFF ) ),
118454c96e61dd85c172b999d6afc88ce6640aeba9962sewardj                               mkexpr( g0_4 ) ),
118464c96e61dd85c172b999d6afc88ce6640aeba9962sewardj                        unop( Iop_64to32, mkexpr( without_lmd ) ) ) );
118474c96e61dd85c172b999d6afc88ce6640aeba9962sewardj
118484c96e61dd85c172b999d6afc88ce6640aeba9962sewardj      } else if ( s == 1 ) {
118494c96e61dd85c172b999d6afc88ce6640aeba9962sewardj         IRTemp sign = newTemp( Ity_I32 );
118504c96e61dd85c172b999d6afc88ce6640aeba9962sewardj         IRTemp sign_bit = newTemp( Ity_I32 );
118514c96e61dd85c172b999d6afc88ce6640aeba9962sewardj         IRTemp pos_sign_mask = newTemp( Ity_I32 );
118524c96e61dd85c172b999d6afc88ce6640aeba9962sewardj         IRTemp neg_sign_mask = newTemp( Ity_I32 );
118534c96e61dd85c172b999d6afc88ce6640aeba9962sewardj         IRTemp tmp = newTemp( Ity_I64 );
118544c96e61dd85c172b999d6afc88ce6640aeba9962sewardj
118554c96e61dd85c172b999d6afc88ce6640aeba9962sewardj         /* Signed BCD string, least significant 4 bits are sign bits
118564c96e61dd85c172b999d6afc88ce6640aeba9962sewardj          * positive sign = 0xC, negative sign = 0xD
118574c96e61dd85c172b999d6afc88ce6640aeba9962sewardj          */
118584c96e61dd85c172b999d6afc88ce6640aeba9962sewardj         assign( tmp, unop( Iop_BCDtoDPB,
118594c96e61dd85c172b999d6afc88ce6640aeba9962sewardj                            binop( Iop_32HLto64,
118604c96e61dd85c172b999d6afc88ce6640aeba9962sewardj                                   binop( Iop_Shr32,
118614c96e61dd85c172b999d6afc88ce6640aeba9962sewardj                                          unop( Iop_64HIto32,
118624c96e61dd85c172b999d6afc88ce6640aeba9962sewardj                                                mkexpr( frBI64 ) ),
118634c96e61dd85c172b999d6afc88ce6640aeba9962sewardj                                                mkU8( 4 ) ),
118644c96e61dd85c172b999d6afc88ce6640aeba9962sewardj                                   binop( Iop_Or32,
118654c96e61dd85c172b999d6afc88ce6640aeba9962sewardj                                          binop( Iop_Shr32,
118664c96e61dd85c172b999d6afc88ce6640aeba9962sewardj                                                 unop( Iop_64to32,
118674c96e61dd85c172b999d6afc88ce6640aeba9962sewardj                                                       mkexpr( frBI64 ) ),
118684c96e61dd85c172b999d6afc88ce6640aeba9962sewardj                                                  mkU8( 4 ) ),
118694c96e61dd85c172b999d6afc88ce6640aeba9962sewardj                                          binop( Iop_Shl32,
118704c96e61dd85c172b999d6afc88ce6640aeba9962sewardj                                                 unop( Iop_64HIto32,
118714c96e61dd85c172b999d6afc88ce6640aeba9962sewardj                                                       mkexpr( frBI64 ) ),
118724c96e61dd85c172b999d6afc88ce6640aeba9962sewardj                                                       mkU8( 28 ) ) ) ) ) );
118734c96e61dd85c172b999d6afc88ce6640aeba9962sewardj
118744c96e61dd85c172b999d6afc88ce6640aeba9962sewardj         assign( dbcd_u, unop( Iop_64HIto32, mkexpr( tmp ) ) );
118754c96e61dd85c172b999d6afc88ce6640aeba9962sewardj         assign( dbcd_l, unop( Iop_64to32, mkexpr( tmp ) ) );
118764c96e61dd85c172b999d6afc88ce6640aeba9962sewardj
118774c96e61dd85c172b999d6afc88ce6640aeba9962sewardj         /* Get the sign of the BCD string. */
118784c96e61dd85c172b999d6afc88ce6640aeba9962sewardj         assign( sign,
118794c96e61dd85c172b999d6afc88ce6640aeba9962sewardj                 binop( Iop_And32,
118804c96e61dd85c172b999d6afc88ce6640aeba9962sewardj                        unop( Iop_64to32, mkexpr( frBI64 ) ),
118814c96e61dd85c172b999d6afc88ce6640aeba9962sewardj                        mkU32( 0xF ) ) );
118824c96e61dd85c172b999d6afc88ce6640aeba9962sewardj
118834c96e61dd85c172b999d6afc88ce6640aeba9962sewardj         assign( neg_sign_mask, Generate_neg_sign_mask( mkexpr( sign ) ) );
118844c96e61dd85c172b999d6afc88ce6640aeba9962sewardj         assign( pos_sign_mask, Generate_pos_sign_mask( mkexpr( sign ) ) );
118854c96e61dd85c172b999d6afc88ce6640aeba9962sewardj         assign( sign_bit,
118864c96e61dd85c172b999d6afc88ce6640aeba9962sewardj                 Generate_sign_bit( mkexpr( pos_sign_mask ),
118874c96e61dd85c172b999d6afc88ce6640aeba9962sewardj                                    mkexpr( neg_sign_mask ) ) );
118884c96e61dd85c172b999d6afc88ce6640aeba9962sewardj
118894c96e61dd85c172b999d6afc88ce6640aeba9962sewardj         /* Check for invalid sign and BCD digit.  Don't check the bottom
118904c96e61dd85c172b999d6afc88ce6640aeba9962sewardj          * four bits of bcd_l as that is the sign value.
118914c96e61dd85c172b999d6afc88ce6640aeba9962sewardj          */
118924c96e61dd85c172b999d6afc88ce6640aeba9962sewardj         assign( invalid_mask,
118934c96e61dd85c172b999d6afc88ce6640aeba9962sewardj                 Generate_inv_mask(
118944c96e61dd85c172b999d6afc88ce6640aeba9962sewardj                                   bcd_digit_inval( unop( Iop_64HIto32,
118954c96e61dd85c172b999d6afc88ce6640aeba9962sewardj                                                          mkexpr( frBI64 ) ),
118964c96e61dd85c172b999d6afc88ce6640aeba9962sewardj                                                    binop( Iop_Shr32,
118974c96e61dd85c172b999d6afc88ce6640aeba9962sewardj                                                           unop( Iop_64to32,
118984c96e61dd85c172b999d6afc88ce6640aeba9962sewardj                                                                 mkexpr( frBI64 ) ),
118994c96e61dd85c172b999d6afc88ce6640aeba9962sewardj                                                           mkU8( 4 ) ) ),
119004c96e61dd85c172b999d6afc88ce6640aeba9962sewardj                                   mkexpr( pos_sign_mask ),
119014c96e61dd85c172b999d6afc88ce6640aeba9962sewardj                                   mkexpr( neg_sign_mask ) ) );
119024c96e61dd85c172b999d6afc88ce6640aeba9962sewardj
119034c96e61dd85c172b999d6afc88ce6640aeba9962sewardj         assign( valid_mask, unop( Iop_Not32, mkexpr( invalid_mask ) ) );
119044c96e61dd85c172b999d6afc88ce6640aeba9962sewardj
119054c96e61dd85c172b999d6afc88ce6640aeba9962sewardj         /* Generate the result assuming the sign value was valid. */
119064c96e61dd85c172b999d6afc88ce6640aeba9962sewardj         assign( tmp64,
119074c96e61dd85c172b999d6afc88ce6640aeba9962sewardj                 unop( Iop_ReinterpD64asI64,
119084c96e61dd85c172b999d6afc88ce6640aeba9962sewardj                       binop( Iop_InsertExpD64,
11909cea07ccbe9aa9b5fd8e9b318471c6c74aa147acbcarll                              mkU64( DFP_LONG_BIAS ),
119104c96e61dd85c172b999d6afc88ce6640aeba9962sewardj                              unop( Iop_ReinterpI64asD64,
119114c96e61dd85c172b999d6afc88ce6640aeba9962sewardj                                    binop( Iop_32HLto64,
119124c96e61dd85c172b999d6afc88ce6640aeba9962sewardj                                           binop( Iop_Or32,
119134c96e61dd85c172b999d6afc88ce6640aeba9962sewardj                                                  mkexpr( dbcd_u ),
119144c96e61dd85c172b999d6afc88ce6640aeba9962sewardj                                                  mkexpr( sign_bit ) ),
119154c96e61dd85c172b999d6afc88ce6640aeba9962sewardj                                           mkexpr( dbcd_l ) ) ) ) ) );
119164c96e61dd85c172b999d6afc88ce6640aeba9962sewardj      }
119174c96e61dd85c172b999d6afc88ce6640aeba9962sewardj
119184c96e61dd85c172b999d6afc88ce6640aeba9962sewardj      /* Generate the value to store depending on the validity of the
119194c96e61dd85c172b999d6afc88ce6640aeba9962sewardj       * sign value and the validity of the BCD digits.
119204c96e61dd85c172b999d6afc88ce6640aeba9962sewardj       */
119214c96e61dd85c172b999d6afc88ce6640aeba9962sewardj      assign( resultD64,
119224c96e61dd85c172b999d6afc88ce6640aeba9962sewardj              unop( Iop_ReinterpI64asD64,
119234c96e61dd85c172b999d6afc88ce6640aeba9962sewardj                    binop( Iop_32HLto64,
119244c96e61dd85c172b999d6afc88ce6640aeba9962sewardj                           binop( Iop_Or32,
119254c96e61dd85c172b999d6afc88ce6640aeba9962sewardj                                  binop( Iop_And32,
119264c96e61dd85c172b999d6afc88ce6640aeba9962sewardj                                         mkexpr( valid_mask ),
119274c96e61dd85c172b999d6afc88ce6640aeba9962sewardj                                         unop( Iop_64HIto32,
119284c96e61dd85c172b999d6afc88ce6640aeba9962sewardj                                               mkexpr( tmp64 ) ) ),
119294c96e61dd85c172b999d6afc88ce6640aeba9962sewardj                                  binop( Iop_And32,
119304c96e61dd85c172b999d6afc88ce6640aeba9962sewardj                                         mkU32( 0x7C000000 ),
119314c96e61dd85c172b999d6afc88ce6640aeba9962sewardj                                         mkexpr( invalid_mask ) ) ),
119324c96e61dd85c172b999d6afc88ce6640aeba9962sewardj                           binop( Iop_Or32,
119334c96e61dd85c172b999d6afc88ce6640aeba9962sewardj                                  binop( Iop_And32,
119344c96e61dd85c172b999d6afc88ce6640aeba9962sewardj                                         mkexpr( valid_mask ),
119354c96e61dd85c172b999d6afc88ce6640aeba9962sewardj                                         unop( Iop_64to32, mkexpr( tmp64 ) ) ),
119364c96e61dd85c172b999d6afc88ce6640aeba9962sewardj                                  binop( Iop_And32,
119374c96e61dd85c172b999d6afc88ce6640aeba9962sewardj                                         mkU32( 0x0 ),
119384c96e61dd85c172b999d6afc88ce6640aeba9962sewardj                                         mkexpr( invalid_mask ) ) ) ) ) );
119394c96e61dd85c172b999d6afc88ce6640aeba9962sewardj      putDReg( frT_addr, mkexpr( resultD64 ) );
119404c96e61dd85c172b999d6afc88ce6640aeba9962sewardj   }
119414c96e61dd85c172b999d6afc88ce6640aeba9962sewardj   break;
119424c96e61dd85c172b999d6afc88ce6640aeba9962sewardj   default:
119434c96e61dd85c172b999d6afc88ce6640aeba9962sewardj      vpanic( "ERROR: dis_dfp_bcd(ppc), undefined opc2 case " );
119444c96e61dd85c172b999d6afc88ce6640aeba9962sewardj      return False;
119454c96e61dd85c172b999d6afc88ce6640aeba9962sewardj   }
119464c96e61dd85c172b999d6afc88ce6640aeba9962sewardj   return True;
119474c96e61dd85c172b999d6afc88ce6640aeba9962sewardj}
119484c96e61dd85c172b999d6afc88ce6640aeba9962sewardj
119494c96e61dd85c172b999d6afc88ce6640aeba9962sewardjstatic Bool dis_dfp_bcdq( UInt theInstr )
119504c96e61dd85c172b999d6afc88ce6640aeba9962sewardj{
119514c96e61dd85c172b999d6afc88ce6640aeba9962sewardj   UInt opc2        = ifieldOPClo10( theInstr );
119524c96e61dd85c172b999d6afc88ce6640aeba9962sewardj   ULong sp         = IFIELD(theInstr, 19, 2);
119534c96e61dd85c172b999d6afc88ce6640aeba9962sewardj   ULong s          = IFIELD(theInstr, 20, 1);
119544c96e61dd85c172b999d6afc88ce6640aeba9962sewardj   IRTemp frB_hi    = newTemp( Ity_D64 );
119554c96e61dd85c172b999d6afc88ce6640aeba9962sewardj   IRTemp frB_lo    = newTemp( Ity_D64 );
119564c96e61dd85c172b999d6afc88ce6640aeba9962sewardj   IRTemp frBI64_hi = newTemp( Ity_I64 );
119574c96e61dd85c172b999d6afc88ce6640aeba9962sewardj   IRTemp frBI64_lo = newTemp( Ity_I64 );
119584c96e61dd85c172b999d6afc88ce6640aeba9962sewardj   UChar frT_addr   = ifieldRegDS( theInstr );
119594c96e61dd85c172b999d6afc88ce6640aeba9962sewardj   UChar frB_addr   = ifieldRegB( theInstr );
119604c96e61dd85c172b999d6afc88ce6640aeba9962sewardj
119614c96e61dd85c172b999d6afc88ce6640aeba9962sewardj   IRTemp lmd       = newTemp( Ity_I32 );
119624c96e61dd85c172b999d6afc88ce6640aeba9962sewardj   IRTemp result_hi = newTemp( Ity_I64 );
119634c96e61dd85c172b999d6afc88ce6640aeba9962sewardj   IRTemp result_lo = newTemp( Ity_I64 );
119644c96e61dd85c172b999d6afc88ce6640aeba9962sewardj
119654c96e61dd85c172b999d6afc88ce6640aeba9962sewardj   assign( frB_hi, getDReg( frB_addr ) );
119664c96e61dd85c172b999d6afc88ce6640aeba9962sewardj   assign( frB_lo, getDReg( frB_addr + 1 ) );
119674c96e61dd85c172b999d6afc88ce6640aeba9962sewardj   assign( frBI64_hi, unop( Iop_ReinterpD64asI64, mkexpr( frB_hi ) ) );
119684c96e61dd85c172b999d6afc88ce6640aeba9962sewardj   assign( frBI64_lo, unop( Iop_ReinterpD64asI64, mkexpr( frB_lo ) ) );
119694c96e61dd85c172b999d6afc88ce6640aeba9962sewardj
119704c96e61dd85c172b999d6afc88ce6640aeba9962sewardj   switch ( opc2 ) {
119714c96e61dd85c172b999d6afc88ce6640aeba9962sewardj   case 0x142: // ddedpdq   DFP Decode DPD to BCD
119724c96e61dd85c172b999d6afc88ce6640aeba9962sewardj   {
119734c96e61dd85c172b999d6afc88ce6640aeba9962sewardj      IRTemp low_60_u = newTemp( Ity_I32 );
119744c96e61dd85c172b999d6afc88ce6640aeba9962sewardj      IRTemp low_60_l = newTemp( Ity_I32 );
119754c96e61dd85c172b999d6afc88ce6640aeba9962sewardj      IRTemp mid_60_u = newTemp( Ity_I32 );
119764c96e61dd85c172b999d6afc88ce6640aeba9962sewardj      IRTemp mid_60_l = newTemp( Ity_I32 );
119774c96e61dd85c172b999d6afc88ce6640aeba9962sewardj      IRTemp top_12_l = newTemp( Ity_I32 );
119784c96e61dd85c172b999d6afc88ce6640aeba9962sewardj
119794c96e61dd85c172b999d6afc88ce6640aeba9962sewardj      DIP( "ddedpdq %llu,r%u,r%u\n", sp, frT_addr, frB_addr );
119804c96e61dd85c172b999d6afc88ce6640aeba9962sewardj
119814c96e61dd85c172b999d6afc88ce6640aeba9962sewardj      /* Note, instruction only stores the lower 32 BCD digits in
119824c96e61dd85c172b999d6afc88ce6640aeba9962sewardj       * the result
119834c96e61dd85c172b999d6afc88ce6640aeba9962sewardj       */
119844c96e61dd85c172b999d6afc88ce6640aeba9962sewardj      Generate_132_bit_bcd_string( mkexpr( frBI64_hi ),
119854c96e61dd85c172b999d6afc88ce6640aeba9962sewardj                                   mkexpr( frBI64_lo ),
119864c96e61dd85c172b999d6afc88ce6640aeba9962sewardj                                   &top_12_l,
119874c96e61dd85c172b999d6afc88ce6640aeba9962sewardj                                   &mid_60_u,
119884c96e61dd85c172b999d6afc88ce6640aeba9962sewardj                                   &mid_60_l,
119894c96e61dd85c172b999d6afc88ce6640aeba9962sewardj                                   &low_60_u,
119904c96e61dd85c172b999d6afc88ce6640aeba9962sewardj                                   &low_60_l );
119914c96e61dd85c172b999d6afc88ce6640aeba9962sewardj
119924c96e61dd85c172b999d6afc88ce6640aeba9962sewardj      if ( ( sp == 0 ) || ( sp == 1 ) ) {
119934c96e61dd85c172b999d6afc88ce6640aeba9962sewardj         /* Unsigned BCD string */
119944c96e61dd85c172b999d6afc88ce6640aeba9962sewardj         assign( result_hi,
119954c96e61dd85c172b999d6afc88ce6640aeba9962sewardj                 binop( Iop_32HLto64,
119964c96e61dd85c172b999d6afc88ce6640aeba9962sewardj                        binop( Iop_Or32,
119974c96e61dd85c172b999d6afc88ce6640aeba9962sewardj                               binop( Iop_Shl32,
119984c96e61dd85c172b999d6afc88ce6640aeba9962sewardj                                      mkexpr( top_12_l ),
119994c96e61dd85c172b999d6afc88ce6640aeba9962sewardj                                      mkU8( 24 ) ),
120004c96e61dd85c172b999d6afc88ce6640aeba9962sewardj                               binop( Iop_Shr32,
120014c96e61dd85c172b999d6afc88ce6640aeba9962sewardj                                      mkexpr( mid_60_u ),
120024c96e61dd85c172b999d6afc88ce6640aeba9962sewardj                                      mkU8( 4 ) ) ),
120034c96e61dd85c172b999d6afc88ce6640aeba9962sewardj                        binop( Iop_Or32,
120044c96e61dd85c172b999d6afc88ce6640aeba9962sewardj                               binop( Iop_Shl32,
120054c96e61dd85c172b999d6afc88ce6640aeba9962sewardj                                      mkexpr( mid_60_u ),
120064c96e61dd85c172b999d6afc88ce6640aeba9962sewardj                                      mkU8( 28 ) ),
120074c96e61dd85c172b999d6afc88ce6640aeba9962sewardj                               binop( Iop_Shr32,
120084c96e61dd85c172b999d6afc88ce6640aeba9962sewardj                                      mkexpr( mid_60_l ),
120094c96e61dd85c172b999d6afc88ce6640aeba9962sewardj                                      mkU8( 4 ) ) ) ) );
120104c96e61dd85c172b999d6afc88ce6640aeba9962sewardj
120114c96e61dd85c172b999d6afc88ce6640aeba9962sewardj         assign( result_lo,
120124c96e61dd85c172b999d6afc88ce6640aeba9962sewardj                 binop( Iop_32HLto64,
120134c96e61dd85c172b999d6afc88ce6640aeba9962sewardj                        binop( Iop_Or32,
120144c96e61dd85c172b999d6afc88ce6640aeba9962sewardj                               binop( Iop_Shl32,
120154c96e61dd85c172b999d6afc88ce6640aeba9962sewardj                                      mkexpr( mid_60_l ),
120164c96e61dd85c172b999d6afc88ce6640aeba9962sewardj                                      mkU8( 28 ) ),
120174c96e61dd85c172b999d6afc88ce6640aeba9962sewardj                               mkexpr( low_60_u ) ),
120184c96e61dd85c172b999d6afc88ce6640aeba9962sewardj                        mkexpr( low_60_l ) ) );
120194c96e61dd85c172b999d6afc88ce6640aeba9962sewardj
120204c96e61dd85c172b999d6afc88ce6640aeba9962sewardj      } else {
120214c96e61dd85c172b999d6afc88ce6640aeba9962sewardj         /* Signed BCD string, the cases for sp 2 and 3 only differ in how
120224c96e61dd85c172b999d6afc88ce6640aeba9962sewardj          * the positive and negative values are encoded in the least
120234c96e61dd85c172b999d6afc88ce6640aeba9962sewardj          * significant bits.
120244c96e61dd85c172b999d6afc88ce6640aeba9962sewardj          */
120254c96e61dd85c172b999d6afc88ce6640aeba9962sewardj         IRTemp sign = newTemp( Ity_I32 );
120264c96e61dd85c172b999d6afc88ce6640aeba9962sewardj
120274c96e61dd85c172b999d6afc88ce6640aeba9962sewardj         if ( sp == 2 ) {
120284c96e61dd85c172b999d6afc88ce6640aeba9962sewardj            /* Positive sign = 0xC, negative sign = 0xD */
120294c96e61dd85c172b999d6afc88ce6640aeba9962sewardj            assign( sign,
120304c96e61dd85c172b999d6afc88ce6640aeba9962sewardj                    binop( Iop_Or32,
120314c96e61dd85c172b999d6afc88ce6640aeba9962sewardj                           binop( Iop_Shr32,
120324c96e61dd85c172b999d6afc88ce6640aeba9962sewardj                                  unop( Iop_64HIto32, mkexpr( frBI64_hi ) ),
120334c96e61dd85c172b999d6afc88ce6640aeba9962sewardj                                  mkU8( 31 ) ),
120344c96e61dd85c172b999d6afc88ce6640aeba9962sewardj                           mkU32( 0xC ) ) );
120354c96e61dd85c172b999d6afc88ce6640aeba9962sewardj
120364c96e61dd85c172b999d6afc88ce6640aeba9962sewardj         } else if ( sp == 3 ) {
120374c96e61dd85c172b999d6afc88ce6640aeba9962sewardj            IRTemp tmp32 = newTemp( Ity_I32 );
120384c96e61dd85c172b999d6afc88ce6640aeba9962sewardj
120394c96e61dd85c172b999d6afc88ce6640aeba9962sewardj            /* Positive sign = 0xF, negative sign = 0xD.
120404c96e61dd85c172b999d6afc88ce6640aeba9962sewardj             * Need to complement sign bit then OR into bit position 1.
120414c96e61dd85c172b999d6afc88ce6640aeba9962sewardj             */
120424c96e61dd85c172b999d6afc88ce6640aeba9962sewardj            assign( tmp32,
120434c96e61dd85c172b999d6afc88ce6640aeba9962sewardj                    binop( Iop_Xor32,
120444c96e61dd85c172b999d6afc88ce6640aeba9962sewardj                           binop( Iop_Shr32,
120454c96e61dd85c172b999d6afc88ce6640aeba9962sewardj                                  unop( Iop_64HIto32, mkexpr( frBI64_hi ) ),
120464c96e61dd85c172b999d6afc88ce6640aeba9962sewardj                                  mkU8( 30 ) ),
120474c96e61dd85c172b999d6afc88ce6640aeba9962sewardj                           mkU32( 0x2 ) ) );
120484c96e61dd85c172b999d6afc88ce6640aeba9962sewardj
120494c96e61dd85c172b999d6afc88ce6640aeba9962sewardj            assign( sign, binop( Iop_Or32, mkexpr( tmp32 ), mkU32( 0xD ) ) );
120504c96e61dd85c172b999d6afc88ce6640aeba9962sewardj
120514c96e61dd85c172b999d6afc88ce6640aeba9962sewardj         } else {
120524c96e61dd85c172b999d6afc88ce6640aeba9962sewardj            vpanic( "The impossible happened: dis_dfp_bcd(ppc), undefined SP field" );
120534c96e61dd85c172b999d6afc88ce6640aeba9962sewardj         }
120544c96e61dd85c172b999d6afc88ce6640aeba9962sewardj
120554c96e61dd85c172b999d6afc88ce6640aeba9962sewardj         assign( result_hi,
120564c96e61dd85c172b999d6afc88ce6640aeba9962sewardj                 binop( Iop_32HLto64,
120574c96e61dd85c172b999d6afc88ce6640aeba9962sewardj                        binop( Iop_Or32,
120584c96e61dd85c172b999d6afc88ce6640aeba9962sewardj                               binop( Iop_Shl32,
120594c96e61dd85c172b999d6afc88ce6640aeba9962sewardj                                      mkexpr( top_12_l ),
120604c96e61dd85c172b999d6afc88ce6640aeba9962sewardj                                      mkU8( 28 ) ),
120614c96e61dd85c172b999d6afc88ce6640aeba9962sewardj                               mkexpr( mid_60_u ) ),
120624c96e61dd85c172b999d6afc88ce6640aeba9962sewardj                        mkexpr( mid_60_l ) ) );
120634c96e61dd85c172b999d6afc88ce6640aeba9962sewardj
120644c96e61dd85c172b999d6afc88ce6640aeba9962sewardj         assign( result_lo,
120654c96e61dd85c172b999d6afc88ce6640aeba9962sewardj                 binop( Iop_32HLto64,
120664c96e61dd85c172b999d6afc88ce6640aeba9962sewardj                        binop( Iop_Or32,
120674c96e61dd85c172b999d6afc88ce6640aeba9962sewardj                               binop( Iop_Shl32,
120684c96e61dd85c172b999d6afc88ce6640aeba9962sewardj                                      mkexpr( low_60_u ),
120694c96e61dd85c172b999d6afc88ce6640aeba9962sewardj                                      mkU8( 4 ) ),
120704c96e61dd85c172b999d6afc88ce6640aeba9962sewardj                               binop( Iop_Shr32,
120714c96e61dd85c172b999d6afc88ce6640aeba9962sewardj                                      mkexpr( low_60_l ),
120724c96e61dd85c172b999d6afc88ce6640aeba9962sewardj                                      mkU8( 28 ) ) ),
120734c96e61dd85c172b999d6afc88ce6640aeba9962sewardj                        binop( Iop_Or32,
120744c96e61dd85c172b999d6afc88ce6640aeba9962sewardj                               binop( Iop_Shl32,
120754c96e61dd85c172b999d6afc88ce6640aeba9962sewardj                                      mkexpr( low_60_l ),
120764c96e61dd85c172b999d6afc88ce6640aeba9962sewardj                                      mkU8( 4 ) ),
120774c96e61dd85c172b999d6afc88ce6640aeba9962sewardj                               mkexpr( sign ) ) ) );
120784c96e61dd85c172b999d6afc88ce6640aeba9962sewardj      }
120794c96e61dd85c172b999d6afc88ce6640aeba9962sewardj
120804c96e61dd85c172b999d6afc88ce6640aeba9962sewardj      putDReg( frT_addr, unop( Iop_ReinterpI64asD64, mkexpr( result_hi ) ) );
120814c96e61dd85c172b999d6afc88ce6640aeba9962sewardj      putDReg( frT_addr + 1,
120824c96e61dd85c172b999d6afc88ce6640aeba9962sewardj               unop( Iop_ReinterpI64asD64, mkexpr( result_lo ) ) );
120834c96e61dd85c172b999d6afc88ce6640aeba9962sewardj   }
120844c96e61dd85c172b999d6afc88ce6640aeba9962sewardj   break;
120854c96e61dd85c172b999d6afc88ce6640aeba9962sewardj   case 0x342: // denbcdq   DFP Encode BCD to DPD
120864c96e61dd85c172b999d6afc88ce6640aeba9962sewardj   {
120874c96e61dd85c172b999d6afc88ce6640aeba9962sewardj      IRTemp valid_mask      = newTemp( Ity_I32 );
120884c96e61dd85c172b999d6afc88ce6640aeba9962sewardj      IRTemp invalid_mask    = newTemp( Ity_I32 );
120894c96e61dd85c172b999d6afc88ce6640aeba9962sewardj      IRTemp result128       = newTemp( Ity_D128 );
120904c96e61dd85c172b999d6afc88ce6640aeba9962sewardj      IRTemp dfp_significand = newTemp( Ity_D128 );
120914c96e61dd85c172b999d6afc88ce6640aeba9962sewardj      IRTemp tmp_hi          = newTemp( Ity_I64 );
120924c96e61dd85c172b999d6afc88ce6640aeba9962sewardj      IRTemp tmp_lo          = newTemp( Ity_I64 );
120934c96e61dd85c172b999d6afc88ce6640aeba9962sewardj      IRTemp dbcd_top_l      = newTemp( Ity_I32 );
120944c96e61dd85c172b999d6afc88ce6640aeba9962sewardj      IRTemp dbcd_mid_u      = newTemp( Ity_I32 );
120954c96e61dd85c172b999d6afc88ce6640aeba9962sewardj      IRTemp dbcd_mid_l      = newTemp( Ity_I32 );
120964c96e61dd85c172b999d6afc88ce6640aeba9962sewardj      IRTemp dbcd_low_u      = newTemp( Ity_I32 );
120974c96e61dd85c172b999d6afc88ce6640aeba9962sewardj      IRTemp dbcd_low_l      = newTemp( Ity_I32 );
120984c96e61dd85c172b999d6afc88ce6640aeba9962sewardj      IRTemp bcd_top_8       = newTemp( Ity_I64 );
120994c96e61dd85c172b999d6afc88ce6640aeba9962sewardj      IRTemp bcd_mid_60      = newTemp( Ity_I64 );
121004c96e61dd85c172b999d6afc88ce6640aeba9962sewardj      IRTemp bcd_low_60      = newTemp( Ity_I64 );
121014c96e61dd85c172b999d6afc88ce6640aeba9962sewardj      IRTemp sign_bit        = newTemp( Ity_I32 );
121024c96e61dd85c172b999d6afc88ce6640aeba9962sewardj      IRTemp tmptop10        = newTemp( Ity_I64 );
121034c96e61dd85c172b999d6afc88ce6640aeba9962sewardj      IRTemp tmpmid50        = newTemp( Ity_I64 );
121044c96e61dd85c172b999d6afc88ce6640aeba9962sewardj      IRTemp tmplow50        = newTemp( Ity_I64 );
121054c96e61dd85c172b999d6afc88ce6640aeba9962sewardj      IRTemp inval_bcd_digit_mask = newTemp( Ity_I32 );
121064c96e61dd85c172b999d6afc88ce6640aeba9962sewardj
121074c96e61dd85c172b999d6afc88ce6640aeba9962sewardj      DIP( "denbcd %llu,r%u,r%u\n", s, frT_addr, frB_addr );
121084c96e61dd85c172b999d6afc88ce6640aeba9962sewardj
121094c96e61dd85c172b999d6afc88ce6640aeba9962sewardj      if ( s == 0 ) {
121104c96e61dd85c172b999d6afc88ce6640aeba9962sewardj         /* Unsigned BCD string */
121114c96e61dd85c172b999d6afc88ce6640aeba9962sewardj         assign( sign_bit, mkU32( 0 ) ); // set to zero for unsigned string
121124c96e61dd85c172b999d6afc88ce6640aeba9962sewardj
121134c96e61dd85c172b999d6afc88ce6640aeba9962sewardj         assign( bcd_top_8,
121144c96e61dd85c172b999d6afc88ce6640aeba9962sewardj                 binop( Iop_32HLto64,
121154c96e61dd85c172b999d6afc88ce6640aeba9962sewardj                        mkU32( 0 ),
121164c96e61dd85c172b999d6afc88ce6640aeba9962sewardj                        binop( Iop_And32,
121174c96e61dd85c172b999d6afc88ce6640aeba9962sewardj                               binop( Iop_Shr32,
121184c96e61dd85c172b999d6afc88ce6640aeba9962sewardj                                      unop( Iop_64HIto32,
121194c96e61dd85c172b999d6afc88ce6640aeba9962sewardj                                            mkexpr( frBI64_hi ) ),
121204c96e61dd85c172b999d6afc88ce6640aeba9962sewardj                                      mkU8( 24 ) ),
121214c96e61dd85c172b999d6afc88ce6640aeba9962sewardj                               mkU32( 0xFF ) ) ) );
121224c96e61dd85c172b999d6afc88ce6640aeba9962sewardj         assign( bcd_mid_60,
121234c96e61dd85c172b999d6afc88ce6640aeba9962sewardj                 binop( Iop_32HLto64,
121244c96e61dd85c172b999d6afc88ce6640aeba9962sewardj                        binop( Iop_Or32,
121254c96e61dd85c172b999d6afc88ce6640aeba9962sewardj                               binop( Iop_Shr32,
121264c96e61dd85c172b999d6afc88ce6640aeba9962sewardj                                      unop( Iop_64to32,
121274c96e61dd85c172b999d6afc88ce6640aeba9962sewardj                                            mkexpr( frBI64_hi ) ),
121284c96e61dd85c172b999d6afc88ce6640aeba9962sewardj                                      mkU8( 28 ) ),
121294c96e61dd85c172b999d6afc88ce6640aeba9962sewardj                               binop( Iop_Shl32,
121304c96e61dd85c172b999d6afc88ce6640aeba9962sewardj                                      unop( Iop_64HIto32,
121314c96e61dd85c172b999d6afc88ce6640aeba9962sewardj                                            mkexpr( frBI64_hi ) ),
121324c96e61dd85c172b999d6afc88ce6640aeba9962sewardj                                      mkU8( 4 ) ) ),
121334c96e61dd85c172b999d6afc88ce6640aeba9962sewardj                        binop( Iop_Or32,
121344c96e61dd85c172b999d6afc88ce6640aeba9962sewardj                               binop( Iop_Shl32,
121354c96e61dd85c172b999d6afc88ce6640aeba9962sewardj                                      unop( Iop_64to32,
121364c96e61dd85c172b999d6afc88ce6640aeba9962sewardj                                            mkexpr( frBI64_hi ) ),
121374c96e61dd85c172b999d6afc88ce6640aeba9962sewardj                                      mkU8( 4 ) ),
121384c96e61dd85c172b999d6afc88ce6640aeba9962sewardj                               binop( Iop_Shr32,
121394c96e61dd85c172b999d6afc88ce6640aeba9962sewardj                                      unop( Iop_64HIto32,
121404c96e61dd85c172b999d6afc88ce6640aeba9962sewardj                                            mkexpr( frBI64_lo ) ),
121414c96e61dd85c172b999d6afc88ce6640aeba9962sewardj                                      mkU8( 28 ) ) ) ) );
121424c96e61dd85c172b999d6afc88ce6640aeba9962sewardj
121434c96e61dd85c172b999d6afc88ce6640aeba9962sewardj         /* Note, the various helper functions ignores top 4-bits */
121444c96e61dd85c172b999d6afc88ce6640aeba9962sewardj         assign( bcd_low_60, mkexpr( frBI64_lo ) );
121454c96e61dd85c172b999d6afc88ce6640aeba9962sewardj
121464c96e61dd85c172b999d6afc88ce6640aeba9962sewardj         assign( tmptop10, unop( Iop_BCDtoDPB, mkexpr( bcd_top_8 ) ) );
121474c96e61dd85c172b999d6afc88ce6640aeba9962sewardj         assign( dbcd_top_l, unop( Iop_64to32, mkexpr( tmptop10 ) ) );
121484c96e61dd85c172b999d6afc88ce6640aeba9962sewardj
121494c96e61dd85c172b999d6afc88ce6640aeba9962sewardj         assign( tmpmid50, unop( Iop_BCDtoDPB, mkexpr( bcd_mid_60 ) ) );
121504c96e61dd85c172b999d6afc88ce6640aeba9962sewardj         assign( dbcd_mid_u, unop( Iop_64HIto32, mkexpr( tmpmid50 ) ) );
121514c96e61dd85c172b999d6afc88ce6640aeba9962sewardj         assign( dbcd_mid_l, unop( Iop_64to32, mkexpr( tmpmid50 ) ) );
121524c96e61dd85c172b999d6afc88ce6640aeba9962sewardj
121534c96e61dd85c172b999d6afc88ce6640aeba9962sewardj         assign( tmplow50, unop( Iop_BCDtoDPB, mkexpr( bcd_low_60 ) ) );
121544c96e61dd85c172b999d6afc88ce6640aeba9962sewardj         assign( dbcd_low_u, unop( Iop_64HIto32, mkexpr( tmplow50 ) ) );
121554c96e61dd85c172b999d6afc88ce6640aeba9962sewardj         assign( dbcd_low_l, unop( Iop_64to32, mkexpr( tmplow50 ) ) );
121564c96e61dd85c172b999d6afc88ce6640aeba9962sewardj
121574c96e61dd85c172b999d6afc88ce6640aeba9962sewardj         /* The entire BCD string fits in lower 110-bits.  The LMD = 0,
121584c96e61dd85c172b999d6afc88ce6640aeba9962sewardj          * value is not part of the final result. Only the right most
121594c96e61dd85c172b999d6afc88ce6640aeba9962sewardj          * BCD digits are stored.
121604c96e61dd85c172b999d6afc88ce6640aeba9962sewardj          */
121614c96e61dd85c172b999d6afc88ce6640aeba9962sewardj         assign( lmd, mkU32( 0 ) );
121624c96e61dd85c172b999d6afc88ce6640aeba9962sewardj
121634c96e61dd85c172b999d6afc88ce6640aeba9962sewardj         assign( invalid_mask,
121644c96e61dd85c172b999d6afc88ce6640aeba9962sewardj                 binop( Iop_Or32,
121654c96e61dd85c172b999d6afc88ce6640aeba9962sewardj                        bcd_digit_inval( mkU32( 0 ),
121664c96e61dd85c172b999d6afc88ce6640aeba9962sewardj                                         unop( Iop_64to32,
121674c96e61dd85c172b999d6afc88ce6640aeba9962sewardj                                               mkexpr( bcd_top_8 ) ) ),
121684c96e61dd85c172b999d6afc88ce6640aeba9962sewardj                        binop( Iop_Or32,
121694c96e61dd85c172b999d6afc88ce6640aeba9962sewardj                               bcd_digit_inval( unop( Iop_64HIto32,
121704c96e61dd85c172b999d6afc88ce6640aeba9962sewardj                                                      mkexpr( bcd_mid_60 ) ),
121714c96e61dd85c172b999d6afc88ce6640aeba9962sewardj                                                unop( Iop_64to32,
121724c96e61dd85c172b999d6afc88ce6640aeba9962sewardj                                                      mkexpr( bcd_mid_60 ) ) ),
121734c96e61dd85c172b999d6afc88ce6640aeba9962sewardj                               bcd_digit_inval( unop( Iop_64HIto32,
121744c96e61dd85c172b999d6afc88ce6640aeba9962sewardj                                                      mkexpr( bcd_low_60 ) ),
121754c96e61dd85c172b999d6afc88ce6640aeba9962sewardj                                                unop( Iop_64to32,
121764c96e61dd85c172b999d6afc88ce6640aeba9962sewardj                                                      mkexpr( bcd_low_60 ) )
121774c96e61dd85c172b999d6afc88ce6640aeba9962sewardj                                                ) ) ) );
121784c96e61dd85c172b999d6afc88ce6640aeba9962sewardj
121794c96e61dd85c172b999d6afc88ce6640aeba9962sewardj      } else if ( s == 1 ) {
121804c96e61dd85c172b999d6afc88ce6640aeba9962sewardj         IRTemp sign          = newTemp( Ity_I32 );
121814c96e61dd85c172b999d6afc88ce6640aeba9962sewardj         IRTemp zero          = newTemp( Ity_I32 );
121824c96e61dd85c172b999d6afc88ce6640aeba9962sewardj         IRTemp pos_sign_mask = newTemp( Ity_I32 );
121834c96e61dd85c172b999d6afc88ce6640aeba9962sewardj         IRTemp neg_sign_mask = newTemp( Ity_I32 );
121844c96e61dd85c172b999d6afc88ce6640aeba9962sewardj
121854c96e61dd85c172b999d6afc88ce6640aeba9962sewardj         /* The sign of the BCD string is stored in lower 4 bits */
121864c96e61dd85c172b999d6afc88ce6640aeba9962sewardj         assign( sign,
121874c96e61dd85c172b999d6afc88ce6640aeba9962sewardj                 binop( Iop_And32,
121884c96e61dd85c172b999d6afc88ce6640aeba9962sewardj                        unop( Iop_64to32, mkexpr( frBI64_lo ) ),
121894c96e61dd85c172b999d6afc88ce6640aeba9962sewardj                        mkU32( 0xF ) ) );
121904c96e61dd85c172b999d6afc88ce6640aeba9962sewardj         assign( neg_sign_mask, Generate_neg_sign_mask( mkexpr( sign ) ) );
121914c96e61dd85c172b999d6afc88ce6640aeba9962sewardj         assign( pos_sign_mask, Generate_pos_sign_mask( mkexpr( sign ) ) );
121924c96e61dd85c172b999d6afc88ce6640aeba9962sewardj         assign( sign_bit,
121934c96e61dd85c172b999d6afc88ce6640aeba9962sewardj                 Generate_sign_bit( mkexpr( pos_sign_mask ),
121944c96e61dd85c172b999d6afc88ce6640aeba9962sewardj                                    mkexpr( neg_sign_mask ) ) );
121954c96e61dd85c172b999d6afc88ce6640aeba9962sewardj
121964c96e61dd85c172b999d6afc88ce6640aeba9962sewardj         /* Generate the value assuminig the sign and BCD digits are vaild */
121974c96e61dd85c172b999d6afc88ce6640aeba9962sewardj         assign( bcd_top_8,
121984c96e61dd85c172b999d6afc88ce6640aeba9962sewardj                 binop( Iop_32HLto64,
121994c96e61dd85c172b999d6afc88ce6640aeba9962sewardj                        mkU32( 0x0 ),
122004c96e61dd85c172b999d6afc88ce6640aeba9962sewardj                        binop( Iop_Shr32,
122014c96e61dd85c172b999d6afc88ce6640aeba9962sewardj                               unop( Iop_64HIto32, mkexpr( frBI64_hi ) ),
122024c96e61dd85c172b999d6afc88ce6640aeba9962sewardj                               mkU8( 28 ) ) ) );
122034c96e61dd85c172b999d6afc88ce6640aeba9962sewardj
122044c96e61dd85c172b999d6afc88ce6640aeba9962sewardj         /* The various helper routines ignore the upper 4-bits */
122054c96e61dd85c172b999d6afc88ce6640aeba9962sewardj         assign( bcd_mid_60, mkexpr( frBI64_hi ) );
122064c96e61dd85c172b999d6afc88ce6640aeba9962sewardj
122074c96e61dd85c172b999d6afc88ce6640aeba9962sewardj         /* Remove bottom four sign bits */
122084c96e61dd85c172b999d6afc88ce6640aeba9962sewardj         assign( bcd_low_60,
122094c96e61dd85c172b999d6afc88ce6640aeba9962sewardj                 binop( Iop_32HLto64,
122104c96e61dd85c172b999d6afc88ce6640aeba9962sewardj                        binop( Iop_Shr32,
122114c96e61dd85c172b999d6afc88ce6640aeba9962sewardj                               unop( Iop_64HIto32,
122124c96e61dd85c172b999d6afc88ce6640aeba9962sewardj                                     mkexpr( frBI64_lo ) ),
122134c96e61dd85c172b999d6afc88ce6640aeba9962sewardj                               mkU8( 4 ) ),
122144c96e61dd85c172b999d6afc88ce6640aeba9962sewardj                               binop( Iop_Or32,
122154c96e61dd85c172b999d6afc88ce6640aeba9962sewardj                                      binop( Iop_Shl32,
122164c96e61dd85c172b999d6afc88ce6640aeba9962sewardj                                             unop( Iop_64HIto32,
122174c96e61dd85c172b999d6afc88ce6640aeba9962sewardj                                                   mkexpr( frBI64_lo ) ),
122184c96e61dd85c172b999d6afc88ce6640aeba9962sewardj                                             mkU8( 28 ) ),
122194c96e61dd85c172b999d6afc88ce6640aeba9962sewardj                                      binop( Iop_Shr32,
122204c96e61dd85c172b999d6afc88ce6640aeba9962sewardj                                             unop( Iop_64to32,
122214c96e61dd85c172b999d6afc88ce6640aeba9962sewardj                                                   mkexpr( frBI64_lo ) ),
122224c96e61dd85c172b999d6afc88ce6640aeba9962sewardj                                             mkU8( 4 ) ) ) ) );
122234c96e61dd85c172b999d6afc88ce6640aeba9962sewardj         assign( tmptop10, unop( Iop_BCDtoDPB, mkexpr(bcd_top_8 ) ) );
122244c96e61dd85c172b999d6afc88ce6640aeba9962sewardj         assign( dbcd_top_l, unop( Iop_64to32, mkexpr( tmptop10 ) ) );
122254c96e61dd85c172b999d6afc88ce6640aeba9962sewardj
122264c96e61dd85c172b999d6afc88ce6640aeba9962sewardj         assign( tmpmid50, unop( Iop_BCDtoDPB, mkexpr(bcd_mid_60 ) ) );
122274c96e61dd85c172b999d6afc88ce6640aeba9962sewardj         assign( dbcd_mid_u, unop( Iop_64HIto32, mkexpr( tmpmid50 ) ) );
122284c96e61dd85c172b999d6afc88ce6640aeba9962sewardj         assign( dbcd_mid_l, unop( Iop_64to32, mkexpr( tmpmid50 ) ) );
122294c96e61dd85c172b999d6afc88ce6640aeba9962sewardj
122304c96e61dd85c172b999d6afc88ce6640aeba9962sewardj         assign( tmplow50, unop( Iop_BCDtoDPB, mkexpr( bcd_low_60 ) ) );
122314c96e61dd85c172b999d6afc88ce6640aeba9962sewardj         assign( dbcd_low_u, unop( Iop_64HIto32, mkexpr( tmplow50 ) ) );
122324c96e61dd85c172b999d6afc88ce6640aeba9962sewardj         assign( dbcd_low_l, unop( Iop_64to32, mkexpr( tmplow50 ) ) );
122334c96e61dd85c172b999d6afc88ce6640aeba9962sewardj
122344c96e61dd85c172b999d6afc88ce6640aeba9962sewardj         /* The entire BCD string fits in lower 110-bits.  The LMD value
122354c96e61dd85c172b999d6afc88ce6640aeba9962sewardj          * is not stored in the final result for the DFP Long instruction.
122364c96e61dd85c172b999d6afc88ce6640aeba9962sewardj          */
122374c96e61dd85c172b999d6afc88ce6640aeba9962sewardj         assign( lmd, mkU32( 0 ) );
122384c96e61dd85c172b999d6afc88ce6640aeba9962sewardj
122394c96e61dd85c172b999d6afc88ce6640aeba9962sewardj         /* Check for invalid sign and invalid BCD digit.  Don't check the
122404c96e61dd85c172b999d6afc88ce6640aeba9962sewardj          *  bottom four bits of frBI64_lo as that is the sign value.
122414c96e61dd85c172b999d6afc88ce6640aeba9962sewardj          */
122424c96e61dd85c172b999d6afc88ce6640aeba9962sewardj         assign( zero, mkU32( 0 ) );
122434c96e61dd85c172b999d6afc88ce6640aeba9962sewardj         assign( inval_bcd_digit_mask,
122444c96e61dd85c172b999d6afc88ce6640aeba9962sewardj                 binop( Iop_Or32,
122454c96e61dd85c172b999d6afc88ce6640aeba9962sewardj                        bcd_digit_inval( mkexpr( zero ),
122464c96e61dd85c172b999d6afc88ce6640aeba9962sewardj                                         unop( Iop_64to32,
122474c96e61dd85c172b999d6afc88ce6640aeba9962sewardj                                               mkexpr( bcd_top_8 ) ) ),
122484c96e61dd85c172b999d6afc88ce6640aeba9962sewardj                        binop( Iop_Or32,
122494c96e61dd85c172b999d6afc88ce6640aeba9962sewardj                               bcd_digit_inval( unop( Iop_64HIto32,
122504c96e61dd85c172b999d6afc88ce6640aeba9962sewardj                                                     mkexpr( bcd_mid_60 ) ),
122514c96e61dd85c172b999d6afc88ce6640aeba9962sewardj                                               unop( Iop_64to32,
122524c96e61dd85c172b999d6afc88ce6640aeba9962sewardj                                                     mkexpr( bcd_mid_60 ) ) ),
122534c96e61dd85c172b999d6afc88ce6640aeba9962sewardj                               bcd_digit_inval( unop( Iop_64HIto32,
122544c96e61dd85c172b999d6afc88ce6640aeba9962sewardj                                                     mkexpr( frBI64_lo ) ),
122554c96e61dd85c172b999d6afc88ce6640aeba9962sewardj                                               binop( Iop_Shr32,
122564c96e61dd85c172b999d6afc88ce6640aeba9962sewardj                                                      unop( Iop_64to32,
122574c96e61dd85c172b999d6afc88ce6640aeba9962sewardj                                                            mkexpr( frBI64_lo ) ),
122584c96e61dd85c172b999d6afc88ce6640aeba9962sewardj                                                        mkU8( 4 ) ) ) ) ) );
122594c96e61dd85c172b999d6afc88ce6640aeba9962sewardj         assign( invalid_mask,
122604c96e61dd85c172b999d6afc88ce6640aeba9962sewardj                 Generate_inv_mask( mkexpr( inval_bcd_digit_mask ),
122614c96e61dd85c172b999d6afc88ce6640aeba9962sewardj                                    mkexpr( pos_sign_mask ),
122624c96e61dd85c172b999d6afc88ce6640aeba9962sewardj                                    mkexpr( neg_sign_mask ) ) );
122634c96e61dd85c172b999d6afc88ce6640aeba9962sewardj
122644c96e61dd85c172b999d6afc88ce6640aeba9962sewardj      }
122654c96e61dd85c172b999d6afc88ce6640aeba9962sewardj
122664c96e61dd85c172b999d6afc88ce6640aeba9962sewardj      assign( valid_mask, unop( Iop_Not32, mkexpr( invalid_mask ) ) );
122674c96e61dd85c172b999d6afc88ce6640aeba9962sewardj
122684c96e61dd85c172b999d6afc88ce6640aeba9962sewardj      /* Calculate the value of the result assuming sign and BCD digits
122694c96e61dd85c172b999d6afc88ce6640aeba9962sewardj       * are all valid.
122704c96e61dd85c172b999d6afc88ce6640aeba9962sewardj       */
122714c96e61dd85c172b999d6afc88ce6640aeba9962sewardj      assign( dfp_significand,
122724c96e61dd85c172b999d6afc88ce6640aeba9962sewardj              binop( Iop_D64HLtoD128,
122734c96e61dd85c172b999d6afc88ce6640aeba9962sewardj                     unop( Iop_ReinterpI64asD64,
122744c96e61dd85c172b999d6afc88ce6640aeba9962sewardj                           binop( Iop_32HLto64,
122754c96e61dd85c172b999d6afc88ce6640aeba9962sewardj                                  binop( Iop_Or32,
122764c96e61dd85c172b999d6afc88ce6640aeba9962sewardj                                         mkexpr( sign_bit ),
122774c96e61dd85c172b999d6afc88ce6640aeba9962sewardj                                         mkexpr( dbcd_top_l ) ),
122784c96e61dd85c172b999d6afc88ce6640aeba9962sewardj                                  binop( Iop_Or32,
122794c96e61dd85c172b999d6afc88ce6640aeba9962sewardj                                         binop( Iop_Shl32,
122804c96e61dd85c172b999d6afc88ce6640aeba9962sewardj                                                mkexpr( dbcd_mid_u ),
122814c96e61dd85c172b999d6afc88ce6640aeba9962sewardj                                                mkU8( 18 ) ),
122824c96e61dd85c172b999d6afc88ce6640aeba9962sewardj                                         binop( Iop_Shr32,
122834c96e61dd85c172b999d6afc88ce6640aeba9962sewardj                                                mkexpr( dbcd_mid_l ),
122844c96e61dd85c172b999d6afc88ce6640aeba9962sewardj                                                mkU8( 14 ) ) ) ) ),
122854c96e61dd85c172b999d6afc88ce6640aeba9962sewardj                     unop( Iop_ReinterpI64asD64,
122864c96e61dd85c172b999d6afc88ce6640aeba9962sewardj                           binop( Iop_32HLto64,
122874c96e61dd85c172b999d6afc88ce6640aeba9962sewardj                                  binop( Iop_Or32,
122884c96e61dd85c172b999d6afc88ce6640aeba9962sewardj                                         mkexpr( dbcd_low_u ),
122894c96e61dd85c172b999d6afc88ce6640aeba9962sewardj                                         binop( Iop_Shl32,
122904c96e61dd85c172b999d6afc88ce6640aeba9962sewardj                                                mkexpr( dbcd_mid_l ),
122914c96e61dd85c172b999d6afc88ce6640aeba9962sewardj                                                mkU8( 18 ) ) ),
122924c96e61dd85c172b999d6afc88ce6640aeba9962sewardj                                  mkexpr( dbcd_low_l ) ) ) ) );
122934c96e61dd85c172b999d6afc88ce6640aeba9962sewardj
122944c96e61dd85c172b999d6afc88ce6640aeba9962sewardj      /* Break the result back down to 32-bit chunks and replace chunks.
122954c96e61dd85c172b999d6afc88ce6640aeba9962sewardj       * If there was an invalid BCD digit or invalid sign value, replace
122964c96e61dd85c172b999d6afc88ce6640aeba9962sewardj       * the calculated result with the invalid bit string.
122974c96e61dd85c172b999d6afc88ce6640aeba9962sewardj       */
122984c96e61dd85c172b999d6afc88ce6640aeba9962sewardj      assign( result128,
122994c96e61dd85c172b999d6afc88ce6640aeba9962sewardj              binop( Iop_InsertExpD128,
12300cea07ccbe9aa9b5fd8e9b318471c6c74aa147acbcarll                     mkU64( DFP_EXTND_BIAS ),
123014c96e61dd85c172b999d6afc88ce6640aeba9962sewardj                     mkexpr( dfp_significand ) ) );
123024c96e61dd85c172b999d6afc88ce6640aeba9962sewardj
123034c96e61dd85c172b999d6afc88ce6640aeba9962sewardj      assign( tmp_hi,
123044c96e61dd85c172b999d6afc88ce6640aeba9962sewardj              unop( Iop_ReinterpD64asI64,
123054c96e61dd85c172b999d6afc88ce6640aeba9962sewardj                    unop( Iop_D128HItoD64, mkexpr( result128 ) ) ) );
123064c96e61dd85c172b999d6afc88ce6640aeba9962sewardj
123074c96e61dd85c172b999d6afc88ce6640aeba9962sewardj      assign( tmp_lo,
123084c96e61dd85c172b999d6afc88ce6640aeba9962sewardj              unop( Iop_ReinterpD64asI64,
123094c96e61dd85c172b999d6afc88ce6640aeba9962sewardj                    unop( Iop_D128LOtoD64, mkexpr( result128 ) ) ) );
123104c96e61dd85c172b999d6afc88ce6640aeba9962sewardj
123114c96e61dd85c172b999d6afc88ce6640aeba9962sewardj      assign( result_hi,
123124c96e61dd85c172b999d6afc88ce6640aeba9962sewardj              binop( Iop_32HLto64,
123134c96e61dd85c172b999d6afc88ce6640aeba9962sewardj                     binop( Iop_Or32,
123144c96e61dd85c172b999d6afc88ce6640aeba9962sewardj                            binop( Iop_And32,
123154c96e61dd85c172b999d6afc88ce6640aeba9962sewardj                                   mkexpr( valid_mask ),
123164c96e61dd85c172b999d6afc88ce6640aeba9962sewardj                                   unop( Iop_64HIto32, mkexpr( tmp_hi ) ) ),
123174c96e61dd85c172b999d6afc88ce6640aeba9962sewardj                            binop( Iop_And32,
123184c96e61dd85c172b999d6afc88ce6640aeba9962sewardj                                   mkU32( 0x7C000000 ),
123194c96e61dd85c172b999d6afc88ce6640aeba9962sewardj                                   mkexpr( invalid_mask ) ) ),
123204c96e61dd85c172b999d6afc88ce6640aeba9962sewardj                     binop( Iop_Or32,
123214c96e61dd85c172b999d6afc88ce6640aeba9962sewardj                            binop( Iop_And32,
123224c96e61dd85c172b999d6afc88ce6640aeba9962sewardj                                   mkexpr( valid_mask ),
123234c96e61dd85c172b999d6afc88ce6640aeba9962sewardj                                   unop( Iop_64to32, mkexpr( tmp_hi ) ) ),
123244c96e61dd85c172b999d6afc88ce6640aeba9962sewardj                            binop( Iop_And32,
123254c96e61dd85c172b999d6afc88ce6640aeba9962sewardj                                   mkU32( 0x0 ),
123264c96e61dd85c172b999d6afc88ce6640aeba9962sewardj                                   mkexpr( invalid_mask ) ) ) ) );
123274c96e61dd85c172b999d6afc88ce6640aeba9962sewardj
123284c96e61dd85c172b999d6afc88ce6640aeba9962sewardj      assign( result_lo,
123294c96e61dd85c172b999d6afc88ce6640aeba9962sewardj              binop( Iop_32HLto64,
123304c96e61dd85c172b999d6afc88ce6640aeba9962sewardj                     binop( Iop_Or32,
123314c96e61dd85c172b999d6afc88ce6640aeba9962sewardj                            binop( Iop_And32,
123324c96e61dd85c172b999d6afc88ce6640aeba9962sewardj                                   mkexpr( valid_mask ),
123334c96e61dd85c172b999d6afc88ce6640aeba9962sewardj                                   unop( Iop_64HIto32, mkexpr( tmp_lo ) ) ),
123344c96e61dd85c172b999d6afc88ce6640aeba9962sewardj                            binop( Iop_And32,
123354c96e61dd85c172b999d6afc88ce6640aeba9962sewardj                                   mkU32( 0x0 ),
123364c96e61dd85c172b999d6afc88ce6640aeba9962sewardj                                   mkexpr( invalid_mask ) ) ),
123374c96e61dd85c172b999d6afc88ce6640aeba9962sewardj                     binop( Iop_Or32,
123384c96e61dd85c172b999d6afc88ce6640aeba9962sewardj                            binop( Iop_And32,
123394c96e61dd85c172b999d6afc88ce6640aeba9962sewardj                                   mkexpr( valid_mask ),
123404c96e61dd85c172b999d6afc88ce6640aeba9962sewardj                                   unop( Iop_64to32, mkexpr( tmp_lo ) ) ),
123414c96e61dd85c172b999d6afc88ce6640aeba9962sewardj                            binop( Iop_And32,
123424c96e61dd85c172b999d6afc88ce6640aeba9962sewardj                                   mkU32( 0x0 ),
123434c96e61dd85c172b999d6afc88ce6640aeba9962sewardj                                   mkexpr( invalid_mask ) ) ) ) );
123444c96e61dd85c172b999d6afc88ce6640aeba9962sewardj
123454c96e61dd85c172b999d6afc88ce6640aeba9962sewardj      putDReg( frT_addr, unop( Iop_ReinterpI64asD64, mkexpr( result_hi ) ) );
123464c96e61dd85c172b999d6afc88ce6640aeba9962sewardj      putDReg( frT_addr + 1,
123474c96e61dd85c172b999d6afc88ce6640aeba9962sewardj               unop( Iop_ReinterpI64asD64, mkexpr( result_lo ) ) );
123484c96e61dd85c172b999d6afc88ce6640aeba9962sewardj
123494c96e61dd85c172b999d6afc88ce6640aeba9962sewardj   }
123504c96e61dd85c172b999d6afc88ce6640aeba9962sewardj   break;
123514c96e61dd85c172b999d6afc88ce6640aeba9962sewardj   default:
123524c96e61dd85c172b999d6afc88ce6640aeba9962sewardj      vpanic( "ERROR: dis_dfp_bcdq(ppc), undefined opc2 case " );
123534c96e61dd85c172b999d6afc88ce6640aeba9962sewardj      break;
123544c96e61dd85c172b999d6afc88ce6640aeba9962sewardj   }
123554c96e61dd85c172b999d6afc88ce6640aeba9962sewardj   return True;
123564c96e61dd85c172b999d6afc88ce6640aeba9962sewardj}
123574c96e61dd85c172b999d6afc88ce6640aeba9962sewardj
123584c96e61dd85c172b999d6afc88ce6640aeba9962sewardjstatic Bool dis_dfp_significant_digits( UInt theInstr )
123594c96e61dd85c172b999d6afc88ce6640aeba9962sewardj{
123604c96e61dd85c172b999d6afc88ce6640aeba9962sewardj   UChar frA_addr = ifieldRegA( theInstr );
123614c96e61dd85c172b999d6afc88ce6640aeba9962sewardj   UChar frB_addr = ifieldRegB( theInstr );
123624c96e61dd85c172b999d6afc88ce6640aeba9962sewardj   IRTemp frA     = newTemp( Ity_D64 );
123634c96e61dd85c172b999d6afc88ce6640aeba9962sewardj   UInt opc1      = ifieldOPC( theInstr );
123644c96e61dd85c172b999d6afc88ce6640aeba9962sewardj   IRTemp B_sig   = newTemp( Ity_I8 );
123654c96e61dd85c172b999d6afc88ce6640aeba9962sewardj   IRTemp K       = newTemp( Ity_I8 );
123664c96e61dd85c172b999d6afc88ce6640aeba9962sewardj   IRTemp lmd_B   = newTemp( Ity_I32 );
123674c96e61dd85c172b999d6afc88ce6640aeba9962sewardj   IRTemp field   = newTemp( Ity_I32 );
123684c96e61dd85c172b999d6afc88ce6640aeba9962sewardj   UChar crfD     = toUChar( IFIELD( theInstr, 23, 3 ) ); // AKA BF
123694c96e61dd85c172b999d6afc88ce6640aeba9962sewardj   IRTemp Unordered_true     = newTemp( Ity_I32 );
123704c96e61dd85c172b999d6afc88ce6640aeba9962sewardj   IRTemp Eq_true_mask       = newTemp( Ity_I32 );
123714c96e61dd85c172b999d6afc88ce6640aeba9962sewardj   IRTemp Lt_true_mask       = newTemp( Ity_I32 );
123724c96e61dd85c172b999d6afc88ce6640aeba9962sewardj   IRTemp Gt_true_mask       = newTemp( Ity_I32 );
123734c96e61dd85c172b999d6afc88ce6640aeba9962sewardj   IRTemp KisZero_true_mask  = newTemp( Ity_I32 );
123744c96e61dd85c172b999d6afc88ce6640aeba9962sewardj   IRTemp KisZero_false_mask = newTemp( Ity_I32 );
123754c96e61dd85c172b999d6afc88ce6640aeba9962sewardj
123764c96e61dd85c172b999d6afc88ce6640aeba9962sewardj   /* Get the reference singificance stored in frA */
123774c96e61dd85c172b999d6afc88ce6640aeba9962sewardj   assign( frA, getDReg( frA_addr ) );
123784c96e61dd85c172b999d6afc88ce6640aeba9962sewardj
123794c96e61dd85c172b999d6afc88ce6640aeba9962sewardj   /* Convert from 64 bit to 8 bits in two steps.  The Iop_64to8 is not
123804c96e61dd85c172b999d6afc88ce6640aeba9962sewardj    * supported in 32-bit mode.
123814c96e61dd85c172b999d6afc88ce6640aeba9962sewardj    */
123824c96e61dd85c172b999d6afc88ce6640aeba9962sewardj   assign( K, unop( Iop_32to8,
123834c96e61dd85c172b999d6afc88ce6640aeba9962sewardj                    binop( Iop_And32,
123844c96e61dd85c172b999d6afc88ce6640aeba9962sewardj                           unop( Iop_64to32,
123854c96e61dd85c172b999d6afc88ce6640aeba9962sewardj                                 unop( Iop_ReinterpD64asI64,
123864c96e61dd85c172b999d6afc88ce6640aeba9962sewardj                                       mkexpr( frA ) ) ),
123874c96e61dd85c172b999d6afc88ce6640aeba9962sewardj                           mkU32( 0x3F ) ) ) );
123884c96e61dd85c172b999d6afc88ce6640aeba9962sewardj
123894c96e61dd85c172b999d6afc88ce6640aeba9962sewardj   switch ( opc1 ) {
123904c96e61dd85c172b999d6afc88ce6640aeba9962sewardj   case 0x3b: // dtstsf   DFP Test Significance
123914c96e61dd85c172b999d6afc88ce6640aeba9962sewardj   {
123924c96e61dd85c172b999d6afc88ce6640aeba9962sewardj      IRTemp frB     = newTemp( Ity_D64 );
123934c96e61dd85c172b999d6afc88ce6640aeba9962sewardj      IRTemp frBI64  = newTemp( Ity_I64 );
123944c96e61dd85c172b999d6afc88ce6640aeba9962sewardj      IRTemp B_bcd_u = newTemp( Ity_I32 );
123954c96e61dd85c172b999d6afc88ce6640aeba9962sewardj      IRTemp B_bcd_l = newTemp( Ity_I32 );
123964c96e61dd85c172b999d6afc88ce6640aeba9962sewardj      IRTemp tmp64   = newTemp( Ity_I64 );
123974c96e61dd85c172b999d6afc88ce6640aeba9962sewardj
123984c96e61dd85c172b999d6afc88ce6640aeba9962sewardj      DIP( "dtstsf %u,r%u,r%u\n", crfD, frA_addr, frB_addr );
123994c96e61dd85c172b999d6afc88ce6640aeba9962sewardj
124004c96e61dd85c172b999d6afc88ce6640aeba9962sewardj      assign( frB, getDReg( frB_addr ) );
124014c96e61dd85c172b999d6afc88ce6640aeba9962sewardj      assign( frBI64, unop( Iop_ReinterpD64asI64, mkexpr( frB ) ) );
124024c96e61dd85c172b999d6afc88ce6640aeba9962sewardj
124034c96e61dd85c172b999d6afc88ce6640aeba9962sewardj      /* Get the BCD string for the value stored in a series of I32 values.
124044c96e61dd85c172b999d6afc88ce6640aeba9962sewardj       * Count the number of leading zeros.  Subtract the number of leading
124054c96e61dd85c172b999d6afc88ce6640aeba9962sewardj       * zeros from 16 (maximum number of significant digits in DFP
124064c96e61dd85c172b999d6afc88ce6640aeba9962sewardj       * Long).
124074c96e61dd85c172b999d6afc88ce6640aeba9962sewardj       */
124084c96e61dd85c172b999d6afc88ce6640aeba9962sewardj      Get_lmd( &lmd_B,
124094c96e61dd85c172b999d6afc88ce6640aeba9962sewardj               binop( Iop_Shr32,
124104c96e61dd85c172b999d6afc88ce6640aeba9962sewardj                      unop( Iop_64HIto32, mkexpr( frBI64 ) ),
124114c96e61dd85c172b999d6afc88ce6640aeba9962sewardj                      mkU8( 31 - 5 ) ) ); // G-field[0:4]
124124c96e61dd85c172b999d6afc88ce6640aeba9962sewardj
124134c96e61dd85c172b999d6afc88ce6640aeba9962sewardj      assign( tmp64, unop( Iop_DPBtoBCD, mkexpr( frBI64 ) ) );
124144c96e61dd85c172b999d6afc88ce6640aeba9962sewardj      assign( B_bcd_u, unop( Iop_64HIto32, mkexpr( tmp64 ) ) );
124154c96e61dd85c172b999d6afc88ce6640aeba9962sewardj      assign( B_bcd_l, unop( Iop_64to32, mkexpr( tmp64 ) ) );
124164c96e61dd85c172b999d6afc88ce6640aeba9962sewardj
124174c96e61dd85c172b999d6afc88ce6640aeba9962sewardj      assign( B_sig,
124184c96e61dd85c172b999d6afc88ce6640aeba9962sewardj              binop( Iop_Sub8,
124194c96e61dd85c172b999d6afc88ce6640aeba9962sewardj                     mkU8( DFP_LONG_MAX_SIG_DIGITS ),
124204c96e61dd85c172b999d6afc88ce6640aeba9962sewardj                     Count_leading_zeros_60( mkexpr( lmd_B ),
124214c96e61dd85c172b999d6afc88ce6640aeba9962sewardj                                             mkexpr( B_bcd_u ),
124224c96e61dd85c172b999d6afc88ce6640aeba9962sewardj                                             mkexpr( B_bcd_l ) ) ) );
124234c96e61dd85c172b999d6afc88ce6640aeba9962sewardj      assign( Unordered_true, Check_unordered( mkexpr( frBI64 ) ) );
124244c96e61dd85c172b999d6afc88ce6640aeba9962sewardj   }
124254c96e61dd85c172b999d6afc88ce6640aeba9962sewardj   break;
124264c96e61dd85c172b999d6afc88ce6640aeba9962sewardj   case 0x3F: // dtstsfq     DFP Test Significance
124274c96e61dd85c172b999d6afc88ce6640aeba9962sewardj   {
124284c96e61dd85c172b999d6afc88ce6640aeba9962sewardj      IRTemp frB_hi     = newTemp( Ity_D64 );
124294c96e61dd85c172b999d6afc88ce6640aeba9962sewardj      IRTemp frB_lo     = newTemp( Ity_D64 );
124304c96e61dd85c172b999d6afc88ce6640aeba9962sewardj      IRTemp frBI64_hi  = newTemp( Ity_I64 );
124314c96e61dd85c172b999d6afc88ce6640aeba9962sewardj      IRTemp frBI64_lo  = newTemp( Ity_I64 );
124324c96e61dd85c172b999d6afc88ce6640aeba9962sewardj      IRTemp B_low_60_u = newTemp( Ity_I32 );
124334c96e61dd85c172b999d6afc88ce6640aeba9962sewardj      IRTemp B_low_60_l = newTemp( Ity_I32 );
124344c96e61dd85c172b999d6afc88ce6640aeba9962sewardj      IRTemp B_mid_60_u = newTemp( Ity_I32 );
124354c96e61dd85c172b999d6afc88ce6640aeba9962sewardj      IRTemp B_mid_60_l = newTemp( Ity_I32 );
124364c96e61dd85c172b999d6afc88ce6640aeba9962sewardj      IRTemp B_top_12_l = newTemp( Ity_I32 );
124374c96e61dd85c172b999d6afc88ce6640aeba9962sewardj
124384c96e61dd85c172b999d6afc88ce6640aeba9962sewardj      DIP( "dtstsfq %u,r%u,r%u\n", crfD, frA_addr, frB_addr );
124394c96e61dd85c172b999d6afc88ce6640aeba9962sewardj
124404c96e61dd85c172b999d6afc88ce6640aeba9962sewardj      assign( frB_hi, getDReg( frB_addr ) );
124414c96e61dd85c172b999d6afc88ce6640aeba9962sewardj      assign( frB_lo, getDReg( frB_addr + 1 ) );
124424c96e61dd85c172b999d6afc88ce6640aeba9962sewardj
124434c96e61dd85c172b999d6afc88ce6640aeba9962sewardj      assign( frBI64_hi, unop( Iop_ReinterpD64asI64, mkexpr( frB_hi ) ) );
124444c96e61dd85c172b999d6afc88ce6640aeba9962sewardj      assign( frBI64_lo, unop( Iop_ReinterpD64asI64, mkexpr( frB_lo ) ) );
124454c96e61dd85c172b999d6afc88ce6640aeba9962sewardj
124464c96e61dd85c172b999d6afc88ce6640aeba9962sewardj      /* Get the BCD string for the value stored in a series of I32 values.
124474c96e61dd85c172b999d6afc88ce6640aeba9962sewardj       * Count the number of leading zeros.  Subtract the number of leading
124484c96e61dd85c172b999d6afc88ce6640aeba9962sewardj       * zeros from 32 (maximum number of significant digits in DFP
124494c96e61dd85c172b999d6afc88ce6640aeba9962sewardj       * extended).
124504c96e61dd85c172b999d6afc88ce6640aeba9962sewardj       */
124514c96e61dd85c172b999d6afc88ce6640aeba9962sewardj      Get_lmd( &lmd_B,
124524c96e61dd85c172b999d6afc88ce6640aeba9962sewardj               binop( Iop_Shr32,
124534c96e61dd85c172b999d6afc88ce6640aeba9962sewardj                      unop( Iop_64HIto32, mkexpr( frBI64_hi ) ),
124544c96e61dd85c172b999d6afc88ce6640aeba9962sewardj                      mkU8( 31 - 5 ) ) ); // G-field[0:4]
124554c96e61dd85c172b999d6afc88ce6640aeba9962sewardj
124564c96e61dd85c172b999d6afc88ce6640aeba9962sewardj      Generate_132_bit_bcd_string( mkexpr( frBI64_hi ),
124574c96e61dd85c172b999d6afc88ce6640aeba9962sewardj                                   mkexpr( frBI64_lo ),
124584c96e61dd85c172b999d6afc88ce6640aeba9962sewardj                                   &B_top_12_l,
124594c96e61dd85c172b999d6afc88ce6640aeba9962sewardj                                   &B_mid_60_u,
124604c96e61dd85c172b999d6afc88ce6640aeba9962sewardj                                   &B_mid_60_l,
124614c96e61dd85c172b999d6afc88ce6640aeba9962sewardj                                   &B_low_60_u,
124624c96e61dd85c172b999d6afc88ce6640aeba9962sewardj                                   &B_low_60_l );
124634c96e61dd85c172b999d6afc88ce6640aeba9962sewardj
124644c96e61dd85c172b999d6afc88ce6640aeba9962sewardj      assign( B_sig,
124654c96e61dd85c172b999d6afc88ce6640aeba9962sewardj              binop( Iop_Sub8,
124664c96e61dd85c172b999d6afc88ce6640aeba9962sewardj                     mkU8( DFP_EXTND_MAX_SIG_DIGITS ),
124674c96e61dd85c172b999d6afc88ce6640aeba9962sewardj                     Count_leading_zeros_128( mkexpr( lmd_B ),
124684c96e61dd85c172b999d6afc88ce6640aeba9962sewardj                                              mkexpr( B_top_12_l ),
124694c96e61dd85c172b999d6afc88ce6640aeba9962sewardj                                              mkexpr( B_mid_60_u ),
124704c96e61dd85c172b999d6afc88ce6640aeba9962sewardj                                              mkexpr( B_mid_60_l ),
124714c96e61dd85c172b999d6afc88ce6640aeba9962sewardj                                              mkexpr( B_low_60_u ),
124724c96e61dd85c172b999d6afc88ce6640aeba9962sewardj                                              mkexpr( B_low_60_l ) ) ) );
124734c96e61dd85c172b999d6afc88ce6640aeba9962sewardj
124744c96e61dd85c172b999d6afc88ce6640aeba9962sewardj      assign( Unordered_true, Check_unordered( mkexpr( frBI64_hi ) ) );
124754c96e61dd85c172b999d6afc88ce6640aeba9962sewardj   }
124764c96e61dd85c172b999d6afc88ce6640aeba9962sewardj   break;
124774c96e61dd85c172b999d6afc88ce6640aeba9962sewardj   }
124784c96e61dd85c172b999d6afc88ce6640aeba9962sewardj
124794c96e61dd85c172b999d6afc88ce6640aeba9962sewardj   /* Compare (16 - cnt[0]) against K and set the condition code field
124804c96e61dd85c172b999d6afc88ce6640aeba9962sewardj    * accordingly.
124814c96e61dd85c172b999d6afc88ce6640aeba9962sewardj    *
124824c96e61dd85c172b999d6afc88ce6640aeba9962sewardj    * The field layout is as follows:
124834c96e61dd85c172b999d6afc88ce6640aeba9962sewardj    *
124844c96e61dd85c172b999d6afc88ce6640aeba9962sewardj    * bit[3:0]    Description
124854c96e61dd85c172b999d6afc88ce6640aeba9962sewardj    *    3     K != 0 and K < Number of significant digits if FRB
124864c96e61dd85c172b999d6afc88ce6640aeba9962sewardj    *    2     K != 0 and K > Number of significant digits if FRB OR K = 0
124874c96e61dd85c172b999d6afc88ce6640aeba9962sewardj    *    1     K != 0 and K = Number of significant digits if FRB
124884c96e61dd85c172b999d6afc88ce6640aeba9962sewardj    *    0     K ? Number of significant digits if FRB
124894c96e61dd85c172b999d6afc88ce6640aeba9962sewardj    */
124904c96e61dd85c172b999d6afc88ce6640aeba9962sewardj   assign( Eq_true_mask,
124914c96e61dd85c172b999d6afc88ce6640aeba9962sewardj           unop( Iop_1Sto32,
124924c96e61dd85c172b999d6afc88ce6640aeba9962sewardj                 binop( Iop_CmpEQ32,
124934c96e61dd85c172b999d6afc88ce6640aeba9962sewardj                        unop( Iop_8Uto32, mkexpr( K ) ),
124944c96e61dd85c172b999d6afc88ce6640aeba9962sewardj                        unop( Iop_8Uto32, mkexpr( B_sig ) ) ) ) );
124954c96e61dd85c172b999d6afc88ce6640aeba9962sewardj   assign( Lt_true_mask,
124964c96e61dd85c172b999d6afc88ce6640aeba9962sewardj           unop( Iop_1Sto32,
124974c96e61dd85c172b999d6afc88ce6640aeba9962sewardj                 binop( Iop_CmpLT32U,
124984c96e61dd85c172b999d6afc88ce6640aeba9962sewardj                        unop( Iop_8Uto32, mkexpr( K ) ),
124994c96e61dd85c172b999d6afc88ce6640aeba9962sewardj                        unop( Iop_8Uto32, mkexpr( B_sig ) ) ) ) );
125004c96e61dd85c172b999d6afc88ce6640aeba9962sewardj   assign( Gt_true_mask,
125014c96e61dd85c172b999d6afc88ce6640aeba9962sewardj           unop( Iop_1Sto32,
125024c96e61dd85c172b999d6afc88ce6640aeba9962sewardj                 binop( Iop_CmpLT32U,
125034c96e61dd85c172b999d6afc88ce6640aeba9962sewardj                        unop( Iop_8Uto32, mkexpr( B_sig ) ),
125044c96e61dd85c172b999d6afc88ce6640aeba9962sewardj                        unop( Iop_8Uto32, mkexpr( K ) ) ) ) );
125054c96e61dd85c172b999d6afc88ce6640aeba9962sewardj
125064c96e61dd85c172b999d6afc88ce6640aeba9962sewardj   assign( KisZero_true_mask,
125074c96e61dd85c172b999d6afc88ce6640aeba9962sewardj           unop( Iop_1Sto32,
125084c96e61dd85c172b999d6afc88ce6640aeba9962sewardj                 binop( Iop_CmpEQ32,
125094c96e61dd85c172b999d6afc88ce6640aeba9962sewardj                        unop( Iop_8Uto32, mkexpr( K ) ),
125104c96e61dd85c172b999d6afc88ce6640aeba9962sewardj                        mkU32( 0 ) ) ) );
125114c96e61dd85c172b999d6afc88ce6640aeba9962sewardj   assign( KisZero_false_mask,
125124c96e61dd85c172b999d6afc88ce6640aeba9962sewardj           unop( Iop_1Sto32,
125134c96e61dd85c172b999d6afc88ce6640aeba9962sewardj                 binop( Iop_CmpNE32,
125144c96e61dd85c172b999d6afc88ce6640aeba9962sewardj                        unop( Iop_8Uto32, mkexpr( K ) ),
125154c96e61dd85c172b999d6afc88ce6640aeba9962sewardj                        mkU32( 0 ) ) ) );
125164c96e61dd85c172b999d6afc88ce6640aeba9962sewardj
125174c96e61dd85c172b999d6afc88ce6640aeba9962sewardj   assign( field,
125184c96e61dd85c172b999d6afc88ce6640aeba9962sewardj           binop( Iop_Or32,
125194c96e61dd85c172b999d6afc88ce6640aeba9962sewardj                  binop( Iop_And32,
125204c96e61dd85c172b999d6afc88ce6640aeba9962sewardj                         mkexpr( KisZero_false_mask ),
125214c96e61dd85c172b999d6afc88ce6640aeba9962sewardj                         binop( Iop_Or32,
125224c96e61dd85c172b999d6afc88ce6640aeba9962sewardj                                binop( Iop_And32,
125234c96e61dd85c172b999d6afc88ce6640aeba9962sewardj                                       mkexpr( Lt_true_mask ),
125244c96e61dd85c172b999d6afc88ce6640aeba9962sewardj                                       mkU32( 0x8 ) ),
125254c96e61dd85c172b999d6afc88ce6640aeba9962sewardj                                binop( Iop_Or32,
125264c96e61dd85c172b999d6afc88ce6640aeba9962sewardj                                       binop( Iop_And32,
125274c96e61dd85c172b999d6afc88ce6640aeba9962sewardj                                              mkexpr( Gt_true_mask ),
125284c96e61dd85c172b999d6afc88ce6640aeba9962sewardj                                              mkU32( 0x4 ) ),
125294c96e61dd85c172b999d6afc88ce6640aeba9962sewardj                                       binop( Iop_And32,
125304c96e61dd85c172b999d6afc88ce6640aeba9962sewardj                                              mkexpr( Eq_true_mask ),
125314c96e61dd85c172b999d6afc88ce6640aeba9962sewardj                                              mkU32( 0x2 ) ) ) ) ),
125324c96e61dd85c172b999d6afc88ce6640aeba9962sewardj                  binop( Iop_And32,
125334c96e61dd85c172b999d6afc88ce6640aeba9962sewardj                         mkexpr( KisZero_true_mask ),
125344c96e61dd85c172b999d6afc88ce6640aeba9962sewardj                         mkU32( 0x4 ) ) ) );
125354c96e61dd85c172b999d6afc88ce6640aeba9962sewardj
125364c96e61dd85c172b999d6afc88ce6640aeba9962sewardj   putGST_field( PPC_GST_CR,
125374c96e61dd85c172b999d6afc88ce6640aeba9962sewardj                 binop( Iop_Or32,
125384c96e61dd85c172b999d6afc88ce6640aeba9962sewardj                        binop( Iop_And32,
125394c96e61dd85c172b999d6afc88ce6640aeba9962sewardj                               mkexpr( Unordered_true ),
125404c96e61dd85c172b999d6afc88ce6640aeba9962sewardj                               mkU32( 0x1 ) ),
125414c96e61dd85c172b999d6afc88ce6640aeba9962sewardj                        binop( Iop_And32,
125424c96e61dd85c172b999d6afc88ce6640aeba9962sewardj                               unop( Iop_Not32, mkexpr( Unordered_true ) ),
125434c96e61dd85c172b999d6afc88ce6640aeba9962sewardj                               mkexpr( field ) ) ),
125444c96e61dd85c172b999d6afc88ce6640aeba9962sewardj                 crfD );
125454c96e61dd85c172b999d6afc88ce6640aeba9962sewardj
125464c96e61dd85c172b999d6afc88ce6640aeba9962sewardj   return True;
125474c96e61dd85c172b999d6afc88ce6640aeba9962sewardj}
125485eff1c502e995d1f9668cc9def72d5db59f21b13sewardj
1254932aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion/*------------------------------------------------------------*/
1255032aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion/*--- AltiVec Instruction Translation                      ---*/
1255132aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion/*------------------------------------------------------------*/
1255232aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion
1255332aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion/*
1255432aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion  Altivec Cache Control Instructions (Data Streams)
1255532aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion*/
1255632aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerionstatic Bool dis_av_datastream ( UInt theInstr )
1255732aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion{
1255876de5cf615380b23b4b5bcced6541233cd4a93a0cerion   /* X-Form */
1255976de5cf615380b23b4b5bcced6541233cd4a93a0cerion   UChar opc1     = ifieldOPC(theInstr);
1256076de5cf615380b23b4b5bcced6541233cd4a93a0cerion   UChar flag_T   = toUChar( IFIELD( theInstr, 25, 1 ) );
1256176de5cf615380b23b4b5bcced6541233cd4a93a0cerion   UChar flag_A   = flag_T;
1256276de5cf615380b23b4b5bcced6541233cd4a93a0cerion   UChar b23to24  = toUChar( IFIELD( theInstr, 23, 2 ) );
1256376de5cf615380b23b4b5bcced6541233cd4a93a0cerion   UChar STRM     = toUChar( IFIELD( theInstr, 21, 2 ) );
1256476de5cf615380b23b4b5bcced6541233cd4a93a0cerion   UChar rA_addr  = ifieldRegA(theInstr);
1256576de5cf615380b23b4b5bcced6541233cd4a93a0cerion   UChar rB_addr  = ifieldRegB(theInstr);
1256676de5cf615380b23b4b5bcced6541233cd4a93a0cerion   UInt  opc2     = ifieldOPClo10(theInstr);
1256776de5cf615380b23b4b5bcced6541233cd4a93a0cerion   UChar b0       = ifieldBIT0(theInstr);
1256832aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion
1256932aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion   if (opc1 != 0x1F || b23to24 != 0 || b0 != 0) {
125705b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion      vex_printf("dis_av_datastream(ppc)(instr)\n");
1257132aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion      return False;
1257232aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion   }
1257332aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion
1257432aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion   switch (opc2) {
1257532aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion   case 0x156: // dst (Data Stream Touch, AV p115)
125765b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion      DIP("dst%s r%u,r%u,%d\n", flag_T ? "t" : "",
125775b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion                                rA_addr, rB_addr, STRM);
12578923c65b4e7bd32fb022735115d2bbcb8e03f13d2sewardj      break;
1257932aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion
1258032aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion   case 0x176: // dstst (Data Stream Touch for Store, AV p117)
125815b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion      DIP("dstst%s r%u,r%u,%d\n", flag_T ? "t" : "",
125825b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion                                  rA_addr, rB_addr, STRM);
12583923c65b4e7bd32fb022735115d2bbcb8e03f13d2sewardj      break;
1258432aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion
1258532aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion   case 0x336: // dss (Data Stream Stop, AV p114)
1258632aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion      if (rA_addr != 0 || rB_addr != 0) {
125875b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion         vex_printf("dis_av_datastream(ppc)(opc2,dst)\n");
1258832aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion         return False;
1258932aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion      }
1259032aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion      if (flag_A == 0) {
1259132aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion         DIP("dss %d\n", STRM);
1259232aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion      } else {
1259332aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion         DIP("dssall\n");
1259432aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion      }
12595923c65b4e7bd32fb022735115d2bbcb8e03f13d2sewardj      break;
1259632aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion
1259732aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion   default:
125985b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion      vex_printf("dis_av_datastream(ppc)(opc2)\n");
1259932aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion      return False;
1260032aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion   }
1260132aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion   return True;
1260232aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion}
1260332aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion
1260432aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion/*
1260532aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion  AltiVec Processor Control Instructions
1260632aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion*/
1260732aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerionstatic Bool dis_av_procctl ( UInt theInstr )
1260832aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion{
1260976de5cf615380b23b4b5bcced6541233cd4a93a0cerion   /* VX-Form */
1261076de5cf615380b23b4b5bcced6541233cd4a93a0cerion   UChar opc1    = ifieldOPC(theInstr);
1261176de5cf615380b23b4b5bcced6541233cd4a93a0cerion   UChar vD_addr = ifieldRegDS(theInstr);
1261276de5cf615380b23b4b5bcced6541233cd4a93a0cerion   UChar vA_addr = ifieldRegA(theInstr);
1261376de5cf615380b23b4b5bcced6541233cd4a93a0cerion   UChar vB_addr = ifieldRegB(theInstr);
1261476de5cf615380b23b4b5bcced6541233cd4a93a0cerion   UInt  opc2    = IFIELD( theInstr, 0, 11 );
1261532aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion
1261632aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion   if (opc1 != 0x4) {
126175b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion      vex_printf("dis_av_procctl(ppc)(instr)\n");
1261832aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion      return False;
1261932aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion   }
1262032aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion
1262132aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion   switch (opc2) {
1262232aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion   case 0x604: // mfvscr (Move from VSCR, AV p129)
1262332aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion      if (vA_addr != 0 || vB_addr != 0) {
126245b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion         vex_printf("dis_av_procctl(ppc)(opc2,dst)\n");
1262532aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion         return False;
1262632aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion      }
1262732aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion      DIP("mfvscr v%d\n", vD_addr);
12628d953ebb9b04cbad6891676df597bf0c542b1ec89cerion      putVReg( vD_addr, unop(Iop_32UtoV128, getGST( PPC_GST_VSCR )) );
12629225a034683024109da729a4d2f080364b9485007cerion      break;
1263032aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion
12631225a034683024109da729a4d2f080364b9485007cerion   case 0x644: { // mtvscr (Move to VSCR, AV p130)
12632197bd17d3ba8ac5204cd5c9ba5fab571249eb791sewardj      IRTemp vB = newTemp(Ity_V128);
1263332aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion      if (vD_addr != 0 || vA_addr != 0) {
126345b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion         vex_printf("dis_av_procctl(ppc)(opc2,dst)\n");
1263532aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion         return False;
1263632aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion      }
1263732aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion      DIP("mtvscr v%d\n", vB_addr);
12638225a034683024109da729a4d2f080364b9485007cerion      assign( vB, getVReg(vB_addr));
12639d953ebb9b04cbad6891676df597bf0c542b1ec89cerion      putGST( PPC_GST_VSCR, unop(Iop_V128to32, mkexpr(vB)) );
12640225a034683024109da729a4d2f080364b9485007cerion      break;
12641225a034683024109da729a4d2f080364b9485007cerion   }
1264232aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion   default:
126435b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion      vex_printf("dis_av_procctl(ppc)(opc2)\n");
1264432aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion      return False;
1264532aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion   }
1264632aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion   return True;
1264732aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion}
12648a982c0503d8c0c6069ae453bfe70657bd2c134aecerion
12649a982c0503d8c0c6069ae453bfe70657bd2c134aecerion/*
126504aa412af1d8166cc11f39a6e721df49431d23618sewardj * VSX scalar and vector convert instructions
1265166d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj */
1265266d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardjstatic Bool
1265366d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardjdis_vx_conv ( UInt theInstr, UInt opc2 )
1265466d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj{
1265566d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj   /* XX2-Form */
1265666d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj   UChar opc1 = ifieldOPC( theInstr );
1265766d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj   UChar XT = ifieldRegXT( theInstr );
1265866d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj   UChar XB = ifieldRegXB( theInstr );
12659e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj   IRTemp xB, xB2;
12660e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj   IRTemp b3, b2, b1, b0;
12661e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj   xB = xB2 = IRTemp_INVALID;
1266266d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj
1266366d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj   if (opc1 != 0x3C) {
1266466d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj      vex_printf( "dis_vx_conv(ppc)(instr)\n" );
1266566d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj      return False;
1266666d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj   }
1266766d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj
12668e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj   /* Create and assign temps only as needed for the given instruction. */
12669e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj   switch (opc2) {
12670e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj      // scalar double-precision floating point argument
126710c74bb5aa3240f693df0568d578baabf0c376dc4carll      case 0x2B0: case 0x0b0: case 0x290: case 0x212: case 0x216: case 0x090:
12672e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj         xB = newTemp(Ity_F64);
12673e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj         assign( xB,
12674e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj                 unop( Iop_ReinterpI64asF64,
12675e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj                       unop( Iop_V128HIto64, getVSReg( XB ) ) ) );
12676e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj         break;
12677e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj      // vector double-precision floating point arguments
12678e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj      case 0x1b0: case 0x312: case 0x390: case 0x190: case 0x3B0:
12679e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj
12680e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj         xB = newTemp(Ity_F64);
12681e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj         xB2 = newTemp(Ity_F64);
12682e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj         assign( xB,
12683e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj                 unop( Iop_ReinterpI64asF64,
12684e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj                       unop( Iop_V128HIto64, getVSReg( XB ) ) ) );
12685e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj         assign( xB2,
12686e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj                 unop( Iop_ReinterpI64asF64,
12687e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj                       unop( Iop_V128to64, getVSReg( XB ) ) ) );
12688e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj         break;
12689e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj      // vector single precision or [un]signed integer word arguments
12690e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj      case 0x130: case 0x392: case 0x330: case 0x310: case 0x110:
12691e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj      case 0x1f0: case 0x1d0:
12692e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj         b3 = b2 = b1 = b0 = IRTemp_INVALID;
12693e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj         breakV128to4x32(getVSReg(XB), &b3, &b2, &b1, &b0);
12694e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj         break;
12695e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj         // vector [un]signed integer doubleword argument
12696e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj      case 0x3f0: case 0x370: case 0x3d0: case 0x350:
12697e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj         xB = newTemp(Ity_I64);
12698e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj         assign( xB, unop( Iop_V128HIto64, getVSReg( XB ) ) );
12699e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj         xB2 = newTemp(Ity_I64);
12700e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj         assign( xB2, unop( Iop_V128to64, getVSReg( XB ) ) );
12701e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj         break;
12702e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj      // scalar [un]signed integer doubleword argument
127036c758b64a77c254065ab7450576bbd3a0b583595carll      case 0x250: case 0x270: case 0x2D0: case 0x2F0:
12704e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj         xB = newTemp(Ity_I64);
12705e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj         assign( xB, unop( Iop_V128HIto64, getVSReg( XB ) ) );
12706e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj         break;
12707e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj      // scalar single precision argument
12708e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj      case 0x292: // xscvspdp
127096fef87a15cd79526ece8c38798e2d304b805a1f3carll         xB  = newTemp(Ity_I32);
127106fef87a15cd79526ece8c38798e2d304b805a1f3carll
127116fef87a15cd79526ece8c38798e2d304b805a1f3carll         assign( xB, handle_SNaN_to_QNaN_32(unop( Iop_64HIto32,
127126fef87a15cd79526ece8c38798e2d304b805a1f3carll                                                  unop( Iop_V128HIto64,
127136fef87a15cd79526ece8c38798e2d304b805a1f3carll                                                        getVSReg( XB ) ) ) ) );
12714e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj         break;
127150c74bb5aa3240f693df0568d578baabf0c376dc4carll      case 0x296: // xscvspdpn (non signaling version of xscvpdp)
127160c74bb5aa3240f693df0568d578baabf0c376dc4carll         xB = newTemp(Ity_I32);
127170c74bb5aa3240f693df0568d578baabf0c376dc4carll         assign( xB,
127180c74bb5aa3240f693df0568d578baabf0c376dc4carll                 unop( Iop_64HIto32, unop( Iop_V128HIto64, getVSReg( XB ) ) ) );
127190c74bb5aa3240f693df0568d578baabf0c376dc4carll         break;
12720e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj
12721e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj      /* Certain instructions have their complete implementation in the main switch statement
12722e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj       * that follows this one; thus we have a "do nothing" case for those instructions here.
12723e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj       */
12724e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj      case 0x170: case 0x150:
12725e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj         break; // do nothing
12726e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj
12727e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj      default:
12728e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj         vex_printf( "dis_vx_conv(ppc)(opc2)\n" );
12729e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj         return False;
12730e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj   }
12731e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj
1273266d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj
1273366d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj   switch (opc2) {
12734e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj      case 0x2B0:
12735e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj         // xscvdpsxds (VSX Scalar truncate Double-Precision to integer and Convert
12736e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj         //             to Signed Integer Doubleword format with Saturate)
12737b173774421d015736c2316b5e6e998e7de545a5cflorian         DIP("xscvdpsxds v%u,v%u\n", XT, XB);
12738e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj         putVSReg( XT,
1273966d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj                   binop( Iop_64HLtoV128, binop( Iop_F64toI64S,
1274066d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj                                                 mkU32( Irrm_ZERO ),
12741e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj                                                 mkexpr( xB ) ), mkU64( 0 ) ) );
12742e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj         break;
12743e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj      case 0x0b0: // xscvdpsxws (VSX Scalar truncate Double-Precision to integer and
12744e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj                  //             Convert to Signed Integer Word format with Saturate)
12745b173774421d015736c2316b5e6e998e7de545a5cflorian         DIP("xscvdpsxws v%u,v%u\n", XT, XB);
12746e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj         putVSReg( XT,
127474aa412af1d8166cc11f39a6e721df49431d23618sewardj                   binop( Iop_64HLtoV128,
127484aa412af1d8166cc11f39a6e721df49431d23618sewardj                          unop( Iop_32Sto64,
127494aa412af1d8166cc11f39a6e721df49431d23618sewardj                                binop( Iop_F64toI32S,
127504aa412af1d8166cc11f39a6e721df49431d23618sewardj                                       mkU32( Irrm_ZERO ),
12751e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj                                       mkexpr( xB ) ) ),
12752e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj                                       mkU64( 0ULL ) ) );
127534aa412af1d8166cc11f39a6e721df49431d23618sewardj         break;
12754e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj      case 0x290: // xscvdpuxds (VSX Scalar truncate Double-Precision integer and Convert
12755e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj                  //             to Unsigned Integer Doubleword format with Saturate)
12756b173774421d015736c2316b5e6e998e7de545a5cflorian         DIP("xscvdpuxds v%u,v%u\n", XT, XB);
12757e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj         putVSReg( XT,
127584aa412af1d8166cc11f39a6e721df49431d23618sewardj                   binop( Iop_64HLtoV128,
127594aa412af1d8166cc11f39a6e721df49431d23618sewardj                          binop( Iop_F64toI64U,
127604aa412af1d8166cc11f39a6e721df49431d23618sewardj                                 mkU32( Irrm_ZERO ),
12761e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj                                 mkexpr( xB ) ),
12762e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj                                 mkU64( 0ULL ) ) );
12763e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj         break;
127646c758b64a77c254065ab7450576bbd3a0b583595carll      case 0x270:
127656c758b64a77c254065ab7450576bbd3a0b583595carll         // xscvsxdsp (VSX Scalar Convert and round Signed Integer Doubleword
127666c758b64a77c254065ab7450576bbd3a0b583595carll         //             to Single-Precision format)
12767b173774421d015736c2316b5e6e998e7de545a5cflorian         DIP("xscvsxdsp v%u,v%u\n", XT, XB);
127686c758b64a77c254065ab7450576bbd3a0b583595carll         putVSReg( XT,
127696c758b64a77c254065ab7450576bbd3a0b583595carll                   binop( Iop_64HLtoV128,
127706c758b64a77c254065ab7450576bbd3a0b583595carll                          unop( Iop_ReinterpF64asI64,
127716c758b64a77c254065ab7450576bbd3a0b583595carll                                binop( Iop_RoundF64toF32,
127726c758b64a77c254065ab7450576bbd3a0b583595carll                                       get_IR_roundingmode(),
127736c758b64a77c254065ab7450576bbd3a0b583595carll                                       binop( Iop_I64StoF64,
127746c758b64a77c254065ab7450576bbd3a0b583595carll                                              get_IR_roundingmode(),
127756c758b64a77c254065ab7450576bbd3a0b583595carll                                              mkexpr( xB ) ) ) ),
127766c758b64a77c254065ab7450576bbd3a0b583595carll                          mkU64( 0 ) ) );
127776c758b64a77c254065ab7450576bbd3a0b583595carll         break;
12778e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj      case 0x2F0:
12779e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj         // xscvsxddp (VSX Scalar Convert and round Signed Integer Doubleword to
12780e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj         //            Double-Precision format)
12781b173774421d015736c2316b5e6e998e7de545a5cflorian         DIP("xscvsxddp v%u,v%u\n", XT, XB);
12782e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj         putVSReg( XT,
1278366d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj                   binop( Iop_64HLtoV128, unop( Iop_ReinterpF64asI64,
127844aa412af1d8166cc11f39a6e721df49431d23618sewardj                                                binop( Iop_I64StoF64, get_IR_roundingmode(),
12785e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj                                                       mkexpr( xB ) ) ),
12786e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj                                                       mkU64( 0 ) ) );
12787e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj         break;
127886c758b64a77c254065ab7450576bbd3a0b583595carll      case 0x250:
127896c758b64a77c254065ab7450576bbd3a0b583595carll         // xscvuxdsp (VSX Scalar Convert and round Unsigned Integer
127906c758b64a77c254065ab7450576bbd3a0b583595carll         //            Doubleword to Singel-Precision format)
12791b173774421d015736c2316b5e6e998e7de545a5cflorian         DIP("xscvuxdsp v%u,v%u\n", XT, XB);
127926c758b64a77c254065ab7450576bbd3a0b583595carll         putVSReg( XT,
127936c758b64a77c254065ab7450576bbd3a0b583595carll                   binop( Iop_64HLtoV128,
127946c758b64a77c254065ab7450576bbd3a0b583595carll                          unop( Iop_ReinterpF64asI64,
127956c758b64a77c254065ab7450576bbd3a0b583595carll                                binop( Iop_RoundF64toF32,
127966c758b64a77c254065ab7450576bbd3a0b583595carll                                       get_IR_roundingmode(),
127976c758b64a77c254065ab7450576bbd3a0b583595carll                                       binop( Iop_I64UtoF64,
127986c758b64a77c254065ab7450576bbd3a0b583595carll                                              get_IR_roundingmode(),
127996c758b64a77c254065ab7450576bbd3a0b583595carll                                              mkexpr( xB ) ) ) ),
128006c758b64a77c254065ab7450576bbd3a0b583595carll                          mkU64( 0 ) ) );
128016c758b64a77c254065ab7450576bbd3a0b583595carll         break;
12802e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj      case 0x2D0:
12803e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj         // xscvuxddp (VSX Scalar Convert and round Unsigned Integer Doubleword to
12804e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj         //            Double-Precision format)
12805b173774421d015736c2316b5e6e998e7de545a5cflorian         DIP("xscvuxddp v%u,v%u\n", XT, XB);
12806e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj         putVSReg( XT,
1280766d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj                   binop( Iop_64HLtoV128, unop( Iop_ReinterpF64asI64,
128084aa412af1d8166cc11f39a6e721df49431d23618sewardj                                                binop( Iop_I64UtoF64, get_IR_roundingmode(),
12809e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj                                                       mkexpr( xB ) ) ),
12810e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj                                                       mkU64( 0 ) ) );
12811e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj         break;
12812e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj      case 0x1b0: // xvcvdpsxws (VSX Vector truncate Double-Precision to integer and Convert
12813e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj                  //             to Signed Integer Word format with Saturate)
12814e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj      {
12815e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj         IRTemp hiResult_32 = newTemp(Ity_I32);
12816e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj         IRTemp loResult_32 = newTemp(Ity_I32);
12817e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj         IRExpr* rmZero = mkU32(Irrm_ZERO);
1281866d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj
12819b173774421d015736c2316b5e6e998e7de545a5cflorian         DIP("xvcvdpsxws v%u,v%u\n",  XT, XB);
12820e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj         assign(hiResult_32, binop(Iop_F64toI32S, rmZero, mkexpr(xB)));
12821e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj         assign(loResult_32, binop(Iop_F64toI32S, rmZero, mkexpr(xB2)));
12822e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj         putVSReg( XT,
128234aa412af1d8166cc11f39a6e721df49431d23618sewardj                   binop( Iop_64HLtoV128,
128244aa412af1d8166cc11f39a6e721df49431d23618sewardj                          unop( Iop_32Sto64, mkexpr( hiResult_32 ) ),
128254aa412af1d8166cc11f39a6e721df49431d23618sewardj                          unop( Iop_32Sto64, mkexpr( loResult_32 ) ) ) );
12826e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj         break;
12827e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj      }
12828e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj      case 0x130: case 0x110: // xvcvspsxws, xvcvspuxws
12829e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj         //  (VSX Vector truncate Single-Precision to integer and
12830e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj         //   Convert to [Un]signed Integer Word format with Saturate)
12831e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj      {
12832e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj         IRExpr * b0_result, * b1_result, * b2_result, * b3_result;
12833e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj         IRTemp tempResult = newTemp(Ity_V128);
12834e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj         IRTemp res0 = newTemp(Ity_I32);
12835e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj         IRTemp res1 = newTemp(Ity_I32);
12836e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj         IRTemp res2 = newTemp(Ity_I32);
12837e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj         IRTemp res3 = newTemp(Ity_I32);
12838e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj         IRTemp hi64 = newTemp(Ity_I64);
12839e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj         IRTemp lo64 = newTemp(Ity_I64);
12840e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj         Bool un_signed = (opc2 == 0x110);
12841e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj         IROp op = un_signed ? Iop_QFtoI32Ux4_RZ : Iop_QFtoI32Sx4_RZ;
12842e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj
12843b173774421d015736c2316b5e6e998e7de545a5cflorian         DIP("xvcvsp%sxws v%u,v%u\n", un_signed ? "u" : "s", XT, XB);
12844e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj         /* The xvcvsp{s|u}xws instruction is similar to vct{s|u}xs, except if src is a NaN,
12845e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj          * then result is set to 0x80000000.  */
12846e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj         assign(tempResult, unop(op, getVSReg(XB)));
12847e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj         assign( hi64, unop(Iop_V128HIto64, mkexpr(tempResult)) );
12848e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj         assign( lo64, unop(Iop_V128to64,   mkexpr(tempResult)) );
12849e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj         assign( res3, unop(Iop_64HIto32, mkexpr(hi64)) );
12850e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj         assign( res2, unop(Iop_64to32,   mkexpr(hi64)) );
12851e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj         assign( res1, unop(Iop_64HIto32, mkexpr(lo64)) );
12852e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj         assign( res0, unop(Iop_64to32,   mkexpr(lo64)) );
12853e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj
1285499dd03e04a6914d90d5fee727d61d76905334becflorian         b3_result = IRExpr_ITE(is_NaN_32(b3),
1285599dd03e04a6914d90d5fee727d61d76905334becflorian                                // then: result is 0x{8|0}80000000
1285699dd03e04a6914d90d5fee727d61d76905334becflorian                                mkU32(un_signed ? 0x00000000 : 0x80000000),
1285799dd03e04a6914d90d5fee727d61d76905334becflorian                                // else: result is from the Iop_QFtoI32{s|u}x4_RZ
1285899dd03e04a6914d90d5fee727d61d76905334becflorian                                mkexpr(res3));
1285999dd03e04a6914d90d5fee727d61d76905334becflorian         b2_result = IRExpr_ITE(is_NaN_32(b2),
1286099dd03e04a6914d90d5fee727d61d76905334becflorian                                // then: result is 0x{8|0}80000000
1286199dd03e04a6914d90d5fee727d61d76905334becflorian                                mkU32(un_signed ? 0x00000000 : 0x80000000),
1286299dd03e04a6914d90d5fee727d61d76905334becflorian                                // else: result is from the Iop_QFtoI32{s|u}x4_RZ
1286399dd03e04a6914d90d5fee727d61d76905334becflorian                                mkexpr(res2));
1286499dd03e04a6914d90d5fee727d61d76905334becflorian         b1_result = IRExpr_ITE(is_NaN_32(b1),
1286599dd03e04a6914d90d5fee727d61d76905334becflorian                                // then: result is 0x{8|0}80000000
1286699dd03e04a6914d90d5fee727d61d76905334becflorian                                mkU32(un_signed ? 0x00000000 : 0x80000000),
1286799dd03e04a6914d90d5fee727d61d76905334becflorian                                // else: result is from the Iop_QFtoI32{s|u}x4_RZ
1286899dd03e04a6914d90d5fee727d61d76905334becflorian                                mkexpr(res1));
1286999dd03e04a6914d90d5fee727d61d76905334becflorian         b0_result = IRExpr_ITE(is_NaN_32(b0),
1287099dd03e04a6914d90d5fee727d61d76905334becflorian                                // then: result is 0x{8|0}80000000
1287199dd03e04a6914d90d5fee727d61d76905334becflorian                                mkU32(un_signed ? 0x00000000 : 0x80000000),
1287299dd03e04a6914d90d5fee727d61d76905334becflorian                                // else: result is from the Iop_QFtoI32{s|u}x4_RZ
1287399dd03e04a6914d90d5fee727d61d76905334becflorian                                mkexpr(res0));
12874e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj
12875e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj         putVSReg( XT,
128764aa412af1d8166cc11f39a6e721df49431d23618sewardj                   binop( Iop_64HLtoV128,
128774aa412af1d8166cc11f39a6e721df49431d23618sewardj                          binop( Iop_32HLto64, b3_result, b2_result ),
128784aa412af1d8166cc11f39a6e721df49431d23618sewardj                          binop( Iop_32HLto64, b1_result, b0_result ) ) );
12879e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj         break;
12880e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj      }
12881e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj      case 0x212: // xscvdpsp (VSX Scalar round Double-Precision to single-precision and
12882e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj                  //           Convert to Single-Precision format
12883b173774421d015736c2316b5e6e998e7de545a5cflorian         DIP("xscvdpsp v%u,v%u\n", XT, XB);
12884e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj         putVSReg( XT,
12885e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj                   binop( Iop_64HLtoV128,
12886e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj                          binop( Iop_32HLto64,
12887e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj                                 unop( Iop_ReinterpF32asI32,
12888e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj                                       unop( Iop_TruncF64asF32,
12889e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj                                             binop( Iop_RoundF64toF32,
12890e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj                                                    get_IR_roundingmode(),
12891e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj                                                    mkexpr( xB ) ) ) ),
12892e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj                                 mkU32( 0 ) ),
12893e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj                          mkU64( 0ULL ) ) );
12894e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj         break;
128950c74bb5aa3240f693df0568d578baabf0c376dc4carll      case 0x216: /* xscvdpspn (VSX Scalar convert scalar Single-Precision to
128966c758b64a77c254065ab7450576bbd3a0b583595carll                              vector Single-Precision non-signalling */
12897b173774421d015736c2316b5e6e998e7de545a5cflorian         DIP("xscvdpspn v%u,v%u\n", XT, XB);
128980c74bb5aa3240f693df0568d578baabf0c376dc4carll         putVSReg( XT,
128990c74bb5aa3240f693df0568d578baabf0c376dc4carll                   binop( Iop_64HLtoV128,
129000c74bb5aa3240f693df0568d578baabf0c376dc4carll                          binop( Iop_32HLto64,
129010c74bb5aa3240f693df0568d578baabf0c376dc4carll                                 unop( Iop_ReinterpF32asI32,
129020c74bb5aa3240f693df0568d578baabf0c376dc4carll                                       unop( Iop_TruncF64asF32,
129030c74bb5aa3240f693df0568d578baabf0c376dc4carll                                             mkexpr( xB ) ) ),
129046c758b64a77c254065ab7450576bbd3a0b583595carll                                 mkU32( 0 ) ),
129056c758b64a77c254065ab7450576bbd3a0b583595carll                          mkU64( 0ULL ) ) );
129060c74bb5aa3240f693df0568d578baabf0c376dc4carll         break;
12907e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj      case 0x090: // xscvdpuxws (VSX Scalar truncate Double-Precision to integer
12908e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj                  //             and Convert to Unsigned Integer Word format with Saturate)
12909b173774421d015736c2316b5e6e998e7de545a5cflorian         DIP("xscvdpuxws v%u,v%u\n", XT, XB);
12910e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj         putVSReg( XT,
12911e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj                   binop( Iop_64HLtoV128,
12912e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj                          binop( Iop_32HLto64,
12913e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj                                 mkU32( 0 ),
12914e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj                                 binop( Iop_F64toI32U,
12915e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj                                        mkU32( Irrm_ZERO ),
12916e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj                                        mkexpr( xB ) ) ),
12917e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj                          mkU64( 0ULL ) ) );
12918e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj         break;
129196c758b64a77c254065ab7450576bbd3a0b583595carll      case 0x292: // xscvspdp (VSX Scalar Convert Single-Precision to Double-Precision format, signaling)
12920b173774421d015736c2316b5e6e998e7de545a5cflorian         DIP("xscvspdp v%u,v%u\n", XT, XB);
12921e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj         putVSReg( XT,
12922e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj                   binop( Iop_64HLtoV128,
12923e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj                          unop( Iop_ReinterpF64asI64,
12924e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj                                unop( Iop_F32toF64,
12925e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj                                      unop( Iop_ReinterpI32asF32, mkexpr( xB ) ) ) ),
12926e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj                          mkU64( 0ULL ) ) );
12927e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj         break;
129280c74bb5aa3240f693df0568d578baabf0c376dc4carll      case 0x296: // xscvspdpn (VSX Scalar Convert Single-Precision to Double-Precision format Non signaling)
12929b173774421d015736c2316b5e6e998e7de545a5cflorian         DIP("xscvspdpn v%u,v%u\n", XT, XB);
129300c74bb5aa3240f693df0568d578baabf0c376dc4carll         putVSReg( XT,
129310c74bb5aa3240f693df0568d578baabf0c376dc4carll                   binop( Iop_64HLtoV128,
129320c74bb5aa3240f693df0568d578baabf0c376dc4carll                          unop( Iop_ReinterpF64asI64,
129330c74bb5aa3240f693df0568d578baabf0c376dc4carll                                unop( Iop_F32toF64,
129340c74bb5aa3240f693df0568d578baabf0c376dc4carll                                      unop( Iop_ReinterpI32asF32, mkexpr( xB ) ) ) ),
129350c74bb5aa3240f693df0568d578baabf0c376dc4carll                                      mkU64( 0ULL ) ) );
129360c74bb5aa3240f693df0568d578baabf0c376dc4carll         break;
12937e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj      case 0x312: // xvcvdpsp (VSX Vector round Double-Precision to single-precision
12938e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj                  //           and Convert to Single-Precision format)
12939b173774421d015736c2316b5e6e998e7de545a5cflorian         DIP("xvcvdpsp v%u,v%u\n", XT, XB);
12940e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj         putVSReg( XT,
12941e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj                   binop( Iop_64HLtoV128,
12942e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj                          binop( Iop_32HLto64,
12943e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj                                 unop( Iop_ReinterpF32asI32,
12944e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj                                       unop( Iop_TruncF64asF32,
12945e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj                                             binop( Iop_RoundF64toF32,
12946e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj                                                    get_IR_roundingmode(),
12947e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj                                                    mkexpr( xB ) ) ) ),
12948e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj                                 mkU32( 0 ) ),
12949e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj                          binop( Iop_32HLto64,
12950e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj                                 unop( Iop_ReinterpF32asI32,
12951e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj                                       unop( Iop_TruncF64asF32,
12952e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj                                             binop( Iop_RoundF64toF32,
12953e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj                                                    get_IR_roundingmode(),
12954e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj                                                    mkexpr( xB2 ) ) ) ),
12955e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj                                 mkU32( 0 ) ) ) );
12956e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj         break;
12957e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj      case 0x390: // xvcvdpuxds (VSX Vector truncate Double-Precision to integer
12958e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj                  //             and Convert to Unsigned Integer Doubleword format
12959e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj                  //             with Saturate)
12960b173774421d015736c2316b5e6e998e7de545a5cflorian         DIP("xvcvdpuxds v%u,v%u\n", XT, XB);
12961e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj         putVSReg( XT,
12962e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj                   binop( Iop_64HLtoV128,
12963e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj                          binop( Iop_F64toI64U, mkU32( Irrm_ZERO ), mkexpr( xB ) ),
12964e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj                          binop( Iop_F64toI64U, mkU32( Irrm_ZERO ), mkexpr( xB2 ) ) ) );
12965e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj         break;
12966e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj      case 0x190: // xvcvdpuxws (VSX Vector truncate Double-Precision to integer and
12967e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj                  //             Convert to Unsigned Integer Word format with Saturate)
12968b173774421d015736c2316b5e6e998e7de545a5cflorian         DIP("xvcvdpuxws v%u,v%u\n", XT, XB);
12969e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj         putVSReg( XT,
12970e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj                   binop( Iop_64HLtoV128,
12971e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj                          binop( Iop_32HLto64,
12972e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj                                 binop( Iop_F64toI32U,
12973e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj                                        mkU32( Irrm_ZERO ),
12974e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj                                        mkexpr( xB ) ),
12975e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj                                 mkU32( 0 ) ),
12976e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj                          binop( Iop_32HLto64,
12977e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj                                 binop( Iop_F64toI32U,
12978e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj                                        mkU32( Irrm_ZERO ),
12979e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj                                        mkexpr( xB2 ) ),
12980e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj                                 mkU32( 0 ) ) ) );
12981e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj         break;
12982e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj      case 0x392: // xvcvspdp (VSX Vector Convert Single-Precision to Double-Precision format)
12983b173774421d015736c2316b5e6e998e7de545a5cflorian         DIP("xvcvspdp v%u,v%u\n", XT, XB);
12984e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj         putVSReg( XT,
12985e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj                   binop( Iop_64HLtoV128,
12986e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj                          unop( Iop_ReinterpF64asI64,
12987e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj                                unop( Iop_F32toF64,
129886fef87a15cd79526ece8c38798e2d304b805a1f3carll                                      unop( Iop_ReinterpI32asF32,
129896fef87a15cd79526ece8c38798e2d304b805a1f3carll                                            handle_SNaN_to_QNaN_32( mkexpr( b3 ) ) ) ) ),
12990e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj                          unop( Iop_ReinterpF64asI64,
12991e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj                                unop( Iop_F32toF64,
129926fef87a15cd79526ece8c38798e2d304b805a1f3carll                                      unop( Iop_ReinterpI32asF32,
129936fef87a15cd79526ece8c38798e2d304b805a1f3carll                                            handle_SNaN_to_QNaN_32( mkexpr( b1 ) ) ) ) ) ) );
12994e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj         break;
12995e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj      case 0x330: // xvcvspsxds (VSX Vector truncate Single-Precision to integer and
12996e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj                  //           Convert to Signed Integer Doubleword format with Saturate)
12997b173774421d015736c2316b5e6e998e7de545a5cflorian         DIP("xvcvspsxds v%u,v%u\n", XT, XB);
12998e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj         putVSReg( XT,
12999e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj                   binop( Iop_64HLtoV128,
13000e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj                          binop( Iop_F64toI64S,
13001e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj                                 mkU32( Irrm_ZERO ),
13002e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj                                 unop( Iop_F32toF64,
13003e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj                                       unop( Iop_ReinterpI32asF32, mkexpr( b3 ) ) ) ),
13004e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj                          binop( Iop_F64toI64S,
13005e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj                                 mkU32( Irrm_ZERO ),
13006e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj                                 unop( Iop_F32toF64,
13007e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj                                       unop( Iop_ReinterpI32asF32, mkexpr( b1 ) ) ) ) ) );
13008e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj         break;
13009e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj      case 0x310: // xvcvspuxds (VSX Vector truncate Single-Precision to integer and
13010e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj                  //            Convert to Unsigned Integer Doubleword format with Saturate)
13011b173774421d015736c2316b5e6e998e7de545a5cflorian         DIP("xvcvspuxds v%u,v%u\n", XT, XB);
13012e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj         putVSReg( XT,
13013e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj                   binop( Iop_64HLtoV128,
13014e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj                          binop( Iop_F64toI64U,
13015e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj                                 mkU32( Irrm_ZERO ),
13016e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj                                 unop( Iop_F32toF64,
13017e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj                                       unop( Iop_ReinterpI32asF32, mkexpr( b3 ) ) ) ),
13018e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj                          binop( Iop_F64toI64U,
13019e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj                                 mkU32( Irrm_ZERO ),
13020e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj                                 unop( Iop_F32toF64,
13021e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj                                       unop( Iop_ReinterpI32asF32, mkexpr( b1 ) ) ) ) ) );
13022e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj         break;
13023e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj      case 0x3B0: // xvcvdpsxds (VSX Vector truncate Double-Precision to integer and
13024e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj                  //             Convert to Signed Integer Doubleword format with Saturate)
13025b173774421d015736c2316b5e6e998e7de545a5cflorian         DIP("xvcvdpsxds v%u,v%u\n", XT, XB);
13026e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj         putVSReg( XT,
13027e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj                   binop( Iop_64HLtoV128,
13028e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj                          binop( Iop_F64toI64S, mkU32( Irrm_ZERO ), mkexpr( xB ) ),
13029e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj                          binop( Iop_F64toI64S, mkU32( Irrm_ZERO ), mkexpr( xB2 ) ) ) );
13030e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj         break;
13031e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj      case 0x3f0: // xvcvsxddp (VSX Vector Convert and round Signed Integer Doubleword
13032e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj                  //            to Double-Precision format)
13033b173774421d015736c2316b5e6e998e7de545a5cflorian         DIP("xvcvsxddp v%u,v%u\n", XT, XB);
13034e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj         putVSReg( XT,
13035e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj                   binop( Iop_64HLtoV128,
13036e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj                          unop( Iop_ReinterpF64asI64,
13037e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj                                binop( Iop_I64StoF64,
13038e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj                                       get_IR_roundingmode(),
13039e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj                                       mkexpr( xB ) ) ),
13040e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj                          unop( Iop_ReinterpF64asI64,
13041e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj                                binop( Iop_I64StoF64,
13042e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj                                       get_IR_roundingmode(),
13043e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj                                       mkexpr( xB2 ) ) ) ) );
13044e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj         break;
13045e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj      case 0x3d0: // xvcvuxddp (VSX Vector Convert and round Unsigned Integer Doubleword
13046e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj                  //            to Double-Precision format)
13047b173774421d015736c2316b5e6e998e7de545a5cflorian         DIP("xvcvuxddp v%u,v%u\n", XT, XB);
13048e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj         putVSReg( XT,
13049e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj                   binop( Iop_64HLtoV128,
13050e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj                          unop( Iop_ReinterpF64asI64,
13051e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj                                binop( Iop_I64UtoF64,
13052e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj                                       get_IR_roundingmode(),
13053e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj                                       mkexpr( xB ) ) ),
13054e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj                          unop( Iop_ReinterpF64asI64,
13055e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj                                binop( Iop_I64UtoF64,
13056e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj                                       get_IR_roundingmode(),
13057e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj                                       mkexpr( xB2 ) ) ) ) );
13058e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj
13059e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj         break;
13060e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj      case 0x370: // xvcvsxdsp (VSX Vector Convert and round Signed Integer Doubleword
13061e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj                  //            to Single-Precision format)
13062b173774421d015736c2316b5e6e998e7de545a5cflorian         DIP("xvcvsxddp v%u,v%u\n",  XT, XB);
13063e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj         putVSReg( XT,
13064e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj                   binop( Iop_64HLtoV128,
13065e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj                          binop( Iop_32HLto64,
13066e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj                                 unop( Iop_ReinterpF32asI32,
13067e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj                                       unop( Iop_TruncF64asF32,
13068e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj                                             binop( Iop_RoundF64toF32,
13069e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj                                                    get_IR_roundingmode(),
13070e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj                                                    binop( Iop_I64StoF64,
13071e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj                                                           get_IR_roundingmode(),
13072e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj                                                           mkexpr( xB ) ) ) ) ),
13073e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj                                 mkU32( 0 ) ),
13074e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj                          binop( Iop_32HLto64,
13075e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj                                 unop( Iop_ReinterpF32asI32,
13076e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj                                       unop( Iop_TruncF64asF32,
13077e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj                                             binop( Iop_RoundF64toF32,
13078e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj                                                    get_IR_roundingmode(),
13079e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj                                                    binop( Iop_I64StoF64,
13080e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj                                                           get_IR_roundingmode(),
13081e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj                                                           mkexpr( xB2 ) ) ) ) ),
13082e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj                                 mkU32( 0 ) ) ) );
13083e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj         break;
13084e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj      case 0x350: // xvcvuxdsp (VSX Vector Convert and round Unsigned Integer Doubleword
13085e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj                  //            to Single-Precision format)
13086b173774421d015736c2316b5e6e998e7de545a5cflorian         DIP("xvcvuxddp v%u,v%u\n", XT, XB);
13087e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj         putVSReg( XT,
13088e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj                   binop( Iop_64HLtoV128,
13089e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj                          binop( Iop_32HLto64,
13090e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj                                 unop( Iop_ReinterpF32asI32,
13091e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj                                       unop( Iop_TruncF64asF32,
13092e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj                                             binop( Iop_RoundF64toF32,
13093e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj                                                    get_IR_roundingmode(),
13094e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj                                                    binop( Iop_I64UtoF64,
13095e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj                                                           get_IR_roundingmode(),
13096e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj                                                           mkexpr( xB ) ) ) ) ),
13097e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj                                 mkU32( 0 ) ),
13098e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj                          binop( Iop_32HLto64,
13099e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj                                 unop( Iop_ReinterpF32asI32,
13100e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj                                       unop( Iop_TruncF64asF32,
13101e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj                                             binop( Iop_RoundF64toF32,
13102e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj                                                    get_IR_roundingmode(),
13103e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj                                                    binop( Iop_I64UtoF64,
13104e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj                                                           get_IR_roundingmode(),
13105e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj                                                           mkexpr( xB2 ) ) ) ) ),
13106e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj                                 mkU32( 0 ) ) ) );
13107e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj         break;
13108e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj
13109e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj      case 0x1f0: // xvcvsxwdp (VSX Vector Convert Signed Integer Word to Double-Precision format)
13110b173774421d015736c2316b5e6e998e7de545a5cflorian         DIP("xvcvsxwdp v%u,v%u\n",  XT, XB);
13111e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj         putVSReg( XT,
13112e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj                   binop( Iop_64HLtoV128,
13113e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj                          unop( Iop_ReinterpF64asI64,
13114e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj                                binop( Iop_I64StoF64, get_IR_roundingmode(),
13115e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj                                       unop( Iop_32Sto64, mkexpr( b3 ) ) ) ),
13116e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj                          unop( Iop_ReinterpF64asI64,
13117e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj                                binop( Iop_I64StoF64, get_IR_roundingmode(),
13118e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj                                       unop( Iop_32Sto64, mkexpr( b1 ) ) ) ) ) );
13119e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj         break;
13120e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj      case 0x1d0: // xvcvuxwdp (VSX Vector Convert Unsigned Integer Word to Double-Precision format)
13121b173774421d015736c2316b5e6e998e7de545a5cflorian         DIP("xvcvuxwdp v%u,v%u\n",  XT, XB);
13122e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj         putVSReg( XT,
13123e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj                   binop( Iop_64HLtoV128,
13124e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj                          unop( Iop_ReinterpF64asI64,
13125e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj                                binop( Iop_I64UtoF64, get_IR_roundingmode(),
13126e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj                                       unop( Iop_32Uto64, mkexpr( b3 ) ) ) ),
13127e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj                          unop( Iop_ReinterpF64asI64,
13128e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj                                binop( Iop_I64UtoF64, get_IR_roundingmode(),
13129e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj                                       unop( Iop_32Uto64, mkexpr( b1 ) ) ) ) ) );
13130e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj         break;
13131e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj      case 0x170: // xvcvsxwsp (VSX Vector Convert Signed Integer Word to Single-Precision format)
13132b173774421d015736c2316b5e6e998e7de545a5cflorian         DIP("xvcvsxwsp v%u,v%u\n",  XT, XB);
13133e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj         putVSReg( XT, unop( Iop_I32StoFx4, getVSReg( XB ) ) );
13134e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj         break;
13135e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj      case 0x150: // xvcvuxwsp (VSX Vector Convert Unsigned Integer Word to Single-Precision format)
13136b173774421d015736c2316b5e6e998e7de545a5cflorian         DIP("xvcvuxwsp v%u,v%u\n",  XT, XB);
13137e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj         putVSReg( XT, unop( Iop_I32UtoFx4, getVSReg( XB ) ) );
13138e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj         break;
131394aa412af1d8166cc11f39a6e721df49431d23618sewardj
13140e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj      default:
13141e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj         vex_printf( "dis_vx_conv(ppc)(opc2)\n" );
13142e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj         return False;
1314366d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj   }
1314466d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj   return True;
1314566d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj}
1314666d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj
1314766d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj/*
131484aa412af1d8166cc11f39a6e721df49431d23618sewardj * VSX vector Double Precision Floating Point Arithmetic Instructions
131494aa412af1d8166cc11f39a6e721df49431d23618sewardj */
131504aa412af1d8166cc11f39a6e721df49431d23618sewardjstatic Bool
131514aa412af1d8166cc11f39a6e721df49431d23618sewardjdis_vxv_dp_arith ( UInt theInstr, UInt opc2 )
131524aa412af1d8166cc11f39a6e721df49431d23618sewardj{
131534aa412af1d8166cc11f39a6e721df49431d23618sewardj   /* XX3-Form */
131544aa412af1d8166cc11f39a6e721df49431d23618sewardj   UChar opc1 = ifieldOPC( theInstr );
131554aa412af1d8166cc11f39a6e721df49431d23618sewardj   UChar XT = ifieldRegXT( theInstr );
131564aa412af1d8166cc11f39a6e721df49431d23618sewardj   UChar XA = ifieldRegXA( theInstr );
131574aa412af1d8166cc11f39a6e721df49431d23618sewardj   UChar XB = ifieldRegXB( theInstr );
131584aa412af1d8166cc11f39a6e721df49431d23618sewardj   IRExpr* rm = get_IR_roundingmode();
131594aa412af1d8166cc11f39a6e721df49431d23618sewardj   IRTemp frA = newTemp(Ity_F64);
131604aa412af1d8166cc11f39a6e721df49431d23618sewardj   IRTemp frB = newTemp(Ity_F64);
131614aa412af1d8166cc11f39a6e721df49431d23618sewardj   IRTemp frA2 = newTemp(Ity_F64);
131624aa412af1d8166cc11f39a6e721df49431d23618sewardj   IRTemp frB2 = newTemp(Ity_F64);
131634aa412af1d8166cc11f39a6e721df49431d23618sewardj
131644aa412af1d8166cc11f39a6e721df49431d23618sewardj   if (opc1 != 0x3C) {
131654aa412af1d8166cc11f39a6e721df49431d23618sewardj      vex_printf( "dis_vxv_dp_arith(ppc)(instr)\n" );
131664aa412af1d8166cc11f39a6e721df49431d23618sewardj      return False;
131674aa412af1d8166cc11f39a6e721df49431d23618sewardj   }
131684aa412af1d8166cc11f39a6e721df49431d23618sewardj
131694aa412af1d8166cc11f39a6e721df49431d23618sewardj   assign(frA,  unop(Iop_ReinterpI64asF64, unop(Iop_V128HIto64, getVSReg( XA ))));
131704aa412af1d8166cc11f39a6e721df49431d23618sewardj   assign(frB,  unop(Iop_ReinterpI64asF64, unop(Iop_V128HIto64, getVSReg( XB ))));
131714aa412af1d8166cc11f39a6e721df49431d23618sewardj   assign(frA2, unop(Iop_ReinterpI64asF64, unop(Iop_V128to64, getVSReg( XA ))));
131724aa412af1d8166cc11f39a6e721df49431d23618sewardj   assign(frB2, unop(Iop_ReinterpI64asF64, unop(Iop_V128to64, getVSReg( XB ))));
131734aa412af1d8166cc11f39a6e721df49431d23618sewardj
131744aa412af1d8166cc11f39a6e721df49431d23618sewardj   switch (opc2) {
131754aa412af1d8166cc11f39a6e721df49431d23618sewardj      case 0x1E0: // xvdivdp (VSX Vector Divide Double-Precision)
131764aa412af1d8166cc11f39a6e721df49431d23618sewardj      case 0x1C0: // xvmuldp (VSX Vector Multiply Double-Precision)
131774aa412af1d8166cc11f39a6e721df49431d23618sewardj      case 0x180: // xvadddp (VSX Vector Add Double-Precision)
131784aa412af1d8166cc11f39a6e721df49431d23618sewardj      case 0x1A0: // xvsubdp (VSX Vector Subtract Double-Precision)
131794aa412af1d8166cc11f39a6e721df49431d23618sewardj      {
131804aa412af1d8166cc11f39a6e721df49431d23618sewardj         IROp mOp;
1318155085f8680acc89d727e321f3b34cae1a8c4093aflorian         const HChar * oper_name;
131824aa412af1d8166cc11f39a6e721df49431d23618sewardj         switch (opc2) {
131834aa412af1d8166cc11f39a6e721df49431d23618sewardj            case 0x1E0:
131844aa412af1d8166cc11f39a6e721df49431d23618sewardj               mOp = Iop_DivF64;
131854aa412af1d8166cc11f39a6e721df49431d23618sewardj               oper_name = "div";
131864aa412af1d8166cc11f39a6e721df49431d23618sewardj               break;
131874aa412af1d8166cc11f39a6e721df49431d23618sewardj            case 0x1C0:
131884aa412af1d8166cc11f39a6e721df49431d23618sewardj               mOp = Iop_MulF64;
131894aa412af1d8166cc11f39a6e721df49431d23618sewardj               oper_name = "mul";
131904aa412af1d8166cc11f39a6e721df49431d23618sewardj               break;
131914aa412af1d8166cc11f39a6e721df49431d23618sewardj            case 0x180:
131924aa412af1d8166cc11f39a6e721df49431d23618sewardj               mOp = Iop_AddF64;
131934aa412af1d8166cc11f39a6e721df49431d23618sewardj               oper_name = "add";
131944aa412af1d8166cc11f39a6e721df49431d23618sewardj               break;
131954aa412af1d8166cc11f39a6e721df49431d23618sewardj            case 0x1A0:
131964aa412af1d8166cc11f39a6e721df49431d23618sewardj               mOp = Iop_SubF64;
131974aa412af1d8166cc11f39a6e721df49431d23618sewardj               oper_name = "sub";
131984aa412af1d8166cc11f39a6e721df49431d23618sewardj               break;
131994aa412af1d8166cc11f39a6e721df49431d23618sewardj
132004aa412af1d8166cc11f39a6e721df49431d23618sewardj            default:
132014aa412af1d8166cc11f39a6e721df49431d23618sewardj               vpanic("The impossible happened: dis_vxv_dp_arith(ppc)");
132024aa412af1d8166cc11f39a6e721df49431d23618sewardj         }
132034aa412af1d8166cc11f39a6e721df49431d23618sewardj         IRTemp hiResult = newTemp(Ity_I64);
132044aa412af1d8166cc11f39a6e721df49431d23618sewardj         IRTemp loResult = newTemp(Ity_I64);
13205b173774421d015736c2316b5e6e998e7de545a5cflorian         DIP("xv%sdp v%d,v%d,v%d\n", oper_name, XT, XA, XB);
132064aa412af1d8166cc11f39a6e721df49431d23618sewardj
132074aa412af1d8166cc11f39a6e721df49431d23618sewardj         assign( hiResult,
132084aa412af1d8166cc11f39a6e721df49431d23618sewardj                 unop( Iop_ReinterpF64asI64,
132094aa412af1d8166cc11f39a6e721df49431d23618sewardj                       triop( mOp, rm, mkexpr( frA ), mkexpr( frB ) ) ) );
132104aa412af1d8166cc11f39a6e721df49431d23618sewardj         assign( loResult,
132114aa412af1d8166cc11f39a6e721df49431d23618sewardj                 unop( Iop_ReinterpF64asI64,
132124aa412af1d8166cc11f39a6e721df49431d23618sewardj                       triop( mOp, rm, mkexpr( frA2 ), mkexpr( frB2 ) ) ) );
132134aa412af1d8166cc11f39a6e721df49431d23618sewardj         putVSReg( XT,
132144aa412af1d8166cc11f39a6e721df49431d23618sewardj                   binop( Iop_64HLtoV128, mkexpr( hiResult ), mkexpr( loResult ) ) );
132154aa412af1d8166cc11f39a6e721df49431d23618sewardj         break;
132164aa412af1d8166cc11f39a6e721df49431d23618sewardj      }
13217e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj      case 0x196: // xvsqrtdp
13218e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj      {
13219e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj         IRTemp hiResult = newTemp(Ity_I64);
13220e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj         IRTemp loResult = newTemp(Ity_I64);
13221b173774421d015736c2316b5e6e998e7de545a5cflorian         DIP("xvsqrtdp v%d,v%d\n", XT, XB);
132224aa412af1d8166cc11f39a6e721df49431d23618sewardj
13223e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj         assign( hiResult,
13224e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj                 unop( Iop_ReinterpF64asI64,
13225e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj                       binop( Iop_SqrtF64, rm, mkexpr( frB ) ) ) );
13226e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj         assign( loResult,
13227e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj                 unop( Iop_ReinterpF64asI64,
13228e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj                       binop( Iop_SqrtF64, rm, mkexpr( frB2 ) ) ) );
13229e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj         putVSReg( XT,
13230e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj                   binop( Iop_64HLtoV128, mkexpr( hiResult ), mkexpr( loResult ) ) );
13231e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj         break;
13232e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj      }
132334aa412af1d8166cc11f39a6e721df49431d23618sewardj      case 0x184: case 0x1A4: // xvmaddadp, xvmaddmdp (VSX Vector Multiply-Add Double-Precision)
132344aa412af1d8166cc11f39a6e721df49431d23618sewardj      case 0x1C4: case 0x1E4: // xvmsubadp, xvmsubmdp (VSX Vector Multiply-Subtract Double-Precision)
132354aa412af1d8166cc11f39a6e721df49431d23618sewardj      case 0x384: case 0x3A4: // xvnmaddadp, xvnmaddmdp (VSX Vector Negate Multiply-Add Double-Precision)
132364aa412af1d8166cc11f39a6e721df49431d23618sewardj      case 0x3C4: case 0x3E4: // xvnmsubadp, xvnmsubmdp (VSX Vector Negate Multiply-Subtract Double-Precision)
132374aa412af1d8166cc11f39a6e721df49431d23618sewardj      {
132384aa412af1d8166cc11f39a6e721df49431d23618sewardj         /* xvm{add|sub}mdp XT,XA,XB is element-wise equivalent to fm{add|sub} FRT,FRA,FRC,FRB with . . .
132394aa412af1d8166cc11f39a6e721df49431d23618sewardj          *    XT == FRC
132404aa412af1d8166cc11f39a6e721df49431d23618sewardj          *    XA == FRA
132414aa412af1d8166cc11f39a6e721df49431d23618sewardj          *    XB == FRB
132424aa412af1d8166cc11f39a6e721df49431d23618sewardj          *
132434aa412af1d8166cc11f39a6e721df49431d23618sewardj          * and for xvm{add|sub}adp . . .
132444aa412af1d8166cc11f39a6e721df49431d23618sewardj          *    XT == FRB
132454aa412af1d8166cc11f39a6e721df49431d23618sewardj          *    XA == FRA
132464aa412af1d8166cc11f39a6e721df49431d23618sewardj          *    XB == FRC
132474aa412af1d8166cc11f39a6e721df49431d23618sewardj          */
132484aa412af1d8166cc11f39a6e721df49431d23618sewardj         Bool negate;
132494aa412af1d8166cc11f39a6e721df49431d23618sewardj         IROp mOp = Iop_INVALID;
1325055085f8680acc89d727e321f3b34cae1a8c4093aflorian         const HChar * oper_name = NULL;
132514aa412af1d8166cc11f39a6e721df49431d23618sewardj         Bool mdp = False;
132524aa412af1d8166cc11f39a6e721df49431d23618sewardj
132534aa412af1d8166cc11f39a6e721df49431d23618sewardj         switch (opc2) {
132544aa412af1d8166cc11f39a6e721df49431d23618sewardj            case 0x184: case 0x1A4:
132554aa412af1d8166cc11f39a6e721df49431d23618sewardj            case 0x384: case 0x3A4:
132564aa412af1d8166cc11f39a6e721df49431d23618sewardj               mOp = Iop_MAddF64;
132574aa412af1d8166cc11f39a6e721df49431d23618sewardj               oper_name = "add";
132584aa412af1d8166cc11f39a6e721df49431d23618sewardj               mdp = (opc2 & 0x0FF) == 0x0A4;
132594aa412af1d8166cc11f39a6e721df49431d23618sewardj               break;
132604aa412af1d8166cc11f39a6e721df49431d23618sewardj
132614aa412af1d8166cc11f39a6e721df49431d23618sewardj            case 0x1C4: case 0x1E4:
132624aa412af1d8166cc11f39a6e721df49431d23618sewardj            case 0x3C4: case 0x3E4:
132634aa412af1d8166cc11f39a6e721df49431d23618sewardj               mOp = Iop_MSubF64;
132644aa412af1d8166cc11f39a6e721df49431d23618sewardj               oper_name = "sub";
132654aa412af1d8166cc11f39a6e721df49431d23618sewardj               mdp = (opc2 & 0x0FF) == 0x0E4;
132664aa412af1d8166cc11f39a6e721df49431d23618sewardj               break;
132674aa412af1d8166cc11f39a6e721df49431d23618sewardj
132684aa412af1d8166cc11f39a6e721df49431d23618sewardj            default:
132694aa412af1d8166cc11f39a6e721df49431d23618sewardj               vpanic("The impossible happened: dis_vxv_sp_arith(ppc)");
132704aa412af1d8166cc11f39a6e721df49431d23618sewardj         }
132714aa412af1d8166cc11f39a6e721df49431d23618sewardj
132724aa412af1d8166cc11f39a6e721df49431d23618sewardj         switch (opc2) {
132734aa412af1d8166cc11f39a6e721df49431d23618sewardj            case 0x384: case 0x3A4:
132744aa412af1d8166cc11f39a6e721df49431d23618sewardj            case 0x3C4: case 0x3E4:
132754aa412af1d8166cc11f39a6e721df49431d23618sewardj               negate = True;
132764aa412af1d8166cc11f39a6e721df49431d23618sewardj               break;
132774aa412af1d8166cc11f39a6e721df49431d23618sewardj            default:
132784aa412af1d8166cc11f39a6e721df49431d23618sewardj               negate = False;
132794aa412af1d8166cc11f39a6e721df49431d23618sewardj         }
132804aa412af1d8166cc11f39a6e721df49431d23618sewardj         IRTemp hiResult = newTemp(Ity_I64);
132814aa412af1d8166cc11f39a6e721df49431d23618sewardj         IRTemp loResult = newTemp(Ity_I64);
132824aa412af1d8166cc11f39a6e721df49431d23618sewardj         IRTemp frT = newTemp(Ity_F64);
132834aa412af1d8166cc11f39a6e721df49431d23618sewardj         IRTemp frT2 = newTemp(Ity_F64);
132844aa412af1d8166cc11f39a6e721df49431d23618sewardj         DIP("xv%sm%s%s v%d,v%d,v%d\n", negate ? "n" : "", oper_name, mdp ? "mdp" : "adp",
13285b173774421d015736c2316b5e6e998e7de545a5cflorian             XT, XA, XB);
132864aa412af1d8166cc11f39a6e721df49431d23618sewardj         assign(frT,  unop(Iop_ReinterpI64asF64, unop(Iop_V128HIto64, getVSReg( XT ) ) ) );
132874aa412af1d8166cc11f39a6e721df49431d23618sewardj         assign(frT2, unop(Iop_ReinterpI64asF64, unop(Iop_V128to64, getVSReg( XT ) ) ) );
132884aa412af1d8166cc11f39a6e721df49431d23618sewardj
132894aa412af1d8166cc11f39a6e721df49431d23618sewardj         assign( hiResult,
132904aa412af1d8166cc11f39a6e721df49431d23618sewardj                 unop( Iop_ReinterpF64asI64,
132914aa412af1d8166cc11f39a6e721df49431d23618sewardj                       qop( mOp,
132924aa412af1d8166cc11f39a6e721df49431d23618sewardj                            rm,
132934aa412af1d8166cc11f39a6e721df49431d23618sewardj                            mkexpr( frA ),
132944aa412af1d8166cc11f39a6e721df49431d23618sewardj                            mkexpr( mdp ? frT : frB ),
132954aa412af1d8166cc11f39a6e721df49431d23618sewardj                            mkexpr( mdp ? frB : frT ) ) ) );
132964aa412af1d8166cc11f39a6e721df49431d23618sewardj         assign( loResult,
132974aa412af1d8166cc11f39a6e721df49431d23618sewardj                 unop( Iop_ReinterpF64asI64,
132984aa412af1d8166cc11f39a6e721df49431d23618sewardj                       qop( mOp,
132994aa412af1d8166cc11f39a6e721df49431d23618sewardj                            rm,
133004aa412af1d8166cc11f39a6e721df49431d23618sewardj                            mkexpr( frA2 ),
133014aa412af1d8166cc11f39a6e721df49431d23618sewardj                            mkexpr( mdp ? frT2 : frB2 ),
133024aa412af1d8166cc11f39a6e721df49431d23618sewardj                            mkexpr( mdp ? frB2 : frT2 ) ) ) );
133034aa412af1d8166cc11f39a6e721df49431d23618sewardj         putVSReg( XT,
133044aa412af1d8166cc11f39a6e721df49431d23618sewardj                   binop( Iop_64HLtoV128,
133054aa412af1d8166cc11f39a6e721df49431d23618sewardj                          mkexpr( negate ? getNegatedResult( hiResult )
133064aa412af1d8166cc11f39a6e721df49431d23618sewardj                                         : hiResult ),
133074aa412af1d8166cc11f39a6e721df49431d23618sewardj                          mkexpr( negate ? getNegatedResult( loResult )
133084aa412af1d8166cc11f39a6e721df49431d23618sewardj                                         : loResult ) ) );
133094aa412af1d8166cc11f39a6e721df49431d23618sewardj         break;
133104aa412af1d8166cc11f39a6e721df49431d23618sewardj      }
13311e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj      case 0x1D4: // xvtsqrtdp (VSX Vector Test for software Square Root Double-Precision)
13312e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj      {
13313e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj         IRTemp frBHi_I64 = newTemp(Ity_I64);
13314e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj         IRTemp frBLo_I64 = newTemp(Ity_I64);
13315e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj         IRTemp flagsHi = newTemp(Ity_I32);
13316e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj         IRTemp flagsLo = newTemp(Ity_I32);
13317e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj         UChar crfD     = toUChar( IFIELD( theInstr, 23, 3 ) );
13318e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj         IRTemp  fe_flagHi, fg_flagHi, fe_flagLo, fg_flagLo;
13319e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj         fe_flagHi = fg_flagHi = fe_flagLo = fg_flagLo = IRTemp_INVALID;
13320e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj
13321b173774421d015736c2316b5e6e998e7de545a5cflorian         DIP("xvtsqrtdp cr%d,v%d\n", crfD, XB);
13322e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj         assign( frBHi_I64, unop(Iop_V128HIto64, getVSReg( XB )) );
13323e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj         assign( frBLo_I64, unop(Iop_V128to64, getVSReg( XB )) );
13324e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj         do_fp_tsqrt(frBHi_I64, False /*not single precision*/, &fe_flagHi, &fg_flagHi);
13325e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj         do_fp_tsqrt(frBLo_I64, False /*not single precision*/, &fe_flagLo, &fg_flagLo);
13326e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj         /* The CR field consists of fl_flag || fg_flag || fe_flag || 0b0
13327e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj          * where fl_flag == 1 on ppc64.
13328e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj          */
13329e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj         assign( flagsHi,
13330e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj                 binop( Iop_Or32,
13331e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj                        binop( Iop_Or32, mkU32( 8 ), // fl_flag
13332e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj                               binop( Iop_Shl32, mkexpr(fg_flagHi), mkU8( 2 ) ) ),
13333e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj                        binop( Iop_Shl32, mkexpr(fe_flagHi), mkU8( 1 ) ) ) );
13334e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj         assign( flagsLo,
13335e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj                 binop( Iop_Or32,
13336e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj                        binop( Iop_Or32, mkU32( 8 ), // fl_flag
13337e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj                               binop( Iop_Shl32, mkexpr(fg_flagLo), mkU8( 2 ) ) ),
13338e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj                        binop( Iop_Shl32, mkexpr(fe_flagLo), mkU8( 1 ) ) ) );
13339e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj         putGST_field( PPC_GST_CR,
13340e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj                       binop( Iop_Or32, mkexpr( flagsHi ), mkexpr( flagsLo ) ),
13341e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj                       crfD );
13342e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj         break;
13343e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj      }
13344e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj      case 0x1F4: // xvtdivdp (VSX Vector Test for software Divide Double-Precision)
13345e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj      {
13346e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj         IRTemp frBHi_I64 = newTemp(Ity_I64);
13347e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj         IRTemp frBLo_I64 = newTemp(Ity_I64);
13348e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj         IRTemp frAHi_I64 = newTemp(Ity_I64);
13349e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj         IRTemp frALo_I64 = newTemp(Ity_I64);
13350e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj         IRTemp flagsHi = newTemp(Ity_I32);
13351e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj         IRTemp flagsLo = newTemp(Ity_I32);
13352e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj         UChar crfD     = toUChar( IFIELD( theInstr, 23, 3 ) );
13353e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj         IRTemp  fe_flagHi, fg_flagHi, fe_flagLo, fg_flagLo;
13354e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj         fe_flagHi = fg_flagHi = fe_flagLo = fg_flagLo = IRTemp_INVALID;
13355e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj
13356b173774421d015736c2316b5e6e998e7de545a5cflorian         DIP("xvtdivdp cr%d,v%d,v%d\n", crfD, XA, XB);
13357e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj         assign( frAHi_I64, unop(Iop_V128HIto64, getVSReg( XA )) );
13358e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj         assign( frALo_I64, unop(Iop_V128to64, getVSReg( XA )) );
13359e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj         assign( frBHi_I64, unop(Iop_V128HIto64, getVSReg( XB )) );
13360e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj         assign( frBLo_I64, unop(Iop_V128to64, getVSReg( XB )) );
13361e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj
13362e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj         _do_fp_tdiv(frAHi_I64, frBHi_I64, False/*dp*/, &fe_flagHi, &fg_flagHi);
13363e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj         _do_fp_tdiv(frALo_I64, frBLo_I64, False/*dp*/, &fe_flagLo, &fg_flagLo);
13364e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj         /* The CR field consists of fl_flag || fg_flag || fe_flag || 0b0
13365e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj          * where fl_flag == 1 on ppc64.
13366e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj          */
13367e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj         assign( flagsHi,
13368e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj                 binop( Iop_Or32,
13369e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj                        binop( Iop_Or32, mkU32( 8 ), // fl_flag
13370e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj                               binop( Iop_Shl32, mkexpr(fg_flagHi), mkU8( 2 ) ) ),
13371e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj                        binop( Iop_Shl32, mkexpr(fe_flagHi), mkU8( 1 ) ) ) );
13372e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj         assign( flagsLo,
13373e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj                 binop( Iop_Or32,
13374e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj                        binop( Iop_Or32, mkU32( 8 ), // fl_flag
13375e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj                               binop( Iop_Shl32, mkexpr(fg_flagLo), mkU8( 2 ) ) ),
13376e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj                        binop( Iop_Shl32, mkexpr(fe_flagLo), mkU8( 1 ) ) ) );
13377e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj         putGST_field( PPC_GST_CR,
13378e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj                       binop( Iop_Or32, mkexpr( flagsHi ), mkexpr( flagsLo ) ),
13379e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj                       crfD );
13380e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj         break;
13381e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj      }
133824aa412af1d8166cc11f39a6e721df49431d23618sewardj
133834aa412af1d8166cc11f39a6e721df49431d23618sewardj      default:
133844aa412af1d8166cc11f39a6e721df49431d23618sewardj         vex_printf( "dis_vxv_dp_arith(ppc)(opc2)\n" );
133854aa412af1d8166cc11f39a6e721df49431d23618sewardj         return False;
133864aa412af1d8166cc11f39a6e721df49431d23618sewardj   }
133874aa412af1d8166cc11f39a6e721df49431d23618sewardj   return True;
133884aa412af1d8166cc11f39a6e721df49431d23618sewardj}
133894aa412af1d8166cc11f39a6e721df49431d23618sewardj
133904aa412af1d8166cc11f39a6e721df49431d23618sewardj/*
133914aa412af1d8166cc11f39a6e721df49431d23618sewardj * VSX vector Single Precision Floating Point Arithmetic Instructions
133924aa412af1d8166cc11f39a6e721df49431d23618sewardj */
133934aa412af1d8166cc11f39a6e721df49431d23618sewardjstatic Bool
133944aa412af1d8166cc11f39a6e721df49431d23618sewardjdis_vxv_sp_arith ( UInt theInstr, UInt opc2 )
133954aa412af1d8166cc11f39a6e721df49431d23618sewardj{
133964aa412af1d8166cc11f39a6e721df49431d23618sewardj   /* XX3-Form */
133974aa412af1d8166cc11f39a6e721df49431d23618sewardj   UChar opc1 = ifieldOPC( theInstr );
133984aa412af1d8166cc11f39a6e721df49431d23618sewardj   UChar XT = ifieldRegXT( theInstr );
133994aa412af1d8166cc11f39a6e721df49431d23618sewardj   UChar XA = ifieldRegXA( theInstr );
134004aa412af1d8166cc11f39a6e721df49431d23618sewardj   UChar XB = ifieldRegXB( theInstr );
134014aa412af1d8166cc11f39a6e721df49431d23618sewardj   IRExpr* rm = get_IR_roundingmode();
134024aa412af1d8166cc11f39a6e721df49431d23618sewardj   IRTemp a3, a2, a1, a0;
134034aa412af1d8166cc11f39a6e721df49431d23618sewardj   IRTemp b3, b2, b1, b0;
134044aa412af1d8166cc11f39a6e721df49431d23618sewardj   IRTemp res0 = newTemp(Ity_I32);
134054aa412af1d8166cc11f39a6e721df49431d23618sewardj   IRTemp res1 = newTemp(Ity_I32);
134064aa412af1d8166cc11f39a6e721df49431d23618sewardj   IRTemp res2 = newTemp(Ity_I32);
134074aa412af1d8166cc11f39a6e721df49431d23618sewardj   IRTemp res3 = newTemp(Ity_I32);
134084aa412af1d8166cc11f39a6e721df49431d23618sewardj
134094aa412af1d8166cc11f39a6e721df49431d23618sewardj   a3 = a2 = a1 = a0 = IRTemp_INVALID;
134104aa412af1d8166cc11f39a6e721df49431d23618sewardj   b3 = b2 = b1 = b0 = IRTemp_INVALID;
134114aa412af1d8166cc11f39a6e721df49431d23618sewardj
134124aa412af1d8166cc11f39a6e721df49431d23618sewardj   if (opc1 != 0x3C) {
134134aa412af1d8166cc11f39a6e721df49431d23618sewardj      vex_printf( "dis_vxv_sp_arith(ppc)(instr)\n" );
134144aa412af1d8166cc11f39a6e721df49431d23618sewardj      return False;
134154aa412af1d8166cc11f39a6e721df49431d23618sewardj   }
134164aa412af1d8166cc11f39a6e721df49431d23618sewardj
134174aa412af1d8166cc11f39a6e721df49431d23618sewardj   switch (opc2) {
134184aa412af1d8166cc11f39a6e721df49431d23618sewardj      case 0x100: // xvaddsp (VSX Vector Add Single-Precision)
13419b173774421d015736c2316b5e6e998e7de545a5cflorian         DIP("xvaddsp v%d,v%d,v%d\n", XT, XA, XB);
1342020a760ec66a13a93147a40d3c3530be21d7fe411sewardj         // WARNING: BOGUS! The backend ignores rm on Iop_Add32Fx4
1342120a760ec66a13a93147a40d3c3530be21d7fe411sewardj         putVSReg( XT, triop(Iop_Add32Fx4, rm,
1342220a760ec66a13a93147a40d3c3530be21d7fe411sewardj                             getVSReg( XA ), getVSReg( XB )) );
134234aa412af1d8166cc11f39a6e721df49431d23618sewardj         break;
134244aa412af1d8166cc11f39a6e721df49431d23618sewardj
134254aa412af1d8166cc11f39a6e721df49431d23618sewardj      case 0x140: // xvmulsp (VSX Vector Multiply Single-Precision)
13426b173774421d015736c2316b5e6e998e7de545a5cflorian         DIP("xvmulsp v%d,v%d,v%d\n", XT, XA, XB);
1342720a760ec66a13a93147a40d3c3530be21d7fe411sewardj         // WARNING: BOGUS! The backend ignores rm on Iop_Mul32Fx4
1342820a760ec66a13a93147a40d3c3530be21d7fe411sewardj         putVSReg( XT, triop(Iop_Mul32Fx4, rm,
1342920a760ec66a13a93147a40d3c3530be21d7fe411sewardj                             getVSReg( XA ), getVSReg( XB )) );
134304aa412af1d8166cc11f39a6e721df49431d23618sewardj         break;
134314aa412af1d8166cc11f39a6e721df49431d23618sewardj
134324aa412af1d8166cc11f39a6e721df49431d23618sewardj      case 0x120: // xvsubsp (VSX Vector Subtract Single-Precision)
13433b173774421d015736c2316b5e6e998e7de545a5cflorian         DIP("xvsubsp v%d,v%d,v%d\n", XT, XA, XB);
1343420a760ec66a13a93147a40d3c3530be21d7fe411sewardj         // WARNING: BOGUS! The backend ignores rm on Iop_Sub32Fx4
1343520a760ec66a13a93147a40d3c3530be21d7fe411sewardj         putVSReg( XT, triop(Iop_Sub32Fx4, rm,
1343620a760ec66a13a93147a40d3c3530be21d7fe411sewardj                             getVSReg( XA ), getVSReg( XB )) );
134374aa412af1d8166cc11f39a6e721df49431d23618sewardj         break;
134384aa412af1d8166cc11f39a6e721df49431d23618sewardj
134394aa412af1d8166cc11f39a6e721df49431d23618sewardj      case 0x160: // xvdivsp (VSX Vector Divide Single-Precision)
134404aa412af1d8166cc11f39a6e721df49431d23618sewardj      {
134414aa412af1d8166cc11f39a6e721df49431d23618sewardj         /* Iop_Div32Fx4 is not implemented for ppc64 (in host_ppc_{isel|defs}.c.
134424aa412af1d8166cc11f39a6e721df49431d23618sewardj          * So there are two choices:
134434aa412af1d8166cc11f39a6e721df49431d23618sewardj          *   1. Implement the xvdivsp with a native insn; or
134444aa412af1d8166cc11f39a6e721df49431d23618sewardj          *   2. Extract the 4 single precision floats from each vector
134454aa412af1d8166cc11f39a6e721df49431d23618sewardj          *      register inputs and perform fdivs on each pair
134464aa412af1d8166cc11f39a6e721df49431d23618sewardj          * I will do the latter, due to the general philosophy of
134474aa412af1d8166cc11f39a6e721df49431d23618sewardj          * reusing existing implementations when practical.
134484aa412af1d8166cc11f39a6e721df49431d23618sewardj          */
13449b173774421d015736c2316b5e6e998e7de545a5cflorian         DIP("xvdivsp v%d,v%d,v%d\n", XT, XA, XB);
134504aa412af1d8166cc11f39a6e721df49431d23618sewardj         breakV128to4xF64( getVSReg( XA ), &a3, &a2, &a1, &a0 );
134514aa412af1d8166cc11f39a6e721df49431d23618sewardj         breakV128to4xF64( getVSReg( XB ), &b3, &b2, &b1, &b0 );
134524aa412af1d8166cc11f39a6e721df49431d23618sewardj
134534aa412af1d8166cc11f39a6e721df49431d23618sewardj         assign( res0,
134544aa412af1d8166cc11f39a6e721df49431d23618sewardj              unop( Iop_ReinterpF32asI32,
134554aa412af1d8166cc11f39a6e721df49431d23618sewardj                    unop( Iop_TruncF64asF32,
134564aa412af1d8166cc11f39a6e721df49431d23618sewardj                          triop( Iop_DivF64r32, rm, mkexpr( a0 ), mkexpr( b0 ) ) ) ) );
134574aa412af1d8166cc11f39a6e721df49431d23618sewardj         assign( res1,
134584aa412af1d8166cc11f39a6e721df49431d23618sewardj                 unop( Iop_ReinterpF32asI32,
134594aa412af1d8166cc11f39a6e721df49431d23618sewardj                       unop( Iop_TruncF64asF32,
134604aa412af1d8166cc11f39a6e721df49431d23618sewardj                             triop( Iop_DivF64r32, rm, mkexpr( a1 ), mkexpr( b1 ) ) ) ) );
134614aa412af1d8166cc11f39a6e721df49431d23618sewardj         assign( res2,
134624aa412af1d8166cc11f39a6e721df49431d23618sewardj                 unop( Iop_ReinterpF32asI32,
134634aa412af1d8166cc11f39a6e721df49431d23618sewardj                       unop( Iop_TruncF64asF32,
134644aa412af1d8166cc11f39a6e721df49431d23618sewardj                             triop( Iop_DivF64r32, rm, mkexpr( a2 ), mkexpr( b2 ) ) ) ) );
134654aa412af1d8166cc11f39a6e721df49431d23618sewardj         assign( res3,
134664aa412af1d8166cc11f39a6e721df49431d23618sewardj                 unop( Iop_ReinterpF32asI32,
134674aa412af1d8166cc11f39a6e721df49431d23618sewardj                       unop( Iop_TruncF64asF32,
134684aa412af1d8166cc11f39a6e721df49431d23618sewardj                             triop( Iop_DivF64r32, rm, mkexpr( a3 ), mkexpr( b3 ) ) ) ) );
134694aa412af1d8166cc11f39a6e721df49431d23618sewardj
134704aa412af1d8166cc11f39a6e721df49431d23618sewardj         putVSReg( XT,
134714aa412af1d8166cc11f39a6e721df49431d23618sewardj                   binop( Iop_64HLtoV128,
134724aa412af1d8166cc11f39a6e721df49431d23618sewardj                          binop( Iop_32HLto64, mkexpr( res3 ), mkexpr( res2 ) ),
134734aa412af1d8166cc11f39a6e721df49431d23618sewardj                          binop( Iop_32HLto64, mkexpr( res1 ), mkexpr( res0 ) ) ) );
134744aa412af1d8166cc11f39a6e721df49431d23618sewardj         break;
134754aa412af1d8166cc11f39a6e721df49431d23618sewardj      }
13476e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj      case 0x116: // xvsqrtsp (VSX Vector Square Root Single-Precision)
13477e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj      {
13478b173774421d015736c2316b5e6e998e7de545a5cflorian         DIP("xvsqrtsp v%d,v%d\n", XT, XB);
13479e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj         breakV128to4xF64( getVSReg( XB ), &b3, &b2, &b1, &b0 );
13480e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj         /* Note: The native xvsqrtsp insruction does not always give the same precision
13481e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj          * as what we get with Iop_SqrtF64.  But it doesn't seem worthwhile to implement
13482e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj          * an Iop_SqrtF32 that would give us a lower precision result, albeit more true
13483e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj          * to the actual instruction.
13484e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj          */
13485e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj
13486e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj         assign( res0,
13487e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj                 unop( Iop_ReinterpF32asI32,
13488e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj                       unop( Iop_TruncF64asF32,
13489e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj                             binop(Iop_SqrtF64, rm, mkexpr( b0 ) ) ) ) );
13490e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj         assign( res1,
13491e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj                 unop( Iop_ReinterpF32asI32,
13492e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj                       unop( Iop_TruncF64asF32,
13493e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj                             binop(Iop_SqrtF64, rm, mkexpr( b1 ) ) ) ) );
13494e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj         assign( res2,
13495e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj                 unop( Iop_ReinterpF32asI32,
13496e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj                       unop( Iop_TruncF64asF32,
13497e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj                             binop(Iop_SqrtF64, rm, mkexpr( b2) ) ) ) );
13498e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj         assign( res3,
13499e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj                 unop( Iop_ReinterpF32asI32,
13500e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj                       unop( Iop_TruncF64asF32,
13501e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj                             binop(Iop_SqrtF64, rm, mkexpr( b3 ) ) ) ) );
13502e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj
13503e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj         putVSReg( XT,
13504e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj                   binop( Iop_64HLtoV128,
13505e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj                          binop( Iop_32HLto64, mkexpr( res3 ), mkexpr( res2 ) ),
13506e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj                          binop( Iop_32HLto64, mkexpr( res1 ), mkexpr( res0 ) ) ) );
13507e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj         break;
13508e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj      }
135094aa412af1d8166cc11f39a6e721df49431d23618sewardj
135104aa412af1d8166cc11f39a6e721df49431d23618sewardj      case 0x104: case 0x124: // xvmaddasp, xvmaddmsp (VSX Vector Multiply-Add Single-Precision)
135114aa412af1d8166cc11f39a6e721df49431d23618sewardj      case 0x144: case 0x164: // xvmsubasp, xvmsubmsp (VSX Vector Multiply-Subtract Single-Precision)
135124aa412af1d8166cc11f39a6e721df49431d23618sewardj      case 0x304: case 0x324: // xvnmaddasp, xvnmaddmsp (VSX Vector Negate Multiply-Add Single-Precision)
135134aa412af1d8166cc11f39a6e721df49431d23618sewardj      case 0x344: case 0x364: // xvnmsubasp, xvnmsubmsp (VSX Vector Negate Multiply-Subtract Single-Precision)
135144aa412af1d8166cc11f39a6e721df49431d23618sewardj      {
135154aa412af1d8166cc11f39a6e721df49431d23618sewardj         IRTemp t3, t2, t1, t0;
135164aa412af1d8166cc11f39a6e721df49431d23618sewardj         Bool msp = False;
135174aa412af1d8166cc11f39a6e721df49431d23618sewardj         Bool negate;
1351855085f8680acc89d727e321f3b34cae1a8c4093aflorian         const HChar * oper_name = NULL;
135194aa412af1d8166cc11f39a6e721df49431d23618sewardj         IROp mOp = Iop_INVALID;
135204aa412af1d8166cc11f39a6e721df49431d23618sewardj         switch (opc2) {
135214aa412af1d8166cc11f39a6e721df49431d23618sewardj            case 0x104: case 0x124:
135224aa412af1d8166cc11f39a6e721df49431d23618sewardj            case 0x304: case 0x324:
135234aa412af1d8166cc11f39a6e721df49431d23618sewardj               msp = (opc2 & 0x0FF) == 0x024;
135244aa412af1d8166cc11f39a6e721df49431d23618sewardj               mOp = Iop_MAddF64r32;
135254aa412af1d8166cc11f39a6e721df49431d23618sewardj               oper_name = "madd";
135264aa412af1d8166cc11f39a6e721df49431d23618sewardj               break;
135274aa412af1d8166cc11f39a6e721df49431d23618sewardj
135284aa412af1d8166cc11f39a6e721df49431d23618sewardj            case 0x144: case 0x164:
135294aa412af1d8166cc11f39a6e721df49431d23618sewardj            case 0x344: case 0x364:
135304aa412af1d8166cc11f39a6e721df49431d23618sewardj               msp = (opc2 & 0x0FF) == 0x064;
135314aa412af1d8166cc11f39a6e721df49431d23618sewardj               mOp = Iop_MSubF64r32;
135324aa412af1d8166cc11f39a6e721df49431d23618sewardj               oper_name = "sub";
135334aa412af1d8166cc11f39a6e721df49431d23618sewardj               break;
135344aa412af1d8166cc11f39a6e721df49431d23618sewardj
135354aa412af1d8166cc11f39a6e721df49431d23618sewardj            default:
135364aa412af1d8166cc11f39a6e721df49431d23618sewardj               vpanic("The impossible happened: dis_vxv_sp_arith(ppc)");
135374aa412af1d8166cc11f39a6e721df49431d23618sewardj         }
135384aa412af1d8166cc11f39a6e721df49431d23618sewardj
135394aa412af1d8166cc11f39a6e721df49431d23618sewardj         switch (opc2) {
135404aa412af1d8166cc11f39a6e721df49431d23618sewardj            case 0x304: case 0x324:
135414aa412af1d8166cc11f39a6e721df49431d23618sewardj            case 0x344: case 0x364:
135424aa412af1d8166cc11f39a6e721df49431d23618sewardj               negate = True;
135434aa412af1d8166cc11f39a6e721df49431d23618sewardj               break;
135444aa412af1d8166cc11f39a6e721df49431d23618sewardj
135454aa412af1d8166cc11f39a6e721df49431d23618sewardj            default:
135464aa412af1d8166cc11f39a6e721df49431d23618sewardj               negate = False;
135474aa412af1d8166cc11f39a6e721df49431d23618sewardj         }
135484aa412af1d8166cc11f39a6e721df49431d23618sewardj
13549b173774421d015736c2316b5e6e998e7de545a5cflorian         DIP("xv%sm%s%s v%d,v%d,v%d\n", negate ? "n" : "", oper_name,
13550b173774421d015736c2316b5e6e998e7de545a5cflorian             msp ? "msp" : "asp", XT, XA, XB);
135514aa412af1d8166cc11f39a6e721df49431d23618sewardj
135524aa412af1d8166cc11f39a6e721df49431d23618sewardj         t3 = t2 = t1 = t0 = IRTemp_INVALID;
135534aa412af1d8166cc11f39a6e721df49431d23618sewardj         breakV128to4xF64( getVSReg( XA ), &a3, &a2, &a1, &a0 );
135544aa412af1d8166cc11f39a6e721df49431d23618sewardj         breakV128to4xF64( getVSReg( XB ), &b3, &b2, &b1, &b0 );
135554aa412af1d8166cc11f39a6e721df49431d23618sewardj         breakV128to4xF64( getVSReg( XT ), &t3, &t2, &t1, &t0 );
135564aa412af1d8166cc11f39a6e721df49431d23618sewardj
135574aa412af1d8166cc11f39a6e721df49431d23618sewardj         assign( res0,
135584aa412af1d8166cc11f39a6e721df49431d23618sewardj                 unop( Iop_ReinterpF32asI32,
135594aa412af1d8166cc11f39a6e721df49431d23618sewardj                       unop( Iop_TruncF64asF32,
135604aa412af1d8166cc11f39a6e721df49431d23618sewardj                             qop( mOp,
135614aa412af1d8166cc11f39a6e721df49431d23618sewardj                                  rm,
135624aa412af1d8166cc11f39a6e721df49431d23618sewardj                                  mkexpr( a0 ),
135634aa412af1d8166cc11f39a6e721df49431d23618sewardj                                  mkexpr( msp ? t0 : b0 ),
135644aa412af1d8166cc11f39a6e721df49431d23618sewardj                                  mkexpr( msp ? b0 : t0 ) ) ) ) );
135654aa412af1d8166cc11f39a6e721df49431d23618sewardj         assign( res1,
135664aa412af1d8166cc11f39a6e721df49431d23618sewardj                 unop( Iop_ReinterpF32asI32,
135674aa412af1d8166cc11f39a6e721df49431d23618sewardj                       unop( Iop_TruncF64asF32,
135684aa412af1d8166cc11f39a6e721df49431d23618sewardj                             qop( mOp,
135694aa412af1d8166cc11f39a6e721df49431d23618sewardj                                  rm,
135704aa412af1d8166cc11f39a6e721df49431d23618sewardj                                  mkexpr( a1 ),
135714aa412af1d8166cc11f39a6e721df49431d23618sewardj                                  mkexpr( msp ? t1 : b1 ),
135724aa412af1d8166cc11f39a6e721df49431d23618sewardj                                  mkexpr( msp ? b1 : t1 ) ) ) ) );
135734aa412af1d8166cc11f39a6e721df49431d23618sewardj         assign( res2,
135744aa412af1d8166cc11f39a6e721df49431d23618sewardj                 unop( Iop_ReinterpF32asI32,
135754aa412af1d8166cc11f39a6e721df49431d23618sewardj                       unop( Iop_TruncF64asF32,
135764aa412af1d8166cc11f39a6e721df49431d23618sewardj                             qop( mOp,
135774aa412af1d8166cc11f39a6e721df49431d23618sewardj                                  rm,
135784aa412af1d8166cc11f39a6e721df49431d23618sewardj                                  mkexpr( a2 ),
135794aa412af1d8166cc11f39a6e721df49431d23618sewardj                                  mkexpr( msp ? t2 : b2 ),
135804aa412af1d8166cc11f39a6e721df49431d23618sewardj                                  mkexpr( msp ? b2 : t2 ) ) ) ) );
135814aa412af1d8166cc11f39a6e721df49431d23618sewardj         assign( res3,
135824aa412af1d8166cc11f39a6e721df49431d23618sewardj                 unop( Iop_ReinterpF32asI32,
135834aa412af1d8166cc11f39a6e721df49431d23618sewardj                       unop( Iop_TruncF64asF32,
135844aa412af1d8166cc11f39a6e721df49431d23618sewardj                             qop( mOp,
135854aa412af1d8166cc11f39a6e721df49431d23618sewardj                                  rm,
135864aa412af1d8166cc11f39a6e721df49431d23618sewardj                                  mkexpr( a3 ),
135874aa412af1d8166cc11f39a6e721df49431d23618sewardj                                  mkexpr( msp ? t3 : b3 ),
135884aa412af1d8166cc11f39a6e721df49431d23618sewardj                                  mkexpr( msp ? b3 : t3 ) ) ) ) );
135894aa412af1d8166cc11f39a6e721df49431d23618sewardj
135904aa412af1d8166cc11f39a6e721df49431d23618sewardj         putVSReg( XT,
135914aa412af1d8166cc11f39a6e721df49431d23618sewardj                   binop( Iop_64HLtoV128,
135924aa412af1d8166cc11f39a6e721df49431d23618sewardj                          binop( Iop_32HLto64, mkexpr( negate ? getNegatedResult_32( res3 ) : res3 ),
135934aa412af1d8166cc11f39a6e721df49431d23618sewardj                                 mkexpr( negate ? getNegatedResult_32( res2 ) : res2 ) ),
135944aa412af1d8166cc11f39a6e721df49431d23618sewardj                          binop( Iop_32HLto64, mkexpr( negate ? getNegatedResult_32( res1 ) : res1 ),
135954aa412af1d8166cc11f39a6e721df49431d23618sewardj                                 mkexpr( negate ? getNegatedResult_32( res0 ) : res0 ) ) ) );
135964aa412af1d8166cc11f39a6e721df49431d23618sewardj
135974aa412af1d8166cc11f39a6e721df49431d23618sewardj         break;
135984aa412af1d8166cc11f39a6e721df49431d23618sewardj      }
13599e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj      case 0x154: // xvtsqrtsp (VSX Vector Test for software Square Root Single-Precision)
13600e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj      {
13601e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj         IRTemp flags0 = newTemp(Ity_I32);
13602e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj         IRTemp flags1 = newTemp(Ity_I32);
13603e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj         IRTemp flags2 = newTemp(Ity_I32);
13604e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj         IRTemp flags3 = newTemp(Ity_I32);
13605e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj         UChar crfD     = toUChar( IFIELD( theInstr, 23, 3 ) );
13606e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj         IRTemp  fe_flag0, fg_flag0, fe_flag1, fg_flag1;
13607e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj         IRTemp  fe_flag2, fg_flag2, fe_flag3, fg_flag3;
13608e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj         fe_flag0 = fg_flag0 = fe_flag1 = fg_flag1 = IRTemp_INVALID;
13609e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj         fe_flag2 = fg_flag2 = fe_flag3 = fg_flag3 = IRTemp_INVALID;
13610b173774421d015736c2316b5e6e998e7de545a5cflorian         DIP("xvtsqrtsp cr%d,v%d\n", crfD, XB);
13611e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj
13612e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj         breakV128to4x32( getVSReg( XB ), &b3, &b2, &b1, &b0 );
13613e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj         do_fp_tsqrt(b0, True /* single precision*/, &fe_flag0, &fg_flag0);
13614e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj         do_fp_tsqrt(b1, True /* single precision*/, &fe_flag1, &fg_flag1);
13615e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj         do_fp_tsqrt(b2, True /* single precision*/, &fe_flag2, &fg_flag2);
13616e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj         do_fp_tsqrt(b3, True /* single precision*/, &fe_flag3, &fg_flag3);
13617e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj
13618e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj         /* The CR field consists of fl_flag || fg_flag || fe_flag || 0b0
13619e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj          * where fl_flag == 1 on ppc64.
13620e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj          */
13621e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj         assign( flags0,
13622e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj                 binop( Iop_Or32,
13623e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj                        binop( Iop_Or32, mkU32( 8 ), // fl_flag
13624e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj                               binop( Iop_Shl32, mkexpr(fg_flag0), mkU8( 2 ) ) ),
13625e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj                        binop( Iop_Shl32, mkexpr(fe_flag0), mkU8( 1 ) ) ) );
13626e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj         assign( flags1,
13627e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj                 binop( Iop_Or32,
13628e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj                        binop( Iop_Or32, mkU32( 8 ), // fl_flag
13629e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj                               binop( Iop_Shl32, mkexpr(fg_flag1), mkU8( 2 ) ) ),
13630e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj                        binop( Iop_Shl32, mkexpr(fe_flag1), mkU8( 1 ) ) ) );
13631e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj         assign( flags2,
13632e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj                 binop( Iop_Or32,
13633e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj                        binop( Iop_Or32, mkU32( 8 ), // fl_flag
13634e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj                               binop( Iop_Shl32, mkexpr(fg_flag2), mkU8( 2 ) ) ),
13635e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj                        binop( Iop_Shl32, mkexpr(fe_flag2), mkU8( 1 ) ) ) );
13636e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj         assign( flags3,
13637e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj                 binop( Iop_Or32,
13638e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj                        binop( Iop_Or32, mkU32( 8 ), // fl_flag
13639e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj                               binop( Iop_Shl32, mkexpr(fg_flag3), mkU8( 2 ) ) ),
13640e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj                        binop( Iop_Shl32, mkexpr(fe_flag3), mkU8( 1 ) ) ) );
13641e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj         putGST_field( PPC_GST_CR,
13642e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj                       binop( Iop_Or32,
13643e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj                              mkexpr( flags0 ),
13644e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj                              binop( Iop_Or32,
13645e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj                                     mkexpr( flags1 ),
13646e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj                                     binop( Iop_Or32,
13647e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj                                            mkexpr( flags2 ),
13648e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj                                            mkexpr( flags3 ) ) ) ),
13649e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj                       crfD );
13650e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj
13651e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj         break;
13652e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj      }
13653e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj      case 0x174: // xvtdivsp (VSX Vector Test for software Divide Single-Precision)
13654e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj      {
13655e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj         IRTemp flags0 = newTemp(Ity_I32);
13656e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj         IRTemp flags1 = newTemp(Ity_I32);
13657e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj         IRTemp flags2 = newTemp(Ity_I32);
13658e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj         IRTemp flags3 = newTemp(Ity_I32);
13659e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj         UChar crfD     = toUChar( IFIELD( theInstr, 23, 3 ) );
13660e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj         IRTemp  fe_flag0, fg_flag0, fe_flag1, fg_flag1;
13661e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj         IRTemp  fe_flag2, fg_flag2, fe_flag3, fg_flag3;
13662e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj         fe_flag0 = fg_flag0 = fe_flag1 = fg_flag1 = IRTemp_INVALID;
13663e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj         fe_flag2 = fg_flag2 = fe_flag3 = fg_flag3 = IRTemp_INVALID;
13664b173774421d015736c2316b5e6e998e7de545a5cflorian         DIP("xvtdivsp cr%d,v%d,v%d\n", crfD, XA, XB);
13665e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj
13666e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj         breakV128to4x32( getVSReg( XA ), &a3, &a2, &a1, &a0 );
13667e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj         breakV128to4x32( getVSReg( XB ), &b3, &b2, &b1, &b0 );
13668e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj         _do_fp_tdiv(a0, b0, True /* single precision*/, &fe_flag0, &fg_flag0);
13669e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj         _do_fp_tdiv(a1, b1, True /* single precision*/, &fe_flag1, &fg_flag1);
13670e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj         _do_fp_tdiv(a2, b2, True /* single precision*/, &fe_flag2, &fg_flag2);
13671e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj         _do_fp_tdiv(a3, b3, True /* single precision*/, &fe_flag3, &fg_flag3);
13672e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj
13673e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj         /* The CR field consists of fl_flag || fg_flag || fe_flag || 0b0
13674e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj          * where fl_flag == 1 on ppc64.
13675e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj          */
13676e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj         assign( flags0,
13677e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj                 binop( Iop_Or32,
13678e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj                        binop( Iop_Or32, mkU32( 8 ), // fl_flag
13679e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj                               binop( Iop_Shl32, mkexpr(fg_flag0), mkU8( 2 ) ) ),
13680e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj                        binop( Iop_Shl32, mkexpr(fe_flag0), mkU8( 1 ) ) ) );
13681e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj         assign( flags1,
13682e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj                 binop( Iop_Or32,
13683e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj                        binop( Iop_Or32, mkU32( 8 ), // fl_flag
13684e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj                               binop( Iop_Shl32, mkexpr(fg_flag1), mkU8( 2 ) ) ),
13685e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj                        binop( Iop_Shl32, mkexpr(fe_flag1), mkU8( 1 ) ) ) );
13686e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj         assign( flags2,
13687e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj                 binop( Iop_Or32,
13688e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj                        binop( Iop_Or32, mkU32( 8 ), // fl_flag
13689e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj                               binop( Iop_Shl32, mkexpr(fg_flag2), mkU8( 2 ) ) ),
13690e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj                        binop( Iop_Shl32, mkexpr(fe_flag2), mkU8( 1 ) ) ) );
13691e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj         assign( flags3,
13692e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj                 binop( Iop_Or32,
13693e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj                        binop( Iop_Or32, mkU32( 8 ), // fl_flag
13694e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj                               binop( Iop_Shl32, mkexpr(fg_flag3), mkU8( 2 ) ) ),
13695e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj                        binop( Iop_Shl32, mkexpr(fe_flag3), mkU8( 1 ) ) ) );
13696e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj         putGST_field( PPC_GST_CR,
13697e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj                       binop( Iop_Or32,
13698e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj                              mkexpr( flags0 ),
13699e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj                              binop( Iop_Or32,
13700e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj                                     mkexpr( flags1 ),
13701e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj                                     binop( Iop_Or32,
13702e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj                                            mkexpr( flags2 ),
13703e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj                                            mkexpr( flags3 ) ) ) ),
13704e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj                       crfD );
13705e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj
13706e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj         break;
13707e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj      }
137084aa412af1d8166cc11f39a6e721df49431d23618sewardj
137094aa412af1d8166cc11f39a6e721df49431d23618sewardj      default:
137104aa412af1d8166cc11f39a6e721df49431d23618sewardj         vex_printf( "dis_vxv_sp_arith(ppc)(opc2)\n" );
137114aa412af1d8166cc11f39a6e721df49431d23618sewardj         return False;
137124aa412af1d8166cc11f39a6e721df49431d23618sewardj   }
137134aa412af1d8166cc11f39a6e721df49431d23618sewardj   return True;
137144aa412af1d8166cc11f39a6e721df49431d23618sewardj}
137154aa412af1d8166cc11f39a6e721df49431d23618sewardj
137167deaf9552b546b847528cf39b38898fb7742b5f5carll/*
1371760c6bac19ffe055cabab554e7877d73096a8bf17carll * Vector Population Count/bit matrix transpose
137187deaf9552b546b847528cf39b38898fb7742b5f5carll */
137197deaf9552b546b847528cf39b38898fb7742b5f5carllstatic Bool
1372060c6bac19ffe055cabab554e7877d73096a8bf17carlldis_av_count_bitTranspose ( UInt theInstr, UInt opc2 )
137217deaf9552b546b847528cf39b38898fb7742b5f5carll{
137227deaf9552b546b847528cf39b38898fb7742b5f5carll   UChar vRB_addr = ifieldRegB(theInstr);
137237deaf9552b546b847528cf39b38898fb7742b5f5carll   UChar vRT_addr = ifieldRegDS(theInstr);
137247deaf9552b546b847528cf39b38898fb7742b5f5carll   UChar opc1 = ifieldOPC( theInstr );
137257deaf9552b546b847528cf39b38898fb7742b5f5carll   IRTemp vB = newTemp(Ity_V128);
137267deaf9552b546b847528cf39b38898fb7742b5f5carll   assign( vB, getVReg(vRB_addr));
137277deaf9552b546b847528cf39b38898fb7742b5f5carll
137287deaf9552b546b847528cf39b38898fb7742b5f5carll   if (opc1 != 0x4) {
1372960c6bac19ffe055cabab554e7877d73096a8bf17carll      vex_printf( "dis_av_count_bitTranspose(ppc)(instr)\n" );
137307deaf9552b546b847528cf39b38898fb7742b5f5carll      return False;
137317deaf9552b546b847528cf39b38898fb7742b5f5carll   }
137327deaf9552b546b847528cf39b38898fb7742b5f5carll
137337deaf9552b546b847528cf39b38898fb7742b5f5carll   switch (opc2) {
137347deaf9552b546b847528cf39b38898fb7742b5f5carll      case 0x702:    // vclzb
137357deaf9552b546b847528cf39b38898fb7742b5f5carll         DIP("vclzb v%d,v%d\n", vRT_addr, vRB_addr);
13736a8c7b0f2ac208ed08763d0873131962a65669d58sewardj         putVReg( vRT_addr, unop(Iop_Clz8x16, mkexpr( vB ) ) );
137377deaf9552b546b847528cf39b38898fb7742b5f5carll         break;
137387deaf9552b546b847528cf39b38898fb7742b5f5carll
137397deaf9552b546b847528cf39b38898fb7742b5f5carll      case 0x742:    // vclzh
137407deaf9552b546b847528cf39b38898fb7742b5f5carll         DIP("vclzh v%d,v%d\n", vRT_addr, vRB_addr);
13741a8c7b0f2ac208ed08763d0873131962a65669d58sewardj         putVReg( vRT_addr, unop(Iop_Clz16x8, mkexpr( vB ) ) );
137427deaf9552b546b847528cf39b38898fb7742b5f5carll         break;
137437deaf9552b546b847528cf39b38898fb7742b5f5carll
137447deaf9552b546b847528cf39b38898fb7742b5f5carll      case 0x782:    // vclzw
137457deaf9552b546b847528cf39b38898fb7742b5f5carll         DIP("vclzw v%d,v%d\n", vRT_addr, vRB_addr);
13746a8c7b0f2ac208ed08763d0873131962a65669d58sewardj         putVReg( vRT_addr, unop(Iop_Clz32x4, mkexpr( vB ) ) );
137477deaf9552b546b847528cf39b38898fb7742b5f5carll         break;
137487deaf9552b546b847528cf39b38898fb7742b5f5carll
137497deaf9552b546b847528cf39b38898fb7742b5f5carll      case 0x7C2:    // vclzd
137507deaf9552b546b847528cf39b38898fb7742b5f5carll         DIP("vclzd v%d,v%d\n", vRT_addr, vRB_addr);
137517deaf9552b546b847528cf39b38898fb7742b5f5carll         putVReg( vRT_addr, unop(Iop_Clz64x2, mkexpr( vB ) ) );
137527deaf9552b546b847528cf39b38898fb7742b5f5carll         break;
137537deaf9552b546b847528cf39b38898fb7742b5f5carll
137547deaf9552b546b847528cf39b38898fb7742b5f5carll      case 0x703:    // vpopcntb
137557deaf9552b546b847528cf39b38898fb7742b5f5carll      {
137567deaf9552b546b847528cf39b38898fb7742b5f5carll         /* Break vector into 32-bit words and do the population count
137577deaf9552b546b847528cf39b38898fb7742b5f5carll          * on byte in the words
137587deaf9552b546b847528cf39b38898fb7742b5f5carll          */
137597deaf9552b546b847528cf39b38898fb7742b5f5carll         IRType ty = Ity_I32;
137607deaf9552b546b847528cf39b38898fb7742b5f5carll         IRTemp bits0_31, bits32_63, bits64_95, bits96_127;
137617deaf9552b546b847528cf39b38898fb7742b5f5carll         bits0_31 = bits32_63 = bits64_95 = bits96_127 = IRTemp_INVALID;
137627deaf9552b546b847528cf39b38898fb7742b5f5carll         IRTemp cnt_bits0_31, cnt_bits32_63, cnt_bits64_95, cnt_bits96_127;
137637deaf9552b546b847528cf39b38898fb7742b5f5carll         cnt_bits0_31 = cnt_bits32_63 = cnt_bits64_95 = cnt_bits96_127 = IRTemp_INVALID;
137647deaf9552b546b847528cf39b38898fb7742b5f5carll
137657deaf9552b546b847528cf39b38898fb7742b5f5carll         DIP("vpopcntb v%d,v%d\n", vRT_addr, vRB_addr);
137667deaf9552b546b847528cf39b38898fb7742b5f5carll         breakV128to4x32(mkexpr( vB), &bits96_127, &bits64_95, &bits32_63, &bits0_31 );
137677deaf9552b546b847528cf39b38898fb7742b5f5carll         cnt_bits0_31   = gen_POPCOUNT(ty, bits0_31,   BYTE);
137687deaf9552b546b847528cf39b38898fb7742b5f5carll         cnt_bits32_63  = gen_POPCOUNT(ty, bits32_63,  BYTE);
137697deaf9552b546b847528cf39b38898fb7742b5f5carll         cnt_bits64_95  = gen_POPCOUNT(ty, bits64_95,  BYTE);
137707deaf9552b546b847528cf39b38898fb7742b5f5carll         cnt_bits96_127 = gen_POPCOUNT(ty, bits96_127, BYTE);
137717deaf9552b546b847528cf39b38898fb7742b5f5carll
137727deaf9552b546b847528cf39b38898fb7742b5f5carll         putVReg( vRT_addr, mkV128from32(cnt_bits96_127, cnt_bits64_95,
137737deaf9552b546b847528cf39b38898fb7742b5f5carll                                         cnt_bits32_63, cnt_bits0_31) );
137747deaf9552b546b847528cf39b38898fb7742b5f5carll         break;
137757deaf9552b546b847528cf39b38898fb7742b5f5carll      }
137767deaf9552b546b847528cf39b38898fb7742b5f5carll
137777deaf9552b546b847528cf39b38898fb7742b5f5carll      case 0x743:    // vpopcnth
137787deaf9552b546b847528cf39b38898fb7742b5f5carll      {
137797deaf9552b546b847528cf39b38898fb7742b5f5carll         /* Break vector into 32-bit words and do the population count
137807deaf9552b546b847528cf39b38898fb7742b5f5carll          * for each half word
137817deaf9552b546b847528cf39b38898fb7742b5f5carll          */
137827deaf9552b546b847528cf39b38898fb7742b5f5carll         IRType ty = Ity_I32;
137837deaf9552b546b847528cf39b38898fb7742b5f5carll         IRTemp bits0_31, bits32_63, bits64_95, bits96_127;
137847deaf9552b546b847528cf39b38898fb7742b5f5carll         bits0_31 = bits32_63 = bits64_95 = bits96_127 = IRTemp_INVALID;
137857deaf9552b546b847528cf39b38898fb7742b5f5carll         IRTemp cnt_bits0_31, cnt_bits32_63, cnt_bits64_95, cnt_bits96_127;
137867deaf9552b546b847528cf39b38898fb7742b5f5carll         cnt_bits0_31 = cnt_bits32_63 = cnt_bits64_95 = cnt_bits96_127 = IRTemp_INVALID;
137877deaf9552b546b847528cf39b38898fb7742b5f5carll
137887deaf9552b546b847528cf39b38898fb7742b5f5carll         DIP("vpopcnth v%d,v%d\n", vRT_addr, vRB_addr);
137897deaf9552b546b847528cf39b38898fb7742b5f5carll         breakV128to4x32(mkexpr( vB), &bits96_127, &bits64_95, &bits32_63, &bits0_31 );
137907deaf9552b546b847528cf39b38898fb7742b5f5carll
137917deaf9552b546b847528cf39b38898fb7742b5f5carll         cnt_bits0_31   = gen_POPCOUNT(ty, bits0_31,   HWORD);
137927deaf9552b546b847528cf39b38898fb7742b5f5carll         cnt_bits32_63  = gen_POPCOUNT(ty, bits32_63,  HWORD);
137937deaf9552b546b847528cf39b38898fb7742b5f5carll         cnt_bits64_95  = gen_POPCOUNT(ty, bits64_95,  HWORD);
137947deaf9552b546b847528cf39b38898fb7742b5f5carll         cnt_bits96_127 = gen_POPCOUNT(ty, bits96_127, HWORD);
137957deaf9552b546b847528cf39b38898fb7742b5f5carll
137967deaf9552b546b847528cf39b38898fb7742b5f5carll         putVReg( vRT_addr, mkV128from32(cnt_bits96_127, cnt_bits64_95,
137977deaf9552b546b847528cf39b38898fb7742b5f5carll                                         cnt_bits32_63, cnt_bits0_31) );
137987deaf9552b546b847528cf39b38898fb7742b5f5carll         break;
137997deaf9552b546b847528cf39b38898fb7742b5f5carll      }
138007deaf9552b546b847528cf39b38898fb7742b5f5carll
138017deaf9552b546b847528cf39b38898fb7742b5f5carll      case 0x783:    // vpopcntw
138027deaf9552b546b847528cf39b38898fb7742b5f5carll      {
138037deaf9552b546b847528cf39b38898fb7742b5f5carll         /* Break vector into 32-bit words and do the population count
138047deaf9552b546b847528cf39b38898fb7742b5f5carll          * on each word.
138057deaf9552b546b847528cf39b38898fb7742b5f5carll          */
138067deaf9552b546b847528cf39b38898fb7742b5f5carll         IRType ty = Ity_I32;
138077deaf9552b546b847528cf39b38898fb7742b5f5carll         IRTemp bits0_31, bits32_63, bits64_95, bits96_127;
138087deaf9552b546b847528cf39b38898fb7742b5f5carll         bits0_31 = bits32_63 = bits64_95 = bits96_127 = IRTemp_INVALID;
138097deaf9552b546b847528cf39b38898fb7742b5f5carll         IRTemp cnt_bits0_31, cnt_bits32_63, cnt_bits64_95, cnt_bits96_127;
138107deaf9552b546b847528cf39b38898fb7742b5f5carll         cnt_bits0_31 = cnt_bits32_63 = cnt_bits64_95 = cnt_bits96_127 = IRTemp_INVALID;
138117deaf9552b546b847528cf39b38898fb7742b5f5carll
138127deaf9552b546b847528cf39b38898fb7742b5f5carll         DIP("vpopcntw v%d,v%d\n", vRT_addr, vRB_addr);
138137deaf9552b546b847528cf39b38898fb7742b5f5carll         breakV128to4x32(mkexpr( vB), &bits96_127, &bits64_95, &bits32_63, &bits0_31 );
138147deaf9552b546b847528cf39b38898fb7742b5f5carll
138157deaf9552b546b847528cf39b38898fb7742b5f5carll         cnt_bits0_31   = gen_POPCOUNT(ty, bits0_31,   WORD);
138167deaf9552b546b847528cf39b38898fb7742b5f5carll         cnt_bits32_63  = gen_POPCOUNT(ty, bits32_63,  WORD);
138177deaf9552b546b847528cf39b38898fb7742b5f5carll         cnt_bits64_95  = gen_POPCOUNT(ty, bits64_95,  WORD);
138187deaf9552b546b847528cf39b38898fb7742b5f5carll         cnt_bits96_127 = gen_POPCOUNT(ty, bits96_127, WORD);
138197deaf9552b546b847528cf39b38898fb7742b5f5carll
138207deaf9552b546b847528cf39b38898fb7742b5f5carll         putVReg( vRT_addr, mkV128from32(cnt_bits96_127, cnt_bits64_95,
138217deaf9552b546b847528cf39b38898fb7742b5f5carll                                         cnt_bits32_63, cnt_bits0_31) );
138227deaf9552b546b847528cf39b38898fb7742b5f5carll         break;
138237deaf9552b546b847528cf39b38898fb7742b5f5carll      }
138247deaf9552b546b847528cf39b38898fb7742b5f5carll
138257deaf9552b546b847528cf39b38898fb7742b5f5carll      case 0x7C3:    // vpopcntd
138267deaf9552b546b847528cf39b38898fb7742b5f5carll      {
138277deaf9552b546b847528cf39b38898fb7742b5f5carll         if (mode64) {
138287deaf9552b546b847528cf39b38898fb7742b5f5carll            /* Break vector into 64-bit double words and do the population count
138297deaf9552b546b847528cf39b38898fb7742b5f5carll             * on each double word.
138307deaf9552b546b847528cf39b38898fb7742b5f5carll             */
138317deaf9552b546b847528cf39b38898fb7742b5f5carll            IRType ty = Ity_I64;
138327deaf9552b546b847528cf39b38898fb7742b5f5carll            IRTemp bits0_63   = newTemp(Ity_I64);
138337deaf9552b546b847528cf39b38898fb7742b5f5carll            IRTemp bits64_127 = newTemp(Ity_I64);
138347deaf9552b546b847528cf39b38898fb7742b5f5carll            IRTemp cnt_bits0_63   = newTemp(Ity_I64);
138357deaf9552b546b847528cf39b38898fb7742b5f5carll            IRTemp cnt_bits64_127 = newTemp(Ity_I64);
138367deaf9552b546b847528cf39b38898fb7742b5f5carll
138377deaf9552b546b847528cf39b38898fb7742b5f5carll            DIP("vpopcntd v%d,v%d\n", vRT_addr, vRB_addr);
138387deaf9552b546b847528cf39b38898fb7742b5f5carll
138397deaf9552b546b847528cf39b38898fb7742b5f5carll            assign(bits0_63,   unop( Iop_V128to64,   mkexpr( vB ) ) );
138407deaf9552b546b847528cf39b38898fb7742b5f5carll            assign(bits64_127, unop( Iop_V128HIto64, mkexpr( vB ) ) );
138417deaf9552b546b847528cf39b38898fb7742b5f5carll            cnt_bits0_63   = gen_POPCOUNT(ty, bits0_63,   DWORD);
138427deaf9552b546b847528cf39b38898fb7742b5f5carll            cnt_bits64_127 = gen_POPCOUNT(ty, bits64_127, DWORD);
138437deaf9552b546b847528cf39b38898fb7742b5f5carll
138447deaf9552b546b847528cf39b38898fb7742b5f5carll            putVReg( vRT_addr, binop( Iop_64HLtoV128,
138457deaf9552b546b847528cf39b38898fb7742b5f5carll                                      mkexpr( cnt_bits64_127 ),
138467deaf9552b546b847528cf39b38898fb7742b5f5carll                                      mkexpr( cnt_bits0_63 ) ) );
138477deaf9552b546b847528cf39b38898fb7742b5f5carll         } else {
138487deaf9552b546b847528cf39b38898fb7742b5f5carll            /* Break vector into 32-bit words and do the population count
138497deaf9552b546b847528cf39b38898fb7742b5f5carll             * on each doubleword.
138507deaf9552b546b847528cf39b38898fb7742b5f5carll             */
138517deaf9552b546b847528cf39b38898fb7742b5f5carll            IRTemp bits0_31, bits32_63, bits64_95, bits96_127;
138527deaf9552b546b847528cf39b38898fb7742b5f5carll            bits0_31 = bits32_63 = bits64_95 = bits96_127 = IRTemp_INVALID;
138537deaf9552b546b847528cf39b38898fb7742b5f5carll            IRTemp cnt_bits0_63   = newTemp(Ity_I64);
138547deaf9552b546b847528cf39b38898fb7742b5f5carll            IRTemp cnt_bits64_127  = newTemp(Ity_I64);
138557deaf9552b546b847528cf39b38898fb7742b5f5carll
138567deaf9552b546b847528cf39b38898fb7742b5f5carll            DIP("vpopcntd v%d,v%d\n", vRT_addr, vRB_addr);
138577deaf9552b546b847528cf39b38898fb7742b5f5carll            breakV128to4x32(mkexpr( vB), &bits96_127, &bits64_95, &bits32_63, &bits0_31 );
138587deaf9552b546b847528cf39b38898fb7742b5f5carll
138597deaf9552b546b847528cf39b38898fb7742b5f5carll            cnt_bits0_63   = gen_vpopcntd_mode32(bits0_31, bits32_63);
138607deaf9552b546b847528cf39b38898fb7742b5f5carll            cnt_bits64_127 = gen_vpopcntd_mode32(bits64_95, bits96_127);
138617deaf9552b546b847528cf39b38898fb7742b5f5carll
138627deaf9552b546b847528cf39b38898fb7742b5f5carll            putVReg( vRT_addr, binop( Iop_64HLtoV128,
138637deaf9552b546b847528cf39b38898fb7742b5f5carll                                      mkexpr( cnt_bits64_127 ),
138647deaf9552b546b847528cf39b38898fb7742b5f5carll                                      mkexpr( cnt_bits0_63 ) ) );
138657deaf9552b546b847528cf39b38898fb7742b5f5carll         }
138667deaf9552b546b847528cf39b38898fb7742b5f5carll         break;
138677deaf9552b546b847528cf39b38898fb7742b5f5carll      }
138687deaf9552b546b847528cf39b38898fb7742b5f5carll
1386960c6bac19ffe055cabab554e7877d73096a8bf17carll      case 0x50C:  // vgbbd Vector Gather Bits by Bytes by Doubleword
1387060c6bac19ffe055cabab554e7877d73096a8bf17carll         DIP("vgbbd v%d,v%d\n", vRT_addr, vRB_addr);
1387160c6bac19ffe055cabab554e7877d73096a8bf17carll         putVReg( vRT_addr, unop( Iop_PwBitMtxXpose64x2, mkexpr( vB ) ) );
1387260c6bac19ffe055cabab554e7877d73096a8bf17carll         break;
1387360c6bac19ffe055cabab554e7877d73096a8bf17carll
138747deaf9552b546b847528cf39b38898fb7742b5f5carll      default:
1387560c6bac19ffe055cabab554e7877d73096a8bf17carll         vex_printf("dis_av_count_bitTranspose(ppc)(opc2)\n");
138767deaf9552b546b847528cf39b38898fb7742b5f5carll         return False;
138777deaf9552b546b847528cf39b38898fb7742b5f5carll      break;
138787deaf9552b546b847528cf39b38898fb7742b5f5carll   }
138797deaf9552b546b847528cf39b38898fb7742b5f5carll   return True;
138807deaf9552b546b847528cf39b38898fb7742b5f5carll}
138817deaf9552b546b847528cf39b38898fb7742b5f5carll
138824aa412af1d8166cc11f39a6e721df49431d23618sewardjtypedef enum {
138834aa412af1d8166cc11f39a6e721df49431d23618sewardj   PPC_CMP_EQ = 2,
138844aa412af1d8166cc11f39a6e721df49431d23618sewardj   PPC_CMP_GT = 4,
138854aa412af1d8166cc11f39a6e721df49431d23618sewardj   PPC_CMP_GE = 6,
138864aa412af1d8166cc11f39a6e721df49431d23618sewardj   PPC_CMP_LT = 8
138874aa412af1d8166cc11f39a6e721df49431d23618sewardj} ppc_cmp_t;
138884aa412af1d8166cc11f39a6e721df49431d23618sewardj
138894aa412af1d8166cc11f39a6e721df49431d23618sewardj
138904aa412af1d8166cc11f39a6e721df49431d23618sewardj/*
138914aa412af1d8166cc11f39a6e721df49431d23618sewardj  This helper function takes as input the IRExpr returned
138924aa412af1d8166cc11f39a6e721df49431d23618sewardj  from a binop( Iop_CmpF64, fpA, fpB), whose result is returned
138934aa412af1d8166cc11f39a6e721df49431d23618sewardj  in IR form.  This helper function converts it to PPC form.
138944aa412af1d8166cc11f39a6e721df49431d23618sewardj
138954aa412af1d8166cc11f39a6e721df49431d23618sewardj  Map compare result from IR to PPC
138964aa412af1d8166cc11f39a6e721df49431d23618sewardj
138974aa412af1d8166cc11f39a6e721df49431d23618sewardj  FP cmp result | PPC | IR
138984aa412af1d8166cc11f39a6e721df49431d23618sewardj  --------------------------
138994aa412af1d8166cc11f39a6e721df49431d23618sewardj  UN            | 0x1 | 0x45
139004aa412af1d8166cc11f39a6e721df49431d23618sewardj  EQ            | 0x2 | 0x40
139014aa412af1d8166cc11f39a6e721df49431d23618sewardj  GT            | 0x4 | 0x00
139024aa412af1d8166cc11f39a6e721df49431d23618sewardj  LT            | 0x8 | 0x01
139034aa412af1d8166cc11f39a6e721df49431d23618sewardj
139044aa412af1d8166cc11f39a6e721df49431d23618sewardj condcode = Shl(1, (~(ccIR>>5) & 2)
139054aa412af1d8166cc11f39a6e721df49431d23618sewardj                    | ((ccIR ^ (ccIR>>6)) & 1)
139064aa412af1d8166cc11f39a6e721df49431d23618sewardj*/
139074aa412af1d8166cc11f39a6e721df49431d23618sewardjstatic IRTemp
139084aa412af1d8166cc11f39a6e721df49431d23618sewardjget_fp_cmp_CR_val (IRExpr * ccIR_expr)
139094aa412af1d8166cc11f39a6e721df49431d23618sewardj{
139104aa412af1d8166cc11f39a6e721df49431d23618sewardj   IRTemp condcode = newTemp( Ity_I32 );
139114aa412af1d8166cc11f39a6e721df49431d23618sewardj   IRTemp ccIR = newTemp( Ity_I32 );
139124aa412af1d8166cc11f39a6e721df49431d23618sewardj
139134aa412af1d8166cc11f39a6e721df49431d23618sewardj   assign(ccIR, ccIR_expr);
139144aa412af1d8166cc11f39a6e721df49431d23618sewardj   assign( condcode,
139154aa412af1d8166cc11f39a6e721df49431d23618sewardj           binop( Iop_Shl32,
139164aa412af1d8166cc11f39a6e721df49431d23618sewardj                  mkU32( 1 ),
139174aa412af1d8166cc11f39a6e721df49431d23618sewardj                  unop( Iop_32to8,
139184aa412af1d8166cc11f39a6e721df49431d23618sewardj                        binop( Iop_Or32,
139194aa412af1d8166cc11f39a6e721df49431d23618sewardj                               binop( Iop_And32,
139204aa412af1d8166cc11f39a6e721df49431d23618sewardj                                      unop( Iop_Not32,
139214aa412af1d8166cc11f39a6e721df49431d23618sewardj                                            binop( Iop_Shr32,
139224aa412af1d8166cc11f39a6e721df49431d23618sewardj                                                   mkexpr( ccIR ),
139234aa412af1d8166cc11f39a6e721df49431d23618sewardj                                                   mkU8( 5 ) ) ),
139244aa412af1d8166cc11f39a6e721df49431d23618sewardj                                      mkU32( 2 ) ),
139254aa412af1d8166cc11f39a6e721df49431d23618sewardj                               binop( Iop_And32,
139264aa412af1d8166cc11f39a6e721df49431d23618sewardj                                      binop( Iop_Xor32,
139274aa412af1d8166cc11f39a6e721df49431d23618sewardj                                             mkexpr( ccIR ),
139284aa412af1d8166cc11f39a6e721df49431d23618sewardj                                             binop( Iop_Shr32,
139294aa412af1d8166cc11f39a6e721df49431d23618sewardj                                                    mkexpr( ccIR ),
139304aa412af1d8166cc11f39a6e721df49431d23618sewardj                                                    mkU8( 6 ) ) ),
139314aa412af1d8166cc11f39a6e721df49431d23618sewardj                                      mkU32( 1 ) ) ) ) ) );
139324aa412af1d8166cc11f39a6e721df49431d23618sewardj   return condcode;
139334aa412af1d8166cc11f39a6e721df49431d23618sewardj}
139344aa412af1d8166cc11f39a6e721df49431d23618sewardj
139354aa412af1d8166cc11f39a6e721df49431d23618sewardj/*
139364aa412af1d8166cc11f39a6e721df49431d23618sewardj * Helper function for get_max_min_fp for ascertaining the max or min between two doubles
139374aa412af1d8166cc11f39a6e721df49431d23618sewardj * following these special rules:
139384aa412af1d8166cc11f39a6e721df49431d23618sewardj *   - The max/min of a QNaN and any value is that value
139394aa412af1d8166cc11f39a6e721df49431d23618sewardj *     (When two QNaNs are being compared, the frA QNaN is the return value.)
139404aa412af1d8166cc11f39a6e721df49431d23618sewardj *   - The max/min of any value and an SNaN is that SNaN converted to a QNaN
139414aa412af1d8166cc11f39a6e721df49431d23618sewardj *     (When two SNaNs are being compared, the frA SNaN is converted to a QNaN.)
139424aa412af1d8166cc11f39a6e721df49431d23618sewardj */
139434aa412af1d8166cc11f39a6e721df49431d23618sewardjstatic IRExpr * _get_maxmin_fp_NaN(IRTemp frA_I64, IRTemp frB_I64)
139444aa412af1d8166cc11f39a6e721df49431d23618sewardj{
139454aa412af1d8166cc11f39a6e721df49431d23618sewardj   IRTemp frA_isNaN = newTemp(Ity_I1);
139464aa412af1d8166cc11f39a6e721df49431d23618sewardj   IRTemp frB_isNaN = newTemp(Ity_I1);
139474aa412af1d8166cc11f39a6e721df49431d23618sewardj   IRTemp frA_isSNaN = newTemp(Ity_I1);
139484aa412af1d8166cc11f39a6e721df49431d23618sewardj   IRTemp frB_isSNaN = newTemp(Ity_I1);
139494aa412af1d8166cc11f39a6e721df49431d23618sewardj   IRTemp frA_isQNaN = newTemp(Ity_I1);
139504aa412af1d8166cc11f39a6e721df49431d23618sewardj   IRTemp frB_isQNaN = newTemp(Ity_I1);
139514aa412af1d8166cc11f39a6e721df49431d23618sewardj
139524aa412af1d8166cc11f39a6e721df49431d23618sewardj   assign( frA_isNaN, is_NaN( frA_I64 ) );
139534aa412af1d8166cc11f39a6e721df49431d23618sewardj   assign( frB_isNaN, is_NaN( frB_I64 ) );
139544aa412af1d8166cc11f39a6e721df49431d23618sewardj   // If operand is a NAN and bit 12 is '0', then it's an SNaN
139554aa412af1d8166cc11f39a6e721df49431d23618sewardj   assign( frA_isSNaN,
139564aa412af1d8166cc11f39a6e721df49431d23618sewardj           mkAND1( mkexpr(frA_isNaN),
139574aa412af1d8166cc11f39a6e721df49431d23618sewardj                   binop( Iop_CmpEQ32,
139584aa412af1d8166cc11f39a6e721df49431d23618sewardj                          binop( Iop_And32,
139594aa412af1d8166cc11f39a6e721df49431d23618sewardj                                 unop( Iop_64HIto32, mkexpr( frA_I64 ) ),
139604aa412af1d8166cc11f39a6e721df49431d23618sewardj                                 mkU32( 0x00080000 ) ),
139614aa412af1d8166cc11f39a6e721df49431d23618sewardj                          mkU32( 0 ) ) ) );
139624aa412af1d8166cc11f39a6e721df49431d23618sewardj   assign( frB_isSNaN,
139634aa412af1d8166cc11f39a6e721df49431d23618sewardj           mkAND1( mkexpr(frB_isNaN),
139644aa412af1d8166cc11f39a6e721df49431d23618sewardj                   binop( Iop_CmpEQ32,
139654aa412af1d8166cc11f39a6e721df49431d23618sewardj                          binop( Iop_And32,
139664aa412af1d8166cc11f39a6e721df49431d23618sewardj                                 unop( Iop_64HIto32, mkexpr( frB_I64 ) ),
139674aa412af1d8166cc11f39a6e721df49431d23618sewardj                                 mkU32( 0x00080000 ) ),
139684aa412af1d8166cc11f39a6e721df49431d23618sewardj                          mkU32( 0 ) ) ) );
139694aa412af1d8166cc11f39a6e721df49431d23618sewardj   assign( frA_isQNaN,
139704aa412af1d8166cc11f39a6e721df49431d23618sewardj           mkAND1( mkexpr( frA_isNaN ), unop( Iop_Not1, mkexpr( frA_isSNaN ) ) ) );
139714aa412af1d8166cc11f39a6e721df49431d23618sewardj   assign( frB_isQNaN,
139724aa412af1d8166cc11f39a6e721df49431d23618sewardj           mkAND1( mkexpr( frB_isNaN ), unop( Iop_Not1, mkexpr( frB_isSNaN ) ) ) );
139734aa412af1d8166cc11f39a6e721df49431d23618sewardj
139744aa412af1d8166cc11f39a6e721df49431d23618sewardj   /* Based on the rules specified in the function prologue, the algorithm is as follows:
139754aa412af1d8166cc11f39a6e721df49431d23618sewardj    *  <<<<<<<<<>>>>>>>>>>>>>>>>>>
139764aa412af1d8166cc11f39a6e721df49431d23618sewardj    *   if frA is a SNaN
139774aa412af1d8166cc11f39a6e721df49431d23618sewardj    *     result = frA converted to QNaN
139784aa412af1d8166cc11f39a6e721df49431d23618sewardj    *   else if frB is a SNaN
139794aa412af1d8166cc11f39a6e721df49431d23618sewardj    *     result = frB converted to QNaN
139804aa412af1d8166cc11f39a6e721df49431d23618sewardj    *   else if frB is a QNaN
139814aa412af1d8166cc11f39a6e721df49431d23618sewardj    *     result = frA
139824aa412af1d8166cc11f39a6e721df49431d23618sewardj    *   // One of frA or frB was a NaN in order for this function to be called, so
139834aa412af1d8166cc11f39a6e721df49431d23618sewardj    *   // if we get to this point, we KNOW that frA must be a QNaN.
139844aa412af1d8166cc11f39a6e721df49431d23618sewardj    *   else // frA is a QNaN
139854aa412af1d8166cc11f39a6e721df49431d23618sewardj    *     result = frB
139864aa412af1d8166cc11f39a6e721df49431d23618sewardj    *  <<<<<<<<<>>>>>>>>>>>>>>>>>>
139874aa412af1d8166cc11f39a6e721df49431d23618sewardj    */
139884aa412af1d8166cc11f39a6e721df49431d23618sewardj
139894aa412af1d8166cc11f39a6e721df49431d23618sewardj#define SNAN_MASK 0x0008000000000000ULL
139904aa412af1d8166cc11f39a6e721df49431d23618sewardj   return
1399199dd03e04a6914d90d5fee727d61d76905334becflorian   IRExpr_ITE(mkexpr(frA_isSNaN),
1399299dd03e04a6914d90d5fee727d61d76905334becflorian              /* then: result = frA converted to QNaN */
1399399dd03e04a6914d90d5fee727d61d76905334becflorian              binop(Iop_Or64, mkexpr(frA_I64), mkU64(SNAN_MASK)),
1399499dd03e04a6914d90d5fee727d61d76905334becflorian              /* else:  if frB is a SNaN */
1399599dd03e04a6914d90d5fee727d61d76905334becflorian              IRExpr_ITE(mkexpr(frB_isSNaN),
1399699dd03e04a6914d90d5fee727d61d76905334becflorian                         /* then: result = frB converted to QNaN */
1399799dd03e04a6914d90d5fee727d61d76905334becflorian                         binop(Iop_Or64, mkexpr(frB_I64), mkU64(SNAN_MASK)),
1399899dd03e04a6914d90d5fee727d61d76905334becflorian                         /* else:  if frB is a QNaN */
1399999dd03e04a6914d90d5fee727d61d76905334becflorian                         IRExpr_ITE(mkexpr(frB_isQNaN),
1400099dd03e04a6914d90d5fee727d61d76905334becflorian                                    /* then: result = frA */
1400199dd03e04a6914d90d5fee727d61d76905334becflorian                                    mkexpr(frA_I64),
1400299dd03e04a6914d90d5fee727d61d76905334becflorian                                    /* else:  frA is a QNaN, so result = frB */
1400399dd03e04a6914d90d5fee727d61d76905334becflorian                                    mkexpr(frB_I64))));
140044aa412af1d8166cc11f39a6e721df49431d23618sewardj}
140054aa412af1d8166cc11f39a6e721df49431d23618sewardj
140064aa412af1d8166cc11f39a6e721df49431d23618sewardj/*
140074aa412af1d8166cc11f39a6e721df49431d23618sewardj * Helper function for get_max_min_fp.
140084aa412af1d8166cc11f39a6e721df49431d23618sewardj */
140094aa412af1d8166cc11f39a6e721df49431d23618sewardjstatic IRExpr * _get_maxmin_fp_cmp(IRTemp src1, IRTemp src2, Bool isMin)
140104aa412af1d8166cc11f39a6e721df49431d23618sewardj{
140114aa412af1d8166cc11f39a6e721df49431d23618sewardj   IRTemp src1cmpsrc2 = get_fp_cmp_CR_val( binop( Iop_CmpF64,
140124aa412af1d8166cc11f39a6e721df49431d23618sewardj                                                  unop( Iop_ReinterpI64asF64,
140134aa412af1d8166cc11f39a6e721df49431d23618sewardj                                                        mkexpr( src1 ) ),
140144aa412af1d8166cc11f39a6e721df49431d23618sewardj                                                  unop( Iop_ReinterpI64asF64,
140154aa412af1d8166cc11f39a6e721df49431d23618sewardj                                                        mkexpr( src2 ) ) ) );
140164aa412af1d8166cc11f39a6e721df49431d23618sewardj
1401799dd03e04a6914d90d5fee727d61d76905334becflorian   return IRExpr_ITE( binop( Iop_CmpEQ32,
14018009230b9758291b594e60d7c0243a73d53e81854sewardj                               mkexpr( src1cmpsrc2 ),
14019009230b9758291b594e60d7c0243a73d53e81854sewardj                               mkU32( isMin ? PPC_CMP_LT : PPC_CMP_GT ) ),
1402099dd03e04a6914d90d5fee727d61d76905334becflorian                      /* then: use src1 */
1402199dd03e04a6914d90d5fee727d61d76905334becflorian                      mkexpr( src1 ),
1402299dd03e04a6914d90d5fee727d61d76905334becflorian                      /* else: use src2 */
1402399dd03e04a6914d90d5fee727d61d76905334becflorian                      mkexpr( src2 ) );
140244aa412af1d8166cc11f39a6e721df49431d23618sewardj}
140254aa412af1d8166cc11f39a6e721df49431d23618sewardj
140264aa412af1d8166cc11f39a6e721df49431d23618sewardj/*
140274aa412af1d8166cc11f39a6e721df49431d23618sewardj * Helper function for "Maximum/Minimum Double Precision" operations.
140284aa412af1d8166cc11f39a6e721df49431d23618sewardj * Arguments: frA and frb are Ity_I64
140294aa412af1d8166cc11f39a6e721df49431d23618sewardj * Returns Ity_I64 IRExpr that answers the "which is Maxiumum/Minimum" question
140304aa412af1d8166cc11f39a6e721df49431d23618sewardj */
140314aa412af1d8166cc11f39a6e721df49431d23618sewardjstatic IRExpr * get_max_min_fp(IRTemp frA_I64, IRTemp frB_I64, Bool isMin)
140324aa412af1d8166cc11f39a6e721df49431d23618sewardj{
140334aa412af1d8166cc11f39a6e721df49431d23618sewardj   /* There are three special cases where get_fp_cmp_CR_val is not helpful
140344aa412af1d8166cc11f39a6e721df49431d23618sewardj    * for ascertaining the maximum between two doubles:
140354aa412af1d8166cc11f39a6e721df49431d23618sewardj    *   1. The max/min of +0 and -0 is +0.
140364aa412af1d8166cc11f39a6e721df49431d23618sewardj    *   2. The max/min of a QNaN and any value is that value.
140374aa412af1d8166cc11f39a6e721df49431d23618sewardj    *   3. The max/min of any value and an SNaN is that SNaN converted to a QNaN.
140384aa412af1d8166cc11f39a6e721df49431d23618sewardj    * We perform the check for [+/-]0 here in this function and use the
140394aa412af1d8166cc11f39a6e721df49431d23618sewardj    * _get_maxmin_fp_NaN helper for the two NaN cases; otherwise we call _get_maxmin_fp_cmp
140404aa412af1d8166cc11f39a6e721df49431d23618sewardj    * to do the standard comparison function.
140414aa412af1d8166cc11f39a6e721df49431d23618sewardj    */
140424aa412af1d8166cc11f39a6e721df49431d23618sewardj   IRTemp anyNaN = newTemp(Ity_I1);
140434aa412af1d8166cc11f39a6e721df49431d23618sewardj   IRTemp frA_isZero = newTemp(Ity_I1);
140444aa412af1d8166cc11f39a6e721df49431d23618sewardj   IRTemp frB_isZero = newTemp(Ity_I1);
14045e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj   assign(frA_isZero, is_Zero(frA_I64, False /*not single precision*/ ));
14046e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj   assign(frB_isZero, is_Zero(frB_I64, False /*not single precision*/ ));
140474aa412af1d8166cc11f39a6e721df49431d23618sewardj   assign(anyNaN, mkOR1(is_NaN(frA_I64), is_NaN(frB_I64)));
140484aa412af1d8166cc11f39a6e721df49431d23618sewardj#define MINUS_ZERO 0x8000000000000000ULL
140494aa412af1d8166cc11f39a6e721df49431d23618sewardj
1405099dd03e04a6914d90d5fee727d61d76905334becflorian   return IRExpr_ITE( /* If both arguments are zero . . . */
1405199dd03e04a6914d90d5fee727d61d76905334becflorian                     mkAND1( mkexpr( frA_isZero ), mkexpr( frB_isZero ) ),
1405299dd03e04a6914d90d5fee727d61d76905334becflorian                     /* then: if frA is -0 and isMin==True, return -0;
1405399dd03e04a6914d90d5fee727d61d76905334becflorian                      *     else if frA is +0 and isMin==False; return +0;
1405499dd03e04a6914d90d5fee727d61d76905334becflorian                      *     otherwise, simply return frB. */
1405599dd03e04a6914d90d5fee727d61d76905334becflorian                     IRExpr_ITE( binop( Iop_CmpEQ32,
1405699dd03e04a6914d90d5fee727d61d76905334becflorian                                        unop( Iop_64HIto32,
1405799dd03e04a6914d90d5fee727d61d76905334becflorian                                              mkexpr( frA_I64 ) ),
1405899dd03e04a6914d90d5fee727d61d76905334becflorian                                        mkU32( isMin ? 0x80000000 : 0 ) ),
1405999dd03e04a6914d90d5fee727d61d76905334becflorian                                 mkU64( isMin ? MINUS_ZERO : 0ULL ),
1406099dd03e04a6914d90d5fee727d61d76905334becflorian                                 mkexpr( frB_I64 ) ),
1406199dd03e04a6914d90d5fee727d61d76905334becflorian                     /* else: check if either input is a NaN*/
1406299dd03e04a6914d90d5fee727d61d76905334becflorian                     IRExpr_ITE( mkexpr( anyNaN ),
1406399dd03e04a6914d90d5fee727d61d76905334becflorian                                 /* then: use "NaN helper" */
1406499dd03e04a6914d90d5fee727d61d76905334becflorian                                 _get_maxmin_fp_NaN( frA_I64, frB_I64 ),
1406599dd03e04a6914d90d5fee727d61d76905334becflorian                                 /* else: use "comparison helper" */
1406699dd03e04a6914d90d5fee727d61d76905334becflorian                                 _get_maxmin_fp_cmp( frB_I64, frA_I64, isMin ) ));
140674aa412af1d8166cc11f39a6e721df49431d23618sewardj}
14068e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj
140699884af0b3cfe935b8fab54231f394fe4ee2d7ebccarllstatic const HChar * _get_vsx_rdpi_suffix(UInt opc2)
140709884af0b3cfe935b8fab54231f394fe4ee2d7ebccarll{
140719884af0b3cfe935b8fab54231f394fe4ee2d7ebccarll   switch (opc2 & 0x7F) {
140729884af0b3cfe935b8fab54231f394fe4ee2d7ebccarll      case 0x72:
140739884af0b3cfe935b8fab54231f394fe4ee2d7ebccarll         return "m";
140749884af0b3cfe935b8fab54231f394fe4ee2d7ebccarll      case 0x52:
140759884af0b3cfe935b8fab54231f394fe4ee2d7ebccarll         return "p";
140769884af0b3cfe935b8fab54231f394fe4ee2d7ebccarll      case 0x56:
140779884af0b3cfe935b8fab54231f394fe4ee2d7ebccarll         return "c";
140789884af0b3cfe935b8fab54231f394fe4ee2d7ebccarll      case 0x32:
140799884af0b3cfe935b8fab54231f394fe4ee2d7ebccarll         return "z";
140809884af0b3cfe935b8fab54231f394fe4ee2d7ebccarll      case 0x12:
140819884af0b3cfe935b8fab54231f394fe4ee2d7ebccarll         return "";
140829884af0b3cfe935b8fab54231f394fe4ee2d7ebccarll
140839884af0b3cfe935b8fab54231f394fe4ee2d7ebccarll      default: // Impossible to get here
140849884af0b3cfe935b8fab54231f394fe4ee2d7ebccarll         vex_printf("Unrecognized opcode %x\n", opc2);
140859884af0b3cfe935b8fab54231f394fe4ee2d7ebccarll         vpanic("_get_vsx_rdpi_suffix(ppc)(opc2)");
140869884af0b3cfe935b8fab54231f394fe4ee2d7ebccarll   }
140879884af0b3cfe935b8fab54231f394fe4ee2d7ebccarll}
140889884af0b3cfe935b8fab54231f394fe4ee2d7ebccarll
14089e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj/*
14090e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj * Helper function for vector/scalar double precision fp round to integer instructions.
14091e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj */
140929884af0b3cfe935b8fab54231f394fe4ee2d7ebccarllstatic IRExpr * _do_vsx_fp_roundToInt(IRTemp frB_I64, UInt opc2)
14093e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj{
14094e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj
14095e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj   /* The same rules apply for x{s|v}rdpi{m|p|c|z} as for floating point round operations (fri{m|n|p|z}). */
14096e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj   IRTemp frB = newTemp(Ity_F64);
14097e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj   IRTemp frD = newTemp(Ity_F64);
14098e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj   IRTemp intermediateResult = newTemp(Ity_I64);
14099e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj   IRTemp is_SNAN = newTemp(Ity_I1);
14100e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj   IRExpr * hi32;
14101e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj   IRExpr * rxpi_rm;
14102e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj   switch (opc2 & 0x7F) {
14103e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj      case 0x72:
14104e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj         rxpi_rm = mkU32(Irrm_NegINF);
14105e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj         break;
14106e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj      case 0x52:
14107e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj         rxpi_rm = mkU32(Irrm_PosINF);
14108e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj         break;
14109e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj      case 0x56:
14110e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj         rxpi_rm = get_IR_roundingmode();
14111e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj         break;
14112e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj      case 0x32:
14113e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj         rxpi_rm = mkU32(Irrm_ZERO);
14114e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj         break;
14115e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj      case 0x12:
14116e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj         rxpi_rm = mkU32(Irrm_NEAREST);
14117e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj         break;
14118e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj
14119e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj      default: // Impossible to get here
141209884af0b3cfe935b8fab54231f394fe4ee2d7ebccarll         vex_printf("Unrecognized opcode %x\n", opc2);
141219884af0b3cfe935b8fab54231f394fe4ee2d7ebccarll         vpanic("_do_vsx_fp_roundToInt(ppc)(opc2)");
14122e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj   }
14123e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj   assign(frB, unop(Iop_ReinterpI64asF64, mkexpr(frB_I64)));
14124e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj   assign( intermediateResult,
14125e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj           binop( Iop_F64toI64S, rxpi_rm,
14126e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj                  mkexpr( frB ) ) );
14127e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj
14128e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj   /* don't use the rounded integer if frB is outside -9e18..9e18 */
14129e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj   /* F64 has only log10(2**52) significant digits anyway */
14130e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj   /* need to preserve sign of zero */
14131e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj   /*   frD = (fabs(frB) > 9e18) ? frB :
14132e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj            (sign(frB)) ? -fabs((double)intermediateResult) : (double)intermediateResult  */
14133e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj   assign( frD,
1413499dd03e04a6914d90d5fee727d61d76905334becflorian           IRExpr_ITE(
14135009230b9758291b594e60d7c0243a73d53e81854sewardj              binop( Iop_CmpNE8,
14136009230b9758291b594e60d7c0243a73d53e81854sewardj                     unop( Iop_32to8,
14137009230b9758291b594e60d7c0243a73d53e81854sewardj                           binop( Iop_CmpF64,
14138009230b9758291b594e60d7c0243a73d53e81854sewardj                                  IRExpr_Const( IRConst_F64( 9e18 ) ),
14139009230b9758291b594e60d7c0243a73d53e81854sewardj                                  unop( Iop_AbsF64, mkexpr( frB ) ) ) ),
14140009230b9758291b594e60d7c0243a73d53e81854sewardj                     mkU8(0) ),
1414199dd03e04a6914d90d5fee727d61d76905334becflorian              mkexpr( frB ),
1414299dd03e04a6914d90d5fee727d61d76905334becflorian              IRExpr_ITE(
14143009230b9758291b594e60d7c0243a73d53e81854sewardj                 binop( Iop_CmpNE32,
14144009230b9758291b594e60d7c0243a73d53e81854sewardj                        binop( Iop_Shr32,
14145009230b9758291b594e60d7c0243a73d53e81854sewardj                               unop( Iop_64HIto32,
14146009230b9758291b594e60d7c0243a73d53e81854sewardj                                     mkexpr( frB_I64 ) ),
14147009230b9758291b594e60d7c0243a73d53e81854sewardj                               mkU8( 31 ) ),
14148009230b9758291b594e60d7c0243a73d53e81854sewardj                        mkU32(0) ),
14149009230b9758291b594e60d7c0243a73d53e81854sewardj                 unop( Iop_NegF64,
14150009230b9758291b594e60d7c0243a73d53e81854sewardj                       unop( Iop_AbsF64,
14151009230b9758291b594e60d7c0243a73d53e81854sewardj                             binop( Iop_I64StoF64,
14152009230b9758291b594e60d7c0243a73d53e81854sewardj                                    mkU32( 0 ),
1415399dd03e04a6914d90d5fee727d61d76905334becflorian                                    mkexpr( intermediateResult ) ) ) ),
1415499dd03e04a6914d90d5fee727d61d76905334becflorian                 binop( Iop_I64StoF64,
1415599dd03e04a6914d90d5fee727d61d76905334becflorian                        mkU32( 0 ),
1415699dd03e04a6914d90d5fee727d61d76905334becflorian                        mkexpr( intermediateResult ) )
1415799dd03e04a6914d90d5fee727d61d76905334becflorian              )
14158009230b9758291b594e60d7c0243a73d53e81854sewardj           )
14159009230b9758291b594e60d7c0243a73d53e81854sewardj   );
14160e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj
14161e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj   /* See Appendix "Floating-Point Round to Integer Model" in ISA doc.
14162e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj    * If frB is a SNAN, then frD <- frB, with bit 12 set to '1'.
14163e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj    */
14164e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj#define SNAN_MASK 0x0008000000000000ULL
14165e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj   hi32 = unop( Iop_64HIto32, mkexpr(frB_I64) );
14166e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj   assign( is_SNAN,
14167e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj           mkAND1( is_NaN( frB_I64 ),
14168e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj                   binop( Iop_CmpEQ32,
14169e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj                          binop( Iop_And32, hi32, mkU32( 0x00080000 ) ),
14170e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj                          mkU32( 0 ) ) ) );
14171e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj
1417299dd03e04a6914d90d5fee727d61d76905334becflorian   return IRExpr_ITE( mkexpr( is_SNAN ),
14173e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj                        unop( Iop_ReinterpI64asF64,
14174e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj                              binop( Iop_Xor64,
14175e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj                                     mkU64( SNAN_MASK ),
1417699dd03e04a6914d90d5fee727d61d76905334becflorian                                     mkexpr( frB_I64 ) ) ),
1417799dd03e04a6914d90d5fee727d61d76905334becflorian                      mkexpr( frD ));
14178e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj}
14179e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj
141804aa412af1d8166cc11f39a6e721df49431d23618sewardj/*
141814aa412af1d8166cc11f39a6e721df49431d23618sewardj * Miscellaneous VSX vector instructions
141824aa412af1d8166cc11f39a6e721df49431d23618sewardj */
141834aa412af1d8166cc11f39a6e721df49431d23618sewardjstatic Bool
141844aa412af1d8166cc11f39a6e721df49431d23618sewardjdis_vxv_misc ( UInt theInstr, UInt opc2 )
141854aa412af1d8166cc11f39a6e721df49431d23618sewardj{
141864aa412af1d8166cc11f39a6e721df49431d23618sewardj   /* XX3-Form */
141874aa412af1d8166cc11f39a6e721df49431d23618sewardj   UChar opc1 = ifieldOPC( theInstr );
141884aa412af1d8166cc11f39a6e721df49431d23618sewardj   UChar XT = ifieldRegXT( theInstr );
141894aa412af1d8166cc11f39a6e721df49431d23618sewardj   UChar XB = ifieldRegXB( theInstr );
141904aa412af1d8166cc11f39a6e721df49431d23618sewardj
141914aa412af1d8166cc11f39a6e721df49431d23618sewardj   if (opc1 != 0x3C) {
141924aa412af1d8166cc11f39a6e721df49431d23618sewardj      vex_printf( "dis_vxv_misc(ppc)(instr)\n" );
141934aa412af1d8166cc11f39a6e721df49431d23618sewardj      return False;
141944aa412af1d8166cc11f39a6e721df49431d23618sewardj   }
141954aa412af1d8166cc11f39a6e721df49431d23618sewardj
141964aa412af1d8166cc11f39a6e721df49431d23618sewardj   switch (opc2) {
14197e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj      case 0x1B4:  // xvredp (VSX Vector Reciprocal Estimate Double-Precision)
14198e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj      case 0x194:  // xvrsqrtedp (VSX Vector Reciprocal Square Root Estimate
14199e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj                   //             Double-Precision)
14200e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj      {
14201e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj         IRExpr* ieee_one = IRExpr_Const(IRConst_F64i(0x3ff0000000000000ULL));
14202e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj         IRExpr* rm  = get_IR_roundingmode();
14203e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj         IRTemp frB = newTemp(Ity_I64);
14204e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj         IRTemp frB2 = newTemp(Ity_I64);
14205e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj         Bool redp = opc2 == 0x1B4;
14206e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj         IRTemp sqrtHi = newTemp(Ity_F64);
14207e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj         IRTemp sqrtLo = newTemp(Ity_F64);
14208e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj         assign(frB,  unop(Iop_V128HIto64, getVSReg( XB )));
14209e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj         assign(frB2, unop(Iop_V128to64, getVSReg( XB )));
14210e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj
14211b173774421d015736c2316b5e6e998e7de545a5cflorian         DIP("%s v%d,v%d\n", redp ? "xvredp" : "xvrsqrtedp", XT, XB);
14212e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj         if (!redp) {
14213e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj            assign( sqrtHi,
14214e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj                    binop( Iop_SqrtF64,
14215e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj                           rm,
14216e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj                           unop( Iop_ReinterpI64asF64, mkexpr( frB ) ) ) );
14217e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj            assign( sqrtLo,
14218e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj                    binop( Iop_SqrtF64,
14219e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj                           rm,
14220e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj                           unop( Iop_ReinterpI64asF64, mkexpr( frB2 ) ) ) );
14221e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj         }
14222e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj         putVSReg( XT,
14223e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj                   binop( Iop_64HLtoV128,
14224e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj                          unop( Iop_ReinterpF64asI64,
14225e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj                                triop( Iop_DivF64,
14226e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj                                       rm,
14227e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj                                       ieee_one,
14228e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj                                       redp ? unop( Iop_ReinterpI64asF64,
14229e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj                                                    mkexpr( frB ) )
14230e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj                                            : mkexpr( sqrtHi ) ) ),
14231e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj                          unop( Iop_ReinterpF64asI64,
14232e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj                                triop( Iop_DivF64,
14233e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj                                       rm,
14234e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj                                       ieee_one,
14235e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj                                       redp ? unop( Iop_ReinterpI64asF64,
14236e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj                                                    mkexpr( frB2 ) )
14237e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj                                            : mkexpr( sqrtLo ) ) ) ) );
14238e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj         break;
14239e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj
14240e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj      }
142414aa412af1d8166cc11f39a6e721df49431d23618sewardj      case 0x134: // xvresp (VSX Vector Reciprocal Estimate Single-Precision)
14242e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj      case 0x114: // xvrsqrtesp (VSX Vector Reciprocal Square Root Estimate Single-Precision)
142434aa412af1d8166cc11f39a6e721df49431d23618sewardj      {
142444aa412af1d8166cc11f39a6e721df49431d23618sewardj         IRTemp b3, b2, b1, b0;
142454aa412af1d8166cc11f39a6e721df49431d23618sewardj         IRTemp res0 = newTemp(Ity_I32);
142464aa412af1d8166cc11f39a6e721df49431d23618sewardj         IRTemp res1 = newTemp(Ity_I32);
142474aa412af1d8166cc11f39a6e721df49431d23618sewardj         IRTemp res2 = newTemp(Ity_I32);
142484aa412af1d8166cc11f39a6e721df49431d23618sewardj         IRTemp res3 = newTemp(Ity_I32);
14249e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj         IRTemp sqrt3 = newTemp(Ity_F64);
14250e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj         IRTemp sqrt2 = newTemp(Ity_F64);
14251e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj         IRTemp sqrt1 = newTemp(Ity_F64);
14252e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj         IRTemp sqrt0 = newTemp(Ity_F64);
142534aa412af1d8166cc11f39a6e721df49431d23618sewardj         IRExpr* rm  = get_IR_roundingmode();
14254e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj         Bool resp = opc2 == 0x134;
14255e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj
142564aa412af1d8166cc11f39a6e721df49431d23618sewardj         IRExpr* ieee_one = IRExpr_Const(IRConst_F64i(0x3ff0000000000000ULL));
142574aa412af1d8166cc11f39a6e721df49431d23618sewardj
142584aa412af1d8166cc11f39a6e721df49431d23618sewardj         b3 = b2 = b1 = b0 = IRTemp_INVALID;
14259b173774421d015736c2316b5e6e998e7de545a5cflorian         DIP("%s v%d,v%d\n", resp ? "xvresp" : "xvrsqrtesp", XT, XB);
142604aa412af1d8166cc11f39a6e721df49431d23618sewardj         breakV128to4xF64( getVSReg( XB ), &b3, &b2, &b1, &b0 );
14261e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj
14262e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj         if (!resp) {
14263e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj            assign( sqrt3, binop( Iop_SqrtF64, rm, mkexpr( b3 ) ) );
14264e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj            assign( sqrt2, binop( Iop_SqrtF64, rm, mkexpr( b2 ) ) );
14265e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj            assign( sqrt1, binop( Iop_SqrtF64, rm, mkexpr( b1 ) ) );
14266e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj            assign( sqrt0, binop( Iop_SqrtF64, rm, mkexpr( b0 ) ) );
14267e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj         }
14268e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj
142694aa412af1d8166cc11f39a6e721df49431d23618sewardj         assign( res0,
142704aa412af1d8166cc11f39a6e721df49431d23618sewardj                 unop( Iop_ReinterpF32asI32,
142714aa412af1d8166cc11f39a6e721df49431d23618sewardj                       unop( Iop_TruncF64asF32,
14272e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj                             triop( Iop_DivF64r32,
14273e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj                                    rm,
14274e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj                                    ieee_one,
14275e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj                                    resp ? mkexpr( b0 ) : mkexpr( sqrt0 ) ) ) ) );
142764aa412af1d8166cc11f39a6e721df49431d23618sewardj         assign( res1,
142774aa412af1d8166cc11f39a6e721df49431d23618sewardj                 unop( Iop_ReinterpF32asI32,
142784aa412af1d8166cc11f39a6e721df49431d23618sewardj                       unop( Iop_TruncF64asF32,
14279e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj                             triop( Iop_DivF64r32,
14280e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj                                    rm,
14281e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj                                    ieee_one,
14282e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj                                    resp ? mkexpr( b1 ) : mkexpr( sqrt1 ) ) ) ) );
142834aa412af1d8166cc11f39a6e721df49431d23618sewardj         assign( res2,
142844aa412af1d8166cc11f39a6e721df49431d23618sewardj                 unop( Iop_ReinterpF32asI32,
142854aa412af1d8166cc11f39a6e721df49431d23618sewardj                       unop( Iop_TruncF64asF32,
14286e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj                             triop( Iop_DivF64r32,
14287e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj                                    rm,
14288e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj                                    ieee_one,
14289e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj                                    resp ? mkexpr( b2 ) : mkexpr( sqrt2 ) ) ) ) );
142904aa412af1d8166cc11f39a6e721df49431d23618sewardj         assign( res3,
142914aa412af1d8166cc11f39a6e721df49431d23618sewardj                 unop( Iop_ReinterpF32asI32,
142924aa412af1d8166cc11f39a6e721df49431d23618sewardj                       unop( Iop_TruncF64asF32,
14293e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj                             triop( Iop_DivF64r32,
14294e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj                                    rm,
14295e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj                                    ieee_one,
14296e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj                                    resp ? mkexpr( b3 ) : mkexpr( sqrt3 ) ) ) ) );
142974aa412af1d8166cc11f39a6e721df49431d23618sewardj         putVSReg( XT,
142984aa412af1d8166cc11f39a6e721df49431d23618sewardj                   binop( Iop_64HLtoV128,
142994aa412af1d8166cc11f39a6e721df49431d23618sewardj                          binop( Iop_32HLto64, mkexpr( res3 ), mkexpr( res2 ) ),
143004aa412af1d8166cc11f39a6e721df49431d23618sewardj                          binop( Iop_32HLto64, mkexpr( res1 ), mkexpr( res0 ) ) ) );
143014aa412af1d8166cc11f39a6e721df49431d23618sewardj         break;
143024aa412af1d8166cc11f39a6e721df49431d23618sewardj      }
143034aa412af1d8166cc11f39a6e721df49431d23618sewardj      case 0x300: // xvmaxsp (VSX Vector Maximum Single-Precision)
143044aa412af1d8166cc11f39a6e721df49431d23618sewardj      case 0x320: // xvminsp (VSX Vector Minimum Single-Precision)
143054aa412af1d8166cc11f39a6e721df49431d23618sewardj      {
143064aa412af1d8166cc11f39a6e721df49431d23618sewardj         UChar XA = ifieldRegXA( theInstr );
143074aa412af1d8166cc11f39a6e721df49431d23618sewardj         IRTemp a3, a2, a1, a0;
143084aa412af1d8166cc11f39a6e721df49431d23618sewardj         IRTemp b3, b2, b1, b0;
143094aa412af1d8166cc11f39a6e721df49431d23618sewardj         IRTemp res0 = newTemp( Ity_I32 );
143104aa412af1d8166cc11f39a6e721df49431d23618sewardj         IRTemp res1 = newTemp( Ity_I32 );
143114aa412af1d8166cc11f39a6e721df49431d23618sewardj         IRTemp res2 = newTemp( Ity_I32 );
143124aa412af1d8166cc11f39a6e721df49431d23618sewardj         IRTemp res3 = newTemp( Ity_I32 );
143134aa412af1d8166cc11f39a6e721df49431d23618sewardj         IRTemp a0_I64 = newTemp( Ity_I64 );
143144aa412af1d8166cc11f39a6e721df49431d23618sewardj         IRTemp a1_I64 = newTemp( Ity_I64 );
143154aa412af1d8166cc11f39a6e721df49431d23618sewardj         IRTemp a2_I64 = newTemp( Ity_I64 );
143164aa412af1d8166cc11f39a6e721df49431d23618sewardj         IRTemp a3_I64 = newTemp( Ity_I64 );
143174aa412af1d8166cc11f39a6e721df49431d23618sewardj         IRTemp b0_I64 = newTemp( Ity_I64 );
143184aa412af1d8166cc11f39a6e721df49431d23618sewardj         IRTemp b1_I64 = newTemp( Ity_I64 );
143194aa412af1d8166cc11f39a6e721df49431d23618sewardj         IRTemp b2_I64 = newTemp( Ity_I64 );
143204aa412af1d8166cc11f39a6e721df49431d23618sewardj         IRTemp b3_I64 = newTemp( Ity_I64 );
143214aa412af1d8166cc11f39a6e721df49431d23618sewardj
143224aa412af1d8166cc11f39a6e721df49431d23618sewardj         Bool isMin = opc2 == 0x320 ? True : False;
143234aa412af1d8166cc11f39a6e721df49431d23618sewardj
143244aa412af1d8166cc11f39a6e721df49431d23618sewardj         a3 = a2 = a1 = a0 = IRTemp_INVALID;
143254aa412af1d8166cc11f39a6e721df49431d23618sewardj         b3 = b2 = b1 = b0 = IRTemp_INVALID;
14326b173774421d015736c2316b5e6e998e7de545a5cflorian         DIP("%s v%d,v%d v%d\n", isMin ? "xvminsp" : "xvmaxsp", XT, XA, XB);
143274aa412af1d8166cc11f39a6e721df49431d23618sewardj         breakV128to4xF64( getVSReg( XA ), &a3, &a2, &a1, &a0 );
143284aa412af1d8166cc11f39a6e721df49431d23618sewardj         breakV128to4xF64( getVSReg( XB ), &b3, &b2, &b1, &b0 );
143294aa412af1d8166cc11f39a6e721df49431d23618sewardj         assign( a0_I64, unop( Iop_ReinterpF64asI64, mkexpr( a0 ) ) );
143304aa412af1d8166cc11f39a6e721df49431d23618sewardj         assign( b0_I64, unop( Iop_ReinterpF64asI64, mkexpr( b0 ) ) );
143314aa412af1d8166cc11f39a6e721df49431d23618sewardj         assign( a1_I64, unop( Iop_ReinterpF64asI64, mkexpr( a1 ) ) );
143324aa412af1d8166cc11f39a6e721df49431d23618sewardj         assign( b1_I64, unop( Iop_ReinterpF64asI64, mkexpr( b1 ) ) );
143334aa412af1d8166cc11f39a6e721df49431d23618sewardj         assign( a2_I64, unop( Iop_ReinterpF64asI64, mkexpr( a2 ) ) );
143344aa412af1d8166cc11f39a6e721df49431d23618sewardj         assign( b2_I64, unop( Iop_ReinterpF64asI64, mkexpr( b2 ) ) );
143354aa412af1d8166cc11f39a6e721df49431d23618sewardj         assign( a3_I64, unop( Iop_ReinterpF64asI64, mkexpr( a3 ) ) );
143364aa412af1d8166cc11f39a6e721df49431d23618sewardj         assign( b3_I64, unop( Iop_ReinterpF64asI64, mkexpr( b3 ) ) );
143374aa412af1d8166cc11f39a6e721df49431d23618sewardj         assign( res0,
143384aa412af1d8166cc11f39a6e721df49431d23618sewardj                 unop( Iop_ReinterpF32asI32,
143394aa412af1d8166cc11f39a6e721df49431d23618sewardj                       unop( Iop_TruncF64asF32,
143404aa412af1d8166cc11f39a6e721df49431d23618sewardj                             unop( Iop_ReinterpI64asF64,
143414aa412af1d8166cc11f39a6e721df49431d23618sewardj                                   get_max_min_fp( a0_I64, b0_I64, isMin ) ) ) ) );
143424aa412af1d8166cc11f39a6e721df49431d23618sewardj         assign( res1,
143434aa412af1d8166cc11f39a6e721df49431d23618sewardj                 unop( Iop_ReinterpF32asI32,
143444aa412af1d8166cc11f39a6e721df49431d23618sewardj                       unop( Iop_TruncF64asF32,
143454aa412af1d8166cc11f39a6e721df49431d23618sewardj                             unop( Iop_ReinterpI64asF64,
143464aa412af1d8166cc11f39a6e721df49431d23618sewardj                                   get_max_min_fp( a1_I64, b1_I64, isMin ) ) ) ) );
143474aa412af1d8166cc11f39a6e721df49431d23618sewardj         assign( res2,
143484aa412af1d8166cc11f39a6e721df49431d23618sewardj                 unop( Iop_ReinterpF32asI32,
143494aa412af1d8166cc11f39a6e721df49431d23618sewardj                       unop( Iop_TruncF64asF32,
143504aa412af1d8166cc11f39a6e721df49431d23618sewardj                             unop( Iop_ReinterpI64asF64,
143514aa412af1d8166cc11f39a6e721df49431d23618sewardj                                   get_max_min_fp( a2_I64, b2_I64, isMin ) ) ) ) );
143524aa412af1d8166cc11f39a6e721df49431d23618sewardj         assign( res3,
143534aa412af1d8166cc11f39a6e721df49431d23618sewardj                 unop( Iop_ReinterpF32asI32,
143544aa412af1d8166cc11f39a6e721df49431d23618sewardj                       unop( Iop_TruncF64asF32,
143554aa412af1d8166cc11f39a6e721df49431d23618sewardj                             unop( Iop_ReinterpI64asF64,
143564aa412af1d8166cc11f39a6e721df49431d23618sewardj                                   get_max_min_fp( a3_I64, b3_I64, isMin ) ) ) ) );
143574aa412af1d8166cc11f39a6e721df49431d23618sewardj         putVSReg( XT,
143584aa412af1d8166cc11f39a6e721df49431d23618sewardj                   binop( Iop_64HLtoV128,
143594aa412af1d8166cc11f39a6e721df49431d23618sewardj                          binop( Iop_32HLto64, mkexpr( res3 ), mkexpr( res2 ) ),
143604aa412af1d8166cc11f39a6e721df49431d23618sewardj                          binop( Iop_32HLto64, mkexpr( res1 ), mkexpr( res0 ) ) ) );
143614aa412af1d8166cc11f39a6e721df49431d23618sewardj         break;
143624aa412af1d8166cc11f39a6e721df49431d23618sewardj      }
143634aa412af1d8166cc11f39a6e721df49431d23618sewardj      case 0x380: // xvmaxdp (VSX Vector Maximum Double-Precision)
143644aa412af1d8166cc11f39a6e721df49431d23618sewardj      case 0x3A0: // xvmindp (VSX Vector Minimum Double-Precision)
143654aa412af1d8166cc11f39a6e721df49431d23618sewardj      {
143664aa412af1d8166cc11f39a6e721df49431d23618sewardj         UChar XA = ifieldRegXA( theInstr );
143674aa412af1d8166cc11f39a6e721df49431d23618sewardj         IRTemp frA = newTemp(Ity_I64);
143684aa412af1d8166cc11f39a6e721df49431d23618sewardj         IRTemp frB = newTemp(Ity_I64);
143694aa412af1d8166cc11f39a6e721df49431d23618sewardj         IRTemp frA2 = newTemp(Ity_I64);
143704aa412af1d8166cc11f39a6e721df49431d23618sewardj         IRTemp frB2 = newTemp(Ity_I64);
143714aa412af1d8166cc11f39a6e721df49431d23618sewardj         Bool isMin = opc2 == 0x3A0 ? True : False;
143724aa412af1d8166cc11f39a6e721df49431d23618sewardj
143734aa412af1d8166cc11f39a6e721df49431d23618sewardj         assign(frA,  unop(Iop_V128HIto64, getVSReg( XA )));
143744aa412af1d8166cc11f39a6e721df49431d23618sewardj         assign(frB,  unop(Iop_V128HIto64, getVSReg( XB )));
143754aa412af1d8166cc11f39a6e721df49431d23618sewardj         assign(frA2, unop(Iop_V128to64, getVSReg( XA )));
143764aa412af1d8166cc11f39a6e721df49431d23618sewardj         assign(frB2, unop(Iop_V128to64, getVSReg( XB )));
14377b173774421d015736c2316b5e6e998e7de545a5cflorian         DIP("%s v%d,v%d v%d\n", isMin ? "xvmindp" : "xvmaxdp", XT, XA, XB);
143784aa412af1d8166cc11f39a6e721df49431d23618sewardj         putVSReg( XT, binop( Iop_64HLtoV128, get_max_min_fp(frA, frB, isMin), get_max_min_fp(frA2, frB2, isMin) ) );
143794aa412af1d8166cc11f39a6e721df49431d23618sewardj
143804aa412af1d8166cc11f39a6e721df49431d23618sewardj         break;
143814aa412af1d8166cc11f39a6e721df49431d23618sewardj      }
143824aa412af1d8166cc11f39a6e721df49431d23618sewardj      case 0x3c0: // xvcpsgndp (VSX Vector Copy Sign Double-Precision)
143834aa412af1d8166cc11f39a6e721df49431d23618sewardj      {
143844aa412af1d8166cc11f39a6e721df49431d23618sewardj         UChar XA = ifieldRegXA( theInstr );
143854aa412af1d8166cc11f39a6e721df49431d23618sewardj         IRTemp frA = newTemp(Ity_I64);
143864aa412af1d8166cc11f39a6e721df49431d23618sewardj         IRTemp frB = newTemp(Ity_I64);
143874aa412af1d8166cc11f39a6e721df49431d23618sewardj         IRTemp frA2 = newTemp(Ity_I64);
143884aa412af1d8166cc11f39a6e721df49431d23618sewardj         IRTemp frB2 = newTemp(Ity_I64);
143894aa412af1d8166cc11f39a6e721df49431d23618sewardj         assign(frA,  unop(Iop_V128HIto64, getVSReg( XA )));
143904aa412af1d8166cc11f39a6e721df49431d23618sewardj         assign(frB,  unop(Iop_V128HIto64, getVSReg( XB )));
143914aa412af1d8166cc11f39a6e721df49431d23618sewardj         assign(frA2, unop(Iop_V128to64, getVSReg( XA )));
143924aa412af1d8166cc11f39a6e721df49431d23618sewardj         assign(frB2, unop(Iop_V128to64, getVSReg( XB )));
143934aa412af1d8166cc11f39a6e721df49431d23618sewardj
14394b173774421d015736c2316b5e6e998e7de545a5cflorian         DIP("xvcpsgndp v%d,v%d,v%d\n", XT, XA, XB);
143954aa412af1d8166cc11f39a6e721df49431d23618sewardj         putVSReg( XT,
143964aa412af1d8166cc11f39a6e721df49431d23618sewardj                   binop( Iop_64HLtoV128,
143974aa412af1d8166cc11f39a6e721df49431d23618sewardj                          binop( Iop_Or64,
143984aa412af1d8166cc11f39a6e721df49431d23618sewardj                                 binop( Iop_And64,
143994aa412af1d8166cc11f39a6e721df49431d23618sewardj                                        mkexpr( frA ),
144004aa412af1d8166cc11f39a6e721df49431d23618sewardj                                        mkU64( SIGN_BIT ) ),
144014aa412af1d8166cc11f39a6e721df49431d23618sewardj                                 binop( Iop_And64,
144024aa412af1d8166cc11f39a6e721df49431d23618sewardj                                        mkexpr( frB ),
144034aa412af1d8166cc11f39a6e721df49431d23618sewardj                                        mkU64( SIGN_MASK ) ) ),
144044aa412af1d8166cc11f39a6e721df49431d23618sewardj                          binop( Iop_Or64,
144054aa412af1d8166cc11f39a6e721df49431d23618sewardj                                 binop( Iop_And64,
144064aa412af1d8166cc11f39a6e721df49431d23618sewardj                                        mkexpr( frA2 ),
144074aa412af1d8166cc11f39a6e721df49431d23618sewardj                                        mkU64( SIGN_BIT ) ),
144084aa412af1d8166cc11f39a6e721df49431d23618sewardj                                 binop( Iop_And64,
144094aa412af1d8166cc11f39a6e721df49431d23618sewardj                                        mkexpr( frB2 ),
144104aa412af1d8166cc11f39a6e721df49431d23618sewardj                                        mkU64( SIGN_MASK ) ) ) ) );
144114aa412af1d8166cc11f39a6e721df49431d23618sewardj         break;
144124aa412af1d8166cc11f39a6e721df49431d23618sewardj      }
144134aa412af1d8166cc11f39a6e721df49431d23618sewardj      case 0x340: // xvcpsgnsp
144144aa412af1d8166cc11f39a6e721df49431d23618sewardj      {
144154aa412af1d8166cc11f39a6e721df49431d23618sewardj         UChar XA = ifieldRegXA( theInstr );
144164aa412af1d8166cc11f39a6e721df49431d23618sewardj         IRTemp a3_I64, a2_I64, a1_I64, a0_I64;
144174aa412af1d8166cc11f39a6e721df49431d23618sewardj         IRTemp b3_I64, b2_I64, b1_I64, b0_I64;
144184aa412af1d8166cc11f39a6e721df49431d23618sewardj         IRTemp resHi = newTemp(Ity_I64);
144194aa412af1d8166cc11f39a6e721df49431d23618sewardj         IRTemp resLo = newTemp(Ity_I64);
144204aa412af1d8166cc11f39a6e721df49431d23618sewardj
144214aa412af1d8166cc11f39a6e721df49431d23618sewardj         a3_I64 = a2_I64 = a1_I64 = a0_I64 = IRTemp_INVALID;
144224aa412af1d8166cc11f39a6e721df49431d23618sewardj         b3_I64 = b2_I64 = b1_I64 = b0_I64 = IRTemp_INVALID;
14423b173774421d015736c2316b5e6e998e7de545a5cflorian         DIP("xvcpsgnsp v%d,v%d v%d\n",XT, XA, XB);
144244aa412af1d8166cc11f39a6e721df49431d23618sewardj         breakV128to4x64U( getVSReg( XA ), &a3_I64, &a2_I64, &a1_I64, &a0_I64 );
144254aa412af1d8166cc11f39a6e721df49431d23618sewardj         breakV128to4x64U( getVSReg( XB ), &b3_I64, &b2_I64, &b1_I64, &b0_I64 );
144264aa412af1d8166cc11f39a6e721df49431d23618sewardj
144274aa412af1d8166cc11f39a6e721df49431d23618sewardj         assign( resHi,
144284aa412af1d8166cc11f39a6e721df49431d23618sewardj                 binop( Iop_32HLto64,
144294aa412af1d8166cc11f39a6e721df49431d23618sewardj                        binop( Iop_Or32,
144304aa412af1d8166cc11f39a6e721df49431d23618sewardj                               binop( Iop_And32,
144314aa412af1d8166cc11f39a6e721df49431d23618sewardj                                      unop(Iop_64to32, mkexpr( a3_I64 ) ),
144324aa412af1d8166cc11f39a6e721df49431d23618sewardj                                      mkU32( SIGN_BIT32 ) ),
144334aa412af1d8166cc11f39a6e721df49431d23618sewardj                               binop( Iop_And32,
144344aa412af1d8166cc11f39a6e721df49431d23618sewardj                                      unop(Iop_64to32, mkexpr( b3_I64 ) ),
144354aa412af1d8166cc11f39a6e721df49431d23618sewardj                                      mkU32( SIGN_MASK32) ) ),
144364aa412af1d8166cc11f39a6e721df49431d23618sewardj
144374aa412af1d8166cc11f39a6e721df49431d23618sewardj                        binop( Iop_Or32,
144384aa412af1d8166cc11f39a6e721df49431d23618sewardj                               binop( Iop_And32,
144394aa412af1d8166cc11f39a6e721df49431d23618sewardj                                      unop(Iop_64to32, mkexpr( a2_I64 ) ),
144404aa412af1d8166cc11f39a6e721df49431d23618sewardj                                      mkU32( SIGN_BIT32 ) ),
144414aa412af1d8166cc11f39a6e721df49431d23618sewardj                               binop( Iop_And32,
144424aa412af1d8166cc11f39a6e721df49431d23618sewardj                                      unop(Iop_64to32, mkexpr( b2_I64 ) ),
144434aa412af1d8166cc11f39a6e721df49431d23618sewardj                                      mkU32( SIGN_MASK32 ) ) ) ) );
144444aa412af1d8166cc11f39a6e721df49431d23618sewardj         assign( resLo,
144454aa412af1d8166cc11f39a6e721df49431d23618sewardj                 binop( Iop_32HLto64,
144464aa412af1d8166cc11f39a6e721df49431d23618sewardj                        binop( Iop_Or32,
144474aa412af1d8166cc11f39a6e721df49431d23618sewardj                               binop( Iop_And32,
144484aa412af1d8166cc11f39a6e721df49431d23618sewardj                                      unop(Iop_64to32, mkexpr( a1_I64 ) ),
144494aa412af1d8166cc11f39a6e721df49431d23618sewardj                                      mkU32( SIGN_BIT32 ) ),
144504aa412af1d8166cc11f39a6e721df49431d23618sewardj                               binop( Iop_And32,
144514aa412af1d8166cc11f39a6e721df49431d23618sewardj                                      unop(Iop_64to32, mkexpr( b1_I64 ) ),
144524aa412af1d8166cc11f39a6e721df49431d23618sewardj                                      mkU32( SIGN_MASK32 ) ) ),
144534aa412af1d8166cc11f39a6e721df49431d23618sewardj
144544aa412af1d8166cc11f39a6e721df49431d23618sewardj                        binop( Iop_Or32,
144554aa412af1d8166cc11f39a6e721df49431d23618sewardj                               binop( Iop_And32,
144564aa412af1d8166cc11f39a6e721df49431d23618sewardj                                      unop(Iop_64to32, mkexpr( a0_I64 ) ),
144574aa412af1d8166cc11f39a6e721df49431d23618sewardj                                      mkU32( SIGN_BIT32 ) ),
144584aa412af1d8166cc11f39a6e721df49431d23618sewardj                               binop( Iop_And32,
144594aa412af1d8166cc11f39a6e721df49431d23618sewardj                                      unop(Iop_64to32, mkexpr( b0_I64 ) ),
144604aa412af1d8166cc11f39a6e721df49431d23618sewardj                                      mkU32( SIGN_MASK32 ) ) ) ) );
144614aa412af1d8166cc11f39a6e721df49431d23618sewardj         putVSReg( XT, binop( Iop_64HLtoV128, mkexpr( resHi ), mkexpr( resLo ) ) );
144624aa412af1d8166cc11f39a6e721df49431d23618sewardj         break;
144634aa412af1d8166cc11f39a6e721df49431d23618sewardj      }
14464e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj      case 0x3B2: // xvabsdp (VSX Vector Absolute Value Double-Precision)
14465e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj      case 0x3D2: // xvnabsdp VSX Vector Negative Absolute Value Double-Precision)
14466e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj      {
14467e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj         IRTemp frB = newTemp(Ity_F64);
14468e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj         IRTemp frB2 = newTemp(Ity_F64);
14469e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj         IRTemp abs_resultHi = newTemp(Ity_F64);
14470e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj         IRTemp abs_resultLo = newTemp(Ity_F64);
14471e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj         Bool make_negative = (opc2 == 0x3D2) ? True : False;
14472e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj         assign(frB,  unop(Iop_ReinterpI64asF64, unop(Iop_V128HIto64, getVSReg( XB ))));
14473e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj         assign(frB2, unop(Iop_ReinterpI64asF64, unop(Iop_V128to64, getVSReg(XB))));
14474e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj
14475b173774421d015736c2316b5e6e998e7de545a5cflorian         DIP("xv%sabsdp v%d,v%d\n", make_negative ? "n" : "", XT, XB);
14476e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj         if (make_negative) {
14477e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj            assign(abs_resultHi, unop( Iop_NegF64, unop( Iop_AbsF64, mkexpr( frB ) ) ) );
14478e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj            assign(abs_resultLo, unop( Iop_NegF64, unop( Iop_AbsF64, mkexpr( frB2 ) ) ) );
14479e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj
14480e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj         } else {
14481e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj            assign(abs_resultHi, unop( Iop_AbsF64, mkexpr( frB ) ) );
14482e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj            assign(abs_resultLo, unop( Iop_AbsF64, mkexpr( frB2 ) ) );
14483e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj         }
14484e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj         putVSReg( XT, binop( Iop_64HLtoV128,
14485e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj                              unop( Iop_ReinterpF64asI64, mkexpr( abs_resultHi ) ),
14486e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj                              unop( Iop_ReinterpF64asI64, mkexpr( abs_resultLo ) ) ) );
14487e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj         break;
14488e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj      }
14489e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj      case 0x332: // xvabssp (VSX Vector Absolute Value Single-Precision)
14490e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj      case 0x352: // xvnabssp (VSX Vector Negative Absolute Value Single-Precision)
14491e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj      {
14492e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj         /*
14493e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj          * The Iop_AbsF32 IRop is not implemented for ppc64 since, up until introduction
14494e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj          * of xvabssp, there has not been an abs(sp) type of instruction.  But since emulation
14495e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj          * of this function is so easy using shifts, I choose to emulate this instruction that
14496e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj          * way versus a native instruction method of implementation.
14497e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj          */
14498e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj         Bool make_negative = (opc2 == 0x352) ? True : False;
14499e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj         IRTemp shiftVector = newTemp(Ity_V128);
14500e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj         IRTemp absVal_vector = newTemp(Ity_V128);
14501e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj         assign( shiftVector,
14502e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj                 binop( Iop_64HLtoV128,
14503e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj                        binop( Iop_32HLto64, mkU32( 1 ), mkU32( 1 ) ),
14504e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj                        binop( Iop_32HLto64, mkU32( 1 ), mkU32( 1 ) ) ) );
14505e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj         assign( absVal_vector,
14506e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj                   binop( Iop_Shr32x4,
14507e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj                          binop( Iop_Shl32x4,
14508e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj                                 getVSReg( XB ),
14509e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj                                 mkexpr( shiftVector ) ),
14510e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj                          mkexpr( shiftVector ) ) );
14511e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj         if (make_negative) {
14512e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj            IRTemp signBit_vector = newTemp(Ity_V128);
14513e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj            assign( signBit_vector,
14514e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj                    binop( Iop_64HLtoV128,
14515e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj                           binop( Iop_32HLto64,
14516e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj                                  mkU32( 0x80000000 ),
14517e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj                                  mkU32( 0x80000000 ) ),
14518e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj                           binop( Iop_32HLto64,
14519e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj                                  mkU32( 0x80000000 ),
14520e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj                                  mkU32( 0x80000000 ) ) ) );
14521e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj            putVSReg( XT,
14522e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj                      binop( Iop_OrV128,
14523e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj                             mkexpr( absVal_vector ),
14524e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj                             mkexpr( signBit_vector ) ) );
14525e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj         } else {
14526e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj            putVSReg( XT, mkexpr( absVal_vector ) );
14527e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj         }
14528e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj         break;
14529e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj      }
14530e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj      case 0x3F2: // xvnegdp (VSX Vector Negate Double-Precision)
14531e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj      {
14532e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj         IRTemp frB = newTemp(Ity_F64);
14533e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj         IRTemp frB2 = newTemp(Ity_F64);
14534e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj         assign(frB,  unop(Iop_ReinterpI64asF64, unop(Iop_V128HIto64, getVSReg( XB ))));
14535e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj         assign(frB2, unop(Iop_ReinterpI64asF64, unop(Iop_V128to64, getVSReg(XB))));
14536b173774421d015736c2316b5e6e998e7de545a5cflorian         DIP("xvnegdp v%d,v%d\n",  XT, XB);
14537e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj         putVSReg( XT,
14538e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj                   binop( Iop_64HLtoV128,
14539e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj                          unop( Iop_ReinterpF64asI64,
14540e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj                                unop( Iop_NegF64, mkexpr( frB ) ) ),
14541e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj                          unop( Iop_ReinterpF64asI64,
14542e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj                                unop( Iop_NegF64, mkexpr( frB2 ) ) ) ) );
14543e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj         break;
14544e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj      }
14545e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj      case 0x192: // xvrdpi  (VSX Vector Round to Double-Precision Integer using round toward Nearest Away)
14546e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj      case 0x1D6: // xvrdpic (VSX Vector Round to Double-Precision Integer using Current rounding mode)
14547e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj      case 0x1F2: // xvrdpim (VSX Vector Round to Double-Precision Integer using round toward -Infinity)
14548e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj      case 0x1D2: // xvrdpip (VSX Vector Round to Double-Precision Integer using round toward +Infinity)
14549e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj      case 0x1B2: // xvrdpiz (VSX Vector Round to Double-Precision Integer using round toward Zero)
14550e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj      {
14551e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj         IRTemp frBHi_I64 = newTemp(Ity_I64);
14552e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj         IRTemp frBLo_I64 = newTemp(Ity_I64);
14553e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj         IRExpr * frD_fp_roundHi = NULL;
14554e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj         IRExpr * frD_fp_roundLo = NULL;
14555e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj
14556e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj         assign( frBHi_I64, unop( Iop_V128HIto64, getVSReg( XB ) ) );
145579884af0b3cfe935b8fab54231f394fe4ee2d7ebccarll         frD_fp_roundHi = _do_vsx_fp_roundToInt(frBHi_I64, opc2);
14558e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj         assign( frBLo_I64, unop( Iop_V128to64, getVSReg( XB ) ) );
145599884af0b3cfe935b8fab54231f394fe4ee2d7ebccarll         frD_fp_roundLo = _do_vsx_fp_roundToInt(frBLo_I64, opc2);
14560e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj
14561b173774421d015736c2316b5e6e998e7de545a5cflorian         DIP("xvrdpi%s v%d,v%d\n", _get_vsx_rdpi_suffix(opc2), XT, XB);
14562e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj         putVSReg( XT,
14563e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj                   binop( Iop_64HLtoV128,
14564e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj                          unop( Iop_ReinterpF64asI64, frD_fp_roundHi ),
14565e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj                          unop( Iop_ReinterpF64asI64, frD_fp_roundLo ) ) );
14566e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj         break;
14567e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj      }
14568e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj      case 0x112: // xvrspi  (VSX Vector Round to Single-Precision Integer using round toward Nearest Away)
14569e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj      case 0x156: // xvrspic (VSX Vector Round to SinglePrecision Integer using Current rounding mode)
14570e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj      case 0x172: // xvrspim (VSX Vector Round to SinglePrecision Integer using round toward -Infinity)
14571e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj      case 0x152: // xvrspip (VSX Vector Round to SinglePrecision Integer using round toward +Infinity)
14572e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj      case 0x132: // xvrspiz (VSX Vector Round to SinglePrecision Integer using round toward Zero)
14573e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj      {
1457455085f8680acc89d727e321f3b34cae1a8c4093aflorian         const HChar * insn_suffix = NULL;
14575e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj         IROp op;
14576e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj         if (opc2 != 0x156) {
14577e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj            // Use pre-defined IRop's for vrfi{m|n|p|z}
14578e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj            switch (opc2) {
14579e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj               case 0x112:
14580e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj                  insn_suffix = "";
14581e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj                  op = Iop_RoundF32x4_RN;
14582e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj                  break;
14583e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj               case 0x172:
14584e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj                  insn_suffix = "m";
14585e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj                  op = Iop_RoundF32x4_RM;
14586e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj                  break;
14587e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj               case 0x152:
14588e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj                  insn_suffix = "p";
14589e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj                  op = Iop_RoundF32x4_RP;
14590e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj                  break;
14591e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj               case 0x132:
14592e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj                  insn_suffix = "z";
14593e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj                  op = Iop_RoundF32x4_RZ;
14594e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj                  break;
14595e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj
14596e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj               default:
145979884af0b3cfe935b8fab54231f394fe4ee2d7ebccarll                  vex_printf("Unrecognized opcode %x\n", opc2);
145989884af0b3cfe935b8fab54231f394fe4ee2d7ebccarll                  vpanic("dis_vxv_misc(ppc)(vrspi<x>)(opc2)\n");
14599e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj            }
14600b173774421d015736c2316b5e6e998e7de545a5cflorian            DIP("xvrspi%s v%d,v%d\n", insn_suffix, XT, XB);
14601e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj            putVSReg( XT, unop( op, getVSReg(XB) ) );
14602e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj         } else {
14603e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj            // Handle xvrspic.  Unfortunately there is no corresponding "vfric" instruction.
14604e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj            IRExpr * frD_fp_roundb3, * frD_fp_roundb2, * frD_fp_roundb1, * frD_fp_roundb0;
14605e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj            IRTemp b3_F64, b2_F64, b1_F64, b0_F64;
14606e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj            IRTemp b3_I64 = newTemp(Ity_I64);
14607e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj            IRTemp b2_I64 = newTemp(Ity_I64);
14608e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj            IRTemp b1_I64 = newTemp(Ity_I64);
14609e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj            IRTemp b0_I64 = newTemp(Ity_I64);
14610e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj
14611e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj            b3_F64 = b2_F64 = b1_F64 = b0_F64 = IRTemp_INVALID;
14612e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj            frD_fp_roundb3 = frD_fp_roundb2 = frD_fp_roundb1 = frD_fp_roundb0 = NULL;
14613e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj            breakV128to4xF64( getVSReg(XB), &b3_F64, &b2_F64, &b1_F64, &b0_F64);
14614e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj            assign(b3_I64, unop(Iop_ReinterpF64asI64, mkexpr(b3_F64)));
14615e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj            assign(b2_I64, unop(Iop_ReinterpF64asI64, mkexpr(b2_F64)));
14616e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj            assign(b1_I64, unop(Iop_ReinterpF64asI64, mkexpr(b1_F64)));
14617e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj            assign(b0_I64, unop(Iop_ReinterpF64asI64, mkexpr(b0_F64)));
14618e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj            frD_fp_roundb3 = unop(Iop_TruncF64asF32,
146199884af0b3cfe935b8fab54231f394fe4ee2d7ebccarll                                  _do_vsx_fp_roundToInt(b3_I64, opc2));
14620e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj            frD_fp_roundb2 = unop(Iop_TruncF64asF32,
146219884af0b3cfe935b8fab54231f394fe4ee2d7ebccarll                                  _do_vsx_fp_roundToInt(b2_I64, opc2));
14622e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj            frD_fp_roundb1 = unop(Iop_TruncF64asF32,
146239884af0b3cfe935b8fab54231f394fe4ee2d7ebccarll                                  _do_vsx_fp_roundToInt(b1_I64, opc2));
14624e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj            frD_fp_roundb0 = unop(Iop_TruncF64asF32,
146259884af0b3cfe935b8fab54231f394fe4ee2d7ebccarll                                  _do_vsx_fp_roundToInt(b0_I64, opc2));
14626b173774421d015736c2316b5e6e998e7de545a5cflorian            DIP("xvrspic v%d,v%d\n", XT, XB);
14627e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj            putVSReg( XT,
14628e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj                      binop( Iop_64HLtoV128,
14629e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj                             binop( Iop_32HLto64,
14630e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj                                    unop( Iop_ReinterpF32asI32, frD_fp_roundb3 ),
14631e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj                                    unop( Iop_ReinterpF32asI32, frD_fp_roundb2 ) ),
14632e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj                             binop( Iop_32HLto64,
14633e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj                                    unop( Iop_ReinterpF32asI32, frD_fp_roundb1 ),
14634e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj                                    unop( Iop_ReinterpF32asI32, frD_fp_roundb0 ) ) ) );
14635e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj         }
14636e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj         break;
14637e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj      }
146384aa412af1d8166cc11f39a6e721df49431d23618sewardj
146394aa412af1d8166cc11f39a6e721df49431d23618sewardj      default:
146404aa412af1d8166cc11f39a6e721df49431d23618sewardj         vex_printf( "dis_vxv_misc(ppc)(opc2)\n" );
146414aa412af1d8166cc11f39a6e721df49431d23618sewardj         return False;
146424aa412af1d8166cc11f39a6e721df49431d23618sewardj   }
146434aa412af1d8166cc11f39a6e721df49431d23618sewardj   return True;
146444aa412af1d8166cc11f39a6e721df49431d23618sewardj}
146454aa412af1d8166cc11f39a6e721df49431d23618sewardj
146464aa412af1d8166cc11f39a6e721df49431d23618sewardj
146474aa412af1d8166cc11f39a6e721df49431d23618sewardj/*
1464866d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj * VSX Scalar Floating Point Arithmetic Instructions
1464966d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj */
1465066d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardjstatic Bool
146514aa412af1d8166cc11f39a6e721df49431d23618sewardjdis_vxs_arith ( UInt theInstr, UInt opc2 )
1465266d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj{
1465366d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj   /* XX3-Form */
1465466d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj   UChar opc1 = ifieldOPC( theInstr );
1465566d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj   UChar XT = ifieldRegXT( theInstr );
1465666d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj   UChar XA = ifieldRegXA( theInstr );
1465766d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj   UChar XB = ifieldRegXB( theInstr );
1465866d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj   IRExpr* rm = get_IR_roundingmode();
1465966d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj   IRTemp frA = newTemp(Ity_F64);
1466066d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj   IRTemp frB = newTemp(Ity_F64);
1466166d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj
1466266d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj   if (opc1 != 0x3C) {
146634aa412af1d8166cc11f39a6e721df49431d23618sewardj      vex_printf( "dis_vxs_arith(ppc)(instr)\n" );
1466466d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj      return False;
1466566d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj   }
1466666d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj
1466766d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj   assign(frA, unop(Iop_ReinterpI64asF64, unop(Iop_V128HIto64, getVSReg( XA ))));
1466866d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj   assign(frB, unop(Iop_ReinterpI64asF64, unop(Iop_V128HIto64, getVSReg( XB ))));
1466966d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj
1467066d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj   /* For all the VSX sclar arithmetic instructions, the contents of doubleword element 1
1467166d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj    * of VSX[XT] are undefined after the operation; therefore, we can simply set
1467266d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj    * element to zero where it makes sense to do so.
1467366d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj    */
1467466d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj   switch (opc2) {
146756c758b64a77c254065ab7450576bbd3a0b583595carll      case 0x000: // xsaddsp  (VSX Scalar Add Single-Precision)
14676b173774421d015736c2316b5e6e998e7de545a5cflorian         DIP("xsaddsp v%d,v%d,v%d\n", XT, XA, XB);
146776c758b64a77c254065ab7450576bbd3a0b583595carll         putVSReg( XT, binop( Iop_64HLtoV128,
146786c758b64a77c254065ab7450576bbd3a0b583595carll                              unop( Iop_ReinterpF64asI64,
146796c758b64a77c254065ab7450576bbd3a0b583595carll                                    binop( Iop_RoundF64toF32, rm,
146806c758b64a77c254065ab7450576bbd3a0b583595carll                                           triop( Iop_AddF64, rm,
146816c758b64a77c254065ab7450576bbd3a0b583595carll                                                  mkexpr( frA ),
146826c758b64a77c254065ab7450576bbd3a0b583595carll                                                  mkexpr( frB ) ) ) ),
146836c758b64a77c254065ab7450576bbd3a0b583595carll                              mkU64( 0 ) ) );
146846c758b64a77c254065ab7450576bbd3a0b583595carll         break;
146856c758b64a77c254065ab7450576bbd3a0b583595carll      case 0x020: // xssubsp  (VSX Scalar Subtract Single-Precision)
14686b173774421d015736c2316b5e6e998e7de545a5cflorian         DIP("xssubsp v%d,v%d,v%d\n", XT, XA, XB);
146876c758b64a77c254065ab7450576bbd3a0b583595carll         putVSReg( XT, binop( Iop_64HLtoV128,
146886c758b64a77c254065ab7450576bbd3a0b583595carll                              unop( Iop_ReinterpF64asI64,
146896c758b64a77c254065ab7450576bbd3a0b583595carll                                    binop( Iop_RoundF64toF32, rm,
146906c758b64a77c254065ab7450576bbd3a0b583595carll                                           triop( Iop_SubF64, rm,
146916c758b64a77c254065ab7450576bbd3a0b583595carll                                                  mkexpr( frA ),
146926c758b64a77c254065ab7450576bbd3a0b583595carll                                                  mkexpr( frB ) ) ) ),
146936c758b64a77c254065ab7450576bbd3a0b583595carll                              mkU64( 0 ) ) );
146946c758b64a77c254065ab7450576bbd3a0b583595carll         break;
1469566d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj      case 0x080: // xsadddp (VSX scalar add double-precision)
14696b173774421d015736c2316b5e6e998e7de545a5cflorian         DIP("xsadddp v%d,v%d,v%d\n", XT, XA, XB);
1469766d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj         putVSReg( XT, binop( Iop_64HLtoV128, unop( Iop_ReinterpF64asI64,
1469866d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj                                                    triop( Iop_AddF64, rm,
1469966d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj                                                           mkexpr( frA ),
1470066d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj                                                           mkexpr( frB ) ) ),
1470166d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj                              mkU64( 0 ) ) );
1470266d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj         break;
147036c758b64a77c254065ab7450576bbd3a0b583595carll      case 0x060: // xsdivsp (VSX scalar divide single-precision)
14704b173774421d015736c2316b5e6e998e7de545a5cflorian         DIP("xsdivsp v%d,v%d,v%d\n", XT, XA, XB);
147056c758b64a77c254065ab7450576bbd3a0b583595carll         putVSReg( XT, binop( Iop_64HLtoV128,
147066c758b64a77c254065ab7450576bbd3a0b583595carll                              unop( Iop_ReinterpF64asI64,
147076c758b64a77c254065ab7450576bbd3a0b583595carll                                    binop( Iop_RoundF64toF32, rm,
147086c758b64a77c254065ab7450576bbd3a0b583595carll                                           triop( Iop_DivF64, rm,
147096c758b64a77c254065ab7450576bbd3a0b583595carll                                                  mkexpr( frA ),
147106c758b64a77c254065ab7450576bbd3a0b583595carll                                                  mkexpr( frB ) ) ) ),
147116c758b64a77c254065ab7450576bbd3a0b583595carll                               mkU64( 0 ) ) );
147126c758b64a77c254065ab7450576bbd3a0b583595carll         break;
1471366d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj      case 0x0E0: // xsdivdp (VSX scalar divide double-precision)
14714b173774421d015736c2316b5e6e998e7de545a5cflorian         DIP("xsdivdp v%d,v%d,v%d\n", XT, XA, XB);
1471566d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj         putVSReg( XT, binop( Iop_64HLtoV128, unop( Iop_ReinterpF64asI64,
1471666d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj                                                    triop( Iop_DivF64, rm,
1471766d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj                                                           mkexpr( frA ),
1471866d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj                                                           mkexpr( frB ) ) ),
1471966d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj                              mkU64( 0 ) ) );
1472066d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj         break;
147216c758b64a77c254065ab7450576bbd3a0b583595carll      case 0x004: case 0x024: /* xsmaddasp, xsmaddmsp (VSX scalar multiply-add
147226c758b64a77c254065ab7450576bbd3a0b583595carll                               * single-precision)
147236c758b64a77c254065ab7450576bbd3a0b583595carll                               */
147246c758b64a77c254065ab7450576bbd3a0b583595carll      {
147256c758b64a77c254065ab7450576bbd3a0b583595carll         IRTemp frT = newTemp(Ity_F64);
147266c758b64a77c254065ab7450576bbd3a0b583595carll         Bool mdp = opc2 == 0x024;
14727b173774421d015736c2316b5e6e998e7de545a5cflorian         DIP("xsmadd%ssp v%d,v%d,v%d\n", mdp ? "m" : "a", XT, XA, XB);
147286c758b64a77c254065ab7450576bbd3a0b583595carll         assign( frT, unop( Iop_ReinterpI64asF64, unop( Iop_V128HIto64,
147296c758b64a77c254065ab7450576bbd3a0b583595carll                                                        getVSReg( XT ) ) ) );
147306c758b64a77c254065ab7450576bbd3a0b583595carll         putVSReg( XT,
147316c758b64a77c254065ab7450576bbd3a0b583595carll                   binop( Iop_64HLtoV128,
147326c758b64a77c254065ab7450576bbd3a0b583595carll                          unop( Iop_ReinterpF64asI64,
147336c758b64a77c254065ab7450576bbd3a0b583595carll                                binop( Iop_RoundF64toF32, rm,
147346c758b64a77c254065ab7450576bbd3a0b583595carll                                       qop( Iop_MAddF64, rm,
147356c758b64a77c254065ab7450576bbd3a0b583595carll                                            mkexpr( frA ),
147366c758b64a77c254065ab7450576bbd3a0b583595carll                                            mkexpr( mdp ? frT : frB ),
147376c758b64a77c254065ab7450576bbd3a0b583595carll                                            mkexpr( mdp ? frB : frT ) ) ) ),
147386c758b64a77c254065ab7450576bbd3a0b583595carll                          mkU64( 0 ) ) );
147396c758b64a77c254065ab7450576bbd3a0b583595carll         break;
147406c758b64a77c254065ab7450576bbd3a0b583595carll      }
1474166d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj      case 0x084: case 0x0A4: // xsmaddadp, xsmaddmdp (VSX scalar multiply-add double-precision)
1474266d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj      {
1474366d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj         IRTemp frT = newTemp(Ity_F64);
1474466d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj         Bool mdp = opc2 == 0x0A4;
14745b173774421d015736c2316b5e6e998e7de545a5cflorian         DIP("xsmadd%sdp v%d,v%d,v%d\n", mdp ? "m" : "a", XT, XA, XB);
1474666d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj         assign( frT, unop( Iop_ReinterpI64asF64, unop( Iop_V128HIto64,
1474766d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj                                                        getVSReg( XT ) ) ) );
1474866d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj         putVSReg( XT, binop( Iop_64HLtoV128, unop( Iop_ReinterpF64asI64,
1474966d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj                                                    qop( Iop_MAddF64, rm,
1475066d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj                                                         mkexpr( frA ),
1475166d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj                                                         mkexpr( mdp ? frT : frB ),
1475266d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj                                                         mkexpr( mdp ? frB : frT ) ) ),
1475366d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj                              mkU64( 0 ) ) );
1475466d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj         break;
1475566d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj      }
147566c758b64a77c254065ab7450576bbd3a0b583595carll      case 0x044: case 0x064: /* xsmsubasp, xsmsubmsp (VSX scalar
147576c758b64a77c254065ab7450576bbd3a0b583595carll                               * multiply-subtract single-precision)
147586c758b64a77c254065ab7450576bbd3a0b583595carll			       */
147596c758b64a77c254065ab7450576bbd3a0b583595carll      {
147606c758b64a77c254065ab7450576bbd3a0b583595carll         IRTemp frT = newTemp(Ity_F64);
147616c758b64a77c254065ab7450576bbd3a0b583595carll         Bool mdp = opc2 == 0x064;
14762b173774421d015736c2316b5e6e998e7de545a5cflorian         DIP("xsmsub%ssp v%d,v%d,v%d\n", mdp ? "m" : "a", XT, XA, XB);
147636c758b64a77c254065ab7450576bbd3a0b583595carll         assign( frT, unop( Iop_ReinterpI64asF64, unop( Iop_V128HIto64,
147646c758b64a77c254065ab7450576bbd3a0b583595carll                                                        getVSReg( XT ) ) ) );
147656c758b64a77c254065ab7450576bbd3a0b583595carll         putVSReg( XT,
147666c758b64a77c254065ab7450576bbd3a0b583595carll                   binop( Iop_64HLtoV128,
147676c758b64a77c254065ab7450576bbd3a0b583595carll                          unop( Iop_ReinterpF64asI64,
147686c758b64a77c254065ab7450576bbd3a0b583595carll                                binop( Iop_RoundF64toF32, rm,
147696c758b64a77c254065ab7450576bbd3a0b583595carll                                       qop( Iop_MSubF64, rm,
147706c758b64a77c254065ab7450576bbd3a0b583595carll                                            mkexpr( frA ),
147716c758b64a77c254065ab7450576bbd3a0b583595carll                                            mkexpr( mdp ? frT : frB ),
147726c758b64a77c254065ab7450576bbd3a0b583595carll                                            mkexpr( mdp ? frB : frT ) ) ) ),
147736c758b64a77c254065ab7450576bbd3a0b583595carll                          mkU64( 0 ) ) );
147746c758b64a77c254065ab7450576bbd3a0b583595carll         break;
147756c758b64a77c254065ab7450576bbd3a0b583595carll      }
1477666d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj      case 0x0C4: case 0x0E4: // xsmsubadp, xsmsubmdp (VSX scalar multiply-subtract double-precision)
1477766d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj      {
1477866d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj         IRTemp frT = newTemp(Ity_F64);
1477966d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj         Bool mdp = opc2 == 0x0E4;
14780b173774421d015736c2316b5e6e998e7de545a5cflorian         DIP("xsmsub%sdp v%d,v%d,v%d\n", mdp ? "m" : "a", XT, XA, XB);
1478166d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj         assign( frT, unop( Iop_ReinterpI64asF64, unop( Iop_V128HIto64,
1478266d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj                                                        getVSReg( XT ) ) ) );
1478366d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj         putVSReg( XT, binop( Iop_64HLtoV128, unop( Iop_ReinterpF64asI64,
1478466d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj                                                    qop( Iop_MSubF64, rm,
1478566d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj                                                         mkexpr( frA ),
1478666d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj                                                         mkexpr( mdp ? frT : frB ),
1478766d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj                                                         mkexpr( mdp ? frB : frT ) ) ),
1478866d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj                              mkU64( 0 ) ) );
1478966d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj         break;
1479066d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj      }
1479166d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj      case 0x284: case 0x2A4: // xsnmaddadp, xsnmaddmdp (VSX scalar multiply-add double-precision)
1479266d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj      {
1479366d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj         /* TODO: mpj -- Naturally, I expected to be able to leverage the implementation
1479466d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj          * of fnmadd and use pretty much the same code. However, that code has a bug in the
1479566d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj          * way it blindly negates the signbit, even if the floating point result is a NaN.
1479666d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj          * So, the TODO is to fix fnmadd (which I'll do in a different patch).
147972bcdd653612c726da0b7203b579b8f6114703be4sewardj          * FIXED 7/1/2012: carll fnmadd and fnmsubs fixed to not negate sign
147982bcdd653612c726da0b7203b579b8f6114703be4sewardj          * bit for NaN result.
1479966d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj          */
1480066d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj         Bool mdp = opc2 == 0x2A4;
1480166d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj         IRTemp frT = newTemp(Ity_F64);
1480266d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj         IRTemp maddResult = newTemp(Ity_I64);
1480366d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj
14804b173774421d015736c2316b5e6e998e7de545a5cflorian         DIP("xsnmadd%sdp v%d,v%d,v%d\n", mdp ? "m" : "a", XT, XA, XB);
1480566d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj         assign( frT, unop( Iop_ReinterpI64asF64, unop( Iop_V128HIto64,
1480666d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj                                                        getVSReg( XT ) ) ) );
1480766d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj         assign( maddResult, unop( Iop_ReinterpF64asI64, qop( Iop_MAddF64, rm,
1480866d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj                                                              mkexpr( frA ),
1480966d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj                                                              mkexpr( mdp ? frT : frB ),
1481066d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj                                                              mkexpr( mdp ? frB : frT ) ) ) );
148114aa412af1d8166cc11f39a6e721df49431d23618sewardj
148124aa412af1d8166cc11f39a6e721df49431d23618sewardj         putVSReg( XT, binop( Iop_64HLtoV128, mkexpr( getNegatedResult(maddResult) ),
1481366d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj                              mkU64( 0 ) ) );
1481466d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj         break;
1481566d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj      }
148166c758b64a77c254065ab7450576bbd3a0b583595carll      case 0x204: case 0x224: /* xsnmaddasp, xsnmaddmsp (VSX scalar
148176c758b64a77c254065ab7450576bbd3a0b583595carll                               * multiply-add single-precision)
148186c758b64a77c254065ab7450576bbd3a0b583595carll                               */
148196c758b64a77c254065ab7450576bbd3a0b583595carll      {
148206c758b64a77c254065ab7450576bbd3a0b583595carll         Bool mdp = opc2 == 0x224;
148216c758b64a77c254065ab7450576bbd3a0b583595carll         IRTemp frT = newTemp(Ity_F64);
148226c758b64a77c254065ab7450576bbd3a0b583595carll         IRTemp maddResult = newTemp(Ity_I64);
148236c758b64a77c254065ab7450576bbd3a0b583595carll
14824b173774421d015736c2316b5e6e998e7de545a5cflorian         DIP("xsnmadd%ssp v%d,v%d,v%d\n", mdp ? "m" : "a", XT, XA, XB);
148256c758b64a77c254065ab7450576bbd3a0b583595carll         assign( frT, unop( Iop_ReinterpI64asF64, unop( Iop_V128HIto64,
148266c758b64a77c254065ab7450576bbd3a0b583595carll                                                        getVSReg( XT ) ) ) );
148276c758b64a77c254065ab7450576bbd3a0b583595carll         assign( maddResult,
148286c758b64a77c254065ab7450576bbd3a0b583595carll                 unop( Iop_ReinterpF64asI64,
148296c758b64a77c254065ab7450576bbd3a0b583595carll                       binop( Iop_RoundF64toF32, rm,
148306c758b64a77c254065ab7450576bbd3a0b583595carll                              qop( Iop_MAddF64, rm,
148316c758b64a77c254065ab7450576bbd3a0b583595carll                                   mkexpr( frA ),
148326c758b64a77c254065ab7450576bbd3a0b583595carll                                   mkexpr( mdp ? frT : frB ),
148336c758b64a77c254065ab7450576bbd3a0b583595carll                                   mkexpr( mdp ? frB : frT ) ) ) ) );
148346c758b64a77c254065ab7450576bbd3a0b583595carll
148356c758b64a77c254065ab7450576bbd3a0b583595carll         putVSReg( XT, binop( Iop_64HLtoV128,
148366c758b64a77c254065ab7450576bbd3a0b583595carll                              mkexpr( getNegatedResult(maddResult) ),
148376c758b64a77c254065ab7450576bbd3a0b583595carll                              mkU64( 0 ) ) );
148386c758b64a77c254065ab7450576bbd3a0b583595carll         break;
148396c758b64a77c254065ab7450576bbd3a0b583595carll      }
148406c758b64a77c254065ab7450576bbd3a0b583595carll      case 0x244: case 0x264: /* xsnmsubasp, xsnmsubmsp (VSX Scalar Negative
148416c758b64a77c254065ab7450576bbd3a0b583595carll                               * Multiply-Subtract Single-Precision)
148426c758b64a77c254065ab7450576bbd3a0b583595carll                               */
148436c758b64a77c254065ab7450576bbd3a0b583595carll      {
148446c758b64a77c254065ab7450576bbd3a0b583595carll         IRTemp frT = newTemp(Ity_F64);
148456c758b64a77c254065ab7450576bbd3a0b583595carll         Bool mdp = opc2 == 0x264;
148466c758b64a77c254065ab7450576bbd3a0b583595carll         IRTemp msubResult = newTemp(Ity_I64);
148476c758b64a77c254065ab7450576bbd3a0b583595carll
14848b173774421d015736c2316b5e6e998e7de545a5cflorian         DIP("xsnmsub%ssp v%d,v%d,v%d\n", mdp ? "m" : "a", XT, XA, XB);
148496c758b64a77c254065ab7450576bbd3a0b583595carll         assign( frT, unop( Iop_ReinterpI64asF64, unop( Iop_V128HIto64,
148506c758b64a77c254065ab7450576bbd3a0b583595carll                                                        getVSReg( XT ) ) ) );
148516c758b64a77c254065ab7450576bbd3a0b583595carll         assign( msubResult,
148526c758b64a77c254065ab7450576bbd3a0b583595carll                 unop( Iop_ReinterpF64asI64,
148536c758b64a77c254065ab7450576bbd3a0b583595carll                       binop( Iop_RoundF64toF32, rm,
148546c758b64a77c254065ab7450576bbd3a0b583595carll                              qop( Iop_MSubF64, rm,
148556c758b64a77c254065ab7450576bbd3a0b583595carll                                   mkexpr( frA ),
148566c758b64a77c254065ab7450576bbd3a0b583595carll                                   mkexpr( mdp ? frT : frB ),
148576c758b64a77c254065ab7450576bbd3a0b583595carll                                   mkexpr( mdp ? frB : frT ) ) ) ) );
148586c758b64a77c254065ab7450576bbd3a0b583595carll
148596c758b64a77c254065ab7450576bbd3a0b583595carll         putVSReg( XT, binop( Iop_64HLtoV128,
148606c758b64a77c254065ab7450576bbd3a0b583595carll                              mkexpr( getNegatedResult(msubResult) ),
148616c758b64a77c254065ab7450576bbd3a0b583595carll                              mkU64( 0 ) ) );
148626c758b64a77c254065ab7450576bbd3a0b583595carll
148636c758b64a77c254065ab7450576bbd3a0b583595carll         break;
148646c758b64a77c254065ab7450576bbd3a0b583595carll      }
148656c758b64a77c254065ab7450576bbd3a0b583595carll
148664aa412af1d8166cc11f39a6e721df49431d23618sewardj      case 0x2C4: case 0x2E4: // xsnmsubadp, xsnmsubmdp (VSX Scalar Negative Multiply-Subtract Double-Precision)
148674aa412af1d8166cc11f39a6e721df49431d23618sewardj      {
148684aa412af1d8166cc11f39a6e721df49431d23618sewardj         IRTemp frT = newTemp(Ity_F64);
148694aa412af1d8166cc11f39a6e721df49431d23618sewardj         Bool mdp = opc2 == 0x2E4;
148704aa412af1d8166cc11f39a6e721df49431d23618sewardj         IRTemp msubResult = newTemp(Ity_I64);
148714aa412af1d8166cc11f39a6e721df49431d23618sewardj
14872b173774421d015736c2316b5e6e998e7de545a5cflorian         DIP("xsnmsub%sdp v%d,v%d,v%d\n", mdp ? "m" : "a", XT, XA, XB);
148734aa412af1d8166cc11f39a6e721df49431d23618sewardj         assign( frT, unop( Iop_ReinterpI64asF64, unop( Iop_V128HIto64,
148744aa412af1d8166cc11f39a6e721df49431d23618sewardj                                                        getVSReg( XT ) ) ) );
148754aa412af1d8166cc11f39a6e721df49431d23618sewardj         assign(msubResult, unop( Iop_ReinterpF64asI64,
148764aa412af1d8166cc11f39a6e721df49431d23618sewardj                                      qop( Iop_MSubF64,
148774aa412af1d8166cc11f39a6e721df49431d23618sewardj                                           rm,
148784aa412af1d8166cc11f39a6e721df49431d23618sewardj                                           mkexpr( frA ),
148794aa412af1d8166cc11f39a6e721df49431d23618sewardj                                           mkexpr( mdp ? frT : frB ),
148804aa412af1d8166cc11f39a6e721df49431d23618sewardj                                           mkexpr( mdp ? frB : frT ) ) ));
148814aa412af1d8166cc11f39a6e721df49431d23618sewardj
148824aa412af1d8166cc11f39a6e721df49431d23618sewardj         putVSReg( XT, binop( Iop_64HLtoV128, mkexpr( getNegatedResult(msubResult) ), mkU64( 0 ) ) );
148834aa412af1d8166cc11f39a6e721df49431d23618sewardj
148844aa412af1d8166cc11f39a6e721df49431d23618sewardj         break;
148854aa412af1d8166cc11f39a6e721df49431d23618sewardj      }
148864aa412af1d8166cc11f39a6e721df49431d23618sewardj
148876c758b64a77c254065ab7450576bbd3a0b583595carll      case 0x040: // xsmulsp (VSX Scalar Multiply Single-Precision)
14888b173774421d015736c2316b5e6e998e7de545a5cflorian         DIP("xsmulsp v%d,v%d,v%d\n", XT, XA, XB);
148896c758b64a77c254065ab7450576bbd3a0b583595carll         putVSReg( XT, binop( Iop_64HLtoV128,
148906c758b64a77c254065ab7450576bbd3a0b583595carll                              unop( Iop_ReinterpF64asI64,
148916c758b64a77c254065ab7450576bbd3a0b583595carll                                    binop( Iop_RoundF64toF32, rm,
148926c758b64a77c254065ab7450576bbd3a0b583595carll                                           triop( Iop_MulF64, rm,
148936c758b64a77c254065ab7450576bbd3a0b583595carll                                                   mkexpr( frA ),
148946c758b64a77c254065ab7450576bbd3a0b583595carll                                                   mkexpr( frB ) ) ) ),
148956c758b64a77c254065ab7450576bbd3a0b583595carll                              mkU64( 0 ) ) );
148966c758b64a77c254065ab7450576bbd3a0b583595carll         break;
148976c758b64a77c254065ab7450576bbd3a0b583595carll
1489866d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj      case 0x0C0: // xsmuldp (VSX Scalar Multiply Double-Precision)
14899b173774421d015736c2316b5e6e998e7de545a5cflorian         DIP("xsmuldp v%d,v%d,v%d\n", XT, XA, XB);
1490066d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj         putVSReg( XT, binop( Iop_64HLtoV128, unop( Iop_ReinterpF64asI64,
1490166d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj                                                    triop( Iop_MulF64, rm,
1490266d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj                                                           mkexpr( frA ),
1490366d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj                                                           mkexpr( frB ) ) ),
1490466d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj                              mkU64( 0 ) ) );
1490566d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj         break;
1490666d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj      case 0x0A0: // xssubdp (VSX Scalar Subtract Double-Precision)
14907b173774421d015736c2316b5e6e998e7de545a5cflorian         DIP("xssubdp v%d,v%d,v%d\n", XT, XA, XB);
1490866d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj         putVSReg( XT, binop( Iop_64HLtoV128, unop( Iop_ReinterpF64asI64,
1490966d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj                                                    triop( Iop_SubF64, rm,
1491066d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj                                                           mkexpr( frA ),
1491166d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj                                                           mkexpr( frB ) ) ),
1491266d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj                              mkU64( 0 ) ) );
1491366d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj         break;
1491466d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj
149156c758b64a77c254065ab7450576bbd3a0b583595carll      case 0x016: // xssqrtsp (VSX Scalar Square Root Single-Precision)
14916b173774421d015736c2316b5e6e998e7de545a5cflorian         DIP("xssqrtsp v%d,v%d\n", XT, XB);
149176c758b64a77c254065ab7450576bbd3a0b583595carll         putVSReg( XT,
149186c758b64a77c254065ab7450576bbd3a0b583595carll                   binop( Iop_64HLtoV128,
149196c758b64a77c254065ab7450576bbd3a0b583595carll                          unop( Iop_ReinterpF64asI64,
149206c758b64a77c254065ab7450576bbd3a0b583595carll                                binop( Iop_RoundF64toF32, rm,
149216c758b64a77c254065ab7450576bbd3a0b583595carll                                       binop( Iop_SqrtF64, rm,
149226c758b64a77c254065ab7450576bbd3a0b583595carll                                              mkexpr( frB ) ) ) ),
149236c758b64a77c254065ab7450576bbd3a0b583595carll                          mkU64( 0 ) ) );
149246c758b64a77c254065ab7450576bbd3a0b583595carll         break;
149256c758b64a77c254065ab7450576bbd3a0b583595carll
149264aa412af1d8166cc11f39a6e721df49431d23618sewardj      case 0x096: // xssqrtdp (VSX Scalar Square Root Double-Precision)
14927b173774421d015736c2316b5e6e998e7de545a5cflorian         DIP("xssqrtdp v%d,v%d\n", XT, XB);
149284aa412af1d8166cc11f39a6e721df49431d23618sewardj         putVSReg( XT,  binop( Iop_64HLtoV128, unop( Iop_ReinterpF64asI64,
149294aa412af1d8166cc11f39a6e721df49431d23618sewardj                                                     binop( Iop_SqrtF64, rm,
149304aa412af1d8166cc11f39a6e721df49431d23618sewardj                                                            mkexpr( frB ) ) ),
149314aa412af1d8166cc11f39a6e721df49431d23618sewardj                               mkU64( 0 ) ) );
149324aa412af1d8166cc11f39a6e721df49431d23618sewardj         break;
149334aa412af1d8166cc11f39a6e721df49431d23618sewardj
149344aa412af1d8166cc11f39a6e721df49431d23618sewardj      case 0x0F4: // xstdivdp (VSX Scalar Test for software Divide Double-Precision)
149354aa412af1d8166cc11f39a6e721df49431d23618sewardj      {
149364aa412af1d8166cc11f39a6e721df49431d23618sewardj         UChar crfD     = toUChar( IFIELD( theInstr, 23, 3 ) );
149374aa412af1d8166cc11f39a6e721df49431d23618sewardj         IRTemp frA_I64 = newTemp(Ity_I64);
149384aa412af1d8166cc11f39a6e721df49431d23618sewardj         IRTemp frB_I64 = newTemp(Ity_I64);
14939b173774421d015736c2316b5e6e998e7de545a5cflorian         DIP("xstdivdp crf%d,v%d,v%d\n", crfD, XA, XB);
149404aa412af1d8166cc11f39a6e721df49431d23618sewardj         assign( frA_I64, unop( Iop_ReinterpF64asI64, mkexpr( frA ) ) );
149414aa412af1d8166cc11f39a6e721df49431d23618sewardj         assign( frB_I64, unop( Iop_ReinterpF64asI64, mkexpr( frB ) ) );
149424aa412af1d8166cc11f39a6e721df49431d23618sewardj         putGST_field( PPC_GST_CR, do_fp_tdiv(frA_I64, frB_I64), crfD );
149434aa412af1d8166cc11f39a6e721df49431d23618sewardj         break;
149444aa412af1d8166cc11f39a6e721df49431d23618sewardj      }
14945e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj      case 0x0D4: // xstsqrtdp (VSX Vector Test for software Square Root Double-Precision)
14946e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj      {
14947e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj         IRTemp frB_I64 = newTemp(Ity_I64);
14948e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj         UChar crfD     = toUChar( IFIELD( theInstr, 23, 3 ) );
14949e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj         IRTemp flags = newTemp(Ity_I32);
14950e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj         IRTemp  fe_flag, fg_flag;
14951e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj         fe_flag = fg_flag = IRTemp_INVALID;
14952b173774421d015736c2316b5e6e998e7de545a5cflorian         DIP("xstsqrtdp v%d,v%d\n", XT, XB);
14953e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj         assign( frB_I64, unop(Iop_V128HIto64, getVSReg( XB )) );
14954e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj         do_fp_tsqrt(frB_I64, False /*not single precision*/, &fe_flag, &fg_flag);
14955e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj         /* The CR field consists of fl_flag || fg_flag || fe_flag || 0b0
14956e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj          * where fl_flag == 1 on ppc64.
14957e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj          */
14958e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj         assign( flags,
14959e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj                 binop( Iop_Or32,
14960e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj                        binop( Iop_Or32, mkU32( 8 ), // fl_flag
14961e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj                               binop( Iop_Shl32, mkexpr(fg_flag), mkU8( 2 ) ) ),
14962e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj                        binop( Iop_Shl32, mkexpr(fe_flag), mkU8( 1 ) ) ) );
14963e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj         putGST_field( PPC_GST_CR, mkexpr(flags), crfD );
14964e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj         break;
14965e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj      }
149664aa412af1d8166cc11f39a6e721df49431d23618sewardj
1496766d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj      default:
149684aa412af1d8166cc11f39a6e721df49431d23618sewardj         vex_printf( "dis_vxs_arith(ppc)(opc2)\n" );
1496966d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj         return False;
1497066d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj   }
149714aa412af1d8166cc11f39a6e721df49431d23618sewardj
1497266d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj   return True;
1497366d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj}
1497466d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj
149754aa412af1d8166cc11f39a6e721df49431d23618sewardj
1497666d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj/*
1497766d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj * VSX Floating Point Compare Instructions
1497866d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj */
1497966d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardjstatic Bool
1498066d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardjdis_vx_cmp( UInt theInstr, UInt opc2 )
1498166d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj{
1498266d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj   /* XX3-Form and XX2-Form */
1498366d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj   UChar opc1 = ifieldOPC( theInstr );
1498466d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj   UChar crfD     = toUChar( IFIELD( theInstr, 23, 3 ) );
149854aa412af1d8166cc11f39a6e721df49431d23618sewardj   IRTemp ccPPC32;
1498666d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj   UChar XA       = ifieldRegXA ( theInstr );
1498766d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj   UChar XB       = ifieldRegXB ( theInstr );
1498866d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj   IRTemp frA     = newTemp(Ity_F64);
1498966d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj   IRTemp frB     = newTemp(Ity_F64);
1499066d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj
1499166d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj   if (opc1 != 0x3C) {
1499266d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj      vex_printf( "dis_vx_cmp(ppc)(instr)\n" );
1499366d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj      return False;
1499466d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj   }
1499566d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj
1499666d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj   assign(frA, unop(Iop_ReinterpI64asF64, unop(Iop_V128HIto64, getVSReg( XA ))));
1499766d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj   assign(frB, unop(Iop_ReinterpI64asF64, unop(Iop_V128HIto64, getVSReg( XB ))));
1499866d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj   switch (opc2) {
1499966d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj      case 0x08C: case 0x0AC: // xscmpudp, xscmpodp
1500066d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj         /* Note: Differences between xscmpudp and xscmpodp are only in
1500166d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj          * exception flag settings, which aren't supported anyway. */
1500266d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj         DIP("xscmp%sdp crf%d,fr%u,fr%u\n", opc2 == 0x08c ? "u" : "o",
15003b173774421d015736c2316b5e6e998e7de545a5cflorian                                           crfD, XA, XB);
150044aa412af1d8166cc11f39a6e721df49431d23618sewardj         ccPPC32 = get_fp_cmp_CR_val( binop(Iop_CmpF64, mkexpr(frA), mkexpr(frB)));
150054aa412af1d8166cc11f39a6e721df49431d23618sewardj         putGST_field( PPC_GST_CR, mkexpr(ccPPC32), crfD );
150064aa412af1d8166cc11f39a6e721df49431d23618sewardj         break;
1500766d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj
150084aa412af1d8166cc11f39a6e721df49431d23618sewardj      default:
150094aa412af1d8166cc11f39a6e721df49431d23618sewardj         vex_printf( "dis_vx_cmp(ppc)(opc2)\n" );
150104aa412af1d8166cc11f39a6e721df49431d23618sewardj         return False;
150114aa412af1d8166cc11f39a6e721df49431d23618sewardj   }
150124aa412af1d8166cc11f39a6e721df49431d23618sewardj   return True;
150134aa412af1d8166cc11f39a6e721df49431d23618sewardj}
1501466d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj
150154aa412af1d8166cc11f39a6e721df49431d23618sewardjstatic void
150164aa412af1d8166cc11f39a6e721df49431d23618sewardjdo_vvec_fp_cmp ( IRTemp vA, IRTemp vB, UChar XT, UChar flag_rC,
150174aa412af1d8166cc11f39a6e721df49431d23618sewardj                 ppc_cmp_t cmp_type )
150184aa412af1d8166cc11f39a6e721df49431d23618sewardj{
150194aa412af1d8166cc11f39a6e721df49431d23618sewardj   IRTemp frA_hi     = newTemp(Ity_F64);
150204aa412af1d8166cc11f39a6e721df49431d23618sewardj   IRTemp frB_hi     = newTemp(Ity_F64);
150214aa412af1d8166cc11f39a6e721df49431d23618sewardj   IRTemp frA_lo     = newTemp(Ity_F64);
150224aa412af1d8166cc11f39a6e721df49431d23618sewardj   IRTemp frB_lo     = newTemp(Ity_F64);
150234aa412af1d8166cc11f39a6e721df49431d23618sewardj   IRTemp ccPPC32    = newTemp(Ity_I32);
150244aa412af1d8166cc11f39a6e721df49431d23618sewardj   IRTemp ccIR_hi;
150254aa412af1d8166cc11f39a6e721df49431d23618sewardj   IRTemp ccIR_lo;
150264aa412af1d8166cc11f39a6e721df49431d23618sewardj
150274aa412af1d8166cc11f39a6e721df49431d23618sewardj   IRTemp hiResult = newTemp(Ity_I64);
150284aa412af1d8166cc11f39a6e721df49431d23618sewardj   IRTemp loResult = newTemp(Ity_I64);
150294aa412af1d8166cc11f39a6e721df49431d23618sewardj   IRTemp hiEQlo = newTemp(Ity_I1);
150304aa412af1d8166cc11f39a6e721df49431d23618sewardj   IRTemp all_elem_true = newTemp(Ity_I32);
150314aa412af1d8166cc11f39a6e721df49431d23618sewardj   IRTemp all_elem_false = newTemp(Ity_I32);
150324aa412af1d8166cc11f39a6e721df49431d23618sewardj
150334aa412af1d8166cc11f39a6e721df49431d23618sewardj   assign(frA_hi, unop(Iop_ReinterpI64asF64, unop(Iop_V128HIto64, mkexpr( vA ))));
150344aa412af1d8166cc11f39a6e721df49431d23618sewardj   assign(frB_hi, unop(Iop_ReinterpI64asF64, unop(Iop_V128HIto64, mkexpr( vB ))));
150354aa412af1d8166cc11f39a6e721df49431d23618sewardj   assign(frA_lo, unop(Iop_ReinterpI64asF64, unop(Iop_V128to64, mkexpr( vA ))));
150364aa412af1d8166cc11f39a6e721df49431d23618sewardj   assign(frB_lo, unop(Iop_ReinterpI64asF64, unop(Iop_V128to64, mkexpr( vB ))));
150374aa412af1d8166cc11f39a6e721df49431d23618sewardj
150384aa412af1d8166cc11f39a6e721df49431d23618sewardj   ccIR_hi = get_fp_cmp_CR_val( binop( Iop_CmpF64,
150394aa412af1d8166cc11f39a6e721df49431d23618sewardj                                       mkexpr( frA_hi ),
150404aa412af1d8166cc11f39a6e721df49431d23618sewardj                                       mkexpr( frB_hi ) ) );
150414aa412af1d8166cc11f39a6e721df49431d23618sewardj   ccIR_lo = get_fp_cmp_CR_val( binop( Iop_CmpF64,
150424aa412af1d8166cc11f39a6e721df49431d23618sewardj                                       mkexpr( frA_lo ),
150434aa412af1d8166cc11f39a6e721df49431d23618sewardj                                       mkexpr( frB_lo ) ) );
150444aa412af1d8166cc11f39a6e721df49431d23618sewardj
150454aa412af1d8166cc11f39a6e721df49431d23618sewardj   if (cmp_type != PPC_CMP_GE) {
150464aa412af1d8166cc11f39a6e721df49431d23618sewardj      assign( hiResult,
150474aa412af1d8166cc11f39a6e721df49431d23618sewardj              unop( Iop_1Sto64,
150484aa412af1d8166cc11f39a6e721df49431d23618sewardj                    binop( Iop_CmpEQ32, mkexpr( ccIR_hi ), mkU32( cmp_type ) ) ) );
150494aa412af1d8166cc11f39a6e721df49431d23618sewardj      assign( loResult,
150504aa412af1d8166cc11f39a6e721df49431d23618sewardj              unop( Iop_1Sto64,
150514aa412af1d8166cc11f39a6e721df49431d23618sewardj                    binop( Iop_CmpEQ32, mkexpr( ccIR_lo ), mkU32( cmp_type ) ) ) );
150524aa412af1d8166cc11f39a6e721df49431d23618sewardj   } else {
150534aa412af1d8166cc11f39a6e721df49431d23618sewardj      // For PPC_CMP_GE, one element compare may return "4" (for "greater than") and
150544aa412af1d8166cc11f39a6e721df49431d23618sewardj      // the other element compare may return "2" (for "equal to").
150554aa412af1d8166cc11f39a6e721df49431d23618sewardj      IRTemp lo_GE = newTemp(Ity_I1);
150564aa412af1d8166cc11f39a6e721df49431d23618sewardj      IRTemp hi_GE = newTemp(Ity_I1);
150574aa412af1d8166cc11f39a6e721df49431d23618sewardj
150584aa412af1d8166cc11f39a6e721df49431d23618sewardj      assign(hi_GE, mkOR1( binop( Iop_CmpEQ32, mkexpr( ccIR_hi ), mkU32( 2 ) ),
150594aa412af1d8166cc11f39a6e721df49431d23618sewardj                           binop( Iop_CmpEQ32, mkexpr( ccIR_hi ), mkU32( 4 ) ) ) );
150604aa412af1d8166cc11f39a6e721df49431d23618sewardj      assign( hiResult,unop( Iop_1Sto64, mkexpr( hi_GE ) ) );
150614aa412af1d8166cc11f39a6e721df49431d23618sewardj
150624aa412af1d8166cc11f39a6e721df49431d23618sewardj      assign(lo_GE, mkOR1( binop( Iop_CmpEQ32, mkexpr( ccIR_lo ), mkU32( 2 ) ),
150634aa412af1d8166cc11f39a6e721df49431d23618sewardj                           binop( Iop_CmpEQ32, mkexpr( ccIR_lo ), mkU32( 4 ) ) ) );
150644aa412af1d8166cc11f39a6e721df49431d23618sewardj      assign( loResult, unop( Iop_1Sto64, mkexpr( lo_GE ) ) );
150654aa412af1d8166cc11f39a6e721df49431d23618sewardj   }
150664aa412af1d8166cc11f39a6e721df49431d23618sewardj
150674aa412af1d8166cc11f39a6e721df49431d23618sewardj   // The [hi/lo]Result will be all 1's or all 0's.  We just look at the lower word.
150684aa412af1d8166cc11f39a6e721df49431d23618sewardj   assign( hiEQlo,
150694aa412af1d8166cc11f39a6e721df49431d23618sewardj           binop( Iop_CmpEQ32,
150704aa412af1d8166cc11f39a6e721df49431d23618sewardj                  unop( Iop_64to32, mkexpr( hiResult ) ),
150714aa412af1d8166cc11f39a6e721df49431d23618sewardj                  unop( Iop_64to32, mkexpr( loResult ) ) ) );
150724aa412af1d8166cc11f39a6e721df49431d23618sewardj   putVSReg( XT,
150734aa412af1d8166cc11f39a6e721df49431d23618sewardj             binop( Iop_64HLtoV128, mkexpr( hiResult ), mkexpr( loResult ) ) );
150744aa412af1d8166cc11f39a6e721df49431d23618sewardj
150754aa412af1d8166cc11f39a6e721df49431d23618sewardj   assign( all_elem_true,
150764aa412af1d8166cc11f39a6e721df49431d23618sewardj           unop( Iop_1Uto32,
150774aa412af1d8166cc11f39a6e721df49431d23618sewardj                 mkAND1( mkexpr( hiEQlo ),
150784aa412af1d8166cc11f39a6e721df49431d23618sewardj                         binop( Iop_CmpEQ32,
150794aa412af1d8166cc11f39a6e721df49431d23618sewardj                                mkU32( 0xffffffff ),
150804aa412af1d8166cc11f39a6e721df49431d23618sewardj                                unop( Iop_64to32,
150814aa412af1d8166cc11f39a6e721df49431d23618sewardj                                mkexpr( hiResult ) ) ) ) ) );
150824aa412af1d8166cc11f39a6e721df49431d23618sewardj
150834aa412af1d8166cc11f39a6e721df49431d23618sewardj   assign( all_elem_false,
150844aa412af1d8166cc11f39a6e721df49431d23618sewardj           unop( Iop_1Uto32,
150854aa412af1d8166cc11f39a6e721df49431d23618sewardj                 mkAND1( mkexpr( hiEQlo ),
150864aa412af1d8166cc11f39a6e721df49431d23618sewardj                         binop( Iop_CmpEQ32,
150874aa412af1d8166cc11f39a6e721df49431d23618sewardj                                mkU32( 0 ),
150884aa412af1d8166cc11f39a6e721df49431d23618sewardj                                unop( Iop_64to32,
150894aa412af1d8166cc11f39a6e721df49431d23618sewardj                                mkexpr( hiResult ) ) ) ) ) );
150904aa412af1d8166cc11f39a6e721df49431d23618sewardj   assign( ccPPC32,
150914aa412af1d8166cc11f39a6e721df49431d23618sewardj           binop( Iop_Or32,
150924aa412af1d8166cc11f39a6e721df49431d23618sewardj                  binop( Iop_Shl32, mkexpr( all_elem_false ), mkU8( 1 ) ),
150934aa412af1d8166cc11f39a6e721df49431d23618sewardj                  binop( Iop_Shl32, mkexpr( all_elem_true ), mkU8( 3 ) ) ) );
1509466d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj
150954aa412af1d8166cc11f39a6e721df49431d23618sewardj   if (flag_rC) {
150964aa412af1d8166cc11f39a6e721df49431d23618sewardj      putGST_field( PPC_GST_CR, mkexpr(ccPPC32), 6 );
150974aa412af1d8166cc11f39a6e721df49431d23618sewardj   }
150984aa412af1d8166cc11f39a6e721df49431d23618sewardj}
150994aa412af1d8166cc11f39a6e721df49431d23618sewardj
151004aa412af1d8166cc11f39a6e721df49431d23618sewardj/*
151014aa412af1d8166cc11f39a6e721df49431d23618sewardj * VSX Vector Compare Instructions
151024aa412af1d8166cc11f39a6e721df49431d23618sewardj */
151034aa412af1d8166cc11f39a6e721df49431d23618sewardjstatic Bool
151044aa412af1d8166cc11f39a6e721df49431d23618sewardjdis_vvec_cmp( UInt theInstr, UInt opc2 )
151054aa412af1d8166cc11f39a6e721df49431d23618sewardj{
151064aa412af1d8166cc11f39a6e721df49431d23618sewardj   /* XX3-Form */
151074aa412af1d8166cc11f39a6e721df49431d23618sewardj   UChar opc1 = ifieldOPC( theInstr );
151084aa412af1d8166cc11f39a6e721df49431d23618sewardj   UChar XT = ifieldRegXT ( theInstr );
151094aa412af1d8166cc11f39a6e721df49431d23618sewardj   UChar XA = ifieldRegXA ( theInstr );
151104aa412af1d8166cc11f39a6e721df49431d23618sewardj   UChar XB = ifieldRegXB ( theInstr );
151114aa412af1d8166cc11f39a6e721df49431d23618sewardj   UChar flag_rC  = ifieldBIT10(theInstr);
151124aa412af1d8166cc11f39a6e721df49431d23618sewardj   IRTemp vA = newTemp( Ity_V128 );
151134aa412af1d8166cc11f39a6e721df49431d23618sewardj   IRTemp vB = newTemp( Ity_V128 );
151144aa412af1d8166cc11f39a6e721df49431d23618sewardj
151154aa412af1d8166cc11f39a6e721df49431d23618sewardj   if (opc1 != 0x3C) {
151164aa412af1d8166cc11f39a6e721df49431d23618sewardj      vex_printf( "dis_vvec_cmp(ppc)(instr)\n" );
151174aa412af1d8166cc11f39a6e721df49431d23618sewardj      return False;
151184aa412af1d8166cc11f39a6e721df49431d23618sewardj   }
151194aa412af1d8166cc11f39a6e721df49431d23618sewardj
151204aa412af1d8166cc11f39a6e721df49431d23618sewardj   assign( vA, getVSReg( XA ) );
151214aa412af1d8166cc11f39a6e721df49431d23618sewardj   assign( vB, getVSReg( XB ) );
151224aa412af1d8166cc11f39a6e721df49431d23618sewardj
151234aa412af1d8166cc11f39a6e721df49431d23618sewardj   switch (opc2) {
151244aa412af1d8166cc11f39a6e721df49431d23618sewardj      case 0x18C: case 0x38C:  // xvcmpeqdp[.] (VSX Vector Compare Equal To Double-Precision [ & Record ])
151254aa412af1d8166cc11f39a6e721df49431d23618sewardj      {
151264aa412af1d8166cc11f39a6e721df49431d23618sewardj         DIP("xvcmpeqdp%s crf%d,fr%u,fr%u\n", (flag_rC ? ".":""),
15127b173774421d015736c2316b5e6e998e7de545a5cflorian             XT, XA, XB);
151284aa412af1d8166cc11f39a6e721df49431d23618sewardj         do_vvec_fp_cmp(vA, vB, XT, flag_rC, PPC_CMP_EQ);
151294aa412af1d8166cc11f39a6e721df49431d23618sewardj         break;
151304aa412af1d8166cc11f39a6e721df49431d23618sewardj      }
151314aa412af1d8166cc11f39a6e721df49431d23618sewardj
151324aa412af1d8166cc11f39a6e721df49431d23618sewardj      case 0x1CC: case 0x3CC: // xvcmpgedp[.] (VSX Vector Compare Greater Than or Equal To Double-Precision [ & Record ])
151334aa412af1d8166cc11f39a6e721df49431d23618sewardj      {
151344aa412af1d8166cc11f39a6e721df49431d23618sewardj         DIP("xvcmpgedp%s crf%d,fr%u,fr%u\n", (flag_rC ? ".":""),
15135b173774421d015736c2316b5e6e998e7de545a5cflorian             XT, XA, XB);
151364aa412af1d8166cc11f39a6e721df49431d23618sewardj         do_vvec_fp_cmp(vA, vB, XT, flag_rC, PPC_CMP_GE);
151374aa412af1d8166cc11f39a6e721df49431d23618sewardj         break;
151384aa412af1d8166cc11f39a6e721df49431d23618sewardj      }
151394aa412af1d8166cc11f39a6e721df49431d23618sewardj
151404aa412af1d8166cc11f39a6e721df49431d23618sewardj      case 0x1AC: case 0x3AC: // xvcmpgtdp[.] (VSX Vector Compare Greater Than Double-Precision [ & Record ])
151414aa412af1d8166cc11f39a6e721df49431d23618sewardj      {
151424aa412af1d8166cc11f39a6e721df49431d23618sewardj         DIP("xvcmpgtdp%s crf%d,fr%u,fr%u\n", (flag_rC ? ".":""),
15143b173774421d015736c2316b5e6e998e7de545a5cflorian             XT, XA, XB);
151444aa412af1d8166cc11f39a6e721df49431d23618sewardj         do_vvec_fp_cmp(vA, vB, XT, flag_rC, PPC_CMP_GT);
151454aa412af1d8166cc11f39a6e721df49431d23618sewardj         break;
151464aa412af1d8166cc11f39a6e721df49431d23618sewardj      }
151474aa412af1d8166cc11f39a6e721df49431d23618sewardj
151484aa412af1d8166cc11f39a6e721df49431d23618sewardj      case 0x10C: case 0x30C: // xvcmpeqsp[.] (VSX Vector Compare Equal To Single-Precision [ & Record ])
151494aa412af1d8166cc11f39a6e721df49431d23618sewardj      {
151504aa412af1d8166cc11f39a6e721df49431d23618sewardj         IRTemp vD = newTemp(Ity_V128);
151514aa412af1d8166cc11f39a6e721df49431d23618sewardj
151524aa412af1d8166cc11f39a6e721df49431d23618sewardj         DIP("xvcmpeqsp%s crf%d,fr%u,fr%u\n", (flag_rC ? ".":""),
15153b173774421d015736c2316b5e6e998e7de545a5cflorian             XT, XA, XB);
151544aa412af1d8166cc11f39a6e721df49431d23618sewardj         assign( vD, binop(Iop_CmpEQ32Fx4, mkexpr(vA), mkexpr(vB)) );
151554aa412af1d8166cc11f39a6e721df49431d23618sewardj         putVSReg( XT, mkexpr(vD) );
151564aa412af1d8166cc11f39a6e721df49431d23618sewardj         if (flag_rC) {
151574aa412af1d8166cc11f39a6e721df49431d23618sewardj            set_AV_CR6( mkexpr(vD), True );
151584aa412af1d8166cc11f39a6e721df49431d23618sewardj         }
151594aa412af1d8166cc11f39a6e721df49431d23618sewardj         break;
151604aa412af1d8166cc11f39a6e721df49431d23618sewardj      }
151614aa412af1d8166cc11f39a6e721df49431d23618sewardj
151624aa412af1d8166cc11f39a6e721df49431d23618sewardj      case 0x14C: case 0x34C: // xvcmpgesp[.] (VSX Vector Compare Greater Than or Equal To Single-Precision [ & Record ])
151634aa412af1d8166cc11f39a6e721df49431d23618sewardj      {
151644aa412af1d8166cc11f39a6e721df49431d23618sewardj         IRTemp vD = newTemp(Ity_V128);
151654aa412af1d8166cc11f39a6e721df49431d23618sewardj
151664aa412af1d8166cc11f39a6e721df49431d23618sewardj         DIP("xvcmpgesp%s crf%d,fr%u,fr%u\n", (flag_rC ? ".":""),
15167b173774421d015736c2316b5e6e998e7de545a5cflorian             XT, XA, XB);
151684aa412af1d8166cc11f39a6e721df49431d23618sewardj         assign( vD, binop(Iop_CmpGE32Fx4, mkexpr(vA), mkexpr(vB)) );
151694aa412af1d8166cc11f39a6e721df49431d23618sewardj         putVSReg( XT, mkexpr(vD) );
151704aa412af1d8166cc11f39a6e721df49431d23618sewardj         if (flag_rC) {
151714aa412af1d8166cc11f39a6e721df49431d23618sewardj            set_AV_CR6( mkexpr(vD), True );
151724aa412af1d8166cc11f39a6e721df49431d23618sewardj         }
151734aa412af1d8166cc11f39a6e721df49431d23618sewardj         break;
151744aa412af1d8166cc11f39a6e721df49431d23618sewardj      }
1517566d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj
151764aa412af1d8166cc11f39a6e721df49431d23618sewardj      case 0x12C: case 0x32C: //xvcmpgtsp[.] (VSX Vector Compare Greater Than Single-Precision [ & Record ])
151774aa412af1d8166cc11f39a6e721df49431d23618sewardj      {
151784aa412af1d8166cc11f39a6e721df49431d23618sewardj         IRTemp vD = newTemp(Ity_V128);
151794aa412af1d8166cc11f39a6e721df49431d23618sewardj
151804aa412af1d8166cc11f39a6e721df49431d23618sewardj         DIP("xvcmpgtsp%s crf%d,fr%u,fr%u\n", (flag_rC ? ".":""),
15181b173774421d015736c2316b5e6e998e7de545a5cflorian             XT, XA, XB);
151824aa412af1d8166cc11f39a6e721df49431d23618sewardj         assign( vD, binop(Iop_CmpGT32Fx4, mkexpr(vA), mkexpr(vB)) );
151834aa412af1d8166cc11f39a6e721df49431d23618sewardj         putVSReg( XT, mkexpr(vD) );
151844aa412af1d8166cc11f39a6e721df49431d23618sewardj         if (flag_rC) {
151854aa412af1d8166cc11f39a6e721df49431d23618sewardj            set_AV_CR6( mkexpr(vD), True );
151864aa412af1d8166cc11f39a6e721df49431d23618sewardj         }
1518766d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj         break;
151884aa412af1d8166cc11f39a6e721df49431d23618sewardj      }
151894aa412af1d8166cc11f39a6e721df49431d23618sewardj
1519066d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj      default:
151914aa412af1d8166cc11f39a6e721df49431d23618sewardj         vex_printf( "dis_vvec_cmp(ppc)(opc2)\n" );
1519266d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj         return False;
1519366d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj   }
1519466d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj   return True;
1519566d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj}
1519666d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj/*
151974aa412af1d8166cc11f39a6e721df49431d23618sewardj * Miscellaneous VSX Scalar Instructions
1519866d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj */
1519966d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardjstatic Bool
152004aa412af1d8166cc11f39a6e721df49431d23618sewardjdis_vxs_misc( UInt theInstr, UInt opc2 )
1520166d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj{
152021f5fe1fc3a37ca729925e8eec25aa1025b4a6cdbcarll#define VG_PPC_SIGN_MASK 0x7fffffffffffffffULL
1520366d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj   /* XX3-Form and XX2-Form */
1520466d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj   UChar opc1 = ifieldOPC( theInstr );
1520566d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj   UChar XT = ifieldRegXT ( theInstr );
1520666d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj   UChar XA = ifieldRegXA ( theInstr );
1520766d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj   UChar XB = ifieldRegXB ( theInstr );
1520866d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj   IRTemp vA = newTemp( Ity_V128 );
1520966d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj   IRTemp vB = newTemp( Ity_V128 );
1521066d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj
1521166d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj   if (opc1 != 0x3C) {
152124aa412af1d8166cc11f39a6e721df49431d23618sewardj      vex_printf( "dis_vxs_misc(ppc)(instr)\n" );
1521366d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj      return False;
1521466d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj   }
1521566d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj
1521666d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj   assign( vA, getVSReg( XA ) );
1521766d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj   assign( vB, getVSReg( XB ) );
1521866d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj
1521966d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj   /* For all the VSX move instructions, the contents of doubleword element 1
1522066d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj    * of VSX[XT] are undefined after the operation; therefore, we can simply
1522166d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj    * move the entire array element where it makes sense to do so.
1522266d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj    */
1522366d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj
1522466d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj   switch (opc2) {
1522566d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj      case 0x2B2: // xsabsdp (VSX scalar absolute value double-precision
1522666d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj      {
1522766d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj         /* Move abs val of dw 0 of VSX[XB] to dw 0 of VSX[XT]. */
1522866d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj         IRTemp absVal = newTemp(Ity_V128);
152291f5fe1fc3a37ca729925e8eec25aa1025b4a6cdbcarll         if (host_endness == VexEndnessLE) {
152301f5fe1fc3a37ca729925e8eec25aa1025b4a6cdbcarll            IRTemp hi64 = newTemp(Ity_I64);
152311f5fe1fc3a37ca729925e8eec25aa1025b4a6cdbcarll            IRTemp lo64 = newTemp(Ity_I64);
152321f5fe1fc3a37ca729925e8eec25aa1025b4a6cdbcarll            assign( hi64, unop( Iop_V128HIto64, mkexpr(vB) ) );
152331f5fe1fc3a37ca729925e8eec25aa1025b4a6cdbcarll            assign( lo64, unop( Iop_V128to64, mkexpr(vB) ) );
152341f5fe1fc3a37ca729925e8eec25aa1025b4a6cdbcarll            assign( absVal, binop( Iop_64HLtoV128,
152351f5fe1fc3a37ca729925e8eec25aa1025b4a6cdbcarll                                   binop( Iop_And64, mkexpr(hi64),
152361f5fe1fc3a37ca729925e8eec25aa1025b4a6cdbcarll                                          mkU64(VG_PPC_SIGN_MASK) ),
152371f5fe1fc3a37ca729925e8eec25aa1025b4a6cdbcarll                                   mkexpr(lo64) ) );
152381f5fe1fc3a37ca729925e8eec25aa1025b4a6cdbcarll         } else {
152391f5fe1fc3a37ca729925e8eec25aa1025b4a6cdbcarll            assign(absVal, binop(Iop_ShrV128,
152401f5fe1fc3a37ca729925e8eec25aa1025b4a6cdbcarll                                 binop(Iop_ShlV128, mkexpr(vB),
152411f5fe1fc3a37ca729925e8eec25aa1025b4a6cdbcarll                                       mkU8(1)), mkU8(1)));
152421f5fe1fc3a37ca729925e8eec25aa1025b4a6cdbcarll         }
15243b173774421d015736c2316b5e6e998e7de545a5cflorian         DIP("xsabsdp v%d,v%d\n", XT, XB);
1524466d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj         putVSReg(XT, mkexpr(absVal));
1524566d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj         break;
1524666d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj      }
1524766d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj      case 0x2C0: // xscpsgndp
1524866d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj      {
1524966d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj         /* Scalar copy sign double-precision */
152501f5fe1fc3a37ca729925e8eec25aa1025b4a6cdbcarll         IRTemp vecA_signed = newTemp(Ity_I64);
152511f5fe1fc3a37ca729925e8eec25aa1025b4a6cdbcarll         IRTemp vecB_unsigned = newTemp(Ity_I64);
1525266d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj         IRTemp vec_result = newTemp(Ity_V128);
15253b173774421d015736c2316b5e6e998e7de545a5cflorian         DIP("xscpsgndp v%d,v%d v%d\n", XT, XA, XB);
152541f5fe1fc3a37ca729925e8eec25aa1025b4a6cdbcarll         assign( vecA_signed, binop( Iop_And64,
152551f5fe1fc3a37ca729925e8eec25aa1025b4a6cdbcarll                                     unop( Iop_V128HIto64,
152561f5fe1fc3a37ca729925e8eec25aa1025b4a6cdbcarll                                           mkexpr(vA)),
152571f5fe1fc3a37ca729925e8eec25aa1025b4a6cdbcarll                                           mkU64(~VG_PPC_SIGN_MASK) ) );
152581f5fe1fc3a37ca729925e8eec25aa1025b4a6cdbcarll         assign( vecB_unsigned, binop( Iop_And64,
152591f5fe1fc3a37ca729925e8eec25aa1025b4a6cdbcarll                                       unop( Iop_V128HIto64,
152601f5fe1fc3a37ca729925e8eec25aa1025b4a6cdbcarll                                             mkexpr(vB) ),
152611f5fe1fc3a37ca729925e8eec25aa1025b4a6cdbcarll                                             mkU64(VG_PPC_SIGN_MASK) ) );
152621f5fe1fc3a37ca729925e8eec25aa1025b4a6cdbcarll         assign( vec_result, binop( Iop_64HLtoV128,
152631f5fe1fc3a37ca729925e8eec25aa1025b4a6cdbcarll                                    binop( Iop_Or64,
152641f5fe1fc3a37ca729925e8eec25aa1025b4a6cdbcarll                                           mkexpr(vecA_signed),
152651f5fe1fc3a37ca729925e8eec25aa1025b4a6cdbcarll                                           mkexpr(vecB_unsigned) ),
152661f5fe1fc3a37ca729925e8eec25aa1025b4a6cdbcarll                                    mkU64(0x0ULL)));
1526766d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj         putVSReg(XT, mkexpr(vec_result));
1526866d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj         break;
1526966d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj      }
1527066d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj      case 0x2D2: // xsnabsdp
1527166d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj      {
1527266d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj         /* Scalar negative absolute value double-precision */
152731f5fe1fc3a37ca729925e8eec25aa1025b4a6cdbcarll         IRTemp BHi_signed = newTemp(Ity_I64);
15274b173774421d015736c2316b5e6e998e7de545a5cflorian         DIP("xsnabsdp v%d,v%d\n", XT, XB);
152751f5fe1fc3a37ca729925e8eec25aa1025b4a6cdbcarll         assign( BHi_signed, binop( Iop_Or64,
152761f5fe1fc3a37ca729925e8eec25aa1025b4a6cdbcarll                                    unop( Iop_V128HIto64,
152771f5fe1fc3a37ca729925e8eec25aa1025b4a6cdbcarll                                          mkexpr(vB) ),
152781f5fe1fc3a37ca729925e8eec25aa1025b4a6cdbcarll                                          mkU64(~VG_PPC_SIGN_MASK) ) );
152791f5fe1fc3a37ca729925e8eec25aa1025b4a6cdbcarll         putVSReg(XT, binop( Iop_64HLtoV128,
152801f5fe1fc3a37ca729925e8eec25aa1025b4a6cdbcarll                             mkexpr(BHi_signed), mkU64(0x0ULL) ) );
1528166d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj         break;
1528266d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj      }
1528366d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj      case 0x2F2: // xsnegdp
1528466d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj      {
1528566d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj         /* Scalar negate double-precision */
152861f5fe1fc3a37ca729925e8eec25aa1025b4a6cdbcarll         IRTemp BHi_signed = newTemp(Ity_I64);
152871f5fe1fc3a37ca729925e8eec25aa1025b4a6cdbcarll         IRTemp BHi_unsigned = newTemp(Ity_I64);
152881f5fe1fc3a37ca729925e8eec25aa1025b4a6cdbcarll         IRTemp BHi_negated = newTemp(Ity_I64);
152891f5fe1fc3a37ca729925e8eec25aa1025b4a6cdbcarll         IRTemp BHi_negated_signbit = newTemp(Ity_I1);
152901f5fe1fc3a37ca729925e8eec25aa1025b4a6cdbcarll         IRTemp vec_result = newTemp(Ity_V128);
15291b173774421d015736c2316b5e6e998e7de545a5cflorian         DIP("xsnabsdp v%d,v%d\n", XT, XB);
152921f5fe1fc3a37ca729925e8eec25aa1025b4a6cdbcarll         assign( BHi_signed, unop( Iop_V128HIto64, mkexpr(vB) ) );
152931f5fe1fc3a37ca729925e8eec25aa1025b4a6cdbcarll         assign( BHi_unsigned, binop( Iop_And64, mkexpr(BHi_signed),
152941f5fe1fc3a37ca729925e8eec25aa1025b4a6cdbcarll                                      mkU64(VG_PPC_SIGN_MASK) ) );
152951f5fe1fc3a37ca729925e8eec25aa1025b4a6cdbcarll         assign( BHi_negated_signbit,
152961f5fe1fc3a37ca729925e8eec25aa1025b4a6cdbcarll                 unop( Iop_Not1,
152971f5fe1fc3a37ca729925e8eec25aa1025b4a6cdbcarll                       unop( Iop_32to1,
152981f5fe1fc3a37ca729925e8eec25aa1025b4a6cdbcarll                             binop( Iop_Shr32,
152991f5fe1fc3a37ca729925e8eec25aa1025b4a6cdbcarll                                    unop( Iop_64HIto32,
153001f5fe1fc3a37ca729925e8eec25aa1025b4a6cdbcarll                                          binop( Iop_And64,
153011f5fe1fc3a37ca729925e8eec25aa1025b4a6cdbcarll                                                 mkexpr(BHi_signed),
153021f5fe1fc3a37ca729925e8eec25aa1025b4a6cdbcarll                                                 mkU64(~VG_PPC_SIGN_MASK) )
153031f5fe1fc3a37ca729925e8eec25aa1025b4a6cdbcarll                                          ),
153041f5fe1fc3a37ca729925e8eec25aa1025b4a6cdbcarll                                    mkU8(31) ) ) ) );
153051f5fe1fc3a37ca729925e8eec25aa1025b4a6cdbcarll         assign( BHi_negated,
153061f5fe1fc3a37ca729925e8eec25aa1025b4a6cdbcarll                 binop( Iop_Or64,
153071f5fe1fc3a37ca729925e8eec25aa1025b4a6cdbcarll                        binop( Iop_32HLto64,
153081f5fe1fc3a37ca729925e8eec25aa1025b4a6cdbcarll                               binop( Iop_Shl32,
153091f5fe1fc3a37ca729925e8eec25aa1025b4a6cdbcarll                                      unop( Iop_1Uto32,
153101f5fe1fc3a37ca729925e8eec25aa1025b4a6cdbcarll                                            mkexpr(BHi_negated_signbit) ),
153111f5fe1fc3a37ca729925e8eec25aa1025b4a6cdbcarll                                      mkU8(31) ),
153121f5fe1fc3a37ca729925e8eec25aa1025b4a6cdbcarll                               mkU32(0) ),
153131f5fe1fc3a37ca729925e8eec25aa1025b4a6cdbcarll                        mkexpr(BHi_unsigned) ) );
153141f5fe1fc3a37ca729925e8eec25aa1025b4a6cdbcarll         assign( vec_result, binop( Iop_64HLtoV128, mkexpr(BHi_negated),
153151f5fe1fc3a37ca729925e8eec25aa1025b4a6cdbcarll                                    mkU64(0x0ULL)));
153161f5fe1fc3a37ca729925e8eec25aa1025b4a6cdbcarll         putVSReg( XT, mkexpr(vec_result));
1531766d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj         break;
1531866d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj      }
153194aa412af1d8166cc11f39a6e721df49431d23618sewardj      case 0x280: // xsmaxdp (VSX Scalar Maximum Double-Precision)
153204aa412af1d8166cc11f39a6e721df49431d23618sewardj      case 0x2A0: // xsmindp (VSX Scalar Minimum Double-Precision)
153214aa412af1d8166cc11f39a6e721df49431d23618sewardj      {
153224aa412af1d8166cc11f39a6e721df49431d23618sewardj         IRTemp frA     = newTemp(Ity_I64);
153234aa412af1d8166cc11f39a6e721df49431d23618sewardj         IRTemp frB     = newTemp(Ity_I64);
153244aa412af1d8166cc11f39a6e721df49431d23618sewardj         Bool isMin = opc2 == 0x2A0 ? True : False;
15325b173774421d015736c2316b5e6e998e7de545a5cflorian         DIP("%s v%d,v%d v%d\n", isMin ? "xsmaxdp" : "xsmindp", XT, XA, XB);
153264aa412af1d8166cc11f39a6e721df49431d23618sewardj
153274aa412af1d8166cc11f39a6e721df49431d23618sewardj         assign(frA, unop(Iop_V128HIto64, mkexpr( vA )));
153284aa412af1d8166cc11f39a6e721df49431d23618sewardj         assign(frB, unop(Iop_V128HIto64, mkexpr( vB )));
153294aa412af1d8166cc11f39a6e721df49431d23618sewardj         putVSReg( XT, binop( Iop_64HLtoV128, get_max_min_fp(frA, frB, isMin), mkU64( 0 ) ) );
153304aa412af1d8166cc11f39a6e721df49431d23618sewardj
153314aa412af1d8166cc11f39a6e721df49431d23618sewardj         break;
153324aa412af1d8166cc11f39a6e721df49431d23618sewardj      }
153334aa412af1d8166cc11f39a6e721df49431d23618sewardj      case 0x0F2: // xsrdpim (VSX Scalar Round to Double-Precision Integer using round toward -Infinity)
15334e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj      case 0x0D2: // xsrdpip (VSX Scalar Round to Double-Precision Integer using round toward +Infinity)
15335e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj      case 0x0D6: // xsrdpic (VSX Scalar Round to Double-Precision Integer using Current rounding mode)
15336e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj      case 0x0B2: // xsrdpiz (VSX Scalar Round to Double-Precision Integer using round toward Zero)
15337e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj      case 0x092: // xsrdpi  (VSX Scalar Round to Double-Precision Integer using round toward Nearest Away)
153384aa412af1d8166cc11f39a6e721df49431d23618sewardj      {
153394aa412af1d8166cc11f39a6e721df49431d23618sewardj         IRTemp frB_I64 = newTemp(Ity_I64);
15340e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj         IRExpr * frD_fp_round = NULL;
15341e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj
153424aa412af1d8166cc11f39a6e721df49431d23618sewardj         assign(frB_I64, unop(Iop_V128HIto64, mkexpr( vB )));
153439884af0b3cfe935b8fab54231f394fe4ee2d7ebccarll         frD_fp_round = _do_vsx_fp_roundToInt(frB_I64, opc2);
153444aa412af1d8166cc11f39a6e721df49431d23618sewardj
15345b173774421d015736c2316b5e6e998e7de545a5cflorian         DIP("xsrdpi%s v%d,v%d\n", _get_vsx_rdpi_suffix(opc2), XT, XB);
153464aa412af1d8166cc11f39a6e721df49431d23618sewardj         putVSReg( XT,
153474aa412af1d8166cc11f39a6e721df49431d23618sewardj                   binop( Iop_64HLtoV128,
15348e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj                          unop( Iop_ReinterpF64asI64, frD_fp_round),
153494aa412af1d8166cc11f39a6e721df49431d23618sewardj                          mkU64( 0 ) ) );
15350e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj         break;
15351e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj      }
153526c758b64a77c254065ab7450576bbd3a0b583595carll      case 0x034: // xsresp (VSX Scalar Reciprocal Estimate single-Precision)
153536c758b64a77c254065ab7450576bbd3a0b583595carll      case 0x014: /* xsrsqrtesp (VSX Scalar Reciprocal Square Root Estimate
153546c758b64a77c254065ab7450576bbd3a0b583595carll                   * single-Precision)
153556c758b64a77c254065ab7450576bbd3a0b583595carll                   */
153566c758b64a77c254065ab7450576bbd3a0b583595carll      {
153576c758b64a77c254065ab7450576bbd3a0b583595carll         IRTemp frB = newTemp(Ity_F64);
153586c758b64a77c254065ab7450576bbd3a0b583595carll         IRTemp sqrt = newTemp(Ity_F64);
153596c758b64a77c254065ab7450576bbd3a0b583595carll         IRExpr* ieee_one = IRExpr_Const(IRConst_F64i(0x3ff0000000000000ULL));
153606c758b64a77c254065ab7450576bbd3a0b583595carll         IRExpr* rm  = get_IR_roundingmode();
153616c758b64a77c254065ab7450576bbd3a0b583595carll         Bool redp = opc2 == 0x034;
15362b173774421d015736c2316b5e6e998e7de545a5cflorian         DIP("%s v%d,v%d\n", redp ? "xsresp" : "xsrsqrtesp", XT,
15363b173774421d015736c2316b5e6e998e7de545a5cflorian             XB);
153646c758b64a77c254065ab7450576bbd3a0b583595carll
153656c758b64a77c254065ab7450576bbd3a0b583595carll         assign( frB,
153666c758b64a77c254065ab7450576bbd3a0b583595carll                 unop( Iop_ReinterpI64asF64,
153676c758b64a77c254065ab7450576bbd3a0b583595carll                       unop( Iop_V128HIto64, mkexpr( vB ) ) ) );
153686c758b64a77c254065ab7450576bbd3a0b583595carll
153696c758b64a77c254065ab7450576bbd3a0b583595carll         if (!redp)
153706c758b64a77c254065ab7450576bbd3a0b583595carll            assign( sqrt,
153716c758b64a77c254065ab7450576bbd3a0b583595carll                    binop( Iop_SqrtF64,
153726c758b64a77c254065ab7450576bbd3a0b583595carll                           rm,
153736c758b64a77c254065ab7450576bbd3a0b583595carll                           mkexpr(frB) ) );
153746c758b64a77c254065ab7450576bbd3a0b583595carll         putVSReg( XT,
153756c758b64a77c254065ab7450576bbd3a0b583595carll                      binop( Iop_64HLtoV128,
153766c758b64a77c254065ab7450576bbd3a0b583595carll                             unop( Iop_ReinterpF64asI64,
153776c758b64a77c254065ab7450576bbd3a0b583595carll                                   binop( Iop_RoundF64toF32, rm,
153786c758b64a77c254065ab7450576bbd3a0b583595carll                                          triop( Iop_DivF64,
153796c758b64a77c254065ab7450576bbd3a0b583595carll                                                 rm,
153806c758b64a77c254065ab7450576bbd3a0b583595carll                                                 ieee_one,
153816c758b64a77c254065ab7450576bbd3a0b583595carll                                                 redp ? mkexpr( frB ) :
153826c758b64a77c254065ab7450576bbd3a0b583595carll                                                        mkexpr( sqrt ) ) ) ),
153836c758b64a77c254065ab7450576bbd3a0b583595carll                             mkU64( 0 ) ) );
153846c758b64a77c254065ab7450576bbd3a0b583595carll         break;
153856c758b64a77c254065ab7450576bbd3a0b583595carll      }
153866c758b64a77c254065ab7450576bbd3a0b583595carll
15387e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj      case 0x0B4: // xsredp (VSX Scalar Reciprocal Estimate Double-Precision)
15388e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj      case 0x094: // xsrsqrtedp (VSX Scalar Reciprocal Square Root Estimate Double-Precision)
153894aa412af1d8166cc11f39a6e721df49431d23618sewardj
15390e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj      {
15391e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj         IRTemp frB = newTemp(Ity_F64);
15392e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj         IRTemp sqrt = newTemp(Ity_F64);
15393e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj         IRExpr* ieee_one = IRExpr_Const(IRConst_F64i(0x3ff0000000000000ULL));
15394e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj         IRExpr* rm  = get_IR_roundingmode();
15395e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj         Bool redp = opc2 == 0x0B4;
15396b173774421d015736c2316b5e6e998e7de545a5cflorian         DIP("%s v%d,v%d\n", redp ? "xsredp" : "xsrsqrtedp", XT, XB);
15397e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj         assign( frB,
15398e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj                 unop( Iop_ReinterpI64asF64,
15399e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj                       unop( Iop_V128HIto64, mkexpr( vB ) ) ) );
15400e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj
15401e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj         if (!redp)
15402e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj            assign( sqrt,
15403e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj                    binop( Iop_SqrtF64,
15404e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj                           rm,
15405e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj                           mkexpr(frB) ) );
15406e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj         putVSReg( XT,
15407e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj                      binop( Iop_64HLtoV128,
15408e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj                             unop( Iop_ReinterpF64asI64,
15409e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj                                   triop( Iop_DivF64,
15410e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj                                          rm,
15411e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj                                          ieee_one,
15412e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj                                          redp ? mkexpr( frB ) : mkexpr( sqrt ) ) ),
15413e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj                             mkU64( 0 ) ) );
154144aa412af1d8166cc11f39a6e721df49431d23618sewardj         break;
154154aa412af1d8166cc11f39a6e721df49431d23618sewardj      }
1541666d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj
154176c758b64a77c254065ab7450576bbd3a0b583595carll      case 0x232: // xsrsp (VSX Scalar Round to Single-Precision)
154186c758b64a77c254065ab7450576bbd3a0b583595carll      {
154196c758b64a77c254065ab7450576bbd3a0b583595carll         IRTemp frB = newTemp(Ity_F64);
154206c758b64a77c254065ab7450576bbd3a0b583595carll         IRExpr* rm  = get_IR_roundingmode();
15421b173774421d015736c2316b5e6e998e7de545a5cflorian         DIP("xsrsp v%d, v%d\n", XT, XB);
154226c758b64a77c254065ab7450576bbd3a0b583595carll         assign( frB,
154236c758b64a77c254065ab7450576bbd3a0b583595carll                 unop( Iop_ReinterpI64asF64,
154246c758b64a77c254065ab7450576bbd3a0b583595carll                       unop( Iop_V128HIto64, mkexpr( vB ) ) ) );
154256c758b64a77c254065ab7450576bbd3a0b583595carll
154266c758b64a77c254065ab7450576bbd3a0b583595carll         putVSReg( XT, binop( Iop_64HLtoV128,
154276c758b64a77c254065ab7450576bbd3a0b583595carll                              unop( Iop_ReinterpF64asI64,
154286c758b64a77c254065ab7450576bbd3a0b583595carll                                    binop( Iop_RoundF64toF32,
154296c758b64a77c254065ab7450576bbd3a0b583595carll                                           rm,
154306c758b64a77c254065ab7450576bbd3a0b583595carll                                           mkexpr( frB ) ) ),
154316c758b64a77c254065ab7450576bbd3a0b583595carll                              mkU64( 0 ) ) );
154326c758b64a77c254065ab7450576bbd3a0b583595carll         break;
154336c758b64a77c254065ab7450576bbd3a0b583595carll      }
154346c758b64a77c254065ab7450576bbd3a0b583595carll
1543566d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj      default:
154364aa412af1d8166cc11f39a6e721df49431d23618sewardj         vex_printf( "dis_vxs_misc(ppc)(opc2)\n" );
1543766d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj         return False;
1543866d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj   }
1543966d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj   return True;
1544066d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj}
1544166d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj
1544266d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj/*
1544366d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj * VSX Logical Instructions
1544466d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj */
1544566d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardjstatic Bool
1544666d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardjdis_vx_logic ( UInt theInstr, UInt opc2 )
1544766d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj{
1544866d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj   /* XX3-Form */
1544966d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj   UChar opc1 = ifieldOPC( theInstr );
1545066d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj   UChar XT = ifieldRegXT ( theInstr );
1545166d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj   UChar XA = ifieldRegXA ( theInstr );
1545266d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj   UChar XB = ifieldRegXB ( theInstr );
1545366d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj   IRTemp vA = newTemp( Ity_V128 );
1545466d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj   IRTemp vB = newTemp( Ity_V128 );
1545566d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj
1545666d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj   if (opc1 != 0x3C) {
1545766d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj      vex_printf( "dis_vx_logic(ppc)(instr)\n" );
1545866d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj      return False;
1545966d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj   }
1546066d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj
1546166d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj   assign( vA, getVSReg( XA ) );
1546266d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj   assign( vB, getVSReg( XB ) );
1546366d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj
1546466d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj   switch (opc2) {
1546566d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj      case 0x268: // xxlxor
15466b173774421d015736c2316b5e6e998e7de545a5cflorian         DIP("xxlxor v%d,v%d,v%d\n", XT, XA, XB);
1546766d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj         putVSReg( XT, binop( Iop_XorV128, mkexpr( vA ), mkexpr( vB ) ) );
1546866d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj         break;
1546966d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj      case 0x248: // xxlor
15470b173774421d015736c2316b5e6e998e7de545a5cflorian         DIP("xxlor v%d,v%d,v%d\n", XT, XA, XB);
1547166d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj         putVSReg( XT, binop( Iop_OrV128, mkexpr( vA ), mkexpr( vB ) ) );
1547266d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj         break;
1547366d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj      case 0x288: // xxlnor
15474b173774421d015736c2316b5e6e998e7de545a5cflorian         DIP("xxlnor v%d,v%d,v%d\n", XT, XA, XB);
1547566d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj         putVSReg( XT, unop( Iop_NotV128, binop( Iop_OrV128, mkexpr( vA ),
1547666d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj                                                 mkexpr( vB ) ) ) );
1547766d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj         break;
1547866d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj      case 0x208: // xxland
15479b173774421d015736c2316b5e6e998e7de545a5cflorian         DIP("xxland v%d,v%d,v%d\n", XT, XA, XB);
1548066d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj         putVSReg( XT, binop( Iop_AndV128, mkexpr( vA ), mkexpr( vB ) ) );
1548166d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj         break;
1548266d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj      case 0x228: //xxlandc
15483b173774421d015736c2316b5e6e998e7de545a5cflorian         DIP("xxlandc v%d,v%d,v%d\n", XT, XA, XB);
1548466d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj         putVSReg( XT, binop( Iop_AndV128, mkexpr( vA ), unop( Iop_NotV128,
1548566d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj                                                               mkexpr( vB ) ) ) );
1548666d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj         break;
154876c758b64a77c254065ab7450576bbd3a0b583595carll      case 0x2A8: // xxlorc (VSX Logical OR with complement)
15488b173774421d015736c2316b5e6e998e7de545a5cflorian         DIP("xxlorc v%d,v%d,v%d\n", XT, XA, XB);
154896c758b64a77c254065ab7450576bbd3a0b583595carll         putVSReg( XT, binop( Iop_OrV128,
154906c758b64a77c254065ab7450576bbd3a0b583595carll                              mkexpr( vA ),
154916c758b64a77c254065ab7450576bbd3a0b583595carll                              unop( Iop_NotV128, mkexpr( vB ) ) ) );
154926c758b64a77c254065ab7450576bbd3a0b583595carll         break;
154936c758b64a77c254065ab7450576bbd3a0b583595carll      case 0x2C8: // xxlnand (VSX Logical NAND)
15494b173774421d015736c2316b5e6e998e7de545a5cflorian         DIP("xxlnand v%d,v%d,v%d\n", XT, XA, XB);
154956c758b64a77c254065ab7450576bbd3a0b583595carll         putVSReg( XT, unop( Iop_NotV128,
154966c758b64a77c254065ab7450576bbd3a0b583595carll                             binop( Iop_AndV128, mkexpr( vA ),
154976c758b64a77c254065ab7450576bbd3a0b583595carll                                    mkexpr( vB ) ) ) );
154986c758b64a77c254065ab7450576bbd3a0b583595carll         break;
154996c758b64a77c254065ab7450576bbd3a0b583595carll      case 0x2E8: // xxleqv (VSX Logical Equivalence)
15500b173774421d015736c2316b5e6e998e7de545a5cflorian         DIP("xxleqv v%d,v%d,v%d\n", XT, XA, XB);
155016c758b64a77c254065ab7450576bbd3a0b583595carll         putVSReg( XT, unop( Iop_NotV128,
155026c758b64a77c254065ab7450576bbd3a0b583595carll                             binop( Iop_XorV128,
155036c758b64a77c254065ab7450576bbd3a0b583595carll                             mkexpr( vA ), mkexpr( vB ) ) ) );
155046c758b64a77c254065ab7450576bbd3a0b583595carll         break;
1550566d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj      default:
1550666d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj         vex_printf( "dis_vx_logic(ppc)(opc2)\n" );
1550766d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj         return False;
1550866d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj   }
1550966d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj   return True;
1551066d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj}
1551166d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj
1551266d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj/*
1551366d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj * VSX Load Instructions
1551466d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj * NOTE: VSX supports word-aligned storage access.
1551566d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj */
1551666d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardjstatic Bool
1551766d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardjdis_vx_load ( UInt theInstr )
1551866d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj{
1551966d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj   /* XX1-Form */
1552066d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj   UChar opc1 = ifieldOPC( theInstr );
1552166d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj   UChar XT = ifieldRegXT ( theInstr );
1552266d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj   UChar rA_addr = ifieldRegA( theInstr );
1552366d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj   UChar rB_addr = ifieldRegB( theInstr );
1552466d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj   UInt opc2 = ifieldOPClo10( theInstr );
1552566d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj
1552666d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj   IRType ty = mode64 ? Ity_I64 : Ity_I32;
1552766d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj   IRTemp EA = newTemp( ty );
1552866d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj
1552966d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj   if (opc1 != 0x1F) {
1553066d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj      vex_printf( "dis_vx_load(ppc)(instr)\n" );
1553166d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj      return False;
1553266d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj   }
1553366d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj
1553466d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj   assign( EA, ea_rAor0_idxd( rA_addr, rB_addr ) );
1553566d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj
1553666d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj   switch (opc2) {
155376c758b64a77c254065ab7450576bbd3a0b583595carll   case 0x00C: // lxsiwzx (Load VSX Scalar as Integer Word and Zero Indexed)
155386c758b64a77c254065ab7450576bbd3a0b583595carll   {
155396c758b64a77c254065ab7450576bbd3a0b583595carll      IRExpr * exp;
15540b173774421d015736c2316b5e6e998e7de545a5cflorian      DIP("lxsiwzx %d,r%u,r%u\n", XT, rA_addr, rB_addr);
15541256df5959b423b38443329b15e4b1ff74240da1ecarll
15542256df5959b423b38443329b15e4b1ff74240da1ecarll      if (host_endness == VexEndnessLE)
15543256df5959b423b38443329b15e4b1ff74240da1ecarll         exp = unop( Iop_64to32, load( Ity_I64, mkexpr( EA ) ) );
15544256df5959b423b38443329b15e4b1ff74240da1ecarll      else
15545256df5959b423b38443329b15e4b1ff74240da1ecarll         exp = unop( Iop_64HIto32, load( Ity_I64, mkexpr( EA ) ) );
15546256df5959b423b38443329b15e4b1ff74240da1ecarll
155476c758b64a77c254065ab7450576bbd3a0b583595carll      putVSReg( XT, binop( Iop_64HLtoV128,
155486c758b64a77c254065ab7450576bbd3a0b583595carll                           unop( Iop_32Uto64, exp),
155496c758b64a77c254065ab7450576bbd3a0b583595carll                           mkU64(0) ) );
155506c758b64a77c254065ab7450576bbd3a0b583595carll      break;
155516c758b64a77c254065ab7450576bbd3a0b583595carll   }
155526c758b64a77c254065ab7450576bbd3a0b583595carll   case 0x04C: // lxsiwax (Load VSX Scalar as Integer Word Algebraic Indexed)
155536c758b64a77c254065ab7450576bbd3a0b583595carll   {
155546c758b64a77c254065ab7450576bbd3a0b583595carll      IRExpr * exp;
15555b173774421d015736c2316b5e6e998e7de545a5cflorian      DIP("lxsiwax %d,r%u,r%u\n", XT, rA_addr, rB_addr);
15556256df5959b423b38443329b15e4b1ff74240da1ecarll
15557256df5959b423b38443329b15e4b1ff74240da1ecarll      if (host_endness == VexEndnessLE)
15558256df5959b423b38443329b15e4b1ff74240da1ecarll         exp = unop( Iop_64to32, load( Ity_I64, mkexpr( EA ) ) );
15559256df5959b423b38443329b15e4b1ff74240da1ecarll      else
15560256df5959b423b38443329b15e4b1ff74240da1ecarll         exp = unop( Iop_64HIto32, load( Ity_I64, mkexpr( EA ) ) );
15561256df5959b423b38443329b15e4b1ff74240da1ecarll
155626c758b64a77c254065ab7450576bbd3a0b583595carll      putVSReg( XT, binop( Iop_64HLtoV128,
155636c758b64a77c254065ab7450576bbd3a0b583595carll                           unop( Iop_32Sto64, exp),
155646c758b64a77c254065ab7450576bbd3a0b583595carll                           mkU64(0) ) );
155656c758b64a77c254065ab7450576bbd3a0b583595carll      break;
155666c758b64a77c254065ab7450576bbd3a0b583595carll   }
155676c758b64a77c254065ab7450576bbd3a0b583595carll   case 0x20C: // lxsspx (Load VSX Scalar Single-Precision Indexed)
155686c758b64a77c254065ab7450576bbd3a0b583595carll   {
155696c758b64a77c254065ab7450576bbd3a0b583595carll      IRExpr * exp;
15570b173774421d015736c2316b5e6e998e7de545a5cflorian      DIP("lxsspx %d,r%u,r%u\n", XT, rA_addr, rB_addr);
155716c758b64a77c254065ab7450576bbd3a0b583595carll      /* Take 32-bit floating point value in the upper half of the fetched
155726c758b64a77c254065ab7450576bbd3a0b583595carll       * 64-bit value, convert to 64-bit floating point value and load into
155736c758b64a77c254065ab7450576bbd3a0b583595carll       * top word of V128.
155746c758b64a77c254065ab7450576bbd3a0b583595carll       */
155756c758b64a77c254065ab7450576bbd3a0b583595carll      exp = unop( Iop_ReinterpF64asI64,
155766c758b64a77c254065ab7450576bbd3a0b583595carll                  unop( Iop_F32toF64,
155776c758b64a77c254065ab7450576bbd3a0b583595carll                        unop( Iop_ReinterpI32asF32,
155781f5fe1fc3a37ca729925e8eec25aa1025b4a6cdbcarll                              load( Ity_I32, mkexpr( EA ) ) ) ) );
155796c758b64a77c254065ab7450576bbd3a0b583595carll
155806c758b64a77c254065ab7450576bbd3a0b583595carll      putVSReg( XT, binop( Iop_64HLtoV128, exp, mkU64( 0 ) ) );
155816c758b64a77c254065ab7450576bbd3a0b583595carll      break;
155826c758b64a77c254065ab7450576bbd3a0b583595carll   }
1558366d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj   case 0x24C: // lxsdx
1558466d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj   {
1558566d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj      IRExpr * exp;
15586b173774421d015736c2316b5e6e998e7de545a5cflorian      DIP("lxsdx %d,r%u,r%u\n", XT, rA_addr, rB_addr);
155871f5fe1fc3a37ca729925e8eec25aa1025b4a6cdbcarll      exp = load( Ity_I64, mkexpr( EA ) );
1558866d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj      // We need to pass an expression of type Ity_V128 with putVSReg, but the load
1558966d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj      // we just performed is only a DW.  But since the contents of VSR[XT] element 1
1559066d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj      // are undefined after this operation, we can just do a splat op.
1559166d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj      putVSReg( XT, binop( Iop_64HLtoV128, exp, exp ) );
1559266d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj      break;
1559366d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj   }
1559466d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj   case 0x34C: // lxvd2x
1559566d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj   {
1559666d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj      IROp addOp = ty == Ity_I64 ? Iop_Add64 : Iop_Add32;
1559766d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj      IRExpr * high, *low;
1559866d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj      ULong ea_off = 8;
1559966d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj      IRExpr* high_addr;
15600b173774421d015736c2316b5e6e998e7de545a5cflorian      DIP("lxvd2x %d,r%u,r%u\n", XT, rA_addr, rB_addr);
156011f5fe1fc3a37ca729925e8eec25aa1025b4a6cdbcarll      high = load( Ity_I64, mkexpr( EA ) );
1560266d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj      high_addr = binop( addOp, mkexpr( EA ), ty == Ity_I64 ? mkU64( ea_off )
1560366d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj            : mkU32( ea_off ) );
156041f5fe1fc3a37ca729925e8eec25aa1025b4a6cdbcarll      low = load( Ity_I64, high_addr );
1560566d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj      putVSReg( XT, binop( Iop_64HLtoV128, high, low ) );
1560666d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj      break;
1560766d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj   }
1560866d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj   case 0x14C: // lxvdsx
1560966d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj   {
1561066d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj      IRTemp data = newTemp(Ity_I64);
15611b173774421d015736c2316b5e6e998e7de545a5cflorian      DIP("lxvdsx %d,r%u,r%u\n", XT, rA_addr, rB_addr);
156121f5fe1fc3a37ca729925e8eec25aa1025b4a6cdbcarll      assign( data, load( Ity_I64, mkexpr( EA ) ) );
1561366d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj      putVSReg( XT, binop( Iop_64HLtoV128, mkexpr( data ), mkexpr( data ) ) );
1561466d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj      break;
1561566d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj   }
1561666d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj   case 0x30C:
1561766d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj   {
156184e303f232d62781940a56d48649118f4d801abc1carll      IRExpr *t0;
1561966d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj
15620b173774421d015736c2316b5e6e998e7de545a5cflorian      DIP("lxvw4x %d,r%u,r%u\n", XT, rA_addr, rB_addr);
156214e303f232d62781940a56d48649118f4d801abc1carll
1562285175a7453c4cc4a7d29a247766b627d5cb933decarll      /* The load will result in the data being in BE order. */
1562385175a7453c4cc4a7d29a247766b627d5cb933decarll      if (host_endness == VexEndnessLE) {
1562485175a7453c4cc4a7d29a247766b627d5cb933decarll         IRExpr *t0_BE;
1562585175a7453c4cc4a7d29a247766b627d5cb933decarll         IRTemp perm_LE = newTemp(Ity_V128);
1562685175a7453c4cc4a7d29a247766b627d5cb933decarll
1562785175a7453c4cc4a7d29a247766b627d5cb933decarll         t0_BE = load( Ity_V128, mkexpr( EA ) );
1562885175a7453c4cc4a7d29a247766b627d5cb933decarll
1562985175a7453c4cc4a7d29a247766b627d5cb933decarll         /*  Permute the data to LE format */
156304047e01fdfc71ddfa1912bd29de45f20fcb77355carll         assign( perm_LE, binop( Iop_64HLtoV128, mkU64(0x0c0d0e0f08090a0bULL),
156314047e01fdfc71ddfa1912bd29de45f20fcb77355carll                                 mkU64(0x0405060700010203ULL)));
1563285175a7453c4cc4a7d29a247766b627d5cb933decarll
1563385175a7453c4cc4a7d29a247766b627d5cb933decarll         t0 = binop( Iop_Perm8x16, t0_BE, mkexpr(perm_LE) );
1563485175a7453c4cc4a7d29a247766b627d5cb933decarll      } else {
1563585175a7453c4cc4a7d29a247766b627d5cb933decarll         t0 = load( Ity_V128, mkexpr( EA ) );
1563685175a7453c4cc4a7d29a247766b627d5cb933decarll      }
1563785175a7453c4cc4a7d29a247766b627d5cb933decarll
156384e303f232d62781940a56d48649118f4d801abc1carll      putVSReg( XT, t0 );
1563966d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj      break;
1564066d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj   }
1564166d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj   default:
1564266d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj      vex_printf( "dis_vx_load(ppc)(opc2)\n" );
1564366d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj      return False;
1564466d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj   }
1564566d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj   return True;
1564666d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj}
1564766d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj
1564866d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj/*
1564966d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj * VSX Store Instructions
1565066d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj * NOTE: VSX supports word-aligned storage access.
1565166d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj */
1565266d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardjstatic Bool
1565366d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardjdis_vx_store ( UInt theInstr )
1565466d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj{
1565566d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj   /* XX1-Form */
1565666d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj   UChar opc1 = ifieldOPC( theInstr );
1565766d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj   UChar XS = ifieldRegXS( theInstr );
1565866d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj   UChar rA_addr = ifieldRegA( theInstr );
1565966d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj   UChar rB_addr = ifieldRegB( theInstr );
1566066d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj   IRTemp vS = newTemp( Ity_V128 );
1566166d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj   UInt opc2 = ifieldOPClo10( theInstr );
1566266d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj
1566366d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj   IRType ty = mode64 ? Ity_I64 : Ity_I32;
1566466d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj   IRTemp EA = newTemp( ty );
1566566d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj
1566666d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj   if (opc1 != 0x1F) {
1566766d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj      vex_printf( "dis_vx_store(ppc)(instr)\n" );
1566866d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj      return False;
1566966d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj   }
1567066d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj
1567166d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj   assign( EA, ea_rAor0_idxd( rA_addr, rB_addr ) );
1567266d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj   assign( vS, getVSReg( XS ) );
1567366d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj
1567466d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj   switch (opc2) {
156756c758b64a77c254065ab7450576bbd3a0b583595carll   case 0x08C:
156766c758b64a77c254065ab7450576bbd3a0b583595carll   {
156776c758b64a77c254065ab7450576bbd3a0b583595carll     /* Need the next to the most significant 32-bit word from
156786c758b64a77c254065ab7450576bbd3a0b583595carll      * the 128-bit vector.
156796c758b64a77c254065ab7450576bbd3a0b583595carll      */
156806c758b64a77c254065ab7450576bbd3a0b583595carll      IRExpr * high64, * low32;
15681b173774421d015736c2316b5e6e998e7de545a5cflorian      DIP("stxsiwx %d,r%u,r%u\n", XS, rA_addr, rB_addr);
156826c758b64a77c254065ab7450576bbd3a0b583595carll      high64 = unop( Iop_V128HIto64, mkexpr( vS ) );
156836c758b64a77c254065ab7450576bbd3a0b583595carll      low32  = unop( Iop_64to32, high64 );
156841f5fe1fc3a37ca729925e8eec25aa1025b4a6cdbcarll      store( mkexpr( EA ), low32 );
156856c758b64a77c254065ab7450576bbd3a0b583595carll      break;
156866c758b64a77c254065ab7450576bbd3a0b583595carll   }
156876c758b64a77c254065ab7450576bbd3a0b583595carll   case 0x28C:
156886c758b64a77c254065ab7450576bbd3a0b583595carll   {
156896c758b64a77c254065ab7450576bbd3a0b583595carll      IRTemp high64 = newTemp(Ity_F64);
156906c758b64a77c254065ab7450576bbd3a0b583595carll      IRTemp val32  = newTemp(Ity_I32);
15691b173774421d015736c2316b5e6e998e7de545a5cflorian      DIP("stxsspx %d,r%u,r%u\n", XS, rA_addr, rB_addr);
156926c758b64a77c254065ab7450576bbd3a0b583595carll      assign(high64, unop( Iop_ReinterpI64asF64,
156936c758b64a77c254065ab7450576bbd3a0b583595carll                           unop( Iop_V128HIto64, mkexpr( vS ) ) ) );
156946c758b64a77c254065ab7450576bbd3a0b583595carll      assign(val32, unop( Iop_ReinterpF32asI32,
156956c758b64a77c254065ab7450576bbd3a0b583595carll                          unop( Iop_TruncF64asF32,
156966c758b64a77c254065ab7450576bbd3a0b583595carll                                mkexpr(high64) ) ) );
156971f5fe1fc3a37ca729925e8eec25aa1025b4a6cdbcarll      store( mkexpr( EA ), mkexpr( val32 ) );
156986c758b64a77c254065ab7450576bbd3a0b583595carll      break;
156996c758b64a77c254065ab7450576bbd3a0b583595carll   }
1570066d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj   case 0x2CC:
1570166d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj   {
1570266d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj      IRExpr * high64;
15703b173774421d015736c2316b5e6e998e7de545a5cflorian      DIP("stxsdx %d,r%u,r%u\n", XS, rA_addr, rB_addr);
1570466d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj      high64 = unop( Iop_V128HIto64, mkexpr( vS ) );
157051f5fe1fc3a37ca729925e8eec25aa1025b4a6cdbcarll      store( mkexpr( EA ), high64 );
1570666d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj      break;
1570766d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj   }
1570866d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj   case 0x3CC:
1570966d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj   {
1571066d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj      IRExpr * high64, *low64;
15711b173774421d015736c2316b5e6e998e7de545a5cflorian      DIP("stxvd2x %d,r%u,r%u\n", XS, rA_addr, rB_addr);
1571266d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj      high64 = unop( Iop_V128HIto64, mkexpr( vS ) );
1571366d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj      low64 = unop( Iop_V128to64, mkexpr( vS ) );
157141f5fe1fc3a37ca729925e8eec25aa1025b4a6cdbcarll      store( mkexpr( EA ), high64 );
157151f5fe1fc3a37ca729925e8eec25aa1025b4a6cdbcarll      store( binop( mkSzOp( ty, Iop_Add8 ), mkexpr( EA ),
157161f5fe1fc3a37ca729925e8eec25aa1025b4a6cdbcarll                    ty == Ity_I64 ? mkU64( 8 ) : mkU32( 8 ) ), low64 );
1571766d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj      break;
1571866d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj   }
1571966d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj   case 0x38C:
1572066d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj   {
1572166d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj      UInt ea_off = 0;
1572266d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj      IRExpr* irx_addr;
1572366d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj      IRTemp hi64 = newTemp( Ity_I64 );
1572466d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj      IRTemp lo64 = newTemp( Ity_I64 );
1572566d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj
15726b173774421d015736c2316b5e6e998e7de545a5cflorian      DIP("stxvw4x %d,r%u,r%u\n", XS, rA_addr, rB_addr);
1572766d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj
1572866d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj      // This instruction supports word-aligned stores, so EA may not be
1572966d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj      // quad-word aligned.  Therefore, do 4 individual word-size stores.
1573066d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj      assign( hi64, unop( Iop_V128HIto64, mkexpr( vS ) ) );
1573166d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj      assign( lo64, unop( Iop_V128to64, mkexpr( vS ) ) );
157321f5fe1fc3a37ca729925e8eec25aa1025b4a6cdbcarll      store( mkexpr( EA ), unop( Iop_64HIto32, mkexpr( hi64 ) ) );
1573366d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj      ea_off += 4;
1573466d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj      irx_addr = binop( mkSzOp( ty, Iop_Add8 ), mkexpr( EA ),
1573566d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj                        ty == Ity_I64 ? mkU64( ea_off ) : mkU32( ea_off ) );
157361f5fe1fc3a37ca729925e8eec25aa1025b4a6cdbcarll      store( irx_addr, unop( Iop_64to32, mkexpr( hi64 ) ) );
1573766d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj      ea_off += 4;
1573866d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj      irx_addr = binop( mkSzOp( ty, Iop_Add8 ), mkexpr( EA ),
1573966d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj                        ty == Ity_I64 ? mkU64( ea_off ) : mkU32( ea_off ) );
157401f5fe1fc3a37ca729925e8eec25aa1025b4a6cdbcarll      store( irx_addr, unop( Iop_64HIto32, mkexpr( lo64 ) ) );
1574166d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj      ea_off += 4;
1574266d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj      irx_addr = binop( mkSzOp( ty, Iop_Add8 ), mkexpr( EA ),
1574366d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj                        ty == Ity_I64 ? mkU64( ea_off ) : mkU32( ea_off ) );
157441f5fe1fc3a37ca729925e8eec25aa1025b4a6cdbcarll      store( irx_addr, unop( Iop_64to32, mkexpr( lo64 ) ) );
1574566d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj
1574666d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj      break;
1574766d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj   }
1574866d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj   default:
1574966d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj      vex_printf( "dis_vx_store(ppc)(opc2)\n" );
1575066d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj      return False;
1575166d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj   }
1575266d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj   return True;
1575366d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj}
1575466d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj
1575566d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj/*
157564aa412af1d8166cc11f39a6e721df49431d23618sewardj * VSX permute and other miscealleous instructions
1575766d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj */
1575866d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardjstatic Bool
157594aa412af1d8166cc11f39a6e721df49431d23618sewardjdis_vx_permute_misc( UInt theInstr, UInt opc2 )
1576066d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj{
1576166d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj   /* XX3-Form */
1576266d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj   UChar opc1 = ifieldOPC( theInstr );
1576366d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj   UChar XT = ifieldRegXT ( theInstr );
1576466d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj   UChar XA = ifieldRegXA ( theInstr );
1576566d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj   UChar XB = ifieldRegXB ( theInstr );
1576666d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj   IRTemp vT = newTemp( Ity_V128 );
1576766d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj   IRTemp vA = newTemp( Ity_V128 );
1576866d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj   IRTemp vB = newTemp( Ity_V128 );
1576966d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj
1577066d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj   if (opc1 != 0x3C) {
157714aa412af1d8166cc11f39a6e721df49431d23618sewardj      vex_printf( "dis_vx_permute_misc(ppc)(instr)\n" );
1577266d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj      return False;
1577366d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj   }
1577466d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj
1577566d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj   assign( vA, getVSReg( XA ) );
1577666d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj   assign( vB, getVSReg( XB ) );
1577766d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj
1577866d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj   switch (opc2) {
1577966d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj      case 0x8: // xxsldwi (VSX Shift Left Double by Word Immediate)
1578066d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj      {
1578166d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj         UChar SHW = ifieldSHW ( theInstr );
1578266d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj         IRTemp result = newTemp(Ity_V128);
1578366d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj         if ( SHW != 0 ) {
1578466d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj             IRTemp hi = newTemp(Ity_V128);
1578566d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj             IRTemp lo = newTemp(Ity_V128);
1578666d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj             assign( hi, binop(Iop_ShlV128, mkexpr(vA), mkU8(SHW*32)) );
1578766d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj             assign( lo, binop(Iop_ShrV128, mkexpr(vB), mkU8(128-SHW*32)) );
1578866d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj             assign ( result, binop(Iop_OrV128, mkexpr(hi), mkexpr(lo)) );
1578966d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj         } else
1579066d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj             assign ( result, mkexpr(vA) );
15791b173774421d015736c2316b5e6e998e7de545a5cflorian         DIP("xxsldwi v%d,v%d,v%d,%d\n", XT, XA, XB, SHW);
1579266d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj         putVSReg( XT, mkexpr(result) );
1579366d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj         break;
1579466d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj      }
1579566d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj      case 0x28: // xpermdi (VSX Permute Doubleword Immediate)
1579666d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj      {
1579766d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj         UChar DM = ifieldDM ( theInstr );
1579866d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj         IRTemp hi = newTemp(Ity_I64);
1579966d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj         IRTemp lo = newTemp(Ity_I64);
1580066d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj
1580166d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj         if (DM & 0x2)
1580266d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj           assign( hi, unop(Iop_V128to64, mkexpr(vA)) );
1580366d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj         else
1580466d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj           assign( hi, unop(Iop_V128HIto64, mkexpr(vA)) );
1580566d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj
1580666d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj         if (DM & 0x1)
1580766d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj           assign( lo, unop(Iop_V128to64, mkexpr(vB)) );
1580866d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj         else
1580966d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj           assign( lo, unop(Iop_V128HIto64, mkexpr(vB)) );
1581066d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj
1581166d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj         assign( vT, binop(Iop_64HLtoV128, mkexpr(hi), mkexpr(lo)) );
1581266d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj
15813b173774421d015736c2316b5e6e998e7de545a5cflorian         DIP("xxpermdi v%d,v%d,v%d,0x%x\n", XT, XA, XB, DM);
1581466d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj         putVSReg( XT, mkexpr( vT ) );
1581566d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj         break;
1581666d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj      }
1581766d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj      case 0x48: // xxmrghw (VSX Merge High Word)
1581866d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj      case 0xc8: // xxmrglw (VSX Merge Low Word)
1581966d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj      {
1582055085f8680acc89d727e321f3b34cae1a8c4093aflorian         const HChar type = (opc2 == 0x48) ? 'h' : 'l';
1582166d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj         IROp word_op = (opc2 == 0x48) ? Iop_V128HIto64 : Iop_V128to64;
1582266d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj         IRTemp a64 = newTemp(Ity_I64);
1582366d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj         IRTemp ahi32 = newTemp(Ity_I32);
1582466d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj         IRTemp alo32 = newTemp(Ity_I32);
1582566d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj         IRTemp b64 = newTemp(Ity_I64);
1582666d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj         IRTemp bhi32 = newTemp(Ity_I32);
1582766d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj         IRTemp blo32 = newTemp(Ity_I32);
1582866d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj
1582966d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj         assign( a64, unop(word_op, mkexpr(vA)) );
1583066d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj         assign( ahi32, unop(Iop_64HIto32, mkexpr(a64)) );
1583166d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj         assign( alo32, unop(Iop_64to32, mkexpr(a64)) );
1583266d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj
1583366d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj         assign( b64, unop(word_op, mkexpr(vB)) );
1583466d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj         assign( bhi32, unop(Iop_64HIto32, mkexpr(b64)) );
1583566d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj         assign( blo32, unop(Iop_64to32, mkexpr(b64)) );
1583666d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj
1583766d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj         assign( vT, binop(Iop_64HLtoV128,
1583866d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj                           binop(Iop_32HLto64, mkexpr(ahi32), mkexpr(bhi32)),
1583966d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj                           binop(Iop_32HLto64, mkexpr(alo32), mkexpr(blo32))) );
1584066d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj
15841b173774421d015736c2316b5e6e998e7de545a5cflorian         DIP("xxmrg%cw v%d,v%d,v%d\n", type, XT, XA, XB);
1584266d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj         putVSReg( XT, mkexpr( vT ) );
1584366d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj         break;
1584466d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj      }
158454aa412af1d8166cc11f39a6e721df49431d23618sewardj      case 0x018: // xxsel (VSX Select)
158464aa412af1d8166cc11f39a6e721df49431d23618sewardj      {
158474aa412af1d8166cc11f39a6e721df49431d23618sewardj         UChar XC = ifieldRegXC(theInstr);
158484aa412af1d8166cc11f39a6e721df49431d23618sewardj         IRTemp vC = newTemp( Ity_V128 );
158494aa412af1d8166cc11f39a6e721df49431d23618sewardj         assign( vC, getVSReg( XC ) );
15850b173774421d015736c2316b5e6e998e7de545a5cflorian         DIP("xxsel v%d,v%d,v%d,v%d\n", XT, XA, XB, XC);
158514aa412af1d8166cc11f39a6e721df49431d23618sewardj         /* vD = (vA & ~vC) | (vB & vC) */
158524aa412af1d8166cc11f39a6e721df49431d23618sewardj         putVSReg( XT, binop(Iop_OrV128,
158534aa412af1d8166cc11f39a6e721df49431d23618sewardj            binop(Iop_AndV128, mkexpr(vA), unop(Iop_NotV128, mkexpr(vC))),
158544aa412af1d8166cc11f39a6e721df49431d23618sewardj            binop(Iop_AndV128, mkexpr(vB), mkexpr(vC))) );
158554aa412af1d8166cc11f39a6e721df49431d23618sewardj         break;
158564aa412af1d8166cc11f39a6e721df49431d23618sewardj      }
158574aa412af1d8166cc11f39a6e721df49431d23618sewardj      case 0x148: // xxspltw (VSX Splat Word)
158584aa412af1d8166cc11f39a6e721df49431d23618sewardj      {
158594aa412af1d8166cc11f39a6e721df49431d23618sewardj         UChar UIM   = ifieldRegA(theInstr) & 3;
158604aa412af1d8166cc11f39a6e721df49431d23618sewardj         UChar sh_uim = (3 - (UIM)) * 32;
15861b173774421d015736c2316b5e6e998e7de545a5cflorian         DIP("xxspltw v%d,v%d,%d\n", XT, XB, UIM);
158624aa412af1d8166cc11f39a6e721df49431d23618sewardj         putVSReg( XT,
158634aa412af1d8166cc11f39a6e721df49431d23618sewardj                   unop( Iop_Dup32x4,
158644aa412af1d8166cc11f39a6e721df49431d23618sewardj                         unop( Iop_V128to32,
158654aa412af1d8166cc11f39a6e721df49431d23618sewardj                               binop( Iop_ShrV128, mkexpr( vB ), mkU8( sh_uim ) ) ) ) );
158664aa412af1d8166cc11f39a6e721df49431d23618sewardj         break;
158674aa412af1d8166cc11f39a6e721df49431d23618sewardj      }
1586866d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj
1586966d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj      default:
158704aa412af1d8166cc11f39a6e721df49431d23618sewardj         vex_printf( "dis_vx_permute_misc(ppc)(opc2)\n" );
1587166d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj         return False;
1587266d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj   }
1587366d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj   return True;
1587466d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj}
1587566d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj
1587666d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj/*
15877b51f0f4f33256638ed953156a2635aa739b232f1sewardj  AltiVec Load Instructions
15878a982c0503d8c0c6069ae453bfe70657bd2c134aecerion*/
15879cacba8e675988fbf21b08feea1f317a9c896c053florianstatic Bool dis_av_load ( const VexAbiInfo* vbi, UInt theInstr )
15880a982c0503d8c0c6069ae453bfe70657bd2c134aecerion{
1588176de5cf615380b23b4b5bcced6541233cd4a93a0cerion   /* X-Form */
1588276de5cf615380b23b4b5bcced6541233cd4a93a0cerion   UChar opc1     = ifieldOPC(theInstr);
1588376de5cf615380b23b4b5bcced6541233cd4a93a0cerion   UChar vD_addr  = ifieldRegDS(theInstr);
1588476de5cf615380b23b4b5bcced6541233cd4a93a0cerion   UChar rA_addr  = ifieldRegA(theInstr);
1588576de5cf615380b23b4b5bcced6541233cd4a93a0cerion   UChar rB_addr  = ifieldRegB(theInstr);
1588676de5cf615380b23b4b5bcced6541233cd4a93a0cerion   UInt  opc2     = ifieldOPClo10(theInstr);
1588776de5cf615380b23b4b5bcced6541233cd4a93a0cerion   UChar b0       = ifieldBIT0(theInstr);
15888b51f0f4f33256638ed953156a2635aa739b232f1sewardj
15889fb197c49c89d04987ef801657b2bedc4050e1539cerion   IRType ty         = mode64 ? Ity_I64 : Ity_I32;
15890fb197c49c89d04987ef801657b2bedc4050e1539cerion   IRTemp EA         = newTemp(ty);
15891fb197c49c89d04987ef801657b2bedc4050e1539cerion   IRTemp EA_align16 = newTemp(ty);
158922831b00c4950d6c2b061def05fd67528fe132ececerion
15893b51f0f4f33256638ed953156a2635aa739b232f1sewardj   if (opc1 != 0x1F || b0 != 0) {
158945b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion      vex_printf("dis_av_load(ppc)(instr)\n");
15895a982c0503d8c0c6069ae453bfe70657bd2c134aecerion      return False;
15896a982c0503d8c0c6069ae453bfe70657bd2c134aecerion   }
15897a982c0503d8c0c6069ae453bfe70657bd2c134aecerion
15898fb197c49c89d04987ef801657b2bedc4050e1539cerion   assign( EA, ea_rAor0_idxd(rA_addr, rB_addr) );
15899fb197c49c89d04987ef801657b2bedc4050e1539cerion   assign( EA_align16, addr_align( mkexpr(EA), 16 ) );
15900b51f0f4f33256638ed953156a2635aa739b232f1sewardj
15901a982c0503d8c0c6069ae453bfe70657bd2c134aecerion   switch (opc2) {
15902a982c0503d8c0c6069ae453bfe70657bd2c134aecerion
159036f6c6a0d6a601af3137f861f5fc9d76365c48e96cerion   case 0x006: { // lvsl (Load Vector for Shift Left, AV p123)
15904fb197c49c89d04987ef801657b2bedc4050e1539cerion      IRDirty* d;
15905d14709407df9363767aa888b03f95f08df169dcesewardj      UInt vD_off = vectorGuestRegOffset(vD_addr);
159061f5fe1fc3a37ca729925e8eec25aa1025b4a6cdbcarll      IRExpr** args_be = mkIRExprVec_5(
159079041956f39c57e265122ed0a71061dea1e554edcflorian                         IRExpr_BBPTR(),
159081f5fe1fc3a37ca729925e8eec25aa1025b4a6cdbcarll                         mkU32(vD_off),
15909e9d8a26b690c2561ac54ab0cd6ad83ecbadcbe76sewardj                         binop(Iop_And32, mkNarrowTo32(ty, mkexpr(EA)),
15910fb197c49c89d04987ef801657b2bedc4050e1539cerion                                          mkU32(0xF)),
159111f5fe1fc3a37ca729925e8eec25aa1025b4a6cdbcarll                         mkU32(0)/*left*/,
159121f5fe1fc3a37ca729925e8eec25aa1025b4a6cdbcarll                         mkU32(1)/*Big Endian*/);
159131f5fe1fc3a37ca729925e8eec25aa1025b4a6cdbcarll      IRExpr** args_le = mkIRExprVec_5(
159141f5fe1fc3a37ca729925e8eec25aa1025b4a6cdbcarll                         IRExpr_BBPTR(),
159151f5fe1fc3a37ca729925e8eec25aa1025b4a6cdbcarll                         mkU32(vD_off),
159161f5fe1fc3a37ca729925e8eec25aa1025b4a6cdbcarll                         binop(Iop_And32, mkNarrowTo32(ty, mkexpr(EA)),
159171f5fe1fc3a37ca729925e8eec25aa1025b4a6cdbcarll                                          mkU32(0xF)),
159181f5fe1fc3a37ca729925e8eec25aa1025b4a6cdbcarll                         mkU32(0)/*left*/,
159191f5fe1fc3a37ca729925e8eec25aa1025b4a6cdbcarll                         mkU32(0)/*Little Endian*/);
159205b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion      if (!mode64) {
159214c4f5ef69f89a19844a22a34b7a0cb717f83f033cerion         d = unsafeIRDirty_0_N (
159224c4f5ef69f89a19844a22a34b7a0cb717f83f033cerion                        0/*regparms*/,
159234c4f5ef69f89a19844a22a34b7a0cb717f83f033cerion                        "ppc32g_dirtyhelper_LVS",
15924dd40fdf58cc8a6fe9466c4f00bdfc9fe9bf00449sewardj                        fnptr_to_fnentry(vbi, &ppc32g_dirtyhelper_LVS),
159251f5fe1fc3a37ca729925e8eec25aa1025b4a6cdbcarll                        args_be );
159265b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion      } else {
159271f5fe1fc3a37ca729925e8eec25aa1025b4a6cdbcarll         if (host_endness == VexEndnessBE)
159281f5fe1fc3a37ca729925e8eec25aa1025b4a6cdbcarll            d = unsafeIRDirty_0_N (
159291f5fe1fc3a37ca729925e8eec25aa1025b4a6cdbcarll                           0/*regparms*/,
159301f5fe1fc3a37ca729925e8eec25aa1025b4a6cdbcarll                           "ppc64g_dirtyhelper_LVS",
159311f5fe1fc3a37ca729925e8eec25aa1025b4a6cdbcarll                           fnptr_to_fnentry(vbi, &ppc64g_dirtyhelper_LVS),
159321f5fe1fc3a37ca729925e8eec25aa1025b4a6cdbcarll                           args_be );
159331f5fe1fc3a37ca729925e8eec25aa1025b4a6cdbcarll         else
159341f5fe1fc3a37ca729925e8eec25aa1025b4a6cdbcarll            d = unsafeIRDirty_0_N (
159351f5fe1fc3a37ca729925e8eec25aa1025b4a6cdbcarll                           0/*regparms*/,
159361f5fe1fc3a37ca729925e8eec25aa1025b4a6cdbcarll                           "ppc64g_dirtyhelper_LVS",
159371f5fe1fc3a37ca729925e8eec25aa1025b4a6cdbcarll                           &ppc64g_dirtyhelper_LVS,
159381f5fe1fc3a37ca729925e8eec25aa1025b4a6cdbcarll                           args_le );
159395b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion      }
15940d953ebb9b04cbad6891676df597bf0c542b1ec89cerion      DIP("lvsl v%d,r%u,r%u\n", vD_addr, rA_addr, rB_addr);
159416f6c6a0d6a601af3137f861f5fc9d76365c48e96cerion      /* declare guest state effects */
159426f6c6a0d6a601af3137f861f5fc9d76365c48e96cerion      d->nFxState = 1;
15943c9069f2908814843e9a4da00da9c8905440195a6sewardj      vex_bzero(&d->fxState, sizeof(d->fxState));
159446f6c6a0d6a601af3137f861f5fc9d76365c48e96cerion      d->fxState[0].fx     = Ifx_Write;
15945d14709407df9363767aa888b03f95f08df169dcesewardj      d->fxState[0].offset = vD_off;
159466f6c6a0d6a601af3137f861f5fc9d76365c48e96cerion      d->fxState[0].size   = sizeof(U128);
159476f6c6a0d6a601af3137f861f5fc9d76365c48e96cerion
159486f6c6a0d6a601af3137f861f5fc9d76365c48e96cerion      /* execute the dirty call, side-effecting guest state */
159496f6c6a0d6a601af3137f861f5fc9d76365c48e96cerion      stmt( IRStmt_Dirty(d) );
159506f6c6a0d6a601af3137f861f5fc9d76365c48e96cerion      break;
159516f6c6a0d6a601af3137f861f5fc9d76365c48e96cerion   }
159526f6c6a0d6a601af3137f861f5fc9d76365c48e96cerion   case 0x026: { // lvsr (Load Vector for Shift Right, AV p125)
15953fb197c49c89d04987ef801657b2bedc4050e1539cerion      IRDirty* d;
15954d14709407df9363767aa888b03f95f08df169dcesewardj      UInt vD_off = vectorGuestRegOffset(vD_addr);
159551f5fe1fc3a37ca729925e8eec25aa1025b4a6cdbcarll      IRExpr** args_be = mkIRExprVec_5(
159561f5fe1fc3a37ca729925e8eec25aa1025b4a6cdbcarll                             IRExpr_BBPTR(),
159571f5fe1fc3a37ca729925e8eec25aa1025b4a6cdbcarll                             mkU32(vD_off),
159581f5fe1fc3a37ca729925e8eec25aa1025b4a6cdbcarll                             binop(Iop_And32, mkNarrowTo32(ty, mkexpr(EA)),
159591f5fe1fc3a37ca729925e8eec25aa1025b4a6cdbcarll                                              mkU32(0xF)),
159601f5fe1fc3a37ca729925e8eec25aa1025b4a6cdbcarll                             mkU32(1)/*right*/,
159611f5fe1fc3a37ca729925e8eec25aa1025b4a6cdbcarll                             mkU32(1)/*Big Endian*/);
159621f5fe1fc3a37ca729925e8eec25aa1025b4a6cdbcarll      IRExpr** args_le = mkIRExprVec_5(
159631f5fe1fc3a37ca729925e8eec25aa1025b4a6cdbcarll                             IRExpr_BBPTR(),
159641f5fe1fc3a37ca729925e8eec25aa1025b4a6cdbcarll                             mkU32(vD_off),
159651f5fe1fc3a37ca729925e8eec25aa1025b4a6cdbcarll                             binop(Iop_And32, mkNarrowTo32(ty, mkexpr(EA)),
159661f5fe1fc3a37ca729925e8eec25aa1025b4a6cdbcarll                                              mkU32(0xF)),
159671f5fe1fc3a37ca729925e8eec25aa1025b4a6cdbcarll                             mkU32(1)/*right*/,
159681f5fe1fc3a37ca729925e8eec25aa1025b4a6cdbcarll                             mkU32(0)/*Little Endian*/);
159691f5fe1fc3a37ca729925e8eec25aa1025b4a6cdbcarll
159705b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion      if (!mode64) {
159714c4f5ef69f89a19844a22a34b7a0cb717f83f033cerion         d = unsafeIRDirty_0_N (
159721f5fe1fc3a37ca729925e8eec25aa1025b4a6cdbcarll                        0/*regparms*/,
159734c4f5ef69f89a19844a22a34b7a0cb717f83f033cerion                        "ppc32g_dirtyhelper_LVS",
15974dd40fdf58cc8a6fe9466c4f00bdfc9fe9bf00449sewardj                        fnptr_to_fnentry(vbi, &ppc32g_dirtyhelper_LVS),
159751f5fe1fc3a37ca729925e8eec25aa1025b4a6cdbcarll                        args_be );
159765b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion      } else {
159771f5fe1fc3a37ca729925e8eec25aa1025b4a6cdbcarll         if (host_endness == VexEndnessBE)
159781f5fe1fc3a37ca729925e8eec25aa1025b4a6cdbcarll            d = unsafeIRDirty_0_N (
159791f5fe1fc3a37ca729925e8eec25aa1025b4a6cdbcarll                           0/*regparms*/,
159801f5fe1fc3a37ca729925e8eec25aa1025b4a6cdbcarll                           "ppc64g_dirtyhelper_LVS",
159811f5fe1fc3a37ca729925e8eec25aa1025b4a6cdbcarll                           fnptr_to_fnentry(vbi, &ppc64g_dirtyhelper_LVS),
159821f5fe1fc3a37ca729925e8eec25aa1025b4a6cdbcarll                           args_be );
159831f5fe1fc3a37ca729925e8eec25aa1025b4a6cdbcarll         else
159841f5fe1fc3a37ca729925e8eec25aa1025b4a6cdbcarll            d = unsafeIRDirty_0_N (
159851f5fe1fc3a37ca729925e8eec25aa1025b4a6cdbcarll                           0/*regparms*/,
159861f5fe1fc3a37ca729925e8eec25aa1025b4a6cdbcarll                           "ppc64g_dirtyhelper_LVS",
159871f5fe1fc3a37ca729925e8eec25aa1025b4a6cdbcarll                           &ppc64g_dirtyhelper_LVS,
159881f5fe1fc3a37ca729925e8eec25aa1025b4a6cdbcarll                           args_le );
159895b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion      }
15990d953ebb9b04cbad6891676df597bf0c542b1ec89cerion      DIP("lvsr v%d,r%u,r%u\n", vD_addr, rA_addr, rB_addr);
159916f6c6a0d6a601af3137f861f5fc9d76365c48e96cerion      /* declare guest state effects */
159926f6c6a0d6a601af3137f861f5fc9d76365c48e96cerion      d->nFxState = 1;
15993c9069f2908814843e9a4da00da9c8905440195a6sewardj      vex_bzero(&d->fxState, sizeof(d->fxState));
159946f6c6a0d6a601af3137f861f5fc9d76365c48e96cerion      d->fxState[0].fx     = Ifx_Write;
15995d14709407df9363767aa888b03f95f08df169dcesewardj      d->fxState[0].offset = vD_off;
159966f6c6a0d6a601af3137f861f5fc9d76365c48e96cerion      d->fxState[0].size   = sizeof(U128);
159976f6c6a0d6a601af3137f861f5fc9d76365c48e96cerion
159986f6c6a0d6a601af3137f861f5fc9d76365c48e96cerion      /* execute the dirty call, side-effecting guest state */
159996f6c6a0d6a601af3137f861f5fc9d76365c48e96cerion      stmt( IRStmt_Dirty(d) );
160006f6c6a0d6a601af3137f861f5fc9d76365c48e96cerion      break;
160016f6c6a0d6a601af3137f861f5fc9d76365c48e96cerion   }
1600232aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion   case 0x007: // lvebx (Load Vector Element Byte Indexed, AV p119)
16003d953ebb9b04cbad6891676df597bf0c542b1ec89cerion      DIP("lvebx v%d,r%u,r%u\n", vD_addr, rA_addr, rB_addr);
1600461c92742ac68a38d61602eaac047ae79f07ff06ecerion      /* loads addressed byte into vector[EA[0:3]
1600561c92742ac68a38d61602eaac047ae79f07ff06ecerion         since all other destination bytes are undefined,
1600661c92742ac68a38d61602eaac047ae79f07ff06ecerion         can simply load entire vector from 16-aligned EA */
160071f5fe1fc3a37ca729925e8eec25aa1025b4a6cdbcarll      putVReg( vD_addr, load(Ity_V128, mkexpr(EA_align16)) );
1600861c92742ac68a38d61602eaac047ae79f07ff06ecerion      break;
1600932aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion
1601032aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion   case 0x027: // lvehx (Load Vector Element Half Word Indexed, AV p121)
16011d953ebb9b04cbad6891676df597bf0c542b1ec89cerion      DIP("lvehx v%d,r%u,r%u\n", vD_addr, rA_addr, rB_addr);
1601261c92742ac68a38d61602eaac047ae79f07ff06ecerion      /* see note for lvebx */
160131f5fe1fc3a37ca729925e8eec25aa1025b4a6cdbcarll      putVReg( vD_addr, load(Ity_V128, mkexpr(EA_align16)) );
1601461c92742ac68a38d61602eaac047ae79f07ff06ecerion      break;
1601532aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion
1601632aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion   case 0x047: // lvewx (Load Vector Element Word Indexed, AV p122)
16017d953ebb9b04cbad6891676df597bf0c542b1ec89cerion      DIP("lvewx v%d,r%u,r%u\n", vD_addr, rA_addr, rB_addr);
1601861c92742ac68a38d61602eaac047ae79f07ff06ecerion      /* see note for lvebx */
160191f5fe1fc3a37ca729925e8eec25aa1025b4a6cdbcarll      putVReg( vD_addr, load(Ity_V128, mkexpr(EA_align16)) );
1602061c92742ac68a38d61602eaac047ae79f07ff06ecerion      break;
16021a982c0503d8c0c6069ae453bfe70657bd2c134aecerion
16022b51f0f4f33256638ed953156a2635aa739b232f1sewardj   case 0x067: // lvx (Load Vector Indexed, AV p127)
16023d953ebb9b04cbad6891676df597bf0c542b1ec89cerion      DIP("lvx v%d,r%u,r%u\n", vD_addr, rA_addr, rB_addr);
160241f5fe1fc3a37ca729925e8eec25aa1025b4a6cdbcarll      putVReg( vD_addr, load(Ity_V128, mkexpr(EA_align16)) );
16025b51f0f4f33256638ed953156a2635aa739b232f1sewardj      break;
16026a982c0503d8c0c6069ae453bfe70657bd2c134aecerion
1602732aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion   case 0x167: // lvxl (Load Vector Indexed LRU, AV p128)
16028d953ebb9b04cbad6891676df597bf0c542b1ec89cerion      DIP("lvxl v%d,r%u,r%u\n", vD_addr, rA_addr, rB_addr);
160291f5fe1fc3a37ca729925e8eec25aa1025b4a6cdbcarll      putVReg( vD_addr, load(Ity_V128, mkexpr(EA_align16)) );
16030d2fd864dcbe236580d4f2c9417b6fd98ff6e55d7sewardj      break;
16031a982c0503d8c0c6069ae453bfe70657bd2c134aecerion
16032a982c0503d8c0c6069ae453bfe70657bd2c134aecerion   default:
160335b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion      vex_printf("dis_av_load(ppc)(opc2)\n");
16034a982c0503d8c0c6069ae453bfe70657bd2c134aecerion      return False;
16035a982c0503d8c0c6069ae453bfe70657bd2c134aecerion   }
16036a982c0503d8c0c6069ae453bfe70657bd2c134aecerion   return True;
16037a982c0503d8c0c6069ae453bfe70657bd2c134aecerion}
16038a982c0503d8c0c6069ae453bfe70657bd2c134aecerion
16039a982c0503d8c0c6069ae453bfe70657bd2c134aecerion/*
16040b51f0f4f33256638ed953156a2635aa739b232f1sewardj  AltiVec Store Instructions
16041a982c0503d8c0c6069ae453bfe70657bd2c134aecerion*/
16042b51f0f4f33256638ed953156a2635aa739b232f1sewardjstatic Bool dis_av_store ( UInt theInstr )
16043a982c0503d8c0c6069ae453bfe70657bd2c134aecerion{
1604476de5cf615380b23b4b5bcced6541233cd4a93a0cerion   /* X-Form */
1604576de5cf615380b23b4b5bcced6541233cd4a93a0cerion   UChar opc1     = ifieldOPC(theInstr);
1604676de5cf615380b23b4b5bcced6541233cd4a93a0cerion   UChar vS_addr  = ifieldRegDS(theInstr);
1604776de5cf615380b23b4b5bcced6541233cd4a93a0cerion   UChar rA_addr  = ifieldRegA(theInstr);
1604876de5cf615380b23b4b5bcced6541233cd4a93a0cerion   UChar rB_addr  = ifieldRegB(theInstr);
1604976de5cf615380b23b4b5bcced6541233cd4a93a0cerion   UInt  opc2     = ifieldOPClo10(theInstr);
1605076de5cf615380b23b4b5bcced6541233cd4a93a0cerion   UChar b0       = ifieldBIT0(theInstr);
16051a982c0503d8c0c6069ae453bfe70657bd2c134aecerion
160522831b00c4950d6c2b061def05fd67528fe132ececerion   IRType ty           = mode64 ? Ity_I64 : Ity_I32;
160532831b00c4950d6c2b061def05fd67528fe132ececerion   IRTemp EA           = newTemp(ty);
16054dba87e2eb883914b8c1bc3ef05a1147dd4f930eacerion   IRTemp addr_aligned = newTemp(ty);
160552831b00c4950d6c2b061def05fd67528fe132ececerion   IRTemp vS           = newTemp(Ity_V128);
160562831b00c4950d6c2b061def05fd67528fe132ececerion   IRTemp eb           = newTemp(Ity_I8);
160572831b00c4950d6c2b061def05fd67528fe132ececerion   IRTemp idx          = newTemp(Ity_I8);
16058a982c0503d8c0c6069ae453bfe70657bd2c134aecerion
16059b51f0f4f33256638ed953156a2635aa739b232f1sewardj   if (opc1 != 0x1F || b0 != 0) {
160605b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion      vex_printf("dis_av_store(ppc)(instr)\n");
16061a982c0503d8c0c6069ae453bfe70657bd2c134aecerion      return False;
16062a982c0503d8c0c6069ae453bfe70657bd2c134aecerion   }
16063a982c0503d8c0c6069ae453bfe70657bd2c134aecerion
16064d953ebb9b04cbad6891676df597bf0c542b1ec89cerion   assign( vS, getVReg(vS_addr));
160652831b00c4950d6c2b061def05fd67528fe132ececerion   assign( EA, ea_rAor0_idxd(rA_addr, rB_addr) );
16066d953ebb9b04cbad6891676df597bf0c542b1ec89cerion
16067a982c0503d8c0c6069ae453bfe70657bd2c134aecerion   switch (opc2) {
1606861c92742ac68a38d61602eaac047ae79f07ff06ecerion   case 0x087: { // stvebx (Store Vector Byte Indexed, AV p131)
16069d953ebb9b04cbad6891676df597bf0c542b1ec89cerion      DIP("stvebx v%d,r%u,r%u\n", vS_addr, rA_addr, rB_addr);
1607061c92742ac68a38d61602eaac047ae79f07ff06ecerion      assign( eb, binop(Iop_And8, mkU8(0xF),
160712831b00c4950d6c2b061def05fd67528fe132ececerion                        unop(Iop_32to8,
16072e9d8a26b690c2561ac54ab0cd6ad83ecbadcbe76sewardj                             mkNarrowTo32(ty, mkexpr(EA)) )) );
160731f5fe1fc3a37ca729925e8eec25aa1025b4a6cdbcarll     if (host_endness == VexEndnessLE) {
160741f5fe1fc3a37ca729925e8eec25aa1025b4a6cdbcarll         assign( idx, binop(Iop_Shl8, mkexpr(eb), mkU8(3)) );
160751f5fe1fc3a37ca729925e8eec25aa1025b4a6cdbcarll      } else {
160761f5fe1fc3a37ca729925e8eec25aa1025b4a6cdbcarll         assign( idx, binop(Iop_Shl8,
160771f5fe1fc3a37ca729925e8eec25aa1025b4a6cdbcarll                            binop(Iop_Sub8, mkU8(15), mkexpr(eb)),
160781f5fe1fc3a37ca729925e8eec25aa1025b4a6cdbcarll                            mkU8(3)) );
160791f5fe1fc3a37ca729925e8eec25aa1025b4a6cdbcarll      }
160801f5fe1fc3a37ca729925e8eec25aa1025b4a6cdbcarll      store( mkexpr(EA),
160811f5fe1fc3a37ca729925e8eec25aa1025b4a6cdbcarll             unop( Iop_32to8, unop(Iop_V128to32,
160821f5fe1fc3a37ca729925e8eec25aa1025b4a6cdbcarll                   binop(Iop_ShrV128, mkexpr(vS), mkexpr(idx)))) );
1608361c92742ac68a38d61602eaac047ae79f07ff06ecerion      break;
1608461c92742ac68a38d61602eaac047ae79f07ff06ecerion   }
1608561c92742ac68a38d61602eaac047ae79f07ff06ecerion   case 0x0A7: { // stvehx (Store Vector Half Word Indexed, AV p132)
16086d953ebb9b04cbad6891676df597bf0c542b1ec89cerion      DIP("stvehx v%d,r%u,r%u\n", vS_addr, rA_addr, rB_addr);
16087dba87e2eb883914b8c1bc3ef05a1147dd4f930eacerion      assign( addr_aligned, addr_align(mkexpr(EA), 2) );
1608861c92742ac68a38d61602eaac047ae79f07ff06ecerion      assign( eb, binop(Iop_And8, mkU8(0xF),
16089e9d8a26b690c2561ac54ab0cd6ad83ecbadcbe76sewardj                        mkNarrowTo8(ty, mkexpr(addr_aligned) )) );
160901f5fe1fc3a37ca729925e8eec25aa1025b4a6cdbcarll      if (host_endness == VexEndnessLE) {
160911f5fe1fc3a37ca729925e8eec25aa1025b4a6cdbcarll          assign( idx, binop(Iop_Shl8, mkexpr(eb), mkU8(3)) );
160921f5fe1fc3a37ca729925e8eec25aa1025b4a6cdbcarll      } else {
160931f5fe1fc3a37ca729925e8eec25aa1025b4a6cdbcarll         assign( idx, binop(Iop_Shl8,
160941f5fe1fc3a37ca729925e8eec25aa1025b4a6cdbcarll                            binop(Iop_Sub8, mkU8(14), mkexpr(eb)),
160951f5fe1fc3a37ca729925e8eec25aa1025b4a6cdbcarll                            mkU8(3)) );
160961f5fe1fc3a37ca729925e8eec25aa1025b4a6cdbcarll      }
160971f5fe1fc3a37ca729925e8eec25aa1025b4a6cdbcarll      store( mkexpr(addr_aligned),
160981f5fe1fc3a37ca729925e8eec25aa1025b4a6cdbcarll             unop( Iop_32to16, unop(Iop_V128to32,
160991f5fe1fc3a37ca729925e8eec25aa1025b4a6cdbcarll                   binop(Iop_ShrV128, mkexpr(vS), mkexpr(idx)))) );
1610061c92742ac68a38d61602eaac047ae79f07ff06ecerion      break;
1610161c92742ac68a38d61602eaac047ae79f07ff06ecerion   }
1610261c92742ac68a38d61602eaac047ae79f07ff06ecerion   case 0x0C7: { // stvewx (Store Vector Word Indexed, AV p133)
16103d953ebb9b04cbad6891676df597bf0c542b1ec89cerion      DIP("stvewx v%d,r%u,r%u\n", vS_addr, rA_addr, rB_addr);
16104dba87e2eb883914b8c1bc3ef05a1147dd4f930eacerion      assign( addr_aligned, addr_align(mkexpr(EA), 4) );
1610561c92742ac68a38d61602eaac047ae79f07ff06ecerion      assign( eb, binop(Iop_And8, mkU8(0xF),
16106e9d8a26b690c2561ac54ab0cd6ad83ecbadcbe76sewardj                        mkNarrowTo8(ty, mkexpr(addr_aligned) )) );
161071f5fe1fc3a37ca729925e8eec25aa1025b4a6cdbcarll      if (host_endness == VexEndnessLE) {
161081f5fe1fc3a37ca729925e8eec25aa1025b4a6cdbcarll         assign( idx, binop(Iop_Shl8, mkexpr(eb), mkU8(3)) );
161091f5fe1fc3a37ca729925e8eec25aa1025b4a6cdbcarll      } else {
161101f5fe1fc3a37ca729925e8eec25aa1025b4a6cdbcarll         assign( idx, binop(Iop_Shl8,
161111f5fe1fc3a37ca729925e8eec25aa1025b4a6cdbcarll                            binop(Iop_Sub8, mkU8(12), mkexpr(eb)),
161121f5fe1fc3a37ca729925e8eec25aa1025b4a6cdbcarll                            mkU8(3)) );
161131f5fe1fc3a37ca729925e8eec25aa1025b4a6cdbcarll      }
161141f5fe1fc3a37ca729925e8eec25aa1025b4a6cdbcarll      store( mkexpr( addr_aligned),
161151f5fe1fc3a37ca729925e8eec25aa1025b4a6cdbcarll             unop( Iop_V128to32,
161161f5fe1fc3a37ca729925e8eec25aa1025b4a6cdbcarll                   binop(Iop_ShrV128, mkexpr(vS), mkexpr(idx))) );
1611761c92742ac68a38d61602eaac047ae79f07ff06ecerion      break;
1611861c92742ac68a38d61602eaac047ae79f07ff06ecerion   }
1611932aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion
16120b51f0f4f33256638ed953156a2635aa739b232f1sewardj   case 0x0E7: // stvx (Store Vector Indexed, AV p134)
16121d953ebb9b04cbad6891676df597bf0c542b1ec89cerion      DIP("stvx v%d,r%u,r%u\n", vS_addr, rA_addr, rB_addr);
161221f5fe1fc3a37ca729925e8eec25aa1025b4a6cdbcarll      store( addr_align( mkexpr(EA), 16 ), mkexpr(vS) );
16123b51f0f4f33256638ed953156a2635aa739b232f1sewardj      break;
16124a982c0503d8c0c6069ae453bfe70657bd2c134aecerion
1612532aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion   case 0x1E7: // stvxl (Store Vector Indexed LRU, AV p135)
16126d953ebb9b04cbad6891676df597bf0c542b1ec89cerion      DIP("stvxl v%d,r%u,r%u\n", vS_addr, rA_addr, rB_addr);
161271f5fe1fc3a37ca729925e8eec25aa1025b4a6cdbcarll      store( addr_align( mkexpr(EA), 16 ), mkexpr(vS) );
16128d2fd864dcbe236580d4f2c9417b6fd98ff6e55d7sewardj      break;
16129a982c0503d8c0c6069ae453bfe70657bd2c134aecerion
16130a982c0503d8c0c6069ae453bfe70657bd2c134aecerion   default:
161315b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion      vex_printf("dis_av_store(ppc)(opc2)\n");
16132a982c0503d8c0c6069ae453bfe70657bd2c134aecerion      return False;
16133a982c0503d8c0c6069ae453bfe70657bd2c134aecerion   }
16134a982c0503d8c0c6069ae453bfe70657bd2c134aecerion   return True;
16135a982c0503d8c0c6069ae453bfe70657bd2c134aecerion}
16136a982c0503d8c0c6069ae453bfe70657bd2c134aecerion
1613732aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion/*
1613832aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion  AltiVec Arithmetic Instructions
1613932aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion*/
1614032aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerionstatic Bool dis_av_arith ( UInt theInstr )
1614132aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion{
1614276de5cf615380b23b4b5bcced6541233cd4a93a0cerion   /* VX-Form */
1614376de5cf615380b23b4b5bcced6541233cd4a93a0cerion   UChar opc1     = ifieldOPC(theInstr);
1614476de5cf615380b23b4b5bcced6541233cd4a93a0cerion   UChar vD_addr  = ifieldRegDS(theInstr);
1614576de5cf615380b23b4b5bcced6541233cd4a93a0cerion   UChar vA_addr  = ifieldRegA(theInstr);
1614676de5cf615380b23b4b5bcced6541233cd4a93a0cerion   UChar vB_addr  = ifieldRegB(theInstr);
1614776de5cf615380b23b4b5bcced6541233cd4a93a0cerion   UInt  opc2     = IFIELD( theInstr, 0, 11 );
1614832aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion
16149d3e52410a03147c36dbf977a37e77a4de246f7c9cerion   IRTemp vA = newTemp(Ity_V128);
16150d3e52410a03147c36dbf977a37e77a4de246f7c9cerion   IRTemp vB = newTemp(Ity_V128);
161514a49b0393204185f87664ea58f2b7a2ae1d37338cerion   IRTemp z3 = newTemp(Ity_I64);
161524a49b0393204185f87664ea58f2b7a2ae1d37338cerion   IRTemp z2 = newTemp(Ity_I64);
161534a49b0393204185f87664ea58f2b7a2ae1d37338cerion   IRTemp z1 = newTemp(Ity_I64);
161544a49b0393204185f87664ea58f2b7a2ae1d37338cerion   IRTemp z0 = newTemp(Ity_I64);
161554a49b0393204185f87664ea58f2b7a2ae1d37338cerion   IRTemp aEvn, aOdd;
161564a49b0393204185f87664ea58f2b7a2ae1d37338cerion   IRTemp a15, a14, a13, a12, a11, a10, a9, a8;
161574a49b0393204185f87664ea58f2b7a2ae1d37338cerion   IRTemp a7, a6, a5, a4, a3, a2, a1, a0;
161584a49b0393204185f87664ea58f2b7a2ae1d37338cerion   IRTemp b3, b2, b1, b0;
161594a49b0393204185f87664ea58f2b7a2ae1d37338cerion
161604a49b0393204185f87664ea58f2b7a2ae1d37338cerion   aEvn = aOdd = IRTemp_INVALID;
161614a49b0393204185f87664ea58f2b7a2ae1d37338cerion   a15 = a14 = a13 = a12 = a11 = a10 = a9 = a8 = IRTemp_INVALID;
161624a49b0393204185f87664ea58f2b7a2ae1d37338cerion   a7 = a6 = a5 = a4 = a3 = a2 = a1 = a0 = IRTemp_INVALID;
161634a49b0393204185f87664ea58f2b7a2ae1d37338cerion   b3 = b2 = b1 = b0 = IRTemp_INVALID;
161644a49b0393204185f87664ea58f2b7a2ae1d37338cerion
16165d3e52410a03147c36dbf977a37e77a4de246f7c9cerion   assign( vA, getVReg(vA_addr));
16166d3e52410a03147c36dbf977a37e77a4de246f7c9cerion   assign( vB, getVReg(vB_addr));
16167d3e52410a03147c36dbf977a37e77a4de246f7c9cerion
1616832aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion   if (opc1 != 0x4) {
161695b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion      vex_printf("dis_av_arith(ppc)(opc1 != 0x4)\n");
1617032aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion      return False;
1617132aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion   }
1617232aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion
1617332aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion   switch (opc2) {
1617432aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion   /* Add */
16175d3e52410a03147c36dbf977a37e77a4de246f7c9cerion   case 0x180: { // vaddcuw (Add Carryout Unsigned Word, AV p136)
1617632aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion      DIP("vaddcuw v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
1617736991efdccc3af11ee9691dfa5297872dfb88312cerion      /* unsigned_ov(x+y) = (y >u not(x)) */
16178d3e52410a03147c36dbf977a37e77a4de246f7c9cerion      putVReg( vD_addr, binop(Iop_ShrN32x4,
1617936991efdccc3af11ee9691dfa5297872dfb88312cerion                              binop(Iop_CmpGT32Ux4, mkexpr(vB),
1618036991efdccc3af11ee9691dfa5297872dfb88312cerion                                    unop(Iop_NotV128, mkexpr(vA))),
16181d3e52410a03147c36dbf977a37e77a4de246f7c9cerion                              mkU8(31)) );
16182d3e52410a03147c36dbf977a37e77a4de246f7c9cerion      break;
16183d3e52410a03147c36dbf977a37e77a4de246f7c9cerion   }
1618432aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion   case 0x000: // vaddubm (Add Unsigned Byte Modulo, AV p141)
1618532aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion      DIP("vaddubm v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
1618636991efdccc3af11ee9691dfa5297872dfb88312cerion      putVReg( vD_addr, binop(Iop_Add8x16, mkexpr(vA), mkexpr(vB)) );
1618736991efdccc3af11ee9691dfa5297872dfb88312cerion      break;
1618836991efdccc3af11ee9691dfa5297872dfb88312cerion
1618932aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion   case 0x040: // vadduhm (Add Unsigned Half Word Modulo, AV p143)
1619032aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion      DIP("vadduhm v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
1619136991efdccc3af11ee9691dfa5297872dfb88312cerion      putVReg( vD_addr, binop(Iop_Add16x8, mkexpr(vA), mkexpr(vB)) );
1619236991efdccc3af11ee9691dfa5297872dfb88312cerion      break;
1619336991efdccc3af11ee9691dfa5297872dfb88312cerion
1619432aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion   case 0x080: // vadduwm (Add Unsigned Word Modulo, AV p145)
1619532aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion      DIP("vadduwm v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
1619636991efdccc3af11ee9691dfa5297872dfb88312cerion      putVReg( vD_addr, binop(Iop_Add32x4, mkexpr(vA), mkexpr(vB)) );
1619736991efdccc3af11ee9691dfa5297872dfb88312cerion      break;
1619836991efdccc3af11ee9691dfa5297872dfb88312cerion
161990c74bb5aa3240f693df0568d578baabf0c376dc4carll   case 0x0C0: // vaddudm (Add Unsigned Double Word Modulo)
162000c74bb5aa3240f693df0568d578baabf0c376dc4carll      DIP("vaddudm v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
162010c74bb5aa3240f693df0568d578baabf0c376dc4carll      putVReg( vD_addr, binop(Iop_Add64x2, mkexpr(vA), mkexpr(vB)) );
162020c74bb5aa3240f693df0568d578baabf0c376dc4carll      break;
162030c74bb5aa3240f693df0568d578baabf0c376dc4carll
1620432aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion   case 0x200: // vaddubs (Add Unsigned Byte Saturate, AV p142)
1620532aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion      DIP("vaddubs v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
1620636991efdccc3af11ee9691dfa5297872dfb88312cerion      putVReg( vD_addr, binop(Iop_QAdd8Ux16, mkexpr(vA), mkexpr(vB)) );
1620736991efdccc3af11ee9691dfa5297872dfb88312cerion      // TODO: set VSCR[SAT], perhaps via new primop: Iop_SatOfQAdd8Ux16
1620836991efdccc3af11ee9691dfa5297872dfb88312cerion      break;
1620936991efdccc3af11ee9691dfa5297872dfb88312cerion
1621032aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion   case 0x240: // vadduhs (Add Unsigned Half Word Saturate, AV p144)
1621132aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion      DIP("vadduhs v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
1621236991efdccc3af11ee9691dfa5297872dfb88312cerion      putVReg( vD_addr, binop(Iop_QAdd16Ux8, mkexpr(vA), mkexpr(vB)) );
1621336991efdccc3af11ee9691dfa5297872dfb88312cerion      // TODO: set VSCR[SAT]
1621436991efdccc3af11ee9691dfa5297872dfb88312cerion      break;
1621536991efdccc3af11ee9691dfa5297872dfb88312cerion
1621632aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion   case 0x280: // vadduws (Add Unsigned Word Saturate, AV p146)
1621732aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion      DIP("vadduws v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
1621836991efdccc3af11ee9691dfa5297872dfb88312cerion      putVReg( vD_addr, binop(Iop_QAdd32Ux4, mkexpr(vA), mkexpr(vB)) );
1621936991efdccc3af11ee9691dfa5297872dfb88312cerion      // TODO: set VSCR[SAT]
1622036991efdccc3af11ee9691dfa5297872dfb88312cerion      break;
1622136991efdccc3af11ee9691dfa5297872dfb88312cerion
1622232aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion   case 0x300: // vaddsbs (Add Signed Byte Saturate, AV p138)
1622332aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion      DIP("vaddsbs v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
1622436991efdccc3af11ee9691dfa5297872dfb88312cerion      putVReg( vD_addr, binop(Iop_QAdd8Sx16, mkexpr(vA), mkexpr(vB)) );
1622536991efdccc3af11ee9691dfa5297872dfb88312cerion      // TODO: set VSCR[SAT]
1622636991efdccc3af11ee9691dfa5297872dfb88312cerion      break;
1622736991efdccc3af11ee9691dfa5297872dfb88312cerion
1622832aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion   case 0x340: // vaddshs (Add Signed Half Word Saturate, AV p139)
1622932aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion      DIP("vaddshs v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
1623036991efdccc3af11ee9691dfa5297872dfb88312cerion      putVReg( vD_addr, binop(Iop_QAdd16Sx8, mkexpr(vA), mkexpr(vB)) );
1623136991efdccc3af11ee9691dfa5297872dfb88312cerion      // TODO: set VSCR[SAT]
1623236991efdccc3af11ee9691dfa5297872dfb88312cerion      break;
1623336991efdccc3af11ee9691dfa5297872dfb88312cerion
1623432aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion   case 0x380: // vaddsws (Add Signed Word Saturate, AV p140)
1623532aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion      DIP("vaddsws v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
1623636991efdccc3af11ee9691dfa5297872dfb88312cerion      putVReg( vD_addr, binop(Iop_QAdd32Sx4, mkexpr(vA), mkexpr(vB)) );
1623736991efdccc3af11ee9691dfa5297872dfb88312cerion      // TODO: set VSCR[SAT]
1623836991efdccc3af11ee9691dfa5297872dfb88312cerion      break;
1623936991efdccc3af11ee9691dfa5297872dfb88312cerion
1624036991efdccc3af11ee9691dfa5297872dfb88312cerion
1624132aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion   /* Subtract */
1624236991efdccc3af11ee9691dfa5297872dfb88312cerion   case 0x580: { // vsubcuw (Subtract Carryout Unsigned Word, AV p260)
1624332aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion      DIP("vsubcuw v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
1624436991efdccc3af11ee9691dfa5297872dfb88312cerion      /* unsigned_ov(x-y) = (y >u x) */
1624536991efdccc3af11ee9691dfa5297872dfb88312cerion      putVReg( vD_addr, binop(Iop_ShrN32x4,
1624636991efdccc3af11ee9691dfa5297872dfb88312cerion                              unop(Iop_NotV128,
1624736991efdccc3af11ee9691dfa5297872dfb88312cerion                                   binop(Iop_CmpGT32Ux4, mkexpr(vB),
1624836991efdccc3af11ee9691dfa5297872dfb88312cerion                                         mkexpr(vA))),
1624936991efdccc3af11ee9691dfa5297872dfb88312cerion                              mkU8(31)) );
1625036991efdccc3af11ee9691dfa5297872dfb88312cerion      break;
1625136991efdccc3af11ee9691dfa5297872dfb88312cerion   }
1625232aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion   case 0x400: // vsububm (Subtract Unsigned Byte Modulo, AV p265)
1625332aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion      DIP("vsububm v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
1625436991efdccc3af11ee9691dfa5297872dfb88312cerion      putVReg( vD_addr, binop(Iop_Sub8x16, mkexpr(vA), mkexpr(vB)) );
1625536991efdccc3af11ee9691dfa5297872dfb88312cerion      break;
1625636991efdccc3af11ee9691dfa5297872dfb88312cerion
1625732aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion   case 0x440: // vsubuhm (Subtract Unsigned Half Word Modulo, AV p267)
1625832aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion      DIP("vsubuhm v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
1625936991efdccc3af11ee9691dfa5297872dfb88312cerion      putVReg( vD_addr, binop(Iop_Sub16x8, mkexpr(vA), mkexpr(vB)) );
1626036991efdccc3af11ee9691dfa5297872dfb88312cerion      break;
1626136991efdccc3af11ee9691dfa5297872dfb88312cerion
1626232aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion   case 0x480: // vsubuwm (Subtract Unsigned Word Modulo, AV p269)
1626332aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion      DIP("vsubuwm v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
1626436991efdccc3af11ee9691dfa5297872dfb88312cerion      putVReg( vD_addr, binop(Iop_Sub32x4, mkexpr(vA), mkexpr(vB)) );
1626536991efdccc3af11ee9691dfa5297872dfb88312cerion      break;
1626636991efdccc3af11ee9691dfa5297872dfb88312cerion
1626748ae46b56cef87c90638b25d6b2462c475033da8carll   case 0x4C0: // vsubudm (Subtract Unsigned Double Word Modulo)
1626848ae46b56cef87c90638b25d6b2462c475033da8carll      DIP("vsubudm v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
1626948ae46b56cef87c90638b25d6b2462c475033da8carll      putVReg( vD_addr, binop(Iop_Sub64x2, mkexpr(vA), mkexpr(vB)) );
1627048ae46b56cef87c90638b25d6b2462c475033da8carll      break;
1627148ae46b56cef87c90638b25d6b2462c475033da8carll
1627232aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion   case 0x600: // vsububs (Subtract Unsigned Byte Saturate, AV p266)
1627332aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion      DIP("vsububs v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
1627436991efdccc3af11ee9691dfa5297872dfb88312cerion      putVReg( vD_addr, binop(Iop_QSub8Ux16, mkexpr(vA), mkexpr(vB)) );
1627536991efdccc3af11ee9691dfa5297872dfb88312cerion      // TODO: set VSCR[SAT]
1627636991efdccc3af11ee9691dfa5297872dfb88312cerion      break;
1627736991efdccc3af11ee9691dfa5297872dfb88312cerion
162785b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion   case 0x640: // vsubuhs (Subtract Unsigned HWord Saturate, AV p268)
1627932aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion      DIP("vsubuhs v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
1628036991efdccc3af11ee9691dfa5297872dfb88312cerion      putVReg( vD_addr, binop(Iop_QSub16Ux8, mkexpr(vA), mkexpr(vB)) );
1628136991efdccc3af11ee9691dfa5297872dfb88312cerion      // TODO: set VSCR[SAT]
1628236991efdccc3af11ee9691dfa5297872dfb88312cerion      break;
1628336991efdccc3af11ee9691dfa5297872dfb88312cerion
1628432aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion   case 0x680: // vsubuws (Subtract Unsigned Word Saturate, AV p270)
1628532aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion      DIP("vsubuws v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
1628636991efdccc3af11ee9691dfa5297872dfb88312cerion      putVReg( vD_addr, binop(Iop_QSub32Ux4, mkexpr(vA), mkexpr(vB)) );
1628736991efdccc3af11ee9691dfa5297872dfb88312cerion      // TODO: set VSCR[SAT]
1628836991efdccc3af11ee9691dfa5297872dfb88312cerion      break;
1628936991efdccc3af11ee9691dfa5297872dfb88312cerion
1629032aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion   case 0x700: // vsubsbs (Subtract Signed Byte Saturate, AV p262)
1629132aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion      DIP("vsubsbs v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
1629236991efdccc3af11ee9691dfa5297872dfb88312cerion      putVReg( vD_addr, binop(Iop_QSub8Sx16, mkexpr(vA), mkexpr(vB)) );
1629336991efdccc3af11ee9691dfa5297872dfb88312cerion      // TODO: set VSCR[SAT]
1629436991efdccc3af11ee9691dfa5297872dfb88312cerion      break;
1629536991efdccc3af11ee9691dfa5297872dfb88312cerion
1629632aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion   case 0x740: // vsubshs (Subtract Signed Half Word Saturate, AV p263)
1629732aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion      DIP("vsubshs v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
1629836991efdccc3af11ee9691dfa5297872dfb88312cerion      putVReg( vD_addr, binop(Iop_QSub16Sx8, mkexpr(vA), mkexpr(vB)) );
1629936991efdccc3af11ee9691dfa5297872dfb88312cerion      // TODO: set VSCR[SAT]
1630036991efdccc3af11ee9691dfa5297872dfb88312cerion      break;
1630136991efdccc3af11ee9691dfa5297872dfb88312cerion
1630232aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion   case 0x780: // vsubsws (Subtract Signed Word Saturate, AV p264)
1630332aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion      DIP("vsubsws v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
1630436991efdccc3af11ee9691dfa5297872dfb88312cerion      putVReg( vD_addr, binop(Iop_QSub32Sx4, mkexpr(vA), mkexpr(vB)) );
1630536991efdccc3af11ee9691dfa5297872dfb88312cerion      // TODO: set VSCR[SAT]
1630636991efdccc3af11ee9691dfa5297872dfb88312cerion      break;
1630732aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion
1630832aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion
1630932aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion   /* Maximum */
1631032aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion   case 0x002: // vmaxub (Maximum Unsigned Byte, AV p182)
1631132aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion      DIP("vmaxub v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
1631236991efdccc3af11ee9691dfa5297872dfb88312cerion      putVReg( vD_addr, binop(Iop_Max8Ux16, mkexpr(vA), mkexpr(vB)) );
1631336991efdccc3af11ee9691dfa5297872dfb88312cerion      break;
1631432aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion
1631532aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion   case 0x042: // vmaxuh (Maximum Unsigned Half Word, AV p183)
1631632aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion      DIP("vmaxuh v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
1631736991efdccc3af11ee9691dfa5297872dfb88312cerion      putVReg( vD_addr, binop(Iop_Max16Ux8, mkexpr(vA), mkexpr(vB)) );
1631836991efdccc3af11ee9691dfa5297872dfb88312cerion      break;
1631932aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion
1632032aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion   case 0x082: // vmaxuw (Maximum Unsigned Word, AV p184)
1632132aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion      DIP("vmaxuw v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
1632236991efdccc3af11ee9691dfa5297872dfb88312cerion      putVReg( vD_addr, binop(Iop_Max32Ux4, mkexpr(vA), mkexpr(vB)) );
1632336991efdccc3af11ee9691dfa5297872dfb88312cerion      break;
1632432aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion
1632548ae46b56cef87c90638b25d6b2462c475033da8carll   case 0x0C2: // vmaxud (Maximum Unsigned Double word)
1632648ae46b56cef87c90638b25d6b2462c475033da8carll      DIP("vmaxud v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
1632748ae46b56cef87c90638b25d6b2462c475033da8carll      putVReg( vD_addr, binop(Iop_Max64Ux2, mkexpr(vA), mkexpr(vB)) );
1632848ae46b56cef87c90638b25d6b2462c475033da8carll      break;
1632948ae46b56cef87c90638b25d6b2462c475033da8carll
1633032aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion   case 0x102: // vmaxsb (Maximum Signed Byte, AV p179)
1633132aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion      DIP("vmaxsb v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
1633236991efdccc3af11ee9691dfa5297872dfb88312cerion      putVReg( vD_addr, binop(Iop_Max8Sx16, mkexpr(vA), mkexpr(vB)) );
1633336991efdccc3af11ee9691dfa5297872dfb88312cerion      break;
1633432aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion
1633532aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion   case 0x142: // vmaxsh (Maximum Signed Half Word, AV p180)
1633632aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion      DIP("vmaxsh v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
1633736991efdccc3af11ee9691dfa5297872dfb88312cerion      putVReg( vD_addr, binop(Iop_Max16Sx8, mkexpr(vA), mkexpr(vB)) );
1633836991efdccc3af11ee9691dfa5297872dfb88312cerion      break;
1633932aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion
1634032aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion   case 0x182: // vmaxsw (Maximum Signed Word, AV p181)
1634132aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion      DIP("vmaxsw v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
1634236991efdccc3af11ee9691dfa5297872dfb88312cerion      putVReg( vD_addr, binop(Iop_Max32Sx4, mkexpr(vA), mkexpr(vB)) );
1634336991efdccc3af11ee9691dfa5297872dfb88312cerion      break;
1634432aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion
1634548ae46b56cef87c90638b25d6b2462c475033da8carll   case 0x1C2: // vmaxsd (Maximum Signed Double word)
1634648ae46b56cef87c90638b25d6b2462c475033da8carll      DIP("vmaxsd v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
1634748ae46b56cef87c90638b25d6b2462c475033da8carll      putVReg( vD_addr, binop(Iop_Max64Sx2, mkexpr(vA), mkexpr(vB)) );
1634848ae46b56cef87c90638b25d6b2462c475033da8carll      break;
1634932aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion
1635032aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion   /* Minimum */
1635132aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion   case 0x202: // vminub (Minimum Unsigned Byte, AV p191)
1635232aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion      DIP("vminub v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
1635336991efdccc3af11ee9691dfa5297872dfb88312cerion      putVReg( vD_addr, binop(Iop_Min8Ux16, mkexpr(vA), mkexpr(vB)) );
1635436991efdccc3af11ee9691dfa5297872dfb88312cerion      break;
1635532aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion
1635632aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion   case 0x242: // vminuh (Minimum Unsigned Half Word, AV p192)
1635732aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion      DIP("vminuh v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
1635836991efdccc3af11ee9691dfa5297872dfb88312cerion      putVReg( vD_addr, binop(Iop_Min16Ux8, mkexpr(vA), mkexpr(vB)) );
1635936991efdccc3af11ee9691dfa5297872dfb88312cerion      break;
1636032aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion
1636132aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion   case 0x282: // vminuw (Minimum Unsigned Word, AV p193)
1636232aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion      DIP("vminuw v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
1636336991efdccc3af11ee9691dfa5297872dfb88312cerion      putVReg( vD_addr, binop(Iop_Min32Ux4, mkexpr(vA), mkexpr(vB)) );
1636436991efdccc3af11ee9691dfa5297872dfb88312cerion      break;
1636532aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion
1636648ae46b56cef87c90638b25d6b2462c475033da8carll   case 0x2C2: // vminud (Minimum Unsigned Double Word)
1636748ae46b56cef87c90638b25d6b2462c475033da8carll      DIP("vminud v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
1636848ae46b56cef87c90638b25d6b2462c475033da8carll      putVReg( vD_addr, binop(Iop_Min64Ux2, mkexpr(vA), mkexpr(vB)) );
1636948ae46b56cef87c90638b25d6b2462c475033da8carll      break;
1637048ae46b56cef87c90638b25d6b2462c475033da8carll
1637132aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion   case 0x302: // vminsb (Minimum Signed Byte, AV p188)
1637232aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion      DIP("vminsb v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
1637336991efdccc3af11ee9691dfa5297872dfb88312cerion      putVReg( vD_addr, binop(Iop_Min8Sx16, mkexpr(vA), mkexpr(vB)) );
1637436991efdccc3af11ee9691dfa5297872dfb88312cerion      break;
1637532aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion
1637632aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion   case 0x342: // vminsh (Minimum Signed Half Word, AV p189)
1637732aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion      DIP("vminsh v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
1637836991efdccc3af11ee9691dfa5297872dfb88312cerion      putVReg( vD_addr, binop(Iop_Min16Sx8, mkexpr(vA), mkexpr(vB)) );
1637936991efdccc3af11ee9691dfa5297872dfb88312cerion      break;
1638032aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion
1638132aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion   case 0x382: // vminsw (Minimum Signed Word, AV p190)
1638232aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion      DIP("vminsw v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
1638336991efdccc3af11ee9691dfa5297872dfb88312cerion      putVReg( vD_addr, binop(Iop_Min32Sx4, mkexpr(vA), mkexpr(vB)) );
1638436991efdccc3af11ee9691dfa5297872dfb88312cerion      break;
1638536991efdccc3af11ee9691dfa5297872dfb88312cerion
1638648ae46b56cef87c90638b25d6b2462c475033da8carll   case 0x3C2: // vminsd (Minimum Signed Double Word)
1638748ae46b56cef87c90638b25d6b2462c475033da8carll      DIP("vminsd v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
1638848ae46b56cef87c90638b25d6b2462c475033da8carll      putVReg( vD_addr, binop(Iop_Min64Sx2, mkexpr(vA), mkexpr(vB)) );
1638948ae46b56cef87c90638b25d6b2462c475033da8carll      break;
1639048ae46b56cef87c90638b25d6b2462c475033da8carll
1639132aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion
1639232aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion   /* Average */
1639332aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion   case 0x402: // vavgub (Average Unsigned Byte, AV p152)
1639432aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion      DIP("vavgub v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
1639536991efdccc3af11ee9691dfa5297872dfb88312cerion      putVReg( vD_addr, binop(Iop_Avg8Ux16, mkexpr(vA), mkexpr(vB)) );
1639636991efdccc3af11ee9691dfa5297872dfb88312cerion      break;
1639732aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion
1639832aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion   case 0x442: // vavguh (Average Unsigned Half Word, AV p153)
1639932aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion      DIP("vavguh v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
1640036991efdccc3af11ee9691dfa5297872dfb88312cerion      putVReg( vD_addr, binop(Iop_Avg16Ux8, mkexpr(vA), mkexpr(vB)) );
1640136991efdccc3af11ee9691dfa5297872dfb88312cerion      break;
1640232aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion
1640332aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion   case 0x482: // vavguw (Average Unsigned Word, AV p154)
1640432aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion      DIP("vavguw v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
1640536991efdccc3af11ee9691dfa5297872dfb88312cerion      putVReg( vD_addr, binop(Iop_Avg32Ux4, mkexpr(vA), mkexpr(vB)) );
1640636991efdccc3af11ee9691dfa5297872dfb88312cerion      break;
1640732aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion
1640832aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion   case 0x502: // vavgsb (Average Signed Byte, AV p149)
1640932aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion      DIP("vavgsb v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
1641036991efdccc3af11ee9691dfa5297872dfb88312cerion      putVReg( vD_addr, binop(Iop_Avg8Sx16, mkexpr(vA), mkexpr(vB)) );
1641136991efdccc3af11ee9691dfa5297872dfb88312cerion      break;
1641232aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion
1641332aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion   case 0x542: // vavgsh (Average Signed Half Word, AV p150)
1641432aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion      DIP("vavgsh v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
1641536991efdccc3af11ee9691dfa5297872dfb88312cerion      putVReg( vD_addr, binop(Iop_Avg16Sx8, mkexpr(vA), mkexpr(vB)) );
1641636991efdccc3af11ee9691dfa5297872dfb88312cerion      break;
1641732aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion
1641832aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion   case 0x582: // vavgsw (Average Signed Word, AV p151)
1641932aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion      DIP("vavgsw v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
1642036991efdccc3af11ee9691dfa5297872dfb88312cerion      putVReg( vD_addr, binop(Iop_Avg32Sx4, mkexpr(vA), mkexpr(vB)) );
1642136991efdccc3af11ee9691dfa5297872dfb88312cerion      break;
1642232aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion
1642332aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion
1642432aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion   /* Multiply */
1642532aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion   case 0x008: // vmuloub (Multiply Odd Unsigned Byte, AV p213)
1642632aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion      DIP("vmuloub v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
164275b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion      putVReg( vD_addr,
164285b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion               binop(Iop_MullEven8Ux16, mkexpr(vA), mkexpr(vB)));
1642936991efdccc3af11ee9691dfa5297872dfb88312cerion      break;
1643032aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion
1643132aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion   case 0x048: // vmulouh (Multiply Odd Unsigned Half Word, AV p214)
1643232aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion      DIP("vmulouh v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
164335b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion      putVReg( vD_addr,
164345b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion               binop(Iop_MullEven16Ux8, mkexpr(vA), mkexpr(vB)));
1643536991efdccc3af11ee9691dfa5297872dfb88312cerion      break;
1643632aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion
1643748ae46b56cef87c90638b25d6b2462c475033da8carll   case 0x088: // vmulouw (Multiply Odd Unsigned Word)
1643848ae46b56cef87c90638b25d6b2462c475033da8carll      DIP("vmulouw v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
1643948ae46b56cef87c90638b25d6b2462c475033da8carll      putVReg( vD_addr, binop( Iop_MullEven32Ux4, mkexpr(vA), mkexpr(vB) ) );
1644048ae46b56cef87c90638b25d6b2462c475033da8carll      break;
1644148ae46b56cef87c90638b25d6b2462c475033da8carll
1644248ae46b56cef87c90638b25d6b2462c475033da8carll   case 0x089: // vmuluwm (Multiply Unsigned Word Modulo)
1644348ae46b56cef87c90638b25d6b2462c475033da8carll      DIP("vmuluwm v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
1644448ae46b56cef87c90638b25d6b2462c475033da8carll      putVReg( vD_addr, binop( Iop_Mul32x4, mkexpr(vA), mkexpr(vB) ) );
1644548ae46b56cef87c90638b25d6b2462c475033da8carll      break;
1644648ae46b56cef87c90638b25d6b2462c475033da8carll
1644732aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion   case 0x108: // vmulosb (Multiply Odd Signed Byte, AV p211)
1644832aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion      DIP("vmulosb v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
164495b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion      putVReg( vD_addr,
164505b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion               binop(Iop_MullEven8Sx16, mkexpr(vA), mkexpr(vB)));
1645136991efdccc3af11ee9691dfa5297872dfb88312cerion      break;
1645232aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion
1645332aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion   case 0x148: // vmulosh (Multiply Odd Signed Half Word, AV p212)
1645432aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion      DIP("vmulosh v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
164555b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion      putVReg( vD_addr,
164565b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion               binop(Iop_MullEven16Sx8, mkexpr(vA), mkexpr(vB)));
1645736991efdccc3af11ee9691dfa5297872dfb88312cerion      break;
1645832aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion
1645948ae46b56cef87c90638b25d6b2462c475033da8carll   case 0x188: // vmulosw (Multiply Odd Signed Word)
1646048ae46b56cef87c90638b25d6b2462c475033da8carll      DIP("vmulosw v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
1646148ae46b56cef87c90638b25d6b2462c475033da8carll      putVReg( vD_addr, binop( Iop_MullEven32Sx4, mkexpr(vA), mkexpr(vB) ) );
1646248ae46b56cef87c90638b25d6b2462c475033da8carll      break;
1646348ae46b56cef87c90638b25d6b2462c475033da8carll
1646432aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion   case 0x208: // vmuleub (Multiply Even Unsigned Byte, AV p209)
1646532aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion      DIP("vmuleub v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
1646624d06f124e3325e8edcc1c495d15736d5adcda96cerion      putVReg( vD_addr, MK_Iop_MullOdd8Ux16( mkexpr(vA), mkexpr(vB) ));
1646736991efdccc3af11ee9691dfa5297872dfb88312cerion      break;
1646832aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion
1646932aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion   case 0x248: // vmuleuh (Multiply Even Unsigned Half Word, AV p210)
1647032aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion      DIP("vmuleuh v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
1647124d06f124e3325e8edcc1c495d15736d5adcda96cerion      putVReg( vD_addr, MK_Iop_MullOdd16Ux8( mkexpr(vA), mkexpr(vB) ));
1647236991efdccc3af11ee9691dfa5297872dfb88312cerion      break;
1647332aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion
1647448ae46b56cef87c90638b25d6b2462c475033da8carll   case 0x288: // vmuleuw (Multiply Even Unsigned Word)
1647548ae46b56cef87c90638b25d6b2462c475033da8carll      DIP("vmuleuw v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
1647648ae46b56cef87c90638b25d6b2462c475033da8carll      putVReg( vD_addr, MK_Iop_MullOdd32Ux4( mkexpr(vA), mkexpr(vB) ) );
1647748ae46b56cef87c90638b25d6b2462c475033da8carll      break;
1647848ae46b56cef87c90638b25d6b2462c475033da8carll
1647932aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion   case 0x308: // vmulesb (Multiply Even Signed Byte, AV p207)
1648032aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion      DIP("vmulesb v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
1648124d06f124e3325e8edcc1c495d15736d5adcda96cerion      putVReg( vD_addr, MK_Iop_MullOdd8Sx16( mkexpr(vA), mkexpr(vB) ));
1648236991efdccc3af11ee9691dfa5297872dfb88312cerion      break;
1648332aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion
1648432aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion   case 0x348: // vmulesh (Multiply Even Signed Half Word, AV p208)
1648532aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion      DIP("vmulesh v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
1648624d06f124e3325e8edcc1c495d15736d5adcda96cerion      putVReg( vD_addr, MK_Iop_MullOdd16Sx8( mkexpr(vA), mkexpr(vB) ));
1648736991efdccc3af11ee9691dfa5297872dfb88312cerion      break;
1648832aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion
1648948ae46b56cef87c90638b25d6b2462c475033da8carll   case 0x388: // vmulesw (Multiply Even Signed Word)
1649048ae46b56cef87c90638b25d6b2462c475033da8carll      DIP("vmulesw v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
1649148ae46b56cef87c90638b25d6b2462c475033da8carll      putVReg( vD_addr, MK_Iop_MullOdd32Sx4( mkexpr(vA), mkexpr(vB) ) );
1649248ae46b56cef87c90638b25d6b2462c475033da8carll      break;
1649332aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion
1649432aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion   /* Sum Across Partial */
164954a49b0393204185f87664ea58f2b7a2ae1d37338cerion   case 0x608: { // vsum4ubs (Sum Partial (1/4) UB Saturate, AV p275)
164964a49b0393204185f87664ea58f2b7a2ae1d37338cerion      IRTemp aEE, aEO, aOE, aOO;
164974a49b0393204185f87664ea58f2b7a2ae1d37338cerion      aEE = aEO = aOE = aOO = IRTemp_INVALID;
1649832aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion      DIP("vsum4ubs v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
1649932aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion
165004a49b0393204185f87664ea58f2b7a2ae1d37338cerion      /* vA: V128_8Ux16 -> 4 x V128_32Ux4, sign-extended */
165014a49b0393204185f87664ea58f2b7a2ae1d37338cerion      expand8Ux16( mkexpr(vA), &aEvn, &aOdd ); // (15,13...),(14,12...)
165024a49b0393204185f87664ea58f2b7a2ae1d37338cerion      expand16Ux8( mkexpr(aEvn), &aEE, &aEO ); // (15,11...),(13, 9...)
165034a49b0393204185f87664ea58f2b7a2ae1d37338cerion      expand16Ux8( mkexpr(aOdd), &aOE, &aOO ); // (14,10...),(12, 8...)
165044a49b0393204185f87664ea58f2b7a2ae1d37338cerion
165054a49b0393204185f87664ea58f2b7a2ae1d37338cerion      /* break V128 to 4xI32's, zero-extending to I64's */
165064a49b0393204185f87664ea58f2b7a2ae1d37338cerion      breakV128to4x64U( mkexpr(aEE), &a15, &a11, &a7, &a3 );
165074a49b0393204185f87664ea58f2b7a2ae1d37338cerion      breakV128to4x64U( mkexpr(aOE), &a14, &a10, &a6, &a2 );
165084a49b0393204185f87664ea58f2b7a2ae1d37338cerion      breakV128to4x64U( mkexpr(aEO), &a13, &a9,  &a5, &a1 );
165094a49b0393204185f87664ea58f2b7a2ae1d37338cerion      breakV128to4x64U( mkexpr(aOO), &a12, &a8,  &a4, &a0 );
165104a49b0393204185f87664ea58f2b7a2ae1d37338cerion      breakV128to4x64U( mkexpr(vB),  &b3,  &b2,  &b1, &b0 );
165114a49b0393204185f87664ea58f2b7a2ae1d37338cerion
165124a49b0393204185f87664ea58f2b7a2ae1d37338cerion      /* add lanes */
165134a49b0393204185f87664ea58f2b7a2ae1d37338cerion      assign( z3, binop(Iop_Add64, mkexpr(b3),
165145b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion                     binop(Iop_Add64,
165155b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion                        binop(Iop_Add64, mkexpr(a15), mkexpr(a14)),
165165b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion                        binop(Iop_Add64, mkexpr(a13), mkexpr(a12)))) );
165174a49b0393204185f87664ea58f2b7a2ae1d37338cerion      assign( z2, binop(Iop_Add64, mkexpr(b2),
165185b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion                     binop(Iop_Add64,
165195b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion                         binop(Iop_Add64, mkexpr(a11), mkexpr(a10)),
165205b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion                         binop(Iop_Add64, mkexpr(a9), mkexpr(a8)))) );
165214a49b0393204185f87664ea58f2b7a2ae1d37338cerion      assign( z1, binop(Iop_Add64, mkexpr(b1),
165225b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion                     binop(Iop_Add64,
165235b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion                         binop(Iop_Add64, mkexpr(a7), mkexpr(a6)),
165245b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion                         binop(Iop_Add64, mkexpr(a5), mkexpr(a4)))) );
165254a49b0393204185f87664ea58f2b7a2ae1d37338cerion      assign( z0, binop(Iop_Add64, mkexpr(b0),
165265b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion                     binop(Iop_Add64,
165275b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion                         binop(Iop_Add64, mkexpr(a3), mkexpr(a2)),
165285b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion                         binop(Iop_Add64, mkexpr(a1), mkexpr(a0)))) );
165294a49b0393204185f87664ea58f2b7a2ae1d37338cerion
165304a49b0393204185f87664ea58f2b7a2ae1d37338cerion      /* saturate-narrow to 32bit, and combine to V128 */
165314a49b0393204185f87664ea58f2b7a2ae1d37338cerion      putVReg( vD_addr, mkV128from4x64U( mkexpr(z3), mkexpr(z2),
165324a49b0393204185f87664ea58f2b7a2ae1d37338cerion                                         mkexpr(z1), mkexpr(z0)) );
165334a49b0393204185f87664ea58f2b7a2ae1d37338cerion      break;
165344a49b0393204185f87664ea58f2b7a2ae1d37338cerion   }
165354a49b0393204185f87664ea58f2b7a2ae1d37338cerion   case 0x708: { // vsum4sbs (Sum Partial (1/4) SB Saturate, AV p273)
165364a49b0393204185f87664ea58f2b7a2ae1d37338cerion      IRTemp aEE, aEO, aOE, aOO;
165374a49b0393204185f87664ea58f2b7a2ae1d37338cerion      aEE = aEO = aOE = aOO = IRTemp_INVALID;
1653832aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion      DIP("vsum4sbs v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
1653932aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion
165404a49b0393204185f87664ea58f2b7a2ae1d37338cerion      /* vA: V128_8Sx16 -> 4 x V128_32Sx4, sign-extended */
165414a49b0393204185f87664ea58f2b7a2ae1d37338cerion      expand8Sx16( mkexpr(vA), &aEvn, &aOdd ); // (15,13...),(14,12...)
165424a49b0393204185f87664ea58f2b7a2ae1d37338cerion      expand16Sx8( mkexpr(aEvn), &aEE, &aEO ); // (15,11...),(13, 9...)
165434a49b0393204185f87664ea58f2b7a2ae1d37338cerion      expand16Sx8( mkexpr(aOdd), &aOE, &aOO ); // (14,10...),(12, 8...)
165444a49b0393204185f87664ea58f2b7a2ae1d37338cerion
165454a49b0393204185f87664ea58f2b7a2ae1d37338cerion      /* break V128 to 4xI32's, sign-extending to I64's */
165464a49b0393204185f87664ea58f2b7a2ae1d37338cerion      breakV128to4x64S( mkexpr(aEE), &a15, &a11, &a7, &a3 );
165474a49b0393204185f87664ea58f2b7a2ae1d37338cerion      breakV128to4x64S( mkexpr(aOE), &a14, &a10, &a6, &a2 );
165484a49b0393204185f87664ea58f2b7a2ae1d37338cerion      breakV128to4x64S( mkexpr(aEO), &a13, &a9,  &a5, &a1 );
165494a49b0393204185f87664ea58f2b7a2ae1d37338cerion      breakV128to4x64S( mkexpr(aOO), &a12, &a8,  &a4, &a0 );
165504a49b0393204185f87664ea58f2b7a2ae1d37338cerion      breakV128to4x64S( mkexpr(vB),  &b3,  &b2,  &b1, &b0 );
165514a49b0393204185f87664ea58f2b7a2ae1d37338cerion
165524a49b0393204185f87664ea58f2b7a2ae1d37338cerion      /* add lanes */
165534a49b0393204185f87664ea58f2b7a2ae1d37338cerion      assign( z3, binop(Iop_Add64, mkexpr(b3),
165545b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion                     binop(Iop_Add64,
165555b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion                        binop(Iop_Add64, mkexpr(a15), mkexpr(a14)),
165565b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion                        binop(Iop_Add64, mkexpr(a13), mkexpr(a12)))) );
165574a49b0393204185f87664ea58f2b7a2ae1d37338cerion      assign( z2, binop(Iop_Add64, mkexpr(b2),
165585b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion                     binop(Iop_Add64,
165595b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion                        binop(Iop_Add64, mkexpr(a11), mkexpr(a10)),
165605b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion                        binop(Iop_Add64, mkexpr(a9), mkexpr(a8)))) );
165614a49b0393204185f87664ea58f2b7a2ae1d37338cerion      assign( z1, binop(Iop_Add64, mkexpr(b1),
165625b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion                     binop(Iop_Add64,
165635b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion                        binop(Iop_Add64, mkexpr(a7), mkexpr(a6)),
165645b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion                        binop(Iop_Add64, mkexpr(a5), mkexpr(a4)))) );
165654a49b0393204185f87664ea58f2b7a2ae1d37338cerion      assign( z0, binop(Iop_Add64, mkexpr(b0),
165665b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion                     binop(Iop_Add64,
165675b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion                        binop(Iop_Add64, mkexpr(a3), mkexpr(a2)),
165685b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion                        binop(Iop_Add64, mkexpr(a1), mkexpr(a0)))) );
165694a49b0393204185f87664ea58f2b7a2ae1d37338cerion
165704a49b0393204185f87664ea58f2b7a2ae1d37338cerion      /* saturate-narrow to 32bit, and combine to V128 */
165714a49b0393204185f87664ea58f2b7a2ae1d37338cerion      putVReg( vD_addr, mkV128from4x64S( mkexpr(z3), mkexpr(z2),
165724a49b0393204185f87664ea58f2b7a2ae1d37338cerion                                         mkexpr(z1), mkexpr(z0)) );
165734a49b0393204185f87664ea58f2b7a2ae1d37338cerion      break;
165744a49b0393204185f87664ea58f2b7a2ae1d37338cerion   }
165754a49b0393204185f87664ea58f2b7a2ae1d37338cerion   case 0x648: { // vsum4shs (Sum Partial (1/4) SHW Saturate, AV p274)
1657632aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion      DIP("vsum4shs v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
1657732aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion
165784a49b0393204185f87664ea58f2b7a2ae1d37338cerion      /* vA: V128_16Sx8 -> 2 x V128_32Sx4, sign-extended */
165794a49b0393204185f87664ea58f2b7a2ae1d37338cerion      expand16Sx8( mkexpr(vA), &aEvn, &aOdd ); // (7,5...),(6,4...)
165804a49b0393204185f87664ea58f2b7a2ae1d37338cerion
165814a49b0393204185f87664ea58f2b7a2ae1d37338cerion      /* break V128 to 4xI32's, sign-extending to I64's */
165824a49b0393204185f87664ea58f2b7a2ae1d37338cerion      breakV128to4x64S( mkexpr(aEvn), &a7, &a5, &a3, &a1 );
165834a49b0393204185f87664ea58f2b7a2ae1d37338cerion      breakV128to4x64S( mkexpr(aOdd), &a6, &a4, &a2, &a0 );
165844a49b0393204185f87664ea58f2b7a2ae1d37338cerion      breakV128to4x64S( mkexpr(vB),   &b3, &b2, &b1, &b0 );
165854a49b0393204185f87664ea58f2b7a2ae1d37338cerion
165864a49b0393204185f87664ea58f2b7a2ae1d37338cerion      /* add lanes */
165874a49b0393204185f87664ea58f2b7a2ae1d37338cerion      assign( z3, binop(Iop_Add64, mkexpr(b3),
165884a49b0393204185f87664ea58f2b7a2ae1d37338cerion                        binop(Iop_Add64, mkexpr(a7), mkexpr(a6))));
165894a49b0393204185f87664ea58f2b7a2ae1d37338cerion      assign( z2, binop(Iop_Add64, mkexpr(b2),
165904a49b0393204185f87664ea58f2b7a2ae1d37338cerion                        binop(Iop_Add64, mkexpr(a5), mkexpr(a4))));
165914a49b0393204185f87664ea58f2b7a2ae1d37338cerion      assign( z1, binop(Iop_Add64, mkexpr(b1),
165924a49b0393204185f87664ea58f2b7a2ae1d37338cerion                        binop(Iop_Add64, mkexpr(a3), mkexpr(a2))));
165934a49b0393204185f87664ea58f2b7a2ae1d37338cerion      assign( z0, binop(Iop_Add64, mkexpr(b0),
165944a49b0393204185f87664ea58f2b7a2ae1d37338cerion                        binop(Iop_Add64, mkexpr(a1), mkexpr(a0))));
165954a49b0393204185f87664ea58f2b7a2ae1d37338cerion
165964a49b0393204185f87664ea58f2b7a2ae1d37338cerion      /* saturate-narrow to 32bit, and combine to V128 */
165974a49b0393204185f87664ea58f2b7a2ae1d37338cerion      putVReg( vD_addr, mkV128from4x64S( mkexpr(z3), mkexpr(z2),
165984a49b0393204185f87664ea58f2b7a2ae1d37338cerion                                         mkexpr(z1), mkexpr(z0)) );
165994a49b0393204185f87664ea58f2b7a2ae1d37338cerion      break;
166004a49b0393204185f87664ea58f2b7a2ae1d37338cerion   }
166014a49b0393204185f87664ea58f2b7a2ae1d37338cerion   case 0x688: { // vsum2sws (Sum Partial (1/2) SW Saturate, AV p272)
1660232aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion      DIP("vsum2sws v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
1660332aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion
166044a49b0393204185f87664ea58f2b7a2ae1d37338cerion      /* break V128 to 4xI32's, sign-extending to I64's */
166054a49b0393204185f87664ea58f2b7a2ae1d37338cerion      breakV128to4x64S( mkexpr(vA), &a3, &a2, &a1, &a0 );
166064a49b0393204185f87664ea58f2b7a2ae1d37338cerion      breakV128to4x64S( mkexpr(vB), &b3, &b2, &b1, &b0 );
166074a49b0393204185f87664ea58f2b7a2ae1d37338cerion
166084a49b0393204185f87664ea58f2b7a2ae1d37338cerion      /* add lanes */
166094a49b0393204185f87664ea58f2b7a2ae1d37338cerion      assign( z2, binop(Iop_Add64, mkexpr(b2),
166104a49b0393204185f87664ea58f2b7a2ae1d37338cerion                        binop(Iop_Add64, mkexpr(a3), mkexpr(a2))) );
166114a49b0393204185f87664ea58f2b7a2ae1d37338cerion      assign( z0, binop(Iop_Add64, mkexpr(b0),
166124a49b0393204185f87664ea58f2b7a2ae1d37338cerion                        binop(Iop_Add64, mkexpr(a1), mkexpr(a0))) );
166134a49b0393204185f87664ea58f2b7a2ae1d37338cerion
166144a49b0393204185f87664ea58f2b7a2ae1d37338cerion      /* saturate-narrow to 32bit, and combine to V128 */
166154a49b0393204185f87664ea58f2b7a2ae1d37338cerion      putVReg( vD_addr, mkV128from4x64S( mkU64(0), mkexpr(z2),
166164a49b0393204185f87664ea58f2b7a2ae1d37338cerion                                         mkU64(0), mkexpr(z0)) );
166174a49b0393204185f87664ea58f2b7a2ae1d37338cerion      break;
166184a49b0393204185f87664ea58f2b7a2ae1d37338cerion   }
166194a49b0393204185f87664ea58f2b7a2ae1d37338cerion   case 0x788: { // vsumsws  (Sum SW Saturate, AV p271)
1662032aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion      DIP("vsumsws v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
1662132aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion
166224a49b0393204185f87664ea58f2b7a2ae1d37338cerion      /* break V128 to 4xI32's, sign-extending to I64's */
166234a49b0393204185f87664ea58f2b7a2ae1d37338cerion      breakV128to4x64S( mkexpr(vA), &a3, &a2, &a1, &a0 );
166244a49b0393204185f87664ea58f2b7a2ae1d37338cerion      breakV128to4x64S( mkexpr(vB), &b3, &b2, &b1, &b0 );
166254a49b0393204185f87664ea58f2b7a2ae1d37338cerion
166264a49b0393204185f87664ea58f2b7a2ae1d37338cerion      /* add lanes */
166274a49b0393204185f87664ea58f2b7a2ae1d37338cerion      assign( z0, binop(Iop_Add64, mkexpr(b0),
166285b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion                     binop(Iop_Add64,
166295b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion                        binop(Iop_Add64, mkexpr(a3), mkexpr(a2)),
166305b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion                        binop(Iop_Add64, mkexpr(a1), mkexpr(a0)))) );
166314a49b0393204185f87664ea58f2b7a2ae1d37338cerion
166324a49b0393204185f87664ea58f2b7a2ae1d37338cerion      /* saturate-narrow to 32bit, and combine to V128 */
166334a49b0393204185f87664ea58f2b7a2ae1d37338cerion      putVReg( vD_addr, mkV128from4x64S( mkU64(0), mkU64(0),
166344a49b0393204185f87664ea58f2b7a2ae1d37338cerion                                         mkU64(0), mkexpr(z0)) );
166354a49b0393204185f87664ea58f2b7a2ae1d37338cerion      break;
166364a49b0393204185f87664ea58f2b7a2ae1d37338cerion   }
1663732aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion   default:
166385b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion      vex_printf("dis_av_arith(ppc)(opc2=0x%x)\n", opc2);
1663932aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion      return False;
1664032aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion   }
1664132aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion   return True;
1664232aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion}
1664332aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion
1664432aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion/*
1664532aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion  AltiVec Logic Instructions
1664632aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion*/
1664732aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerionstatic Bool dis_av_logic ( UInt theInstr )
1664832aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion{
1664976de5cf615380b23b4b5bcced6541233cd4a93a0cerion   /* VX-Form */
1665076de5cf615380b23b4b5bcced6541233cd4a93a0cerion   UChar opc1    = ifieldOPC(theInstr);
1665176de5cf615380b23b4b5bcced6541233cd4a93a0cerion   UChar vD_addr = ifieldRegDS(theInstr);
1665276de5cf615380b23b4b5bcced6541233cd4a93a0cerion   UChar vA_addr = ifieldRegA(theInstr);
1665376de5cf615380b23b4b5bcced6541233cd4a93a0cerion   UChar vB_addr = ifieldRegB(theInstr);
1665476de5cf615380b23b4b5bcced6541233cd4a93a0cerion   UInt  opc2    = IFIELD( theInstr, 0, 11 );
1665532aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion
16656225a034683024109da729a4d2f080364b9485007cerion   IRTemp vA = newTemp(Ity_V128);
16657225a034683024109da729a4d2f080364b9485007cerion   IRTemp vB = newTemp(Ity_V128);
16658225a034683024109da729a4d2f080364b9485007cerion   assign( vA, getVReg(vA_addr));
16659225a034683024109da729a4d2f080364b9485007cerion   assign( vB, getVReg(vB_addr));
16660225a034683024109da729a4d2f080364b9485007cerion
1666132aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion   if (opc1 != 0x4) {
166625b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion      vex_printf("dis_av_logic(ppc)(opc1 != 0x4)\n");
1666332aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion      return False;
1666432aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion   }
1666532aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion
1666632aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion   switch (opc2) {
1666732aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion   case 0x404: // vand (And, AV p147)
1666832aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion      DIP("vand v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
16669225a034683024109da729a4d2f080364b9485007cerion      putVReg( vD_addr, binop(Iop_AndV128, mkexpr(vA), mkexpr(vB)) );
16670225a034683024109da729a4d2f080364b9485007cerion      break;
1667132aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion
1667232aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion   case 0x444: // vandc (And, AV p148)
1667332aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion      DIP("vandc v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
166746e7a0ea9abe4e6443ebfc451d5681250eece75fdcerion      putVReg( vD_addr, binop(Iop_AndV128, mkexpr(vA),
1667576de5cf615380b23b4b5bcced6541233cd4a93a0cerion                              unop(Iop_NotV128, mkexpr(vB))) );
166766e7a0ea9abe4e6443ebfc451d5681250eece75fdcerion      break;
1667732aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion
1667832aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion   case 0x484: // vor (Or, AV p217)
1667932aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion      DIP("vor v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
16680225a034683024109da729a4d2f080364b9485007cerion      putVReg( vD_addr, binop(Iop_OrV128, mkexpr(vA), mkexpr(vB)) );
16681225a034683024109da729a4d2f080364b9485007cerion      break;
1668232aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion
1668332aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion   case 0x4C4: // vxor (Xor, AV p282)
1668432aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion      DIP("vxor v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
16685225a034683024109da729a4d2f080364b9485007cerion      putVReg( vD_addr, binop(Iop_XorV128, mkexpr(vA), mkexpr(vB)) );
16686225a034683024109da729a4d2f080364b9485007cerion      break;
1668732aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion
1668832aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion   case 0x504: // vnor (Nor, AV p216)
1668932aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion      DIP("vnor v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
166906e7a0ea9abe4e6443ebfc451d5681250eece75fdcerion      putVReg( vD_addr,
166916e7a0ea9abe4e6443ebfc451d5681250eece75fdcerion         unop(Iop_NotV128, binop(Iop_OrV128, mkexpr(vA), mkexpr(vB))) );
166926e7a0ea9abe4e6443ebfc451d5681250eece75fdcerion      break;
1669332aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion
166947deaf9552b546b847528cf39b38898fb7742b5f5carll   case 0x544: // vorc (vA Or'd with complement of vb)
166957deaf9552b546b847528cf39b38898fb7742b5f5carll      DIP("vorc v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
166967deaf9552b546b847528cf39b38898fb7742b5f5carll      putVReg( vD_addr, binop( Iop_OrV128,
166977deaf9552b546b847528cf39b38898fb7742b5f5carll                               mkexpr( vA ),
166987deaf9552b546b847528cf39b38898fb7742b5f5carll                               unop( Iop_NotV128, mkexpr( vB ) ) ) );
166997deaf9552b546b847528cf39b38898fb7742b5f5carll      break;
167007deaf9552b546b847528cf39b38898fb7742b5f5carll
167017deaf9552b546b847528cf39b38898fb7742b5f5carll   case 0x584: // vnand (Nand)
167027deaf9552b546b847528cf39b38898fb7742b5f5carll      DIP("vnand v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
167037deaf9552b546b847528cf39b38898fb7742b5f5carll      putVReg( vD_addr, unop( Iop_NotV128,
167047deaf9552b546b847528cf39b38898fb7742b5f5carll                              binop(Iop_AndV128, mkexpr( vA ),
167057deaf9552b546b847528cf39b38898fb7742b5f5carll                              mkexpr( vB ) ) ) );
167067deaf9552b546b847528cf39b38898fb7742b5f5carll      break;
167077deaf9552b546b847528cf39b38898fb7742b5f5carll
167087deaf9552b546b847528cf39b38898fb7742b5f5carll   case 0x684: // veqv (complemented XOr)
167097deaf9552b546b847528cf39b38898fb7742b5f5carll      DIP("veqv v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
167107deaf9552b546b847528cf39b38898fb7742b5f5carll      putVReg( vD_addr, unop( Iop_NotV128,
167117deaf9552b546b847528cf39b38898fb7742b5f5carll                              binop( Iop_XorV128, mkexpr( vA ),
167127deaf9552b546b847528cf39b38898fb7742b5f5carll                              mkexpr( vB ) ) ) );
167137deaf9552b546b847528cf39b38898fb7742b5f5carll      break;
167147deaf9552b546b847528cf39b38898fb7742b5f5carll
1671532aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion   default:
167165b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion      vex_printf("dis_av_logic(ppc)(opc2=0x%x)\n", opc2);
1671732aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion      return False;
1671832aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion   }
1671932aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion   return True;
1672032aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion}
1672132aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion
1672232aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion/*
1672332aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion  AltiVec Compare Instructions
1672432aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion*/
1672532aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerionstatic Bool dis_av_cmp ( UInt theInstr )
1672632aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion{
1672776de5cf615380b23b4b5bcced6541233cd4a93a0cerion   /* VXR-Form */
1672876de5cf615380b23b4b5bcced6541233cd4a93a0cerion   UChar opc1     = ifieldOPC(theInstr);
1672976de5cf615380b23b4b5bcced6541233cd4a93a0cerion   UChar vD_addr  = ifieldRegDS(theInstr);
1673076de5cf615380b23b4b5bcced6541233cd4a93a0cerion   UChar vA_addr  = ifieldRegA(theInstr);
1673176de5cf615380b23b4b5bcced6541233cd4a93a0cerion   UChar vB_addr  = ifieldRegB(theInstr);
1673276de5cf615380b23b4b5bcced6541233cd4a93a0cerion   UChar flag_rC  = ifieldBIT10(theInstr);
1673376de5cf615380b23b4b5bcced6541233cd4a93a0cerion   UInt  opc2     = IFIELD( theInstr, 0, 10 );
1673432aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion
167350c43922a06643631fb78de1f6d5a00837c189e9bcerion   IRTemp vA = newTemp(Ity_V128);
167360c43922a06643631fb78de1f6d5a00837c189e9bcerion   IRTemp vB = newTemp(Ity_V128);
167370c43922a06643631fb78de1f6d5a00837c189e9bcerion   IRTemp vD = newTemp(Ity_V128);
167380c43922a06643631fb78de1f6d5a00837c189e9bcerion   assign( vA, getVReg(vA_addr));
167390c43922a06643631fb78de1f6d5a00837c189e9bcerion   assign( vB, getVReg(vB_addr));
167400c43922a06643631fb78de1f6d5a00837c189e9bcerion
1674132aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion   if (opc1 != 0x4) {
167425b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion      vex_printf("dis_av_cmp(ppc)(instr)\n");
1674332aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion      return False;
1674432aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion   }
1674532aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion
1674632aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion   switch (opc2) {
1674732aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion   case 0x006: // vcmpequb (Compare Equal-to Unsigned B, AV p160)
167485b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion      DIP("vcmpequb%s v%d,v%d,v%d\n", (flag_rC ? ".":""),
167495b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion                                      vD_addr, vA_addr, vB_addr);
167500c43922a06643631fb78de1f6d5a00837c189e9bcerion      assign( vD, binop(Iop_CmpEQ8x16, mkexpr(vA), mkexpr(vB)) );
167510c43922a06643631fb78de1f6d5a00837c189e9bcerion      break;
1675232aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion
1675332aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion   case 0x046: // vcmpequh (Compare Equal-to Unsigned HW, AV p161)
167545b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion      DIP("vcmpequh%s v%d,v%d,v%d\n", (flag_rC ? ".":""),
167555b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion                                      vD_addr, vA_addr, vB_addr);
167560c43922a06643631fb78de1f6d5a00837c189e9bcerion      assign( vD, binop(Iop_CmpEQ16x8, mkexpr(vA), mkexpr(vB)) );
167570c43922a06643631fb78de1f6d5a00837c189e9bcerion      break;
1675832aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion
1675932aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion   case 0x086: // vcmpequw (Compare Equal-to Unsigned W, AV p162)
167605b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion      DIP("vcmpequw%s v%d,v%d,v%d\n", (flag_rC ? ".":""),
167615b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion                                      vD_addr, vA_addr, vB_addr);
167620c43922a06643631fb78de1f6d5a00837c189e9bcerion      assign( vD, binop(Iop_CmpEQ32x4, mkexpr(vA), mkexpr(vB)) );
167630c43922a06643631fb78de1f6d5a00837c189e9bcerion      break;
1676432aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion
1676548ae46b56cef87c90638b25d6b2462c475033da8carll   case 0x0C7: // vcmpequd (Compare Equal-to Unsigned Doubleword)
1676648ae46b56cef87c90638b25d6b2462c475033da8carll      DIP("vcmpequd%s v%d,v%d,v%d\n", (flag_rC ? ".":""),
1676748ae46b56cef87c90638b25d6b2462c475033da8carll                                      vD_addr, vA_addr, vB_addr);
1676848ae46b56cef87c90638b25d6b2462c475033da8carll      assign( vD, binop(Iop_CmpEQ64x2, mkexpr(vA), mkexpr(vB)) );
1676948ae46b56cef87c90638b25d6b2462c475033da8carll      break;
1677048ae46b56cef87c90638b25d6b2462c475033da8carll
1677132aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion   case 0x206: // vcmpgtub (Compare Greater-than Unsigned B, AV p168)
167725b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion      DIP("vcmpgtub%s v%d,v%d,v%d\n", (flag_rC ? ".":""),
167735b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion                                      vD_addr, vA_addr, vB_addr);
167740c43922a06643631fb78de1f6d5a00837c189e9bcerion      assign( vD, binop(Iop_CmpGT8Ux16, mkexpr(vA), mkexpr(vB)) );
167750c43922a06643631fb78de1f6d5a00837c189e9bcerion      break;
1677632aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion
1677732aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion   case 0x246: // vcmpgtuh (Compare Greater-than Unsigned HW, AV p169)
167785b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion      DIP("vcmpgtuh%s v%d,v%d,v%d\n", (flag_rC ? ".":""),
167795b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion                                      vD_addr, vA_addr, vB_addr);
167800c43922a06643631fb78de1f6d5a00837c189e9bcerion      assign( vD, binop(Iop_CmpGT16Ux8, mkexpr(vA), mkexpr(vB)) );
167810c43922a06643631fb78de1f6d5a00837c189e9bcerion      break;
1678232aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion
1678332aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion   case 0x286: // vcmpgtuw (Compare Greater-than Unsigned W, AV p170)
167845b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion      DIP("vcmpgtuw%s v%d,v%d,v%d\n", (flag_rC ? ".":""),
167855b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion                                       vD_addr, vA_addr, vB_addr);
167860c43922a06643631fb78de1f6d5a00837c189e9bcerion      assign( vD, binop(Iop_CmpGT32Ux4, mkexpr(vA), mkexpr(vB)) );
167870c43922a06643631fb78de1f6d5a00837c189e9bcerion      break;
1678832aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion
1678948ae46b56cef87c90638b25d6b2462c475033da8carll   case 0x2C7: // vcmpgtud (Compare Greater-than Unsigned double)
1679048ae46b56cef87c90638b25d6b2462c475033da8carll      DIP("vcmpgtud%s v%d,v%d,v%d\n", (flag_rC ? ".":""),
1679148ae46b56cef87c90638b25d6b2462c475033da8carll                                      vD_addr, vA_addr, vB_addr);
1679248ae46b56cef87c90638b25d6b2462c475033da8carll      assign( vD, binop(Iop_CmpGT64Ux2, mkexpr(vA), mkexpr(vB)) );
1679348ae46b56cef87c90638b25d6b2462c475033da8carll      break;
1679448ae46b56cef87c90638b25d6b2462c475033da8carll
1679532aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion   case 0x306: // vcmpgtsb (Compare Greater-than Signed B, AV p165)
167965b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion      DIP("vcmpgtsb%s v%d,v%d,v%d\n", (flag_rC ? ".":""),
167975b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion                                       vD_addr, vA_addr, vB_addr);
167980c43922a06643631fb78de1f6d5a00837c189e9bcerion      assign( vD, binop(Iop_CmpGT8Sx16, mkexpr(vA), mkexpr(vB)) );
167990c43922a06643631fb78de1f6d5a00837c189e9bcerion      break;
1680032aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion
1680132aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion   case 0x346: // vcmpgtsh (Compare Greater-than Signed HW, AV p166)
168025b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion      DIP("vcmpgtsh%s v%d,v%d,v%d\n", (flag_rC ? ".":""),
168035b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion                                      vD_addr, vA_addr, vB_addr);
168040c43922a06643631fb78de1f6d5a00837c189e9bcerion      assign( vD, binop(Iop_CmpGT16Sx8, mkexpr(vA), mkexpr(vB)) );
168050c43922a06643631fb78de1f6d5a00837c189e9bcerion      break;
1680632aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion
1680732aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion   case 0x386: // vcmpgtsw (Compare Greater-than Signed W, AV p167)
168085b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion      DIP("vcmpgtsw%s v%d,v%d,v%d\n", (flag_rC ? ".":""),
168095b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion                                      vD_addr, vA_addr, vB_addr);
168100c43922a06643631fb78de1f6d5a00837c189e9bcerion      assign( vD, binop(Iop_CmpGT32Sx4, mkexpr(vA), mkexpr(vB)) );
168110c43922a06643631fb78de1f6d5a00837c189e9bcerion      break;
1681232aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion
1681348ae46b56cef87c90638b25d6b2462c475033da8carll   case 0x3C7: // vcmpgtsd (Compare Greater-than Signed double)
1681448ae46b56cef87c90638b25d6b2462c475033da8carll      DIP("vcmpgtsd%s v%d,v%d,v%d\n", (flag_rC ? ".":""),
1681548ae46b56cef87c90638b25d6b2462c475033da8carll                                      vD_addr, vA_addr, vB_addr);
1681648ae46b56cef87c90638b25d6b2462c475033da8carll      assign( vD, binop(Iop_CmpGT64Sx2, mkexpr(vA), mkexpr(vB)) );
1681748ae46b56cef87c90638b25d6b2462c475033da8carll      break;
1681848ae46b56cef87c90638b25d6b2462c475033da8carll
1681932aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion   default:
168205b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion      vex_printf("dis_av_cmp(ppc)(opc2)\n");
1682132aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion      return False;
1682232aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion   }
168230c43922a06643631fb78de1f6d5a00837c189e9bcerion
168240c43922a06643631fb78de1f6d5a00837c189e9bcerion   putVReg( vD_addr, mkexpr(vD) );
168250c43922a06643631fb78de1f6d5a00837c189e9bcerion
1682676de5cf615380b23b4b5bcced6541233cd4a93a0cerion   if (flag_rC) {
168278ea0d3ebfb8b1e4d8b6f851b0079c47a9886c686cerion      set_AV_CR6( mkexpr(vD), True );
168280c43922a06643631fb78de1f6d5a00837c189e9bcerion   }
1682932aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion   return True;
1683032aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion}
1683132aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion
1683232aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion/*
1683332aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion  AltiVec Multiply-Sum Instructions
1683432aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion*/
1683532aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerionstatic Bool dis_av_multarith ( UInt theInstr )
1683632aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion{
1683776de5cf615380b23b4b5bcced6541233cd4a93a0cerion   /* VA-Form */
1683876de5cf615380b23b4b5bcced6541233cd4a93a0cerion   UChar opc1     = ifieldOPC(theInstr);
1683976de5cf615380b23b4b5bcced6541233cd4a93a0cerion   UChar vD_addr  = ifieldRegDS(theInstr);
1684076de5cf615380b23b4b5bcced6541233cd4a93a0cerion   UChar vA_addr  = ifieldRegA(theInstr);
1684176de5cf615380b23b4b5bcced6541233cd4a93a0cerion   UChar vB_addr  = ifieldRegB(theInstr);
1684276de5cf615380b23b4b5bcced6541233cd4a93a0cerion   UChar vC_addr  = ifieldRegC(theInstr);
1684376de5cf615380b23b4b5bcced6541233cd4a93a0cerion   UChar opc2     = toUChar( IFIELD( theInstr, 0, 6 ) );
1684432aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion
168454a49b0393204185f87664ea58f2b7a2ae1d37338cerion   IRTemp vA    = newTemp(Ity_V128);
168464a49b0393204185f87664ea58f2b7a2ae1d37338cerion   IRTemp vB    = newTemp(Ity_V128);
168474a49b0393204185f87664ea58f2b7a2ae1d37338cerion   IRTemp vC    = newTemp(Ity_V128);
16848197bd17d3ba8ac5204cd5c9ba5fab571249eb791sewardj   IRTemp zeros = newTemp(Ity_V128);
168494a49b0393204185f87664ea58f2b7a2ae1d37338cerion   IRTemp aLo   = newTemp(Ity_V128);
168504a49b0393204185f87664ea58f2b7a2ae1d37338cerion   IRTemp bLo   = newTemp(Ity_V128);
168514a49b0393204185f87664ea58f2b7a2ae1d37338cerion   IRTemp cLo   = newTemp(Ity_V128);
168524a49b0393204185f87664ea58f2b7a2ae1d37338cerion   IRTemp zLo   = newTemp(Ity_V128);
168534a49b0393204185f87664ea58f2b7a2ae1d37338cerion   IRTemp aHi   = newTemp(Ity_V128);
168544a49b0393204185f87664ea58f2b7a2ae1d37338cerion   IRTemp bHi   = newTemp(Ity_V128);
168554a49b0393204185f87664ea58f2b7a2ae1d37338cerion   IRTemp cHi   = newTemp(Ity_V128);
168564a49b0393204185f87664ea58f2b7a2ae1d37338cerion   IRTemp zHi   = newTemp(Ity_V128);
168574a49b0393204185f87664ea58f2b7a2ae1d37338cerion   IRTemp abEvn = newTemp(Ity_V128);
168584a49b0393204185f87664ea58f2b7a2ae1d37338cerion   IRTemp abOdd = newTemp(Ity_V128);
168594a49b0393204185f87664ea58f2b7a2ae1d37338cerion   IRTemp z3    = newTemp(Ity_I64);
168604a49b0393204185f87664ea58f2b7a2ae1d37338cerion   IRTemp z2    = newTemp(Ity_I64);
168614a49b0393204185f87664ea58f2b7a2ae1d37338cerion   IRTemp z1    = newTemp(Ity_I64);
168624a49b0393204185f87664ea58f2b7a2ae1d37338cerion   IRTemp z0    = newTemp(Ity_I64);
168634a49b0393204185f87664ea58f2b7a2ae1d37338cerion   IRTemp ab7, ab6, ab5, ab4, ab3, ab2, ab1, ab0;
168644a49b0393204185f87664ea58f2b7a2ae1d37338cerion   IRTemp c3, c2, c1, c0;
168654a49b0393204185f87664ea58f2b7a2ae1d37338cerion
168664a49b0393204185f87664ea58f2b7a2ae1d37338cerion   ab7 = ab6 = ab5 = ab4 = ab3 = ab2 = ab1 = ab0 = IRTemp_INVALID;
168674a49b0393204185f87664ea58f2b7a2ae1d37338cerion   c3 = c2 = c1 = c0 = IRTemp_INVALID;
168684a49b0393204185f87664ea58f2b7a2ae1d37338cerion
168696f1cc0fd33c0b074bcac7901fe0dd277c73ca01ccerion   assign( vA, getVReg(vA_addr));
168706f1cc0fd33c0b074bcac7901fe0dd277c73ca01ccerion   assign( vB, getVReg(vB_addr));
168716f1cc0fd33c0b074bcac7901fe0dd277c73ca01ccerion   assign( vC, getVReg(vC_addr));
168724a49b0393204185f87664ea58f2b7a2ae1d37338cerion   assign( zeros, unop(Iop_Dup32x4, mkU32(0)) );
168736f1cc0fd33c0b074bcac7901fe0dd277c73ca01ccerion
1687432aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion   if (opc1 != 0x4) {
168755b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion      vex_printf("dis_av_multarith(ppc)(instr)\n");
1687632aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion      return False;
1687732aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion   }
1687832aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion
168796f1cc0fd33c0b074bcac7901fe0dd277c73ca01ccerion   switch (opc2) {
1688032aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion   /* Multiply-Add */
168815b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion   case 0x20: { // vmhaddshs (Mult Hi, Add Signed HW Saturate, AV p185)
168826f1cc0fd33c0b074bcac7901fe0dd277c73ca01ccerion      IRTemp cSigns = newTemp(Ity_V128);
168835b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion      DIP("vmhaddshs v%d,v%d,v%d,v%d\n",
168845b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion          vD_addr, vA_addr, vB_addr, vC_addr);
168855b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion      assign(cSigns, binop(Iop_CmpGT16Sx8, mkexpr(zeros), mkexpr(vC)));
168865b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion      assign(aLo, binop(Iop_InterleaveLO16x8, mkexpr(zeros), mkexpr(vA)));
168875b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion      assign(bLo, binop(Iop_InterleaveLO16x8, mkexpr(zeros), mkexpr(vB)));
168885b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion      assign(cLo, binop(Iop_InterleaveLO16x8, mkexpr(cSigns),mkexpr(vC)));
168895b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion      assign(aHi, binop(Iop_InterleaveHI16x8, mkexpr(zeros), mkexpr(vA)));
168905b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion      assign(bHi, binop(Iop_InterleaveHI16x8, mkexpr(zeros), mkexpr(vB)));
168915b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion      assign(cHi, binop(Iop_InterleaveHI16x8, mkexpr(cSigns),mkexpr(vC)));
168926f1cc0fd33c0b074bcac7901fe0dd277c73ca01ccerion
1689324d06f124e3325e8edcc1c495d15736d5adcda96cerion      assign( zLo, binop(Iop_Add32x4, mkexpr(cLo),
168946f1cc0fd33c0b074bcac7901fe0dd277c73ca01ccerion                         binop(Iop_SarN32x4,
168951ac656a3b8eead55eeb0fb9090efec1c6719f989cerion                               binop(Iop_MullEven16Sx8,
1689624d06f124e3325e8edcc1c495d15736d5adcda96cerion                                     mkexpr(aLo), mkexpr(bLo)),
1689724d06f124e3325e8edcc1c495d15736d5adcda96cerion                               mkU8(15))) );
168986f1cc0fd33c0b074bcac7901fe0dd277c73ca01ccerion
1689924d06f124e3325e8edcc1c495d15736d5adcda96cerion      assign( zHi, binop(Iop_Add32x4, mkexpr(cHi),
169006f1cc0fd33c0b074bcac7901fe0dd277c73ca01ccerion                         binop(Iop_SarN32x4,
169011ac656a3b8eead55eeb0fb9090efec1c6719f989cerion                               binop(Iop_MullEven16Sx8,
1690224d06f124e3325e8edcc1c495d15736d5adcda96cerion                                     mkexpr(aHi), mkexpr(bHi)),
1690324d06f124e3325e8edcc1c495d15736d5adcda96cerion                               mkU8(15))) );
169046f1cc0fd33c0b074bcac7901fe0dd277c73ca01ccerion
169055b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion      putVReg( vD_addr,
169065f438dd73072211989c6d496845bdc9b777ecbecsewardj               binop(Iop_QNarrowBin32Sto16Sx8, mkexpr(zHi), mkexpr(zLo)) );
169076f1cc0fd33c0b074bcac7901fe0dd277c73ca01ccerion      break;
169086f1cc0fd33c0b074bcac7901fe0dd277c73ca01ccerion   }
169095b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion   case 0x21: { // vmhraddshs (Mult High Round, Add Signed HW Saturate, AV p186)
169106f1cc0fd33c0b074bcac7901fe0dd277c73ca01ccerion      IRTemp zKonst = newTemp(Ity_V128);
169116f1cc0fd33c0b074bcac7901fe0dd277c73ca01ccerion      IRTemp cSigns = newTemp(Ity_V128);
169125b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion      DIP("vmhraddshs v%d,v%d,v%d,v%d\n",
169135b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion          vD_addr, vA_addr, vB_addr, vC_addr);
169145b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion      assign(cSigns, binop(Iop_CmpGT16Sx8, mkexpr(zeros), mkexpr(vC)) );
169155b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion      assign(aLo, binop(Iop_InterleaveLO16x8, mkexpr(zeros), mkexpr(vA)));
169165b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion      assign(bLo, binop(Iop_InterleaveLO16x8, mkexpr(zeros), mkexpr(vB)));
169175b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion      assign(cLo, binop(Iop_InterleaveLO16x8, mkexpr(cSigns),mkexpr(vC)));
169185b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion      assign(aHi, binop(Iop_InterleaveHI16x8, mkexpr(zeros), mkexpr(vA)));
169195b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion      assign(bHi, binop(Iop_InterleaveHI16x8, mkexpr(zeros), mkexpr(vB)));
169205b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion      assign(cHi, binop(Iop_InterleaveHI16x8, mkexpr(cSigns),mkexpr(vC)));
169216f1cc0fd33c0b074bcac7901fe0dd277c73ca01ccerion
169226f1cc0fd33c0b074bcac7901fe0dd277c73ca01ccerion      /* shifting our const avoids store/load version of Dup */
169234a49b0393204185f87664ea58f2b7a2ae1d37338cerion      assign( zKonst, binop(Iop_ShlN32x4, unop(Iop_Dup32x4, mkU32(0x1)),
169244a49b0393204185f87664ea58f2b7a2ae1d37338cerion                            mkU8(14)) );
169256f1cc0fd33c0b074bcac7901fe0dd277c73ca01ccerion
1692624d06f124e3325e8edcc1c495d15736d5adcda96cerion      assign( zLo, binop(Iop_Add32x4, mkexpr(cLo),
169276f1cc0fd33c0b074bcac7901fe0dd277c73ca01ccerion                         binop(Iop_SarN32x4,
169286f1cc0fd33c0b074bcac7901fe0dd277c73ca01ccerion                               binop(Iop_Add32x4, mkexpr(zKonst),
169291ac656a3b8eead55eeb0fb9090efec1c6719f989cerion                                     binop(Iop_MullEven16Sx8,
1693024d06f124e3325e8edcc1c495d15736d5adcda96cerion                                           mkexpr(aLo), mkexpr(bLo))),
1693124d06f124e3325e8edcc1c495d15736d5adcda96cerion                               mkU8(15))) );
169326f1cc0fd33c0b074bcac7901fe0dd277c73ca01ccerion
1693324d06f124e3325e8edcc1c495d15736d5adcda96cerion      assign( zHi, binop(Iop_Add32x4, mkexpr(cHi),
169346f1cc0fd33c0b074bcac7901fe0dd277c73ca01ccerion                         binop(Iop_SarN32x4,
169356f1cc0fd33c0b074bcac7901fe0dd277c73ca01ccerion                               binop(Iop_Add32x4, mkexpr(zKonst),
169361ac656a3b8eead55eeb0fb9090efec1c6719f989cerion                                     binop(Iop_MullEven16Sx8,
1693724d06f124e3325e8edcc1c495d15736d5adcda96cerion                                           mkexpr(aHi), mkexpr(bHi))),
1693824d06f124e3325e8edcc1c495d15736d5adcda96cerion                               mkU8(15))) );
169396f1cc0fd33c0b074bcac7901fe0dd277c73ca01ccerion
16940c9bff7dbb37ba2ee5898ef49aefaa92095ab446bsewardj      putVReg( vD_addr,
169415f438dd73072211989c6d496845bdc9b777ecbecsewardj               binop(Iop_QNarrowBin32Sto16Sx8, mkexpr(zHi), mkexpr(zLo)) );
169426f1cc0fd33c0b074bcac7901fe0dd277c73ca01ccerion      break;
169436f1cc0fd33c0b074bcac7901fe0dd277c73ca01ccerion   }
169445b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion   case 0x22: { // vmladduhm (Mult Low, Add Unsigned HW Modulo, AV p194)
169455b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion      DIP("vmladduhm v%d,v%d,v%d,v%d\n",
169465b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion          vD_addr, vA_addr, vB_addr, vC_addr);
169475b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion      assign(aLo, binop(Iop_InterleaveLO16x8, mkexpr(zeros), mkexpr(vA)));
169485b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion      assign(bLo, binop(Iop_InterleaveLO16x8, mkexpr(zeros), mkexpr(vB)));
169495b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion      assign(cLo, binop(Iop_InterleaveLO16x8, mkexpr(zeros), mkexpr(vC)));
169505b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion      assign(aHi, binop(Iop_InterleaveHI16x8, mkexpr(zeros), mkexpr(vA)));
169515b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion      assign(bHi, binop(Iop_InterleaveHI16x8, mkexpr(zeros), mkexpr(vB)));
169525b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion      assign(cHi, binop(Iop_InterleaveHI16x8, mkexpr(zeros), mkexpr(vC)));
169535b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion      assign(zLo, binop(Iop_Add32x4,
169545b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion                     binop(Iop_MullEven16Ux8, mkexpr(aLo), mkexpr(bLo)),
169555b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion                     mkexpr(cLo)) );
169565b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion      assign(zHi, binop(Iop_Add32x4,
169575b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion                     binop(Iop_MullEven16Ux8, mkexpr(aHi), mkexpr(bHi)),
169585b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion                     mkexpr(cHi)));
169595f438dd73072211989c6d496845bdc9b777ecbecsewardj      putVReg( vD_addr,
169605f438dd73072211989c6d496845bdc9b777ecbecsewardj               binop(Iop_NarrowBin32to16x8, mkexpr(zHi), mkexpr(zLo)) );
169616f1cc0fd33c0b074bcac7901fe0dd277c73ca01ccerion      break;
169626f1cc0fd33c0b074bcac7901fe0dd277c73ca01ccerion   }
1696332aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion
1696432aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion
1696532aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion   /* Multiply-Sum */
169666f1cc0fd33c0b074bcac7901fe0dd277c73ca01ccerion   case 0x24: { // vmsumubm (Multiply Sum Unsigned B Modulo, AV p204)
169674a49b0393204185f87664ea58f2b7a2ae1d37338cerion      IRTemp abEE, abEO, abOE, abOO;
169684a49b0393204185f87664ea58f2b7a2ae1d37338cerion      abEE = abEO = abOE = abOO = IRTemp_INVALID;
169695b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion      DIP("vmsumubm v%d,v%d,v%d,v%d\n",
169705b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion          vD_addr, vA_addr, vB_addr, vC_addr);
1697132aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion
169724a49b0393204185f87664ea58f2b7a2ae1d37338cerion      /* multiply vA,vB (unsigned, widening) */
1697324d06f124e3325e8edcc1c495d15736d5adcda96cerion      assign( abEvn, MK_Iop_MullOdd8Ux16( mkexpr(vA), mkexpr(vB) ));
1697424d06f124e3325e8edcc1c495d15736d5adcda96cerion      assign( abOdd, binop(Iop_MullEven8Ux16, mkexpr(vA), mkexpr(vB)) );
169754a49b0393204185f87664ea58f2b7a2ae1d37338cerion
169764a49b0393204185f87664ea58f2b7a2ae1d37338cerion      /* evn,odd: V128_16Ux8 -> 2 x V128_32Ux4, zero-extended */
169774a49b0393204185f87664ea58f2b7a2ae1d37338cerion      expand16Ux8( mkexpr(abEvn), &abEE, &abEO );
169784a49b0393204185f87664ea58f2b7a2ae1d37338cerion      expand16Ux8( mkexpr(abOdd), &abOE, &abOO );
169794a49b0393204185f87664ea58f2b7a2ae1d37338cerion
169806f1cc0fd33c0b074bcac7901fe0dd277c73ca01ccerion      putVReg( vD_addr,
169815b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion         binop(Iop_Add32x4, mkexpr(vC),
169825b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion               binop(Iop_Add32x4,
169835b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion                     binop(Iop_Add32x4, mkexpr(abEE), mkexpr(abEO)),
169845b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion                     binop(Iop_Add32x4, mkexpr(abOE), mkexpr(abOO)))) );
169856f1cc0fd33c0b074bcac7901fe0dd277c73ca01ccerion      break;
169866f1cc0fd33c0b074bcac7901fe0dd277c73ca01ccerion   }
169874a49b0393204185f87664ea58f2b7a2ae1d37338cerion   case 0x25: { // vmsummbm (Multiply Sum Mixed-Sign B Modulo, AV p201)
169884a49b0393204185f87664ea58f2b7a2ae1d37338cerion      IRTemp aEvn, aOdd, bEvn, bOdd;
169894a49b0393204185f87664ea58f2b7a2ae1d37338cerion      IRTemp abEE = newTemp(Ity_V128);
169904a49b0393204185f87664ea58f2b7a2ae1d37338cerion      IRTemp abEO = newTemp(Ity_V128);
169914a49b0393204185f87664ea58f2b7a2ae1d37338cerion      IRTemp abOE = newTemp(Ity_V128);
169924a49b0393204185f87664ea58f2b7a2ae1d37338cerion      IRTemp abOO = newTemp(Ity_V128);
169934a49b0393204185f87664ea58f2b7a2ae1d37338cerion      aEvn = aOdd = bEvn = bOdd = IRTemp_INVALID;
169945b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion      DIP("vmsummbm v%d,v%d,v%d,v%d\n",
169955b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion          vD_addr, vA_addr, vB_addr, vC_addr);
1699632aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion
169974a49b0393204185f87664ea58f2b7a2ae1d37338cerion      /* sign-extend vA, zero-extend vB, for mixed-sign multiply
169984a49b0393204185f87664ea58f2b7a2ae1d37338cerion         (separating out adjacent lanes to different vectors) */
169994a49b0393204185f87664ea58f2b7a2ae1d37338cerion      expand8Sx16( mkexpr(vA), &aEvn, &aOdd );
170004a49b0393204185f87664ea58f2b7a2ae1d37338cerion      expand8Ux16( mkexpr(vB), &bEvn, &bOdd );
170014a49b0393204185f87664ea58f2b7a2ae1d37338cerion
170024a49b0393204185f87664ea58f2b7a2ae1d37338cerion      /* multiply vA, vB, again separating adjacent lanes */
1700324d06f124e3325e8edcc1c495d15736d5adcda96cerion      assign( abEE, MK_Iop_MullOdd16Sx8( mkexpr(aEvn), mkexpr(bEvn) ));
1700424d06f124e3325e8edcc1c495d15736d5adcda96cerion      assign( abEO, binop(Iop_MullEven16Sx8, mkexpr(aEvn), mkexpr(bEvn)) );
1700524d06f124e3325e8edcc1c495d15736d5adcda96cerion      assign( abOE, MK_Iop_MullOdd16Sx8( mkexpr(aOdd), mkexpr(bOdd) ));
1700624d06f124e3325e8edcc1c495d15736d5adcda96cerion      assign( abOO, binop(Iop_MullEven16Sx8, mkexpr(aOdd), mkexpr(bOdd)) );
170074a49b0393204185f87664ea58f2b7a2ae1d37338cerion
170084a49b0393204185f87664ea58f2b7a2ae1d37338cerion      /* add results together, + vC */
170094a49b0393204185f87664ea58f2b7a2ae1d37338cerion      putVReg( vD_addr,
170105b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion         binop(Iop_QAdd32Sx4, mkexpr(vC),
170115b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion               binop(Iop_QAdd32Sx4,
170125b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion                     binop(Iop_QAdd32Sx4, mkexpr(abEE), mkexpr(abEO)),
170135b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion                     binop(Iop_QAdd32Sx4, mkexpr(abOE), mkexpr(abOO)))) );
170144a49b0393204185f87664ea58f2b7a2ae1d37338cerion      break;
170154a49b0393204185f87664ea58f2b7a2ae1d37338cerion   }
170166f1cc0fd33c0b074bcac7901fe0dd277c73ca01ccerion   case 0x26: { // vmsumuhm (Multiply Sum Unsigned HW Modulo, AV p205)
170175b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion      DIP("vmsumuhm v%d,v%d,v%d,v%d\n",
170185b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion          vD_addr, vA_addr, vB_addr, vC_addr);
1701924d06f124e3325e8edcc1c495d15736d5adcda96cerion      assign( abEvn, MK_Iop_MullOdd16Ux8( mkexpr(vA), mkexpr(vB) ));
1702024d06f124e3325e8edcc1c495d15736d5adcda96cerion      assign( abOdd, binop(Iop_MullEven16Ux8, mkexpr(vA), mkexpr(vB)) );
170216f1cc0fd33c0b074bcac7901fe0dd277c73ca01ccerion      putVReg( vD_addr,
170225b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion         binop(Iop_Add32x4, mkexpr(vC),
170235b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion               binop(Iop_Add32x4, mkexpr(abEvn), mkexpr(abOdd))) );
170246f1cc0fd33c0b074bcac7901fe0dd277c73ca01ccerion      break;
170256f1cc0fd33c0b074bcac7901fe0dd277c73ca01ccerion   }
170264a49b0393204185f87664ea58f2b7a2ae1d37338cerion   case 0x27: { // vmsumuhs (Multiply Sum Unsigned HW Saturate, AV p206)
170275b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion      DIP("vmsumuhs v%d,v%d,v%d,v%d\n",
170285b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion          vD_addr, vA_addr, vB_addr, vC_addr);
170294a49b0393204185f87664ea58f2b7a2ae1d37338cerion      /* widening multiply, separating lanes */
1703024d06f124e3325e8edcc1c495d15736d5adcda96cerion      assign( abEvn, MK_Iop_MullOdd16Ux8(mkexpr(vA), mkexpr(vB) ));
1703124d06f124e3325e8edcc1c495d15736d5adcda96cerion      assign( abOdd, binop(Iop_MullEven16Ux8, mkexpr(vA), mkexpr(vB)) );
170324a49b0393204185f87664ea58f2b7a2ae1d37338cerion
170334a49b0393204185f87664ea58f2b7a2ae1d37338cerion      /* break V128 to 4xI32's, zero-extending to I64's */
170344a49b0393204185f87664ea58f2b7a2ae1d37338cerion      breakV128to4x64U( mkexpr(abEvn), &ab7, &ab5, &ab3, &ab1 );
170354a49b0393204185f87664ea58f2b7a2ae1d37338cerion      breakV128to4x64U( mkexpr(abOdd), &ab6, &ab4, &ab2, &ab0 );
170364a49b0393204185f87664ea58f2b7a2ae1d37338cerion      breakV128to4x64U( mkexpr(vC),    &c3,  &c2,  &c1,  &c0  );
170374a49b0393204185f87664ea58f2b7a2ae1d37338cerion
170384a49b0393204185f87664ea58f2b7a2ae1d37338cerion      /* add lanes */
170394a49b0393204185f87664ea58f2b7a2ae1d37338cerion      assign( z3, binop(Iop_Add64, mkexpr(c3),
170404a49b0393204185f87664ea58f2b7a2ae1d37338cerion                        binop(Iop_Add64, mkexpr(ab7), mkexpr(ab6))));
170414a49b0393204185f87664ea58f2b7a2ae1d37338cerion      assign( z2, binop(Iop_Add64, mkexpr(c2),
170424a49b0393204185f87664ea58f2b7a2ae1d37338cerion                        binop(Iop_Add64, mkexpr(ab5), mkexpr(ab4))));
170434a49b0393204185f87664ea58f2b7a2ae1d37338cerion      assign( z1, binop(Iop_Add64, mkexpr(c1),
170444a49b0393204185f87664ea58f2b7a2ae1d37338cerion                        binop(Iop_Add64, mkexpr(ab3), mkexpr(ab2))));
170454a49b0393204185f87664ea58f2b7a2ae1d37338cerion      assign( z0, binop(Iop_Add64, mkexpr(c0),
170464a49b0393204185f87664ea58f2b7a2ae1d37338cerion                        binop(Iop_Add64, mkexpr(ab1), mkexpr(ab0))));
170474a49b0393204185f87664ea58f2b7a2ae1d37338cerion
170484a49b0393204185f87664ea58f2b7a2ae1d37338cerion      /* saturate-narrow to 32bit, and combine to V128 */
170494a49b0393204185f87664ea58f2b7a2ae1d37338cerion      putVReg( vD_addr, mkV128from4x64U( mkexpr(z3), mkexpr(z2),
170504a49b0393204185f87664ea58f2b7a2ae1d37338cerion                                         mkexpr(z1), mkexpr(z0)) );
1705132aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion
170524a49b0393204185f87664ea58f2b7a2ae1d37338cerion      break;
170534a49b0393204185f87664ea58f2b7a2ae1d37338cerion   }
170546f1cc0fd33c0b074bcac7901fe0dd277c73ca01ccerion   case 0x28: { // vmsumshm (Multiply Sum Signed HW Modulo, AV p202)
170555b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion      DIP("vmsumshm v%d,v%d,v%d,v%d\n",
170565b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion          vD_addr, vA_addr, vB_addr, vC_addr);
1705724d06f124e3325e8edcc1c495d15736d5adcda96cerion      assign( abEvn, MK_Iop_MullOdd16Sx8( mkexpr(vA), mkexpr(vB) ));
1705824d06f124e3325e8edcc1c495d15736d5adcda96cerion      assign( abOdd, binop(Iop_MullEven16Sx8, mkexpr(vA), mkexpr(vB)) );
170596f1cc0fd33c0b074bcac7901fe0dd277c73ca01ccerion      putVReg( vD_addr,
170605b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion         binop(Iop_Add32x4, mkexpr(vC),
170615b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion               binop(Iop_Add32x4, mkexpr(abOdd), mkexpr(abEvn))) );
170626f1cc0fd33c0b074bcac7901fe0dd277c73ca01ccerion      break;
170636f1cc0fd33c0b074bcac7901fe0dd277c73ca01ccerion   }
170644a49b0393204185f87664ea58f2b7a2ae1d37338cerion   case 0x29: { // vmsumshs (Multiply Sum Signed HW Saturate, AV p203)
170655b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion      DIP("vmsumshs v%d,v%d,v%d,v%d\n",
170665b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion          vD_addr, vA_addr, vB_addr, vC_addr);
170674a49b0393204185f87664ea58f2b7a2ae1d37338cerion      /* widening multiply, separating lanes */
1706824d06f124e3325e8edcc1c495d15736d5adcda96cerion      assign( abEvn, MK_Iop_MullOdd16Sx8( mkexpr(vA), mkexpr(vB) ));
1706924d06f124e3325e8edcc1c495d15736d5adcda96cerion      assign( abOdd, binop(Iop_MullEven16Sx8, mkexpr(vA), mkexpr(vB)) );
170704a49b0393204185f87664ea58f2b7a2ae1d37338cerion
170714a49b0393204185f87664ea58f2b7a2ae1d37338cerion      /* break V128 to 4xI32's, sign-extending to I64's */
170724a49b0393204185f87664ea58f2b7a2ae1d37338cerion      breakV128to4x64S( mkexpr(abEvn), &ab7, &ab5, &ab3, &ab1 );
170734a49b0393204185f87664ea58f2b7a2ae1d37338cerion      breakV128to4x64S( mkexpr(abOdd), &ab6, &ab4, &ab2, &ab0 );
170744a49b0393204185f87664ea58f2b7a2ae1d37338cerion      breakV128to4x64S( mkexpr(vC),    &c3,  &c2,  &c1,  &c0  );
170754a49b0393204185f87664ea58f2b7a2ae1d37338cerion
170764a49b0393204185f87664ea58f2b7a2ae1d37338cerion      /* add lanes */
170774a49b0393204185f87664ea58f2b7a2ae1d37338cerion      assign( z3, binop(Iop_Add64, mkexpr(c3),
170784a49b0393204185f87664ea58f2b7a2ae1d37338cerion                        binop(Iop_Add64, mkexpr(ab7), mkexpr(ab6))));
170794a49b0393204185f87664ea58f2b7a2ae1d37338cerion      assign( z2, binop(Iop_Add64, mkexpr(c2),
170804a49b0393204185f87664ea58f2b7a2ae1d37338cerion                        binop(Iop_Add64, mkexpr(ab5), mkexpr(ab4))));
170814a49b0393204185f87664ea58f2b7a2ae1d37338cerion      assign( z1, binop(Iop_Add64, mkexpr(c1),
170824a49b0393204185f87664ea58f2b7a2ae1d37338cerion                        binop(Iop_Add64, mkexpr(ab3), mkexpr(ab2))));
170834a49b0393204185f87664ea58f2b7a2ae1d37338cerion      assign( z0, binop(Iop_Add64, mkexpr(c0),
170844a49b0393204185f87664ea58f2b7a2ae1d37338cerion                        binop(Iop_Add64, mkexpr(ab1), mkexpr(ab0))));
170854a49b0393204185f87664ea58f2b7a2ae1d37338cerion
170864a49b0393204185f87664ea58f2b7a2ae1d37338cerion      /* saturate-narrow to 32bit, and combine to V128 */
170874a49b0393204185f87664ea58f2b7a2ae1d37338cerion      putVReg( vD_addr, mkV128from4x64S( mkexpr(z3), mkexpr(z2),
170884a49b0393204185f87664ea58f2b7a2ae1d37338cerion                                         mkexpr(z1), mkexpr(z0)) );
170894a49b0393204185f87664ea58f2b7a2ae1d37338cerion      break;
170904a49b0393204185f87664ea58f2b7a2ae1d37338cerion   }
1709132aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion   default:
170925b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion      vex_printf("dis_av_multarith(ppc)(opc2)\n");
1709332aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion      return False;
1709432aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion   }
1709532aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion   return True;
1709632aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion}
1709732aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion
1709832aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion/*
170997deaf9552b546b847528cf39b38898fb7742b5f5carll  AltiVec Polynomial Multiply-Sum Instructions
171007deaf9552b546b847528cf39b38898fb7742b5f5carll*/
171017deaf9552b546b847528cf39b38898fb7742b5f5carllstatic Bool dis_av_polymultarith ( UInt theInstr )
171027deaf9552b546b847528cf39b38898fb7742b5f5carll{
171037deaf9552b546b847528cf39b38898fb7742b5f5carll   /* VA-Form */
171047deaf9552b546b847528cf39b38898fb7742b5f5carll   UChar opc1     = ifieldOPC(theInstr);
171057deaf9552b546b847528cf39b38898fb7742b5f5carll   UChar vD_addr  = ifieldRegDS(theInstr);
171067deaf9552b546b847528cf39b38898fb7742b5f5carll   UChar vA_addr  = ifieldRegA(theInstr);
171077deaf9552b546b847528cf39b38898fb7742b5f5carll   UChar vB_addr  = ifieldRegB(theInstr);
171087deaf9552b546b847528cf39b38898fb7742b5f5carll   UChar vC_addr  = ifieldRegC(theInstr);
171097deaf9552b546b847528cf39b38898fb7742b5f5carll   UInt  opc2     = IFIELD(theInstr, 0, 11);
171107deaf9552b546b847528cf39b38898fb7742b5f5carll   IRTemp vA    = newTemp(Ity_V128);
171117deaf9552b546b847528cf39b38898fb7742b5f5carll   IRTemp vB    = newTemp(Ity_V128);
171127deaf9552b546b847528cf39b38898fb7742b5f5carll   IRTemp vC    = newTemp(Ity_V128);
171137deaf9552b546b847528cf39b38898fb7742b5f5carll
171147deaf9552b546b847528cf39b38898fb7742b5f5carll   assign( vA, getVReg(vA_addr));
171157deaf9552b546b847528cf39b38898fb7742b5f5carll   assign( vB, getVReg(vB_addr));
171167deaf9552b546b847528cf39b38898fb7742b5f5carll   assign( vC, getVReg(vC_addr));
171177deaf9552b546b847528cf39b38898fb7742b5f5carll
171187deaf9552b546b847528cf39b38898fb7742b5f5carll   if (opc1 != 0x4) {
171197deaf9552b546b847528cf39b38898fb7742b5f5carll      vex_printf("dis_av_polymultarith(ppc)(instr)\n");
171207deaf9552b546b847528cf39b38898fb7742b5f5carll      return False;
171217deaf9552b546b847528cf39b38898fb7742b5f5carll   }
171227deaf9552b546b847528cf39b38898fb7742b5f5carll
171237deaf9552b546b847528cf39b38898fb7742b5f5carll   switch (opc2) {
171247deaf9552b546b847528cf39b38898fb7742b5f5carll      /* Polynomial Multiply-Add */
171257deaf9552b546b847528cf39b38898fb7742b5f5carll      case 0x408:  // vpmsumb   Vector Polynomial Multipy-sum Byte
171267deaf9552b546b847528cf39b38898fb7742b5f5carll         DIP("vpmsumb v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
171277deaf9552b546b847528cf39b38898fb7742b5f5carll         putVReg( vD_addr, binop(Iop_PolynomialMulAdd8x16,
171287deaf9552b546b847528cf39b38898fb7742b5f5carll                                 mkexpr(vA), mkexpr(vB)) );
171297deaf9552b546b847528cf39b38898fb7742b5f5carll         break;
171307deaf9552b546b847528cf39b38898fb7742b5f5carll      case 0x448:  // vpmsumd   Vector Polynomial Multipy-sum Double Word
171317deaf9552b546b847528cf39b38898fb7742b5f5carll         DIP("vpmsumd v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
171327deaf9552b546b847528cf39b38898fb7742b5f5carll         putVReg( vD_addr, binop(Iop_PolynomialMulAdd64x2,
171337deaf9552b546b847528cf39b38898fb7742b5f5carll                                 mkexpr(vA), mkexpr(vB)) );
171347deaf9552b546b847528cf39b38898fb7742b5f5carll         break;
171357deaf9552b546b847528cf39b38898fb7742b5f5carll      case 0x488:  // vpmsumw   Vector Polynomial Multipy-sum Word
171367deaf9552b546b847528cf39b38898fb7742b5f5carll         DIP("vpmsumw v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
171377deaf9552b546b847528cf39b38898fb7742b5f5carll         putVReg( vD_addr, binop(Iop_PolynomialMulAdd32x4,
171387deaf9552b546b847528cf39b38898fb7742b5f5carll                                 mkexpr(vA), mkexpr(vB)) );
171397deaf9552b546b847528cf39b38898fb7742b5f5carll         break;
171407deaf9552b546b847528cf39b38898fb7742b5f5carll      case 0x4C8:  // vpmsumh   Vector Polynomial Multipy-sum Half Word
171417deaf9552b546b847528cf39b38898fb7742b5f5carll         DIP("vpmsumh v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
171427deaf9552b546b847528cf39b38898fb7742b5f5carll         putVReg( vD_addr, binop(Iop_PolynomialMulAdd16x8,
171437deaf9552b546b847528cf39b38898fb7742b5f5carll                                 mkexpr(vA), mkexpr(vB)) );
171447deaf9552b546b847528cf39b38898fb7742b5f5carll         break;
171457deaf9552b546b847528cf39b38898fb7742b5f5carll      default:
171467deaf9552b546b847528cf39b38898fb7742b5f5carll         vex_printf("dis_av_polymultarith(ppc)(opc2=0x%x)\n", opc2);
171477deaf9552b546b847528cf39b38898fb7742b5f5carll         return False;
171487deaf9552b546b847528cf39b38898fb7742b5f5carll   }
171497deaf9552b546b847528cf39b38898fb7742b5f5carll   return True;
171507deaf9552b546b847528cf39b38898fb7742b5f5carll}
171517deaf9552b546b847528cf39b38898fb7742b5f5carll
171527deaf9552b546b847528cf39b38898fb7742b5f5carll/*
1715332aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion  AltiVec Shift/Rotate Instructions
1715432aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion*/
1715532aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerionstatic Bool dis_av_shift ( UInt theInstr )
1715632aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion{
1715776de5cf615380b23b4b5bcced6541233cd4a93a0cerion   /* VX-Form */
1715876de5cf615380b23b4b5bcced6541233cd4a93a0cerion   UChar opc1    = ifieldOPC(theInstr);
1715976de5cf615380b23b4b5bcced6541233cd4a93a0cerion   UChar vD_addr = ifieldRegDS(theInstr);
1716076de5cf615380b23b4b5bcced6541233cd4a93a0cerion   UChar vA_addr = ifieldRegA(theInstr);
1716176de5cf615380b23b4b5bcced6541233cd4a93a0cerion   UChar vB_addr = ifieldRegB(theInstr);
1716276de5cf615380b23b4b5bcced6541233cd4a93a0cerion   UInt  opc2    = IFIELD( theInstr, 0, 11 );
1716332aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion
1716427b3d7ec17c3a0814d4980db87defbb4f07339bfcerion   IRTemp vA = newTemp(Ity_V128);
1716527b3d7ec17c3a0814d4980db87defbb4f07339bfcerion   IRTemp vB = newTemp(Ity_V128);
1716627b3d7ec17c3a0814d4980db87defbb4f07339bfcerion   assign( vA, getVReg(vA_addr));
1716727b3d7ec17c3a0814d4980db87defbb4f07339bfcerion   assign( vB, getVReg(vB_addr));
1716827b3d7ec17c3a0814d4980db87defbb4f07339bfcerion
1716932aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion   if (opc1 != 0x4){
171705b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion      vex_printf("dis_av_shift(ppc)(instr)\n");
1717132aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion      return False;
1717232aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion   }
1717332aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion
1717432aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion   switch (opc2) {
1717532aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion   /* Rotate */
1717632aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion   case 0x004: // vrlb (Rotate Left Integer B, AV p234)
1717732aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion      DIP("vrlb v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
171781bee561912427ca8f8998c89b62d86ba2ee49732sewardj      putVReg( vD_addr, binop(Iop_Rol8x16, mkexpr(vA), mkexpr(vB)) );
171790a7b4f40d11db65d00af3b0f51c23807dd83817fcerion      break;
1718032aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion
1718132aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion   case 0x044: // vrlh (Rotate Left Integer HW, AV p235)
1718232aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion      DIP("vrlh v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
171831bee561912427ca8f8998c89b62d86ba2ee49732sewardj      putVReg( vD_addr, binop(Iop_Rol16x8, mkexpr(vA), mkexpr(vB)) );
171840a7b4f40d11db65d00af3b0f51c23807dd83817fcerion      break;
1718532aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion
1718632aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion   case 0x084: // vrlw (Rotate Left Integer W, AV p236)
1718732aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion      DIP("vrlw v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
171881bee561912427ca8f8998c89b62d86ba2ee49732sewardj      putVReg( vD_addr, binop(Iop_Rol32x4, mkexpr(vA), mkexpr(vB)) );
171890a7b4f40d11db65d00af3b0f51c23807dd83817fcerion      break;
1719032aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion
1719148ae46b56cef87c90638b25d6b2462c475033da8carll   case 0x0C4: // vrld (Rotate Left Integer Double Word)
1719248ae46b56cef87c90638b25d6b2462c475033da8carll      DIP("vrld v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
1719348ae46b56cef87c90638b25d6b2462c475033da8carll      putVReg( vD_addr, binop(Iop_Rol64x2, mkexpr(vA), mkexpr(vB)) );
1719448ae46b56cef87c90638b25d6b2462c475033da8carll      break;
1719548ae46b56cef87c90638b25d6b2462c475033da8carll
1719632aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion
1719732aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion   /* Shift Left */
1719832aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion   case 0x104: // vslb (Shift Left Integer B, AV p240)
1719932aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion      DIP("vslb v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
172000a7b4f40d11db65d00af3b0f51c23807dd83817fcerion      putVReg( vD_addr, binop(Iop_Shl8x16, mkexpr(vA), mkexpr(vB)) );
172010a7b4f40d11db65d00af3b0f51c23807dd83817fcerion      break;
1720232aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion
1720332aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion   case 0x144: // vslh (Shift Left Integer HW, AV p242)
1720432aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion      DIP("vslh v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
172050a7b4f40d11db65d00af3b0f51c23807dd83817fcerion      putVReg( vD_addr, binop(Iop_Shl16x8, mkexpr(vA), mkexpr(vB)) );
172060a7b4f40d11db65d00af3b0f51c23807dd83817fcerion      break;
1720732aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion
1720832aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion   case 0x184: // vslw (Shift Left Integer W, AV p244)
1720932aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion      DIP("vslw v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
172100a7b4f40d11db65d00af3b0f51c23807dd83817fcerion      putVReg( vD_addr, binop(Iop_Shl32x4, mkexpr(vA), mkexpr(vB)) );
172110a7b4f40d11db65d00af3b0f51c23807dd83817fcerion      break;
1721232aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion
1721348ae46b56cef87c90638b25d6b2462c475033da8carll   case 0x5C4: // vsld (Shift Left Integer Double Word)
1721448ae46b56cef87c90638b25d6b2462c475033da8carll      DIP("vsld v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
1721548ae46b56cef87c90638b25d6b2462c475033da8carll      putVReg( vD_addr, binop(Iop_Shl64x2, mkexpr(vA), mkexpr(vB)) );
1721648ae46b56cef87c90638b25d6b2462c475033da8carll      break;
1721748ae46b56cef87c90638b25d6b2462c475033da8carll
172180a7b4f40d11db65d00af3b0f51c23807dd83817fcerion   case 0x1C4: { // vsl (Shift Left, AV p239)
172190a7b4f40d11db65d00af3b0f51c23807dd83817fcerion      IRTemp sh = newTemp(Ity_I8);
17220197bd17d3ba8ac5204cd5c9ba5fab571249eb791sewardj      DIP("vsl v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
172210a7b4f40d11db65d00af3b0f51c23807dd83817fcerion      assign( sh, binop(Iop_And8, mkU8(0x7),
172220a7b4f40d11db65d00af3b0f51c23807dd83817fcerion                        unop(Iop_32to8,
172230a7b4f40d11db65d00af3b0f51c23807dd83817fcerion                             unop(Iop_V128to32, mkexpr(vB)))) );
172240a7b4f40d11db65d00af3b0f51c23807dd83817fcerion      putVReg( vD_addr,
172250a7b4f40d11db65d00af3b0f51c23807dd83817fcerion               binop(Iop_ShlV128, mkexpr(vA), mkexpr(sh)) );
172260a7b4f40d11db65d00af3b0f51c23807dd83817fcerion      break;
172270a7b4f40d11db65d00af3b0f51c23807dd83817fcerion   }
172280a7b4f40d11db65d00af3b0f51c23807dd83817fcerion   case 0x40C: { // vslo (Shift Left by Octet, AV p243)
172290a7b4f40d11db65d00af3b0f51c23807dd83817fcerion      IRTemp sh = newTemp(Ity_I8);
17230197bd17d3ba8ac5204cd5c9ba5fab571249eb791sewardj      DIP("vslo v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
172310a7b4f40d11db65d00af3b0f51c23807dd83817fcerion      assign( sh, binop(Iop_And8, mkU8(0x78),
172320a7b4f40d11db65d00af3b0f51c23807dd83817fcerion                        unop(Iop_32to8,
172330a7b4f40d11db65d00af3b0f51c23807dd83817fcerion                             unop(Iop_V128to32, mkexpr(vB)))) );
172340a7b4f40d11db65d00af3b0f51c23807dd83817fcerion      putVReg( vD_addr,
172350a7b4f40d11db65d00af3b0f51c23807dd83817fcerion               binop(Iop_ShlV128, mkexpr(vA), mkexpr(sh)) );
172360a7b4f40d11db65d00af3b0f51c23807dd83817fcerion      break;
172370a7b4f40d11db65d00af3b0f51c23807dd83817fcerion   }
172380a7b4f40d11db65d00af3b0f51c23807dd83817fcerion
1723932aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion
1724032aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion   /* Shift Right */
1724132aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion   case 0x204: // vsrb (Shift Right B, AV p256)
1724232aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion      DIP("vsrb v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
172430a7b4f40d11db65d00af3b0f51c23807dd83817fcerion      putVReg( vD_addr, binop(Iop_Shr8x16, mkexpr(vA), mkexpr(vB)) );
172440a7b4f40d11db65d00af3b0f51c23807dd83817fcerion      break;
1724532aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion
1724632aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion   case 0x244: // vsrh (Shift Right HW, AV p257)
1724732aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion      DIP("vsrh v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
172480a7b4f40d11db65d00af3b0f51c23807dd83817fcerion      putVReg( vD_addr, binop(Iop_Shr16x8, mkexpr(vA), mkexpr(vB)) );
172490a7b4f40d11db65d00af3b0f51c23807dd83817fcerion      break;
1725032aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion
1725132aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion   case 0x284: // vsrw (Shift Right W, AV p259)
1725232aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion      DIP("vsrw v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
172530a7b4f40d11db65d00af3b0f51c23807dd83817fcerion      putVReg( vD_addr, binop(Iop_Shr32x4, mkexpr(vA), mkexpr(vB)) );
172540a7b4f40d11db65d00af3b0f51c23807dd83817fcerion      break;
1725532aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion
1725627b3d7ec17c3a0814d4980db87defbb4f07339bfcerion   case 0x2C4: { // vsr (Shift Right, AV p251)
1725727b3d7ec17c3a0814d4980db87defbb4f07339bfcerion      IRTemp sh = newTemp(Ity_I8);
17258197bd17d3ba8ac5204cd5c9ba5fab571249eb791sewardj      DIP("vsr v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
1725927b3d7ec17c3a0814d4980db87defbb4f07339bfcerion      assign( sh, binop(Iop_And8, mkU8(0x7),
1726027b3d7ec17c3a0814d4980db87defbb4f07339bfcerion                        unop(Iop_32to8,
1726127b3d7ec17c3a0814d4980db87defbb4f07339bfcerion                             unop(Iop_V128to32, mkexpr(vB)))) );
1726227b3d7ec17c3a0814d4980db87defbb4f07339bfcerion      putVReg( vD_addr,
1726327b3d7ec17c3a0814d4980db87defbb4f07339bfcerion               binop(Iop_ShrV128, mkexpr(vA), mkexpr(sh)) );
1726427b3d7ec17c3a0814d4980db87defbb4f07339bfcerion      break;
1726527b3d7ec17c3a0814d4980db87defbb4f07339bfcerion   }
172665b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion   case 0x304: // vsrab (Shift Right Alg B, AV p253)
1726732aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion      DIP("vsrab v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
172680a7b4f40d11db65d00af3b0f51c23807dd83817fcerion      putVReg( vD_addr, binop(Iop_Sar8x16, mkexpr(vA), mkexpr(vB)) );
172690a7b4f40d11db65d00af3b0f51c23807dd83817fcerion      break;
1727032aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion
172715b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion   case 0x344: // vsrah (Shift Right Alg HW, AV p254)
1727232aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion      DIP("vsrah v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
172730a7b4f40d11db65d00af3b0f51c23807dd83817fcerion      putVReg( vD_addr, binop(Iop_Sar16x8, mkexpr(vA), mkexpr(vB)) );
172740a7b4f40d11db65d00af3b0f51c23807dd83817fcerion      break;
1727532aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion
172765b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion   case 0x384: // vsraw (Shift Right Alg W, AV p255)
1727732aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion      DIP("vsraw v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
172780a7b4f40d11db65d00af3b0f51c23807dd83817fcerion      putVReg( vD_addr, binop(Iop_Sar32x4, mkexpr(vA), mkexpr(vB)) );
172790a7b4f40d11db65d00af3b0f51c23807dd83817fcerion      break;
1728032aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion
1728148ae46b56cef87c90638b25d6b2462c475033da8carll   case 0x3C4: // vsrad (Shift Right Alg Double Word)
1728248ae46b56cef87c90638b25d6b2462c475033da8carll      DIP("vsrad v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
1728348ae46b56cef87c90638b25d6b2462c475033da8carll      putVReg( vD_addr, binop(Iop_Sar64x2, mkexpr(vA), mkexpr(vB)) );
1728448ae46b56cef87c90638b25d6b2462c475033da8carll      break;
1728548ae46b56cef87c90638b25d6b2462c475033da8carll
172860a7b4f40d11db65d00af3b0f51c23807dd83817fcerion   case 0x44C: { // vsro (Shift Right by Octet, AV p258)
172870a7b4f40d11db65d00af3b0f51c23807dd83817fcerion      IRTemp sh = newTemp(Ity_I8);
17288197bd17d3ba8ac5204cd5c9ba5fab571249eb791sewardj      DIP("vsro v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
172890a7b4f40d11db65d00af3b0f51c23807dd83817fcerion      assign( sh, binop(Iop_And8, mkU8(0x78),
172900a7b4f40d11db65d00af3b0f51c23807dd83817fcerion                        unop(Iop_32to8,
172910a7b4f40d11db65d00af3b0f51c23807dd83817fcerion                             unop(Iop_V128to32, mkexpr(vB)))) );
172920a7b4f40d11db65d00af3b0f51c23807dd83817fcerion      putVReg( vD_addr,
172930a7b4f40d11db65d00af3b0f51c23807dd83817fcerion               binop(Iop_ShrV128, mkexpr(vA), mkexpr(sh)) );
172940a7b4f40d11db65d00af3b0f51c23807dd83817fcerion      break;
172950a7b4f40d11db65d00af3b0f51c23807dd83817fcerion   }
1729632aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion
1729748ae46b56cef87c90638b25d6b2462c475033da8carll   case 0x6C4: // vsrd (Shift Right Double Word)
1729848ae46b56cef87c90638b25d6b2462c475033da8carll      DIP("vsrd v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
1729948ae46b56cef87c90638b25d6b2462c475033da8carll      putVReg( vD_addr, binop(Iop_Shr64x2, mkexpr(vA), mkexpr(vB)) );
1730048ae46b56cef87c90638b25d6b2462c475033da8carll      break;
1730148ae46b56cef87c90638b25d6b2462c475033da8carll
1730248ae46b56cef87c90638b25d6b2462c475033da8carll
1730332aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion   default:
173045b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion      vex_printf("dis_av_shift(ppc)(opc2)\n");
1730532aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion      return False;
1730632aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion   }
1730732aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion   return True;
1730832aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion}
1730932aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion
1731032aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion/*
1731132aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion  AltiVec Permute Instructions
1731232aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion*/
1731332aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerionstatic Bool dis_av_permute ( UInt theInstr )
1731432aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion{
1731576de5cf615380b23b4b5bcced6541233cd4a93a0cerion   /* VA-Form, VX-Form */
1731676de5cf615380b23b4b5bcced6541233cd4a93a0cerion   UChar opc1      = ifieldOPC(theInstr);
1731776de5cf615380b23b4b5bcced6541233cd4a93a0cerion   UChar vD_addr   = ifieldRegDS(theInstr);
1731876de5cf615380b23b4b5bcced6541233cd4a93a0cerion   UChar vA_addr   = ifieldRegA(theInstr);
1731976de5cf615380b23b4b5bcced6541233cd4a93a0cerion   UChar UIMM_5    = vA_addr;
1732076de5cf615380b23b4b5bcced6541233cd4a93a0cerion   UChar vB_addr   = ifieldRegB(theInstr);
1732176de5cf615380b23b4b5bcced6541233cd4a93a0cerion   UChar vC_addr   = ifieldRegC(theInstr);
1732276de5cf615380b23b4b5bcced6541233cd4a93a0cerion   UChar b10       = ifieldBIT10(theInstr);
1732376de5cf615380b23b4b5bcced6541233cd4a93a0cerion   UChar SHB_uimm4 = toUChar( IFIELD( theInstr, 6, 4 ) );
1732476de5cf615380b23b4b5bcced6541233cd4a93a0cerion   UInt  opc2      = toUChar( IFIELD( theInstr, 0, 6 ) );
1732576de5cf615380b23b4b5bcced6541233cd4a93a0cerion
1732676de5cf615380b23b4b5bcced6541233cd4a93a0cerion   UChar SIMM_8 = extend_s_5to8(UIMM_5);
1732732aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion
173286e7a0ea9abe4e6443ebfc451d5681250eece75fdcerion   IRTemp vA = newTemp(Ity_V128);
173296e7a0ea9abe4e6443ebfc451d5681250eece75fdcerion   IRTemp vB = newTemp(Ity_V128);
173306e7a0ea9abe4e6443ebfc451d5681250eece75fdcerion   IRTemp vC = newTemp(Ity_V128);
173316e7a0ea9abe4e6443ebfc451d5681250eece75fdcerion   assign( vA, getVReg(vA_addr));
173326e7a0ea9abe4e6443ebfc451d5681250eece75fdcerion   assign( vB, getVReg(vB_addr));
173336e7a0ea9abe4e6443ebfc451d5681250eece75fdcerion   assign( vC, getVReg(vC_addr));
173346e7a0ea9abe4e6443ebfc451d5681250eece75fdcerion
1733532aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion   if (opc1 != 0x4) {
173365b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion      vex_printf("dis_av_permute(ppc)(instr)\n");
1733732aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion      return False;
1733832aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion   }
1733932aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion
1734032aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion   switch (opc2) {
1734132aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion   case 0x2A: // vsel (Conditional Select, AV p238)
1734232aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion      DIP("vsel v%d,v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr, vC_addr);
173436e7a0ea9abe4e6443ebfc451d5681250eece75fdcerion      /* vD = (vA & ~vC) | (vB & vC) */
173446e7a0ea9abe4e6443ebfc451d5681250eece75fdcerion      putVReg( vD_addr, binop(Iop_OrV128,
173456e7a0ea9abe4e6443ebfc451d5681250eece75fdcerion         binop(Iop_AndV128, mkexpr(vA), unop(Iop_NotV128, mkexpr(vC))),
173466e7a0ea9abe4e6443ebfc451d5681250eece75fdcerion         binop(Iop_AndV128, mkexpr(vB), mkexpr(vC))) );
173476e7a0ea9abe4e6443ebfc451d5681250eece75fdcerion      return True;
1734832aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion
1734992d9d876af80d14fa2f319f7109964f2d6231f15cerion   case 0x2B: { // vperm (Permute, AV p218)
1735092d9d876af80d14fa2f319f7109964f2d6231f15cerion      /* limited to two args for IR, so have to play games... */
17351dc1f91317b466ccabbe21bf0feda19658d5b614bsewardj      IRTemp a_perm  = newTemp(Ity_V128);
17352dc1f91317b466ccabbe21bf0feda19658d5b614bsewardj      IRTemp b_perm  = newTemp(Ity_V128);
17353dc1f91317b466ccabbe21bf0feda19658d5b614bsewardj      IRTemp mask    = newTemp(Ity_V128);
17354dc1f91317b466ccabbe21bf0feda19658d5b614bsewardj      IRTemp vC_andF = newTemp(Ity_V128);
173555b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion      DIP("vperm v%d,v%d,v%d,v%d\n",
173565b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion          vD_addr, vA_addr, vB_addr, vC_addr);
17357dc1f91317b466ccabbe21bf0feda19658d5b614bsewardj      /* Limit the Perm8x16 steering values to 0 .. 15 as that is what
17358dc1f91317b466ccabbe21bf0feda19658d5b614bsewardj         IR specifies, and also to hide irrelevant bits from
17359dc1f91317b466ccabbe21bf0feda19658d5b614bsewardj         memcheck */
173605b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion      assign( vC_andF,
173615b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion              binop(Iop_AndV128, mkexpr(vC),
173625b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion                                 unop(Iop_Dup8x16, mkU8(0xF))) );
173635b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion      assign( a_perm,
173645b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion              binop(Iop_Perm8x16, mkexpr(vA), mkexpr(vC_andF)) );
173655b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion      assign( b_perm,
173665b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion              binop(Iop_Perm8x16, mkexpr(vB), mkexpr(vC_andF)) );
1736792d9d876af80d14fa2f319f7109964f2d6231f15cerion      // mask[i8] = (vC[i8]_4 == 1) ? 0xFF : 0x0
1736892d9d876af80d14fa2f319f7109964f2d6231f15cerion      assign( mask, binop(Iop_SarN8x16,
1736992d9d876af80d14fa2f319f7109964f2d6231f15cerion                          binop(Iop_ShlN8x16, mkexpr(vC), mkU8(3)),
1737092d9d876af80d14fa2f319f7109964f2d6231f15cerion                          mkU8(7)) );
1737192d9d876af80d14fa2f319f7109964f2d6231f15cerion      // dst = (a & ~mask) | (b & mask)
1737292d9d876af80d14fa2f319f7109964f2d6231f15cerion      putVReg( vD_addr, binop(Iop_OrV128,
1737392d9d876af80d14fa2f319f7109964f2d6231f15cerion                              binop(Iop_AndV128, mkexpr(a_perm),
1737492d9d876af80d14fa2f319f7109964f2d6231f15cerion                                    unop(Iop_NotV128, mkexpr(mask))),
1737592d9d876af80d14fa2f319f7109964f2d6231f15cerion                              binop(Iop_AndV128, mkexpr(b_perm),
1737692d9d876af80d14fa2f319f7109964f2d6231f15cerion                                    mkexpr(mask))) );
1737792d9d876af80d14fa2f319f7109964f2d6231f15cerion      return True;
1737892d9d876af80d14fa2f319f7109964f2d6231f15cerion   }
1737932aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion   case 0x2C: // vsldoi (Shift Left Double by Octet Imm, AV p241)
1738032aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion      if (b10 != 0) {
173815b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion         vex_printf("dis_av_permute(ppc)(vsldoi)\n");
1738232aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion         return False;
1738332aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion      }
173845b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion      DIP("vsldoi v%d,v%d,v%d,%d\n",
173855b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion          vD_addr, vA_addr, vB_addr, SHB_uimm4);
1738692d9d876af80d14fa2f319f7109964f2d6231f15cerion      if (SHB_uimm4 == 0)
1738792d9d876af80d14fa2f319f7109964f2d6231f15cerion         putVReg( vD_addr, mkexpr(vA) );
1738892d9d876af80d14fa2f319f7109964f2d6231f15cerion      else
1738992d9d876af80d14fa2f319f7109964f2d6231f15cerion         putVReg( vD_addr,
173905b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion            binop(Iop_OrV128,
173915b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion                  binop(Iop_ShlV128, mkexpr(vA), mkU8(SHB_uimm4*8)),
173925b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion                  binop(Iop_ShrV128, mkexpr(vB), mkU8((16-SHB_uimm4)*8))) );
1739392d9d876af80d14fa2f319f7109964f2d6231f15cerion      return True;
173947deaf9552b546b847528cf39b38898fb7742b5f5carll   case 0x2D: {  // vpermxor (Vector Permute and Exclusive-OR)
173957deaf9552b546b847528cf39b38898fb7742b5f5carll      IRTemp a_perm  = newTemp(Ity_V128);
173967deaf9552b546b847528cf39b38898fb7742b5f5carll      IRTemp b_perm  = newTemp(Ity_V128);
173977deaf9552b546b847528cf39b38898fb7742b5f5carll      IRTemp vrc_a   = newTemp(Ity_V128);
173987deaf9552b546b847528cf39b38898fb7742b5f5carll      IRTemp vrc_b   = newTemp(Ity_V128);
173997deaf9552b546b847528cf39b38898fb7742b5f5carll
174007deaf9552b546b847528cf39b38898fb7742b5f5carll      /* IBM index  is 0:7, Change index value to index 7:0 */
174017deaf9552b546b847528cf39b38898fb7742b5f5carll      assign( vrc_b, binop( Iop_AndV128, mkexpr( vC ),
174027deaf9552b546b847528cf39b38898fb7742b5f5carll                            unop( Iop_Dup8x16, mkU8( 0xF ) ) ) );
174037deaf9552b546b847528cf39b38898fb7742b5f5carll      assign( vrc_a, binop( Iop_ShrV128,
174047deaf9552b546b847528cf39b38898fb7742b5f5carll                            binop( Iop_AndV128, mkexpr( vC ),
174057deaf9552b546b847528cf39b38898fb7742b5f5carll                                   unop( Iop_Dup8x16, mkU8( 0xF0 ) ) ),
174067deaf9552b546b847528cf39b38898fb7742b5f5carll                            mkU8 ( 4 ) ) );
174077deaf9552b546b847528cf39b38898fb7742b5f5carll      assign( a_perm, binop( Iop_Perm8x16, mkexpr( vA ), mkexpr( vrc_a ) ) );
174087deaf9552b546b847528cf39b38898fb7742b5f5carll      assign( b_perm, binop( Iop_Perm8x16, mkexpr( vB ), mkexpr( vrc_b ) ) );
174097deaf9552b546b847528cf39b38898fb7742b5f5carll      putVReg( vD_addr, binop( Iop_XorV128,
174107deaf9552b546b847528cf39b38898fb7742b5f5carll                               mkexpr( a_perm ), mkexpr( b_perm) ) );
174117deaf9552b546b847528cf39b38898fb7742b5f5carll      return True;
174127deaf9552b546b847528cf39b38898fb7742b5f5carll   }
1741332aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion   default:
1741432aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion     break; // Fall through...
1741532aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion   }
1741632aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion
1741776de5cf615380b23b4b5bcced6541233cd4a93a0cerion   opc2 = IFIELD( theInstr, 0, 11 );
1741832aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion   switch (opc2) {
1741932aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion
1742032aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion   /* Merge */
1742132aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion   case 0x00C: // vmrghb (Merge High B, AV p195)
1742232aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion      DIP("vmrghb v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
1742392d9d876af80d14fa2f319f7109964f2d6231f15cerion      putVReg( vD_addr,
1742492d9d876af80d14fa2f319f7109964f2d6231f15cerion               binop(Iop_InterleaveHI8x16, mkexpr(vA), mkexpr(vB)) );
1742592d9d876af80d14fa2f319f7109964f2d6231f15cerion      break;
1742632aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion
1742732aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion   case 0x04C: // vmrghh (Merge High HW, AV p196)
1742832aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion      DIP("vmrghh v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
1742992d9d876af80d14fa2f319f7109964f2d6231f15cerion      putVReg( vD_addr,
1743092d9d876af80d14fa2f319f7109964f2d6231f15cerion               binop(Iop_InterleaveHI16x8, mkexpr(vA), mkexpr(vB)) );
1743192d9d876af80d14fa2f319f7109964f2d6231f15cerion      break;
1743232aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion
1743332aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion   case 0x08C: // vmrghw (Merge High W, AV p197)
1743432aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion      DIP("vmrghw v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
1743592d9d876af80d14fa2f319f7109964f2d6231f15cerion      putVReg( vD_addr,
1743692d9d876af80d14fa2f319f7109964f2d6231f15cerion               binop(Iop_InterleaveHI32x4, mkexpr(vA), mkexpr(vB)) );
1743792d9d876af80d14fa2f319f7109964f2d6231f15cerion      break;
1743832aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion
1743932aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion   case 0x10C: // vmrglb (Merge Low B, AV p198)
1744032aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion      DIP("vmrglb v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
1744192d9d876af80d14fa2f319f7109964f2d6231f15cerion      putVReg( vD_addr,
1744292d9d876af80d14fa2f319f7109964f2d6231f15cerion               binop(Iop_InterleaveLO8x16, mkexpr(vA), mkexpr(vB)) );
1744392d9d876af80d14fa2f319f7109964f2d6231f15cerion      break;
1744432aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion
1744532aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion   case 0x14C: // vmrglh (Merge Low HW, AV p199)
1744632aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion      DIP("vmrglh v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
1744792d9d876af80d14fa2f319f7109964f2d6231f15cerion      putVReg( vD_addr,
1744892d9d876af80d14fa2f319f7109964f2d6231f15cerion               binop(Iop_InterleaveLO16x8, mkexpr(vA), mkexpr(vB)) );
1744992d9d876af80d14fa2f319f7109964f2d6231f15cerion      break;
1745032aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion
1745132aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion   case 0x18C: // vmrglw (Merge Low W, AV p200)
1745232aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion      DIP("vmrglw v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
1745392d9d876af80d14fa2f319f7109964f2d6231f15cerion      putVReg( vD_addr,
1745492d9d876af80d14fa2f319f7109964f2d6231f15cerion               binop(Iop_InterleaveLO32x4, mkexpr(vA), mkexpr(vB)) );
1745592d9d876af80d14fa2f319f7109964f2d6231f15cerion      break;
1745692d9d876af80d14fa2f319f7109964f2d6231f15cerion
1745732aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion
1745832aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion   /* Splat */
1745992d9d876af80d14fa2f319f7109964f2d6231f15cerion   case 0x20C: { // vspltb (Splat Byte, AV p245)
1746092d9d876af80d14fa2f319f7109964f2d6231f15cerion      /* vD = Dup8x16( vB[UIMM_5] ) */
17461d14709407df9363767aa888b03f95f08df169dcesewardj      UChar sh_uimm = (15 - (UIMM_5 & 15)) * 8;
17462197bd17d3ba8ac5204cd5c9ba5fab571249eb791sewardj      DIP("vspltb v%d,v%d,%d\n", vD_addr, vB_addr, UIMM_5);
1746392d9d876af80d14fa2f319f7109964f2d6231f15cerion      putVReg( vD_addr, unop(Iop_Dup8x16,
1746492d9d876af80d14fa2f319f7109964f2d6231f15cerion           unop(Iop_32to8, unop(Iop_V128to32,
1746592d9d876af80d14fa2f319f7109964f2d6231f15cerion                binop(Iop_ShrV128, mkexpr(vB), mkU8(sh_uimm))))) );
1746692d9d876af80d14fa2f319f7109964f2d6231f15cerion      break;
1746792d9d876af80d14fa2f319f7109964f2d6231f15cerion   }
1746892d9d876af80d14fa2f319f7109964f2d6231f15cerion   case 0x24C: { // vsplth (Splat Half Word, AV p246)
17469d14709407df9363767aa888b03f95f08df169dcesewardj      UChar sh_uimm = (7 - (UIMM_5 & 7)) * 16;
17470197bd17d3ba8ac5204cd5c9ba5fab571249eb791sewardj      DIP("vsplth v%d,v%d,%d\n", vD_addr, vB_addr, UIMM_5);
1747192d9d876af80d14fa2f319f7109964f2d6231f15cerion      putVReg( vD_addr, unop(Iop_Dup16x8,
1747292d9d876af80d14fa2f319f7109964f2d6231f15cerion           unop(Iop_32to16, unop(Iop_V128to32,
1747392d9d876af80d14fa2f319f7109964f2d6231f15cerion                binop(Iop_ShrV128, mkexpr(vB), mkU8(sh_uimm))))) );
1747492d9d876af80d14fa2f319f7109964f2d6231f15cerion      break;
1747592d9d876af80d14fa2f319f7109964f2d6231f15cerion   }
1747627b3d7ec17c3a0814d4980db87defbb4f07339bfcerion   case 0x28C: { // vspltw (Splat Word, AV p250)
1747727b3d7ec17c3a0814d4980db87defbb4f07339bfcerion      /* vD = Dup32x4( vB[UIMM_5] ) */
17478d14709407df9363767aa888b03f95f08df169dcesewardj      UChar sh_uimm = (3 - (UIMM_5 & 3)) * 32;
17479197bd17d3ba8ac5204cd5c9ba5fab571249eb791sewardj      DIP("vspltw v%d,v%d,%d\n", vD_addr, vB_addr, UIMM_5);
1748027b3d7ec17c3a0814d4980db87defbb4f07339bfcerion      putVReg( vD_addr, unop(Iop_Dup32x4,
1748127b3d7ec17c3a0814d4980db87defbb4f07339bfcerion         unop(Iop_V128to32,
1748227b3d7ec17c3a0814d4980db87defbb4f07339bfcerion              binop(Iop_ShrV128, mkexpr(vB), mkU8(sh_uimm)))) );
1748327b3d7ec17c3a0814d4980db87defbb4f07339bfcerion      break;
1748427b3d7ec17c3a0814d4980db87defbb4f07339bfcerion   }
1748532aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion   case 0x30C: // vspltisb (Splat Immediate Signed B, AV p247)
1748632aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion      DIP("vspltisb v%d,%d\n", vD_addr, (Char)SIMM_8);
1748792d9d876af80d14fa2f319f7109964f2d6231f15cerion      putVReg( vD_addr, unop(Iop_Dup8x16, mkU8(SIMM_8)) );
1748892d9d876af80d14fa2f319f7109964f2d6231f15cerion      break;
1748932aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion
1749032aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion   case 0x34C: // vspltish (Splat Immediate Signed HW, AV p248)
1749132aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion      DIP("vspltish v%d,%d\n", vD_addr, (Char)SIMM_8);
174925b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion      putVReg( vD_addr,
174935b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion               unop(Iop_Dup16x8, mkU16(extend_s_8to32(SIMM_8))) );
1749492d9d876af80d14fa2f319f7109964f2d6231f15cerion      break;
1749532aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion
1749632aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion   case 0x38C: // vspltisw (Splat Immediate Signed W, AV p249)
1749732aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion      DIP("vspltisw v%d,%d\n", vD_addr, (Char)SIMM_8);
174985b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion      putVReg( vD_addr,
174995b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion               unop(Iop_Dup32x4, mkU32(extend_s_8to32(SIMM_8))) );
1750092d9d876af80d14fa2f319f7109964f2d6231f15cerion      break;
1750132aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion
1750248ae46b56cef87c90638b25d6b2462c475033da8carll   case 0x68C: // vmrgow (Merge Odd Word)
1750348ae46b56cef87c90638b25d6b2462c475033da8carll     DIP("vmrgow v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
1750448ae46b56cef87c90638b25d6b2462c475033da8carll      /*   VD[0] <- VA[1]
1750548ae46b56cef87c90638b25d6b2462c475033da8carll           VD[1] <- VB[1]
1750648ae46b56cef87c90638b25d6b2462c475033da8carll           VD[2] <- VA[3]
1750748ae46b56cef87c90638b25d6b2462c475033da8carll           VD[3] <- VB[3]
1750848ae46b56cef87c90638b25d6b2462c475033da8carll      */
1750948ae46b56cef87c90638b25d6b2462c475033da8carll      putVReg( vD_addr,
1751048ae46b56cef87c90638b25d6b2462c475033da8carll               binop(Iop_CatOddLanes32x4, mkexpr(vA), mkexpr(vB) ) );
1751148ae46b56cef87c90638b25d6b2462c475033da8carll      break;
1751248ae46b56cef87c90638b25d6b2462c475033da8carll
1751348ae46b56cef87c90638b25d6b2462c475033da8carll   case 0x78C: // vmrgew (Merge Even Word)
1751448ae46b56cef87c90638b25d6b2462c475033da8carll      DIP("vmrgew v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
1751548ae46b56cef87c90638b25d6b2462c475033da8carll      /*   VD[0] <- VA[0]
1751648ae46b56cef87c90638b25d6b2462c475033da8carll           VD[1] <- VB[0]
1751748ae46b56cef87c90638b25d6b2462c475033da8carll           VD[2] <- VA[2]
1751848ae46b56cef87c90638b25d6b2462c475033da8carll           VD[3] <- VB[2]
1751948ae46b56cef87c90638b25d6b2462c475033da8carll      */
1752048ae46b56cef87c90638b25d6b2462c475033da8carll      putVReg( vD_addr,
1752148ae46b56cef87c90638b25d6b2462c475033da8carll               binop(Iop_CatEvenLanes32x4, mkexpr(vA), mkexpr(vB) ) );
1752248ae46b56cef87c90638b25d6b2462c475033da8carll      break;
1752348ae46b56cef87c90638b25d6b2462c475033da8carll
1752432aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion   default:
175255b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion      vex_printf("dis_av_permute(ppc)(opc2)\n");
1752632aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion      return False;
1752732aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion   }
1752832aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion   return True;
1752932aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion}
1753032aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion
1753132aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion/*
1753232aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion  AltiVec Pack/Unpack Instructions
1753332aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion*/
1753432aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerionstatic Bool dis_av_pack ( UInt theInstr )
1753532aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion{
1753676de5cf615380b23b4b5bcced6541233cd4a93a0cerion   /* VX-Form */
1753776de5cf615380b23b4b5bcced6541233cd4a93a0cerion   UChar opc1     = ifieldOPC(theInstr);
1753876de5cf615380b23b4b5bcced6541233cd4a93a0cerion   UChar vD_addr  = ifieldRegDS(theInstr);
1753976de5cf615380b23b4b5bcced6541233cd4a93a0cerion   UChar vA_addr  = ifieldRegA(theInstr);
1754076de5cf615380b23b4b5bcced6541233cd4a93a0cerion   UChar vB_addr  = ifieldRegB(theInstr);
1754176de5cf615380b23b4b5bcced6541233cd4a93a0cerion   UInt  opc2     = IFIELD( theInstr, 0, 11 );
1754232aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion
17543197bd17d3ba8ac5204cd5c9ba5fab571249eb791sewardj   IRTemp signs = IRTemp_INVALID;
17544197bd17d3ba8ac5204cd5c9ba5fab571249eb791sewardj   IRTemp zeros = IRTemp_INVALID;
1754576de5cf615380b23b4b5bcced6541233cd4a93a0cerion   IRTemp vA    = newTemp(Ity_V128);
1754676de5cf615380b23b4b5bcced6541233cd4a93a0cerion   IRTemp vB    = newTemp(Ity_V128);
175473c052793dacedf702ca4b6ccbfb46a7efa7bc714cerion   assign( vA, getVReg(vA_addr));
175483c052793dacedf702ca4b6ccbfb46a7efa7bc714cerion   assign( vB, getVReg(vB_addr));
175493c052793dacedf702ca4b6ccbfb46a7efa7bc714cerion
1755032aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion   if (opc1 != 0x4) {
175515b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion      vex_printf("dis_av_pack(ppc)(instr)\n");
1755232aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion      return False;
1755332aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion   }
1755432aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion   switch (opc2) {
1755532aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion   /* Packing */
1755632aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion   case 0x00E: // vpkuhum (Pack Unsigned HW Unsigned Modulo, AV p224)
1755732aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion      DIP("vpkuhum v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
175585f438dd73072211989c6d496845bdc9b777ecbecsewardj      putVReg( vD_addr,
175595f438dd73072211989c6d496845bdc9b777ecbecsewardj               binop(Iop_NarrowBin16to8x16, mkexpr(vA), mkexpr(vB)) );
175603c052793dacedf702ca4b6ccbfb46a7efa7bc714cerion      return True;
1756132aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion
1756232aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion   case 0x04E: // vpkuwum (Pack Unsigned W Unsigned Modulo, AV p226)
1756332aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion      DIP("vpkuwum v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
175645f438dd73072211989c6d496845bdc9b777ecbecsewardj      putVReg( vD_addr,
175655f438dd73072211989c6d496845bdc9b777ecbecsewardj               binop(Iop_NarrowBin32to16x8, mkexpr(vA), mkexpr(vB)) );
175663c052793dacedf702ca4b6ccbfb46a7efa7bc714cerion      return True;
1756732aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion
1756832aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion   case 0x08E: // vpkuhus (Pack Unsigned HW Unsigned Saturate, AV p225)
1756932aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion      DIP("vpkuhus v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
175705b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion      putVReg( vD_addr,
175715f438dd73072211989c6d496845bdc9b777ecbecsewardj               binop(Iop_QNarrowBin16Uto8Ux16, mkexpr(vA), mkexpr(vB)) );
175723c052793dacedf702ca4b6ccbfb46a7efa7bc714cerion      // TODO: set VSCR[SAT]
175733c052793dacedf702ca4b6ccbfb46a7efa7bc714cerion      return True;
1757432aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion
1757532aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion   case 0x0CE: // vpkuwus (Pack Unsigned W Unsigned Saturate, AV p227)
1757632aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion      DIP("vpkuwus v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
175775b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion      putVReg( vD_addr,
175785f438dd73072211989c6d496845bdc9b777ecbecsewardj               binop(Iop_QNarrowBin32Uto16Ux8, mkexpr(vA), mkexpr(vB)) );
175793c052793dacedf702ca4b6ccbfb46a7efa7bc714cerion      // TODO: set VSCR[SAT]
175803c052793dacedf702ca4b6ccbfb46a7efa7bc714cerion      return True;
1758132aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion
175823c052793dacedf702ca4b6ccbfb46a7efa7bc714cerion   case 0x10E: { // vpkshus (Pack Signed HW Unsigned Saturate, AV p221)
175833c052793dacedf702ca4b6ccbfb46a7efa7bc714cerion      // This insn does a signed->unsigned saturating conversion.
175843c052793dacedf702ca4b6ccbfb46a7efa7bc714cerion      // Conversion done here, then uses unsigned->unsigned vpk insn:
175853c052793dacedf702ca4b6ccbfb46a7efa7bc714cerion      //  => UnsignedSaturatingNarrow( x & ~ (x >>s 15) )
175863c052793dacedf702ca4b6ccbfb46a7efa7bc714cerion      IRTemp vA_tmp = newTemp(Ity_V128);
175873c052793dacedf702ca4b6ccbfb46a7efa7bc714cerion      IRTemp vB_tmp = newTemp(Ity_V128);
17588197bd17d3ba8ac5204cd5c9ba5fab571249eb791sewardj      DIP("vpkshus v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
175893c052793dacedf702ca4b6ccbfb46a7efa7bc714cerion      assign( vA_tmp, binop(Iop_AndV128, mkexpr(vA),
175903c052793dacedf702ca4b6ccbfb46a7efa7bc714cerion                            unop(Iop_NotV128,
175913c052793dacedf702ca4b6ccbfb46a7efa7bc714cerion                                 binop(Iop_SarN16x8,
175923c052793dacedf702ca4b6ccbfb46a7efa7bc714cerion                                       mkexpr(vA), mkU8(15)))) );
175933c052793dacedf702ca4b6ccbfb46a7efa7bc714cerion      assign( vB_tmp, binop(Iop_AndV128, mkexpr(vB),
175943c052793dacedf702ca4b6ccbfb46a7efa7bc714cerion                            unop(Iop_NotV128,
175953c052793dacedf702ca4b6ccbfb46a7efa7bc714cerion                                 binop(Iop_SarN16x8,
175963c052793dacedf702ca4b6ccbfb46a7efa7bc714cerion                                       mkexpr(vB), mkU8(15)))) );
175975f438dd73072211989c6d496845bdc9b777ecbecsewardj      putVReg( vD_addr, binop(Iop_QNarrowBin16Uto8Ux16,
175983c052793dacedf702ca4b6ccbfb46a7efa7bc714cerion                              mkexpr(vA_tmp), mkexpr(vB_tmp)) );
175993c052793dacedf702ca4b6ccbfb46a7efa7bc714cerion      // TODO: set VSCR[SAT]
176003c052793dacedf702ca4b6ccbfb46a7efa7bc714cerion      return True;
176013c052793dacedf702ca4b6ccbfb46a7efa7bc714cerion   }
176023c052793dacedf702ca4b6ccbfb46a7efa7bc714cerion   case 0x14E: { // vpkswus (Pack Signed W Unsigned Saturate, AV p223)
176033c052793dacedf702ca4b6ccbfb46a7efa7bc714cerion      // This insn does a signed->unsigned saturating conversion.
176043c052793dacedf702ca4b6ccbfb46a7efa7bc714cerion      // Conversion done here, then uses unsigned->unsigned vpk insn:
176053c052793dacedf702ca4b6ccbfb46a7efa7bc714cerion      //  => UnsignedSaturatingNarrow( x & ~ (x >>s 31) )
176063c052793dacedf702ca4b6ccbfb46a7efa7bc714cerion      IRTemp vA_tmp = newTemp(Ity_V128);
176073c052793dacedf702ca4b6ccbfb46a7efa7bc714cerion      IRTemp vB_tmp = newTemp(Ity_V128);
17608197bd17d3ba8ac5204cd5c9ba5fab571249eb791sewardj      DIP("vpkswus v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
176093c052793dacedf702ca4b6ccbfb46a7efa7bc714cerion      assign( vA_tmp, binop(Iop_AndV128, mkexpr(vA),
176103c052793dacedf702ca4b6ccbfb46a7efa7bc714cerion                            unop(Iop_NotV128,
176113c052793dacedf702ca4b6ccbfb46a7efa7bc714cerion                                 binop(Iop_SarN32x4,
176123c052793dacedf702ca4b6ccbfb46a7efa7bc714cerion                                       mkexpr(vA), mkU8(31)))) );
176133c052793dacedf702ca4b6ccbfb46a7efa7bc714cerion      assign( vB_tmp, binop(Iop_AndV128, mkexpr(vB),
176143c052793dacedf702ca4b6ccbfb46a7efa7bc714cerion                            unop(Iop_NotV128,
176153c052793dacedf702ca4b6ccbfb46a7efa7bc714cerion                                 binop(Iop_SarN32x4,
176163c052793dacedf702ca4b6ccbfb46a7efa7bc714cerion                                       mkexpr(vB), mkU8(31)))) );
176175f438dd73072211989c6d496845bdc9b777ecbecsewardj      putVReg( vD_addr, binop(Iop_QNarrowBin32Uto16Ux8,
176183c052793dacedf702ca4b6ccbfb46a7efa7bc714cerion                              mkexpr(vA_tmp), mkexpr(vB_tmp)) );
176193c052793dacedf702ca4b6ccbfb46a7efa7bc714cerion      // TODO: set VSCR[SAT]
176203c052793dacedf702ca4b6ccbfb46a7efa7bc714cerion      return True;
176213c052793dacedf702ca4b6ccbfb46a7efa7bc714cerion   }
1762232aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion   case 0x18E: // vpkshss (Pack Signed HW Signed Saturate, AV p220)
1762332aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion      DIP("vpkshss v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
176245b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion      putVReg( vD_addr,
176255f438dd73072211989c6d496845bdc9b777ecbecsewardj               binop(Iop_QNarrowBin16Sto8Sx16, mkexpr(vA), mkexpr(vB)) );
176263c052793dacedf702ca4b6ccbfb46a7efa7bc714cerion      // TODO: set VSCR[SAT]
176273c052793dacedf702ca4b6ccbfb46a7efa7bc714cerion      return True;
1762832aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion
1762932aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion   case 0x1CE: // vpkswss (Pack Signed W Signed Saturate, AV p222)
1763032aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion      DIP("vpkswss v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
176315b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion      putVReg( vD_addr,
176325f438dd73072211989c6d496845bdc9b777ecbecsewardj               binop(Iop_QNarrowBin32Sto16Sx8, mkexpr(vA), mkexpr(vB)) );
176333c052793dacedf702ca4b6ccbfb46a7efa7bc714cerion      // TODO: set VSCR[SAT]
176343c052793dacedf702ca4b6ccbfb46a7efa7bc714cerion      return True;
1763532aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion
176363c052793dacedf702ca4b6ccbfb46a7efa7bc714cerion   case 0x30E: { // vpkpx (Pack Pixel, AV p219)
176373c052793dacedf702ca4b6ccbfb46a7efa7bc714cerion      /* CAB: Worth a new primop? */
176385b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion      /* Using shifts to compact pixel elements, then packing them */
176393c052793dacedf702ca4b6ccbfb46a7efa7bc714cerion      IRTemp a1 = newTemp(Ity_V128);
176403c052793dacedf702ca4b6ccbfb46a7efa7bc714cerion      IRTemp a2 = newTemp(Ity_V128);
176413c052793dacedf702ca4b6ccbfb46a7efa7bc714cerion      IRTemp a3 = newTemp(Ity_V128);
176423c052793dacedf702ca4b6ccbfb46a7efa7bc714cerion      IRTemp a_tmp = newTemp(Ity_V128);
176433c052793dacedf702ca4b6ccbfb46a7efa7bc714cerion      IRTemp b1 = newTemp(Ity_V128);
176443c052793dacedf702ca4b6ccbfb46a7efa7bc714cerion      IRTemp b2 = newTemp(Ity_V128);
176453c052793dacedf702ca4b6ccbfb46a7efa7bc714cerion      IRTemp b3 = newTemp(Ity_V128);
176463c052793dacedf702ca4b6ccbfb46a7efa7bc714cerion      IRTemp b_tmp = newTemp(Ity_V128);
17647197bd17d3ba8ac5204cd5c9ba5fab571249eb791sewardj      DIP("vpkpx v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
176483c052793dacedf702ca4b6ccbfb46a7efa7bc714cerion      assign( a1, binop(Iop_ShlN16x8,
176493c052793dacedf702ca4b6ccbfb46a7efa7bc714cerion                        binop(Iop_ShrN32x4, mkexpr(vA), mkU8(19)),
176503c052793dacedf702ca4b6ccbfb46a7efa7bc714cerion                        mkU8(10)) );
176513c052793dacedf702ca4b6ccbfb46a7efa7bc714cerion      assign( a2, binop(Iop_ShlN16x8,
176523c052793dacedf702ca4b6ccbfb46a7efa7bc714cerion                        binop(Iop_ShrN16x8, mkexpr(vA), mkU8(11)),
176533c052793dacedf702ca4b6ccbfb46a7efa7bc714cerion                        mkU8(5)) );
176543c052793dacedf702ca4b6ccbfb46a7efa7bc714cerion      assign( a3,  binop(Iop_ShrN16x8,
176553c052793dacedf702ca4b6ccbfb46a7efa7bc714cerion                         binop(Iop_ShlN16x8, mkexpr(vA), mkU8(8)),
176563c052793dacedf702ca4b6ccbfb46a7efa7bc714cerion                         mkU8(11)) );
176573c052793dacedf702ca4b6ccbfb46a7efa7bc714cerion      assign( a_tmp, binop(Iop_OrV128, mkexpr(a1),
176583c052793dacedf702ca4b6ccbfb46a7efa7bc714cerion                           binop(Iop_OrV128, mkexpr(a2), mkexpr(a3))) );
176593c052793dacedf702ca4b6ccbfb46a7efa7bc714cerion
176603c052793dacedf702ca4b6ccbfb46a7efa7bc714cerion      assign( b1, binop(Iop_ShlN16x8,
176613c052793dacedf702ca4b6ccbfb46a7efa7bc714cerion                        binop(Iop_ShrN32x4, mkexpr(vB), mkU8(19)),
176623c052793dacedf702ca4b6ccbfb46a7efa7bc714cerion                        mkU8(10)) );
176633c052793dacedf702ca4b6ccbfb46a7efa7bc714cerion      assign( b2, binop(Iop_ShlN16x8,
176643c052793dacedf702ca4b6ccbfb46a7efa7bc714cerion                        binop(Iop_ShrN16x8, mkexpr(vB), mkU8(11)),
176653c052793dacedf702ca4b6ccbfb46a7efa7bc714cerion                        mkU8(5)) );
176663c052793dacedf702ca4b6ccbfb46a7efa7bc714cerion      assign( b3,  binop(Iop_ShrN16x8,
176673c052793dacedf702ca4b6ccbfb46a7efa7bc714cerion                         binop(Iop_ShlN16x8, mkexpr(vB), mkU8(8)),
176683c052793dacedf702ca4b6ccbfb46a7efa7bc714cerion                         mkU8(11)) );
176693c052793dacedf702ca4b6ccbfb46a7efa7bc714cerion      assign( b_tmp, binop(Iop_OrV128, mkexpr(b1),
176703c052793dacedf702ca4b6ccbfb46a7efa7bc714cerion                           binop(Iop_OrV128, mkexpr(b2), mkexpr(b3))) );
176713c052793dacedf702ca4b6ccbfb46a7efa7bc714cerion
176725f438dd73072211989c6d496845bdc9b777ecbecsewardj      putVReg( vD_addr, binop(Iop_NarrowBin32to16x8,
176733c052793dacedf702ca4b6ccbfb46a7efa7bc714cerion                              mkexpr(a_tmp), mkexpr(b_tmp)) );
176743c052793dacedf702ca4b6ccbfb46a7efa7bc714cerion      return True;
176753c052793dacedf702ca4b6ccbfb46a7efa7bc714cerion   }
1767632aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion
176770c74bb5aa3240f693df0568d578baabf0c376dc4carll   case 0x44E: // vpkudum (Pack Unsigned Double Word Unsigned Modulo)
176780c74bb5aa3240f693df0568d578baabf0c376dc4carll      DIP("vpkudum v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
176790c74bb5aa3240f693df0568d578baabf0c376dc4carll      putVReg( vD_addr,
176800c74bb5aa3240f693df0568d578baabf0c376dc4carll               binop(Iop_NarrowBin64to32x4, mkexpr(vA), mkexpr(vB)) );
176810c74bb5aa3240f693df0568d578baabf0c376dc4carll      return True;
176820c74bb5aa3240f693df0568d578baabf0c376dc4carll
1768348ae46b56cef87c90638b25d6b2462c475033da8carll   case 0x4CE: // vpkudus (Pack Unsigned Double Word Unsigned Saturate)
1768448ae46b56cef87c90638b25d6b2462c475033da8carll      DIP("vpkudus v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
1768548ae46b56cef87c90638b25d6b2462c475033da8carll      putVReg( vD_addr,
1768648ae46b56cef87c90638b25d6b2462c475033da8carll               binop(Iop_QNarrowBin64Uto32Ux4, mkexpr(vA), mkexpr(vB)) );
1768748ae46b56cef87c90638b25d6b2462c475033da8carll      // TODO: set VSCR[SAT]
1768848ae46b56cef87c90638b25d6b2462c475033da8carll      return True;
1768948ae46b56cef87c90638b25d6b2462c475033da8carll
1769048ae46b56cef87c90638b25d6b2462c475033da8carll   case 0x54E: { // vpksdus (Pack Signed Double Word Unsigned Saturate)
1769148ae46b56cef87c90638b25d6b2462c475033da8carll      // This insn does a doubled signed->double unsigned saturating conversion
1769248ae46b56cef87c90638b25d6b2462c475033da8carll      // Conversion done here, then uses unsigned->unsigned vpk insn:
1769348ae46b56cef87c90638b25d6b2462c475033da8carll      //  => UnsignedSaturatingNarrow( x & ~ (x >>s 31) )
1769448ae46b56cef87c90638b25d6b2462c475033da8carll      // This is similar to the technique used for vpkswus, except done
1769548ae46b56cef87c90638b25d6b2462c475033da8carll      // with double word integers versus word integers.
1769648ae46b56cef87c90638b25d6b2462c475033da8carll      IRTemp vA_tmp = newTemp(Ity_V128);
1769748ae46b56cef87c90638b25d6b2462c475033da8carll      IRTemp vB_tmp = newTemp(Ity_V128);
1769848ae46b56cef87c90638b25d6b2462c475033da8carll      DIP("vpksdus v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
1769948ae46b56cef87c90638b25d6b2462c475033da8carll      assign( vA_tmp, binop(Iop_AndV128, mkexpr(vA),
1770048ae46b56cef87c90638b25d6b2462c475033da8carll                            unop(Iop_NotV128,
1770148ae46b56cef87c90638b25d6b2462c475033da8carll                                 binop(Iop_SarN64x2,
1770248ae46b56cef87c90638b25d6b2462c475033da8carll                                       mkexpr(vA), mkU8(63)))) );
1770348ae46b56cef87c90638b25d6b2462c475033da8carll      assign( vB_tmp, binop(Iop_AndV128, mkexpr(vB),
1770448ae46b56cef87c90638b25d6b2462c475033da8carll                            unop(Iop_NotV128,
1770548ae46b56cef87c90638b25d6b2462c475033da8carll                                 binop(Iop_SarN64x2,
1770648ae46b56cef87c90638b25d6b2462c475033da8carll                                       mkexpr(vB), mkU8(63)))) );
1770748ae46b56cef87c90638b25d6b2462c475033da8carll      putVReg( vD_addr, binop(Iop_QNarrowBin64Uto32Ux4,
1770848ae46b56cef87c90638b25d6b2462c475033da8carll                              mkexpr(vA_tmp), mkexpr(vB_tmp)) );
1770948ae46b56cef87c90638b25d6b2462c475033da8carll      // TODO: set VSCR[SAT]
1771048ae46b56cef87c90638b25d6b2462c475033da8carll      return True;
1771148ae46b56cef87c90638b25d6b2462c475033da8carll   }
1771248ae46b56cef87c90638b25d6b2462c475033da8carll
1771348ae46b56cef87c90638b25d6b2462c475033da8carll   case 0x5CE: // vpksdss (Pack Signed double word Signed Saturate)
1771448ae46b56cef87c90638b25d6b2462c475033da8carll      DIP("vpksdss v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
1771548ae46b56cef87c90638b25d6b2462c475033da8carll      putVReg( vD_addr,
1771648ae46b56cef87c90638b25d6b2462c475033da8carll               binop(Iop_QNarrowBin64Sto32Sx4, mkexpr(vA), mkexpr(vB)) );
1771748ae46b56cef87c90638b25d6b2462c475033da8carll      // TODO: set VSCR[SAT]
1771848ae46b56cef87c90638b25d6b2462c475033da8carll      return True;
1771932aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion   default:
1772032aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion      break; // Fall through...
1772132aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion   }
1772232aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion
1772332aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion
1772432aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion   if (vA_addr != 0) {
177255b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion      vex_printf("dis_av_pack(ppc)(vA_addr)\n");
1772632aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion      return False;
1772732aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion   }
1772832aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion
17729197bd17d3ba8ac5204cd5c9ba5fab571249eb791sewardj   signs = newTemp(Ity_V128);
17730197bd17d3ba8ac5204cd5c9ba5fab571249eb791sewardj   zeros = newTemp(Ity_V128);
177313c052793dacedf702ca4b6ccbfb46a7efa7bc714cerion   assign( zeros, unop(Iop_Dup32x4, mkU32(0)) );
177323c052793dacedf702ca4b6ccbfb46a7efa7bc714cerion
1773332aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion   switch (opc2) {
1773432aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion   /* Unpacking */
177353c052793dacedf702ca4b6ccbfb46a7efa7bc714cerion   case 0x20E: { // vupkhsb (Unpack High Signed B, AV p277)
1773632aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion      DIP("vupkhsb v%d,v%d\n", vD_addr, vB_addr);
177373c052793dacedf702ca4b6ccbfb46a7efa7bc714cerion      assign( signs, binop(Iop_CmpGT8Sx16, mkexpr(zeros), mkexpr(vB)) );
177385b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion      putVReg( vD_addr,
177395b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion               binop(Iop_InterleaveHI8x16, mkexpr(signs), mkexpr(vB)) );
177403c052793dacedf702ca4b6ccbfb46a7efa7bc714cerion      break;
177413c052793dacedf702ca4b6ccbfb46a7efa7bc714cerion   }
177423c052793dacedf702ca4b6ccbfb46a7efa7bc714cerion   case 0x24E: { // vupkhsh (Unpack High Signed HW, AV p278)
1774332aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion      DIP("vupkhsh v%d,v%d\n", vD_addr, vB_addr);
177443c052793dacedf702ca4b6ccbfb46a7efa7bc714cerion      assign( signs, binop(Iop_CmpGT16Sx8, mkexpr(zeros), mkexpr(vB)) );
177455b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion      putVReg( vD_addr,
177465b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion               binop(Iop_InterleaveHI16x8, mkexpr(signs), mkexpr(vB)) );
177473c052793dacedf702ca4b6ccbfb46a7efa7bc714cerion      break;
177483c052793dacedf702ca4b6ccbfb46a7efa7bc714cerion   }
177493c052793dacedf702ca4b6ccbfb46a7efa7bc714cerion   case 0x28E: { // vupklsb (Unpack Low Signed B, AV p280)
1775032aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion      DIP("vupklsb v%d,v%d\n", vD_addr, vB_addr);
177513c052793dacedf702ca4b6ccbfb46a7efa7bc714cerion      assign( signs, binop(Iop_CmpGT8Sx16, mkexpr(zeros), mkexpr(vB)) );
177525b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion      putVReg( vD_addr,
177535b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion               binop(Iop_InterleaveLO8x16, mkexpr(signs), mkexpr(vB)) );
177543c052793dacedf702ca4b6ccbfb46a7efa7bc714cerion      break;
177553c052793dacedf702ca4b6ccbfb46a7efa7bc714cerion   }
177563c052793dacedf702ca4b6ccbfb46a7efa7bc714cerion   case 0x2CE: { // vupklsh (Unpack Low Signed HW, AV p281)
1775732aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion      DIP("vupklsh v%d,v%d\n", vD_addr, vB_addr);
177583c052793dacedf702ca4b6ccbfb46a7efa7bc714cerion      assign( signs, binop(Iop_CmpGT16Sx8, mkexpr(zeros), mkexpr(vB)) );
177595b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion      putVReg( vD_addr,
177605b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion               binop(Iop_InterleaveLO16x8, mkexpr(signs), mkexpr(vB)) );
177613c052793dacedf702ca4b6ccbfb46a7efa7bc714cerion      break;
177623c052793dacedf702ca4b6ccbfb46a7efa7bc714cerion   }
177633c052793dacedf702ca4b6ccbfb46a7efa7bc714cerion   case 0x34E: { // vupkhpx (Unpack High Pixel16, AV p276)
177643c052793dacedf702ca4b6ccbfb46a7efa7bc714cerion      /* CAB: Worth a new primop? */
177653c052793dacedf702ca4b6ccbfb46a7efa7bc714cerion      /* Using shifts to isolate pixel elements, then expanding them */
177663c052793dacedf702ca4b6ccbfb46a7efa7bc714cerion      IRTemp z0  = newTemp(Ity_V128);
177673c052793dacedf702ca4b6ccbfb46a7efa7bc714cerion      IRTemp z1  = newTemp(Ity_V128);
177683c052793dacedf702ca4b6ccbfb46a7efa7bc714cerion      IRTemp z01 = newTemp(Ity_V128);
177693c052793dacedf702ca4b6ccbfb46a7efa7bc714cerion      IRTemp z2  = newTemp(Ity_V128);
177703c052793dacedf702ca4b6ccbfb46a7efa7bc714cerion      IRTemp z3  = newTemp(Ity_V128);
177713c052793dacedf702ca4b6ccbfb46a7efa7bc714cerion      IRTemp z23 = newTemp(Ity_V128);
17772197bd17d3ba8ac5204cd5c9ba5fab571249eb791sewardj      DIP("vupkhpx v%d,v%d\n", vD_addr, vB_addr);
177733c052793dacedf702ca4b6ccbfb46a7efa7bc714cerion      assign( z0,  binop(Iop_ShlN16x8,
177743c052793dacedf702ca4b6ccbfb46a7efa7bc714cerion                         binop(Iop_SarN16x8, mkexpr(vB), mkU8(15)),
177753c052793dacedf702ca4b6ccbfb46a7efa7bc714cerion                         mkU8(8)) );
177763c052793dacedf702ca4b6ccbfb46a7efa7bc714cerion      assign( z1,  binop(Iop_ShrN16x8,
177773c052793dacedf702ca4b6ccbfb46a7efa7bc714cerion                         binop(Iop_ShlN16x8, mkexpr(vB), mkU8(1)),
177783c052793dacedf702ca4b6ccbfb46a7efa7bc714cerion                         mkU8(11)) );
177793c052793dacedf702ca4b6ccbfb46a7efa7bc714cerion      assign( z01, binop(Iop_InterleaveHI16x8, mkexpr(zeros),
177803c052793dacedf702ca4b6ccbfb46a7efa7bc714cerion                         binop(Iop_OrV128, mkexpr(z0), mkexpr(z1))) );
177813c052793dacedf702ca4b6ccbfb46a7efa7bc714cerion      assign( z2,  binop(Iop_ShrN16x8,
177823c052793dacedf702ca4b6ccbfb46a7efa7bc714cerion                         binop(Iop_ShlN16x8,
177833c052793dacedf702ca4b6ccbfb46a7efa7bc714cerion                               binop(Iop_ShrN16x8, mkexpr(vB), mkU8(5)),
177843c052793dacedf702ca4b6ccbfb46a7efa7bc714cerion                               mkU8(11)),
177853c052793dacedf702ca4b6ccbfb46a7efa7bc714cerion                         mkU8(3)) );
177863c052793dacedf702ca4b6ccbfb46a7efa7bc714cerion      assign( z3,  binop(Iop_ShrN16x8,
177873c052793dacedf702ca4b6ccbfb46a7efa7bc714cerion                         binop(Iop_ShlN16x8, mkexpr(vB), mkU8(11)),
177883c052793dacedf702ca4b6ccbfb46a7efa7bc714cerion                         mkU8(11)) );
177893c052793dacedf702ca4b6ccbfb46a7efa7bc714cerion      assign( z23, binop(Iop_InterleaveHI16x8, mkexpr(zeros),
177903c052793dacedf702ca4b6ccbfb46a7efa7bc714cerion                         binop(Iop_OrV128, mkexpr(z2), mkexpr(z3))) );
177915b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion      putVReg( vD_addr,
177925b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion               binop(Iop_OrV128,
177935b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion                     binop(Iop_ShlN32x4, mkexpr(z01), mkU8(16)),
177945b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion                     mkexpr(z23)) );
177953c052793dacedf702ca4b6ccbfb46a7efa7bc714cerion      break;
177963c052793dacedf702ca4b6ccbfb46a7efa7bc714cerion   }
177973c052793dacedf702ca4b6ccbfb46a7efa7bc714cerion   case 0x3CE: { // vupklpx (Unpack Low Pixel16, AV p279)
177983c052793dacedf702ca4b6ccbfb46a7efa7bc714cerion      /* identical to vupkhpx, except interleaving LO */
177993c052793dacedf702ca4b6ccbfb46a7efa7bc714cerion      IRTemp z0  = newTemp(Ity_V128);
178003c052793dacedf702ca4b6ccbfb46a7efa7bc714cerion      IRTemp z1  = newTemp(Ity_V128);
178013c052793dacedf702ca4b6ccbfb46a7efa7bc714cerion      IRTemp z01 = newTemp(Ity_V128);
178023c052793dacedf702ca4b6ccbfb46a7efa7bc714cerion      IRTemp z2  = newTemp(Ity_V128);
178033c052793dacedf702ca4b6ccbfb46a7efa7bc714cerion      IRTemp z3  = newTemp(Ity_V128);
178043c052793dacedf702ca4b6ccbfb46a7efa7bc714cerion      IRTemp z23 = newTemp(Ity_V128);
17805197bd17d3ba8ac5204cd5c9ba5fab571249eb791sewardj      DIP("vupklpx v%d,v%d\n", vD_addr, vB_addr);
178063c052793dacedf702ca4b6ccbfb46a7efa7bc714cerion      assign( z0,  binop(Iop_ShlN16x8,
178073c052793dacedf702ca4b6ccbfb46a7efa7bc714cerion                         binop(Iop_SarN16x8, mkexpr(vB), mkU8(15)),
178083c052793dacedf702ca4b6ccbfb46a7efa7bc714cerion                         mkU8(8)) );
178093c052793dacedf702ca4b6ccbfb46a7efa7bc714cerion      assign( z1,  binop(Iop_ShrN16x8,
178103c052793dacedf702ca4b6ccbfb46a7efa7bc714cerion                         binop(Iop_ShlN16x8, mkexpr(vB), mkU8(1)),
178113c052793dacedf702ca4b6ccbfb46a7efa7bc714cerion                         mkU8(11)) );
178123c052793dacedf702ca4b6ccbfb46a7efa7bc714cerion      assign( z01, binop(Iop_InterleaveLO16x8, mkexpr(zeros),
178133c052793dacedf702ca4b6ccbfb46a7efa7bc714cerion                         binop(Iop_OrV128, mkexpr(z0), mkexpr(z1))) );
178143c052793dacedf702ca4b6ccbfb46a7efa7bc714cerion      assign( z2,  binop(Iop_ShrN16x8,
178153c052793dacedf702ca4b6ccbfb46a7efa7bc714cerion                         binop(Iop_ShlN16x8,
178163c052793dacedf702ca4b6ccbfb46a7efa7bc714cerion                               binop(Iop_ShrN16x8, mkexpr(vB), mkU8(5)),
178173c052793dacedf702ca4b6ccbfb46a7efa7bc714cerion                               mkU8(11)),
178183c052793dacedf702ca4b6ccbfb46a7efa7bc714cerion                         mkU8(3)) );
178193c052793dacedf702ca4b6ccbfb46a7efa7bc714cerion      assign( z3,  binop(Iop_ShrN16x8,
178203c052793dacedf702ca4b6ccbfb46a7efa7bc714cerion                         binop(Iop_ShlN16x8, mkexpr(vB), mkU8(11)),
178213c052793dacedf702ca4b6ccbfb46a7efa7bc714cerion                         mkU8(11)) );
178223c052793dacedf702ca4b6ccbfb46a7efa7bc714cerion      assign( z23, binop(Iop_InterleaveLO16x8, mkexpr(zeros),
178233c052793dacedf702ca4b6ccbfb46a7efa7bc714cerion                         binop(Iop_OrV128, mkexpr(z2), mkexpr(z3))) );
178245b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion      putVReg( vD_addr,
178255b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion               binop(Iop_OrV128,
178265b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion                     binop(Iop_ShlN32x4, mkexpr(z01), mkU8(16)),
178275b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion                     mkexpr(z23)) );
178283c052793dacedf702ca4b6ccbfb46a7efa7bc714cerion      break;
178293c052793dacedf702ca4b6ccbfb46a7efa7bc714cerion   }
1783048ae46b56cef87c90638b25d6b2462c475033da8carll   case 0x64E: { // vupkhsw (Unpack High Signed Word)
1783148ae46b56cef87c90638b25d6b2462c475033da8carll      DIP("vupkhsw v%d,v%d\n", vD_addr, vB_addr);
1783248ae46b56cef87c90638b25d6b2462c475033da8carll      assign( signs, binop(Iop_CmpGT32Sx4, mkexpr(zeros), mkexpr(vB)) );
1783348ae46b56cef87c90638b25d6b2462c475033da8carll      putVReg( vD_addr,
1783448ae46b56cef87c90638b25d6b2462c475033da8carll               binop(Iop_InterleaveHI32x4, mkexpr(signs), mkexpr(vB)) );
1783548ae46b56cef87c90638b25d6b2462c475033da8carll      break;
1783648ae46b56cef87c90638b25d6b2462c475033da8carll   }
1783748ae46b56cef87c90638b25d6b2462c475033da8carll   case 0x6CE: { // vupklsw (Unpack Low Signed Word)
1783848ae46b56cef87c90638b25d6b2462c475033da8carll      DIP("vupklsw v%d,v%d\n", vD_addr, vB_addr);
1783948ae46b56cef87c90638b25d6b2462c475033da8carll      assign( signs, binop(Iop_CmpGT32Sx4, mkexpr(zeros), mkexpr(vB)) );
1784048ae46b56cef87c90638b25d6b2462c475033da8carll      putVReg( vD_addr,
1784148ae46b56cef87c90638b25d6b2462c475033da8carll               binop(Iop_InterleaveLO32x4, mkexpr(signs), mkexpr(vB)) );
1784248ae46b56cef87c90638b25d6b2462c475033da8carll      break;
1784348ae46b56cef87c90638b25d6b2462c475033da8carll   }
1784432aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion   default:
178455b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion      vex_printf("dis_av_pack(ppc)(opc2)\n");
1784632aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion      return False;
1784732aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion   }
1784832aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion   return True;
1784932aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion}
1785032aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion
178517deaf9552b546b847528cf39b38898fb7742b5f5carll/*
178527deaf9552b546b847528cf39b38898fb7742b5f5carll  AltiVec Cipher Instructions
178537deaf9552b546b847528cf39b38898fb7742b5f5carll*/
178547deaf9552b546b847528cf39b38898fb7742b5f5carllstatic Bool dis_av_cipher ( UInt theInstr )
178557deaf9552b546b847528cf39b38898fb7742b5f5carll{
178567deaf9552b546b847528cf39b38898fb7742b5f5carll   /* VX-Form */
178577deaf9552b546b847528cf39b38898fb7742b5f5carll   UChar opc1     = ifieldOPC(theInstr);
178587deaf9552b546b847528cf39b38898fb7742b5f5carll   UChar vD_addr  = ifieldRegDS(theInstr);
178597deaf9552b546b847528cf39b38898fb7742b5f5carll   UChar vA_addr  = ifieldRegA(theInstr);
178607deaf9552b546b847528cf39b38898fb7742b5f5carll   UChar vB_addr  = ifieldRegB(theInstr);
178617deaf9552b546b847528cf39b38898fb7742b5f5carll   UInt  opc2     = IFIELD( theInstr, 0, 11 );
178627deaf9552b546b847528cf39b38898fb7742b5f5carll
178637deaf9552b546b847528cf39b38898fb7742b5f5carll   IRTemp vA    = newTemp(Ity_V128);
178647deaf9552b546b847528cf39b38898fb7742b5f5carll   IRTemp vB    = newTemp(Ity_V128);
178657deaf9552b546b847528cf39b38898fb7742b5f5carll   assign( vA, getVReg(vA_addr));
178667deaf9552b546b847528cf39b38898fb7742b5f5carll   assign( vB, getVReg(vB_addr));
178677deaf9552b546b847528cf39b38898fb7742b5f5carll
178687deaf9552b546b847528cf39b38898fb7742b5f5carll   if (opc1 != 0x4) {
178697deaf9552b546b847528cf39b38898fb7742b5f5carll      vex_printf("dis_av_cipher(ppc)(instr)\n");
178707deaf9552b546b847528cf39b38898fb7742b5f5carll      return False;
178717deaf9552b546b847528cf39b38898fb7742b5f5carll   }
178727deaf9552b546b847528cf39b38898fb7742b5f5carll   switch (opc2) {
178737deaf9552b546b847528cf39b38898fb7742b5f5carll      case 0x508: // vcipher (Vector Inverser Cipher)
178747deaf9552b546b847528cf39b38898fb7742b5f5carll         DIP("vcipher v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
178757deaf9552b546b847528cf39b38898fb7742b5f5carll         putVReg( vD_addr,
178767deaf9552b546b847528cf39b38898fb7742b5f5carll                  binop(Iop_CipherV128, mkexpr(vA), mkexpr(vB)) );
178777deaf9552b546b847528cf39b38898fb7742b5f5carll         return True;
178787deaf9552b546b847528cf39b38898fb7742b5f5carll
178797deaf9552b546b847528cf39b38898fb7742b5f5carll      case 0x509: // vcipherlast (Vector Inverser Cipher Last)
178807deaf9552b546b847528cf39b38898fb7742b5f5carll         DIP("vcipherlast v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
178817deaf9552b546b847528cf39b38898fb7742b5f5carll         putVReg( vD_addr,
178827deaf9552b546b847528cf39b38898fb7742b5f5carll                  binop(Iop_CipherLV128, mkexpr(vA), mkexpr(vB)) );
178837deaf9552b546b847528cf39b38898fb7742b5f5carll         return True;
178847deaf9552b546b847528cf39b38898fb7742b5f5carll
178857deaf9552b546b847528cf39b38898fb7742b5f5carll      case 0x548: // vncipher (Vector Inverser Cipher)
178867deaf9552b546b847528cf39b38898fb7742b5f5carll         DIP("vncipher v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
178877deaf9552b546b847528cf39b38898fb7742b5f5carll         putVReg( vD_addr,
178887deaf9552b546b847528cf39b38898fb7742b5f5carll                  binop(Iop_NCipherV128, mkexpr(vA), mkexpr(vB)) );
178897deaf9552b546b847528cf39b38898fb7742b5f5carll         return True;
178907deaf9552b546b847528cf39b38898fb7742b5f5carll
178917deaf9552b546b847528cf39b38898fb7742b5f5carll      case 0x549: // vncipherlast (Vector Inverser Cipher Last)
178927deaf9552b546b847528cf39b38898fb7742b5f5carll         DIP("vncipherlast v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
178937deaf9552b546b847528cf39b38898fb7742b5f5carll         putVReg( vD_addr,
178947deaf9552b546b847528cf39b38898fb7742b5f5carll                  binop(Iop_NCipherLV128, mkexpr(vA), mkexpr(vB)) );
178957deaf9552b546b847528cf39b38898fb7742b5f5carll         return True;
178967deaf9552b546b847528cf39b38898fb7742b5f5carll
178977deaf9552b546b847528cf39b38898fb7742b5f5carll      case 0x5C8: /* vsbox (Vector SubBytes, this does the cipher
178987deaf9552b546b847528cf39b38898fb7742b5f5carll       * subBytes transform)
178997deaf9552b546b847528cf39b38898fb7742b5f5carll       */
179007deaf9552b546b847528cf39b38898fb7742b5f5carll         DIP("vsbox v%d,v%d\n", vD_addr, vA_addr);
179017deaf9552b546b847528cf39b38898fb7742b5f5carll         putVReg( vD_addr,
179027deaf9552b546b847528cf39b38898fb7742b5f5carll                  unop(Iop_CipherSV128, mkexpr(vA) ) );
179037deaf9552b546b847528cf39b38898fb7742b5f5carll         return True;
179047deaf9552b546b847528cf39b38898fb7742b5f5carll
179057deaf9552b546b847528cf39b38898fb7742b5f5carll      default:
179067deaf9552b546b847528cf39b38898fb7742b5f5carll         vex_printf("dis_av_cipher(ppc)(opc2)\n");
179077deaf9552b546b847528cf39b38898fb7742b5f5carll         return False;
179087deaf9552b546b847528cf39b38898fb7742b5f5carll   }
179097deaf9552b546b847528cf39b38898fb7742b5f5carll   return True;
179107deaf9552b546b847528cf39b38898fb7742b5f5carll}
179117deaf9552b546b847528cf39b38898fb7742b5f5carll
179127deaf9552b546b847528cf39b38898fb7742b5f5carll/*
179137deaf9552b546b847528cf39b38898fb7742b5f5carll  AltiVec Secure Hash Instructions
179147deaf9552b546b847528cf39b38898fb7742b5f5carll*/
179157deaf9552b546b847528cf39b38898fb7742b5f5carllstatic Bool dis_av_hash ( UInt theInstr )
179167deaf9552b546b847528cf39b38898fb7742b5f5carll{
179177deaf9552b546b847528cf39b38898fb7742b5f5carll   /* VX-Form */
179187deaf9552b546b847528cf39b38898fb7742b5f5carll   UChar opc1     = ifieldOPC(theInstr);
179197deaf9552b546b847528cf39b38898fb7742b5f5carll   UChar vRT_addr = ifieldRegDS(theInstr);
179207deaf9552b546b847528cf39b38898fb7742b5f5carll   UChar vRA_addr  = ifieldRegA(theInstr);
179217deaf9552b546b847528cf39b38898fb7742b5f5carll   UChar s_field  = IFIELD( theInstr, 11, 5 );  // st and six field
179227deaf9552b546b847528cf39b38898fb7742b5f5carll   UChar st       = IFIELD( theInstr, 15, 1 );  // st
179237deaf9552b546b847528cf39b38898fb7742b5f5carll   UChar six      = IFIELD( theInstr, 11, 4 );  // six field
179247deaf9552b546b847528cf39b38898fb7742b5f5carll   UInt  opc2     = IFIELD( theInstr, 0, 11 );
179257deaf9552b546b847528cf39b38898fb7742b5f5carll
179267deaf9552b546b847528cf39b38898fb7742b5f5carll   IRTemp vA    = newTemp(Ity_V128);
179277deaf9552b546b847528cf39b38898fb7742b5f5carll   IRTemp dst    = newTemp(Ity_V128);
179287deaf9552b546b847528cf39b38898fb7742b5f5carll   assign( vA, getVReg(vRA_addr));
179297deaf9552b546b847528cf39b38898fb7742b5f5carll
179307deaf9552b546b847528cf39b38898fb7742b5f5carll   if (opc1 != 0x4) {
179317deaf9552b546b847528cf39b38898fb7742b5f5carll      vex_printf("dis_av_hash(ppc)(instr)\n");
179327deaf9552b546b847528cf39b38898fb7742b5f5carll      return False;
179337deaf9552b546b847528cf39b38898fb7742b5f5carll   }
179347deaf9552b546b847528cf39b38898fb7742b5f5carll
179357deaf9552b546b847528cf39b38898fb7742b5f5carll   switch (opc2) {
179367deaf9552b546b847528cf39b38898fb7742b5f5carll      case 0x682:  // vshasigmaw
179377deaf9552b546b847528cf39b38898fb7742b5f5carll         DIP("vshasigmaw v%d,v%d,%u,%u\n", vRT_addr, vRA_addr, st, six);
179387deaf9552b546b847528cf39b38898fb7742b5f5carll         assign( dst, binop( Iop_SHA256, mkexpr( vA ), mkU8( s_field) ) );
179397deaf9552b546b847528cf39b38898fb7742b5f5carll         putVReg( vRT_addr, mkexpr(dst));
179407deaf9552b546b847528cf39b38898fb7742b5f5carll         return True;
179417deaf9552b546b847528cf39b38898fb7742b5f5carll
179427deaf9552b546b847528cf39b38898fb7742b5f5carll      case 0x6C2:  // vshasigmad,
179437deaf9552b546b847528cf39b38898fb7742b5f5carll         DIP("vshasigmad v%d,v%d,%u,%u\n", vRT_addr, vRA_addr, st, six);
179447deaf9552b546b847528cf39b38898fb7742b5f5carll         putVReg( vRT_addr, binop( Iop_SHA512, mkexpr( vA ), mkU8( s_field) ) );
179457deaf9552b546b847528cf39b38898fb7742b5f5carll         return True;
179467deaf9552b546b847528cf39b38898fb7742b5f5carll
179477deaf9552b546b847528cf39b38898fb7742b5f5carll      default:
179487deaf9552b546b847528cf39b38898fb7742b5f5carll         vex_printf("dis_av_hash(ppc)(opc2)\n");
179497deaf9552b546b847528cf39b38898fb7742b5f5carll         return False;
179507deaf9552b546b847528cf39b38898fb7742b5f5carll   }
179517deaf9552b546b847528cf39b38898fb7742b5f5carll   return True;
179527deaf9552b546b847528cf39b38898fb7742b5f5carll}
179537deaf9552b546b847528cf39b38898fb7742b5f5carll
179547deaf9552b546b847528cf39b38898fb7742b5f5carll/*
1795560c6bac19ffe055cabab554e7877d73096a8bf17carll * This function is used by the Vector add/subtract [extended] modulo/carry
1795660c6bac19ffe055cabab554e7877d73096a8bf17carll * instructions.
1795760c6bac19ffe055cabab554e7877d73096a8bf17carll *   - For the non-extended add instructions, the cin arg is set to zero.
1795860c6bac19ffe055cabab554e7877d73096a8bf17carll *   - For the extended add instructions, cin is the integer value of
1795960c6bac19ffe055cabab554e7877d73096a8bf17carll *     src3.bit[127].
1796060c6bac19ffe055cabab554e7877d73096a8bf17carll *   - For the non-extended subtract instructions, src1 is added to the one's
1796160c6bac19ffe055cabab554e7877d73096a8bf17carll *     complement of src2 + 1.  We re-use the cin argument to hold the '1'
1796260c6bac19ffe055cabab554e7877d73096a8bf17carll *     value for this operation.
1796360c6bac19ffe055cabab554e7877d73096a8bf17carll *   - For the extended subtract instructions, cin is the integer value of src3.bit[127].
1796460c6bac19ffe055cabab554e7877d73096a8bf17carll */
1796560c6bac19ffe055cabab554e7877d73096a8bf17carllstatic IRTemp _get_quad_modulo_or_carry(IRExpr * vecA, IRExpr * vecB,
1796660c6bac19ffe055cabab554e7877d73096a8bf17carll                                        IRExpr * cin, Bool modulo)
1796760c6bac19ffe055cabab554e7877d73096a8bf17carll{
1796860c6bac19ffe055cabab554e7877d73096a8bf17carll   IRTemp _vecA_32   = IRTemp_INVALID;
1796960c6bac19ffe055cabab554e7877d73096a8bf17carll   IRTemp _vecB_32   = IRTemp_INVALID;
1797060c6bac19ffe055cabab554e7877d73096a8bf17carll   IRTemp res_32     = IRTemp_INVALID;
1797160c6bac19ffe055cabab554e7877d73096a8bf17carll   IRTemp result     = IRTemp_INVALID;
1797260c6bac19ffe055cabab554e7877d73096a8bf17carll   IRTemp tmp_result = IRTemp_INVALID;
1797360c6bac19ffe055cabab554e7877d73096a8bf17carll   IRTemp carry      = IRTemp_INVALID;
1797460c6bac19ffe055cabab554e7877d73096a8bf17carll   Int i;
1797560c6bac19ffe055cabab554e7877d73096a8bf17carll   IRExpr * _vecA_low64 =  unop( Iop_V128to64, vecA );
1797660c6bac19ffe055cabab554e7877d73096a8bf17carll   IRExpr * _vecB_low64 =  unop( Iop_V128to64, vecB );
1797760c6bac19ffe055cabab554e7877d73096a8bf17carll   IRExpr * _vecA_high64 = unop( Iop_V128HIto64, vecA );
1797860c6bac19ffe055cabab554e7877d73096a8bf17carll   IRExpr * _vecB_high64 = unop( Iop_V128HIto64, vecB );
1797960c6bac19ffe055cabab554e7877d73096a8bf17carll
1798060c6bac19ffe055cabab554e7877d73096a8bf17carll   for (i = 0; i < 4; i++) {
1798160c6bac19ffe055cabab554e7877d73096a8bf17carll      _vecA_32 = newTemp(Ity_I32);
1798260c6bac19ffe055cabab554e7877d73096a8bf17carll      _vecB_32 = newTemp(Ity_I32);
1798360c6bac19ffe055cabab554e7877d73096a8bf17carll      res_32   = newTemp(Ity_I32);
1798460c6bac19ffe055cabab554e7877d73096a8bf17carll      switch (i) {
1798560c6bac19ffe055cabab554e7877d73096a8bf17carll      case 0:
1798660c6bac19ffe055cabab554e7877d73096a8bf17carll         assign(_vecA_32, unop( Iop_64to32, _vecA_low64 ) );
1798760c6bac19ffe055cabab554e7877d73096a8bf17carll         assign(_vecB_32, unop( Iop_64to32, _vecB_low64 ) );
1798860c6bac19ffe055cabab554e7877d73096a8bf17carll         break;
1798960c6bac19ffe055cabab554e7877d73096a8bf17carll      case 1:
1799060c6bac19ffe055cabab554e7877d73096a8bf17carll         assign(_vecA_32, unop( Iop_64HIto32, _vecA_low64 ) );
1799160c6bac19ffe055cabab554e7877d73096a8bf17carll         assign(_vecB_32, unop( Iop_64HIto32, _vecB_low64 ) );
1799260c6bac19ffe055cabab554e7877d73096a8bf17carll         break;
1799360c6bac19ffe055cabab554e7877d73096a8bf17carll      case 2:
1799460c6bac19ffe055cabab554e7877d73096a8bf17carll         assign(_vecA_32, unop( Iop_64to32, _vecA_high64 ) );
1799560c6bac19ffe055cabab554e7877d73096a8bf17carll         assign(_vecB_32, unop( Iop_64to32, _vecB_high64 ) );
1799660c6bac19ffe055cabab554e7877d73096a8bf17carll         break;
1799760c6bac19ffe055cabab554e7877d73096a8bf17carll      case 3:
1799860c6bac19ffe055cabab554e7877d73096a8bf17carll         assign(_vecA_32, unop( Iop_64HIto32, _vecA_high64 ) );
1799960c6bac19ffe055cabab554e7877d73096a8bf17carll         assign(_vecB_32, unop( Iop_64HIto32, _vecB_high64 ) );
1800060c6bac19ffe055cabab554e7877d73096a8bf17carll         break;
1800160c6bac19ffe055cabab554e7877d73096a8bf17carll      }
1800260c6bac19ffe055cabab554e7877d73096a8bf17carll
1800360c6bac19ffe055cabab554e7877d73096a8bf17carll      assign(res_32, binop( Iop_Add32,
1800460c6bac19ffe055cabab554e7877d73096a8bf17carll                            binop( Iop_Add32,
1800560c6bac19ffe055cabab554e7877d73096a8bf17carll                                   binop ( Iop_Add32,
1800660c6bac19ffe055cabab554e7877d73096a8bf17carll                                           mkexpr(_vecA_32),
1800760c6bac19ffe055cabab554e7877d73096a8bf17carll                                           mkexpr(_vecB_32) ),
1800860c6bac19ffe055cabab554e7877d73096a8bf17carll                                   (i == 0) ? mkU32(0) : mkexpr(carry) ),
1800960c6bac19ffe055cabab554e7877d73096a8bf17carll                            (i == 0) ? cin : mkU32(0) ) );
1801060c6bac19ffe055cabab554e7877d73096a8bf17carll      if (modulo) {
1801160c6bac19ffe055cabab554e7877d73096a8bf17carll         result = newTemp(Ity_V128);
1801260c6bac19ffe055cabab554e7877d73096a8bf17carll         assign(result, binop( Iop_OrV128,
1801360c6bac19ffe055cabab554e7877d73096a8bf17carll                              (i == 0) ? binop( Iop_64HLtoV128,
1801460c6bac19ffe055cabab554e7877d73096a8bf17carll                                                mkU64(0),
1801560c6bac19ffe055cabab554e7877d73096a8bf17carll                                                mkU64(0) ) : mkexpr(tmp_result),
1801660c6bac19ffe055cabab554e7877d73096a8bf17carll                              binop( Iop_ShlV128,
1801760c6bac19ffe055cabab554e7877d73096a8bf17carll                                     binop( Iop_64HLtoV128,
1801860c6bac19ffe055cabab554e7877d73096a8bf17carll                                            mkU64(0),
1801960c6bac19ffe055cabab554e7877d73096a8bf17carll                                            binop( Iop_32HLto64,
1802060c6bac19ffe055cabab554e7877d73096a8bf17carll                                                   mkU32(0),
1802160c6bac19ffe055cabab554e7877d73096a8bf17carll                                                   mkexpr(res_32) ) ),
1802260c6bac19ffe055cabab554e7877d73096a8bf17carll                                     mkU8(i * 32) ) ) );
1802360c6bac19ffe055cabab554e7877d73096a8bf17carll         tmp_result = newTemp(Ity_V128);
1802460c6bac19ffe055cabab554e7877d73096a8bf17carll         assign(tmp_result, mkexpr(result));
1802560c6bac19ffe055cabab554e7877d73096a8bf17carll      }
1802660c6bac19ffe055cabab554e7877d73096a8bf17carll      carry = newTemp(Ity_I32);
1802760c6bac19ffe055cabab554e7877d73096a8bf17carll      assign(carry, unop(Iop_1Uto32, binop( Iop_CmpLT32U,
1802860c6bac19ffe055cabab554e7877d73096a8bf17carll                                            mkexpr(res_32),
1802960c6bac19ffe055cabab554e7877d73096a8bf17carll                                            mkexpr(_vecA_32 ) ) ) );
1803060c6bac19ffe055cabab554e7877d73096a8bf17carll   }
1803160c6bac19ffe055cabab554e7877d73096a8bf17carll   if (modulo)
1803260c6bac19ffe055cabab554e7877d73096a8bf17carll      return result;
1803360c6bac19ffe055cabab554e7877d73096a8bf17carll   else
1803460c6bac19ffe055cabab554e7877d73096a8bf17carll      return carry;
1803560c6bac19ffe055cabab554e7877d73096a8bf17carll}
1803660c6bac19ffe055cabab554e7877d73096a8bf17carll
1803760c6bac19ffe055cabab554e7877d73096a8bf17carll
1803860c6bac19ffe055cabab554e7877d73096a8bf17carllstatic Bool dis_av_quad ( UInt theInstr )
1803960c6bac19ffe055cabab554e7877d73096a8bf17carll{
1804060c6bac19ffe055cabab554e7877d73096a8bf17carll   /* VX-Form */
1804160c6bac19ffe055cabab554e7877d73096a8bf17carll   UChar opc1     = ifieldOPC(theInstr);
1804260c6bac19ffe055cabab554e7877d73096a8bf17carll   UChar vRT_addr = ifieldRegDS(theInstr);
1804360c6bac19ffe055cabab554e7877d73096a8bf17carll   UChar vRA_addr = ifieldRegA(theInstr);
1804460c6bac19ffe055cabab554e7877d73096a8bf17carll   UChar vRB_addr = ifieldRegB(theInstr);
1804560c6bac19ffe055cabab554e7877d73096a8bf17carll   UChar vRC_addr;
1804660c6bac19ffe055cabab554e7877d73096a8bf17carll   UInt  opc2     = IFIELD( theInstr, 0, 11 );
1804760c6bac19ffe055cabab554e7877d73096a8bf17carll
1804860c6bac19ffe055cabab554e7877d73096a8bf17carll   IRTemp vA    = newTemp(Ity_V128);
1804960c6bac19ffe055cabab554e7877d73096a8bf17carll   IRTemp vB    = newTemp(Ity_V128);
1805060c6bac19ffe055cabab554e7877d73096a8bf17carll   IRTemp vC    = IRTemp_INVALID;
1805160c6bac19ffe055cabab554e7877d73096a8bf17carll   IRTemp cin    = IRTemp_INVALID;
1805260c6bac19ffe055cabab554e7877d73096a8bf17carll   assign( vA, getVReg(vRA_addr));
1805360c6bac19ffe055cabab554e7877d73096a8bf17carll   assign( vB, getVReg(vRB_addr));
1805460c6bac19ffe055cabab554e7877d73096a8bf17carll
1805560c6bac19ffe055cabab554e7877d73096a8bf17carll   if (opc1 != 0x4) {
1805660c6bac19ffe055cabab554e7877d73096a8bf17carll      vex_printf("dis_av_quad(ppc)(instr)\n");
1805760c6bac19ffe055cabab554e7877d73096a8bf17carll      return False;
1805860c6bac19ffe055cabab554e7877d73096a8bf17carll   }
1805960c6bac19ffe055cabab554e7877d73096a8bf17carll
1806060c6bac19ffe055cabab554e7877d73096a8bf17carll   switch (opc2) {
1806160c6bac19ffe055cabab554e7877d73096a8bf17carll   case 0x140:  // vaddcuq
1806260c6bac19ffe055cabab554e7877d73096a8bf17carll     DIP("vaddcuq v%d,v%d,v%d\n", vRT_addr, vRA_addr, vRB_addr);
1806360c6bac19ffe055cabab554e7877d73096a8bf17carll     putVReg( vRT_addr, unop( Iop_32UtoV128,
1806460c6bac19ffe055cabab554e7877d73096a8bf17carll                              mkexpr(_get_quad_modulo_or_carry(mkexpr(vA),
1806560c6bac19ffe055cabab554e7877d73096a8bf17carll                                                               mkexpr(vB),
1806660c6bac19ffe055cabab554e7877d73096a8bf17carll                                                               mkU32(0), False) ) ) );
1806760c6bac19ffe055cabab554e7877d73096a8bf17carll     return True;
1806860c6bac19ffe055cabab554e7877d73096a8bf17carll   case 0x100: // vadduqm
1806960c6bac19ffe055cabab554e7877d73096a8bf17carll      DIP("vadduqm v%d,v%d,v%d\n", vRT_addr, vRA_addr, vRB_addr);
1807060c6bac19ffe055cabab554e7877d73096a8bf17carll      putVReg( vRT_addr, mkexpr(_get_quad_modulo_or_carry(mkexpr(vA),
1807160c6bac19ffe055cabab554e7877d73096a8bf17carll                                                          mkexpr(vB), mkU32(0), True) ) );
1807260c6bac19ffe055cabab554e7877d73096a8bf17carll      return True;
1807360c6bac19ffe055cabab554e7877d73096a8bf17carll   case 0x540: // vsubcuq
1807460c6bac19ffe055cabab554e7877d73096a8bf17carll      DIP("vsubcuq v%d,v%d,v%d\n", vRT_addr, vRA_addr, vRB_addr);
1807560c6bac19ffe055cabab554e7877d73096a8bf17carll      putVReg( vRT_addr,
1807660c6bac19ffe055cabab554e7877d73096a8bf17carll               unop( Iop_32UtoV128,
1807760c6bac19ffe055cabab554e7877d73096a8bf17carll                     mkexpr(_get_quad_modulo_or_carry(mkexpr(vA),
1807860c6bac19ffe055cabab554e7877d73096a8bf17carll                                                      unop( Iop_NotV128,
1807960c6bac19ffe055cabab554e7877d73096a8bf17carll                                                            mkexpr(vB) ),
1808060c6bac19ffe055cabab554e7877d73096a8bf17carll                                                      mkU32(1), False) ) ) );
1808160c6bac19ffe055cabab554e7877d73096a8bf17carll      return True;
1808260c6bac19ffe055cabab554e7877d73096a8bf17carll   case 0x500: // vsubuqm
1808360c6bac19ffe055cabab554e7877d73096a8bf17carll      DIP("vsubuqm v%d,v%d,v%d\n", vRT_addr, vRA_addr, vRB_addr);
1808460c6bac19ffe055cabab554e7877d73096a8bf17carll      putVReg( vRT_addr,
1808560c6bac19ffe055cabab554e7877d73096a8bf17carll               mkexpr(_get_quad_modulo_or_carry(mkexpr(vA),
1808660c6bac19ffe055cabab554e7877d73096a8bf17carll                                                unop( Iop_NotV128, mkexpr(vB) ),
1808760c6bac19ffe055cabab554e7877d73096a8bf17carll                                                mkU32(1), True) ) );
1808860c6bac19ffe055cabab554e7877d73096a8bf17carll      return True;
1808960c6bac19ffe055cabab554e7877d73096a8bf17carll   case 0x054C: // vbpermq
1809060c6bac19ffe055cabab554e7877d73096a8bf17carll   {
1809160c6bac19ffe055cabab554e7877d73096a8bf17carll#define BPERMD_IDX_MASK 0x00000000000000FFULL
1809260c6bac19ffe055cabab554e7877d73096a8bf17carll#define BPERMD_BIT_MASK 0x8000000000000000ULL
1809360c6bac19ffe055cabab554e7877d73096a8bf17carll      int i;
1809460c6bac19ffe055cabab554e7877d73096a8bf17carll      IRExpr * vB_expr = mkexpr(vB);
1809560c6bac19ffe055cabab554e7877d73096a8bf17carll      IRExpr * res = binop(Iop_AndV128, mkV128(0), mkV128(0));
1809660c6bac19ffe055cabab554e7877d73096a8bf17carll      DIP("vbpermq v%d,v%d,v%d\n", vRT_addr, vRA_addr, vRB_addr);
1809760c6bac19ffe055cabab554e7877d73096a8bf17carll      for (i = 0; i < 16; i++) {
1809860c6bac19ffe055cabab554e7877d73096a8bf17carll         IRTemp idx_tmp = newTemp( Ity_V128 );
1809960c6bac19ffe055cabab554e7877d73096a8bf17carll         IRTemp perm_bit = newTemp( Ity_V128 );
1810060c6bac19ffe055cabab554e7877d73096a8bf17carll         IRTemp idx = newTemp( Ity_I8 );
1810160c6bac19ffe055cabab554e7877d73096a8bf17carll         IRTemp idx_LT127 = newTemp( Ity_I1 );
1810260c6bac19ffe055cabab554e7877d73096a8bf17carll         IRTemp idx_LT127_ity128 = newTemp( Ity_V128 );
1810360c6bac19ffe055cabab554e7877d73096a8bf17carll
1810460c6bac19ffe055cabab554e7877d73096a8bf17carll         assign( idx_tmp,
1810560c6bac19ffe055cabab554e7877d73096a8bf17carll                 binop( Iop_AndV128,
1810660c6bac19ffe055cabab554e7877d73096a8bf17carll                        binop( Iop_64HLtoV128,
1810760c6bac19ffe055cabab554e7877d73096a8bf17carll                               mkU64(0),
1810860c6bac19ffe055cabab554e7877d73096a8bf17carll                               mkU64(BPERMD_IDX_MASK) ),
1810960c6bac19ffe055cabab554e7877d73096a8bf17carll                        vB_expr ) );
1811060c6bac19ffe055cabab554e7877d73096a8bf17carll         assign( idx_LT127,
1811160c6bac19ffe055cabab554e7877d73096a8bf17carll                 binop( Iop_CmpEQ32,
1811260c6bac19ffe055cabab554e7877d73096a8bf17carll                        unop ( Iop_64to32,
1811360c6bac19ffe055cabab554e7877d73096a8bf17carll                               unop( Iop_V128to64, binop( Iop_ShrV128,
1811460c6bac19ffe055cabab554e7877d73096a8bf17carll                                                          mkexpr(idx_tmp),
1811560c6bac19ffe055cabab554e7877d73096a8bf17carll                                                          mkU8(7) ) ) ),
1811660c6bac19ffe055cabab554e7877d73096a8bf17carll                        mkU32(0) ) );
1811760c6bac19ffe055cabab554e7877d73096a8bf17carll
1811860c6bac19ffe055cabab554e7877d73096a8bf17carll         /* Below, we set idx to determine which bit of vA to use for the
1811960c6bac19ffe055cabab554e7877d73096a8bf17carll          * perm bit.  If idx_LT127 is 0, the perm bit is forced to '0'.
1812060c6bac19ffe055cabab554e7877d73096a8bf17carll          */
1812160c6bac19ffe055cabab554e7877d73096a8bf17carll         assign( idx,
1812260c6bac19ffe055cabab554e7877d73096a8bf17carll                 binop( Iop_And8,
1812360c6bac19ffe055cabab554e7877d73096a8bf17carll                        unop( Iop_1Sto8,
1812460c6bac19ffe055cabab554e7877d73096a8bf17carll                              mkexpr(idx_LT127) ),
1812560c6bac19ffe055cabab554e7877d73096a8bf17carll                        unop( Iop_32to8,
1812660c6bac19ffe055cabab554e7877d73096a8bf17carll                              unop( Iop_V128to32, mkexpr( idx_tmp ) ) ) ) );
1812760c6bac19ffe055cabab554e7877d73096a8bf17carll
1812860c6bac19ffe055cabab554e7877d73096a8bf17carll         assign( idx_LT127_ity128,
1812960c6bac19ffe055cabab554e7877d73096a8bf17carll                 binop( Iop_64HLtoV128,
1813060c6bac19ffe055cabab554e7877d73096a8bf17carll                        mkU64(0),
1813160c6bac19ffe055cabab554e7877d73096a8bf17carll                        unop( Iop_32Uto64,
1813260c6bac19ffe055cabab554e7877d73096a8bf17carll                              unop( Iop_1Uto32, mkexpr(idx_LT127 ) ) ) ) );
1813360c6bac19ffe055cabab554e7877d73096a8bf17carll         assign( perm_bit,
1813460c6bac19ffe055cabab554e7877d73096a8bf17carll                 binop( Iop_AndV128,
1813560c6bac19ffe055cabab554e7877d73096a8bf17carll                        mkexpr( idx_LT127_ity128 ),
1813660c6bac19ffe055cabab554e7877d73096a8bf17carll                        binop( Iop_ShrV128,
1813760c6bac19ffe055cabab554e7877d73096a8bf17carll                               binop( Iop_AndV128,
1813860c6bac19ffe055cabab554e7877d73096a8bf17carll                                      binop (Iop_64HLtoV128,
1813960c6bac19ffe055cabab554e7877d73096a8bf17carll                                             mkU64( BPERMD_BIT_MASK ),
1814060c6bac19ffe055cabab554e7877d73096a8bf17carll                                             mkU64(0)),
1814160c6bac19ffe055cabab554e7877d73096a8bf17carll                                      binop( Iop_ShlV128,
1814260c6bac19ffe055cabab554e7877d73096a8bf17carll                                             mkexpr( vA ),
1814360c6bac19ffe055cabab554e7877d73096a8bf17carll                                             mkexpr( idx ) ) ),
1814460c6bac19ffe055cabab554e7877d73096a8bf17carll                               mkU8( 127 ) ) ) );
18145bc6db6e02ea0964a8f1da1986ff201d500709a50carll         res = binop( Iop_OrV128,
18146bc6db6e02ea0964a8f1da1986ff201d500709a50carll                      res,
18147bc6db6e02ea0964a8f1da1986ff201d500709a50carll                      binop( Iop_ShlV128,
18148bc6db6e02ea0964a8f1da1986ff201d500709a50carll                             mkexpr( perm_bit ),
18149bc6db6e02ea0964a8f1da1986ff201d500709a50carll                             mkU8( i + 64 ) ) );
1815060c6bac19ffe055cabab554e7877d73096a8bf17carll         vB_expr = binop( Iop_ShrV128, vB_expr, mkU8( 8 ) );
1815160c6bac19ffe055cabab554e7877d73096a8bf17carll      }
1815260c6bac19ffe055cabab554e7877d73096a8bf17carll      putVReg( vRT_addr, res);
1815360c6bac19ffe055cabab554e7877d73096a8bf17carll      return True;
1815460c6bac19ffe055cabab554e7877d73096a8bf17carll#undef BPERMD_IDX_MASK
1815560c6bac19ffe055cabab554e7877d73096a8bf17carll#undef BPERMD_BIT_MASK
1815660c6bac19ffe055cabab554e7877d73096a8bf17carll   }
1815760c6bac19ffe055cabab554e7877d73096a8bf17carll
1815860c6bac19ffe055cabab554e7877d73096a8bf17carll   default:
1815960c6bac19ffe055cabab554e7877d73096a8bf17carll      break;  // fall through
1816060c6bac19ffe055cabab554e7877d73096a8bf17carll   }
1816160c6bac19ffe055cabab554e7877d73096a8bf17carll
1816260c6bac19ffe055cabab554e7877d73096a8bf17carll   opc2     = IFIELD( theInstr, 0, 6 );
1816360c6bac19ffe055cabab554e7877d73096a8bf17carll   vRC_addr = ifieldRegC(theInstr);
1816460c6bac19ffe055cabab554e7877d73096a8bf17carll   vC = newTemp(Ity_V128);
1816560c6bac19ffe055cabab554e7877d73096a8bf17carll   cin = newTemp(Ity_I32);
1816660c6bac19ffe055cabab554e7877d73096a8bf17carll   switch (opc2) {
1816760c6bac19ffe055cabab554e7877d73096a8bf17carll      case 0x3D: // vaddecuq
1816860c6bac19ffe055cabab554e7877d73096a8bf17carll         assign( vC, getVReg(vRC_addr));
1816960c6bac19ffe055cabab554e7877d73096a8bf17carll         DIP("vaddecuq v%d,v%d,v%d,v%d\n", vRT_addr, vRA_addr, vRB_addr,
1817060c6bac19ffe055cabab554e7877d73096a8bf17carll             vRC_addr);
1817160c6bac19ffe055cabab554e7877d73096a8bf17carll         assign(cin, binop( Iop_And32,
1817260c6bac19ffe055cabab554e7877d73096a8bf17carll                            unop( Iop_64to32,
1817360c6bac19ffe055cabab554e7877d73096a8bf17carll                                  unop( Iop_V128to64, mkexpr(vC) ) ),
1817460c6bac19ffe055cabab554e7877d73096a8bf17carll                            mkU32(1) ) );
1817560c6bac19ffe055cabab554e7877d73096a8bf17carll         putVReg( vRT_addr,
1817660c6bac19ffe055cabab554e7877d73096a8bf17carll                  unop( Iop_32UtoV128,
1817760c6bac19ffe055cabab554e7877d73096a8bf17carll                        mkexpr(_get_quad_modulo_or_carry(mkexpr(vA), mkexpr(vB),
1817860c6bac19ffe055cabab554e7877d73096a8bf17carll                                                         mkexpr(cin),
1817960c6bac19ffe055cabab554e7877d73096a8bf17carll                                                         False) ) ) );
1818060c6bac19ffe055cabab554e7877d73096a8bf17carll         return True;
1818160c6bac19ffe055cabab554e7877d73096a8bf17carll      case 0x3C: // vaddeuqm
1818260c6bac19ffe055cabab554e7877d73096a8bf17carll         assign( vC, getVReg(vRC_addr));
1818360c6bac19ffe055cabab554e7877d73096a8bf17carll         DIP("vaddeuqm v%d,v%d,v%d,v%d\n", vRT_addr, vRA_addr, vRB_addr,
1818460c6bac19ffe055cabab554e7877d73096a8bf17carll             vRC_addr);
1818560c6bac19ffe055cabab554e7877d73096a8bf17carll         assign(cin, binop( Iop_And32,
1818660c6bac19ffe055cabab554e7877d73096a8bf17carll                            unop( Iop_64to32,
1818760c6bac19ffe055cabab554e7877d73096a8bf17carll                                  unop( Iop_V128to64, mkexpr(vC) ) ),
1818860c6bac19ffe055cabab554e7877d73096a8bf17carll                            mkU32(1) ) );
1818960c6bac19ffe055cabab554e7877d73096a8bf17carll         putVReg( vRT_addr,
1819060c6bac19ffe055cabab554e7877d73096a8bf17carll                  mkexpr(_get_quad_modulo_or_carry(mkexpr(vA), mkexpr(vB),
1819160c6bac19ffe055cabab554e7877d73096a8bf17carll                                                   mkexpr(cin),
1819260c6bac19ffe055cabab554e7877d73096a8bf17carll                                                   True) ) );
1819360c6bac19ffe055cabab554e7877d73096a8bf17carll         return True;
1819460c6bac19ffe055cabab554e7877d73096a8bf17carll      case 0x3F: // vsubecuq
1819560c6bac19ffe055cabab554e7877d73096a8bf17carll         assign( vC, getVReg(vRC_addr));
1819660c6bac19ffe055cabab554e7877d73096a8bf17carll         DIP("vsubecuq v%d,v%d,v%d,v%d\n", vRT_addr, vRA_addr, vRB_addr,
1819760c6bac19ffe055cabab554e7877d73096a8bf17carll             vRC_addr);
1819860c6bac19ffe055cabab554e7877d73096a8bf17carll         assign(cin, binop( Iop_And32,
1819960c6bac19ffe055cabab554e7877d73096a8bf17carll                            unop( Iop_64to32,
1820060c6bac19ffe055cabab554e7877d73096a8bf17carll                                  unop( Iop_V128to64, mkexpr(vC) ) ),
1820160c6bac19ffe055cabab554e7877d73096a8bf17carll                            mkU32(1) ) );
1820260c6bac19ffe055cabab554e7877d73096a8bf17carll         putVReg( vRT_addr,
1820360c6bac19ffe055cabab554e7877d73096a8bf17carll                  unop( Iop_32UtoV128,
1820460c6bac19ffe055cabab554e7877d73096a8bf17carll                        mkexpr(_get_quad_modulo_or_carry(mkexpr(vA),
1820560c6bac19ffe055cabab554e7877d73096a8bf17carll                                                         unop( Iop_NotV128,
1820660c6bac19ffe055cabab554e7877d73096a8bf17carll                                                               mkexpr(vB) ),
1820760c6bac19ffe055cabab554e7877d73096a8bf17carll                                                         mkexpr(cin),
1820860c6bac19ffe055cabab554e7877d73096a8bf17carll                                                         False) ) ) );
1820960c6bac19ffe055cabab554e7877d73096a8bf17carll         return True;
1821060c6bac19ffe055cabab554e7877d73096a8bf17carll      case 0x3E: // vsubeuqm
1821160c6bac19ffe055cabab554e7877d73096a8bf17carll         assign( vC, getVReg(vRC_addr));
1821260c6bac19ffe055cabab554e7877d73096a8bf17carll         DIP("vsubeuqm v%d,v%d,v%d,v%d\n", vRT_addr, vRA_addr, vRB_addr,
1821360c6bac19ffe055cabab554e7877d73096a8bf17carll             vRC_addr);
1821460c6bac19ffe055cabab554e7877d73096a8bf17carll         assign(cin, binop( Iop_And32,
1821560c6bac19ffe055cabab554e7877d73096a8bf17carll                            unop( Iop_64to32,
1821660c6bac19ffe055cabab554e7877d73096a8bf17carll                                  unop( Iop_V128to64, mkexpr(vC) ) ),
1821760c6bac19ffe055cabab554e7877d73096a8bf17carll                            mkU32(1) ) );
1821860c6bac19ffe055cabab554e7877d73096a8bf17carll         putVReg( vRT_addr,
1821960c6bac19ffe055cabab554e7877d73096a8bf17carll                  mkexpr(_get_quad_modulo_or_carry(mkexpr(vA),
1822060c6bac19ffe055cabab554e7877d73096a8bf17carll                                                   unop( Iop_NotV128, mkexpr(vB) ),
1822160c6bac19ffe055cabab554e7877d73096a8bf17carll                                                   mkexpr(cin),
1822260c6bac19ffe055cabab554e7877d73096a8bf17carll                                                   True) ) );
1822360c6bac19ffe055cabab554e7877d73096a8bf17carll         return True;
1822460c6bac19ffe055cabab554e7877d73096a8bf17carll      default:
1822560c6bac19ffe055cabab554e7877d73096a8bf17carll         vex_printf("dis_av_quad(ppc)(opc2.2)\n");
1822660c6bac19ffe055cabab554e7877d73096a8bf17carll         return False;
1822760c6bac19ffe055cabab554e7877d73096a8bf17carll   }
1822860c6bac19ffe055cabab554e7877d73096a8bf17carll
1822960c6bac19ffe055cabab554e7877d73096a8bf17carll   return True;
1823060c6bac19ffe055cabab554e7877d73096a8bf17carll}
1823160c6bac19ffe055cabab554e7877d73096a8bf17carll
1823260c6bac19ffe055cabab554e7877d73096a8bf17carll
1823360c6bac19ffe055cabab554e7877d73096a8bf17carll/*
182347deaf9552b546b847528cf39b38898fb7742b5f5carll  AltiVec BCD Arithmetic instructions.
182357deaf9552b546b847528cf39b38898fb7742b5f5carll  These instructions modify CR6 for various conditions in the result,
182367deaf9552b546b847528cf39b38898fb7742b5f5carll  including when an overflow occurs.  We could easily detect all conditions
182377deaf9552b546b847528cf39b38898fb7742b5f5carll  except when an overflow occurs.  But since we can't be 100% accurate
182387deaf9552b546b847528cf39b38898fb7742b5f5carll  in our emulation of CR6, it seems best to just not support it all.
182397deaf9552b546b847528cf39b38898fb7742b5f5carll*/
182407deaf9552b546b847528cf39b38898fb7742b5f5carllstatic Bool dis_av_bcd ( UInt theInstr )
182417deaf9552b546b847528cf39b38898fb7742b5f5carll{
182427deaf9552b546b847528cf39b38898fb7742b5f5carll   /* VX-Form */
182437deaf9552b546b847528cf39b38898fb7742b5f5carll   UChar opc1     = ifieldOPC(theInstr);
182447deaf9552b546b847528cf39b38898fb7742b5f5carll   UChar vRT_addr = ifieldRegDS(theInstr);
182457deaf9552b546b847528cf39b38898fb7742b5f5carll   UChar vRA_addr = ifieldRegA(theInstr);
182467deaf9552b546b847528cf39b38898fb7742b5f5carll   UChar vRB_addr = ifieldRegB(theInstr);
182477deaf9552b546b847528cf39b38898fb7742b5f5carll   UChar ps       = IFIELD( theInstr, 9, 1 );
182487deaf9552b546b847528cf39b38898fb7742b5f5carll   UInt  opc2     = IFIELD( theInstr, 0, 9 );
182497deaf9552b546b847528cf39b38898fb7742b5f5carll
182507deaf9552b546b847528cf39b38898fb7742b5f5carll   IRTemp vA    = newTemp(Ity_V128);
182517deaf9552b546b847528cf39b38898fb7742b5f5carll   IRTemp vB    = newTemp(Ity_V128);
182527deaf9552b546b847528cf39b38898fb7742b5f5carll   IRTemp dst    = newTemp(Ity_V128);
182537deaf9552b546b847528cf39b38898fb7742b5f5carll   assign( vA, getVReg(vRA_addr));
182547deaf9552b546b847528cf39b38898fb7742b5f5carll   assign( vB, getVReg(vRB_addr));
182557deaf9552b546b847528cf39b38898fb7742b5f5carll
182567deaf9552b546b847528cf39b38898fb7742b5f5carll   if (opc1 != 0x4) {
182577deaf9552b546b847528cf39b38898fb7742b5f5carll      vex_printf("dis_av_bcd(ppc)(instr)\n");
182587deaf9552b546b847528cf39b38898fb7742b5f5carll      return False;
182597deaf9552b546b847528cf39b38898fb7742b5f5carll   }
182607deaf9552b546b847528cf39b38898fb7742b5f5carll
182617deaf9552b546b847528cf39b38898fb7742b5f5carll   switch (opc2) {
182627deaf9552b546b847528cf39b38898fb7742b5f5carll   case 0x1:  // bcdadd
182637deaf9552b546b847528cf39b38898fb7742b5f5carll     DIP("bcdadd. v%d,v%d,v%d,%u\n", vRT_addr, vRA_addr, vRB_addr, ps);
182647deaf9552b546b847528cf39b38898fb7742b5f5carll     assign( dst, triop( Iop_BCDAdd, mkexpr( vA ),
182657deaf9552b546b847528cf39b38898fb7742b5f5carll                         mkexpr( vB ), mkU8( ps ) ) );
182667deaf9552b546b847528cf39b38898fb7742b5f5carll     putVReg( vRT_addr, mkexpr(dst));
182677deaf9552b546b847528cf39b38898fb7742b5f5carll     return True;
182687deaf9552b546b847528cf39b38898fb7742b5f5carll
182697deaf9552b546b847528cf39b38898fb7742b5f5carll   case 0x41:  // bcdsub
182707deaf9552b546b847528cf39b38898fb7742b5f5carll     DIP("bcdsub. v%d,v%d,v%d,%u\n", vRT_addr, vRA_addr, vRB_addr, ps);
182717deaf9552b546b847528cf39b38898fb7742b5f5carll     assign( dst, triop( Iop_BCDSub, mkexpr( vA ),
182727deaf9552b546b847528cf39b38898fb7742b5f5carll                         mkexpr( vB ), mkU8( ps ) ) );
182737deaf9552b546b847528cf39b38898fb7742b5f5carll     putVReg( vRT_addr, mkexpr(dst));
182747deaf9552b546b847528cf39b38898fb7742b5f5carll     return True;
182757deaf9552b546b847528cf39b38898fb7742b5f5carll
182767deaf9552b546b847528cf39b38898fb7742b5f5carll   default:
182777deaf9552b546b847528cf39b38898fb7742b5f5carll      vex_printf("dis_av_bcd(ppc)(opc2)\n");
182787deaf9552b546b847528cf39b38898fb7742b5f5carll      return False;
182797deaf9552b546b847528cf39b38898fb7742b5f5carll   }
182807deaf9552b546b847528cf39b38898fb7742b5f5carll   return True;
182817deaf9552b546b847528cf39b38898fb7742b5f5carll}
1828232aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion
1828332aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion/*
1828432aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion  AltiVec Floating Point Arithmetic Instructions
1828532aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion*/
1828632aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerionstatic Bool dis_av_fp_arith ( UInt theInstr )
1828732aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion{
1828876de5cf615380b23b4b5bcced6541233cd4a93a0cerion   /* VA-Form */
1828976de5cf615380b23b4b5bcced6541233cd4a93a0cerion   UChar opc1     = ifieldOPC(theInstr);
1829076de5cf615380b23b4b5bcced6541233cd4a93a0cerion   UChar vD_addr  = ifieldRegDS(theInstr);
1829176de5cf615380b23b4b5bcced6541233cd4a93a0cerion   UChar vA_addr  = ifieldRegA(theInstr);
1829276de5cf615380b23b4b5bcced6541233cd4a93a0cerion   UChar vB_addr  = ifieldRegB(theInstr);
1829376de5cf615380b23b4b5bcced6541233cd4a93a0cerion   UChar vC_addr  = ifieldRegC(theInstr);
1829432aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion   UInt  opc2=0;
1829532aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion
182968ea0d3ebfb8b1e4d8b6f851b0079c47a9886c686cerion   IRTemp vA = newTemp(Ity_V128);
182978ea0d3ebfb8b1e4d8b6f851b0079c47a9886c686cerion   IRTemp vB = newTemp(Ity_V128);
182988ea0d3ebfb8b1e4d8b6f851b0079c47a9886c686cerion   IRTemp vC = newTemp(Ity_V128);
182998ea0d3ebfb8b1e4d8b6f851b0079c47a9886c686cerion   assign( vA, getVReg(vA_addr));
183008ea0d3ebfb8b1e4d8b6f851b0079c47a9886c686cerion   assign( vB, getVReg(vB_addr));
183018ea0d3ebfb8b1e4d8b6f851b0079c47a9886c686cerion   assign( vC, getVReg(vC_addr));
183028ea0d3ebfb8b1e4d8b6f851b0079c47a9886c686cerion
1830332aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion   if (opc1 != 0x4) {
183045b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion      vex_printf("dis_av_fp_arith(ppc)(instr)\n");
1830532aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion      return False;
1830632aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion   }
1830732aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion
1830820a760ec66a13a93147a40d3c3530be21d7fe411sewardj   IRTemp rm = newTemp(Ity_I32);
1830920a760ec66a13a93147a40d3c3530be21d7fe411sewardj   assign(rm, get_IR_roundingmode());
1831020a760ec66a13a93147a40d3c3530be21d7fe411sewardj
1831176de5cf615380b23b4b5bcced6541233cd4a93a0cerion   opc2 = IFIELD( theInstr, 0, 6 );
1831232aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion   switch (opc2) {
1831332aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion   case 0x2E: // vmaddfp (Multiply Add FP, AV p177)
183145b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion      DIP("vmaddfp v%d,v%d,v%d,v%d\n",
183155b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion          vD_addr, vA_addr, vC_addr, vB_addr);
183165b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion      putVReg( vD_addr,
1831720a760ec66a13a93147a40d3c3530be21d7fe411sewardj               triop(Iop_Add32Fx4, mkU32(Irrm_NEAREST),
1831820a760ec66a13a93147a40d3c3530be21d7fe411sewardj                     mkexpr(vB),
1831920a760ec66a13a93147a40d3c3530be21d7fe411sewardj                     triop(Iop_Mul32Fx4, mkU32(Irrm_NEAREST),
1832020a760ec66a13a93147a40d3c3530be21d7fe411sewardj                           mkexpr(vA), mkexpr(vC))) );
18321f3f173c1383bb406cf9cd5768712790ac8b5d14bcerion      return True;
1832232aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion
18323f3f173c1383bb406cf9cd5768712790ac8b5d14bcerion   case 0x2F: { // vnmsubfp (Negative Multiply-Subtract FP, AV p215)
183245b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion      DIP("vnmsubfp v%d,v%d,v%d,v%d\n",
183255b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion          vD_addr, vA_addr, vC_addr, vB_addr);
183265b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion      putVReg( vD_addr,
1832720a760ec66a13a93147a40d3c3530be21d7fe411sewardj               triop(Iop_Sub32Fx4, mkU32(Irrm_NEAREST),
183285b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion                     mkexpr(vB),
1832920a760ec66a13a93147a40d3c3530be21d7fe411sewardj                     triop(Iop_Mul32Fx4, mkU32(Irrm_NEAREST),
1833020a760ec66a13a93147a40d3c3530be21d7fe411sewardj                           mkexpr(vA), mkexpr(vC))) );
18331f3f173c1383bb406cf9cd5768712790ac8b5d14bcerion      return True;
18332f3f173c1383bb406cf9cd5768712790ac8b5d14bcerion   }
1833332aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion
1833432aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion   default:
1833532aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion     break; // Fall through...
1833632aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion   }
1833732aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion
1833876de5cf615380b23b4b5bcced6541233cd4a93a0cerion   opc2 = IFIELD( theInstr, 0, 11 );
1833932aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion   switch (opc2) {
1834032aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion   case 0x00A: // vaddfp (Add FP, AV p137)
1834132aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion      DIP("vaddfp v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
1834220a760ec66a13a93147a40d3c3530be21d7fe411sewardj      putVReg( vD_addr, triop(Iop_Add32Fx4,
1834320a760ec66a13a93147a40d3c3530be21d7fe411sewardj                              mkU32(Irrm_NEAREST), mkexpr(vA), mkexpr(vB)) );
183448ea0d3ebfb8b1e4d8b6f851b0079c47a9886c686cerion      return True;
1834532aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion
1834632aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion  case 0x04A: // vsubfp (Subtract FP, AV p261)
1834732aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion      DIP("vsubfp v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
1834820a760ec66a13a93147a40d3c3530be21d7fe411sewardj      putVReg( vD_addr, triop(Iop_Sub32Fx4,
1834920a760ec66a13a93147a40d3c3530be21d7fe411sewardj                              mkU32(Irrm_NEAREST), mkexpr(vA), mkexpr(vB)) );
183508ea0d3ebfb8b1e4d8b6f851b0079c47a9886c686cerion      return True;
1835132aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion
1835232aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion   case 0x40A: // vmaxfp (Maximum FP, AV p178)
1835332aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion      DIP("vmaxfp v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
183548ea0d3ebfb8b1e4d8b6f851b0079c47a9886c686cerion      putVReg( vD_addr, binop(Iop_Max32Fx4, mkexpr(vA), mkexpr(vB)) );
183558ea0d3ebfb8b1e4d8b6f851b0079c47a9886c686cerion      return True;
1835632aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion
1835732aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion   case 0x44A: // vminfp (Minimum FP, AV p187)
1835832aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion      DIP("vminfp v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
183598ea0d3ebfb8b1e4d8b6f851b0079c47a9886c686cerion      putVReg( vD_addr, binop(Iop_Min32Fx4, mkexpr(vA), mkexpr(vB)) );
183608ea0d3ebfb8b1e4d8b6f851b0079c47a9886c686cerion      return True;
1836132aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion
1836232aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion   default:
1836332aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion      break; // Fall through...
1836432aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion   }
1836532aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion
1836632aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion
1836732aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion   if (vA_addr != 0) {
183685b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion      vex_printf("dis_av_fp_arith(ppc)(vA_addr)\n");
1836932aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion      return False;
1837032aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion   }
1837132aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion
1837232aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion   switch (opc2) {
1837332aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion   case 0x10A: // vrefp (Reciprocal Esimate FP, AV p228)
1837432aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion      DIP("vrefp v%d,v%d\n", vD_addr, vB_addr);
183751ddee21008ffdb2ac7f8e6a73445f150f753606fsewardj      putVReg( vD_addr, unop(Iop_RecipEst32Fx4, mkexpr(vB)) );
183768ea0d3ebfb8b1e4d8b6f851b0079c47a9886c686cerion      return True;
1837732aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion
183785b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion   case 0x14A: // vrsqrtefp (Reciprocal Sqrt Estimate FP, AV p237)
1837932aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion      DIP("vrsqrtefp v%d,v%d\n", vD_addr, vB_addr);
183801ddee21008ffdb2ac7f8e6a73445f150f753606fsewardj      putVReg( vD_addr, unop(Iop_RSqrtEst32Fx4, mkexpr(vB)) );
183818ea0d3ebfb8b1e4d8b6f851b0079c47a9886c686cerion      return True;
1838232aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion
1838332aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion   case 0x18A: // vexptefp (2 Raised to the Exp Est FP, AV p173)
1838432aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion      DIP("vexptefp v%d,v%d\n", vD_addr, vB_addr);
1838532aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion      DIP(" => not implemented\n");
1838632aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion      return False;
1838732aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion
1838832aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion   case 0x1CA: // vlogefp (Log2 Estimate FP, AV p175)
1838932aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion      DIP("vlogefp v%d,v%d\n", vD_addr, vB_addr);
1839032aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion      DIP(" => not implemented\n");
1839132aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion      return False;
1839232aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion
1839332aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion   default:
183945b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion      vex_printf("dis_av_fp_arith(ppc)(opc2=0x%x)\n",opc2);
1839532aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion      return False;
1839632aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion   }
1839732aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion   return True;
1839832aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion}
1839932aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion
1840032aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion/*
1840132aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion  AltiVec Floating Point Compare Instructions
1840232aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion*/
1840332aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerionstatic Bool dis_av_fp_cmp ( UInt theInstr )
1840432aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion{
1840576de5cf615380b23b4b5bcced6541233cd4a93a0cerion   /* VXR-Form */
1840676de5cf615380b23b4b5bcced6541233cd4a93a0cerion   UChar opc1     = ifieldOPC(theInstr);
1840776de5cf615380b23b4b5bcced6541233cd4a93a0cerion   UChar vD_addr  = ifieldRegDS(theInstr);
1840876de5cf615380b23b4b5bcced6541233cd4a93a0cerion   UChar vA_addr  = ifieldRegA(theInstr);
1840976de5cf615380b23b4b5bcced6541233cd4a93a0cerion   UChar vB_addr  = ifieldRegB(theInstr);
1841076de5cf615380b23b4b5bcced6541233cd4a93a0cerion   UChar flag_rC  = ifieldBIT10(theInstr);
1841176de5cf615380b23b4b5bcced6541233cd4a93a0cerion   UInt  opc2     = IFIELD( theInstr, 0, 10 );
1841232aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion
184138ea0d3ebfb8b1e4d8b6f851b0079c47a9886c686cerion   Bool cmp_bounds = False;
184148ea0d3ebfb8b1e4d8b6f851b0079c47a9886c686cerion
184158ea0d3ebfb8b1e4d8b6f851b0079c47a9886c686cerion   IRTemp vA = newTemp(Ity_V128);
184168ea0d3ebfb8b1e4d8b6f851b0079c47a9886c686cerion   IRTemp vB = newTemp(Ity_V128);
184178ea0d3ebfb8b1e4d8b6f851b0079c47a9886c686cerion   IRTemp vD = newTemp(Ity_V128);
184188ea0d3ebfb8b1e4d8b6f851b0079c47a9886c686cerion   assign( vA, getVReg(vA_addr));
184198ea0d3ebfb8b1e4d8b6f851b0079c47a9886c686cerion   assign( vB, getVReg(vB_addr));
184208ea0d3ebfb8b1e4d8b6f851b0079c47a9886c686cerion
1842132aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion   if (opc1 != 0x4) {
184225b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion      vex_printf("dis_av_fp_cmp(ppc)(instr)\n");
1842332aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion      return False;
1842432aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion   }
1842532aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion
1842632aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion   switch (opc2) {
1842732aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion   case 0x0C6: // vcmpeqfp (Compare Equal-to FP, AV p159)
184285b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion      DIP("vcmpeqfp%s v%d,v%d,v%d\n", (flag_rC ? ".":""),
184295b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion                                      vD_addr, vA_addr, vB_addr);
184308ea0d3ebfb8b1e4d8b6f851b0079c47a9886c686cerion      assign( vD, binop(Iop_CmpEQ32Fx4, mkexpr(vA), mkexpr(vB)) );
184318ea0d3ebfb8b1e4d8b6f851b0079c47a9886c686cerion      break;
1843232aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion
184335b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion   case 0x1C6: // vcmpgefp (Compare Greater-than-or-Equal-to, AV p163)
184345b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion      DIP("vcmpgefp%s v%d,v%d,v%d\n", (flag_rC ? ".":""),
184355b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion                                      vD_addr, vA_addr, vB_addr);
184368ea0d3ebfb8b1e4d8b6f851b0079c47a9886c686cerion      assign( vD, binop(Iop_CmpGE32Fx4, mkexpr(vA), mkexpr(vB)) );
184378ea0d3ebfb8b1e4d8b6f851b0079c47a9886c686cerion      break;
1843832aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion
1843932aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion   case 0x2C6: // vcmpgtfp (Compare Greater-than FP, AV p164)
184405b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion      DIP("vcmpgtfp%s v%d,v%d,v%d\n", (flag_rC ? ".":""),
184415b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion                                      vD_addr, vA_addr, vB_addr);
184428ea0d3ebfb8b1e4d8b6f851b0079c47a9886c686cerion      assign( vD, binop(Iop_CmpGT32Fx4, mkexpr(vA), mkexpr(vB)) );
184438ea0d3ebfb8b1e4d8b6f851b0079c47a9886c686cerion      break;
1844432aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion
184458ea0d3ebfb8b1e4d8b6f851b0079c47a9886c686cerion   case 0x3C6: { // vcmpbfp (Compare Bounds FP, AV p157)
184468ea0d3ebfb8b1e4d8b6f851b0079c47a9886c686cerion      IRTemp gt      = newTemp(Ity_V128);
184478ea0d3ebfb8b1e4d8b6f851b0079c47a9886c686cerion      IRTemp lt      = newTemp(Ity_V128);
184488ea0d3ebfb8b1e4d8b6f851b0079c47a9886c686cerion      IRTemp zeros   = newTemp(Ity_V128);
184495b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion      DIP("vcmpbfp%s v%d,v%d,v%d\n", (flag_rC ? ".":""),
184505b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion                                     vD_addr, vA_addr, vB_addr);
184518ea0d3ebfb8b1e4d8b6f851b0079c47a9886c686cerion      cmp_bounds = True;
184528ea0d3ebfb8b1e4d8b6f851b0079c47a9886c686cerion      assign( zeros,   unop(Iop_Dup32x4, mkU32(0)) );
184538ea0d3ebfb8b1e4d8b6f851b0079c47a9886c686cerion
184548ea0d3ebfb8b1e4d8b6f851b0079c47a9886c686cerion      /* Note: making use of fact that the ppc backend for compare insns
184555b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion         return zero'd lanes if either of the corresponding arg lanes is
184565b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion         a nan.
184578ea0d3ebfb8b1e4d8b6f851b0079c47a9886c686cerion
184588ea0d3ebfb8b1e4d8b6f851b0079c47a9886c686cerion         Perhaps better to have an irop Iop_isNan32Fx4, but then we'd
184598ea0d3ebfb8b1e4d8b6f851b0079c47a9886c686cerion         need this for the other compares too (vcmpeqfp etc)...
184608ea0d3ebfb8b1e4d8b6f851b0079c47a9886c686cerion         Better still, tighten down the spec for compare irops.
184618ea0d3ebfb8b1e4d8b6f851b0079c47a9886c686cerion       */
184628ea0d3ebfb8b1e4d8b6f851b0079c47a9886c686cerion      assign( gt, unop(Iop_NotV128,
184638ea0d3ebfb8b1e4d8b6f851b0079c47a9886c686cerion                       binop(Iop_CmpLE32Fx4, mkexpr(vA), mkexpr(vB))) );
184648ea0d3ebfb8b1e4d8b6f851b0079c47a9886c686cerion      assign( lt, unop(Iop_NotV128,
184658ea0d3ebfb8b1e4d8b6f851b0079c47a9886c686cerion                       binop(Iop_CmpGE32Fx4, mkexpr(vA),
1846620a760ec66a13a93147a40d3c3530be21d7fe411sewardj                             triop(Iop_Sub32Fx4, mkU32(Irrm_NEAREST),
1846720a760ec66a13a93147a40d3c3530be21d7fe411sewardj                                   mkexpr(zeros),
1846820a760ec66a13a93147a40d3c3530be21d7fe411sewardj                                   mkexpr(vB)))) );
184698ea0d3ebfb8b1e4d8b6f851b0079c47a9886c686cerion
184708ea0d3ebfb8b1e4d8b6f851b0079c47a9886c686cerion      // finally, just shift gt,lt to correct position
184718ea0d3ebfb8b1e4d8b6f851b0079c47a9886c686cerion      assign( vD, binop(Iop_ShlN32x4,
184728ea0d3ebfb8b1e4d8b6f851b0079c47a9886c686cerion                        binop(Iop_OrV128,
184738ea0d3ebfb8b1e4d8b6f851b0079c47a9886c686cerion                              binop(Iop_AndV128, mkexpr(gt),
184748ea0d3ebfb8b1e4d8b6f851b0079c47a9886c686cerion                                    unop(Iop_Dup32x4, mkU32(0x2))),
184758ea0d3ebfb8b1e4d8b6f851b0079c47a9886c686cerion                              binop(Iop_AndV128, mkexpr(lt),
184768ea0d3ebfb8b1e4d8b6f851b0079c47a9886c686cerion                                    unop(Iop_Dup32x4, mkU32(0x1)))),
184778ea0d3ebfb8b1e4d8b6f851b0079c47a9886c686cerion                        mkU8(30)) );
184788ea0d3ebfb8b1e4d8b6f851b0079c47a9886c686cerion      break;
184798ea0d3ebfb8b1e4d8b6f851b0079c47a9886c686cerion   }
1848032aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion
1848132aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion   default:
184825b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion      vex_printf("dis_av_fp_cmp(ppc)(opc2)\n");
1848332aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion      return False;
1848432aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion   }
184858ea0d3ebfb8b1e4d8b6f851b0079c47a9886c686cerion
184868ea0d3ebfb8b1e4d8b6f851b0079c47a9886c686cerion   putVReg( vD_addr, mkexpr(vD) );
184878ea0d3ebfb8b1e4d8b6f851b0079c47a9886c686cerion
1848876de5cf615380b23b4b5bcced6541233cd4a93a0cerion   if (flag_rC) {
184898ea0d3ebfb8b1e4d8b6f851b0079c47a9886c686cerion      set_AV_CR6( mkexpr(vD), !cmp_bounds );
184908ea0d3ebfb8b1e4d8b6f851b0079c47a9886c686cerion   }
1849132aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion   return True;
1849232aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion}
1849332aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion
1849432aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion/*
1849532aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion  AltiVec Floating Point Convert/Round Instructions
1849632aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion*/
1849732aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerionstatic Bool dis_av_fp_convert ( UInt theInstr )
1849832aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion{
1849976de5cf615380b23b4b5bcced6541233cd4a93a0cerion   /* VX-Form */
1850076de5cf615380b23b4b5bcced6541233cd4a93a0cerion   UChar opc1     = ifieldOPC(theInstr);
1850176de5cf615380b23b4b5bcced6541233cd4a93a0cerion   UChar vD_addr  = ifieldRegDS(theInstr);
1850276de5cf615380b23b4b5bcced6541233cd4a93a0cerion   UChar UIMM_5   = ifieldRegA(theInstr);
1850376de5cf615380b23b4b5bcced6541233cd4a93a0cerion   UChar vB_addr  = ifieldRegB(theInstr);
1850476de5cf615380b23b4b5bcced6541233cd4a93a0cerion   UInt  opc2     = IFIELD( theInstr, 0, 11 );
1850576de5cf615380b23b4b5bcced6541233cd4a93a0cerion
1850676de5cf615380b23b4b5bcced6541233cd4a93a0cerion   IRTemp vB        = newTemp(Ity_V128);
1850776de5cf615380b23b4b5bcced6541233cd4a93a0cerion   IRTemp vScale    = newTemp(Ity_V128);
18508d963eb444d05fe1ef210a729ff056e28c330f120cerion   IRTemp vInvScale = newTemp(Ity_V128);
1850941a7b70f888cf73cf3da6a53b31937ce0d26e8f4sewardj
1851041a7b70f888cf73cf3da6a53b31937ce0d26e8f4sewardj   float scale, inv_scale;
1851141a7b70f888cf73cf3da6a53b31937ce0d26e8f4sewardj
18512d963eb444d05fe1ef210a729ff056e28c330f120cerion   assign( vB, getVReg(vB_addr));
18513d963eb444d05fe1ef210a729ff056e28c330f120cerion
18514d963eb444d05fe1ef210a729ff056e28c330f120cerion   /* scale = 2^UIMM, cast to float, reinterpreted as uint */
1851541a7b70f888cf73cf3da6a53b31937ce0d26e8f4sewardj   scale = (float)( (unsigned int) 1<<UIMM_5 );
185162ead522cf1c0069fbc55f7c5d1e8b2a00a044d6bsewardj   assign( vScale, unop(Iop_Dup32x4, mkU32( float_to_bits(scale) )) );
1851741a7b70f888cf73cf3da6a53b31937ce0d26e8f4sewardj   inv_scale = 1/scale;
185185b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion   assign( vInvScale,
185195b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion           unop(Iop_Dup32x4, mkU32( float_to_bits(inv_scale) )) );
18520d963eb444d05fe1ef210a729ff056e28c330f120cerion
1852132aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion   if (opc1 != 0x4) {
185225b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion      vex_printf("dis_av_fp_convert(ppc)(instr)\n");
1852332aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion      return False;
1852432aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion   }
1852532aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion
1852632aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion   switch (opc2) {
1852732aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion   case 0x30A: // vcfux (Convert from Unsigned Fixed-Point W, AV p156)
1852832aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion      DIP("vcfux v%d,v%d,%d\n", vD_addr, vB_addr, UIMM_5);
1852920a760ec66a13a93147a40d3c3530be21d7fe411sewardj      putVReg( vD_addr, triop(Iop_Mul32Fx4, mkU32(Irrm_NEAREST),
18530d963eb444d05fe1ef210a729ff056e28c330f120cerion                              unop(Iop_I32UtoFx4, mkexpr(vB)),
18531d963eb444d05fe1ef210a729ff056e28c330f120cerion                              mkexpr(vInvScale)) );
18532d963eb444d05fe1ef210a729ff056e28c330f120cerion      return True;
1853332aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion
1853432aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion   case 0x34A: // vcfsx (Convert from Signed Fixed-Point W, AV p155)
1853532aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion      DIP("vcfsx v%d,v%d,%d\n", vD_addr, vB_addr, UIMM_5);
18536d963eb444d05fe1ef210a729ff056e28c330f120cerion
1853720a760ec66a13a93147a40d3c3530be21d7fe411sewardj      putVReg( vD_addr, triop(Iop_Mul32Fx4, mkU32(Irrm_NEAREST),
18538d963eb444d05fe1ef210a729ff056e28c330f120cerion                              unop(Iop_I32StoFx4, mkexpr(vB)),
18539d963eb444d05fe1ef210a729ff056e28c330f120cerion                              mkexpr(vInvScale)) );
18540d963eb444d05fe1ef210a729ff056e28c330f120cerion      return True;
1854132aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion
1854232aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion   case 0x38A: // vctuxs (Convert to Unsigned Fixed-Point W Saturate, AV p172)
1854332aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion      DIP("vctuxs v%d,v%d,%d\n", vD_addr, vB_addr, UIMM_5);
18544d963eb444d05fe1ef210a729ff056e28c330f120cerion      putVReg( vD_addr,
18545d963eb444d05fe1ef210a729ff056e28c330f120cerion               unop(Iop_QFtoI32Ux4_RZ,
1854620a760ec66a13a93147a40d3c3530be21d7fe411sewardj                    triop(Iop_Mul32Fx4, mkU32(Irrm_NEAREST),
1854720a760ec66a13a93147a40d3c3530be21d7fe411sewardj                          mkexpr(vB), mkexpr(vScale))) );
18548d963eb444d05fe1ef210a729ff056e28c330f120cerion      return True;
1854932aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion
1855032aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion   case 0x3CA: // vctsxs (Convert to Signed Fixed-Point W Saturate, AV p171)
1855132aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion      DIP("vctsxs v%d,v%d,%d\n", vD_addr, vB_addr, UIMM_5);
18552d963eb444d05fe1ef210a729ff056e28c330f120cerion      putVReg( vD_addr,
18553d963eb444d05fe1ef210a729ff056e28c330f120cerion               unop(Iop_QFtoI32Sx4_RZ,
1855420a760ec66a13a93147a40d3c3530be21d7fe411sewardj                     triop(Iop_Mul32Fx4, mkU32(Irrm_NEAREST),
1855520a760ec66a13a93147a40d3c3530be21d7fe411sewardj                           mkexpr(vB), mkexpr(vScale))) );
18556d963eb444d05fe1ef210a729ff056e28c330f120cerion      return True;
1855732aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion
1855832aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion   default:
1855932aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion     break;    // Fall through...
1856032aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion   }
1856132aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion
1856232aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion   if (UIMM_5 != 0) {
185635b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion      vex_printf("dis_av_fp_convert(ppc)(UIMM_5)\n");
1856432aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion      return False;
1856532aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion   }
1856632aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion
1856732aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion   switch (opc2) {
1856832aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion   case 0x20A: // vrfin (Round to FP Integer Nearest, AV p231)
1856932aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion      DIP("vrfin v%d,v%d\n", vD_addr, vB_addr);
18570d963eb444d05fe1ef210a729ff056e28c330f120cerion      putVReg( vD_addr, unop(Iop_RoundF32x4_RN, mkexpr(vB)) );
18571d963eb444d05fe1ef210a729ff056e28c330f120cerion      break;
1857232aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion
1857332aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion   case 0x24A: // vrfiz (Round to FP Integer toward zero, AV p233)
1857432aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion      DIP("vrfiz v%d,v%d\n", vD_addr, vB_addr);
18575d963eb444d05fe1ef210a729ff056e28c330f120cerion      putVReg( vD_addr, unop(Iop_RoundF32x4_RZ, mkexpr(vB)) );
18576d963eb444d05fe1ef210a729ff056e28c330f120cerion      break;
1857732aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion
1857832aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion   case 0x28A: // vrfip (Round to FP Integer toward +inf, AV p232)
1857932aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion      DIP("vrfip v%d,v%d\n", vD_addr, vB_addr);
18580d963eb444d05fe1ef210a729ff056e28c330f120cerion      putVReg( vD_addr, unop(Iop_RoundF32x4_RP, mkexpr(vB)) );
18581d963eb444d05fe1ef210a729ff056e28c330f120cerion      break;
1858232aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion
1858332aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion   case 0x2CA: // vrfim (Round to FP Integer toward -inf, AV p230)
1858432aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion      DIP("vrfim v%d,v%d\n", vD_addr, vB_addr);
18585d963eb444d05fe1ef210a729ff056e28c330f120cerion      putVReg( vD_addr, unop(Iop_RoundF32x4_RM, mkexpr(vB)) );
18586d963eb444d05fe1ef210a729ff056e28c330f120cerion      break;
1858732aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion
1858832aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion   default:
185895b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion      vex_printf("dis_av_fp_convert(ppc)(opc2)\n");
1859032aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion      return False;
1859132aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion   }
1859232aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion   return True;
1859332aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion}
18594b51f0f4f33256638ed953156a2635aa739b232f1sewardj
185958943d02aa373f45c6e5fdcbe5947620285d442b1carllstatic Bool dis_transactional_memory ( UInt theInstr, UInt nextInstr,
18596cacba8e675988fbf21b08feea1f317a9c896c053florian                                       const VexAbiInfo* vbi,
185978943d02aa373f45c6e5fdcbe5947620285d442b1carll                                       /*OUT*/DisResult* dres,
18598beac530a718fcc646bc61fe60a86f599df54e1d7florian                                       Bool (*resteerOkFn)(void*,Addr),
185998943d02aa373f45c6e5fdcbe5947620285d442b1carll                                       void* callback_opaque )
186008943d02aa373f45c6e5fdcbe5947620285d442b1carll{
186018943d02aa373f45c6e5fdcbe5947620285d442b1carll   UInt   opc2      = IFIELD( theInstr, 1, 10 );
186028943d02aa373f45c6e5fdcbe5947620285d442b1carll
186038943d02aa373f45c6e5fdcbe5947620285d442b1carll   switch (opc2) {
186048943d02aa373f45c6e5fdcbe5947620285d442b1carll   case 0x28E: {        //tbegin.
186058943d02aa373f45c6e5fdcbe5947620285d442b1carll      /* The current implementation is to just fail the tbegin and execute
186068943d02aa373f45c6e5fdcbe5947620285d442b1carll       * the failure path.  The failure path is assumed to be functionaly
186078943d02aa373f45c6e5fdcbe5947620285d442b1carll       * equivalent to the transactional path with the needed data locking
186088943d02aa373f45c6e5fdcbe5947620285d442b1carll       * to ensure correctness.  The tend is just a noop and shouldn't
186098943d02aa373f45c6e5fdcbe5947620285d442b1carll       * actually get executed.
186108943d02aa373f45c6e5fdcbe5947620285d442b1carll       *   1) set cr0 to 0x2
186118943d02aa373f45c6e5fdcbe5947620285d442b1carll       *   2) Initialize TFHAR to CIA+4
186128943d02aa373f45c6e5fdcbe5947620285d442b1carll       *   3) Initialize TEXASR
186138943d02aa373f45c6e5fdcbe5947620285d442b1carll       *   4) Initialize TFIAR (probably to CIA, ie, the address of tbegin.)
186148943d02aa373f45c6e5fdcbe5947620285d442b1carll       *   5) Continue executing at the next instruction.
186158943d02aa373f45c6e5fdcbe5947620285d442b1carll       */
186168943d02aa373f45c6e5fdcbe5947620285d442b1carll      UInt R = IFIELD( theInstr, 21, 1 );
186178943d02aa373f45c6e5fdcbe5947620285d442b1carll
186188943d02aa373f45c6e5fdcbe5947620285d442b1carll      ULong tm_reason;
186198943d02aa373f45c6e5fdcbe5947620285d442b1carll      UInt failure_code = 0;  /* Forcing failure, will not be due to tabort
186208943d02aa373f45c6e5fdcbe5947620285d442b1carll                               * or treclaim.
186218943d02aa373f45c6e5fdcbe5947620285d442b1carll                               */
186228943d02aa373f45c6e5fdcbe5947620285d442b1carll      UInt persistant = 1;    /* set persistant since we are always failing
186238943d02aa373f45c6e5fdcbe5947620285d442b1carll                               * the tbegin.
186248943d02aa373f45c6e5fdcbe5947620285d442b1carll                               */
186258943d02aa373f45c6e5fdcbe5947620285d442b1carll      UInt nest_overflow = 1; /* Alowed nesting depth overflow, we use this
186268943d02aa373f45c6e5fdcbe5947620285d442b1carll                                 as the reason for failing the trasaction */
186278943d02aa373f45c6e5fdcbe5947620285d442b1carll      UInt tm_exact   = 1;    /* have exact address for failure */
186288943d02aa373f45c6e5fdcbe5947620285d442b1carll
18629b173774421d015736c2316b5e6e998e7de545a5cflorian      DIP("tbegin. %u\n", R);
186308943d02aa373f45c6e5fdcbe5947620285d442b1carll
186318943d02aa373f45c6e5fdcbe5947620285d442b1carll      /* Set the CR0 field to indicate the tbegin failed.  Then let
186328943d02aa373f45c6e5fdcbe5947620285d442b1carll       * the code do the branch to the failure path.
186338943d02aa373f45c6e5fdcbe5947620285d442b1carll       *
186348943d02aa373f45c6e5fdcbe5947620285d442b1carll       * 000 || 0  Transaction initiation successful,
186358943d02aa373f45c6e5fdcbe5947620285d442b1carll       *           unnested (Transaction state of
186368943d02aa373f45c6e5fdcbe5947620285d442b1carll       *           Non-transactional prior to tbegin.)
186378943d02aa373f45c6e5fdcbe5947620285d442b1carll       * 010 || 0  Transaction initiation successful, nested
186388943d02aa373f45c6e5fdcbe5947620285d442b1carll       *           (Transaction state of Transactional
186398943d02aa373f45c6e5fdcbe5947620285d442b1carll       *           prior to tbegin.)
186408943d02aa373f45c6e5fdcbe5947620285d442b1carll       * 001 || 0  Transaction initiation unsuccessful,
186418943d02aa373f45c6e5fdcbe5947620285d442b1carll       *           (Transaction state of Suspended prior
186428943d02aa373f45c6e5fdcbe5947620285d442b1carll       *           to tbegin.)
186438943d02aa373f45c6e5fdcbe5947620285d442b1carll       */
186448943d02aa373f45c6e5fdcbe5947620285d442b1carll      putCR321( 0, mkU8( 0x2 ) );
186458943d02aa373f45c6e5fdcbe5947620285d442b1carll
186468943d02aa373f45c6e5fdcbe5947620285d442b1carll      tm_reason = generate_TMreason( failure_code, persistant,
186478943d02aa373f45c6e5fdcbe5947620285d442b1carll                                     nest_overflow, tm_exact );
186488943d02aa373f45c6e5fdcbe5947620285d442b1carll
186498943d02aa373f45c6e5fdcbe5947620285d442b1carll      storeTMfailure( guest_CIA_curr_instr, tm_reason,
186508943d02aa373f45c6e5fdcbe5947620285d442b1carll                      guest_CIA_curr_instr+4 );
186518943d02aa373f45c6e5fdcbe5947620285d442b1carll
186528943d02aa373f45c6e5fdcbe5947620285d442b1carll      return True;
186538943d02aa373f45c6e5fdcbe5947620285d442b1carll
186548943d02aa373f45c6e5fdcbe5947620285d442b1carll      break;
186558943d02aa373f45c6e5fdcbe5947620285d442b1carll   }
186568943d02aa373f45c6e5fdcbe5947620285d442b1carll
186578943d02aa373f45c6e5fdcbe5947620285d442b1carll   case 0x2AE: {        //tend.
186588943d02aa373f45c6e5fdcbe5947620285d442b1carll      /* The tend. is just a noop.  Do nothing */
186598943d02aa373f45c6e5fdcbe5947620285d442b1carll      UInt A = IFIELD( theInstr, 25, 1 );
186608943d02aa373f45c6e5fdcbe5947620285d442b1carll
18661b173774421d015736c2316b5e6e998e7de545a5cflorian      DIP("tend. %u\n", A);
186628943d02aa373f45c6e5fdcbe5947620285d442b1carll      break;
186638943d02aa373f45c6e5fdcbe5947620285d442b1carll   }
186648943d02aa373f45c6e5fdcbe5947620285d442b1carll
186658943d02aa373f45c6e5fdcbe5947620285d442b1carll   case 0x2EE: {        //tsr.
186668943d02aa373f45c6e5fdcbe5947620285d442b1carll      /* The tsr. is just a noop.  Do nothing */
186678943d02aa373f45c6e5fdcbe5947620285d442b1carll      UInt L = IFIELD( theInstr, 21, 1 );
186688943d02aa373f45c6e5fdcbe5947620285d442b1carll
18669b173774421d015736c2316b5e6e998e7de545a5cflorian      DIP("tsr. %u\n", L);
186708943d02aa373f45c6e5fdcbe5947620285d442b1carll      break;
186718943d02aa373f45c6e5fdcbe5947620285d442b1carll   }
186728943d02aa373f45c6e5fdcbe5947620285d442b1carll
186738943d02aa373f45c6e5fdcbe5947620285d442b1carll   case 0x2CE: {        //tcheck.
186748943d02aa373f45c6e5fdcbe5947620285d442b1carll      /* The tcheck. is just a noop.  Do nothing */
186758943d02aa373f45c6e5fdcbe5947620285d442b1carll      UInt BF = IFIELD( theInstr, 25, 1 );
186768943d02aa373f45c6e5fdcbe5947620285d442b1carll
18677b173774421d015736c2316b5e6e998e7de545a5cflorian      DIP("tcheck. %u\n", BF);
186788943d02aa373f45c6e5fdcbe5947620285d442b1carll      break;
186798943d02aa373f45c6e5fdcbe5947620285d442b1carll   }
186808943d02aa373f45c6e5fdcbe5947620285d442b1carll
186818943d02aa373f45c6e5fdcbe5947620285d442b1carll   case 0x30E: {        //tbortwc.
186828943d02aa373f45c6e5fdcbe5947620285d442b1carll      /* The tabortwc. is just a noop.  Do nothing */
186838943d02aa373f45c6e5fdcbe5947620285d442b1carll      UInt TO = IFIELD( theInstr, 25, 1 );
186848943d02aa373f45c6e5fdcbe5947620285d442b1carll      UInt RA = IFIELD( theInstr, 16, 5 );
186858943d02aa373f45c6e5fdcbe5947620285d442b1carll      UInt RB = IFIELD( theInstr, 11, 5 );
186868943d02aa373f45c6e5fdcbe5947620285d442b1carll
18687b173774421d015736c2316b5e6e998e7de545a5cflorian      DIP("tabortwc. %u,%u,%u\n", TO, RA, RB);
186888943d02aa373f45c6e5fdcbe5947620285d442b1carll      break;
186898943d02aa373f45c6e5fdcbe5947620285d442b1carll   }
186908943d02aa373f45c6e5fdcbe5947620285d442b1carll
186918943d02aa373f45c6e5fdcbe5947620285d442b1carll   case 0x32E: {        //tbortdc.
186928943d02aa373f45c6e5fdcbe5947620285d442b1carll      /* The tabortdc. is just a noop.  Do nothing */
186938943d02aa373f45c6e5fdcbe5947620285d442b1carll      UInt TO = IFIELD( theInstr, 25, 1 );
186948943d02aa373f45c6e5fdcbe5947620285d442b1carll      UInt RA = IFIELD( theInstr, 16, 5 );
186958943d02aa373f45c6e5fdcbe5947620285d442b1carll      UInt RB = IFIELD( theInstr, 11, 5 );
186968943d02aa373f45c6e5fdcbe5947620285d442b1carll
18697b173774421d015736c2316b5e6e998e7de545a5cflorian      DIP("tabortdc. %u,%u,%u\n", TO, RA, RB);
186988943d02aa373f45c6e5fdcbe5947620285d442b1carll      break;
186998943d02aa373f45c6e5fdcbe5947620285d442b1carll   }
187008943d02aa373f45c6e5fdcbe5947620285d442b1carll
187018943d02aa373f45c6e5fdcbe5947620285d442b1carll   case 0x34E: {        //tbortwci.
187028943d02aa373f45c6e5fdcbe5947620285d442b1carll      /* The tabortwci. is just a noop.  Do nothing */
187038943d02aa373f45c6e5fdcbe5947620285d442b1carll      UInt TO = IFIELD( theInstr, 25, 1 );
187048943d02aa373f45c6e5fdcbe5947620285d442b1carll      UInt RA = IFIELD( theInstr, 16, 5 );
187058943d02aa373f45c6e5fdcbe5947620285d442b1carll      UInt SI = IFIELD( theInstr, 11, 5 );
187068943d02aa373f45c6e5fdcbe5947620285d442b1carll
18707b173774421d015736c2316b5e6e998e7de545a5cflorian      DIP("tabortwci. %u,%u,%u\n", TO, RA, SI);
187088943d02aa373f45c6e5fdcbe5947620285d442b1carll      break;
187098943d02aa373f45c6e5fdcbe5947620285d442b1carll   }
187108943d02aa373f45c6e5fdcbe5947620285d442b1carll
187118943d02aa373f45c6e5fdcbe5947620285d442b1carll   case 0x36E: {        //tbortdci.
187128943d02aa373f45c6e5fdcbe5947620285d442b1carll      /* The tabortdci. is just a noop.  Do nothing */
187138943d02aa373f45c6e5fdcbe5947620285d442b1carll      UInt TO = IFIELD( theInstr, 25, 1 );
187148943d02aa373f45c6e5fdcbe5947620285d442b1carll      UInt RA = IFIELD( theInstr, 16, 5 );
187158943d02aa373f45c6e5fdcbe5947620285d442b1carll      UInt SI = IFIELD( theInstr, 11, 5 );
187168943d02aa373f45c6e5fdcbe5947620285d442b1carll
18717b173774421d015736c2316b5e6e998e7de545a5cflorian      DIP("tabortdci. %u,%u,%u\n", TO, RA, SI);
187188943d02aa373f45c6e5fdcbe5947620285d442b1carll      break;
187198943d02aa373f45c6e5fdcbe5947620285d442b1carll   }
187208943d02aa373f45c6e5fdcbe5947620285d442b1carll
187218943d02aa373f45c6e5fdcbe5947620285d442b1carll   case 0x38E: {        //tbort.
187228943d02aa373f45c6e5fdcbe5947620285d442b1carll      /* The tabort. is just a noop.  Do nothing */
187238943d02aa373f45c6e5fdcbe5947620285d442b1carll      UInt RA = IFIELD( theInstr, 16, 5 );
187248943d02aa373f45c6e5fdcbe5947620285d442b1carll
18725b173774421d015736c2316b5e6e998e7de545a5cflorian      DIP("tabort. %u\n", RA);
187268943d02aa373f45c6e5fdcbe5947620285d442b1carll      break;
187278943d02aa373f45c6e5fdcbe5947620285d442b1carll   }
187288943d02aa373f45c6e5fdcbe5947620285d442b1carll
18729fcce5f8ca9ad1fbb5939b8c94d7470b4d51a7387carll   case 0x3AE: {        //treclaim.
18730fcce5f8ca9ad1fbb5939b8c94d7470b4d51a7387carll      /* The treclaim. is just a noop.  Do nothing */
18731fcce5f8ca9ad1fbb5939b8c94d7470b4d51a7387carll      UInt RA = IFIELD( theInstr, 16, 5 );
18732fcce5f8ca9ad1fbb5939b8c94d7470b4d51a7387carll
18733b173774421d015736c2316b5e6e998e7de545a5cflorian      DIP("treclaim. %u\n", RA);
18734fcce5f8ca9ad1fbb5939b8c94d7470b4d51a7387carll      break;
18735fcce5f8ca9ad1fbb5939b8c94d7470b4d51a7387carll   }
18736fcce5f8ca9ad1fbb5939b8c94d7470b4d51a7387carll
18737fcce5f8ca9ad1fbb5939b8c94d7470b4d51a7387carll   case 0x3EE: {        //trechkpt.
18738fcce5f8ca9ad1fbb5939b8c94d7470b4d51a7387carll      /* The trechkpt. is just a noop.  Do nothing */
18739fcce5f8ca9ad1fbb5939b8c94d7470b4d51a7387carll      DIP("trechkpt.\n");
18740fcce5f8ca9ad1fbb5939b8c94d7470b4d51a7387carll      break;
18741fcce5f8ca9ad1fbb5939b8c94d7470b4d51a7387carll   }
18742fcce5f8ca9ad1fbb5939b8c94d7470b4d51a7387carll
187438943d02aa373f45c6e5fdcbe5947620285d442b1carll   default:
187448943d02aa373f45c6e5fdcbe5947620285d442b1carll      vex_printf("dis_transactional_memory(ppc): unrecognized instruction\n");
187458943d02aa373f45c6e5fdcbe5947620285d442b1carll      return False;
187468943d02aa373f45c6e5fdcbe5947620285d442b1carll   }
187478943d02aa373f45c6e5fdcbe5947620285d442b1carll
187488943d02aa373f45c6e5fdcbe5947620285d442b1carll   return True;
187498943d02aa373f45c6e5fdcbe5947620285d442b1carll}
187508943d02aa373f45c6e5fdcbe5947620285d442b1carll
18751a982c0503d8c0c6069ae453bfe70657bd2c134aecerion
1875266d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj/* The 0x3C primary opcode (VSX category) uses several different forms of
1875366d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj * extended opcodes:
1875466d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj *   o XX2-form:
1875566d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj *      - [10:2] (IBM notation [21:29])
1875666d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj *   o XX3-form variants:
1875766d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj *       - variant 1: [10:3] (IBM notation [21:28])
1875866d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj *       - variant 2: [9:3] (IBM notation [22:28])
1875966d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj *       - variant 3: [7:3] (IBM notation [24:28])
1876066d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj *   o XX-4 form:
1876166d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj *      - [10:6] (IBM notation [21:25])
1876266d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj *
1876366d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj * The XX2-form needs bit 0 masked from the standard extended opcode
1876466d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj * as returned by ifieldOPClo10; the XX3-form needs bits 0 and 1 masked;
1876566d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj * and the XX4-form needs bits 0, 1, and 2 masked.  Additionally, the
1876666d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj * XX4 and XX3 (variants 2 and 3) forms need certain bits masked on the
1876766d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj * front end since their encoding does not begin at bit 21 like the standard
1876866d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj * format.
1876966d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj *
1877066d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj * The get_VSX60_opc2() function uses the vsx_insn array below to obtain the
1877166d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj * secondary opcode for such VSX instructions.
1877266d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj *
1877366d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj*/
18774a982c0503d8c0c6069ae453bfe70657bd2c134aecerion
18775a982c0503d8c0c6069ae453bfe70657bd2c134aecerion
1877666d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardjstruct vsx_insn {
1877766d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj   UInt opcode;
1877855085f8680acc89d727e321f3b34cae1a8c4093aflorian   const HChar * name;
1877966d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj};
1878066d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj
1878166d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj//  ATTENTION:  Keep this array sorted on the opcocde!!!
1878266d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardjstatic struct vsx_insn vsx_all[] = {
187836c758b64a77c254065ab7450576bbd3a0b583595carll      { 0x0, "xsaddsp" },
187846c758b64a77c254065ab7450576bbd3a0b583595carll      { 0x4, "xsmaddasp" },
1878566d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj      { 0x8, "xxsldwi" },
187866c758b64a77c254065ab7450576bbd3a0b583595carll      { 0x14, "xsrsqrtesp" },
187876c758b64a77c254065ab7450576bbd3a0b583595carll      { 0x16, "xssqrtsp" },
1878866d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj      { 0x18, "xxsel" },
187896c758b64a77c254065ab7450576bbd3a0b583595carll      { 0x20, "xssubsp" },
187906c758b64a77c254065ab7450576bbd3a0b583595carll      { 0x24, "xsmaddmsp" },
1879166d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj      { 0x28, "xxpermdi" },
187926c758b64a77c254065ab7450576bbd3a0b583595carll      { 0x34, "xsresp" },
187936c758b64a77c254065ab7450576bbd3a0b583595carll      { 0x40, "xsmulsp" },
187946c758b64a77c254065ab7450576bbd3a0b583595carll      { 0x44, "xsmsubasp" },
1879566d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj      { 0x48, "xxmrghw" },
187966c758b64a77c254065ab7450576bbd3a0b583595carll      { 0x60, "xsdivsp" },
187976c758b64a77c254065ab7450576bbd3a0b583595carll      { 0x64, "xsmsubmsp" },
1879866d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj      { 0x80, "xsadddp" },
1879966d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj      { 0x84, "xsmaddadp" },
1880066d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj      { 0x8c, "xscmpudp" },
1880166d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj      { 0x90, "xscvdpuxws" },
1880266d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj      { 0x92, "xsrdpi" },
1880366d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj      { 0x94, "xsrsqrtedp" },
1880466d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj      { 0x96, "xssqrtdp" },
1880566d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj      { 0xa0, "xssubdp" },
1880666d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj      { 0xa4, "xsmaddmdp" },
1880766d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj      { 0xac, "xscmpodp" },
1880866d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj      { 0xb0, "xscvdpsxws" },
1880966d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj      { 0xb2, "xsrdpiz" },
1881066d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj      { 0xb4, "xsredp" },
1881166d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj      { 0xc0, "xsmuldp" },
1881266d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj      { 0xc4, "xsmsubadp" },
1881366d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj      { 0xc8, "xxmrglw" },
1881466d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj      { 0xd2, "xsrdpip" },
1881566d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj      { 0xd4, "xstsqrtdp" },
1881666d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj      { 0xd6, "xsrdpic" },
1881766d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj      { 0xe0, "xsdivdp" },
1881866d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj      { 0xe4, "xsmsubmdp" },
1881966d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj      { 0xf2, "xsrdpim" },
1882066d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj      { 0xf4, "xstdivdp" },
1882166d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj      { 0x100, "xvaddsp" },
1882266d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj      { 0x104, "xvmaddasp" },
1882366d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj      { 0x10c, "xvcmpeqsp" },
1882466d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj      { 0x110, "xvcvspuxws" },
1882566d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj      { 0x112, "xvrspi" },
1882666d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj      { 0x114, "xvrsqrtesp" },
1882766d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj      { 0x116, "xvsqrtsp" },
1882866d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj      { 0x120, "xvsubsp" },
1882966d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj      { 0x124, "xvmaddmsp" },
1883066d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj      { 0x12c, "xvcmpgtsp" },
1883166d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj      { 0x130, "xvcvspsxws" },
1883266d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj      { 0x132, "xvrspiz" },
1883366d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj      { 0x134, "xvresp" },
1883466d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj      { 0x140, "xvmulsp" },
1883566d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj      { 0x144, "xvmsubasp" },
1883666d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj      { 0x148, "xxspltw" },
1883766d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj      { 0x14c, "xvcmpgesp" },
1883866d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj      { 0x150, "xvcvuxwsp" },
1883966d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj      { 0x152, "xvrspip" },
1884066d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj      { 0x154, "xvtsqrtsp" },
1884166d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj      { 0x156, "xvrspic" },
1884266d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj      { 0x160, "xvdivsp" },
1884366d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj      { 0x164, "xvmsubmsp" },
1884466d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj      { 0x170, "xvcvsxwsp" },
1884566d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj      { 0x172, "xvrspim" },
1884666d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj      { 0x174, "xvtdivsp" },
1884766d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj      { 0x180, "xvadddp" },
1884866d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj      { 0x184, "xvmaddadp" },
1884966d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj      { 0x18c, "xvcmpeqdp" },
1885066d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj      { 0x190, "xvcvdpuxws" },
1885166d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj      { 0x192, "xvrdpi" },
1885266d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj      { 0x194, "xvrsqrtedp" },
1885366d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj      { 0x196, "xvsqrtdp" },
1885466d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj      { 0x1a0, "xvsubdp" },
1885566d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj      { 0x1a4, "xvmaddmdp" },
1885666d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj      { 0x1ac, "xvcmpgtdp" },
1885766d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj      { 0x1b0, "xvcvdpsxws" },
1885866d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj      { 0x1b2, "xvrdpiz" },
1885966d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj      { 0x1b4, "xvredp" },
1886066d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj      { 0x1c0, "xvmuldp" },
1886166d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj      { 0x1c4, "xvmsubadp" },
1886266d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj      { 0x1cc, "xvcmpgedp" },
1886366d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj      { 0x1d0, "xvcvuxwdp" },
1886466d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj      { 0x1d2, "xvrdpip" },
1886566d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj      { 0x1d4, "xvtsqrtdp" },
1886666d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj      { 0x1d6, "xvrdpic" },
1886766d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj      { 0x1e0, "xvdivdp" },
1886866d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj      { 0x1e4, "xvmsubmdp" },
1886966d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj      { 0x1f0, "xvcvsxwdp" },
1887066d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj      { 0x1f2, "xvrdpim" },
1887166d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj      { 0x1f4, "xvtdivdp" },
188726c758b64a77c254065ab7450576bbd3a0b583595carll      { 0x204, "xsnmaddasp" },
1887366d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj      { 0x208, "xxland" },
1887466d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj      { 0x212, "xscvdpsp" },
188750c74bb5aa3240f693df0568d578baabf0c376dc4carll      { 0x216, "xscvdpspn" },
188766c758b64a77c254065ab7450576bbd3a0b583595carll      { 0x224, "xsnmaddmsp" },
1887766d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj      { 0x228, "xxlandc" },
188786c758b64a77c254065ab7450576bbd3a0b583595carll      { 0x232, "xxrsp" },
188796c758b64a77c254065ab7450576bbd3a0b583595carll      { 0x244, "xsnmsubasp" },
188806c758b64a77c254065ab7450576bbd3a0b583595carll      { 0x248, "xxlor" },
188816c758b64a77c254065ab7450576bbd3a0b583595carll      { 0x250, "xscvuxdsp" },
188826c758b64a77c254065ab7450576bbd3a0b583595carll      { 0x264, "xsnmsubmsp" },
1888366d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj      { 0x268, "xxlxor" },
188846c758b64a77c254065ab7450576bbd3a0b583595carll      { 0x270, "xscvsxdsp" },
1888566d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj      { 0x280, "xsmaxdp" },
1888666d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj      { 0x284, "xsnmaddadp" },
1888766d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj      { 0x288, "xxlnor" },
1888866d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj      { 0x290, "xscvdpuxds" },
1888966d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj      { 0x292, "xscvspdp" },
188900c74bb5aa3240f693df0568d578baabf0c376dc4carll      { 0x296, "xscvspdpn" },
1889166d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj      { 0x2a0, "xsmindp" },
1889266d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj      { 0x2a4, "xsnmaddmdp" },
188936c758b64a77c254065ab7450576bbd3a0b583595carll      { 0x2a8, "xxlorc" },
1889466d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj      { 0x2b0, "xscvdpsxds" },
1889566d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj      { 0x2b2, "xsabsdp" },
1889666d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj      { 0x2c0, "xscpsgndp" },
1889766d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj      { 0x2c4, "xsnmsubadp" },
188986c758b64a77c254065ab7450576bbd3a0b583595carll      { 0x2c8, "xxlnand" },
1889966d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj      { 0x2d0, "xscvuxddp" },
1890066d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj      { 0x2d2, "xsnabsdp" },
1890166d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj      { 0x2e4, "xsnmsubmdp" },
189026c758b64a77c254065ab7450576bbd3a0b583595carll      { 0x2e8, "xxleqv" },
1890366d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj      { 0x2f0, "xscvsxddp" },
1890466d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj      { 0x2f2, "xsnegdp" },
1890566d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj      { 0x300, "xvmaxsp" },
1890666d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj      { 0x304, "xvnmaddasp" },
1890766d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj      { 0x30c, "xvcmpeqsp." },
1890866d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj      { 0x310, "xvcvspuxds" },
1890966d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj      { 0x312, "xvcvdpsp" },
1891066d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj      { 0x320, "xvminsp" },
1891166d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj      { 0x324, "xvnmaddmsp" },
1891266d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj      { 0x32c, "xvcmpgtsp." },
1891366d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj      { 0x330, "xvcvspsxds" },
1891466d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj      { 0x332, "xvabssp" },
1891566d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj      { 0x340, "xvcpsgnsp" },
1891666d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj      { 0x344, "xvnmsubasp" },
1891766d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj      { 0x34c, "xvcmpgesp." },
1891866d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj      { 0x350, "xvcvuxdsp" },
1891966d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj      { 0x352, "xvnabssp" },
1892066d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj      { 0x364, "xvnmsubmsp" },
1892166d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj      { 0x370, "xvcvsxdsp" },
1892266d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj      { 0x372, "xvnegsp" },
1892366d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj      { 0x380, "xvmaxdp" },
1892466d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj      { 0x384, "xvnmaddadp" },
1892566d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj      { 0x38c, "xvcmpeqdp." },
1892666d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj      { 0x390, "xvcvdpuxds" },
1892766d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj      { 0x392, "xvcvspdp" },
1892866d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj      { 0x3a0, "xvmindp" },
1892966d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj      { 0x3a4, "xvnmaddmdp" },
1893066d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj      { 0x3ac, "xvcmpgtdp." },
1893166d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj      { 0x3b0, "xvcvdpsxds" },
1893266d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj      { 0x3b2, "xvabsdp" },
1893366d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj      { 0x3c0, "xvcpsgndp" },
1893466d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj      { 0x3c4, "xvnmsubadp" },
1893566d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj      { 0x3cc, "xvcmpgedp." },
1893666d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj      { 0x3d0, "xvcvuxddp" },
1893766d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj      { 0x3d2, "xvnabsdp" },
1893866d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj      { 0x3e4, "xvnmsubmdp" },
1893966d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj      { 0x3f0, "xvcvsxddp" },
1894066d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj      { 0x3f2, "xvnegdp" }
1894166d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj};
189420c74bb5aa3240f693df0568d578baabf0c376dc4carll#define VSX_ALL_LEN (sizeof vsx_all / sizeof *vsx_all)
189430c74bb5aa3240f693df0568d578baabf0c376dc4carll
1894466d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj
1894566d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj// ATTENTION: This search function assumes vsx_all array is sorted.
1894666d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardjstatic Int findVSXextOpCode(UInt opcode)
1894766d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj{
1894866d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj   Int low, mid, high;
1894966d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj   low = 0;
1895066d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj   high = VSX_ALL_LEN - 1;
1895166d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj   while (low <= high) {
1895266d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj      mid = (low + high)/2;
1895366d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj      if (opcode < vsx_all[mid].opcode)
1895466d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj         high = mid - 1;
1895566d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj      else if (opcode > vsx_all[mid].opcode)
1895666d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj         low = mid + 1;
1895766d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj      else
1895866d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj         return mid;
1895966d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj   }
1896066d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj   return -1;
1896166d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj}
1896266d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj
1896366d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj
1896466d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj/* The full 10-bit extended opcode retrieved via ifieldOPClo10 is
189654aa412af1d8166cc11f39a6e721df49431d23618sewardj * passed, and we then try to match it up with one of the VSX forms
189664aa412af1d8166cc11f39a6e721df49431d23618sewardj * below.
1896766d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj */
1896866d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardjstatic UInt get_VSX60_opc2(UInt opc2_full)
1896966d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj{
1897066d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj#define XX2_MASK 0x000003FE
1897166d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj#define XX3_1_MASK 0x000003FC
1897266d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj#define XX3_2_MASK 0x000001FC
1897366d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj#define XX3_3_MASK 0x0000007C
189744aa412af1d8166cc11f39a6e721df49431d23618sewardj#define XX4_MASK 0x00000018
1897566d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj   Int ret;
1897666d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj   UInt vsxExtOpcode = 0;
1897766d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj
1897866d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj   if (( ret = findVSXextOpCode(opc2_full & XX2_MASK)) >= 0)
1897966d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj      vsxExtOpcode = vsx_all[ret].opcode;
1898066d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj   else if (( ret = findVSXextOpCode(opc2_full & XX3_1_MASK)) >= 0)
1898166d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj      vsxExtOpcode = vsx_all[ret].opcode;
1898266d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj   else if (( ret = findVSXextOpCode(opc2_full & XX3_2_MASK)) >= 0)
1898366d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj      vsxExtOpcode = vsx_all[ret].opcode;
1898466d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj   else if (( ret = findVSXextOpCode(opc2_full & XX3_3_MASK)) >= 0)
1898566d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj      vsxExtOpcode = vsx_all[ret].opcode;
1898666d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj   else if (( ret = findVSXextOpCode(opc2_full & XX4_MASK)) >= 0)
1898766d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj      vsxExtOpcode = vsx_all[ret].opcode;
1898866d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj
1898966d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj   return vsxExtOpcode;
1899066d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj}
18991a982c0503d8c0c6069ae453bfe70657bd2c134aecerion
18992a982c0503d8c0c6069ae453bfe70657bd2c134aecerion/*------------------------------------------------------------*/
18993a982c0503d8c0c6069ae453bfe70657bd2c134aecerion/*--- Disassemble a single instruction                     ---*/
18994a982c0503d8c0c6069ae453bfe70657bd2c134aecerion/*------------------------------------------------------------*/
18995a982c0503d8c0c6069ae453bfe70657bd2c134aecerion
18996a982c0503d8c0c6069ae453bfe70657bd2c134aecerion/* Disassemble a single instruction into IR.  The instruction
189979e6491ab55324b8e45e187b1e1e9632ac3cb3e27sewardj   is located in host memory at &guest_code[delta]. */
189989e6491ab55324b8e45e187b1e1e9632ac3cb3e27sewardj
189999e6491ab55324b8e45e187b1e1e9632ac3cb3e27sewardjstatic
190005b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerionDisResult disInstr_PPC_WRK (
19001beac530a718fcc646bc61fe60a86f599df54e1d7florian             Bool         (*resteerOkFn) ( /*opaque*/void*, Addr ),
19002984d9b164dd17f07e603c41fe1e506e641e57d18sewardj             Bool         resteerCisOk,
19003c716aea1cafe66ee431dc7d6909c98f18788a028sewardj             void*        callback_opaque,
190049e6491ab55324b8e45e187b1e1e9632ac3cb3e27sewardj             Long         delta64,
19005cacba8e675988fbf21b08feea1f317a9c896c053florian             const VexArchInfo* archinfo,
19006cacba8e675988fbf21b08feea1f317a9c896c053florian             const VexAbiInfo*  abiinfo,
19007442e51a26cf3bc7f243167a4ff3fbfb02206f6e6sewardj             Bool         sigill_diag
190089e6491ab55324b8e45e187b1e1e9632ac3cb3e27sewardj          )
19009a982c0503d8c0c6069ae453bfe70657bd2c134aecerion{
190109e6491ab55324b8e45e187b1e1e9632ac3cb3e27sewardj   UChar     opc1;
190119e6491ab55324b8e45e187b1e1e9632ac3cb3e27sewardj   UInt      opc2;
190129e6491ab55324b8e45e187b1e1e9632ac3cb3e27sewardj   DisResult dres;
19013a982c0503d8c0c6069ae453bfe70657bd2c134aecerion   UInt      theInstr;
19014d953ebb9b04cbad6891676df597bf0c542b1ec89cerion   IRType    ty = mode64 ? Ity_I64 : Ity_I32;
190155117ce116f47141cb23d1b49cc826e19323add97sewardj   Bool      allow_F  = False;
190165117ce116f47141cb23d1b49cc826e19323add97sewardj   Bool      allow_V  = False;
190175117ce116f47141cb23d1b49cc826e19323add97sewardj   Bool      allow_FX = False;
190185117ce116f47141cb23d1b49cc826e19323add97sewardj   Bool      allow_GX = False;
190194aa412af1d8166cc11f39a6e721df49431d23618sewardj   Bool      allow_VX = False;  // Equates to "supports Power ISA 2.06
19020c66d6fa5d9397f167b162483cf3419051cc01a80sewardj   Bool      allow_DFP = False;
190210c74bb5aa3240f693df0568d578baabf0c376dc4carll   Bool      allow_isa_2_07 = False;
190225117ce116f47141cb23d1b49cc826e19323add97sewardj   UInt      hwcaps = archinfo->hwcaps;
190235117ce116f47141cb23d1b49cc826e19323add97sewardj   Long      delta;
19024a982c0503d8c0c6069ae453bfe70657bd2c134aecerion
19025059601a7feb5aaf41876db86380679c3b202f5a3sewardj   /* What insn variants are we supporting today? */
190265117ce116f47141cb23d1b49cc826e19323add97sewardj   if (mode64) {
190275117ce116f47141cb23d1b49cc826e19323add97sewardj      allow_F  = True;
190285117ce116f47141cb23d1b49cc826e19323add97sewardj      allow_V  = (0 != (hwcaps & VEX_HWCAPS_PPC64_V));
190295117ce116f47141cb23d1b49cc826e19323add97sewardj      allow_FX = (0 != (hwcaps & VEX_HWCAPS_PPC64_FX));
190305117ce116f47141cb23d1b49cc826e19323add97sewardj      allow_GX = (0 != (hwcaps & VEX_HWCAPS_PPC64_GX));
1903166d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj      allow_VX = (0 != (hwcaps & VEX_HWCAPS_PPC64_VX));
19032c66d6fa5d9397f167b162483cf3419051cc01a80sewardj      allow_DFP = (0 != (hwcaps & VEX_HWCAPS_PPC64_DFP));
190330c74bb5aa3240f693df0568d578baabf0c376dc4carll      allow_isa_2_07 = (0 != (hwcaps & VEX_HWCAPS_PPC64_ISA2_07));
190345117ce116f47141cb23d1b49cc826e19323add97sewardj   } else {
190355117ce116f47141cb23d1b49cc826e19323add97sewardj      allow_F  = (0 != (hwcaps & VEX_HWCAPS_PPC32_F));
190365117ce116f47141cb23d1b49cc826e19323add97sewardj      allow_V  = (0 != (hwcaps & VEX_HWCAPS_PPC32_V));
190375117ce116f47141cb23d1b49cc826e19323add97sewardj      allow_FX = (0 != (hwcaps & VEX_HWCAPS_PPC32_FX));
190385117ce116f47141cb23d1b49cc826e19323add97sewardj      allow_GX = (0 != (hwcaps & VEX_HWCAPS_PPC32_GX));
1903966d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj      allow_VX = (0 != (hwcaps & VEX_HWCAPS_PPC32_VX));
19040c66d6fa5d9397f167b162483cf3419051cc01a80sewardj      allow_DFP = (0 != (hwcaps & VEX_HWCAPS_PPC32_DFP));
190410c74bb5aa3240f693df0568d578baabf0c376dc4carll      allow_isa_2_07 = (0 != (hwcaps & VEX_HWCAPS_PPC32_ISA2_07));
190425117ce116f47141cb23d1b49cc826e19323add97sewardj   }
19043059601a7feb5aaf41876db86380679c3b202f5a3sewardj
190449e6491ab55324b8e45e187b1e1e9632ac3cb3e27sewardj   /* The running delta */
190455117ce116f47141cb23d1b49cc826e19323add97sewardj   delta = (Long)mkSzAddr(ty, (ULong)delta64);
190469e6491ab55324b8e45e187b1e1e9632ac3cb3e27sewardj
190479e6491ab55324b8e45e187b1e1e9632ac3cb3e27sewardj   /* Set result defaults. */
190483dee849ec7c38746749065e67dc53b75daa7617dsewardj   dres.whatNext    = Dis_Continue;
190493dee849ec7c38746749065e67dc53b75daa7617dsewardj   dres.len         = 0;
190503dee849ec7c38746749065e67dc53b75daa7617dsewardj   dres.continueAt  = 0;
190513dee849ec7c38746749065e67dc53b75daa7617dsewardj   dres.jk_StopHere = Ijk_INVALID;
19052a982c0503d8c0c6069ae453bfe70657bd2c134aecerion
19053a982c0503d8c0c6069ae453bfe70657bd2c134aecerion   /* At least this is simple on PPC32: insns are all 4 bytes long, and
19054a982c0503d8c0c6069ae453bfe70657bd2c134aecerion      4-aligned.  So just fish the whole thing out of memory right now
19055a982c0503d8c0c6069ae453bfe70657bd2c134aecerion      and have done. */
190568462d113e3efeacceb304222dada8d85f748295aflorian   theInstr = getUIntPPCendianly( &guest_code[delta] );
19057a982c0503d8c0c6069ae453bfe70657bd2c134aecerion
190585117ce116f47141cb23d1b49cc826e19323add97sewardj   if (0) vex_printf("insn: 0x%x\n", theInstr);
19059f0de28cf1a762b0d6f74c93d3532c89a230673bbcerion
190601eb7e6b8f521143c9c4971b2cea36ade611c5da9sewardj   DIP("\t0x%llx:  ", (ULong)guest_CIA_curr_instr);
19061b51f0f4f33256638ed953156a2635aa739b232f1sewardj
19062ce02aa77bc02dbe225a068df0fb6b31faddedcdfsewardj   /* Spot "Special" instructions (see comment at top of file). */
190631eb7e6b8f521143c9c4971b2cea36ade611c5da9sewardj   {
190648462d113e3efeacceb304222dada8d85f748295aflorian      const UChar* code = guest_code + delta;
190651eb7e6b8f521143c9c4971b2cea36ade611c5da9sewardj      /* Spot the 16-byte preamble:
190661eb7e6b8f521143c9c4971b2cea36ade611c5da9sewardj         32-bit mode:
190672171afd42a0168b49b06dbe723b606046e902099sewardj            5400183E  rlwinm 0,0,3,0,31
190682171afd42a0168b49b06dbe723b606046e902099sewardj            5400683E  rlwinm 0,0,13,0,31
190692171afd42a0168b49b06dbe723b606046e902099sewardj            5400E83E  rlwinm 0,0,29,0,31
190702171afd42a0168b49b06dbe723b606046e902099sewardj            5400983E  rlwinm 0,0,19,0,31
190711eb7e6b8f521143c9c4971b2cea36ade611c5da9sewardj         64-bit mode:
190721eb7e6b8f521143c9c4971b2cea36ade611c5da9sewardj            78001800  rotldi 0,0,3
190731eb7e6b8f521143c9c4971b2cea36ade611c5da9sewardj            78006800  rotldi 0,0,13
190741eb7e6b8f521143c9c4971b2cea36ade611c5da9sewardj            7800E802  rotldi 0,0,61
190751eb7e6b8f521143c9c4971b2cea36ade611c5da9sewardj            78009802  rotldi 0,0,51
19076a982c0503d8c0c6069ae453bfe70657bd2c134aecerion      */
190772171afd42a0168b49b06dbe723b606046e902099sewardj      UInt word1 = mode64 ? 0x78001800 : 0x5400183E;
190782171afd42a0168b49b06dbe723b606046e902099sewardj      UInt word2 = mode64 ? 0x78006800 : 0x5400683E;
190792171afd42a0168b49b06dbe723b606046e902099sewardj      UInt word3 = mode64 ? 0x7800E802 : 0x5400E83E;
190802171afd42a0168b49b06dbe723b606046e902099sewardj      UInt word4 = mode64 ? 0x78009802 : 0x5400983E;
19081d2c19b4f340bd22b93538a25ca20e43a0d04dc09mjw      Bool is_special_preamble = False;
190821f5fe1fc3a37ca729925e8eec25aa1025b4a6cdbcarll      if (getUIntPPCendianly(code+ 0) == word1 &&
190831f5fe1fc3a37ca729925e8eec25aa1025b4a6cdbcarll          getUIntPPCendianly(code+ 4) == word2 &&
190841f5fe1fc3a37ca729925e8eec25aa1025b4a6cdbcarll          getUIntPPCendianly(code+ 8) == word3 &&
190851f5fe1fc3a37ca729925e8eec25aa1025b4a6cdbcarll          getUIntPPCendianly(code+12) == word4) {
19086d2c19b4f340bd22b93538a25ca20e43a0d04dc09mjw         is_special_preamble = True;
19087d2c19b4f340bd22b93538a25ca20e43a0d04dc09mjw      } else if (! mode64 &&
19088d2c19b4f340bd22b93538a25ca20e43a0d04dc09mjw                 getUIntPPCendianly(code+ 0) == 0x54001800 &&
19089d2c19b4f340bd22b93538a25ca20e43a0d04dc09mjw                 getUIntPPCendianly(code+ 4) == 0x54006800 &&
19090d2c19b4f340bd22b93538a25ca20e43a0d04dc09mjw                 getUIntPPCendianly(code+ 8) == 0x5400E800 &&
19091d2c19b4f340bd22b93538a25ca20e43a0d04dc09mjw                 getUIntPPCendianly(code+12) == 0x54009800) {
19092d2c19b4f340bd22b93538a25ca20e43a0d04dc09mjw         static Bool reported = False;
19093d2c19b4f340bd22b93538a25ca20e43a0d04dc09mjw         if (!reported) {
19094d2c19b4f340bd22b93538a25ca20e43a0d04dc09mjw            vex_printf("disInstr(ppc): old ppc32 instruction magic detected. Code might clobber r0.\n");
19095d2c19b4f340bd22b93538a25ca20e43a0d04dc09mjw            vex_printf("disInstr(ppc): source needs to be recompiled against latest valgrind.h.\n");
19096d2c19b4f340bd22b93538a25ca20e43a0d04dc09mjw            reported = True;
19097d2c19b4f340bd22b93538a25ca20e43a0d04dc09mjw         }
19098d2c19b4f340bd22b93538a25ca20e43a0d04dc09mjw         is_special_preamble = True;
19099d2c19b4f340bd22b93538a25ca20e43a0d04dc09mjw      }
19100d2c19b4f340bd22b93538a25ca20e43a0d04dc09mjw      if (is_special_preamble) {
19101ce02aa77bc02dbe225a068df0fb6b31faddedcdfsewardj         /* Got a "Special" instruction preamble.  Which one is it? */
191021f5fe1fc3a37ca729925e8eec25aa1025b4a6cdbcarll         if (getUIntPPCendianly(code+16) == 0x7C210B78 /* or 1,1,1 */) {
19103ce02aa77bc02dbe225a068df0fb6b31faddedcdfsewardj            /* %R3 = client_request ( %R4 ) */
19104ce02aa77bc02dbe225a068df0fb6b31faddedcdfsewardj            DIP("r3 = client_request ( %%r4 )\n");
19105ce02aa77bc02dbe225a068df0fb6b31faddedcdfsewardj            delta += 20;
191063dee849ec7c38746749065e67dc53b75daa7617dsewardj            putGST( PPC_GST_CIA, mkSzImm( ty, guest_CIA_bbstart + delta ));
191073dee849ec7c38746749065e67dc53b75daa7617dsewardj            dres.jk_StopHere = Ijk_ClientReq;
191083dee849ec7c38746749065e67dc53b75daa7617dsewardj            dres.whatNext    = Dis_StopHere;
19109ce02aa77bc02dbe225a068df0fb6b31faddedcdfsewardj            goto decode_success;
19110ce02aa77bc02dbe225a068df0fb6b31faddedcdfsewardj         }
19111ce02aa77bc02dbe225a068df0fb6b31faddedcdfsewardj         else
191121f5fe1fc3a37ca729925e8eec25aa1025b4a6cdbcarll         if (getUIntPPCendianly(code+16) == 0x7C421378 /* or 2,2,2 */) {
19113ce02aa77bc02dbe225a068df0fb6b31faddedcdfsewardj            /* %R3 = guest_NRADDR */
19114ce02aa77bc02dbe225a068df0fb6b31faddedcdfsewardj            DIP("r3 = guest_NRADDR\n");
19115ce02aa77bc02dbe225a068df0fb6b31faddedcdfsewardj            delta += 20;
19116ce02aa77bc02dbe225a068df0fb6b31faddedcdfsewardj            dres.len = 20;
19117ce02aa77bc02dbe225a068df0fb6b31faddedcdfsewardj            putIReg(3, IRExpr_Get( OFFB_NRADDR, ty ));
19118ce02aa77bc02dbe225a068df0fb6b31faddedcdfsewardj            goto decode_success;
19119ce02aa77bc02dbe225a068df0fb6b31faddedcdfsewardj         }
19120ce02aa77bc02dbe225a068df0fb6b31faddedcdfsewardj         else
191211f5fe1fc3a37ca729925e8eec25aa1025b4a6cdbcarll         if (getUIntPPCendianly(code+16) == 0x7C631B78 /* or 3,3,3 */) {
19122ce02aa77bc02dbe225a068df0fb6b31faddedcdfsewardj            delta += 20;
191231f5fe1fc3a37ca729925e8eec25aa1025b4a6cdbcarll            if (host_endness == VexEndnessLE) {
191241f5fe1fc3a37ca729925e8eec25aa1025b4a6cdbcarll                /*  branch-and-link-to-noredir %R12 */
191251f5fe1fc3a37ca729925e8eec25aa1025b4a6cdbcarll                DIP("branch-and-link-to-noredir r12\n");
191261f5fe1fc3a37ca729925e8eec25aa1025b4a6cdbcarll                putGST( PPC_GST_LR,
191271f5fe1fc3a37ca729925e8eec25aa1025b4a6cdbcarll                        mkSzImm(ty, guest_CIA_bbstart + (Long)delta) );
191281f5fe1fc3a37ca729925e8eec25aa1025b4a6cdbcarll                putGST( PPC_GST_CIA, getIReg(12));
191291f5fe1fc3a37ca729925e8eec25aa1025b4a6cdbcarll            } else {
191301f5fe1fc3a37ca729925e8eec25aa1025b4a6cdbcarll                /*  branch-and-link-to-noredir %R11 */
191311f5fe1fc3a37ca729925e8eec25aa1025b4a6cdbcarll                DIP("branch-and-link-to-noredir r11\n");
191321f5fe1fc3a37ca729925e8eec25aa1025b4a6cdbcarll                putGST( PPC_GST_LR,
191331f5fe1fc3a37ca729925e8eec25aa1025b4a6cdbcarll                        mkSzImm(ty, guest_CIA_bbstart + (Long)delta) );
191341f5fe1fc3a37ca729925e8eec25aa1025b4a6cdbcarll                putGST( PPC_GST_CIA, getIReg(11));
191351f5fe1fc3a37ca729925e8eec25aa1025b4a6cdbcarll            }
191363dee849ec7c38746749065e67dc53b75daa7617dsewardj            dres.jk_StopHere = Ijk_NoRedir;
191373dee849ec7c38746749065e67dc53b75daa7617dsewardj            dres.whatNext    = Dis_StopHere;
19138ce02aa77bc02dbe225a068df0fb6b31faddedcdfsewardj            goto decode_success;
19139ce02aa77bc02dbe225a068df0fb6b31faddedcdfsewardj         }
191405ff11ddafe3e0080711657a1cf581e1a64dbf117sewardj         else
191411f5fe1fc3a37ca729925e8eec25aa1025b4a6cdbcarll         if (getUIntPPCendianly(code+16) == 0x7C842378 /* or 4,4,4 */) {
191425ff11ddafe3e0080711657a1cf581e1a64dbf117sewardj            /* %R3 = guest_NRADDR_GPR2 */
191435ff11ddafe3e0080711657a1cf581e1a64dbf117sewardj            DIP("r3 = guest_NRADDR_GPR2\n");
191445ff11ddafe3e0080711657a1cf581e1a64dbf117sewardj            delta += 20;
191455ff11ddafe3e0080711657a1cf581e1a64dbf117sewardj            dres.len = 20;
19146aca070a5b3418a6a9b01e3c57a7eb0fbb5050908sewardj            putIReg(3, IRExpr_Get( OFFB_NRADDR_GPR2, ty ));
191475ff11ddafe3e0080711657a1cf581e1a64dbf117sewardj            goto decode_success;
191485ff11ddafe3e0080711657a1cf581e1a64dbf117sewardj         }
191492245ce9e834193d49261b8a433b4a0bd128c878eflorian         else
191501f5fe1fc3a37ca729925e8eec25aa1025b4a6cdbcarll         if (getUIntPPCendianly(code+16) == 0x7CA52B78 /* or 5,5,5 */) {
191512245ce9e834193d49261b8a433b4a0bd128c878eflorian            DIP("IR injection\n");
191521f5fe1fc3a37ca729925e8eec25aa1025b4a6cdbcarll            if (host_endness == VexEndnessBE)
191531f5fe1fc3a37ca729925e8eec25aa1025b4a6cdbcarll               vex_inject_ir(irsb, Iend_BE);
191541f5fe1fc3a37ca729925e8eec25aa1025b4a6cdbcarll            else
191551f5fe1fc3a37ca729925e8eec25aa1025b4a6cdbcarll               vex_inject_ir(irsb, Iend_LE);
191562245ce9e834193d49261b8a433b4a0bd128c878eflorian
191572245ce9e834193d49261b8a433b4a0bd128c878eflorian            delta += 20;
191582245ce9e834193d49261b8a433b4a0bd128c878eflorian            dres.len = 20;
191592245ce9e834193d49261b8a433b4a0bd128c878eflorian
191602245ce9e834193d49261b8a433b4a0bd128c878eflorian            // Invalidate the current insn. The reason is that the IRop we're
191612245ce9e834193d49261b8a433b4a0bd128c878eflorian            // injecting here can change. In which case the translation has to
191622245ce9e834193d49261b8a433b4a0bd128c878eflorian            // be redone. For ease of handling, we simply invalidate all the
191632245ce9e834193d49261b8a433b4a0bd128c878eflorian            // time.
191649e23873d8f6365b9bf64b767b76ff973c014d693florian
1916505f5e0172384dd2983fb16fbb7deebd74d71cd35sewardj            stmt(IRStmt_Put(OFFB_CMSTART, mkSzImm(ty, guest_CIA_curr_instr)));
1916605f5e0172384dd2983fb16fbb7deebd74d71cd35sewardj            stmt(IRStmt_Put(OFFB_CMLEN,   mkSzImm(ty, 20)));
191672245ce9e834193d49261b8a433b4a0bd128c878eflorian
191682245ce9e834193d49261b8a433b4a0bd128c878eflorian            putGST( PPC_GST_CIA, mkSzImm( ty, guest_CIA_bbstart + delta ));
191692245ce9e834193d49261b8a433b4a0bd128c878eflorian            dres.whatNext    = Dis_StopHere;
1917005f5e0172384dd2983fb16fbb7deebd74d71cd35sewardj            dres.jk_StopHere = Ijk_InvalICache;
191712245ce9e834193d49261b8a433b4a0bd128c878eflorian            goto decode_success;
191722245ce9e834193d49261b8a433b4a0bd128c878eflorian         }
19173ce02aa77bc02dbe225a068df0fb6b31faddedcdfsewardj         /* We don't know what it is.  Set opc1/opc2 so decode_failure
19174ce02aa77bc02dbe225a068df0fb6b31faddedcdfsewardj            can print the insn following the Special-insn preamble. */
191751f5fe1fc3a37ca729925e8eec25aa1025b4a6cdbcarll         theInstr = getUIntPPCendianly(code+16);
19176ce02aa77bc02dbe225a068df0fb6b31faddedcdfsewardj         opc1     = ifieldOPC(theInstr);
19177ce02aa77bc02dbe225a068df0fb6b31faddedcdfsewardj         opc2     = ifieldOPClo10(theInstr);
19178ce02aa77bc02dbe225a068df0fb6b31faddedcdfsewardj         goto decode_failure;
19179ce02aa77bc02dbe225a068df0fb6b31faddedcdfsewardj         /*NOTREACHED*/
19180a982c0503d8c0c6069ae453bfe70657bd2c134aecerion      }
19181a982c0503d8c0c6069ae453bfe70657bd2c134aecerion   }
19182a982c0503d8c0c6069ae453bfe70657bd2c134aecerion
1918376de5cf615380b23b4b5bcced6541233cd4a93a0cerion   opc1 = ifieldOPC(theInstr);
19184b51f0f4f33256638ed953156a2635aa739b232f1sewardj   opc2 = ifieldOPClo10(theInstr);
19185a982c0503d8c0c6069ae453bfe70657bd2c134aecerion
19186a982c0503d8c0c6069ae453bfe70657bd2c134aecerion   // Note: all 'reserved' bits must be cleared, else invalid
19187a982c0503d8c0c6069ae453bfe70657bd2c134aecerion   switch (opc1) {
19188a982c0503d8c0c6069ae453bfe70657bd2c134aecerion
19189a982c0503d8c0c6069ae453bfe70657bd2c134aecerion   /* Integer Arithmetic Instructions */
19190a982c0503d8c0c6069ae453bfe70657bd2c134aecerion   case 0x0C: case 0x0D: case 0x0E:  // addic, addic., addi
19191a982c0503d8c0c6069ae453bfe70657bd2c134aecerion   case 0x0F: case 0x07: case 0x08:  // addis, mulli,  subfic
19192a982c0503d8c0c6069ae453bfe70657bd2c134aecerion      if (dis_int_arith( theInstr )) goto decode_success;
19193a982c0503d8c0c6069ae453bfe70657bd2c134aecerion      goto decode_failure;
19194a982c0503d8c0c6069ae453bfe70657bd2c134aecerion
19195a982c0503d8c0c6069ae453bfe70657bd2c134aecerion   /* Integer Compare Instructions */
19196a982c0503d8c0c6069ae453bfe70657bd2c134aecerion   case 0x0B: case 0x0A: // cmpi, cmpli
19197a982c0503d8c0c6069ae453bfe70657bd2c134aecerion      if (dis_int_cmp( theInstr )) goto decode_success;
19198a982c0503d8c0c6069ae453bfe70657bd2c134aecerion      goto decode_failure;
19199a982c0503d8c0c6069ae453bfe70657bd2c134aecerion
19200a982c0503d8c0c6069ae453bfe70657bd2c134aecerion   /* Integer Logical Instructions */
19201a982c0503d8c0c6069ae453bfe70657bd2c134aecerion   case 0x1C: case 0x1D: case 0x18: // andi., andis., ori
19202a982c0503d8c0c6069ae453bfe70657bd2c134aecerion   case 0x19: case 0x1A: case 0x1B: // oris,  xori,   xoris
19203a982c0503d8c0c6069ae453bfe70657bd2c134aecerion      if (dis_int_logic( theInstr )) goto decode_success;
19204a982c0503d8c0c6069ae453bfe70657bd2c134aecerion      goto decode_failure;
19205a982c0503d8c0c6069ae453bfe70657bd2c134aecerion
19206a982c0503d8c0c6069ae453bfe70657bd2c134aecerion   /* Integer Rotate Instructions */
19207a982c0503d8c0c6069ae453bfe70657bd2c134aecerion   case 0x14: case 0x15:  case 0x17: // rlwimi, rlwinm, rlwnm
19208a982c0503d8c0c6069ae453bfe70657bd2c134aecerion      if (dis_int_rot( theInstr )) goto decode_success;
19209a982c0503d8c0c6069ae453bfe70657bd2c134aecerion      goto decode_failure;
19210a982c0503d8c0c6069ae453bfe70657bd2c134aecerion
19211f0de28cf1a762b0d6f74c93d3532c89a230673bbcerion   /* 64bit Integer Rotate Instructions */
19212f0de28cf1a762b0d6f74c93d3532c89a230673bbcerion   case 0x1E: // rldcl, rldcr, rldic, rldicl, rldicr, rldimi
19213bb3f40144f5e72dfbba740d4b2f090b4a91c3876carll      if (!mode64) goto decode_failure;
19214f0de28cf1a762b0d6f74c93d3532c89a230673bbcerion      if (dis_int_rot( theInstr )) goto decode_success;
19215f0de28cf1a762b0d6f74c93d3532c89a230673bbcerion      goto decode_failure;
19216f0de28cf1a762b0d6f74c93d3532c89a230673bbcerion
19217a982c0503d8c0c6069ae453bfe70657bd2c134aecerion   /* Integer Load Instructions */
19218a982c0503d8c0c6069ae453bfe70657bd2c134aecerion   case 0x22: case 0x23: case 0x2A: // lbz,  lbzu, lha
19219a982c0503d8c0c6069ae453bfe70657bd2c134aecerion   case 0x2B: case 0x28: case 0x29: // lhau, lhz,  lhzu
19220a982c0503d8c0c6069ae453bfe70657bd2c134aecerion   case 0x20: case 0x21:            // lwz,  lwzu
19221a982c0503d8c0c6069ae453bfe70657bd2c134aecerion      if (dis_int_load( theInstr )) goto decode_success;
19222a982c0503d8c0c6069ae453bfe70657bd2c134aecerion      goto decode_failure;
19223a982c0503d8c0c6069ae453bfe70657bd2c134aecerion
19224a982c0503d8c0c6069ae453bfe70657bd2c134aecerion   /* Integer Store Instructions */
19225a982c0503d8c0c6069ae453bfe70657bd2c134aecerion   case 0x26: case 0x27: case 0x2C: // stb,  stbu, sth
19226a982c0503d8c0c6069ae453bfe70657bd2c134aecerion   case 0x2D: case 0x24: case 0x25: // sthu, stw,  stwu
19227dd40fdf58cc8a6fe9466c4f00bdfc9fe9bf00449sewardj      if (dis_int_store( theInstr, abiinfo )) goto decode_success;
19228a982c0503d8c0c6069ae453bfe70657bd2c134aecerion      goto decode_failure;
19229a982c0503d8c0c6069ae453bfe70657bd2c134aecerion
192307787af415a9104b601c2f0ce5b56749e4fd86691sewardj   /* Integer Load and Store Multiple Instructions */
192317787af415a9104b601c2f0ce5b56749e4fd86691sewardj   case 0x2E: case 0x2F: // lmw, stmw
192327787af415a9104b601c2f0ce5b56749e4fd86691sewardj      if (dis_int_ldst_mult( theInstr )) goto decode_success;
192337787af415a9104b601c2f0ce5b56749e4fd86691sewardj      goto decode_failure;
19234a982c0503d8c0c6069ae453bfe70657bd2c134aecerion
19235a982c0503d8c0c6069ae453bfe70657bd2c134aecerion   /* Branch Instructions */
19236a982c0503d8c0c6069ae453bfe70657bd2c134aecerion   case 0x12: case 0x10: // b, bc
19237dd40fdf58cc8a6fe9466c4f00bdfc9fe9bf00449sewardj      if (dis_branch(theInstr, abiinfo, &dres,
19238aca070a5b3418a6a9b01e3c57a7eb0fbb5050908sewardj                               resteerOkFn, callback_opaque))
19239c716aea1cafe66ee431dc7d6909c98f18788a028sewardj         goto decode_success;
19240a982c0503d8c0c6069ae453bfe70657bd2c134aecerion      goto decode_failure;
19241a982c0503d8c0c6069ae453bfe70657bd2c134aecerion
19242a982c0503d8c0c6069ae453bfe70657bd2c134aecerion   /* System Linkage Instructions */
19243a982c0503d8c0c6069ae453bfe70657bd2c134aecerion   case 0x11: // sc
19244dd40fdf58cc8a6fe9466c4f00bdfc9fe9bf00449sewardj      if (dis_syslink(theInstr, abiinfo, &dres)) goto decode_success;
19245a982c0503d8c0c6069ae453bfe70657bd2c134aecerion      goto decode_failure;
19246a982c0503d8c0c6069ae453bfe70657bd2c134aecerion
19247334870db22c2eadcaaa48ef8e47337134d150efdsewardj   /* Trap Instructions */
19248bb3f40144f5e72dfbba740d4b2f090b4a91c3876carll   case 0x02:    // tdi
19249bb3f40144f5e72dfbba740d4b2f090b4a91c3876carll      if (!mode64) goto decode_failure;
19250bb3f40144f5e72dfbba740d4b2f090b4a91c3876carll      if (dis_trapi(theInstr, &dres)) goto decode_success;
19251bb3f40144f5e72dfbba740d4b2f090b4a91c3876carll      goto decode_failure;
19252bb3f40144f5e72dfbba740d4b2f090b4a91c3876carll
19253bb3f40144f5e72dfbba740d4b2f090b4a91c3876carll   case 0x03:   // twi
19254334870db22c2eadcaaa48ef8e47337134d150efdsewardj      if (dis_trapi(theInstr, &dres)) goto decode_success;
19255334870db22c2eadcaaa48ef8e47337134d150efdsewardj      goto decode_failure;
19256a982c0503d8c0c6069ae453bfe70657bd2c134aecerion
19257a982c0503d8c0c6069ae453bfe70657bd2c134aecerion   /* Floating Point Load Instructions */
19258a982c0503d8c0c6069ae453bfe70657bd2c134aecerion   case 0x30: case 0x31: case 0x32: // lfs, lfsu, lfd
19259a982c0503d8c0c6069ae453bfe70657bd2c134aecerion   case 0x33:                       // lfdu
192605117ce116f47141cb23d1b49cc826e19323add97sewardj      if (!allow_F) goto decode_noF;
19261a982c0503d8c0c6069ae453bfe70657bd2c134aecerion      if (dis_fp_load( theInstr )) goto decode_success;
19262a982c0503d8c0c6069ae453bfe70657bd2c134aecerion      goto decode_failure;
19263a982c0503d8c0c6069ae453bfe70657bd2c134aecerion
19264a982c0503d8c0c6069ae453bfe70657bd2c134aecerion   /* Floating Point Store Instructions */
19265a982c0503d8c0c6069ae453bfe70657bd2c134aecerion   case 0x34: case 0x35: case 0x36: // stfsx, stfsux, stfdx
19266a982c0503d8c0c6069ae453bfe70657bd2c134aecerion   case 0x37:                       // stfdux
192675117ce116f47141cb23d1b49cc826e19323add97sewardj      if (!allow_F) goto decode_noF;
19268a982c0503d8c0c6069ae453bfe70657bd2c134aecerion      if (dis_fp_store( theInstr )) goto decode_success;
19269a982c0503d8c0c6069ae453bfe70657bd2c134aecerion      goto decode_failure;
19270a982c0503d8c0c6069ae453bfe70657bd2c134aecerion
192717e84630580f89c1022dde97007bffbf6aef81814sewardj      /* Floating Point Load Double Pair Instructions */
192727e84630580f89c1022dde97007bffbf6aef81814sewardj   case 0x39: case 0x3D:
192737e84630580f89c1022dde97007bffbf6aef81814sewardj      if (!allow_F) goto decode_noF;
192747e84630580f89c1022dde97007bffbf6aef81814sewardj      if (dis_fp_pair( theInstr )) goto decode_success;
192757e84630580f89c1022dde97007bffbf6aef81814sewardj      goto decode_failure;
192767e84630580f89c1022dde97007bffbf6aef81814sewardj
1927778850ae9874a90ea625fcee1fd4c359375b7b538carll   /* 128-bit Integer Load */
1927878850ae9874a90ea625fcee1fd4c359375b7b538carll   case 0x38:  // lq
1927978850ae9874a90ea625fcee1fd4c359375b7b538carll      if (dis_int_load( theInstr )) goto decode_success;
1928078850ae9874a90ea625fcee1fd4c359375b7b538carll      goto decode_failure;
1928178850ae9874a90ea625fcee1fd4c359375b7b538carll
19282f0de28cf1a762b0d6f74c93d3532c89a230673bbcerion   /* 64bit Integer Loads */
19283f0de28cf1a762b0d6f74c93d3532c89a230673bbcerion   case 0x3A:  // ld, ldu, lwa
19284f0de28cf1a762b0d6f74c93d3532c89a230673bbcerion      if (!mode64) goto decode_failure;
19285f0de28cf1a762b0d6f74c93d3532c89a230673bbcerion      if (dis_int_load( theInstr )) goto decode_success;
19286f0de28cf1a762b0d6f74c93d3532c89a230673bbcerion      goto decode_failure;
19287f0de28cf1a762b0d6f74c93d3532c89a230673bbcerion
19288e14bb9f862843c6b804097c124961b5567ded4f1sewardj   case 0x3B:
192895117ce116f47141cb23d1b49cc826e19323add97sewardj      if (!allow_F) goto decode_noF;
1929066d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj      opc2 = ifieldOPClo10(theInstr);
19291c6bbd470e9bd9898b84959227a406d3972d95f3bsewardj
1929266d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj      switch (opc2) {
19293c6bbd470e9bd9898b84959227a406d3972d95f3bsewardj         case 0x2:    // dadd - DFP Add
19294c6bbd470e9bd9898b84959227a406d3972d95f3bsewardj         case 0x202:  // dsub - DFP Subtract
19295c6bbd470e9bd9898b84959227a406d3972d95f3bsewardj         case 0x22:   // dmul - DFP Mult
19296c6bbd470e9bd9898b84959227a406d3972d95f3bsewardj         case 0x222:  // ddiv - DFP Divide
19297c66d6fa5d9397f167b162483cf3419051cc01a80sewardj            if (!allow_DFP) goto decode_noDFP;
19298c6bbd470e9bd9898b84959227a406d3972d95f3bsewardj            if (dis_dfp_arith( theInstr ))
19299c6bbd470e9bd9898b84959227a406d3972d95f3bsewardj               goto decode_success;
19300cdc376dcb5a4560b0a35d4abcb2146c499756f0dsewardj         case 0x82:   // dcmpo, DFP comparison ordered instruction
19301cdc376dcb5a4560b0a35d4abcb2146c499756f0dsewardj         case 0x282:  // dcmpu, DFP comparison unordered instruction
193020c4e9e8eef3824b085973cd6e2b1b39a1fd6062ecarll            if (!allow_DFP) goto decode_noDFP;
19303cdc376dcb5a4560b0a35d4abcb2146c499756f0dsewardj            if (dis_dfp_compare( theInstr ) )
19304cdc376dcb5a4560b0a35d4abcb2146c499756f0dsewardj               goto decode_success;
19305cdc376dcb5a4560b0a35d4abcb2146c499756f0dsewardj            goto decode_failure;
1930626217b09205cc1801b842ba5ba8f0d83aabca1b4sewardj         case 0x102: // dctdp  - DFP convert to DFP long
1930726217b09205cc1801b842ba5ba8f0d83aabca1b4sewardj         case 0x302: // drsp   - DFP round to dfp short
1930826217b09205cc1801b842ba5ba8f0d83aabca1b4sewardj         case 0x122: // dctfix - DFP convert to fixed
193090c4e9e8eef3824b085973cd6e2b1b39a1fd6062ecarll            if (!allow_DFP) goto decode_noDFP;
1931026217b09205cc1801b842ba5ba8f0d83aabca1b4sewardj            if (dis_dfp_fmt_conv( theInstr ))
1931126217b09205cc1801b842ba5ba8f0d83aabca1b4sewardj               goto decode_success;
1931226217b09205cc1801b842ba5ba8f0d83aabca1b4sewardj            goto decode_failure;
1931326217b09205cc1801b842ba5ba8f0d83aabca1b4sewardj         case 0x322: // POWER 7 inst, dcffix - DFP convert from fixed
1931426217b09205cc1801b842ba5ba8f0d83aabca1b4sewardj            if (!allow_VX)
1931526217b09205cc1801b842ba5ba8f0d83aabca1b4sewardj               goto decode_failure;
19316c7910f428436d86d2b18924a8acbdaab49b27e49florian            if (!allow_DFP) goto decode_noDFP;
1931726217b09205cc1801b842ba5ba8f0d83aabca1b4sewardj            if (dis_dfp_fmt_conv( theInstr ))
1931826217b09205cc1801b842ba5ba8f0d83aabca1b4sewardj               goto decode_success;
1931926217b09205cc1801b842ba5ba8f0d83aabca1b4sewardj            goto decode_failure;
193204c96e61dd85c172b999d6afc88ce6640aeba9962sewardj         case 0x2A2: // dtstsf - DFP number of significant digits
193210c4e9e8eef3824b085973cd6e2b1b39a1fd6062ecarll            if (!allow_DFP) goto decode_noDFP;
193224c96e61dd85c172b999d6afc88ce6640aeba9962sewardj            if (dis_dfp_significant_digits(theInstr))
193234c96e61dd85c172b999d6afc88ce6640aeba9962sewardj               goto decode_success;
193244c96e61dd85c172b999d6afc88ce6640aeba9962sewardj            goto decode_failure;
193254c96e61dd85c172b999d6afc88ce6640aeba9962sewardj         case 0x142: // ddedpd   DFP Decode DPD to BCD
193264c96e61dd85c172b999d6afc88ce6640aeba9962sewardj         case 0x342: // denbcd   DFP Encode BCD to DPD
193270c4e9e8eef3824b085973cd6e2b1b39a1fd6062ecarll            if (!allow_DFP) goto decode_noDFP;
193284c96e61dd85c172b999d6afc88ce6640aeba9962sewardj            if (dis_dfp_bcd(theInstr))
193294c96e61dd85c172b999d6afc88ce6640aeba9962sewardj               goto decode_success;
193304c96e61dd85c172b999d6afc88ce6640aeba9962sewardj            goto decode_failure;
19331cdc376dcb5a4560b0a35d4abcb2146c499756f0dsewardj         case 0x162:  // dxex - Extract exponent
19332cdc376dcb5a4560b0a35d4abcb2146c499756f0dsewardj         case 0x362:  // diex - Insert exponent
193330c4e9e8eef3824b085973cd6e2b1b39a1fd6062ecarll            if (!allow_DFP) goto decode_noDFP;
19334cdc376dcb5a4560b0a35d4abcb2146c499756f0dsewardj            if (dis_dfp_extract_insert( theInstr ) )
19335cdc376dcb5a4560b0a35d4abcb2146c499756f0dsewardj               goto decode_success;
19336cdc376dcb5a4560b0a35d4abcb2146c499756f0dsewardj            goto decode_failure;
193374aa412af1d8166cc11f39a6e721df49431d23618sewardj         case 0x3CE: // fcfidus (implemented as native insn)
1933866d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj            if (!allow_VX)
1933966d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj               goto decode_noVX;
1934066d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj            if (dis_fp_round( theInstr ))
1934166d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj               goto decode_success;
1934266d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj            goto decode_failure;
1934366d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj         case 0x34E: // fcfids
1934466d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj            if (dis_fp_round( theInstr ))
1934566d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj               goto decode_success;
1934666d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj            goto decode_failure;
1934766d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj      }
1934866d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj
1934926217b09205cc1801b842ba5ba8f0d83aabca1b4sewardj      opc2 = ifieldOPClo9( theInstr );
1935026217b09205cc1801b842ba5ba8f0d83aabca1b4sewardj      switch (opc2) {
1935126217b09205cc1801b842ba5ba8f0d83aabca1b4sewardj      case 0x42: // dscli, DFP shift left
1935226217b09205cc1801b842ba5ba8f0d83aabca1b4sewardj      case 0x62: // dscri, DFP shift right
193530c4e9e8eef3824b085973cd6e2b1b39a1fd6062ecarll         if (!allow_DFP) goto decode_noDFP;
1935426217b09205cc1801b842ba5ba8f0d83aabca1b4sewardj         if (dis_dfp_shift( theInstr ))
1935526217b09205cc1801b842ba5ba8f0d83aabca1b4sewardj            goto decode_success;
1935626217b09205cc1801b842ba5ba8f0d83aabca1b4sewardj         goto decode_failure;
193575eff1c502e995d1f9668cc9def72d5db59f21b13sewardj      case 0xc2:  // dtstdc, DFP test data class
193585eff1c502e995d1f9668cc9def72d5db59f21b13sewardj      case 0xe2:  // dtstdg, DFP test data group
193590c4e9e8eef3824b085973cd6e2b1b39a1fd6062ecarll         if (!allow_DFP) goto decode_noDFP;
193605eff1c502e995d1f9668cc9def72d5db59f21b13sewardj         if (dis_dfp_class_test( theInstr ))
193615eff1c502e995d1f9668cc9def72d5db59f21b13sewardj            goto decode_success;
193625eff1c502e995d1f9668cc9def72d5db59f21b13sewardj         goto decode_failure;
1936326217b09205cc1801b842ba5ba8f0d83aabca1b4sewardj      }
1936426217b09205cc1801b842ba5ba8f0d83aabca1b4sewardj
19365cdc376dcb5a4560b0a35d4abcb2146c499756f0dsewardj      opc2 = ifieldOPClo8( theInstr );
19366cdc376dcb5a4560b0a35d4abcb2146c499756f0dsewardj      switch (opc2) {
19367cdc376dcb5a4560b0a35d4abcb2146c499756f0dsewardj      case 0x3:   // dqua  - DFP Quantize
19368cdc376dcb5a4560b0a35d4abcb2146c499756f0dsewardj      case 0x23:  // drrnd - DFP Reround
19369cdc376dcb5a4560b0a35d4abcb2146c499756f0dsewardj      case 0x43:  // dquai - DFP Quantize immediate
193700c4e9e8eef3824b085973cd6e2b1b39a1fd6062ecarll         if (!allow_DFP) goto decode_noDFP;
19371cdc376dcb5a4560b0a35d4abcb2146c499756f0dsewardj         if (dis_dfp_quantize_sig_rrnd( theInstr ) )
19372cdc376dcb5a4560b0a35d4abcb2146c499756f0dsewardj            goto decode_success;
19373cdc376dcb5a4560b0a35d4abcb2146c499756f0dsewardj         goto decode_failure;
193745eff1c502e995d1f9668cc9def72d5db59f21b13sewardj      case 0xA2: // dtstex - DFP Test exponent
193750c4e9e8eef3824b085973cd6e2b1b39a1fd6062ecarll         if (!allow_DFP) goto decode_noDFP;
193765eff1c502e995d1f9668cc9def72d5db59f21b13sewardj         if (dis_dfp_exponent_test( theInstr ) )
193775eff1c502e995d1f9668cc9def72d5db59f21b13sewardj            goto decode_success;
193785eff1c502e995d1f9668cc9def72d5db59f21b13sewardj         goto decode_failure;
19379cdc376dcb5a4560b0a35d4abcb2146c499756f0dsewardj      case 0x63: // drintx - Round to an integer value
19380cdc376dcb5a4560b0a35d4abcb2146c499756f0dsewardj      case 0xE3: // drintn - Round to an integer value
193810c4e9e8eef3824b085973cd6e2b1b39a1fd6062ecarll         if (!allow_DFP) goto decode_noDFP;
19382cdc376dcb5a4560b0a35d4abcb2146c499756f0dsewardj         if (dis_dfp_round( theInstr ) ) {
19383cdc376dcb5a4560b0a35d4abcb2146c499756f0dsewardj            goto decode_success;
19384cdc376dcb5a4560b0a35d4abcb2146c499756f0dsewardj         }
19385cdc376dcb5a4560b0a35d4abcb2146c499756f0dsewardj         goto decode_failure;
19386cdc376dcb5a4560b0a35d4abcb2146c499756f0dsewardj      default:
19387cdc376dcb5a4560b0a35d4abcb2146c499756f0dsewardj         break;  /* fall through to next opc2 check */
19388cdc376dcb5a4560b0a35d4abcb2146c499756f0dsewardj      }
19389cdc376dcb5a4560b0a35d4abcb2146c499756f0dsewardj
1939076de5cf615380b23b4b5bcced6541233cd4a93a0cerion      opc2 = IFIELD(theInstr, 1, 5);
19391e14bb9f862843c6b804097c124961b5567ded4f1sewardj      switch (opc2) {
19392d953ebb9b04cbad6891676df597bf0c542b1ec89cerion      /* Floating Point Arith Instructions */
19393d953ebb9b04cbad6891676df597bf0c542b1ec89cerion      case 0x12: case 0x14: case 0x15: // fdivs,  fsubs, fadds
193945117ce116f47141cb23d1b49cc826e19323add97sewardj      case 0x19:                       // fmuls
19395d953ebb9b04cbad6891676df597bf0c542b1ec89cerion         if (dis_fp_arith(theInstr)) goto decode_success;
19396d953ebb9b04cbad6891676df597bf0c542b1ec89cerion         goto decode_failure;
193975117ce116f47141cb23d1b49cc826e19323add97sewardj      case 0x16:                       // fsqrts
193985117ce116f47141cb23d1b49cc826e19323add97sewardj         if (!allow_FX) goto decode_noFX;
193995117ce116f47141cb23d1b49cc826e19323add97sewardj         if (dis_fp_arith(theInstr)) goto decode_success;
194005117ce116f47141cb23d1b49cc826e19323add97sewardj         goto decode_failure;
194015117ce116f47141cb23d1b49cc826e19323add97sewardj      case 0x18:                       // fres
194025117ce116f47141cb23d1b49cc826e19323add97sewardj         if (!allow_GX) goto decode_noGX;
194035117ce116f47141cb23d1b49cc826e19323add97sewardj         if (dis_fp_arith(theInstr)) goto decode_success;
194045117ce116f47141cb23d1b49cc826e19323add97sewardj         goto decode_failure;
194055117ce116f47141cb23d1b49cc826e19323add97sewardj
19406d953ebb9b04cbad6891676df597bf0c542b1ec89cerion      /* Floating Point Mult-Add Instructions */
19407d953ebb9b04cbad6891676df597bf0c542b1ec89cerion      case 0x1C: case 0x1D: case 0x1E: // fmsubs, fmadds, fnmsubs
19408d953ebb9b04cbad6891676df597bf0c542b1ec89cerion      case 0x1F:                       // fnmadds
19409d953ebb9b04cbad6891676df597bf0c542b1ec89cerion         if (dis_fp_multadd(theInstr)) goto decode_success;
19410d953ebb9b04cbad6891676df597bf0c542b1ec89cerion         goto decode_failure;
1941179fd33f4e243276b8109fe56c3eb1d4c9ccea7ccsewardj
1941279fd33f4e243276b8109fe56c3eb1d4c9ccea7ccsewardj      case 0x1A:                       // frsqrtes
1941379fd33f4e243276b8109fe56c3eb1d4c9ccea7ccsewardj         if (!allow_GX) goto decode_noGX;
1941479fd33f4e243276b8109fe56c3eb1d4c9ccea7ccsewardj         if (dis_fp_arith(theInstr)) goto decode_success;
1941579fd33f4e243276b8109fe56c3eb1d4c9ccea7ccsewardj         goto decode_failure;
1941666d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj
19417d953ebb9b04cbad6891676df597bf0c542b1ec89cerion      default:
19418d953ebb9b04cbad6891676df597bf0c542b1ec89cerion         goto decode_failure;
19419e14bb9f862843c6b804097c124961b5567ded4f1sewardj      }
19420e14bb9f862843c6b804097c124961b5567ded4f1sewardj      break;
19421a982c0503d8c0c6069ae453bfe70657bd2c134aecerion
1942266d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj   case 0x3C: // VSX instructions (except load/store)
1942366d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj   {
19424dc7948f8051acfd10087c8e3b66304c0ba0d1b37florian      // All of these VSX instructions use some VMX facilities, so
19425dc7948f8051acfd10087c8e3b66304c0ba0d1b37florian      // if allow_V is not set, we'll skip trying to decode.
19426dc7948f8051acfd10087c8e3b66304c0ba0d1b37florian      if (!allow_V) goto decode_noVX;
19427dc7948f8051acfd10087c8e3b66304c0ba0d1b37florian
1942866d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj      UInt vsxOpc2 = get_VSX60_opc2(opc2);
1942966d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj      /* The vsxOpc2 returned is the "normalized" value, representing the
1943066d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj       * instructions secondary opcode as taken from the standard secondary
1943166d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj       * opcode field [21:30] (IBM notatition), even if the actual field
1943266d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj       * is non-standard.  These normalized values are given in the opcode
1943366d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj       * appendices of the ISA 2.06 document.
1943466d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj       */
1943566d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj
1943666d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj      switch (vsxOpc2) {
1943766d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj         case 0x8: case 0x28: case 0x48: case 0xc8: // xxsldwi, xxpermdi, xxmrghw, xxmrglw
194384aa412af1d8166cc11f39a6e721df49431d23618sewardj         case 0x018: case 0x148: // xxsel, xxspltw
194394aa412af1d8166cc11f39a6e721df49431d23618sewardj            if (dis_vx_permute_misc(theInstr, vsxOpc2)) goto decode_success;
1944066d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj            goto decode_failure;
194416c758b64a77c254065ab7450576bbd3a0b583595carll         case 0x268: case 0x248: case 0x288: // xxlxor, xxlor, xxlnor,
194426c758b64a77c254065ab7450576bbd3a0b583595carll         case 0x208: case 0x228: case 0x2A8: // xxland, xxlandc, xxlorc
194436c758b64a77c254065ab7450576bbd3a0b583595carll         case 0x2C8: case 0x2E8: // xxlnand, xxleqv
1944466d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj            if (dis_vx_logic(theInstr, vsxOpc2)) goto decode_success;
1944566d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj            goto decode_failure;
194464aa412af1d8166cc11f39a6e721df49431d23618sewardj         case 0x2B2: case 0x2C0: // xsabsdp, xscpsgndp
194474aa412af1d8166cc11f39a6e721df49431d23618sewardj         case 0x2D2: case 0x2F2: // xsnabsdp, xsnegdp
194484aa412af1d8166cc11f39a6e721df49431d23618sewardj         case 0x280: case 0x2A0: // xsmaxdp, xsmindp
194494aa412af1d8166cc11f39a6e721df49431d23618sewardj         case 0x0F2: case 0x0D2: // xsrdpim, xsrdpip
194506c758b64a77c254065ab7450576bbd3a0b583595carll         case 0x034: case 0x014: // xsresp, xsrsqrtesp
19451e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj         case 0x0B4: case 0x094: // xsredp, xsrsqrtedp
19452e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj         case 0x0D6: case 0x0B2: // xsrdpic, xsrdpiz
194536c758b64a77c254065ab7450576bbd3a0b583595carll         case 0x092: case 0x232: // xsrdpi, xsrsp
194544aa412af1d8166cc11f39a6e721df49431d23618sewardj            if (dis_vxs_misc(theInstr, vsxOpc2)) goto decode_success;
1945566d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj            goto decode_failure;
1945666d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj         case 0x08C: case 0x0AC: // xscmpudp, xscmpodp
1945766d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj            if (dis_vx_cmp(theInstr, vsxOpc2)) goto decode_success;
1945866d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj            goto decode_failure;
194596c758b64a77c254065ab7450576bbd3a0b583595carll         case 0x0:   case 0x020: // xsaddsp, xssubsp
194606c758b64a77c254065ab7450576bbd3a0b583595carll         case 0x080:             // xsadddp
194616c758b64a77c254065ab7450576bbd3a0b583595carll         case 0x060: case 0x0E0: // xsdivsp, xsdivdp
194626c758b64a77c254065ab7450576bbd3a0b583595carll         case 0x004: case 0x024: // xsmaddasp, xsmaddmsp
1946366d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj         case 0x084: case 0x0A4: // xsmaddadp, xsmaddmdp
194646c758b64a77c254065ab7450576bbd3a0b583595carll         case 0x044: case 0x064: // xsmsubasp, xsmsubmsp
1946566d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj         case 0x0C4: case 0x0E4: // xsmsubadp, xsmsubmdp
194666c758b64a77c254065ab7450576bbd3a0b583595carll         case 0x204: case 0x224: // xsnmaddasp, xsnmaddmsp
1946766d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj         case 0x284: case 0x2A4: // xsnmaddadp, xsnmaddmdp
194686c758b64a77c254065ab7450576bbd3a0b583595carll         case 0x244: case 0x264: // xsnmsubasp, xsnmsubmsp
194694aa412af1d8166cc11f39a6e721df49431d23618sewardj         case 0x2C4: case 0x2E4: // xsnmsubadp, xsnmsubmdp
194706c758b64a77c254065ab7450576bbd3a0b583595carll         case 0x040: case 0x0C0: // xsmulsp, xsmuldp
194716c758b64a77c254065ab7450576bbd3a0b583595carll         case 0x0A0:             // xssubdp
194726c758b64a77c254065ab7450576bbd3a0b583595carll         case 0x016: case 0x096: // xssqrtsp,xssqrtdp
194736c758b64a77c254065ab7450576bbd3a0b583595carll         case 0x0F4: case 0x0D4: // xstdivdp, xstsqrtdp
194744aa412af1d8166cc11f39a6e721df49431d23618sewardj            if (dis_vxs_arith(theInstr, vsxOpc2)) goto decode_success;
194754aa412af1d8166cc11f39a6e721df49431d23618sewardj            goto decode_failure;
194764aa412af1d8166cc11f39a6e721df49431d23618sewardj         case 0x180: // xvadddp
194774aa412af1d8166cc11f39a6e721df49431d23618sewardj         case 0x1E0: // xvdivdp
194784aa412af1d8166cc11f39a6e721df49431d23618sewardj         case 0x1C0: // xvmuldp
194794aa412af1d8166cc11f39a6e721df49431d23618sewardj         case 0x1A0: // xvsubdp
194804aa412af1d8166cc11f39a6e721df49431d23618sewardj         case 0x184: case 0x1A4: // xvmaddadp, xvmaddmdp
194814aa412af1d8166cc11f39a6e721df49431d23618sewardj         case 0x1C4: case 0x1E4: // xvmsubadp, xvmsubmdp
194824aa412af1d8166cc11f39a6e721df49431d23618sewardj         case 0x384: case 0x3A4: // xvnmaddadp, xvnmaddmdp
194834aa412af1d8166cc11f39a6e721df49431d23618sewardj         case 0x3C4: case 0x3E4: // xvnmsubadp, xvnmsubmdp
19484e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj         case 0x1D4: case 0x1F4: // xvtsqrtdp, xvtdivdp
19485e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj         case 0x196: // xvsqrtdp
194864aa412af1d8166cc11f39a6e721df49431d23618sewardj            if (dis_vxv_dp_arith(theInstr, vsxOpc2)) goto decode_success;
194874aa412af1d8166cc11f39a6e721df49431d23618sewardj            goto decode_failure;
194884aa412af1d8166cc11f39a6e721df49431d23618sewardj         case 0x100: // xvaddsp
194894aa412af1d8166cc11f39a6e721df49431d23618sewardj         case 0x160: // xvdivsp
194904aa412af1d8166cc11f39a6e721df49431d23618sewardj         case 0x140: // xvmulsp
194914aa412af1d8166cc11f39a6e721df49431d23618sewardj         case 0x120: // xvsubsp
194924aa412af1d8166cc11f39a6e721df49431d23618sewardj         case 0x104: case 0x124: // xvmaddasp, xvmaddmsp
194934aa412af1d8166cc11f39a6e721df49431d23618sewardj         case 0x144: case 0x164: // xvmsubasp, xvmsubmsp
194944aa412af1d8166cc11f39a6e721df49431d23618sewardj         case 0x304: case 0x324: // xvnmaddasp, xvnmaddmsp
194954aa412af1d8166cc11f39a6e721df49431d23618sewardj         case 0x344: case 0x364: // xvnmsubasp, xvnmsubmsp
19496e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj         case 0x154: case 0x174: // xvtsqrtsp, xvtdivsp
19497e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj         case 0x116: // xvsqrtsp
194984aa412af1d8166cc11f39a6e721df49431d23618sewardj            if (dis_vxv_sp_arith(theInstr, vsxOpc2)) goto decode_success;
1949966d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj            goto decode_failure;
195004aa412af1d8166cc11f39a6e721df49431d23618sewardj
195016c758b64a77c254065ab7450576bbd3a0b583595carll         case 0x250:             // xscvuxdsp
19502dc7948f8051acfd10087c8e3b66304c0ba0d1b37florian         case 0x2D0: case 0x3d0: // xscvuxddp, xvcvuxddp
19503dc7948f8051acfd10087c8e3b66304c0ba0d1b37florian         case 0x350: case 0x1d0: // xvcvuxdsp, xvcvuxwdp
19504dc7948f8051acfd10087c8e3b66304c0ba0d1b37florian         case 0x090: // xscvdpuxws
19505dc7948f8051acfd10087c8e3b66304c0ba0d1b37florian            // The above VSX conversion instructions employ some ISA 2.06
19506dc7948f8051acfd10087c8e3b66304c0ba0d1b37florian            // floating point conversion instructions under the covers,
19507dc7948f8051acfd10087c8e3b66304c0ba0d1b37florian            // so if allow_VX (which means "supports ISA 2.06") is not set,
19508dc7948f8051acfd10087c8e3b66304c0ba0d1b37florian            // we'll skip the decode.
19509dc7948f8051acfd10087c8e3b66304c0ba0d1b37florian            if (!allow_VX) goto decode_noVX;
19510dc7948f8051acfd10087c8e3b66304c0ba0d1b37florian            if (dis_vx_conv(theInstr, vsxOpc2)) goto decode_success;
19511dc7948f8051acfd10087c8e3b66304c0ba0d1b37florian            goto decode_failure;
19512dc7948f8051acfd10087c8e3b66304c0ba0d1b37florian
195136c758b64a77c254065ab7450576bbd3a0b583595carll         case 0x2B0: // xscvdpsxds
195146c758b64a77c254065ab7450576bbd3a0b583595carll         case 0x270: case 0x2F0: // xscvsxdsp, xscvsxddp
195154aa412af1d8166cc11f39a6e721df49431d23618sewardj         case 0x1b0: case 0x130: // xvcvdpsxws, xvcvspsxws
195164aa412af1d8166cc11f39a6e721df49431d23618sewardj         case 0x0b0: case 0x290: // xscvdpsxws, xscvdpuxds
195170c74bb5aa3240f693df0568d578baabf0c376dc4carll         case 0x212: case 0x216: // xscvdpsp, xscvdpspn
195180c74bb5aa3240f693df0568d578baabf0c376dc4carll         case 0x292: case 0x296: // xscvspdp, xscvspdpn
195190c74bb5aa3240f693df0568d578baabf0c376dc4carll         case 0x312: // xvcvdpsp
19520e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj         case 0x390: case 0x190: // xvcvdpuxds, xvcvdpuxws
19521e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj         case 0x3B0: case 0x310: // xvcvdpsxds, xvcvspuxds
19522e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj         case 0x392: case 0x330: // xvcvspdp, xvcvspsxds
19523e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj         case 0x110: case 0x3f0: // xvcvspuxws, xvcvsxddp
19524e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj         case 0x370: case 0x1f0: // xvcvsxdsp, xvcvsxwdp
19525e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj         case 0x170: case 0x150: // xvcvsxwsp, xvcvuxwsp
1952666d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj            if (dis_vx_conv(theInstr, vsxOpc2)) goto decode_success;
1952766d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj            goto decode_failure;
1952866d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj
195294aa412af1d8166cc11f39a6e721df49431d23618sewardj         case 0x18C: case 0x38C: // xvcmpeqdp[.]
195304aa412af1d8166cc11f39a6e721df49431d23618sewardj         case 0x10C: case 0x30C: // xvcmpeqsp[.]
195314aa412af1d8166cc11f39a6e721df49431d23618sewardj         case 0x14C: case 0x34C: // xvcmpgesp[.]
195324aa412af1d8166cc11f39a6e721df49431d23618sewardj         case 0x12C: case 0x32C: // xvcmpgtsp[.]
195334aa412af1d8166cc11f39a6e721df49431d23618sewardj         case 0x1CC: case 0x3CC: // xvcmpgedp[.]
195344aa412af1d8166cc11f39a6e721df49431d23618sewardj         case 0x1AC: case 0x3AC: // xvcmpgtdp[.]
195354aa412af1d8166cc11f39a6e721df49431d23618sewardj             if (dis_vvec_cmp(theInstr, vsxOpc2)) goto decode_success;
195364aa412af1d8166cc11f39a6e721df49431d23618sewardj             goto decode_failure;
195374aa412af1d8166cc11f39a6e721df49431d23618sewardj
195384aa412af1d8166cc11f39a6e721df49431d23618sewardj         case 0x134:  // xvresp
19539e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj         case 0x1B4:  // xvredp
19540e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj         case 0x194: case 0x114: // xvrsqrtedp, xvrsqrtesp
19541e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj         case 0x380: case 0x3A0: // xvmaxdp, xvmindp
195424aa412af1d8166cc11f39a6e721df49431d23618sewardj         case 0x300: case 0x320: // xvmaxsp, xvminsp
19543e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj         case 0x3C0: case 0x340: // xvcpsgndp, xvcpsgnsp
19544e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj         case 0x3B2: case 0x332: // xvabsdp, xvabssp
19545e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj         case 0x3D2: case 0x352: // xvnabsdp, xvnabssp
19546e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj         case 0x192: case 0x1D6: // xvrdpi, xvrdpic
19547e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj         case 0x1F2: case 0x1D2: // xvrdpim, xvrdpip
19548e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj         case 0x1B2: case 0x3F2: // xvrdpiz, xvnegdp
19549e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj         case 0x112: case 0x156: // xvrspi, xvrspic
19550e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj         case 0x172: case 0x152: // xvrspim, xvrspip
19551e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj         case 0x132: // xvrspiz
195524aa412af1d8166cc11f39a6e721df49431d23618sewardj            if (dis_vxv_misc(theInstr, vsxOpc2)) goto decode_success;
195534aa412af1d8166cc11f39a6e721df49431d23618sewardj            goto decode_failure;
195544aa412af1d8166cc11f39a6e721df49431d23618sewardj
1955566d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj         default:
1955666d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj            goto decode_failure;
1955766d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj      }
1955866d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj      break;
1955966d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj   }
1956066d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj
19561f0de28cf1a762b0d6f74c93d3532c89a230673bbcerion   /* 64bit Integer Stores */
1956278850ae9874a90ea625fcee1fd4c359375b7b538carll   case 0x3E:  // std, stdu, stq
19563dd40fdf58cc8a6fe9466c4f00bdfc9fe9bf00449sewardj      if (dis_int_store( theInstr, abiinfo )) goto decode_success;
19564f0de28cf1a762b0d6f74c93d3532c89a230673bbcerion      goto decode_failure;
19565f0de28cf1a762b0d6f74c93d3532c89a230673bbcerion
19566a982c0503d8c0c6069ae453bfe70657bd2c134aecerion   case 0x3F:
195675117ce116f47141cb23d1b49cc826e19323add97sewardj      if (!allow_F) goto decode_noF;
195685b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion      /* Instrs using opc[1:5] never overlap instrs using opc[1:10],
19569a982c0503d8c0c6069ae453bfe70657bd2c134aecerion         so we can simply fall through the first switch statement */
195703d870a39e4d145e2f3d9f9a0eeed3475ec934ac1cerion
1957176de5cf615380b23b4b5bcced6541233cd4a93a0cerion      opc2 = IFIELD(theInstr, 1, 5);
195723d870a39e4d145e2f3d9f9a0eeed3475ec934ac1cerion      switch (opc2) {
19573d953ebb9b04cbad6891676df597bf0c542b1ec89cerion      /* Floating Point Arith Instructions */
195745117ce116f47141cb23d1b49cc826e19323add97sewardj      case 0x12: case 0x14: case 0x15: // fdiv, fsub, fadd
195755117ce116f47141cb23d1b49cc826e19323add97sewardj      case 0x19:                       // fmul
195765117ce116f47141cb23d1b49cc826e19323add97sewardj         if (dis_fp_arith(theInstr)) goto decode_success;
195775117ce116f47141cb23d1b49cc826e19323add97sewardj         goto decode_failure;
195785117ce116f47141cb23d1b49cc826e19323add97sewardj      case 0x16:                       // fsqrt
195795117ce116f47141cb23d1b49cc826e19323add97sewardj         if (!allow_FX) goto decode_noFX;
195805117ce116f47141cb23d1b49cc826e19323add97sewardj         if (dis_fp_arith(theInstr)) goto decode_success;
195815117ce116f47141cb23d1b49cc826e19323add97sewardj         goto decode_failure;
195825117ce116f47141cb23d1b49cc826e19323add97sewardj      case 0x17: case 0x1A:            // fsel, frsqrte
195835117ce116f47141cb23d1b49cc826e19323add97sewardj         if (!allow_GX) goto decode_noGX;
19584d953ebb9b04cbad6891676df597bf0c542b1ec89cerion         if (dis_fp_arith(theInstr)) goto decode_success;
19585d953ebb9b04cbad6891676df597bf0c542b1ec89cerion         goto decode_failure;
19586d953ebb9b04cbad6891676df597bf0c542b1ec89cerion
19587d953ebb9b04cbad6891676df597bf0c542b1ec89cerion      /* Floating Point Mult-Add Instructions */
19588d953ebb9b04cbad6891676df597bf0c542b1ec89cerion      case 0x1C: case 0x1D: case 0x1E: // fmsub, fmadd, fnmsub
19589d953ebb9b04cbad6891676df597bf0c542b1ec89cerion      case 0x1F:                       // fnmadd
19590d953ebb9b04cbad6891676df597bf0c542b1ec89cerion         if (dis_fp_multadd(theInstr)) goto decode_success;
1959179fd33f4e243276b8109fe56c3eb1d4c9ccea7ccsewardj         goto decode_failure;
1959279fd33f4e243276b8109fe56c3eb1d4c9ccea7ccsewardj
1959379fd33f4e243276b8109fe56c3eb1d4c9ccea7ccsewardj      case 0x18:                       // fre
1959479fd33f4e243276b8109fe56c3eb1d4c9ccea7ccsewardj         if (!allow_GX) goto decode_noGX;
1959579fd33f4e243276b8109fe56c3eb1d4c9ccea7ccsewardj         if (dis_fp_arith(theInstr)) goto decode_success;
19596d953ebb9b04cbad6891676df597bf0c542b1ec89cerion         goto decode_failure;
195970c74bb5aa3240f693df0568d578baabf0c376dc4carll
19598d953ebb9b04cbad6891676df597bf0c542b1ec89cerion      default:
19599d953ebb9b04cbad6891676df597bf0c542b1ec89cerion         break; // Fall through
196003d870a39e4d145e2f3d9f9a0eeed3475ec934ac1cerion      }
196013d870a39e4d145e2f3d9f9a0eeed3475ec934ac1cerion
1960276de5cf615380b23b4b5bcced6541233cd4a93a0cerion      opc2 = IFIELD(theInstr, 1, 10);
19603e14bb9f862843c6b804097c124961b5567ded4f1sewardj      switch (opc2) {
19604c6bbd470e9bd9898b84959227a406d3972d95f3bsewardj      /* 128-bit DFP instructions */
19605c6bbd470e9bd9898b84959227a406d3972d95f3bsewardj      case 0x2:    // daddq - DFP Add
19606c6bbd470e9bd9898b84959227a406d3972d95f3bsewardj      case 0x202:  // dsubq - DFP Subtract
19607c6bbd470e9bd9898b84959227a406d3972d95f3bsewardj      case 0x22:   // dmulq - DFP Mult
19608c6bbd470e9bd9898b84959227a406d3972d95f3bsewardj      case 0x222:  // ddivq - DFP Divide
19609c66d6fa5d9397f167b162483cf3419051cc01a80sewardj         if (!allow_DFP) goto decode_noDFP;
19610c6bbd470e9bd9898b84959227a406d3972d95f3bsewardj         if (dis_dfp_arithq( theInstr ))
19611c6bbd470e9bd9898b84959227a406d3972d95f3bsewardj            goto decode_success;
19612c6bbd470e9bd9898b84959227a406d3972d95f3bsewardj         goto decode_failure;
19613cdc376dcb5a4560b0a35d4abcb2146c499756f0dsewardj      case 0x162:  // dxexq - DFP Extract exponent
19614cdc376dcb5a4560b0a35d4abcb2146c499756f0dsewardj      case 0x362:  // diexq - DFP Insert exponent
196150c4e9e8eef3824b085973cd6e2b1b39a1fd6062ecarll         if (!allow_DFP) goto decode_noDFP;
19616cdc376dcb5a4560b0a35d4abcb2146c499756f0dsewardj         if (dis_dfp_extract_insertq( theInstr ))
19617cdc376dcb5a4560b0a35d4abcb2146c499756f0dsewardj            goto decode_success;
19618cdc376dcb5a4560b0a35d4abcb2146c499756f0dsewardj         goto decode_failure;
19619cdc376dcb5a4560b0a35d4abcb2146c499756f0dsewardj
19620cdc376dcb5a4560b0a35d4abcb2146c499756f0dsewardj      case 0x82:   // dcmpoq, DFP comparison ordered instruction
19621cdc376dcb5a4560b0a35d4abcb2146c499756f0dsewardj      case 0x282:  // dcmpuq, DFP comparison unordered instruction
196220c4e9e8eef3824b085973cd6e2b1b39a1fd6062ecarll         if (!allow_DFP) goto decode_noDFP;
19623cdc376dcb5a4560b0a35d4abcb2146c499756f0dsewardj         if (dis_dfp_compare( theInstr ) )
19624cdc376dcb5a4560b0a35d4abcb2146c499756f0dsewardj            goto decode_success;
19625cdc376dcb5a4560b0a35d4abcb2146c499756f0dsewardj         goto decode_failure;
19626c6bbd470e9bd9898b84959227a406d3972d95f3bsewardj
1962726217b09205cc1801b842ba5ba8f0d83aabca1b4sewardj      case 0x102: // dctqpq  - DFP convert to DFP extended
1962826217b09205cc1801b842ba5ba8f0d83aabca1b4sewardj      case 0x302: // drdpq   - DFP round to dfp Long
1962926217b09205cc1801b842ba5ba8f0d83aabca1b4sewardj      case 0x122: // dctfixq - DFP convert to fixed quad
1963026217b09205cc1801b842ba5ba8f0d83aabca1b4sewardj      case 0x322: // dcffixq - DFP convert from fixed quad
196310c4e9e8eef3824b085973cd6e2b1b39a1fd6062ecarll         if (!allow_DFP) goto decode_noDFP;
1963226217b09205cc1801b842ba5ba8f0d83aabca1b4sewardj         if (dis_dfp_fmt_convq( theInstr ))
1963326217b09205cc1801b842ba5ba8f0d83aabca1b4sewardj            goto decode_success;
1963426217b09205cc1801b842ba5ba8f0d83aabca1b4sewardj         goto decode_failure;
1963526217b09205cc1801b842ba5ba8f0d83aabca1b4sewardj
196364c96e61dd85c172b999d6afc88ce6640aeba9962sewardj      case 0x2A2: // dtstsfq - DFP number of significant digits
196370c4e9e8eef3824b085973cd6e2b1b39a1fd6062ecarll         if (!allow_DFP) goto decode_noDFP;
196384c96e61dd85c172b999d6afc88ce6640aeba9962sewardj         if (dis_dfp_significant_digits(theInstr))
196394c96e61dd85c172b999d6afc88ce6640aeba9962sewardj            goto decode_success;
196404c96e61dd85c172b999d6afc88ce6640aeba9962sewardj         goto decode_failure;
196414c96e61dd85c172b999d6afc88ce6640aeba9962sewardj
196424c96e61dd85c172b999d6afc88ce6640aeba9962sewardj      case 0x142: // ddedpdq   DFP Decode DPD to BCD
196434c96e61dd85c172b999d6afc88ce6640aeba9962sewardj      case 0x342: // denbcdq   DFP Encode BCD to DPD
196440c4e9e8eef3824b085973cd6e2b1b39a1fd6062ecarll         if (!allow_DFP) goto decode_noDFP;
196454c96e61dd85c172b999d6afc88ce6640aeba9962sewardj         if (dis_dfp_bcdq(theInstr))
196464c96e61dd85c172b999d6afc88ce6640aeba9962sewardj            goto decode_success;
196474c96e61dd85c172b999d6afc88ce6640aeba9962sewardj         goto decode_failure;
196484c96e61dd85c172b999d6afc88ce6640aeba9962sewardj
19649d953ebb9b04cbad6891676df597bf0c542b1ec89cerion      /* Floating Point Compare Instructions */
19650d953ebb9b04cbad6891676df597bf0c542b1ec89cerion      case 0x000: // fcmpu
19651d953ebb9b04cbad6891676df597bf0c542b1ec89cerion      case 0x020: // fcmpo
19652d953ebb9b04cbad6891676df597bf0c542b1ec89cerion         if (dis_fp_cmp(theInstr)) goto decode_success;
19653d953ebb9b04cbad6891676df597bf0c542b1ec89cerion         goto decode_failure;
196542831b00c4950d6c2b061def05fd67528fe132ececerion
1965566d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj      case 0x080: // ftdiv
19656e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj      case 0x0A0: // ftsqrt
19657e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj         if (dis_fp_tests(theInstr)) goto decode_success;
1965866d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj         goto decode_failure;
1965966d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj
19660d953ebb9b04cbad6891676df597bf0c542b1ec89cerion      /* Floating Point Rounding/Conversion Instructions */
19661d953ebb9b04cbad6891676df597bf0c542b1ec89cerion      case 0x00C: // frsp
19662d953ebb9b04cbad6891676df597bf0c542b1ec89cerion      case 0x00E: // fctiw
19663d953ebb9b04cbad6891676df597bf0c542b1ec89cerion      case 0x00F: // fctiwz
196646be67235ba2829b0bc34c3a0876cee4eac340d95sewardj      case 0x32E: // fctid
196656be67235ba2829b0bc34c3a0876cee4eac340d95sewardj      case 0x32F: // fctidz
196666be67235ba2829b0bc34c3a0876cee4eac340d95sewardj      case 0x34E: // fcfid
19667d953ebb9b04cbad6891676df597bf0c542b1ec89cerion         if (dis_fp_round(theInstr)) goto decode_success;
19668d953ebb9b04cbad6891676df597bf0c542b1ec89cerion         goto decode_failure;
196694aa412af1d8166cc11f39a6e721df49431d23618sewardj      case 0x3CE: case 0x3AE: case 0x3AF: // fcfidu, fctidu[z] (implemented as native insns)
196704aa412af1d8166cc11f39a6e721df49431d23618sewardj      case 0x08F: case 0x08E: // fctiwu[z] (implemented as native insns)
1967166d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj         if (!allow_VX) goto decode_noVX;
1967266d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj         if (dis_fp_round(theInstr)) goto decode_success;
1967366d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj         goto decode_failure;
1967466d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj
196750f1ef86a99d5129e04ed188e44d16a344d2bc42asewardj      /* Power6 rounding stuff */
196760f1ef86a99d5129e04ed188e44d16a344d2bc42asewardj      case 0x1E8: // frim
196770f1ef86a99d5129e04ed188e44d16a344d2bc42asewardj      case 0x1C8: // frip
196780f1ef86a99d5129e04ed188e44d16a344d2bc42asewardj      case 0x188: // frin
196790f1ef86a99d5129e04ed188e44d16a344d2bc42asewardj      case 0x1A8: // friz
196807e84630580f89c1022dde97007bffbf6aef81814sewardj         /* A hack to check for P6 capability . . . */
196817e84630580f89c1022dde97007bffbf6aef81814sewardj         if ((allow_F && allow_V && allow_FX && allow_GX) &&
196827e84630580f89c1022dde97007bffbf6aef81814sewardj             (dis_fp_round(theInstr)))
196830f1ef86a99d5129e04ed188e44d16a344d2bc42asewardj            goto decode_success;
196840f1ef86a99d5129e04ed188e44d16a344d2bc42asewardj         goto decode_failure;
19685d953ebb9b04cbad6891676df597bf0c542b1ec89cerion
19686d953ebb9b04cbad6891676df597bf0c542b1ec89cerion      /* Floating Point Move Instructions */
196877e84630580f89c1022dde97007bffbf6aef81814sewardj      case 0x008: // fcpsgn
19688d953ebb9b04cbad6891676df597bf0c542b1ec89cerion      case 0x028: // fneg
19689d953ebb9b04cbad6891676df597bf0c542b1ec89cerion      case 0x048: // fmr
19690d953ebb9b04cbad6891676df597bf0c542b1ec89cerion      case 0x088: // fnabs
19691d953ebb9b04cbad6891676df597bf0c542b1ec89cerion      case 0x108: // fabs
19692d953ebb9b04cbad6891676df597bf0c542b1ec89cerion         if (dis_fp_move( theInstr )) goto decode_success;
19693d953ebb9b04cbad6891676df597bf0c542b1ec89cerion         goto decode_failure;
19694d953ebb9b04cbad6891676df597bf0c542b1ec89cerion
1969578850ae9874a90ea625fcee1fd4c359375b7b538carll      case 0x3c6: case 0x346:          // fmrgew, fmrgow
1969678850ae9874a90ea625fcee1fd4c359375b7b538carll         if (dis_fp_merge( theInstr )) goto decode_success;
1969778850ae9874a90ea625fcee1fd4c359375b7b538carll         goto decode_failure;
1969878850ae9874a90ea625fcee1fd4c359375b7b538carll
19699d953ebb9b04cbad6891676df597bf0c542b1ec89cerion      /* Floating Point Status/Control Register Instructions */
197003ea49ee14d8c061bc0e7c3e90a22849de1c59d73cerion      case 0x026: // mtfsb1
19701496b88f208ea5cca7b03d41209fba7f4e1ae9c9bsewardj      case 0x040: // mcrfs
19702d953ebb9b04cbad6891676df597bf0c542b1ec89cerion      case 0x046: // mtfsb0
19703d953ebb9b04cbad6891676df597bf0c542b1ec89cerion      case 0x086: // mtfsfi
19704d953ebb9b04cbad6891676df597bf0c542b1ec89cerion      case 0x247: // mffs
19705d953ebb9b04cbad6891676df597bf0c542b1ec89cerion      case 0x2C7: // mtfsf
19706c6bbd470e9bd9898b84959227a406d3972d95f3bsewardj         // Some of the above instructions need to know more about the
19707c6bbd470e9bd9898b84959227a406d3972d95f3bsewardj         // ISA level supported by the host.
19708c6bbd470e9bd9898b84959227a406d3972d95f3bsewardj         if (dis_fp_scr( theInstr, allow_GX )) goto decode_success;
19709d953ebb9b04cbad6891676df597bf0c542b1ec89cerion         goto decode_failure;
19710f0de28cf1a762b0d6f74c93d3532c89a230673bbcerion
19711d953ebb9b04cbad6891676df597bf0c542b1ec89cerion      default:
1971226217b09205cc1801b842ba5ba8f0d83aabca1b4sewardj         break; // Fall through...
1971326217b09205cc1801b842ba5ba8f0d83aabca1b4sewardj      }
1971426217b09205cc1801b842ba5ba8f0d83aabca1b4sewardj
1971526217b09205cc1801b842ba5ba8f0d83aabca1b4sewardj      opc2 = ifieldOPClo9( theInstr );
1971626217b09205cc1801b842ba5ba8f0d83aabca1b4sewardj      switch (opc2) {
1971726217b09205cc1801b842ba5ba8f0d83aabca1b4sewardj      case 0x42: // dscli, DFP shift left
1971826217b09205cc1801b842ba5ba8f0d83aabca1b4sewardj      case 0x62: // dscri, DFP shift right
197190c4e9e8eef3824b085973cd6e2b1b39a1fd6062ecarll         if (!allow_DFP) goto decode_noDFP;
1972026217b09205cc1801b842ba5ba8f0d83aabca1b4sewardj         if (dis_dfp_shiftq( theInstr ))
1972126217b09205cc1801b842ba5ba8f0d83aabca1b4sewardj            goto decode_success;
1972226217b09205cc1801b842ba5ba8f0d83aabca1b4sewardj         goto decode_failure;
197235eff1c502e995d1f9668cc9def72d5db59f21b13sewardj      case 0xc2:  // dtstdc, DFP test data class
197245eff1c502e995d1f9668cc9def72d5db59f21b13sewardj      case 0xe2:  // dtstdg, DFP test data group
197250c4e9e8eef3824b085973cd6e2b1b39a1fd6062ecarll         if (!allow_DFP) goto decode_noDFP;
197265eff1c502e995d1f9668cc9def72d5db59f21b13sewardj         if (dis_dfp_class_test( theInstr ))
197275eff1c502e995d1f9668cc9def72d5db59f21b13sewardj            goto decode_success;
197285eff1c502e995d1f9668cc9def72d5db59f21b13sewardj         goto decode_failure;
1972926217b09205cc1801b842ba5ba8f0d83aabca1b4sewardj      default:
1973026217b09205cc1801b842ba5ba8f0d83aabca1b4sewardj         break;
19731e14bb9f862843c6b804097c124961b5567ded4f1sewardj      }
19732cdc376dcb5a4560b0a35d4abcb2146c499756f0dsewardj
19733cdc376dcb5a4560b0a35d4abcb2146c499756f0dsewardj      opc2 = ifieldOPClo8( theInstr );
19734cdc376dcb5a4560b0a35d4abcb2146c499756f0dsewardj      switch (opc2) {
19735cdc376dcb5a4560b0a35d4abcb2146c499756f0dsewardj      case 0x3:   // dquaq  - DFP Quantize Quad
19736cdc376dcb5a4560b0a35d4abcb2146c499756f0dsewardj      case 0x23:  // drrndq - DFP Reround Quad
19737cdc376dcb5a4560b0a35d4abcb2146c499756f0dsewardj      case 0x43:  // dquaiq - DFP Quantize immediate Quad
197380c4e9e8eef3824b085973cd6e2b1b39a1fd6062ecarll         if (!allow_DFP) goto decode_noDFP;
19739cdc376dcb5a4560b0a35d4abcb2146c499756f0dsewardj         if (dis_dfp_quantize_sig_rrndq( theInstr ))
19740cdc376dcb5a4560b0a35d4abcb2146c499756f0dsewardj            goto decode_success;
19741cdc376dcb5a4560b0a35d4abcb2146c499756f0dsewardj         goto decode_failure;
197425eff1c502e995d1f9668cc9def72d5db59f21b13sewardj      case 0xA2: // dtstexq - DFP Test exponent Quad
19743c7910f428436d86d2b18924a8acbdaab49b27e49florian         if (!allow_DFP) goto decode_noDFP;
197445eff1c502e995d1f9668cc9def72d5db59f21b13sewardj         if (dis_dfp_exponent_test( theInstr ) )
197455eff1c502e995d1f9668cc9def72d5db59f21b13sewardj            goto decode_success;
197465eff1c502e995d1f9668cc9def72d5db59f21b13sewardj         goto decode_failure;
19747cdc376dcb5a4560b0a35d4abcb2146c499756f0dsewardj      case 0x63:  // drintxq - DFP Round to an integer value
19748cdc376dcb5a4560b0a35d4abcb2146c499756f0dsewardj      case 0xE3:  // drintnq - DFP Round to an integer value
197490c4e9e8eef3824b085973cd6e2b1b39a1fd6062ecarll         if (!allow_DFP) goto decode_noDFP;
19750cdc376dcb5a4560b0a35d4abcb2146c499756f0dsewardj         if (dis_dfp_roundq( theInstr ))
19751cdc376dcb5a4560b0a35d4abcb2146c499756f0dsewardj            goto decode_success;
19752cdc376dcb5a4560b0a35d4abcb2146c499756f0dsewardj         goto decode_failure;
19753cdc376dcb5a4560b0a35d4abcb2146c499756f0dsewardj
19754cdc376dcb5a4560b0a35d4abcb2146c499756f0dsewardj      default:
19755cdc376dcb5a4560b0a35d4abcb2146c499756f0dsewardj         goto decode_failure;
19756cdc376dcb5a4560b0a35d4abcb2146c499756f0dsewardj      }
197573d870a39e4d145e2f3d9f9a0eeed3475ec934ac1cerion      break;
1975826217b09205cc1801b842ba5ba8f0d83aabca1b4sewardj
1975991ad5368eb6354ad4fabc86f2b2e641736997a38cerion   case 0x13:
19760b85e8bba97fdae7d892f7bfd12e4601307e4721dcerion      switch (opc2) {
19761b85e8bba97fdae7d892f7bfd12e4601307e4721dcerion
19762d953ebb9b04cbad6891676df597bf0c542b1ec89cerion      /* Condition Register Logical Instructions */
19763d953ebb9b04cbad6891676df597bf0c542b1ec89cerion      case 0x101: case 0x081: case 0x121: // crand,  crandc, creqv
19764d953ebb9b04cbad6891676df597bf0c542b1ec89cerion      case 0x0E1: case 0x021: case 0x1C1: // crnand, crnor,  cror
19765d953ebb9b04cbad6891676df597bf0c542b1ec89cerion      case 0x1A1: case 0x0C1: case 0x000: // crorc,  crxor,  mcrf
19766d953ebb9b04cbad6891676df597bf0c542b1ec89cerion         if (dis_cond_logic( theInstr )) goto decode_success;
19767d953ebb9b04cbad6891676df597bf0c542b1ec89cerion         goto decode_failure;
19768d953ebb9b04cbad6891676df597bf0c542b1ec89cerion
19769d953ebb9b04cbad6891676df597bf0c542b1ec89cerion      /* Branch Instructions */
19770d953ebb9b04cbad6891676df597bf0c542b1ec89cerion      case 0x210: case 0x010: // bcctr, bclr
19771dd40fdf58cc8a6fe9466c4f00bdfc9fe9bf00449sewardj         if (dis_branch(theInstr, abiinfo, &dres,
19772aca070a5b3418a6a9b01e3c57a7eb0fbb5050908sewardj                                  resteerOkFn, callback_opaque))
19773c716aea1cafe66ee431dc7d6909c98f18788a028sewardj            goto decode_success;
19774d953ebb9b04cbad6891676df597bf0c542b1ec89cerion         goto decode_failure;
19775d953ebb9b04cbad6891676df597bf0c542b1ec89cerion
19776d953ebb9b04cbad6891676df597bf0c542b1ec89cerion      /* Memory Synchronization Instructions */
19777d953ebb9b04cbad6891676df597bf0c542b1ec89cerion      case 0x096: // isync
19778d953ebb9b04cbad6891676df597bf0c542b1ec89cerion         if (dis_memsync( theInstr )) goto decode_success;
19779d953ebb9b04cbad6891676df597bf0c542b1ec89cerion         goto decode_failure;
1978078850ae9874a90ea625fcee1fd4c359375b7b538carll
19781d953ebb9b04cbad6891676df597bf0c542b1ec89cerion      default:
19782d953ebb9b04cbad6891676df597bf0c542b1ec89cerion         goto decode_failure;
19783b85e8bba97fdae7d892f7bfd12e4601307e4721dcerion      }
19784b85e8bba97fdae7d892f7bfd12e4601307e4721dcerion      break;
197857aa4bbc850d2978cccd8e12cd7c4cfeaa5ab3e4dcerion
19786b0004f748b0f580e733a9dcb9d92f511920d3dd7cerion
19787b85e8bba97fdae7d892f7bfd12e4601307e4721dcerion   case 0x1F:
19788e9d361ab43518b6dfbd3d846f48859534659dee0cerion
19789e9d361ab43518b6dfbd3d846f48859534659dee0cerion      /* For arith instns, bit10 is the OE flag (overflow enable) */
19790e9d361ab43518b6dfbd3d846f48859534659dee0cerion
1979176de5cf615380b23b4b5bcced6541233cd4a93a0cerion      opc2 = IFIELD(theInstr, 1, 9);
19792b85e8bba97fdae7d892f7bfd12e4601307e4721dcerion      switch (opc2) {
19793d953ebb9b04cbad6891676df597bf0c542b1ec89cerion      /* Integer Arithmetic Instructions */
19794d953ebb9b04cbad6891676df597bf0c542b1ec89cerion      case 0x10A: case 0x00A: case 0x08A: // add,   addc,  adde
19795d953ebb9b04cbad6891676df597bf0c542b1ec89cerion      case 0x0EA: case 0x0CA: case 0x1EB: // addme, addze, divw
19796d953ebb9b04cbad6891676df597bf0c542b1ec89cerion      case 0x1CB: case 0x04B: case 0x00B: // divwu, mulhw, mulhwu
19797d953ebb9b04cbad6891676df597bf0c542b1ec89cerion      case 0x0EB: case 0x068: case 0x028: // mullw, neg,   subf
19798d953ebb9b04cbad6891676df597bf0c542b1ec89cerion      case 0x008: case 0x088: case 0x0E8: // subfc, subfe, subfme
197994aa412af1d8166cc11f39a6e721df49431d23618sewardj      case 0x0C8: // subfze
198004aa412af1d8166cc11f39a6e721df49431d23618sewardj         if (dis_int_arith( theInstr )) goto decode_success;
198014aa412af1d8166cc11f39a6e721df49431d23618sewardj         goto decode_failure;
198024aa412af1d8166cc11f39a6e721df49431d23618sewardj
198034aa412af1d8166cc11f39a6e721df49431d23618sewardj      case 0x18B: // divweu (implemented as native insn)
19804e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj      case 0x1AB: // divwe (implemented as native insn)
198054aa412af1d8166cc11f39a6e721df49431d23618sewardj         if (!allow_VX) goto decode_noVX;
19806d953ebb9b04cbad6891676df597bf0c542b1ec89cerion         if (dis_int_arith( theInstr )) goto decode_success;
19807d953ebb9b04cbad6891676df597bf0c542b1ec89cerion         goto decode_failure;
19808f0de28cf1a762b0d6f74c93d3532c89a230673bbcerion
19809f0de28cf1a762b0d6f74c93d3532c89a230673bbcerion      /* 64bit Integer Arithmetic */
19810f0de28cf1a762b0d6f74c93d3532c89a230673bbcerion      case 0x009: case 0x049: case 0x0E9: // mulhdu, mulhd, mulld
198114aa412af1d8166cc11f39a6e721df49431d23618sewardj      case 0x1C9: case 0x1E9: // divdu, divd
198124aa412af1d8166cc11f39a6e721df49431d23618sewardj         if (!mode64) goto decode_failure;
198134aa412af1d8166cc11f39a6e721df49431d23618sewardj         if (dis_int_arith( theInstr )) goto decode_success;
198144aa412af1d8166cc11f39a6e721df49431d23618sewardj         goto decode_failure;
198154aa412af1d8166cc11f39a6e721df49431d23618sewardj
198164aa412af1d8166cc11f39a6e721df49431d23618sewardj      case 0x1A9: //  divde (implemented as native insn)
19817e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj      case 0x189: //  divdeuo (implemented as native insn)
198184aa412af1d8166cc11f39a6e721df49431d23618sewardj         if (!allow_VX) goto decode_noVX;
19819f0de28cf1a762b0d6f74c93d3532c89a230673bbcerion         if (!mode64) goto decode_failure;
19820f0de28cf1a762b0d6f74c93d3532c89a230673bbcerion         if (dis_int_arith( theInstr )) goto decode_success;
19821f0de28cf1a762b0d6f74c93d3532c89a230673bbcerion         goto decode_failure;
19822f0de28cf1a762b0d6f74c93d3532c89a230673bbcerion
198237e84630580f89c1022dde97007bffbf6aef81814sewardj      case 0x1FC:                         // cmpb
198247e84630580f89c1022dde97007bffbf6aef81814sewardj         if (dis_int_logic( theInstr )) goto decode_success;
198257e84630580f89c1022dde97007bffbf6aef81814sewardj         goto decode_failure;
198267e84630580f89c1022dde97007bffbf6aef81814sewardj
19827d953ebb9b04cbad6891676df597bf0c542b1ec89cerion      default:
19828d953ebb9b04cbad6891676df597bf0c542b1ec89cerion         break;  // Fall through...
19829b85e8bba97fdae7d892f7bfd12e4601307e4721dcerion      }
19830b85e8bba97fdae7d892f7bfd12e4601307e4721dcerion
19831e9d361ab43518b6dfbd3d846f48859534659dee0cerion      /* All remaining opcodes use full 10 bits. */
19832e9d361ab43518b6dfbd3d846f48859534659dee0cerion
1983376de5cf615380b23b4b5bcced6541233cd4a93a0cerion      opc2 = IFIELD(theInstr, 1, 10);
19834b85e8bba97fdae7d892f7bfd12e4601307e4721dcerion      switch (opc2) {
19835e9d361ab43518b6dfbd3d846f48859534659dee0cerion      /* Integer Compare Instructions  */
19836e9d361ab43518b6dfbd3d846f48859534659dee0cerion      case 0x000: case 0x020: // cmp, cmpl
19837e9d361ab43518b6dfbd3d846f48859534659dee0cerion         if (dis_int_cmp( theInstr )) goto decode_success;
19838b85e8bba97fdae7d892f7bfd12e4601307e4721dcerion         goto decode_failure;
19839b85e8bba97fdae7d892f7bfd12e4601307e4721dcerion
19840e9d361ab43518b6dfbd3d846f48859534659dee0cerion      /* Integer Logical Instructions */
19841e9d361ab43518b6dfbd3d846f48859534659dee0cerion      case 0x01C: case 0x03C: case 0x01A: // and,  andc,  cntlzw
19842e9d361ab43518b6dfbd3d846f48859534659dee0cerion      case 0x11C: case 0x3BA: case 0x39A: // eqv,  extsb, extsh
19843e9d361ab43518b6dfbd3d846f48859534659dee0cerion      case 0x1DC: case 0x07C: case 0x1BC: // nand, nor,   or
19844e9d361ab43518b6dfbd3d846f48859534659dee0cerion      case 0x19C: case 0x13C:             // orc,  xor
198457e84630580f89c1022dde97007bffbf6aef81814sewardj      case 0x2DF: case 0x25F:            // mftgpr, mffgpr
19846e9d361ab43518b6dfbd3d846f48859534659dee0cerion         if (dis_int_logic( theInstr )) goto decode_success;
19847b85e8bba97fdae7d892f7bfd12e4601307e4721dcerion         goto decode_failure;
19848b85e8bba97fdae7d892f7bfd12e4601307e4721dcerion
198498943d02aa373f45c6e5fdcbe5947620285d442b1carll      case 0x28E: case 0x2AE:             // tbegin., tend.
198508943d02aa373f45c6e5fdcbe5947620285d442b1carll      case 0x2EE: case 0x2CE: case 0x30E: // tsr., tcheck., tabortwc.
198518943d02aa373f45c6e5fdcbe5947620285d442b1carll      case 0x32E: case 0x34E: case 0x36E: // tabortdc., tabortwci., tabortdci.
19852fcce5f8ca9ad1fbb5939b8c94d7470b4d51a7387carll      case 0x38E: case 0x3AE: case 0x3EE: // tabort., treclaim., trechkpt.
198538943d02aa373f45c6e5fdcbe5947620285d442b1carll      if (dis_transactional_memory( theInstr,
198548462d113e3efeacceb304222dada8d85f748295aflorian                                    getUIntPPCendianly( &guest_code[delta + 4]),
198558943d02aa373f45c6e5fdcbe5947620285d442b1carll                                    abiinfo, &dres,
198568943d02aa373f45c6e5fdcbe5947620285d442b1carll                                    resteerOkFn, callback_opaque))
198578943d02aa373f45c6e5fdcbe5947620285d442b1carll            goto decode_success;
198588943d02aa373f45c6e5fdcbe5947620285d442b1carll         goto decode_failure;
198598943d02aa373f45c6e5fdcbe5947620285d442b1carll
19860f0de28cf1a762b0d6f74c93d3532c89a230673bbcerion      /* 64bit Integer Logical Instructions */
1986107b07a966a2fdbcf621251a0c1a8ab84807fb120cerion      case 0x3DA: case 0x03A: // extsw, cntlzd
19862f0de28cf1a762b0d6f74c93d3532c89a230673bbcerion         if (!mode64) goto decode_failure;
19863f0de28cf1a762b0d6f74c93d3532c89a230673bbcerion         if (dis_int_logic( theInstr )) goto decode_success;
19864f0de28cf1a762b0d6f74c93d3532c89a230673bbcerion         goto decode_failure;
19865f0de28cf1a762b0d6f74c93d3532c89a230673bbcerion
198667e84630580f89c1022dde97007bffbf6aef81814sewardj         /* 64bit Integer Parity Instructions */
19867bb3f40144f5e72dfbba740d4b2f090b4a91c3876carll      case 0xba: // prtyd
19868bb3f40144f5e72dfbba740d4b2f090b4a91c3876carll         if (!mode64) goto decode_failure;
19869bb3f40144f5e72dfbba740d4b2f090b4a91c3876carll         if (dis_int_parity( theInstr )) goto decode_success;
19870bb3f40144f5e72dfbba740d4b2f090b4a91c3876carll         goto decode_failure;
19871bb3f40144f5e72dfbba740d4b2f090b4a91c3876carll
19872bb3f40144f5e72dfbba740d4b2f090b4a91c3876carll      case 0x9a: // prtyw
198737e84630580f89c1022dde97007bffbf6aef81814sewardj         if (dis_int_parity( theInstr )) goto decode_success;
198747e84630580f89c1022dde97007bffbf6aef81814sewardj         goto decode_failure;
198757e84630580f89c1022dde97007bffbf6aef81814sewardj
19876e9d361ab43518b6dfbd3d846f48859534659dee0cerion      /* Integer Shift Instructions */
19877e9d361ab43518b6dfbd3d846f48859534659dee0cerion      case 0x018: case 0x318: case 0x338: // slw, sraw, srawi
19878e9d361ab43518b6dfbd3d846f48859534659dee0cerion      case 0x218:                         // srw
19879e9d361ab43518b6dfbd3d846f48859534659dee0cerion         if (dis_int_shift( theInstr )) goto decode_success;
19880b85e8bba97fdae7d892f7bfd12e4601307e4721dcerion         goto decode_failure;
19881b85e8bba97fdae7d892f7bfd12e4601307e4721dcerion
19882f0de28cf1a762b0d6f74c93d3532c89a230673bbcerion      /* 64bit Integer Shift Instructions */
19883f0de28cf1a762b0d6f74c93d3532c89a230673bbcerion      case 0x01B: case 0x31A: // sld, srad
1988407b07a966a2fdbcf621251a0c1a8ab84807fb120cerion      case 0x33A: case 0x33B: // sradi
19885f0de28cf1a762b0d6f74c93d3532c89a230673bbcerion      case 0x21B:             // srd
19886f0de28cf1a762b0d6f74c93d3532c89a230673bbcerion         if (!mode64) goto decode_failure;
19887f0de28cf1a762b0d6f74c93d3532c89a230673bbcerion         if (dis_int_shift( theInstr )) goto decode_success;
19888f0de28cf1a762b0d6f74c93d3532c89a230673bbcerion         goto decode_failure;
19889f0de28cf1a762b0d6f74c93d3532c89a230673bbcerion
19890e9d361ab43518b6dfbd3d846f48859534659dee0cerion      /* Integer Load Instructions */
19891e9d361ab43518b6dfbd3d846f48859534659dee0cerion      case 0x057: case 0x077: case 0x157: // lbzx,  lbzux, lhax
19892e9d361ab43518b6dfbd3d846f48859534659dee0cerion      case 0x177: case 0x117: case 0x137: // lhaux, lhzx,  lhzux
19893e9d361ab43518b6dfbd3d846f48859534659dee0cerion      case 0x017: case 0x037:             // lwzx,  lwzux
19894e9d361ab43518b6dfbd3d846f48859534659dee0cerion         if (dis_int_load( theInstr )) goto decode_success;
19895b85e8bba97fdae7d892f7bfd12e4601307e4721dcerion         goto decode_failure;
19896b85e8bba97fdae7d892f7bfd12e4601307e4721dcerion
19897f0de28cf1a762b0d6f74c93d3532c89a230673bbcerion      /* 64bit Integer Load Instructions */
19898f0de28cf1a762b0d6f74c93d3532c89a230673bbcerion      case 0x035: case 0x015:             // ldux,  ldx
19899f0de28cf1a762b0d6f74c93d3532c89a230673bbcerion      case 0x175: case 0x155:             // lwaux, lwax
19900f0de28cf1a762b0d6f74c93d3532c89a230673bbcerion         if (!mode64) goto decode_failure;
19901f0de28cf1a762b0d6f74c93d3532c89a230673bbcerion         if (dis_int_load( theInstr )) goto decode_success;
19902f0de28cf1a762b0d6f74c93d3532c89a230673bbcerion         goto decode_failure;
19903f0de28cf1a762b0d6f74c93d3532c89a230673bbcerion
19904b51f0f4f33256638ed953156a2635aa739b232f1sewardj      /* Integer Store Instructions */
19905e9d361ab43518b6dfbd3d846f48859534659dee0cerion      case 0x0F7: case 0x0D7: case 0x1B7: // stbux, stbx,  sthux
19906e9d361ab43518b6dfbd3d846f48859534659dee0cerion      case 0x197: case 0x0B7: case 0x097: // sthx,  stwux, stwx
19907dd40fdf58cc8a6fe9466c4f00bdfc9fe9bf00449sewardj         if (dis_int_store( theInstr, abiinfo )) goto decode_success;
19908b85e8bba97fdae7d892f7bfd12e4601307e4721dcerion         goto decode_failure;
19909b85e8bba97fdae7d892f7bfd12e4601307e4721dcerion
19910f0de28cf1a762b0d6f74c93d3532c89a230673bbcerion      /* 64bit Integer Store Instructions */
19911f0de28cf1a762b0d6f74c93d3532c89a230673bbcerion      case 0x0B5: case 0x095: // stdux, stdx
19912f0de28cf1a762b0d6f74c93d3532c89a230673bbcerion         if (!mode64) goto decode_failure;
19913dd40fdf58cc8a6fe9466c4f00bdfc9fe9bf00449sewardj         if (dis_int_store( theInstr, abiinfo )) goto decode_success;
19914f0de28cf1a762b0d6f74c93d3532c89a230673bbcerion         goto decode_failure;
19915f0de28cf1a762b0d6f74c93d3532c89a230673bbcerion
19916602857d30b8aa87c202517e2be6c7df6d40ee922sewardj      /* Integer Load and Store with Byte Reverse Instructions */
19917bb3f40144f5e72dfbba740d4b2f090b4a91c3876carll      case 0x214: case 0x294: // ldbrx, stdbrx
19918bb3f40144f5e72dfbba740d4b2f090b4a91c3876carll         if (!mode64) goto decode_failure;
19919bb3f40144f5e72dfbba740d4b2f090b4a91c3876carll         if (dis_int_ldst_rev( theInstr )) goto decode_success;
19920bb3f40144f5e72dfbba740d4b2f090b4a91c3876carll         goto decode_failure;
19921bb3f40144f5e72dfbba740d4b2f090b4a91c3876carll
19922bb3f40144f5e72dfbba740d4b2f090b4a91c3876carll      case 0x216: case 0x316: case 0x296:    // lwbrx, lhbrx, stwbrx
19923bb3f40144f5e72dfbba740d4b2f090b4a91c3876carll      case 0x396:                            // sthbrx
19924602857d30b8aa87c202517e2be6c7df6d40ee922sewardj         if (dis_int_ldst_rev( theInstr )) goto decode_success;
19925602857d30b8aa87c202517e2be6c7df6d40ee922sewardj         goto decode_failure;
19926602857d30b8aa87c202517e2be6c7df6d40ee922sewardj
1992787e651f40360a8f1c9418710e79c482028759f8csewardj      /* Integer Load and Store String Instructions */
1992887e651f40360a8f1c9418710e79c482028759f8csewardj      case 0x255: case 0x215: case 0x2D5: // lswi, lswx, stswi
1992987e651f40360a8f1c9418710e79c482028759f8csewardj      case 0x295: {                       // stswx
1993087e651f40360a8f1c9418710e79c482028759f8csewardj         Bool stopHere = False;
1993187e651f40360a8f1c9418710e79c482028759f8csewardj         Bool ok = dis_int_ldst_str( theInstr, &stopHere );
1993287e651f40360a8f1c9418710e79c482028759f8csewardj         if (!ok) goto decode_failure;
1993387e651f40360a8f1c9418710e79c482028759f8csewardj         if (stopHere) {
199343dee849ec7c38746749065e67dc53b75daa7617dsewardj            putGST( PPC_GST_CIA, mkSzImm(ty, nextInsnAddr()) );
199353dee849ec7c38746749065e67dc53b75daa7617dsewardj            dres.jk_StopHere = Ijk_Boring;
199363dee849ec7c38746749065e67dc53b75daa7617dsewardj            dres.whatNext    = Dis_StopHere;
1993787e651f40360a8f1c9418710e79c482028759f8csewardj         }
1993887e651f40360a8f1c9418710e79c482028759f8csewardj         goto decode_success;
1993987e651f40360a8f1c9418710e79c482028759f8csewardj      }
19940b85e8bba97fdae7d892f7bfd12e4601307e4721dcerion
19941e9d361ab43518b6dfbd3d846f48859534659dee0cerion      /* Memory Synchronization Instructions */
19942d826889bd512ded2fbbc4781c595ecf0513f46f6carll      case 0x034: case 0x074:             // lbarx, lharx
19943d826889bd512ded2fbbc4781c595ecf0513f46f6carll      case 0x2B6: case 0x2D6:             // stbcx, sthcx
19944d826889bd512ded2fbbc4781c595ecf0513f46f6carll         if (!allow_isa_2_07) goto decode_noP8;
19945d826889bd512ded2fbbc4781c595ecf0513f46f6carll         if (dis_memsync( theInstr )) goto decode_success;
19946d826889bd512ded2fbbc4781c595ecf0513f46f6carll         goto decode_failure;
19947d826889bd512ded2fbbc4781c595ecf0513f46f6carll
19948e9d361ab43518b6dfbd3d846f48859534659dee0cerion      case 0x356: case 0x014: case 0x096: // eieio, lwarx, stwcx.
19949e9d361ab43518b6dfbd3d846f48859534659dee0cerion      case 0x256:                         // sync
19950e9d361ab43518b6dfbd3d846f48859534659dee0cerion         if (dis_memsync( theInstr )) goto decode_success;
19951b85e8bba97fdae7d892f7bfd12e4601307e4721dcerion         goto decode_failure;
19952b85e8bba97fdae7d892f7bfd12e4601307e4721dcerion
19953f0de28cf1a762b0d6f74c93d3532c89a230673bbcerion      /* 64bit Memory Synchronization Instructions */
19954f0de28cf1a762b0d6f74c93d3532c89a230673bbcerion      case 0x054: case 0x0D6: // ldarx, stdcx.
19955f0de28cf1a762b0d6f74c93d3532c89a230673bbcerion         if (!mode64) goto decode_failure;
19956f0de28cf1a762b0d6f74c93d3532c89a230673bbcerion         if (dis_memsync( theInstr )) goto decode_success;
19957f0de28cf1a762b0d6f74c93d3532c89a230673bbcerion         goto decode_failure;
19958f0de28cf1a762b0d6f74c93d3532c89a230673bbcerion
1995978850ae9874a90ea625fcee1fd4c359375b7b538carll      case 0x114: case 0x0B6: // lqarx, stqcx.
1996078850ae9874a90ea625fcee1fd4c359375b7b538carll         if (dis_memsync( theInstr )) goto decode_success;
1996178850ae9874a90ea625fcee1fd4c359375b7b538carll         goto decode_failure;
1996278850ae9874a90ea625fcee1fd4c359375b7b538carll
19963e9d361ab43518b6dfbd3d846f48859534659dee0cerion      /* Processor Control Instructions */
1996478850ae9874a90ea625fcee1fd4c359375b7b538carll      case 0x33:  case 0x73: // mfvsrd, mfvsrwz
1996578850ae9874a90ea625fcee1fd4c359375b7b538carll      case 0xB3:  case 0xD3: case 0xF3: // mtvsrd, mtvsrwa, mtvsrwz
19966e9d361ab43518b6dfbd3d846f48859534659dee0cerion      case 0x200: case 0x013: case 0x153: // mcrxr, mfcr,  mfspr
19967e9d361ab43518b6dfbd3d846f48859534659dee0cerion      case 0x173: case 0x090: case 0x1D3: // mftb,  mtcrf, mtspr
1996878850ae9874a90ea625fcee1fd4c359375b7b538carll      case 0x220:                         // mcrxrt
19969dd40fdf58cc8a6fe9466c4f00bdfc9fe9bf00449sewardj         if (dis_proc_ctl( abiinfo, theInstr )) goto decode_success;
19970b85e8bba97fdae7d892f7bfd12e4601307e4721dcerion         goto decode_failure;
19971b85e8bba97fdae7d892f7bfd12e4601307e4721dcerion
19972e9d361ab43518b6dfbd3d846f48859534659dee0cerion      /* Cache Management Instructions */
19973e9d361ab43518b6dfbd3d846f48859534659dee0cerion      case 0x2F6: case 0x056: case 0x036: // dcba, dcbf,   dcbst
19974e9d361ab43518b6dfbd3d846f48859534659dee0cerion      case 0x116: case 0x0F6: case 0x3F6: // dcbt, dcbtst, dcbz
19975e9d361ab43518b6dfbd3d846f48859534659dee0cerion      case 0x3D6:                         // icbi
199761f5fe1fc3a37ca729925e8eec25aa1025b4a6cdbcarll         if (dis_cache_manage( theInstr, &dres, archinfo ))
19977d94b73a4ece194130f7a59cca9262d44cf9dbb91sewardj            goto decode_success;
19978b85e8bba97fdae7d892f7bfd12e4601307e4721dcerion         goto decode_failure;
19979b85e8bba97fdae7d892f7bfd12e4601307e4721dcerion
19980b51f0f4f33256638ed953156a2635aa739b232f1sewardj//zz       /* External Control Instructions */
19981b51f0f4f33256638ed953156a2635aa739b232f1sewardj//zz       case 0x136: case 0x1B6: // eciwx, ecowx
19982b51f0f4f33256638ed953156a2635aa739b232f1sewardj//zz          DIP("external control op => not implemented\n");
19983b51f0f4f33256638ed953156a2635aa739b232f1sewardj//zz          goto decode_failure;
1998459c0d8f0997bd03e0f8d90b9144dc0aeb6fe9a3asewardj
1998559c0d8f0997bd03e0f8d90b9144dc0aeb6fe9a3asewardj      /* Trap Instructions */
19986bb3f40144f5e72dfbba740d4b2f090b4a91c3876carll      case 0x004:             // tw
19987bb3f40144f5e72dfbba740d4b2f090b4a91c3876carll         if (dis_trap(theInstr, &dres)) goto decode_success;
19988bb3f40144f5e72dfbba740d4b2f090b4a91c3876carll         goto decode_failure;
19989bb3f40144f5e72dfbba740d4b2f090b4a91c3876carll
19990bb3f40144f5e72dfbba740d4b2f090b4a91c3876carll      case 0x044:             // td
19991bb3f40144f5e72dfbba740d4b2f090b4a91c3876carll         if (!mode64) goto decode_failure;
1999259c0d8f0997bd03e0f8d90b9144dc0aeb6fe9a3asewardj         if (dis_trap(theInstr, &dres)) goto decode_success;
1999359c0d8f0997bd03e0f8d90b9144dc0aeb6fe9a3asewardj         goto decode_failure;
19994e14bb9f862843c6b804097c124961b5567ded4f1sewardj
19995e14bb9f862843c6b804097c124961b5567ded4f1sewardj      /* Floating Point Load Instructions */
19996e14bb9f862843c6b804097c124961b5567ded4f1sewardj      case 0x217: case 0x237: case 0x257: // lfsx, lfsux, lfdx
19997e14bb9f862843c6b804097c124961b5567ded4f1sewardj      case 0x277:                         // lfdux
199985117ce116f47141cb23d1b49cc826e19323add97sewardj         if (!allow_F) goto decode_noF;
19999e14bb9f862843c6b804097c124961b5567ded4f1sewardj         if (dis_fp_load( theInstr )) goto decode_success;
20000e14bb9f862843c6b804097c124961b5567ded4f1sewardj         goto decode_failure;
20001e14bb9f862843c6b804097c124961b5567ded4f1sewardj
20002e14bb9f862843c6b804097c124961b5567ded4f1sewardj      /* Floating Point Store Instructions */
20003e14bb9f862843c6b804097c124961b5567ded4f1sewardj      case 0x297: case 0x2B7: case 0x2D7: // stfs,  stfsu, stfd
200045117ce116f47141cb23d1b49cc826e19323add97sewardj      case 0x2F7:                         // stfdu, stfiwx
200055117ce116f47141cb23d1b49cc826e19323add97sewardj         if (!allow_F) goto decode_noF;
200065117ce116f47141cb23d1b49cc826e19323add97sewardj         if (dis_fp_store( theInstr )) goto decode_success;
200075117ce116f47141cb23d1b49cc826e19323add97sewardj         goto decode_failure;
200085117ce116f47141cb23d1b49cc826e19323add97sewardj      case 0x3D7:                         // stfiwx
200095117ce116f47141cb23d1b49cc826e19323add97sewardj         if (!allow_F) goto decode_noF;
200105117ce116f47141cb23d1b49cc826e19323add97sewardj         if (!allow_GX) goto decode_noGX;
20011e14bb9f862843c6b804097c124961b5567ded4f1sewardj         if (dis_fp_store( theInstr )) goto decode_success;
20012e14bb9f862843c6b804097c124961b5567ded4f1sewardj         goto decode_failure;
20013e14bb9f862843c6b804097c124961b5567ded4f1sewardj
200147e84630580f89c1022dde97007bffbf6aef81814sewardj         /* Floating Point Double Pair Indexed Instructions */
200157e84630580f89c1022dde97007bffbf6aef81814sewardj      case 0x317: // lfdpx (Power6)
200167e84630580f89c1022dde97007bffbf6aef81814sewardj      case 0x397: // stfdpx (Power6)
200177e84630580f89c1022dde97007bffbf6aef81814sewardj         if (!allow_F) goto decode_noF;
200187e84630580f89c1022dde97007bffbf6aef81814sewardj         if (dis_fp_pair(theInstr)) goto decode_success;
200197e84630580f89c1022dde97007bffbf6aef81814sewardj         goto decode_failure;
200207e84630580f89c1022dde97007bffbf6aef81814sewardj
200217e84630580f89c1022dde97007bffbf6aef81814sewardj      case 0x357:                         // lfiwax
200227e84630580f89c1022dde97007bffbf6aef81814sewardj         if (!allow_F) goto decode_noF;
200237e84630580f89c1022dde97007bffbf6aef81814sewardj         if (dis_fp_load( theInstr )) goto decode_success;
200247e84630580f89c1022dde97007bffbf6aef81814sewardj         goto decode_failure;
200257e84630580f89c1022dde97007bffbf6aef81814sewardj
2002666d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj      case 0x377:                         // lfiwzx
2002766d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj         if (!allow_F) goto decode_noF;
2002866d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj         if (dis_fp_load( theInstr )) goto decode_success;
2002966d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj         goto decode_failure;
2003066d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj
2003132aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion      /* AltiVec instructions */
2003232aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion
2003332aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion      /* AV Cache Control - Data streams */
2003432aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion      case 0x156: case 0x176: case 0x336: // dst, dstst, dss
200355117ce116f47141cb23d1b49cc826e19323add97sewardj         if (!allow_V) goto decode_noV;
2003632aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion         if (dis_av_datastream( theInstr )) goto decode_success;
2003732aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion         goto decode_failure;
20038a982c0503d8c0c6069ae453bfe70657bd2c134aecerion
20039a982c0503d8c0c6069ae453bfe70657bd2c134aecerion      /* AV Load */
20040a982c0503d8c0c6069ae453bfe70657bd2c134aecerion      case 0x006: case 0x026:             // lvsl, lvsr
20041a982c0503d8c0c6069ae453bfe70657bd2c134aecerion      case 0x007: case 0x027: case 0x047: // lvebx, lvehx, lvewx
20042a982c0503d8c0c6069ae453bfe70657bd2c134aecerion      case 0x067: case 0x167:             // lvx, lvxl
200435117ce116f47141cb23d1b49cc826e19323add97sewardj         if (!allow_V) goto decode_noV;
20044dd40fdf58cc8a6fe9466c4f00bdfc9fe9bf00449sewardj         if (dis_av_load( abiinfo, theInstr )) goto decode_success;
20045a982c0503d8c0c6069ae453bfe70657bd2c134aecerion         goto decode_failure;
20046a982c0503d8c0c6069ae453bfe70657bd2c134aecerion
20047a982c0503d8c0c6069ae453bfe70657bd2c134aecerion      /* AV Store */
20048a982c0503d8c0c6069ae453bfe70657bd2c134aecerion      case 0x087: case 0x0A7: case 0x0C7: // stvebx, stvehx, stvewx
20049a982c0503d8c0c6069ae453bfe70657bd2c134aecerion      case 0x0E7: case 0x1E7:             // stvx, stvxl
200505117ce116f47141cb23d1b49cc826e19323add97sewardj         if (!allow_V) goto decode_noV;
20051a982c0503d8c0c6069ae453bfe70657bd2c134aecerion         if (dis_av_store( theInstr )) goto decode_success;
20052a982c0503d8c0c6069ae453bfe70657bd2c134aecerion         goto decode_failure;
20053a982c0503d8c0c6069ae453bfe70657bd2c134aecerion
2005466d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj      /* VSX Load */
200556c758b64a77c254065ab7450576bbd3a0b583595carll      case 0x00C: // lxsiwzx
200566c758b64a77c254065ab7450576bbd3a0b583595carll      case 0x04C: // lxsiwax
200576c758b64a77c254065ab7450576bbd3a0b583595carll      case 0x20C: // lxsspx
2005866d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj      case 0x24C: // lxsdx
2005966d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj      case 0x34C: // lxvd2x
2006066d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj      case 0x14C: // lxvdsx
2006166d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj      case 0x30C: // lxvw4x
20062dc7948f8051acfd10087c8e3b66304c0ba0d1b37florian        // All of these VSX load instructions use some VMX facilities, so
20063dc7948f8051acfd10087c8e3b66304c0ba0d1b37florian        // if allow_V is not set, we'll skip trying to decode.
20064dc7948f8051acfd10087c8e3b66304c0ba0d1b37florian        if (!allow_V) goto decode_noV;
20065dc7948f8051acfd10087c8e3b66304c0ba0d1b37florian
200661f5fe1fc3a37ca729925e8eec25aa1025b4a6cdbcarll	if (dis_vx_load( theInstr )) goto decode_success;
2006766d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj          goto decode_failure;
2006866d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj
2006966d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj      /* VSX Store */
200706c758b64a77c254065ab7450576bbd3a0b583595carll      case 0x08C: // stxsiwx
200716c758b64a77c254065ab7450576bbd3a0b583595carll      case 0x28C: // stxsspx
2007266d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj      case 0x2CC: // stxsdx
2007366d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj      case 0x3CC: // stxvd2x
2007466d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj      case 0x38C: // stxvw4x
20075dc7948f8051acfd10087c8e3b66304c0ba0d1b37florian        // All of these VSX store instructions use some VMX facilities, so
20076dc7948f8051acfd10087c8e3b66304c0ba0d1b37florian        // if allow_V is not set, we'll skip trying to decode.
20077dc7948f8051acfd10087c8e3b66304c0ba0d1b37florian        if (!allow_V) goto decode_noV;
20078dc7948f8051acfd10087c8e3b66304c0ba0d1b37florian
200791f5fe1fc3a37ca729925e8eec25aa1025b4a6cdbcarll	if (dis_vx_store( theInstr )) goto decode_success;
2008066d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj    	  goto decode_failure;
2008166d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj
2008266d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj      /* Miscellaneous ISA 2.06 instructions */
2008366d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj      case 0x1FA: // popcntd
20084e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj      case 0x17A: // popcntw
20085738d9dddf788cd66fc04081f5fca872f38859813philippe      case 0x7A:  // popcntb
200861f5fe1fc3a37ca729925e8eec25aa1025b4a6cdbcarll	  if (dis_int_logic( theInstr )) goto decode_success;
2008766d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj    	  goto decode_failure;
2008866d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj
200894aa412af1d8166cc11f39a6e721df49431d23618sewardj      case 0x0FC: // bpermd
20090bb3f40144f5e72dfbba740d4b2f090b4a91c3876carll         if (!mode64) goto decode_failure;
200914aa412af1d8166cc11f39a6e721df49431d23618sewardj         if (dis_int_logic( theInstr )) goto decode_success;
200924aa412af1d8166cc11f39a6e721df49431d23618sewardj         goto decode_failure;
200934aa412af1d8166cc11f39a6e721df49431d23618sewardj
20094a982c0503d8c0c6069ae453bfe70657bd2c134aecerion      default:
20095cb07be2425eee24e72932432059663e1e620e681sewardj         /* Deal with some other cases that we would otherwise have
20096cb07be2425eee24e72932432059663e1e620e681sewardj            punted on. */
20097cb07be2425eee24e72932432059663e1e620e681sewardj         /* --- ISEL (PowerISA_V2.05.pdf, p74) --- */
200981685c2887bec68514f0830a45c082bbcfe5fa3e2sewardj         /* only decode this insn when reserved bit 0 (31 in IBM's
200991685c2887bec68514f0830a45c082bbcfe5fa3e2sewardj            notation) is zero */
201001685c2887bec68514f0830a45c082bbcfe5fa3e2sewardj         if (IFIELD(theInstr, 0, 6) == (15<<1)) {
20101cb07be2425eee24e72932432059663e1e620e681sewardj            UInt rT = ifieldRegDS( theInstr );
20102cb07be2425eee24e72932432059663e1e620e681sewardj            UInt rA = ifieldRegA( theInstr );
20103cb07be2425eee24e72932432059663e1e620e681sewardj            UInt rB = ifieldRegB( theInstr );
20104cb07be2425eee24e72932432059663e1e620e681sewardj            UInt bi = ifieldRegC( theInstr );
20105cb07be2425eee24e72932432059663e1e620e681sewardj            putIReg(
20106cb07be2425eee24e72932432059663e1e620e681sewardj               rT,
2010799dd03e04a6914d90d5fee727d61d76905334becflorian               IRExpr_ITE( binop(Iop_CmpNE32, getCRbit( bi ), mkU32(0)),
2010899dd03e04a6914d90d5fee727d61d76905334becflorian                           rA == 0 ? (mode64 ? mkU64(0) : mkU32(0))
2010999dd03e04a6914d90d5fee727d61d76905334becflorian                                   : getIReg(rA),
2011099dd03e04a6914d90d5fee727d61d76905334becflorian                           getIReg(rB))
2011199dd03e04a6914d90d5fee727d61d76905334becflorian
20112cb07be2425eee24e72932432059663e1e620e681sewardj            );
20113cb07be2425eee24e72932432059663e1e620e681sewardj            DIP("isel r%u,r%u,r%u,crb%u\n", rT,rA,rB,bi);
20114cb07be2425eee24e72932432059663e1e620e681sewardj            goto decode_success;
20115cb07be2425eee24e72932432059663e1e620e681sewardj         }
20116a982c0503d8c0c6069ae453bfe70657bd2c134aecerion         goto decode_failure;
20117a982c0503d8c0c6069ae453bfe70657bd2c134aecerion      }
20118a982c0503d8c0c6069ae453bfe70657bd2c134aecerion      break;
20119a982c0503d8c0c6069ae453bfe70657bd2c134aecerion
20120a982c0503d8c0c6069ae453bfe70657bd2c134aecerion
2012132aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion   case 0x04:
2012232aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion      /* AltiVec instructions */
2012332aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion
2012476de5cf615380b23b4b5bcced6541233cd4a93a0cerion      opc2 = IFIELD(theInstr, 0, 6);
2012532aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion      switch (opc2) {
2012632aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion      /* AV Mult-Add, Mult-Sum */
2012732aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion      case 0x20: case 0x21: case 0x22: // vmhaddshs, vmhraddshs, vmladduhm
2012832aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion      case 0x24: case 0x25: case 0x26: // vmsumubm, vmsummbm, vmsumuhm
2012932aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion      case 0x27: case 0x28: case 0x29: // vmsumuhs, vmsumshm, vmsumshs
201305117ce116f47141cb23d1b49cc826e19323add97sewardj         if (!allow_V) goto decode_noV;
2013132aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion         if (dis_av_multarith( theInstr )) goto decode_success;
2013232aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion         goto decode_failure;
2013332aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion
2013432aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion      /* AV Permutations */
2013532aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion      case 0x2A:                       // vsel
2013632aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion      case 0x2B:                       // vperm
2013732aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion      case 0x2C:                       // vsldoi
201385117ce116f47141cb23d1b49cc826e19323add97sewardj         if (!allow_V) goto decode_noV;
2013992d9d876af80d14fa2f319f7109964f2d6231f15cerion         if (dis_av_permute( theInstr )) goto decode_success;
2014032aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion         goto decode_failure;
2014132aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion
201427deaf9552b546b847528cf39b38898fb7742b5f5carll      case 0x2D:                       // vpermxor
201437deaf9552b546b847528cf39b38898fb7742b5f5carll         if (!allow_isa_2_07) goto decode_noP8;
201447deaf9552b546b847528cf39b38898fb7742b5f5carll         if (dis_av_permute( theInstr )) goto decode_success;
201457deaf9552b546b847528cf39b38898fb7742b5f5carll         goto decode_failure;
201467deaf9552b546b847528cf39b38898fb7742b5f5carll
2014732aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion      /* AV Floating Point Mult-Add/Sub */
2014832aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion      case 0x2E: case 0x2F:            // vmaddfp, vnmsubfp
201495117ce116f47141cb23d1b49cc826e19323add97sewardj         if (!allow_V) goto decode_noV;
2015032aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion         if (dis_av_fp_arith( theInstr )) goto decode_success;
2015132aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion         goto decode_failure;
2015232aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion
2015360c6bac19ffe055cabab554e7877d73096a8bf17carll      case 0x3D: case 0x3C:            // vaddecuq, vaddeuqm
2015460c6bac19ffe055cabab554e7877d73096a8bf17carll      case 0x3F: case 0x3E:            // vsubecuq, vsubeuqm
2015560c6bac19ffe055cabab554e7877d73096a8bf17carll         if (!allow_V) goto decode_noV;
2015660c6bac19ffe055cabab554e7877d73096a8bf17carll         if (dis_av_quad( theInstr)) goto decode_success;
2015760c6bac19ffe055cabab554e7877d73096a8bf17carll         goto decode_failure;
2015860c6bac19ffe055cabab554e7877d73096a8bf17carll
2015932aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion      default:
2016032aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion         break;  // Fall through...
2016132aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion      }
2016232aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion
201637deaf9552b546b847528cf39b38898fb7742b5f5carll      opc2 = IFIELD(theInstr, 0, 9);
201647deaf9552b546b847528cf39b38898fb7742b5f5carll      switch (opc2) {
201657deaf9552b546b847528cf39b38898fb7742b5f5carll      /* BCD arithmetic */
201667deaf9552b546b847528cf39b38898fb7742b5f5carll      case 0x1: case 0x41:             // bcdadd, bcdsub
201677deaf9552b546b847528cf39b38898fb7742b5f5carll         if (!allow_isa_2_07) goto decode_noP8;
201687deaf9552b546b847528cf39b38898fb7742b5f5carll         if (dis_av_bcd( theInstr )) goto decode_success;
201697deaf9552b546b847528cf39b38898fb7742b5f5carll         goto decode_failure;
201707deaf9552b546b847528cf39b38898fb7742b5f5carll
201717deaf9552b546b847528cf39b38898fb7742b5f5carll      default:
201727deaf9552b546b847528cf39b38898fb7742b5f5carll         break;  // Fall through...
201737deaf9552b546b847528cf39b38898fb7742b5f5carll      }
201747deaf9552b546b847528cf39b38898fb7742b5f5carll
2017576de5cf615380b23b4b5bcced6541233cd4a93a0cerion      opc2 = IFIELD(theInstr, 0, 11);
2017632aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion      switch (opc2) {
2017732aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion      /* AV Arithmetic */
2017832aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion      case 0x180:                         // vaddcuw
2017932aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion      case 0x000: case 0x040: case 0x080: // vaddubm, vadduhm, vadduwm
2018032aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion      case 0x200: case 0x240: case 0x280: // vaddubs, vadduhs, vadduws
2018132aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion      case 0x300: case 0x340: case 0x380: // vaddsbs, vaddshs, vaddsws
2018232aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion      case 0x580:                         // vsubcuw
2018332aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion      case 0x400: case 0x440: case 0x480: // vsububm, vsubuhm, vsubuwm
2018432aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion      case 0x600: case 0x640: case 0x680: // vsububs, vsubuhs, vsubuws
2018532aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion      case 0x700: case 0x740: case 0x780: // vsubsbs, vsubshs, vsubsws
2018632aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion      case 0x402: case 0x442: case 0x482: // vavgub, vavguh, vavguw
2018732aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion      case 0x502: case 0x542: case 0x582: // vavgsb, vavgsh, vavgsw
2018832aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion      case 0x002: case 0x042: case 0x082: // vmaxub, vmaxuh, vmaxuw
2018932aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion      case 0x102: case 0x142: case 0x182: // vmaxsb, vmaxsh, vmaxsw
2019032aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion      case 0x202: case 0x242: case 0x282: // vminub, vminuh, vminuw
2019132aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion      case 0x302: case 0x342: case 0x382: // vminsb, vminsh, vminsw
2019232aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion      case 0x008: case 0x048:             // vmuloub, vmulouh
2019332aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion      case 0x108: case 0x148:             // vmulosb, vmulosh
2019432aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion      case 0x208: case 0x248:             // vmuleub, vmuleuh
2019532aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion      case 0x308: case 0x348:             // vmulesb, vmulesh
2019632aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion      case 0x608: case 0x708: case 0x648: // vsum4ubs, vsum4sbs, vsum4shs
2019732aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion      case 0x688: case 0x788:             // vsum2sws, vsumsws
201985117ce116f47141cb23d1b49cc826e19323add97sewardj         if (!allow_V) goto decode_noV;
2019932aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion         if (dis_av_arith( theInstr )) goto decode_success;
2020032aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion         goto decode_failure;
2020132aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion
2020248ae46b56cef87c90638b25d6b2462c475033da8carll      case 0x088: case 0x089:             // vmulouw, vmuluwm
2020348ae46b56cef87c90638b25d6b2462c475033da8carll      case 0x0C0: case 0x0C2:             // vaddudm, vmaxud
2020448ae46b56cef87c90638b25d6b2462c475033da8carll      case 0x1C2: case 0x2C2: case 0x3C2: // vnaxsd, vminud, vminsd
2020548ae46b56cef87c90638b25d6b2462c475033da8carll      case 0x188: case 0x288: case 0x388: // vmulosw, vmuleuw, vmulesw
2020648ae46b56cef87c90638b25d6b2462c475033da8carll      case 0x4C0:                         // vsubudm
202070c74bb5aa3240f693df0568d578baabf0c376dc4carll         if (!allow_isa_2_07) goto decode_noP8;
202080c74bb5aa3240f693df0568d578baabf0c376dc4carll         if (dis_av_arith( theInstr )) goto decode_success;
202090c74bb5aa3240f693df0568d578baabf0c376dc4carll         goto decode_failure;
202100c74bb5aa3240f693df0568d578baabf0c376dc4carll
202117deaf9552b546b847528cf39b38898fb7742b5f5carll      /* AV Polynomial Vector Multiply Add */
202127deaf9552b546b847528cf39b38898fb7742b5f5carll      case 0x408: case 0x448:            // vpmsumb, vpmsumd
202137deaf9552b546b847528cf39b38898fb7742b5f5carll      case 0x488: case 0x4C8:            // vpmsumw, vpmsumh
202147deaf9552b546b847528cf39b38898fb7742b5f5carll         if (!allow_isa_2_07) goto decode_noP8;
202157deaf9552b546b847528cf39b38898fb7742b5f5carll         if (dis_av_polymultarith( theInstr )) goto decode_success;
202167deaf9552b546b847528cf39b38898fb7742b5f5carll         goto decode_failure;
202177deaf9552b546b847528cf39b38898fb7742b5f5carll
2021832aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion      /* AV Rotate, Shift */
2021932aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion      case 0x004: case 0x044: case 0x084: // vrlb, vrlh, vrlw
2022032aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion      case 0x104: case 0x144: case 0x184: // vslb, vslh, vslw
2022132aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion      case 0x204: case 0x244: case 0x284: // vsrb, vsrh, vsrw
2022232aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion      case 0x304: case 0x344: case 0x384: // vsrab, vsrah, vsraw
2022332aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion      case 0x1C4: case 0x2C4:             // vsl, vsr
2022432aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion      case 0x40C: case 0x44C:             // vslo, vsro
202255117ce116f47141cb23d1b49cc826e19323add97sewardj         if (!allow_V) goto decode_noV;
2022632aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion         if (dis_av_shift( theInstr )) goto decode_success;
2022732aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion         goto decode_failure;
2022832aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion
2022948ae46b56cef87c90638b25d6b2462c475033da8carll      case 0x0C4:                         // vrld
2023048ae46b56cef87c90638b25d6b2462c475033da8carll      case 0x3C4: case 0x5C4: case 0x6C4: // vsrad, vsld, vsrd
2023148ae46b56cef87c90638b25d6b2462c475033da8carll          if (!allow_isa_2_07) goto decode_noP8;
2023248ae46b56cef87c90638b25d6b2462c475033da8carll          if (dis_av_shift( theInstr )) goto decode_success;
2023348ae46b56cef87c90638b25d6b2462c475033da8carll          goto decode_failure;
2023448ae46b56cef87c90638b25d6b2462c475033da8carll
2023532aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion      /* AV Logic */
2023632aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion      case 0x404: case 0x444: case 0x484: // vand, vandc, vor
2023732aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion      case 0x4C4: case 0x504:             // vxor, vnor
202385117ce116f47141cb23d1b49cc826e19323add97sewardj         if (!allow_V) goto decode_noV;
2023932aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion         if (dis_av_logic( theInstr )) goto decode_success;
2024032aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion         goto decode_failure;
2024132aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion
202427deaf9552b546b847528cf39b38898fb7742b5f5carll      case 0x544:                         // vorc
202437deaf9552b546b847528cf39b38898fb7742b5f5carll      case 0x584: case 0x684:             // vnand, veqv
202447deaf9552b546b847528cf39b38898fb7742b5f5carll         if (!allow_isa_2_07) goto decode_noP8;
202457deaf9552b546b847528cf39b38898fb7742b5f5carll         if (dis_av_logic( theInstr )) goto decode_success;
202467deaf9552b546b847528cf39b38898fb7742b5f5carll         goto decode_failure;
202477deaf9552b546b847528cf39b38898fb7742b5f5carll
2024832aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion      /* AV Processor Control */
2024932aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion      case 0x604: case 0x644:             // mfvscr, mtvscr
202505117ce116f47141cb23d1b49cc826e19323add97sewardj         if (!allow_V) goto decode_noV;
2025132aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion         if (dis_av_procctl( theInstr )) goto decode_success;
2025232aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion         goto decode_failure;
2025332aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion
2025432aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion      /* AV Floating Point Arithmetic */
2025532aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion      case 0x00A: case 0x04A:             // vaddfp, vsubfp
2025632aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion      case 0x10A: case 0x14A: case 0x18A: // vrefp, vrsqrtefp, vexptefp
2025732aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion      case 0x1CA:                         // vlogefp
2025832aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion      case 0x40A: case 0x44A:             // vmaxfp, vminfp
202595117ce116f47141cb23d1b49cc826e19323add97sewardj         if (!allow_V) goto decode_noV;
2026032aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion         if (dis_av_fp_arith( theInstr )) goto decode_success;
2026132aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion         goto decode_failure;
2026232aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion
2026332aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion      /* AV Floating Point Round/Convert */
2026432aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion      case 0x20A: case 0x24A: case 0x28A: // vrfin, vrfiz, vrfip
2026532aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion      case 0x2CA:                         // vrfim
2026632aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion      case 0x30A: case 0x34A: case 0x38A: // vcfux, vcfsx, vctuxs
2026732aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion      case 0x3CA:                         // vctsxs
202685117ce116f47141cb23d1b49cc826e19323add97sewardj         if (!allow_V) goto decode_noV;
2026932aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion         if (dis_av_fp_convert( theInstr )) goto decode_success;
2027032aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion         goto decode_failure;
2027132aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion
2027232aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion      /* AV Merge, Splat */
2027332aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion      case 0x00C: case 0x04C: case 0x08C: // vmrghb, vmrghh, vmrghw
2027432aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion      case 0x10C: case 0x14C: case 0x18C: // vmrglb, vmrglh, vmrglw
2027532aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion      case 0x20C: case 0x24C: case 0x28C: // vspltb, vsplth, vspltw
2027632aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion      case 0x30C: case 0x34C: case 0x38C: // vspltisb, vspltish, vspltisw
202775117ce116f47141cb23d1b49cc826e19323add97sewardj         if (!allow_V) goto decode_noV;
2027832aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion         if (dis_av_permute( theInstr )) goto decode_success;
2027932aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion         goto decode_failure;
2028032aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion
2028148ae46b56cef87c90638b25d6b2462c475033da8carll      case 0x68C: case 0x78C:             // vmrgow, vmrgew
2028248ae46b56cef87c90638b25d6b2462c475033da8carll          if (!allow_isa_2_07) goto decode_noP8;
2028348ae46b56cef87c90638b25d6b2462c475033da8carll          if (dis_av_permute( theInstr )) goto decode_success;
2028448ae46b56cef87c90638b25d6b2462c475033da8carll          goto decode_failure;
2028548ae46b56cef87c90638b25d6b2462c475033da8carll
2028632aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion      /* AV Pack, Unpack */
2028732aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion      case 0x00E: case 0x04E: case 0x08E: // vpkuhum, vpkuwum, vpkuhus
2028832aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion      case 0x0CE:                         // vpkuwus
2028932aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion      case 0x10E: case 0x14E: case 0x18E: // vpkshus, vpkswus, vpkshss
2029032aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion      case 0x1CE:                         // vpkswss
2029132aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion      case 0x20E: case 0x24E: case 0x28E: // vupkhsb, vupkhsh, vupklsb
2029232aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion      case 0x2CE:                         // vupklsh
2029332aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion      case 0x30E: case 0x34E: case 0x3CE: // vpkpx, vupkhpx, vupklpx
2029448ae46b56cef87c90638b25d6b2462c475033da8carll          if (!allow_V) goto decode_noV;
2029548ae46b56cef87c90638b25d6b2462c475033da8carll          if (dis_av_pack( theInstr )) goto decode_success;
2029648ae46b56cef87c90638b25d6b2462c475033da8carll          goto decode_failure;
2029732aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion
2029848ae46b56cef87c90638b25d6b2462c475033da8carll      case 0x44E: case 0x4CE: case 0x54E: // vpkudum, vpkudus, vpksdus
2029948ae46b56cef87c90638b25d6b2462c475033da8carll      case 0x5CE: case 0x64E: case 0x6cE: // vpksdss, vupkhsw, vupklsw
203000c74bb5aa3240f693df0568d578baabf0c376dc4carll         if (!allow_isa_2_07) goto decode_noP8;
203010c74bb5aa3240f693df0568d578baabf0c376dc4carll         if (dis_av_pack( theInstr )) goto decode_success;
203020c74bb5aa3240f693df0568d578baabf0c376dc4carll         goto decode_failure;
203030c74bb5aa3240f693df0568d578baabf0c376dc4carll
203047deaf9552b546b847528cf39b38898fb7742b5f5carll      case 0x508: case 0x509:             // vcipher, vcipherlast
203057deaf9552b546b847528cf39b38898fb7742b5f5carll      case 0x548: case 0x549:             // vncipher, vncipherlast
203067deaf9552b546b847528cf39b38898fb7742b5f5carll      case 0x5C8:                         // vsbox
203077deaf9552b546b847528cf39b38898fb7742b5f5carll         if (!allow_isa_2_07) goto decode_noP8;
203087deaf9552b546b847528cf39b38898fb7742b5f5carll         if (dis_av_cipher( theInstr )) goto decode_success;
203097deaf9552b546b847528cf39b38898fb7742b5f5carll         goto decode_failure;
203107deaf9552b546b847528cf39b38898fb7742b5f5carll
203117deaf9552b546b847528cf39b38898fb7742b5f5carll      case 0x6C2: case 0x682:             // vshasigmaw, vshasigmad
203127deaf9552b546b847528cf39b38898fb7742b5f5carll         if (!allow_isa_2_07) goto decode_noP8;
203137deaf9552b546b847528cf39b38898fb7742b5f5carll         if (dis_av_hash( theInstr )) goto decode_success;
203147deaf9552b546b847528cf39b38898fb7742b5f5carll         goto decode_failure;
203157deaf9552b546b847528cf39b38898fb7742b5f5carll
203167deaf9552b546b847528cf39b38898fb7742b5f5carll      case 0x702: case 0x742:             // vclzb, vclzh
203177deaf9552b546b847528cf39b38898fb7742b5f5carll      case 0x782: case 0x7c2:             // vclzw, vclzd
203187deaf9552b546b847528cf39b38898fb7742b5f5carll         if (!allow_isa_2_07) goto decode_noP8;
2031960c6bac19ffe055cabab554e7877d73096a8bf17carll         if (dis_av_count_bitTranspose( theInstr, opc2 )) goto decode_success;
203207deaf9552b546b847528cf39b38898fb7742b5f5carll         goto decode_failure;
203217deaf9552b546b847528cf39b38898fb7742b5f5carll
203227deaf9552b546b847528cf39b38898fb7742b5f5carll      case 0x703: case 0x743:             // vpopcntb, vpopcnth
203237deaf9552b546b847528cf39b38898fb7742b5f5carll      case 0x783: case 0x7c3:             // vpopcntw, vpopcntd
203247deaf9552b546b847528cf39b38898fb7742b5f5carll         if (!allow_isa_2_07) goto decode_noP8;
2032560c6bac19ffe055cabab554e7877d73096a8bf17carll         if (dis_av_count_bitTranspose( theInstr, opc2 )) goto decode_success;
2032660c6bac19ffe055cabab554e7877d73096a8bf17carll         goto decode_failure;
2032760c6bac19ffe055cabab554e7877d73096a8bf17carll
2032860c6bac19ffe055cabab554e7877d73096a8bf17carll      case 0x50c:                         // vgbbd
2032960c6bac19ffe055cabab554e7877d73096a8bf17carll         if (!allow_isa_2_07) goto decode_noP8;
2033060c6bac19ffe055cabab554e7877d73096a8bf17carll         if (dis_av_count_bitTranspose( theInstr, opc2 )) goto decode_success;
2033160c6bac19ffe055cabab554e7877d73096a8bf17carll         goto decode_failure;
2033260c6bac19ffe055cabab554e7877d73096a8bf17carll
2033360c6bac19ffe055cabab554e7877d73096a8bf17carll      case 0x140: case 0x100:             // vaddcuq, vadduqm
2033460c6bac19ffe055cabab554e7877d73096a8bf17carll      case 0x540: case 0x500:             // vsubcuq, vsubuqm
2033560c6bac19ffe055cabab554e7877d73096a8bf17carll      case 0x54C:                         // vbpermq
2033660c6bac19ffe055cabab554e7877d73096a8bf17carll         if (!allow_V) goto decode_noV;
2033760c6bac19ffe055cabab554e7877d73096a8bf17carll         if (dis_av_quad( theInstr)) goto decode_success;
203387deaf9552b546b847528cf39b38898fb7742b5f5carll         goto decode_failure;
203397deaf9552b546b847528cf39b38898fb7742b5f5carll
2034032aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion      default:
2034132aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion         break;  // Fall through...
2034232aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion      }
2034332aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion
2034476de5cf615380b23b4b5bcced6541233cd4a93a0cerion      opc2 = IFIELD(theInstr, 0, 10);
2034532aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion      switch (opc2) {
2034632aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion
2034732aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion      /* AV Compare */
2034832aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion      case 0x006: case 0x046: case 0x086: // vcmpequb, vcmpequh, vcmpequw
2034932aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion      case 0x206: case 0x246: case 0x286: // vcmpgtub, vcmpgtuh, vcmpgtuw
2035032aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion      case 0x306: case 0x346: case 0x386: // vcmpgtsb, vcmpgtsh, vcmpgtsw
203515117ce116f47141cb23d1b49cc826e19323add97sewardj         if (!allow_V) goto decode_noV;
2035232aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion         if (dis_av_cmp( theInstr )) goto decode_success;
2035332aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion         goto decode_failure;
2035432aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion
2035548ae46b56cef87c90638b25d6b2462c475033da8carll      case 0x0C7:                         // vcmpequd
2035648ae46b56cef87c90638b25d6b2462c475033da8carll      case 0x2C7:                         // vcmpgtud
2035748ae46b56cef87c90638b25d6b2462c475033da8carll      case 0x3C7:                         // vcmpgtsd
2035848ae46b56cef87c90638b25d6b2462c475033da8carll          if (!allow_isa_2_07) goto decode_noP8;
2035948ae46b56cef87c90638b25d6b2462c475033da8carll          if (dis_av_cmp( theInstr )) goto decode_success;
2036048ae46b56cef87c90638b25d6b2462c475033da8carll          goto decode_failure;
2036148ae46b56cef87c90638b25d6b2462c475033da8carll
2036232aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion      /* AV Floating Point Compare */
2036332aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion      case 0x0C6: case 0x1C6: case 0x2C6: // vcmpeqfp, vcmpgefp, vcmpgtfp
2036432aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion      case 0x3C6:                         // vcmpbfp
203655117ce116f47141cb23d1b49cc826e19323add97sewardj         if (!allow_V) goto decode_noV;
2036632aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion         if (dis_av_fp_cmp( theInstr )) goto decode_success;
2036732aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion         goto decode_failure;
2036832aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion
2036932aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion      default:
2037032aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion         goto decode_failure;
2037132aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion      }
2037232aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion      break;
203737aa4bbc850d2978cccd8e12cd7c4cfeaa5ab3e4dcerion
20374896a1373cfdbaa25f4ab73ed4f27554016defecccerion   default:
203755b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion      goto decode_failure;
203765b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion
203775117ce116f47141cb23d1b49cc826e19323add97sewardj   decode_noF:
203785117ce116f47141cb23d1b49cc826e19323add97sewardj      vassert(!allow_F);
203790c4e9e8eef3824b085973cd6e2b1b39a1fd6062ecarll      vex_printf("disInstr(ppc): found the Floating Point instruction 0x%x that\n"
203800c4e9e8eef3824b085973cd6e2b1b39a1fd6062ecarll		 "can't be handled by Valgrind on this host.  This instruction\n"
203810c4e9e8eef3824b085973cd6e2b1b39a1fd6062ecarll		 "requires a host that supports Floating Point instructions.\n",
203820c4e9e8eef3824b085973cd6e2b1b39a1fd6062ecarll		 theInstr);
203830c4e9e8eef3824b085973cd6e2b1b39a1fd6062ecarll      goto not_supported;
203845117ce116f47141cb23d1b49cc826e19323add97sewardj   decode_noV:
203855117ce116f47141cb23d1b49cc826e19323add97sewardj      vassert(!allow_V);
203860c4e9e8eef3824b085973cd6e2b1b39a1fd6062ecarll      vex_printf("disInstr(ppc): found an AltiVec or an e500 instruction 0x%x\n"
203870c4e9e8eef3824b085973cd6e2b1b39a1fd6062ecarll		 "that can't be handled by Valgrind.  If this instruction is an\n"
203880c4e9e8eef3824b085973cd6e2b1b39a1fd6062ecarll		 "Altivec instruction, Valgrind must be run on a host that supports"
203890c4e9e8eef3824b085973cd6e2b1b39a1fd6062ecarll		 "AltiVec instructions.  If the application was compiled for e500, then\n"
203900c4e9e8eef3824b085973cd6e2b1b39a1fd6062ecarll		 "unfortunately Valgrind does not yet support e500 instructions.\n",
203910c4e9e8eef3824b085973cd6e2b1b39a1fd6062ecarll		 theInstr);
203920c4e9e8eef3824b085973cd6e2b1b39a1fd6062ecarll      goto not_supported;
2039366d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj   decode_noVX:
2039466d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj      vassert(!allow_VX);
203950c4e9e8eef3824b085973cd6e2b1b39a1fd6062ecarll      vex_printf("disInstr(ppc): found the instruction 0x%x that is defined in the\n"
203960c4e9e8eef3824b085973cd6e2b1b39a1fd6062ecarll		 "Power ISA 2.06 ABI but can't be handled by Valgrind on this host.\n"
203970c4e9e8eef3824b085973cd6e2b1b39a1fd6062ecarll		 "This instruction \nrequires a host that supports the ISA 2.06 ABI.\n",
203980c4e9e8eef3824b085973cd6e2b1b39a1fd6062ecarll		 theInstr);
203990c4e9e8eef3824b085973cd6e2b1b39a1fd6062ecarll      goto not_supported;
204005117ce116f47141cb23d1b49cc826e19323add97sewardj   decode_noFX:
204017c5458604bde543a8567e16df74fb2157b79e844sewardj      vassert(!allow_FX);
204020c4e9e8eef3824b085973cd6e2b1b39a1fd6062ecarll      vex_printf("disInstr(ppc): found the General Purpose-Optional instruction 0x%x\n"
204030c4e9e8eef3824b085973cd6e2b1b39a1fd6062ecarll		 "that can't be handled by Valgrind on this host. This instruction\n"
204040c4e9e8eef3824b085973cd6e2b1b39a1fd6062ecarll		 "requires a host that supports the General Purpose-Optional instructions.\n",
204050c4e9e8eef3824b085973cd6e2b1b39a1fd6062ecarll		 theInstr);
204060c4e9e8eef3824b085973cd6e2b1b39a1fd6062ecarll      goto not_supported;
204075117ce116f47141cb23d1b49cc826e19323add97sewardj   decode_noGX:
204087c5458604bde543a8567e16df74fb2157b79e844sewardj      vassert(!allow_GX);
204090c4e9e8eef3824b085973cd6e2b1b39a1fd6062ecarll      vex_printf("disInstr(ppc): found the Graphics-Optional instruction 0x%x\n"
204100c4e9e8eef3824b085973cd6e2b1b39a1fd6062ecarll		 "that can't be handled by Valgrind on this host. This instruction\n"
204110c4e9e8eef3824b085973cd6e2b1b39a1fd6062ecarll		 "requires a host that supports the Graphic-Optional instructions.\n",
204120c4e9e8eef3824b085973cd6e2b1b39a1fd6062ecarll		 theInstr);
204130c4e9e8eef3824b085973cd6e2b1b39a1fd6062ecarll      goto not_supported;
20414c66d6fa5d9397f167b162483cf3419051cc01a80sewardj   decode_noDFP:
20415c66d6fa5d9397f167b162483cf3419051cc01a80sewardj      vassert(!allow_DFP);
204160c4e9e8eef3824b085973cd6e2b1b39a1fd6062ecarll      vex_printf("disInstr(ppc): found the decimal floating point (DFP) instruction 0x%x\n"
204170c4e9e8eef3824b085973cd6e2b1b39a1fd6062ecarll		 "that can't be handled by Valgrind on this host.  This instruction\n"
204180c4e9e8eef3824b085973cd6e2b1b39a1fd6062ecarll		 "requires a host that supports DFP instructions.\n",
204190c4e9e8eef3824b085973cd6e2b1b39a1fd6062ecarll		 theInstr);
204200c4e9e8eef3824b085973cd6e2b1b39a1fd6062ecarll      goto not_supported;
204210c74bb5aa3240f693df0568d578baabf0c376dc4carll   decode_noP8:
204220c74bb5aa3240f693df0568d578baabf0c376dc4carll      vassert(!allow_isa_2_07);
204230c4e9e8eef3824b085973cd6e2b1b39a1fd6062ecarll      vex_printf("disInstr(ppc): found the Power 8 instruction 0x%x that can't be handled\n"
204240c4e9e8eef3824b085973cd6e2b1b39a1fd6062ecarll		 "by Valgrind on this host.  This instruction requires a host that\n"
204250c4e9e8eef3824b085973cd6e2b1b39a1fd6062ecarll		 "supports Power 8 instructions.\n",
204260c4e9e8eef3824b085973cd6e2b1b39a1fd6062ecarll		 theInstr);
204270c4e9e8eef3824b085973cd6e2b1b39a1fd6062ecarll      goto not_supported;
20428c66d6fa5d9397f167b162483cf3419051cc01a80sewardj
204295b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion
20430896a1373cfdbaa25f4ab73ed4f27554016defecccerion   decode_failure:
20431896a1373cfdbaa25f4ab73ed4f27554016defecccerion   /* All decode failures end up here. */
20432225a034683024109da729a4d2f080364b9485007cerion   opc2 = (theInstr) & 0x7FF;
20433442e51a26cf3bc7f243167a4ff3fbfb02206f6e6sewardj   if (sigill_diag) {
20434442e51a26cf3bc7f243167a4ff3fbfb02206f6e6sewardj      vex_printf("disInstr(ppc): unhandled instruction: "
20435442e51a26cf3bc7f243167a4ff3fbfb02206f6e6sewardj                 "0x%x\n", theInstr);
20436442e51a26cf3bc7f243167a4ff3fbfb02206f6e6sewardj      vex_printf("                 primary %d(0x%x), secondary %u(0x%x)\n",
20437442e51a26cf3bc7f243167a4ff3fbfb02206f6e6sewardj                 opc1, opc1, opc2, opc2);
20438442e51a26cf3bc7f243167a4ff3fbfb02206f6e6sewardj   }
20439995bc3600091747f64a3ac2d9a7fed6b41c3c88dcerion
204400c4e9e8eef3824b085973cd6e2b1b39a1fd6062ecarll   not_supported:
2044101a9e808708130f82e935336c887c1bee2d89036sewardj   /* Tell the dispatcher that this insn cannot be decoded, and so has
2044201a9e808708130f82e935336c887c1bee2d89036sewardj      not been executed, and (is currently) the next to be executed.
2044301a9e808708130f82e935336c887c1bee2d89036sewardj      CIA should be up-to-date since it made so at the start of each
2044401a9e808708130f82e935336c887c1bee2d89036sewardj      insn, but nevertheless be paranoid and update it again right
2044501a9e808708130f82e935336c887c1bee2d89036sewardj      now. */
204462831b00c4950d6c2b061def05fd67528fe132ececerion   putGST( PPC_GST_CIA, mkSzImm(ty, guest_CIA_curr_instr) );
204472faf591d71d355911e35cbcd351fe78b6c986207philippe   dres.len         = 0;
204483dee849ec7c38746749065e67dc53b75daa7617dsewardj   dres.whatNext    = Dis_StopHere;
204493dee849ec7c38746749065e67dc53b75daa7617dsewardj   dres.jk_StopHere = Ijk_NoDecode;
204502faf591d71d355911e35cbcd351fe78b6c986207philippe   dres.continueAt  = 0;
204519e6491ab55324b8e45e187b1e1e9632ac3cb3e27sewardj   return dres;
20452896a1373cfdbaa25f4ab73ed4f27554016defecccerion   } /* switch (opc) for the main (primary) opcode switch. */
20453896a1373cfdbaa25f4ab73ed4f27554016defecccerion
20454896a1373cfdbaa25f4ab73ed4f27554016defecccerion  decode_success:
20455896a1373cfdbaa25f4ab73ed4f27554016defecccerion   /* All decode successes end up here. */
204563dee849ec7c38746749065e67dc53b75daa7617dsewardj   switch (dres.whatNext) {
204573dee849ec7c38746749065e67dc53b75daa7617dsewardj      case Dis_Continue:
204583dee849ec7c38746749065e67dc53b75daa7617dsewardj         putGST( PPC_GST_CIA, mkSzImm(ty, guest_CIA_curr_instr + 4));
204593dee849ec7c38746749065e67dc53b75daa7617dsewardj         break;
204603dee849ec7c38746749065e67dc53b75daa7617dsewardj      case Dis_ResteerU:
204613dee849ec7c38746749065e67dc53b75daa7617dsewardj      case Dis_ResteerC:
204623dee849ec7c38746749065e67dc53b75daa7617dsewardj         putGST( PPC_GST_CIA, mkSzImm(ty, dres.continueAt));
204633dee849ec7c38746749065e67dc53b75daa7617dsewardj         break;
204643dee849ec7c38746749065e67dc53b75daa7617dsewardj      case Dis_StopHere:
204653dee849ec7c38746749065e67dc53b75daa7617dsewardj         break;
204663dee849ec7c38746749065e67dc53b75daa7617dsewardj      default:
204673dee849ec7c38746749065e67dc53b75daa7617dsewardj         vassert(0);
204683dee849ec7c38746749065e67dc53b75daa7617dsewardj   }
20469896a1373cfdbaa25f4ab73ed4f27554016defecccerion   DIP("\n");
20470896a1373cfdbaa25f4ab73ed4f27554016defecccerion
20471ce02aa77bc02dbe225a068df0fb6b31faddedcdfsewardj   if (dres.len == 0) {
20472ce02aa77bc02dbe225a068df0fb6b31faddedcdfsewardj      dres.len = 4;
20473ce02aa77bc02dbe225a068df0fb6b31faddedcdfsewardj   } else {
20474ce02aa77bc02dbe225a068df0fb6b31faddedcdfsewardj      vassert(dres.len == 20);
20475ce02aa77bc02dbe225a068df0fb6b31faddedcdfsewardj   }
204769e6491ab55324b8e45e187b1e1e9632ac3cb3e27sewardj   return dres;
20477896a1373cfdbaa25f4ab73ed4f27554016defecccerion}
20478896a1373cfdbaa25f4ab73ed4f27554016defecccerion
20479896a1373cfdbaa25f4ab73ed4f27554016defecccerion#undef DIP
20480896a1373cfdbaa25f4ab73ed4f27554016defecccerion#undef DIS
20481896a1373cfdbaa25f4ab73ed4f27554016defecccerion
204829e6491ab55324b8e45e187b1e1e9632ac3cb3e27sewardj
204839e6491ab55324b8e45e187b1e1e9632ac3cb3e27sewardj/*------------------------------------------------------------*/
204849e6491ab55324b8e45e187b1e1e9632ac3cb3e27sewardj/*--- Top-level fn                                         ---*/
204859e6491ab55324b8e45e187b1e1e9632ac3cb3e27sewardj/*------------------------------------------------------------*/
204869e6491ab55324b8e45e187b1e1e9632ac3cb3e27sewardj
204879e6491ab55324b8e45e187b1e1e9632ac3cb3e27sewardj/* Disassemble a single instruction into IR.  The instruction
204889e6491ab55324b8e45e187b1e1e9632ac3cb3e27sewardj   is located in host memory at &guest_code[delta]. */
204899e6491ab55324b8e45e187b1e1e9632ac3cb3e27sewardj
20490dd40fdf58cc8a6fe9466c4f00bdfc9fe9bf00449sewardjDisResult disInstr_PPC ( IRSB*        irsb_IN,
20491beac530a718fcc646bc61fe60a86f599df54e1d7florian                         Bool         (*resteerOkFn) ( void*, Addr ),
20492984d9b164dd17f07e603c41fe1e506e641e57d18sewardj                         Bool         resteerCisOk,
20493c716aea1cafe66ee431dc7d6909c98f18788a028sewardj                         void*        callback_opaque,
204948462d113e3efeacceb304222dada8d85f748295aflorian                         const UChar* guest_code_IN,
204955b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion                         Long         delta,
20496d4cc0deec55ec0be1f2ac3b20f0d340265341f83florian                         Addr         guest_IP,
20497a5f55da7e956978fddad927436da5fab9568f3f1sewardj                         VexArch      guest_arch,
20498cacba8e675988fbf21b08feea1f317a9c896c053florian                         const VexArchInfo* archinfo,
20499cacba8e675988fbf21b08feea1f317a9c896c053florian                         const VexAbiInfo*  abiinfo,
205009b76916dcc1628e133d57db001563429c6e3a590sewardj                         VexEndness   host_endness_IN,
20501442e51a26cf3bc7f243167a4ff3fbfb02206f6e6sewardj                         Bool         sigill_diag_IN )
205029e6491ab55324b8e45e187b1e1e9632ac3cb3e27sewardj{
205035df65bb742f389a45657a0a6f4a9e46a33025407sewardj   IRType     ty;
205045df65bb742f389a45657a0a6f4a9e46a33025407sewardj   DisResult  dres;
205055117ce116f47141cb23d1b49cc826e19323add97sewardj   UInt       mask32, mask64;
205065117ce116f47141cb23d1b49cc826e19323add97sewardj   UInt hwcaps_guest = archinfo->hwcaps;
205075117ce116f47141cb23d1b49cc826e19323add97sewardj
20508a5f55da7e956978fddad927436da5fab9568f3f1sewardj   vassert(guest_arch == VexArchPPC32 || guest_arch == VexArchPPC64);
20509a5f55da7e956978fddad927436da5fab9568f3f1sewardj
205105117ce116f47141cb23d1b49cc826e19323add97sewardj   /* global -- ick */
20511a5f55da7e956978fddad927436da5fab9568f3f1sewardj   mode64 = guest_arch == VexArchPPC64;
20512a5f55da7e956978fddad927436da5fab9568f3f1sewardj   ty = mode64 ? Ity_I64 : Ity_I32;
205131f5fe1fc3a37ca729925e8eec25aa1025b4a6cdbcarll   if (!mode64 && (host_endness_IN == VexEndnessLE)) {
205141f5fe1fc3a37ca729925e8eec25aa1025b4a6cdbcarll      vex_printf("disInstr(ppc): Little Endian 32-bit mode is not supported\n");
205152faf591d71d355911e35cbcd351fe78b6c986207philippe      dres.len         = 0;
205161f5fe1fc3a37ca729925e8eec25aa1025b4a6cdbcarll      dres.whatNext    = Dis_StopHere;
205171f5fe1fc3a37ca729925e8eec25aa1025b4a6cdbcarll      dres.jk_StopHere = Ijk_NoDecode;
2051899af243417cc0182062d4c3ea8f521940a1089f1philippe      dres.continueAt   = 0;
205191f5fe1fc3a37ca729925e8eec25aa1025b4a6cdbcarll      return dres;
205201f5fe1fc3a37ca729925e8eec25aa1025b4a6cdbcarll   }
205215df65bb742f389a45657a0a6f4a9e46a33025407sewardj
20522a5f55da7e956978fddad927436da5fab9568f3f1sewardj   /* do some sanity checks */
205235117ce116f47141cb23d1b49cc826e19323add97sewardj   mask32 = VEX_HWCAPS_PPC32_F | VEX_HWCAPS_PPC32_V
20524c66d6fa5d9397f167b162483cf3419051cc01a80sewardj            | VEX_HWCAPS_PPC32_FX | VEX_HWCAPS_PPC32_GX | VEX_HWCAPS_PPC32_VX
205250c74bb5aa3240f693df0568d578baabf0c376dc4carll            | VEX_HWCAPS_PPC32_DFP | VEX_HWCAPS_PPC32_ISA2_07;
205265117ce116f47141cb23d1b49cc826e19323add97sewardj
2052766d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj   mask64 = VEX_HWCAPS_PPC64_V | VEX_HWCAPS_PPC64_FX
205280c74bb5aa3240f693df0568d578baabf0c376dc4carll            | VEX_HWCAPS_PPC64_GX | VEX_HWCAPS_PPC64_VX | VEX_HWCAPS_PPC64_DFP
205290c74bb5aa3240f693df0568d578baabf0c376dc4carll            | VEX_HWCAPS_PPC64_ISA2_07;
205305117ce116f47141cb23d1b49cc826e19323add97sewardj
20531a5f55da7e956978fddad927436da5fab9568f3f1sewardj   if (mode64) {
20532a5f55da7e956978fddad927436da5fab9568f3f1sewardj      vassert((hwcaps_guest & mask32) == 0);
20533a5f55da7e956978fddad927436da5fab9568f3f1sewardj   } else {
20534a5f55da7e956978fddad927436da5fab9568f3f1sewardj      vassert((hwcaps_guest & mask64) == 0);
20535a5f55da7e956978fddad927436da5fab9568f3f1sewardj   }
205369e6491ab55324b8e45e187b1e1e9632ac3cb3e27sewardj
205379e6491ab55324b8e45e187b1e1e9632ac3cb3e27sewardj   /* Set globals (see top of this file) */
205389e6491ab55324b8e45e187b1e1e9632ac3cb3e27sewardj   guest_code           = guest_code_IN;
20539dd40fdf58cc8a6fe9466c4f00bdfc9fe9bf00449sewardj   irsb                 = irsb_IN;
205409b76916dcc1628e133d57db001563429c6e3a590sewardj   host_endness         = host_endness_IN;
20541d953ebb9b04cbad6891676df597bf0c542b1ec89cerion
205422831b00c4950d6c2b061def05fd67528fe132ececerion   guest_CIA_curr_instr = mkSzAddr(ty, guest_IP);
205432831b00c4950d6c2b061def05fd67528fe132ececerion   guest_CIA_bbstart    = mkSzAddr(ty, guest_IP - delta);
205449e6491ab55324b8e45e187b1e1e9632ac3cb3e27sewardj
205453dee849ec7c38746749065e67dc53b75daa7617dsewardj   dres = disInstr_PPC_WRK ( resteerOkFn, resteerCisOk, callback_opaque,
205461f5fe1fc3a37ca729925e8eec25aa1025b4a6cdbcarll                             delta, archinfo, abiinfo, sigill_diag_IN);
205479e6491ab55324b8e45e187b1e1e9632ac3cb3e27sewardj
205489e6491ab55324b8e45e187b1e1e9632ac3cb3e27sewardj   return dres;
205499e6491ab55324b8e45e187b1e1e9632ac3cb3e27sewardj}
205509e6491ab55324b8e45e187b1e1e9632ac3cb3e27sewardj
205519e6491ab55324b8e45e187b1e1e9632ac3cb3e27sewardj
20552c808ef7dfe40c18e589490ab1f3980b7b04789ecsewardj/*------------------------------------------------------------*/
20553c808ef7dfe40c18e589490ab1f3980b7b04789ecsewardj/*--- Unused stuff                                         ---*/
20554c808ef7dfe40c18e589490ab1f3980b7b04789ecsewardj/*------------------------------------------------------------*/
20555c808ef7dfe40c18e589490ab1f3980b7b04789ecsewardj
20556c808ef7dfe40c18e589490ab1f3980b7b04789ecsewardj///* A potentially more memcheck-friendly implementation of Clz32, with
20557c808ef7dfe40c18e589490ab1f3980b7b04789ecsewardj//   the boundary case Clz32(0) = 32, which is what ppc requires. */
20558c808ef7dfe40c18e589490ab1f3980b7b04789ecsewardj//
20559c808ef7dfe40c18e589490ab1f3980b7b04789ecsewardj//static IRExpr* /* :: Ity_I32 */ verbose_Clz32 ( IRTemp arg )
20560c808ef7dfe40c18e589490ab1f3980b7b04789ecsewardj//{
20561c808ef7dfe40c18e589490ab1f3980b7b04789ecsewardj//   /* Welcome ... to SSA R Us. */
20562c808ef7dfe40c18e589490ab1f3980b7b04789ecsewardj//   IRTemp n1  = newTemp(Ity_I32);
20563c808ef7dfe40c18e589490ab1f3980b7b04789ecsewardj//   IRTemp n2  = newTemp(Ity_I32);
20564c808ef7dfe40c18e589490ab1f3980b7b04789ecsewardj//   IRTemp n3  = newTemp(Ity_I32);
20565c808ef7dfe40c18e589490ab1f3980b7b04789ecsewardj//   IRTemp n4  = newTemp(Ity_I32);
20566c808ef7dfe40c18e589490ab1f3980b7b04789ecsewardj//   IRTemp n5  = newTemp(Ity_I32);
20567c808ef7dfe40c18e589490ab1f3980b7b04789ecsewardj//   IRTemp n6  = newTemp(Ity_I32);
20568c808ef7dfe40c18e589490ab1f3980b7b04789ecsewardj//   IRTemp n7  = newTemp(Ity_I32);
20569c808ef7dfe40c18e589490ab1f3980b7b04789ecsewardj//   IRTemp n8  = newTemp(Ity_I32);
20570c808ef7dfe40c18e589490ab1f3980b7b04789ecsewardj//   IRTemp n9  = newTemp(Ity_I32);
20571c808ef7dfe40c18e589490ab1f3980b7b04789ecsewardj//   IRTemp n10 = newTemp(Ity_I32);
20572c808ef7dfe40c18e589490ab1f3980b7b04789ecsewardj//   IRTemp n11 = newTemp(Ity_I32);
20573c808ef7dfe40c18e589490ab1f3980b7b04789ecsewardj//   IRTemp n12 = newTemp(Ity_I32);
20574c808ef7dfe40c18e589490ab1f3980b7b04789ecsewardj//
20575c808ef7dfe40c18e589490ab1f3980b7b04789ecsewardj//   /* First, propagate the most significant 1-bit into all lower
20576c808ef7dfe40c18e589490ab1f3980b7b04789ecsewardj//      positions in the word. */
20577c808ef7dfe40c18e589490ab1f3980b7b04789ecsewardj//   /* unsigned int clz ( unsigned int n )
20578c808ef7dfe40c18e589490ab1f3980b7b04789ecsewardj//      {
20579c808ef7dfe40c18e589490ab1f3980b7b04789ecsewardj//         n |= (n >> 1);
20580c808ef7dfe40c18e589490ab1f3980b7b04789ecsewardj//         n |= (n >> 2);
20581c808ef7dfe40c18e589490ab1f3980b7b04789ecsewardj//         n |= (n >> 4);
20582c808ef7dfe40c18e589490ab1f3980b7b04789ecsewardj//         n |= (n >> 8);
20583c808ef7dfe40c18e589490ab1f3980b7b04789ecsewardj//         n |= (n >> 16);
20584c808ef7dfe40c18e589490ab1f3980b7b04789ecsewardj//         return bitcount(~n);
20585c808ef7dfe40c18e589490ab1f3980b7b04789ecsewardj//      }
20586c808ef7dfe40c18e589490ab1f3980b7b04789ecsewardj//   */
20587c808ef7dfe40c18e589490ab1f3980b7b04789ecsewardj//   assign(n1, mkexpr(arg));
20588c808ef7dfe40c18e589490ab1f3980b7b04789ecsewardj//   assign(n2, binop(Iop_Or32, mkexpr(n1), binop(Iop_Shr32, mkexpr(n1), mkU8(1))));
20589c808ef7dfe40c18e589490ab1f3980b7b04789ecsewardj//   assign(n3, binop(Iop_Or32, mkexpr(n2), binop(Iop_Shr32, mkexpr(n2), mkU8(2))));
20590c808ef7dfe40c18e589490ab1f3980b7b04789ecsewardj//   assign(n4, binop(Iop_Or32, mkexpr(n3), binop(Iop_Shr32, mkexpr(n3), mkU8(4))));
20591c808ef7dfe40c18e589490ab1f3980b7b04789ecsewardj//   assign(n5, binop(Iop_Or32, mkexpr(n4), binop(Iop_Shr32, mkexpr(n4), mkU8(8))));
20592c808ef7dfe40c18e589490ab1f3980b7b04789ecsewardj//   assign(n6, binop(Iop_Or32, mkexpr(n5), binop(Iop_Shr32, mkexpr(n5), mkU8(16))));
20593c808ef7dfe40c18e589490ab1f3980b7b04789ecsewardj//   /* This gives a word of the form 0---01---1.  Now invert it, giving
20594c808ef7dfe40c18e589490ab1f3980b7b04789ecsewardj//      a word of the form 1---10---0, then do a population-count idiom
20595c808ef7dfe40c18e589490ab1f3980b7b04789ecsewardj//      (to count the 1s, which is the number of leading zeroes, or 32
20596c808ef7dfe40c18e589490ab1f3980b7b04789ecsewardj//      if the original word was 0. */
20597c808ef7dfe40c18e589490ab1f3980b7b04789ecsewardj//   assign(n7, unop(Iop_Not32, mkexpr(n6)));
20598c808ef7dfe40c18e589490ab1f3980b7b04789ecsewardj//
20599c808ef7dfe40c18e589490ab1f3980b7b04789ecsewardj//   /* unsigned int bitcount ( unsigned int n )
20600c808ef7dfe40c18e589490ab1f3980b7b04789ecsewardj//      {
20601c808ef7dfe40c18e589490ab1f3980b7b04789ecsewardj//         n = n - ((n >> 1) & 0x55555555);
20602c808ef7dfe40c18e589490ab1f3980b7b04789ecsewardj//         n = (n & 0x33333333) + ((n >> 2) & 0x33333333);
20603c808ef7dfe40c18e589490ab1f3980b7b04789ecsewardj//         n = (n + (n >> 4)) & 0x0F0F0F0F;
20604c808ef7dfe40c18e589490ab1f3980b7b04789ecsewardj//         n = n + (n >> 8);
20605c808ef7dfe40c18e589490ab1f3980b7b04789ecsewardj//         n = (n + (n >> 16)) & 0x3F;
20606c808ef7dfe40c18e589490ab1f3980b7b04789ecsewardj//         return n;
20607c808ef7dfe40c18e589490ab1f3980b7b04789ecsewardj//      }
20608c808ef7dfe40c18e589490ab1f3980b7b04789ecsewardj//   */
20609c808ef7dfe40c18e589490ab1f3980b7b04789ecsewardj//   assign(n8,
20610c808ef7dfe40c18e589490ab1f3980b7b04789ecsewardj//          binop(Iop_Sub32,
20611c808ef7dfe40c18e589490ab1f3980b7b04789ecsewardj//                mkexpr(n7),
20612c808ef7dfe40c18e589490ab1f3980b7b04789ecsewardj//                binop(Iop_And32,
20613c808ef7dfe40c18e589490ab1f3980b7b04789ecsewardj//                      binop(Iop_Shr32, mkexpr(n7), mkU8(1)),
20614c808ef7dfe40c18e589490ab1f3980b7b04789ecsewardj//                      mkU32(0x55555555))));
20615c808ef7dfe40c18e589490ab1f3980b7b04789ecsewardj//   assign(n9,
20616c808ef7dfe40c18e589490ab1f3980b7b04789ecsewardj//          binop(Iop_Add32,
20617c808ef7dfe40c18e589490ab1f3980b7b04789ecsewardj//                binop(Iop_And32, mkexpr(n8), mkU32(0x33333333)),
20618c808ef7dfe40c18e589490ab1f3980b7b04789ecsewardj//                binop(Iop_And32,
20619c808ef7dfe40c18e589490ab1f3980b7b04789ecsewardj//                      binop(Iop_Shr32, mkexpr(n8), mkU8(2)),
20620c808ef7dfe40c18e589490ab1f3980b7b04789ecsewardj//                      mkU32(0x33333333))));
20621c808ef7dfe40c18e589490ab1f3980b7b04789ecsewardj//   assign(n10,
20622c808ef7dfe40c18e589490ab1f3980b7b04789ecsewardj//          binop(Iop_And32,
20623c808ef7dfe40c18e589490ab1f3980b7b04789ecsewardj//                binop(Iop_Add32,
20624c808ef7dfe40c18e589490ab1f3980b7b04789ecsewardj//                      mkexpr(n9),
20625c808ef7dfe40c18e589490ab1f3980b7b04789ecsewardj//                      binop(Iop_Shr32, mkexpr(n9), mkU8(4))),
20626c808ef7dfe40c18e589490ab1f3980b7b04789ecsewardj//                mkU32(0x0F0F0F0F)));
20627c808ef7dfe40c18e589490ab1f3980b7b04789ecsewardj//   assign(n11,
20628c808ef7dfe40c18e589490ab1f3980b7b04789ecsewardj//          binop(Iop_Add32,
20629c808ef7dfe40c18e589490ab1f3980b7b04789ecsewardj//                mkexpr(n10),
20630c808ef7dfe40c18e589490ab1f3980b7b04789ecsewardj//                binop(Iop_Shr32, mkexpr(n10), mkU8(8))));
20631c808ef7dfe40c18e589490ab1f3980b7b04789ecsewardj//   assign(n12,
20632c808ef7dfe40c18e589490ab1f3980b7b04789ecsewardj//          binop(Iop_Add32,
20633c808ef7dfe40c18e589490ab1f3980b7b04789ecsewardj//                mkexpr(n11),
20634c808ef7dfe40c18e589490ab1f3980b7b04789ecsewardj//                binop(Iop_Shr32, mkexpr(n11), mkU8(16))));
20635c808ef7dfe40c18e589490ab1f3980b7b04789ecsewardj//   return
20636c808ef7dfe40c18e589490ab1f3980b7b04789ecsewardj//      binop(Iop_And32, mkexpr(n12), mkU32(0x3F));
20637c808ef7dfe40c18e589490ab1f3980b7b04789ecsewardj//}
20638c808ef7dfe40c18e589490ab1f3980b7b04789ecsewardj
20639896a1373cfdbaa25f4ab73ed4f27554016defecccerion/*--------------------------------------------------------------------*/
20640cef7d3e3df4796e35b4521158d9dc058f034aa87sewardj/*--- end                                         guest_ppc_toIR.c ---*/
20641896a1373cfdbaa25f4ab73ed4f27554016defecccerion/*--------------------------------------------------------------------*/
20642