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
1089ae8477745fd2a15453557d729a50e627325ee2sewardj   Copyright (C) 2004-2013 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)
2915ff11ddafe3e0080711657a1cf581e1a64dbf117sewardj
29291ad5368eb6354ad4fabc86f2b2e641736997a38cerion
2933867460f7533d6dc4e2c85656664ee341ea81e7dcerion/*------------------------------------------------------------*/
294b51f0f4f33256638ed953156a2635aa739b232f1sewardj/*--- Extract instruction fields                          --- */
2953867460f7533d6dc4e2c85656664ee341ea81e7dcerion/*------------------------------------------------------------*/
296e9d361ab43518b6dfbd3d846f48859534659dee0cerion
29776de5cf615380b23b4b5bcced6541233cd4a93a0cerion/* Extract field from insn, given idx (zero = lsb) and field length */
29876de5cf615380b23b4b5bcced6541233cd4a93a0cerion#define IFIELD( insn, idx, len ) ((insn >> idx) & ((1<<len)-1))
29976de5cf615380b23b4b5bcced6541233cd4a93a0cerion
300b51f0f4f33256638ed953156a2635aa739b232f1sewardj/* Extract primary opcode, instr[31:26] */
30176de5cf615380b23b4b5bcced6541233cd4a93a0cerionstatic UChar ifieldOPC( UInt instr ) {
30276de5cf615380b23b4b5bcced6541233cd4a93a0cerion   return toUChar( IFIELD( instr, 26, 6 ) );
303b51f0f4f33256638ed953156a2635aa739b232f1sewardj}
304b51f0f4f33256638ed953156a2635aa739b232f1sewardj
30576de5cf615380b23b4b5bcced6541233cd4a93a0cerion/* Extract 10-bit secondary opcode, instr[10:1] */
306b51f0f4f33256638ed953156a2635aa739b232f1sewardjstatic UInt ifieldOPClo10 ( UInt instr) {
30776de5cf615380b23b4b5bcced6541233cd4a93a0cerion   return IFIELD( instr, 1, 10 );
30876de5cf615380b23b4b5bcced6541233cd4a93a0cerion}
30976de5cf615380b23b4b5bcced6541233cd4a93a0cerion
31076de5cf615380b23b4b5bcced6541233cd4a93a0cerion/* Extract 9-bit secondary opcode, instr[9:1] */
31176de5cf615380b23b4b5bcced6541233cd4a93a0cerionstatic UInt ifieldOPClo9 ( UInt instr) {
31276de5cf615380b23b4b5bcced6541233cd4a93a0cerion   return IFIELD( instr, 1, 9 );
31376de5cf615380b23b4b5bcced6541233cd4a93a0cerion}
31476de5cf615380b23b4b5bcced6541233cd4a93a0cerion
315cdc376dcb5a4560b0a35d4abcb2146c499756f0dsewardj/* Extract 8-bit secondary opcode, instr[8:1] */
316cdc376dcb5a4560b0a35d4abcb2146c499756f0dsewardjstatic UInt ifieldOPClo8 ( UInt instr) {
317cdc376dcb5a4560b0a35d4abcb2146c499756f0dsewardj   return IFIELD( instr, 1, 8 );
318cdc376dcb5a4560b0a35d4abcb2146c499756f0dsewardj}
319cdc376dcb5a4560b0a35d4abcb2146c499756f0dsewardj
32076de5cf615380b23b4b5bcced6541233cd4a93a0cerion/* Extract 5-bit secondary opcode, instr[5:1] */
32176de5cf615380b23b4b5bcced6541233cd4a93a0cerionstatic UInt ifieldOPClo5 ( UInt instr) {
32276de5cf615380b23b4b5bcced6541233cd4a93a0cerion   return IFIELD( instr, 1, 5 );
323b51f0f4f33256638ed953156a2635aa739b232f1sewardj}
324b51f0f4f33256638ed953156a2635aa739b232f1sewardj
325b51f0f4f33256638ed953156a2635aa739b232f1sewardj/* Extract RD (destination register) field, instr[25:21] */
32676de5cf615380b23b4b5bcced6541233cd4a93a0cerionstatic UChar ifieldRegDS( UInt instr ) {
32776de5cf615380b23b4b5bcced6541233cd4a93a0cerion   return toUChar( IFIELD( instr, 21, 5 ) );
32876de5cf615380b23b4b5bcced6541233cd4a93a0cerion}
32976de5cf615380b23b4b5bcced6541233cd4a93a0cerion
33066d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj/* Extract XT (destination register) field, instr[0,25:21] */
33166d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardjstatic UChar ifieldRegXT ( UInt instr )
33266d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj{
33366d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj  UChar upper_bit = toUChar (IFIELD (instr, 0, 1));
33466d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj  UChar lower_bits = toUChar (IFIELD (instr, 21, 5));
33566d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj  return (upper_bit << 5) | lower_bits;
33666d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj}
33766d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj
33866d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj/* Extract XS (store source register) field, instr[0,25:21] */
33966d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardjstatic inline UChar ifieldRegXS ( UInt instr )
34066d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj{
34166d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj  return ifieldRegXT ( instr );
34266d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj}
34366d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj
34476de5cf615380b23b4b5bcced6541233cd4a93a0cerion/* Extract RA (1st source register) field, instr[20:16] */
34576de5cf615380b23b4b5bcced6541233cd4a93a0cerionstatic UChar ifieldRegA ( UInt instr ) {
34676de5cf615380b23b4b5bcced6541233cd4a93a0cerion   return toUChar( IFIELD( instr, 16, 5 ) );
34776de5cf615380b23b4b5bcced6541233cd4a93a0cerion}
34876de5cf615380b23b4b5bcced6541233cd4a93a0cerion
34966d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj/* Extract XA (1st source register) field, instr[2,20:16] */
35066d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardjstatic UChar ifieldRegXA ( UInt instr )
35166d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj{
35266d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj  UChar upper_bit = toUChar (IFIELD (instr, 2, 1));
35366d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj  UChar lower_bits = toUChar (IFIELD (instr, 16, 5));
35466d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj  return (upper_bit << 5) | lower_bits;
35566d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj}
35666d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj
35776de5cf615380b23b4b5bcced6541233cd4a93a0cerion/* Extract RB (2nd source register) field, instr[15:11] */
35876de5cf615380b23b4b5bcced6541233cd4a93a0cerionstatic UChar ifieldRegB ( UInt instr ) {
35976de5cf615380b23b4b5bcced6541233cd4a93a0cerion   return toUChar( IFIELD( instr, 11, 5 ) );
360b51f0f4f33256638ed953156a2635aa739b232f1sewardj}
361b51f0f4f33256638ed953156a2635aa739b232f1sewardj
36266d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj/* Extract XB (2nd source register) field, instr[1,15:11] */
36366d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardjstatic UChar ifieldRegXB ( UInt instr )
36466d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj{
36566d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj  UChar upper_bit = toUChar (IFIELD (instr, 1, 1));
36666d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj  UChar lower_bits = toUChar (IFIELD (instr, 11, 5));
36766d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj  return (upper_bit << 5) | lower_bits;
36866d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj}
36966d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj
37076de5cf615380b23b4b5bcced6541233cd4a93a0cerion/* Extract RC (3rd source register) field, instr[10:6] */
37176de5cf615380b23b4b5bcced6541233cd4a93a0cerionstatic UChar ifieldRegC ( UInt instr ) {
37276de5cf615380b23b4b5bcced6541233cd4a93a0cerion   return toUChar( IFIELD( instr, 6, 5 ) );
373b51f0f4f33256638ed953156a2635aa739b232f1sewardj}
374b51f0f4f33256638ed953156a2635aa739b232f1sewardj
3754aa412af1d8166cc11f39a6e721df49431d23618sewardj/* Extract XC (3rd source register) field, instr[3,10:6] */
3764aa412af1d8166cc11f39a6e721df49431d23618sewardjstatic UChar ifieldRegXC ( UInt instr )
3774aa412af1d8166cc11f39a6e721df49431d23618sewardj{
3784aa412af1d8166cc11f39a6e721df49431d23618sewardj  UChar upper_bit = toUChar (IFIELD (instr, 3, 1));
3794aa412af1d8166cc11f39a6e721df49431d23618sewardj  UChar lower_bits = toUChar (IFIELD (instr, 6, 5));
3804aa412af1d8166cc11f39a6e721df49431d23618sewardj  return (upper_bit << 5) | lower_bits;
3814aa412af1d8166cc11f39a6e721df49431d23618sewardj}
3824aa412af1d8166cc11f39a6e721df49431d23618sewardj
38366d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj/* Extract bit 10, instr[10] */
38476de5cf615380b23b4b5bcced6541233cd4a93a0cerionstatic UChar ifieldBIT10 ( UInt instr ) {
38576de5cf615380b23b4b5bcced6541233cd4a93a0cerion   return toUChar( IFIELD( instr, 10, 1 ) );
386b51f0f4f33256638ed953156a2635aa739b232f1sewardj}
387b51f0f4f33256638ed953156a2635aa739b232f1sewardj
38876de5cf615380b23b4b5bcced6541233cd4a93a0cerion/* Extract 2nd lowest bit, instr[1] */
38976de5cf615380b23b4b5bcced6541233cd4a93a0cerionstatic UChar ifieldBIT1 ( UInt instr ) {
39076de5cf615380b23b4b5bcced6541233cd4a93a0cerion   return toUChar( IFIELD( instr, 1, 1 ) );
391b51f0f4f33256638ed953156a2635aa739b232f1sewardj}
392e9d361ab43518b6dfbd3d846f48859534659dee0cerion
39376de5cf615380b23b4b5bcced6541233cd4a93a0cerion/* Extract lowest bit, instr[0] */
39476de5cf615380b23b4b5bcced6541233cd4a93a0cerionstatic UChar ifieldBIT0 ( UInt instr ) {
39576de5cf615380b23b4b5bcced6541233cd4a93a0cerion   return toUChar( instr & 0x1 );
39676de5cf615380b23b4b5bcced6541233cd4a93a0cerion}
39776de5cf615380b23b4b5bcced6541233cd4a93a0cerion
39876de5cf615380b23b4b5bcced6541233cd4a93a0cerion/* Extract unsigned bottom half, instr[15:0] */
39976de5cf615380b23b4b5bcced6541233cd4a93a0cerionstatic UInt ifieldUIMM16 ( UInt instr ) {
40076de5cf615380b23b4b5bcced6541233cd4a93a0cerion   return instr & 0xFFFF;
40176de5cf615380b23b4b5bcced6541233cd4a93a0cerion}
40276de5cf615380b23b4b5bcced6541233cd4a93a0cerion
403d953ebb9b04cbad6891676df597bf0c542b1ec89cerion/* Extract unsigned bottom 26 bits, instr[25:0] */
404d953ebb9b04cbad6891676df597bf0c542b1ec89cerionstatic UInt ifieldUIMM26 ( UInt instr ) {
405d953ebb9b04cbad6891676df597bf0c542b1ec89cerion   return instr & 0x3FFFFFF;
40676de5cf615380b23b4b5bcced6541233cd4a93a0cerion}
40776de5cf615380b23b4b5bcced6541233cd4a93a0cerion
40866d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj/* Extract DM field, instr[9:8] */
40966d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardjstatic UChar ifieldDM ( UInt instr ) {
41066d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj   return toUChar( IFIELD( instr, 8, 2 ) );
41166d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj}
41266d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj
41366d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj/* Extract SHW field, instr[9:8] */
41466d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardjstatic inline UChar ifieldSHW ( UInt instr )
41566d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj{
41666d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj  return ifieldDM ( instr );
41766d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj}
418094d1397b3f69b1a538e80ab509ea8cd75f4be3bcerion
419edf7fc572e2decb93e9143961e8739c8fe18899dcerion/*------------------------------------------------------------*/
420d953ebb9b04cbad6891676df597bf0c542b1ec89cerion/*--- Guest-state identifiers                              ---*/
421edf7fc572e2decb93e9143961e8739c8fe18899dcerion/*------------------------------------------------------------*/
422094d1397b3f69b1a538e80ab509ea8cd75f4be3bcerion
423e9d361ab43518b6dfbd3d846f48859534659dee0ceriontypedef enum {
424d953ebb9b04cbad6891676df597bf0c542b1ec89cerion    PPC_GST_CIA,    // Current Instruction Address
425d953ebb9b04cbad6891676df597bf0c542b1ec89cerion    PPC_GST_LR,     // Link Register
426d953ebb9b04cbad6891676df597bf0c542b1ec89cerion    PPC_GST_CTR,    // Count Register
427d953ebb9b04cbad6891676df597bf0c542b1ec89cerion    PPC_GST_XER,    // Overflow, carry flags, byte count
428d953ebb9b04cbad6891676df597bf0c542b1ec89cerion    PPC_GST_CR,     // Condition Register
429d953ebb9b04cbad6891676df597bf0c542b1ec89cerion    PPC_GST_FPSCR,  // Floating Point Status/Control Register
430d953ebb9b04cbad6891676df597bf0c542b1ec89cerion    PPC_GST_VRSAVE, // Vector Save/Restore Register
431d953ebb9b04cbad6891676df597bf0c542b1ec89cerion    PPC_GST_VSCR,   // Vector Status and Control Register
432d953ebb9b04cbad6891676df597bf0c542b1ec89cerion    PPC_GST_EMWARN, // Emulation warnings
43305f5e0172384dd2983fb16fbb7deebd74d71cd35sewardj    PPC_GST_CMSTART,// For icbi: start of area to invalidate
43405f5e0172384dd2983fb16fbb7deebd74d71cd35sewardj    PPC_GST_CMLEN,  // For icbi: length of area to invalidate
435e86310f555a233cc2ca02e1a5d0adb555f12bdcdsewardj    PPC_GST_IP_AT_SYSCALL, // the CIA of the most recently executed SC insn
436aca070a5b3418a6a9b01e3c57a7eb0fbb5050908sewardj    PPC_GST_SPRG3_RO, // SPRG3
4378943d02aa373f45c6e5fdcbe5947620285d442b1carll    PPC_GST_TFHAR,  // Transactional Failure Handler Address Register
4388943d02aa373f45c6e5fdcbe5947620285d442b1carll    PPC_GST_TFIAR,  // Transactional Failure Instruction Address Register
4398943d02aa373f45c6e5fdcbe5947620285d442b1carll    PPC_GST_TEXASR, // Transactional EXception And Summary Register
440486db12d4767b5c2cc5ae764616e758f30ce21f5carll    PPC_GST_TEXASRU, // Transactional EXception And Summary Register Upper
441d953ebb9b04cbad6891676df597bf0c542b1ec89cerion    PPC_GST_MAX
442d953ebb9b04cbad6891676df597bf0c542b1ec89cerion} PPC_GST;
443e9d361ab43518b6dfbd3d846f48859534659dee0cerion
444c6bbd470e9bd9898b84959227a406d3972d95f3bsewardj#define MASK_FPSCR_RN   0x3ULL  // Binary floating point rounding mode
445c6bbd470e9bd9898b84959227a406d3972d95f3bsewardj#define MASK_FPSCR_DRN  0x700000000ULL // Decimal floating point rounding mode
446edf7fc572e2decb93e9143961e8739c8fe18899dcerion#define MASK_VSCR_VALID 0x00010001
447e14bb9f862843c6b804097c124961b5567ded4f1sewardj
448094d1397b3f69b1a538e80ab509ea8cd75f4be3bcerion
449edf7fc572e2decb93e9143961e8739c8fe18899dcerion/*------------------------------------------------------------*/
450edf7fc572e2decb93e9143961e8739c8fe18899dcerion/*---  FP Helpers                                          ---*/
451edf7fc572e2decb93e9143961e8739c8fe18899dcerion/*------------------------------------------------------------*/
4523867460f7533d6dc4e2c85656664ee341ea81e7dcerion
4532ead522cf1c0069fbc55f7c5d1e8b2a00a044d6bsewardj/* Produce the 32-bit pattern corresponding to the supplied
4542ead522cf1c0069fbc55f7c5d1e8b2a00a044d6bsewardj   float. */
4552ead522cf1c0069fbc55f7c5d1e8b2a00a044d6bsewardjstatic UInt float_to_bits ( Float f )
4562ead522cf1c0069fbc55f7c5d1e8b2a00a044d6bsewardj{
4572ead522cf1c0069fbc55f7c5d1e8b2a00a044d6bsewardj   union { UInt i; Float f; } u;
4582ead522cf1c0069fbc55f7c5d1e8b2a00a044d6bsewardj   vassert(4 == sizeof(UInt));
4592ead522cf1c0069fbc55f7c5d1e8b2a00a044d6bsewardj   vassert(4 == sizeof(Float));
4602ead522cf1c0069fbc55f7c5d1e8b2a00a044d6bsewardj   vassert(4 == sizeof(u));
4612ead522cf1c0069fbc55f7c5d1e8b2a00a044d6bsewardj   u.f = f;
4622ead522cf1c0069fbc55f7c5d1e8b2a00a044d6bsewardj   return u.i;
4632ead522cf1c0069fbc55f7c5d1e8b2a00a044d6bsewardj}
4642ead522cf1c0069fbc55f7c5d1e8b2a00a044d6bsewardj
4653867460f7533d6dc4e2c85656664ee341ea81e7dcerion
4663867460f7533d6dc4e2c85656664ee341ea81e7dcerion/*------------------------------------------------------------*/
4673867460f7533d6dc4e2c85656664ee341ea81e7dcerion/*--- Misc Helpers                                         ---*/
4683867460f7533d6dc4e2c85656664ee341ea81e7dcerion/*------------------------------------------------------------*/
4693867460f7533d6dc4e2c85656664ee341ea81e7dcerion
470f0de28cf1a762b0d6f74c93d3532c89a230673bbcerion/* Generate mask with 1's from 'begin' through 'end',
471f0de28cf1a762b0d6f74c93d3532c89a230673bbcerion   wrapping if begin > end.
472f0de28cf1a762b0d6f74c93d3532c89a230673bbcerion   begin->end works from right to left, 0=lsb
473f0de28cf1a762b0d6f74c93d3532c89a230673bbcerion*/
474d953ebb9b04cbad6891676df597bf0c542b1ec89cerionstatic UInt MASK32( UInt begin, UInt end )
4753867460f7533d6dc4e2c85656664ee341ea81e7dcerion{
476633274098fafebdc79cf1c8a1ef7f9a9914669f1sewardj   UInt m1, m2, mask;
477d953ebb9b04cbad6891676df597bf0c542b1ec89cerion   vassert(begin < 32);
478d953ebb9b04cbad6891676df597bf0c542b1ec89cerion   vassert(end < 32);
479633274098fafebdc79cf1c8a1ef7f9a9914669f1sewardj   m1   = ((UInt)(-1)) << begin;
480633274098fafebdc79cf1c8a1ef7f9a9914669f1sewardj   m2   = ((UInt)(-1)) << end << 1;
481633274098fafebdc79cf1c8a1ef7f9a9914669f1sewardj   mask = m1 ^ m2;
482b85e8bba97fdae7d892f7bfd12e4601307e4721dcerion   if (begin > end) mask = ~mask;  // wrap mask
483b85e8bba97fdae7d892f7bfd12e4601307e4721dcerion   return mask;
4843867460f7533d6dc4e2c85656664ee341ea81e7dcerion}
4853867460f7533d6dc4e2c85656664ee341ea81e7dcerion
486d953ebb9b04cbad6891676df597bf0c542b1ec89cerionstatic ULong MASK64( UInt begin, UInt end )
487d953ebb9b04cbad6891676df597bf0c542b1ec89cerion{
488633274098fafebdc79cf1c8a1ef7f9a9914669f1sewardj   ULong m1, m2, mask;
489d953ebb9b04cbad6891676df597bf0c542b1ec89cerion   vassert(begin < 64);
490d953ebb9b04cbad6891676df597bf0c542b1ec89cerion   vassert(end < 64);
491633274098fafebdc79cf1c8a1ef7f9a9914669f1sewardj   m1   = ((ULong)(-1)) << begin;
492633274098fafebdc79cf1c8a1ef7f9a9914669f1sewardj   m2   = ((ULong)(-1)) << end << 1;
493633274098fafebdc79cf1c8a1ef7f9a9914669f1sewardj   mask = m1 ^ m2;
494d953ebb9b04cbad6891676df597bf0c542b1ec89cerion   if (begin > end) mask = ~mask;  // wrap mask
495d953ebb9b04cbad6891676df597bf0c542b1ec89cerion   return mask;
496d953ebb9b04cbad6891676df597bf0c542b1ec89cerion}
497d953ebb9b04cbad6891676df597bf0c542b1ec89cerion
498f0de28cf1a762b0d6f74c93d3532c89a230673bbcerionstatic Addr64 nextInsnAddr( void )
499f0de28cf1a762b0d6f74c93d3532c89a230673bbcerion{
500f0de28cf1a762b0d6f74c93d3532c89a230673bbcerion   return guest_CIA_curr_instr + 4;
501f0de28cf1a762b0d6f74c93d3532c89a230673bbcerion}
502d953ebb9b04cbad6891676df597bf0c542b1ec89cerion
503896a1373cfdbaa25f4ab73ed4f27554016defecccerion
504896a1373cfdbaa25f4ab73ed4f27554016defecccerion/*------------------------------------------------------------*/
505896a1373cfdbaa25f4ab73ed4f27554016defecccerion/*--- Helper bits and pieces for deconstructing the        ---*/
506d953ebb9b04cbad6891676df597bf0c542b1ec89cerion/*--- ppc32/64 insn stream.                                ---*/
507896a1373cfdbaa25f4ab73ed4f27554016defecccerion/*------------------------------------------------------------*/
508896a1373cfdbaa25f4ab73ed4f27554016defecccerion
509dd40fdf58cc8a6fe9466c4f00bdfc9fe9bf00449sewardj/* Add a statement to the list held by "irsb". */
510896a1373cfdbaa25f4ab73ed4f27554016defecccerionstatic void stmt ( IRStmt* st )
511896a1373cfdbaa25f4ab73ed4f27554016defecccerion{
512dd40fdf58cc8a6fe9466c4f00bdfc9fe9bf00449sewardj   addStmtToIRSB( irsb, st );
513896a1373cfdbaa25f4ab73ed4f27554016defecccerion}
514896a1373cfdbaa25f4ab73ed4f27554016defecccerion
515896a1373cfdbaa25f4ab73ed4f27554016defecccerion/* Generate a new temporary of the given type. */
516896a1373cfdbaa25f4ab73ed4f27554016defecccerionstatic IRTemp newTemp ( IRType ty )
517896a1373cfdbaa25f4ab73ed4f27554016defecccerion{
518496a58d130a28ac3a5ba33c9012dabbe61dc852csewardj   vassert(isPlausibleIRType(ty));
519dd40fdf58cc8a6fe9466c4f00bdfc9fe9bf00449sewardj   return newIRTemp( irsb->tyenv, ty );
520896a1373cfdbaa25f4ab73ed4f27554016defecccerion}
521896a1373cfdbaa25f4ab73ed4f27554016defecccerion
52232aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion/* Various simple conversions */
52332aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion
52432aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerionstatic UChar extend_s_5to8 ( UChar x )
52532aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion{
52632aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion   return toUChar((((Int)x) << 27) >> 27);
52732aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion}
52832aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion
52992d9d876af80d14fa2f319f7109964f2d6231f15cerionstatic UInt extend_s_8to32( UChar x )
53092d9d876af80d14fa2f319f7109964f2d6231f15cerion{
53192d9d876af80d14fa2f319f7109964f2d6231f15cerion   return (UInt)((((Int)x) << 24) >> 24);
53292d9d876af80d14fa2f319f7109964f2d6231f15cerion}
533896a1373cfdbaa25f4ab73ed4f27554016defecccerion
53491ad5368eb6354ad4fabc86f2b2e641736997a38cerionstatic UInt extend_s_16to32 ( UInt x )
535896a1373cfdbaa25f4ab73ed4f27554016defecccerion{
53691ad5368eb6354ad4fabc86f2b2e641736997a38cerion   return (UInt)((((Int)x) << 16) >> 16);
537896a1373cfdbaa25f4ab73ed4f27554016defecccerion}
538896a1373cfdbaa25f4ab73ed4f27554016defecccerion
539d953ebb9b04cbad6891676df597bf0c542b1ec89cerionstatic ULong extend_s_16to64 ( UInt x )
540d953ebb9b04cbad6891676df597bf0c542b1ec89cerion{
541d953ebb9b04cbad6891676df597bf0c542b1ec89cerion   return (ULong)((((Long)x) << 48) >> 48);
542d953ebb9b04cbad6891676df597bf0c542b1ec89cerion}
543d953ebb9b04cbad6891676df597bf0c542b1ec89cerion
544d953ebb9b04cbad6891676df597bf0c542b1ec89cerionstatic ULong extend_s_26to64 ( UInt x )
545d953ebb9b04cbad6891676df597bf0c542b1ec89cerion{
546d953ebb9b04cbad6891676df597bf0c542b1ec89cerion   return (ULong)((((Long)x) << 38) >> 38);
547d953ebb9b04cbad6891676df597bf0c542b1ec89cerion}
548d953ebb9b04cbad6891676df597bf0c542b1ec89cerion
549d953ebb9b04cbad6891676df597bf0c542b1ec89cerionstatic ULong extend_s_32to64 ( UInt x )
550d953ebb9b04cbad6891676df597bf0c542b1ec89cerion{
551d953ebb9b04cbad6891676df597bf0c542b1ec89cerion   return (ULong)((((Long)x) << 32) >> 32);
552d953ebb9b04cbad6891676df597bf0c542b1ec89cerion}
553d953ebb9b04cbad6891676df597bf0c542b1ec89cerion
5541f5fe1fc3a37ca729925e8eec25aa1025b4a6cdbcarll/* Do a proper-endian load of a 32-bit word, regardless of the endianness
555684aa951cf6c31dab26997f63ba6ea81491a45c9sewardj   of the underlying host. */
5568462d113e3efeacceb304222dada8d85f748295aflorianstatic UInt getUIntPPCendianly ( const UChar* p )
557684aa951cf6c31dab26997f63ba6ea81491a45c9sewardj{
558cf0044688fed807d49677656d2c6d12e0424bcfccerion   UInt w = 0;
5591f5fe1fc3a37ca729925e8eec25aa1025b4a6cdbcarll   if (host_endness == VexEndnessBE) {
5601f5fe1fc3a37ca729925e8eec25aa1025b4a6cdbcarll       w = (w << 8) | p[0];
5611f5fe1fc3a37ca729925e8eec25aa1025b4a6cdbcarll       w = (w << 8) | p[1];
5621f5fe1fc3a37ca729925e8eec25aa1025b4a6cdbcarll       w = (w << 8) | p[2];
5631f5fe1fc3a37ca729925e8eec25aa1025b4a6cdbcarll       w = (w << 8) | p[3];
5641f5fe1fc3a37ca729925e8eec25aa1025b4a6cdbcarll   } else {
5651f5fe1fc3a37ca729925e8eec25aa1025b4a6cdbcarll       w = (w << 8) | p[3];
5661f5fe1fc3a37ca729925e8eec25aa1025b4a6cdbcarll       w = (w << 8) | p[2];
5671f5fe1fc3a37ca729925e8eec25aa1025b4a6cdbcarll       w = (w << 8) | p[1];
5681f5fe1fc3a37ca729925e8eec25aa1025b4a6cdbcarll       w = (w << 8) | p[0];
5691f5fe1fc3a37ca729925e8eec25aa1025b4a6cdbcarll   }
570684aa951cf6c31dab26997f63ba6ea81491a45c9sewardj   return w;
571684aa951cf6c31dab26997f63ba6ea81491a45c9sewardj}
572684aa951cf6c31dab26997f63ba6ea81491a45c9sewardj
573896a1373cfdbaa25f4ab73ed4f27554016defecccerion
574896a1373cfdbaa25f4ab73ed4f27554016defecccerion/*------------------------------------------------------------*/
575896a1373cfdbaa25f4ab73ed4f27554016defecccerion/*--- Helpers for constructing IR.                         ---*/
576896a1373cfdbaa25f4ab73ed4f27554016defecccerion/*------------------------------------------------------------*/
577896a1373cfdbaa25f4ab73ed4f27554016defecccerion
578b51f0f4f33256638ed953156a2635aa739b232f1sewardjstatic void assign ( IRTemp dst, IRExpr* e )
579b51f0f4f33256638ed953156a2635aa739b232f1sewardj{
580dd40fdf58cc8a6fe9466c4f00bdfc9fe9bf00449sewardj   stmt( IRStmt_WrTmp(dst, e) );
581b51f0f4f33256638ed953156a2635aa739b232f1sewardj}
582b51f0f4f33256638ed953156a2635aa739b232f1sewardj
583e9d8a26b690c2561ac54ab0cd6ad83ecbadcbe76sewardj/* This generates a normal (non store-conditional) store. */
5841f5fe1fc3a37ca729925e8eec25aa1025b4a6cdbcarllstatic void store ( IRExpr* addr, IRExpr* data )
585b51f0f4f33256638ed953156a2635aa739b232f1sewardj{
586e9d8a26b690c2561ac54ab0cd6ad83ecbadcbe76sewardj   IRType tyA = typeOfIRExpr(irsb->tyenv, addr);
587e9d8a26b690c2561ac54ab0cd6ad83ecbadcbe76sewardj   vassert(tyA == Ity_I32 || tyA == Ity_I64);
5881f5fe1fc3a37ca729925e8eec25aa1025b4a6cdbcarll
5891f5fe1fc3a37ca729925e8eec25aa1025b4a6cdbcarll   if (host_endness == VexEndnessBE)
5901f5fe1fc3a37ca729925e8eec25aa1025b4a6cdbcarll      stmt( IRStmt_Store(Iend_BE, addr, data) );
5911f5fe1fc3a37ca729925e8eec25aa1025b4a6cdbcarll   else
5921f5fe1fc3a37ca729925e8eec25aa1025b4a6cdbcarll      stmt( IRStmt_Store(Iend_LE, addr, data) );
593b51f0f4f33256638ed953156a2635aa739b232f1sewardj}
594b51f0f4f33256638ed953156a2635aa739b232f1sewardj
595b51f0f4f33256638ed953156a2635aa739b232f1sewardjstatic IRExpr* unop ( IROp op, IRExpr* a )
596b51f0f4f33256638ed953156a2635aa739b232f1sewardj{
597b51f0f4f33256638ed953156a2635aa739b232f1sewardj   return IRExpr_Unop(op, a);
598b51f0f4f33256638ed953156a2635aa739b232f1sewardj}
599b51f0f4f33256638ed953156a2635aa739b232f1sewardj
600b51f0f4f33256638ed953156a2635aa739b232f1sewardjstatic IRExpr* binop ( IROp op, IRExpr* a1, IRExpr* a2 )
601b51f0f4f33256638ed953156a2635aa739b232f1sewardj{
602b51f0f4f33256638ed953156a2635aa739b232f1sewardj   return IRExpr_Binop(op, a1, a2);
603b51f0f4f33256638ed953156a2635aa739b232f1sewardj}
604b51f0f4f33256638ed953156a2635aa739b232f1sewardj
605b183b8571b4ec98866ce2b3653a9d066cf5f16f4sewardjstatic IRExpr* triop ( IROp op, IRExpr* a1, IRExpr* a2, IRExpr* a3 )
606b183b8571b4ec98866ce2b3653a9d066cf5f16f4sewardj{
607b183b8571b4ec98866ce2b3653a9d066cf5f16f4sewardj   return IRExpr_Triop(op, a1, a2, a3);
608b183b8571b4ec98866ce2b3653a9d066cf5f16f4sewardj}
609b183b8571b4ec98866ce2b3653a9d066cf5f16f4sewardj
61040c802659108a96bb87cbc1a30b7b77e2abd0829sewardjstatic IRExpr* qop ( IROp op, IRExpr* a1, IRExpr* a2,
61140c802659108a96bb87cbc1a30b7b77e2abd0829sewardj                              IRExpr* a3, IRExpr* a4 )
61240c802659108a96bb87cbc1a30b7b77e2abd0829sewardj{
61340c802659108a96bb87cbc1a30b7b77e2abd0829sewardj   return IRExpr_Qop(op, a1, a2, a3, a4);
61440c802659108a96bb87cbc1a30b7b77e2abd0829sewardj}
61540c802659108a96bb87cbc1a30b7b77e2abd0829sewardj
616b51f0f4f33256638ed953156a2635aa739b232f1sewardjstatic IRExpr* mkexpr ( IRTemp tmp )
617b51f0f4f33256638ed953156a2635aa739b232f1sewardj{
618dd40fdf58cc8a6fe9466c4f00bdfc9fe9bf00449sewardj   return IRExpr_RdTmp(tmp);
619b51f0f4f33256638ed953156a2635aa739b232f1sewardj}
620b51f0f4f33256638ed953156a2635aa739b232f1sewardj
621b51f0f4f33256638ed953156a2635aa739b232f1sewardjstatic IRExpr* mkU8 ( UChar i )
622b51f0f4f33256638ed953156a2635aa739b232f1sewardj{
623b51f0f4f33256638ed953156a2635aa739b232f1sewardj   return IRExpr_Const(IRConst_U8(i));
624b51f0f4f33256638ed953156a2635aa739b232f1sewardj}
625b51f0f4f33256638ed953156a2635aa739b232f1sewardj
62692d9d876af80d14fa2f319f7109964f2d6231f15cerionstatic IRExpr* mkU16 ( UInt i )
62792d9d876af80d14fa2f319f7109964f2d6231f15cerion{
62892d9d876af80d14fa2f319f7109964f2d6231f15cerion   return IRExpr_Const(IRConst_U16(i));
62992d9d876af80d14fa2f319f7109964f2d6231f15cerion}
63092d9d876af80d14fa2f319f7109964f2d6231f15cerion
631b51f0f4f33256638ed953156a2635aa739b232f1sewardjstatic IRExpr* mkU32 ( UInt i )
632b51f0f4f33256638ed953156a2635aa739b232f1sewardj{
633b51f0f4f33256638ed953156a2635aa739b232f1sewardj   return IRExpr_Const(IRConst_U32(i));
634b51f0f4f33256638ed953156a2635aa739b232f1sewardj}
635b51f0f4f33256638ed953156a2635aa739b232f1sewardj
6364a49b0393204185f87664ea58f2b7a2ae1d37338cerionstatic IRExpr* mkU64 ( ULong i )
6374a49b0393204185f87664ea58f2b7a2ae1d37338cerion{
6384a49b0393204185f87664ea58f2b7a2ae1d37338cerion   return IRExpr_Const(IRConst_U64(i));
6394a49b0393204185f87664ea58f2b7a2ae1d37338cerion}
6404a49b0393204185f87664ea58f2b7a2ae1d37338cerion
64166d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardjstatic IRExpr* mkV128 ( UShort i )
64266d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj{
64366d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj   vassert(i == 0 || i == 0xffff);
64466d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj   return IRExpr_Const(IRConst_V128(i));
64566d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj}
64666d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj
647e9d8a26b690c2561ac54ab0cd6ad83ecbadcbe76sewardj/* This generates a normal (non load-linked) load. */
6481f5fe1fc3a37ca729925e8eec25aa1025b4a6cdbcarllstatic IRExpr* load ( IRType ty, IRExpr* addr )
6491f5fe1fc3a37ca729925e8eec25aa1025b4a6cdbcarll{
6501f5fe1fc3a37ca729925e8eec25aa1025b4a6cdbcarll   if (host_endness == VexEndnessBE)
6511f5fe1fc3a37ca729925e8eec25aa1025b4a6cdbcarll      return IRExpr_Load(Iend_BE, ty, addr);
6521f5fe1fc3a37ca729925e8eec25aa1025b4a6cdbcarll   else
6531f5fe1fc3a37ca729925e8eec25aa1025b4a6cdbcarll      return IRExpr_Load(Iend_LE, ty, addr);
6541f5fe1fc3a37ca729925e8eec25aa1025b4a6cdbcarll}
6551f5fe1fc3a37ca729925e8eec25aa1025b4a6cdbcarll
6561f5fe1fc3a37ca729925e8eec25aa1025b4a6cdbcarllstatic IRStmt* stmt_load ( IRTemp result,
6571f5fe1fc3a37ca729925e8eec25aa1025b4a6cdbcarll                           IRExpr* addr, IRExpr* storedata )
658b51f0f4f33256638ed953156a2635aa739b232f1sewardj{
6591f5fe1fc3a37ca729925e8eec25aa1025b4a6cdbcarll   if (host_endness == VexEndnessBE)
6601f5fe1fc3a37ca729925e8eec25aa1025b4a6cdbcarll      return IRStmt_LLSC(Iend_BE, result, addr, storedata);
6611f5fe1fc3a37ca729925e8eec25aa1025b4a6cdbcarll   else
6621f5fe1fc3a37ca729925e8eec25aa1025b4a6cdbcarll      return IRStmt_LLSC(Iend_LE, result, addr, storedata);
663b51f0f4f33256638ed953156a2635aa739b232f1sewardj}
664b51f0f4f33256638ed953156a2635aa739b232f1sewardj
66520ef5472eac767474c93b7835364a23f24c0ec5dsewardjstatic IRExpr* mkOR1 ( IRExpr* arg1, IRExpr* arg2 )
66620ef5472eac767474c93b7835364a23f24c0ec5dsewardj{
667dd40fdf58cc8a6fe9466c4f00bdfc9fe9bf00449sewardj   vassert(typeOfIRExpr(irsb->tyenv, arg1) == Ity_I1);
668dd40fdf58cc8a6fe9466c4f00bdfc9fe9bf00449sewardj   vassert(typeOfIRExpr(irsb->tyenv, arg2) == Ity_I1);
6695b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion   return unop(Iop_32to1, binop(Iop_Or32, unop(Iop_1Uto32, arg1),
6705b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion                                          unop(Iop_1Uto32, arg2)));
67120ef5472eac767474c93b7835364a23f24c0ec5dsewardj}
67220ef5472eac767474c93b7835364a23f24c0ec5dsewardj
67320ef5472eac767474c93b7835364a23f24c0ec5dsewardjstatic IRExpr* mkAND1 ( IRExpr* arg1, IRExpr* arg2 )
67420ef5472eac767474c93b7835364a23f24c0ec5dsewardj{
675dd40fdf58cc8a6fe9466c4f00bdfc9fe9bf00449sewardj   vassert(typeOfIRExpr(irsb->tyenv, arg1) == Ity_I1);
676dd40fdf58cc8a6fe9466c4f00bdfc9fe9bf00449sewardj   vassert(typeOfIRExpr(irsb->tyenv, arg2) == Ity_I1);
6775b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion   return unop(Iop_32to1, binop(Iop_And32, unop(Iop_1Uto32, arg1),
6785b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion                                           unop(Iop_1Uto32, arg2)));
67920ef5472eac767474c93b7835364a23f24c0ec5dsewardj}
680b51f0f4f33256638ed953156a2635aa739b232f1sewardj
6814a49b0393204185f87664ea58f2b7a2ae1d37338cerion/* expand V128_8Ux16 to 2x V128_16Ux8's */
6825b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerionstatic void expand8Ux16( IRExpr* vIn,
6835b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion                         /*OUTs*/ IRTemp* vEvn, IRTemp* vOdd )
6844a49b0393204185f87664ea58f2b7a2ae1d37338cerion{
6854a49b0393204185f87664ea58f2b7a2ae1d37338cerion   IRTemp ones8x16 = newTemp(Ity_V128);
6864a49b0393204185f87664ea58f2b7a2ae1d37338cerion
687dd40fdf58cc8a6fe9466c4f00bdfc9fe9bf00449sewardj   vassert(typeOfIRExpr(irsb->tyenv, vIn) == Ity_V128);
6884a49b0393204185f87664ea58f2b7a2ae1d37338cerion   vassert(vEvn && *vEvn == IRTemp_INVALID);
6894a49b0393204185f87664ea58f2b7a2ae1d37338cerion   vassert(vOdd && *vOdd == IRTemp_INVALID);
6904a49b0393204185f87664ea58f2b7a2ae1d37338cerion   *vEvn = newTemp(Ity_V128);
6914a49b0393204185f87664ea58f2b7a2ae1d37338cerion   *vOdd = newTemp(Ity_V128);
6924a49b0393204185f87664ea58f2b7a2ae1d37338cerion
6934a49b0393204185f87664ea58f2b7a2ae1d37338cerion   assign( ones8x16, unop(Iop_Dup8x16, mkU8(0x1)) );
69424d06f124e3325e8edcc1c495d15736d5adcda96cerion   assign( *vOdd, binop(Iop_MullEven8Ux16, mkexpr(ones8x16), vIn) );
69524d06f124e3325e8edcc1c495d15736d5adcda96cerion   assign( *vEvn, binop(Iop_MullEven8Ux16, mkexpr(ones8x16),
69624d06f124e3325e8edcc1c495d15736d5adcda96cerion                        binop(Iop_ShrV128, vIn, mkU8(8))) );
6974a49b0393204185f87664ea58f2b7a2ae1d37338cerion}
6984a49b0393204185f87664ea58f2b7a2ae1d37338cerion
6994a49b0393204185f87664ea58f2b7a2ae1d37338cerion/* expand V128_8Sx16 to 2x V128_16Sx8's */
7005b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerionstatic void expand8Sx16( IRExpr* vIn,
7015b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion                         /*OUTs*/ IRTemp* vEvn, IRTemp* vOdd )
7024a49b0393204185f87664ea58f2b7a2ae1d37338cerion{
7034a49b0393204185f87664ea58f2b7a2ae1d37338cerion   IRTemp ones8x16 = newTemp(Ity_V128);
7044a49b0393204185f87664ea58f2b7a2ae1d37338cerion
705dd40fdf58cc8a6fe9466c4f00bdfc9fe9bf00449sewardj   vassert(typeOfIRExpr(irsb->tyenv, vIn) == Ity_V128);
7064a49b0393204185f87664ea58f2b7a2ae1d37338cerion   vassert(vEvn && *vEvn == IRTemp_INVALID);
7074a49b0393204185f87664ea58f2b7a2ae1d37338cerion   vassert(vOdd && *vOdd == IRTemp_INVALID);
7084a49b0393204185f87664ea58f2b7a2ae1d37338cerion   *vEvn = newTemp(Ity_V128);
7094a49b0393204185f87664ea58f2b7a2ae1d37338cerion   *vOdd = newTemp(Ity_V128);
7104a49b0393204185f87664ea58f2b7a2ae1d37338cerion
7114a49b0393204185f87664ea58f2b7a2ae1d37338cerion   assign( ones8x16, unop(Iop_Dup8x16, mkU8(0x1)) );
71224d06f124e3325e8edcc1c495d15736d5adcda96cerion   assign( *vOdd, binop(Iop_MullEven8Sx16, mkexpr(ones8x16), vIn) );
71324d06f124e3325e8edcc1c495d15736d5adcda96cerion   assign( *vEvn, binop(Iop_MullEven8Sx16, mkexpr(ones8x16),
71424d06f124e3325e8edcc1c495d15736d5adcda96cerion                        binop(Iop_ShrV128, vIn, mkU8(8))) );
7154a49b0393204185f87664ea58f2b7a2ae1d37338cerion}
7164a49b0393204185f87664ea58f2b7a2ae1d37338cerion
7174a49b0393204185f87664ea58f2b7a2ae1d37338cerion/* expand V128_16Uto8 to 2x V128_32Ux4's */
7185b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerionstatic void expand16Ux8( IRExpr* vIn,
7195b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion                         /*OUTs*/ IRTemp* vEvn, IRTemp* vOdd )
7204a49b0393204185f87664ea58f2b7a2ae1d37338cerion{
7214a49b0393204185f87664ea58f2b7a2ae1d37338cerion   IRTemp ones16x8 = newTemp(Ity_V128);
7224a49b0393204185f87664ea58f2b7a2ae1d37338cerion
723dd40fdf58cc8a6fe9466c4f00bdfc9fe9bf00449sewardj   vassert(typeOfIRExpr(irsb->tyenv, vIn) == Ity_V128);
7244a49b0393204185f87664ea58f2b7a2ae1d37338cerion   vassert(vEvn && *vEvn == IRTemp_INVALID);
7254a49b0393204185f87664ea58f2b7a2ae1d37338cerion   vassert(vOdd && *vOdd == IRTemp_INVALID);
7264a49b0393204185f87664ea58f2b7a2ae1d37338cerion   *vEvn = newTemp(Ity_V128);
7274a49b0393204185f87664ea58f2b7a2ae1d37338cerion   *vOdd = newTemp(Ity_V128);
7284a49b0393204185f87664ea58f2b7a2ae1d37338cerion
7294a49b0393204185f87664ea58f2b7a2ae1d37338cerion   assign( ones16x8, unop(Iop_Dup16x8, mkU16(0x1)) );
73024d06f124e3325e8edcc1c495d15736d5adcda96cerion   assign( *vOdd, binop(Iop_MullEven16Ux8, mkexpr(ones16x8), vIn) );
73124d06f124e3325e8edcc1c495d15736d5adcda96cerion   assign( *vEvn, binop(Iop_MullEven16Ux8, mkexpr(ones16x8),
73224d06f124e3325e8edcc1c495d15736d5adcda96cerion                        binop(Iop_ShrV128, vIn, mkU8(16))) );
7334a49b0393204185f87664ea58f2b7a2ae1d37338cerion}
7344a49b0393204185f87664ea58f2b7a2ae1d37338cerion
7354a49b0393204185f87664ea58f2b7a2ae1d37338cerion/* expand V128_16Sto8 to 2x V128_32Sx4's */
7365b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerionstatic void expand16Sx8( IRExpr* vIn,
7375b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion                         /*OUTs*/ IRTemp* vEvn, IRTemp* vOdd )
7384a49b0393204185f87664ea58f2b7a2ae1d37338cerion{
7394a49b0393204185f87664ea58f2b7a2ae1d37338cerion   IRTemp ones16x8 = newTemp(Ity_V128);
7404a49b0393204185f87664ea58f2b7a2ae1d37338cerion
741dd40fdf58cc8a6fe9466c4f00bdfc9fe9bf00449sewardj   vassert(typeOfIRExpr(irsb->tyenv, vIn) == Ity_V128);
7424a49b0393204185f87664ea58f2b7a2ae1d37338cerion   vassert(vEvn && *vEvn == IRTemp_INVALID);
7434a49b0393204185f87664ea58f2b7a2ae1d37338cerion   vassert(vOdd && *vOdd == IRTemp_INVALID);
7444a49b0393204185f87664ea58f2b7a2ae1d37338cerion   *vEvn = newTemp(Ity_V128);
7454a49b0393204185f87664ea58f2b7a2ae1d37338cerion   *vOdd = newTemp(Ity_V128);
7464a49b0393204185f87664ea58f2b7a2ae1d37338cerion
7474a49b0393204185f87664ea58f2b7a2ae1d37338cerion   assign( ones16x8, unop(Iop_Dup16x8, mkU16(0x1)) );
74824d06f124e3325e8edcc1c495d15736d5adcda96cerion   assign( *vOdd, binop(Iop_MullEven16Sx8, mkexpr(ones16x8), vIn) );
74924d06f124e3325e8edcc1c495d15736d5adcda96cerion   assign( *vEvn, binop(Iop_MullEven16Sx8, mkexpr(ones16x8),
75024d06f124e3325e8edcc1c495d15736d5adcda96cerion                       binop(Iop_ShrV128, vIn, mkU8(16))) );
7514a49b0393204185f87664ea58f2b7a2ae1d37338cerion}
7524a49b0393204185f87664ea58f2b7a2ae1d37338cerion
7534aa412af1d8166cc11f39a6e721df49431d23618sewardj/* break V128 to 4xF64's*/
7544aa412af1d8166cc11f39a6e721df49431d23618sewardjstatic void breakV128to4xF64( IRExpr* t128,
7554aa412af1d8166cc11f39a6e721df49431d23618sewardj                              /*OUTs*/
7564aa412af1d8166cc11f39a6e721df49431d23618sewardj                              IRTemp* t3, IRTemp* t2,
7574aa412af1d8166cc11f39a6e721df49431d23618sewardj                              IRTemp* t1, IRTemp* t0 )
7584aa412af1d8166cc11f39a6e721df49431d23618sewardj{
7594aa412af1d8166cc11f39a6e721df49431d23618sewardj   IRTemp hi64 = newTemp(Ity_I64);
7604aa412af1d8166cc11f39a6e721df49431d23618sewardj   IRTemp lo64 = newTemp(Ity_I64);
7614aa412af1d8166cc11f39a6e721df49431d23618sewardj
7624aa412af1d8166cc11f39a6e721df49431d23618sewardj   vassert(typeOfIRExpr(irsb->tyenv, t128) == Ity_V128);
7634aa412af1d8166cc11f39a6e721df49431d23618sewardj   vassert(t0 && *t0 == IRTemp_INVALID);
7644aa412af1d8166cc11f39a6e721df49431d23618sewardj   vassert(t1 && *t1 == IRTemp_INVALID);
7654aa412af1d8166cc11f39a6e721df49431d23618sewardj   vassert(t2 && *t2 == IRTemp_INVALID);
7664aa412af1d8166cc11f39a6e721df49431d23618sewardj   vassert(t3 && *t3 == IRTemp_INVALID);
7674aa412af1d8166cc11f39a6e721df49431d23618sewardj   *t0 = newTemp(Ity_F64);
7684aa412af1d8166cc11f39a6e721df49431d23618sewardj   *t1 = newTemp(Ity_F64);
7694aa412af1d8166cc11f39a6e721df49431d23618sewardj   *t2 = newTemp(Ity_F64);
7704aa412af1d8166cc11f39a6e721df49431d23618sewardj   *t3 = newTemp(Ity_F64);
7714aa412af1d8166cc11f39a6e721df49431d23618sewardj
7724aa412af1d8166cc11f39a6e721df49431d23618sewardj   assign( hi64, unop(Iop_V128HIto64, t128) );
7734aa412af1d8166cc11f39a6e721df49431d23618sewardj   assign( lo64, unop(Iop_V128to64,   t128) );
7744aa412af1d8166cc11f39a6e721df49431d23618sewardj   assign( *t3,
7754aa412af1d8166cc11f39a6e721df49431d23618sewardj           unop( Iop_F32toF64,
7764aa412af1d8166cc11f39a6e721df49431d23618sewardj                 unop( Iop_ReinterpI32asF32,
7774aa412af1d8166cc11f39a6e721df49431d23618sewardj                       unop( Iop_64HIto32, mkexpr( hi64 ) ) ) ) );
7784aa412af1d8166cc11f39a6e721df49431d23618sewardj   assign( *t2,
7794aa412af1d8166cc11f39a6e721df49431d23618sewardj           unop( Iop_F32toF64,
7804aa412af1d8166cc11f39a6e721df49431d23618sewardj                 unop( Iop_ReinterpI32asF32, unop( Iop_64to32, mkexpr( hi64 ) ) ) ) );
7814aa412af1d8166cc11f39a6e721df49431d23618sewardj   assign( *t1,
7824aa412af1d8166cc11f39a6e721df49431d23618sewardj           unop( Iop_F32toF64,
7834aa412af1d8166cc11f39a6e721df49431d23618sewardj                 unop( Iop_ReinterpI32asF32,
7844aa412af1d8166cc11f39a6e721df49431d23618sewardj                       unop( Iop_64HIto32, mkexpr( lo64 ) ) ) ) );
7854aa412af1d8166cc11f39a6e721df49431d23618sewardj   assign( *t0,
7864aa412af1d8166cc11f39a6e721df49431d23618sewardj           unop( Iop_F32toF64,
7874aa412af1d8166cc11f39a6e721df49431d23618sewardj                 unop( Iop_ReinterpI32asF32, unop( Iop_64to32, mkexpr( lo64 ) ) ) ) );
7884aa412af1d8166cc11f39a6e721df49431d23618sewardj}
7894aa412af1d8166cc11f39a6e721df49431d23618sewardj
7904aa412af1d8166cc11f39a6e721df49431d23618sewardj
7914a49b0393204185f87664ea58f2b7a2ae1d37338cerion/* break V128 to 4xI32's, then sign-extend to I64's */
7924a49b0393204185f87664ea58f2b7a2ae1d37338cerionstatic void breakV128to4x64S( IRExpr* t128,
7934a49b0393204185f87664ea58f2b7a2ae1d37338cerion                              /*OUTs*/
7944a49b0393204185f87664ea58f2b7a2ae1d37338cerion                              IRTemp* t3, IRTemp* t2,
7954a49b0393204185f87664ea58f2b7a2ae1d37338cerion                              IRTemp* t1, IRTemp* t0 )
7964a49b0393204185f87664ea58f2b7a2ae1d37338cerion{
7974a49b0393204185f87664ea58f2b7a2ae1d37338cerion   IRTemp hi64 = newTemp(Ity_I64);
7984a49b0393204185f87664ea58f2b7a2ae1d37338cerion   IRTemp lo64 = newTemp(Ity_I64);
7994a49b0393204185f87664ea58f2b7a2ae1d37338cerion
800dd40fdf58cc8a6fe9466c4f00bdfc9fe9bf00449sewardj   vassert(typeOfIRExpr(irsb->tyenv, t128) == Ity_V128);
8014a49b0393204185f87664ea58f2b7a2ae1d37338cerion   vassert(t0 && *t0 == IRTemp_INVALID);
8024a49b0393204185f87664ea58f2b7a2ae1d37338cerion   vassert(t1 && *t1 == IRTemp_INVALID);
8034a49b0393204185f87664ea58f2b7a2ae1d37338cerion   vassert(t2 && *t2 == IRTemp_INVALID);
8044a49b0393204185f87664ea58f2b7a2ae1d37338cerion   vassert(t3 && *t3 == IRTemp_INVALID);
8054a49b0393204185f87664ea58f2b7a2ae1d37338cerion   *t0 = newTemp(Ity_I64);
8064a49b0393204185f87664ea58f2b7a2ae1d37338cerion   *t1 = newTemp(Ity_I64);
8074a49b0393204185f87664ea58f2b7a2ae1d37338cerion   *t2 = newTemp(Ity_I64);
8084a49b0393204185f87664ea58f2b7a2ae1d37338cerion   *t3 = newTemp(Ity_I64);
8094a49b0393204185f87664ea58f2b7a2ae1d37338cerion
8104a49b0393204185f87664ea58f2b7a2ae1d37338cerion   assign( hi64, unop(Iop_V128HIto64, t128) );
8114a49b0393204185f87664ea58f2b7a2ae1d37338cerion   assign( lo64, unop(Iop_V128to64,   t128) );
8124a49b0393204185f87664ea58f2b7a2ae1d37338cerion   assign( *t3, unop(Iop_32Sto64, unop(Iop_64HIto32, mkexpr(hi64))) );
8134a49b0393204185f87664ea58f2b7a2ae1d37338cerion   assign( *t2, unop(Iop_32Sto64, unop(Iop_64to32,   mkexpr(hi64))) );
8144a49b0393204185f87664ea58f2b7a2ae1d37338cerion   assign( *t1, unop(Iop_32Sto64, unop(Iop_64HIto32, mkexpr(lo64))) );
8154a49b0393204185f87664ea58f2b7a2ae1d37338cerion   assign( *t0, unop(Iop_32Sto64, unop(Iop_64to32,   mkexpr(lo64))) );
8164a49b0393204185f87664ea58f2b7a2ae1d37338cerion}
8174a49b0393204185f87664ea58f2b7a2ae1d37338cerion
8184a49b0393204185f87664ea58f2b7a2ae1d37338cerion/* break V128 to 4xI32's, then zero-extend to I64's */
8194a49b0393204185f87664ea58f2b7a2ae1d37338cerionstatic void breakV128to4x64U ( IRExpr* t128,
8204a49b0393204185f87664ea58f2b7a2ae1d37338cerion                               /*OUTs*/
8214a49b0393204185f87664ea58f2b7a2ae1d37338cerion                               IRTemp* t3, IRTemp* t2,
8224a49b0393204185f87664ea58f2b7a2ae1d37338cerion                               IRTemp* t1, IRTemp* t0 )
8234a49b0393204185f87664ea58f2b7a2ae1d37338cerion{
8244a49b0393204185f87664ea58f2b7a2ae1d37338cerion   IRTemp hi64 = newTemp(Ity_I64);
8254a49b0393204185f87664ea58f2b7a2ae1d37338cerion   IRTemp lo64 = newTemp(Ity_I64);
8264a49b0393204185f87664ea58f2b7a2ae1d37338cerion
827dd40fdf58cc8a6fe9466c4f00bdfc9fe9bf00449sewardj   vassert(typeOfIRExpr(irsb->tyenv, t128) == Ity_V128);
8284a49b0393204185f87664ea58f2b7a2ae1d37338cerion   vassert(t0 && *t0 == IRTemp_INVALID);
8294a49b0393204185f87664ea58f2b7a2ae1d37338cerion   vassert(t1 && *t1 == IRTemp_INVALID);
8304a49b0393204185f87664ea58f2b7a2ae1d37338cerion   vassert(t2 && *t2 == IRTemp_INVALID);
8314a49b0393204185f87664ea58f2b7a2ae1d37338cerion   vassert(t3 && *t3 == IRTemp_INVALID);
8324a49b0393204185f87664ea58f2b7a2ae1d37338cerion   *t0 = newTemp(Ity_I64);
8334a49b0393204185f87664ea58f2b7a2ae1d37338cerion   *t1 = newTemp(Ity_I64);
8344a49b0393204185f87664ea58f2b7a2ae1d37338cerion   *t2 = newTemp(Ity_I64);
8354a49b0393204185f87664ea58f2b7a2ae1d37338cerion   *t3 = newTemp(Ity_I64);
8364a49b0393204185f87664ea58f2b7a2ae1d37338cerion
8374a49b0393204185f87664ea58f2b7a2ae1d37338cerion   assign( hi64, unop(Iop_V128HIto64, t128) );
8384a49b0393204185f87664ea58f2b7a2ae1d37338cerion   assign( lo64, unop(Iop_V128to64,   t128) );
8394a49b0393204185f87664ea58f2b7a2ae1d37338cerion   assign( *t3, unop(Iop_32Uto64, unop(Iop_64HIto32, mkexpr(hi64))) );
8404a49b0393204185f87664ea58f2b7a2ae1d37338cerion   assign( *t2, unop(Iop_32Uto64, unop(Iop_64to32,   mkexpr(hi64))) );
8414a49b0393204185f87664ea58f2b7a2ae1d37338cerion   assign( *t1, unop(Iop_32Uto64, unop(Iop_64HIto32, mkexpr(lo64))) );
8424a49b0393204185f87664ea58f2b7a2ae1d37338cerion   assign( *t0, unop(Iop_32Uto64, unop(Iop_64to32,   mkexpr(lo64))) );
8434a49b0393204185f87664ea58f2b7a2ae1d37338cerion}
8444a49b0393204185f87664ea58f2b7a2ae1d37338cerion
845e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardjstatic void breakV128to4x32( IRExpr* t128,
846e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj                              /*OUTs*/
847e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj                              IRTemp* t3, IRTemp* t2,
848e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj                              IRTemp* t1, IRTemp* t0 )
849e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj{
850e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj   IRTemp hi64 = newTemp(Ity_I64);
851e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj   IRTemp lo64 = newTemp(Ity_I64);
852e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj
853e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj   vassert(typeOfIRExpr(irsb->tyenv, t128) == Ity_V128);
854e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj   vassert(t0 && *t0 == IRTemp_INVALID);
855e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj   vassert(t1 && *t1 == IRTemp_INVALID);
856e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj   vassert(t2 && *t2 == IRTemp_INVALID);
857e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj   vassert(t3 && *t3 == IRTemp_INVALID);
858e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj   *t0 = newTemp(Ity_I32);
859e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj   *t1 = newTemp(Ity_I32);
860e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj   *t2 = newTemp(Ity_I32);
861e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj   *t3 = newTemp(Ity_I32);
862e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj
863e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj   assign( hi64, unop(Iop_V128HIto64, t128) );
864e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj   assign( lo64, unop(Iop_V128to64,   t128) );
865e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj   assign( *t3, unop(Iop_64HIto32, mkexpr(hi64)) );
866e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj   assign( *t2, unop(Iop_64to32,   mkexpr(hi64)) );
867e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj   assign( *t1, unop(Iop_64HIto32, mkexpr(lo64)) );
868e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj   assign( *t0, unop(Iop_64to32,   mkexpr(lo64)) );
869e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj}
870e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj
8717deaf9552b546b847528cf39b38898fb7742b5f5carllstatic IRExpr* mkV128from32( IRTemp t3, IRTemp t2,
8727deaf9552b546b847528cf39b38898fb7742b5f5carll                               IRTemp t1, IRTemp t0 )
8737deaf9552b546b847528cf39b38898fb7742b5f5carll{
8747deaf9552b546b847528cf39b38898fb7742b5f5carll   return
8757deaf9552b546b847528cf39b38898fb7742b5f5carll      binop( Iop_64HLtoV128,
8767deaf9552b546b847528cf39b38898fb7742b5f5carll             binop(Iop_32HLto64, mkexpr(t3), mkexpr(t2)),
8777deaf9552b546b847528cf39b38898fb7742b5f5carll             binop(Iop_32HLto64, mkexpr(t1), mkexpr(t0))
8787deaf9552b546b847528cf39b38898fb7742b5f5carll   );
8797deaf9552b546b847528cf39b38898fb7742b5f5carll}
8807deaf9552b546b847528cf39b38898fb7742b5f5carll
881e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj
8824a49b0393204185f87664ea58f2b7a2ae1d37338cerion/* Signed saturating narrow 64S to 32 */
8834a49b0393204185f87664ea58f2b7a2ae1d37338cerionstatic IRExpr* mkQNarrow64Sto32 ( IRExpr* t64 )
8844a49b0393204185f87664ea58f2b7a2ae1d37338cerion{
8854a49b0393204185f87664ea58f2b7a2ae1d37338cerion   IRTemp hi32 = newTemp(Ity_I32);
8864a49b0393204185f87664ea58f2b7a2ae1d37338cerion   IRTemp lo32 = newTemp(Ity_I32);
8874a49b0393204185f87664ea58f2b7a2ae1d37338cerion
888dd40fdf58cc8a6fe9466c4f00bdfc9fe9bf00449sewardj   vassert(typeOfIRExpr(irsb->tyenv, t64) == Ity_I64);
8894a49b0393204185f87664ea58f2b7a2ae1d37338cerion
8904a49b0393204185f87664ea58f2b7a2ae1d37338cerion   assign( hi32, unop(Iop_64HIto32, t64));
8914a49b0393204185f87664ea58f2b7a2ae1d37338cerion   assign( lo32, unop(Iop_64to32,   t64));
8924a49b0393204185f87664ea58f2b7a2ae1d37338cerion
89399dd03e04a6914d90d5fee727d61d76905334becflorian   return IRExpr_ITE(
8944a49b0393204185f87664ea58f2b7a2ae1d37338cerion             /* if (hi32 == (lo32 >>s 31)) */
895009230b9758291b594e60d7c0243a73d53e81854sewardj             binop(Iop_CmpEQ32, mkexpr(hi32),
896009230b9758291b594e60d7c0243a73d53e81854sewardj                   binop( Iop_Sar32, mkexpr(lo32), mkU8(31))),
89799dd03e04a6914d90d5fee727d61d76905334becflorian             /* then: within signed-32 range: lo half good enough */
89899dd03e04a6914d90d5fee727d61d76905334becflorian             mkexpr(lo32),
8994a49b0393204185f87664ea58f2b7a2ae1d37338cerion             /* else: sign dep saturate: 1->0x80000000, 0->0x7FFFFFFF */
9004a49b0393204185f87664ea58f2b7a2ae1d37338cerion             binop(Iop_Add32, mkU32(0x7FFFFFFF),
90199dd03e04a6914d90d5fee727d61d76905334becflorian                   binop(Iop_Shr32, mkexpr(hi32), mkU8(31))));
9024a49b0393204185f87664ea58f2b7a2ae1d37338cerion}
9034a49b0393204185f87664ea58f2b7a2ae1d37338cerion
9044a49b0393204185f87664ea58f2b7a2ae1d37338cerion/* Unsigned saturating narrow 64S to 32 */
9054a49b0393204185f87664ea58f2b7a2ae1d37338cerionstatic IRExpr* mkQNarrow64Uto32 ( IRExpr* t64 )
9064a49b0393204185f87664ea58f2b7a2ae1d37338cerion{
9074a49b0393204185f87664ea58f2b7a2ae1d37338cerion   IRTemp hi32 = newTemp(Ity_I32);
9084a49b0393204185f87664ea58f2b7a2ae1d37338cerion   IRTemp lo32 = newTemp(Ity_I32);
9094a49b0393204185f87664ea58f2b7a2ae1d37338cerion
910dd40fdf58cc8a6fe9466c4f00bdfc9fe9bf00449sewardj   vassert(typeOfIRExpr(irsb->tyenv, t64) == Ity_I64);
9114a49b0393204185f87664ea58f2b7a2ae1d37338cerion
9124a49b0393204185f87664ea58f2b7a2ae1d37338cerion   assign( hi32, unop(Iop_64HIto32, t64));
9134a49b0393204185f87664ea58f2b7a2ae1d37338cerion   assign( lo32, unop(Iop_64to32,   t64));
9144a49b0393204185f87664ea58f2b7a2ae1d37338cerion
91599dd03e04a6914d90d5fee727d61d76905334becflorian   return IRExpr_ITE(
9164a49b0393204185f87664ea58f2b7a2ae1d37338cerion            /* if (top 32 bits of t64 are 0) */
917009230b9758291b594e60d7c0243a73d53e81854sewardj            binop(Iop_CmpEQ32, mkexpr(hi32), mkU32(0)),
9184a49b0393204185f87664ea58f2b7a2ae1d37338cerion            /* then: within unsigned-32 range: lo half good enough */
91999dd03e04a6914d90d5fee727d61d76905334becflorian            mkexpr(lo32),
92099dd03e04a6914d90d5fee727d61d76905334becflorian            /* else: positive saturate -> 0xFFFFFFFF */
92199dd03e04a6914d90d5fee727d61d76905334becflorian            mkU32(0xFFFFFFFF));
9224a49b0393204185f87664ea58f2b7a2ae1d37338cerion}
9234a49b0393204185f87664ea58f2b7a2ae1d37338cerion
9244a49b0393204185f87664ea58f2b7a2ae1d37338cerion/* Signed saturate narrow 64->32, combining to V128 */
9254a49b0393204185f87664ea58f2b7a2ae1d37338cerionstatic IRExpr* mkV128from4x64S ( IRExpr* t3, IRExpr* t2,
9264a49b0393204185f87664ea58f2b7a2ae1d37338cerion                                 IRExpr* t1, IRExpr* t0 )
9274a49b0393204185f87664ea58f2b7a2ae1d37338cerion{
928dd40fdf58cc8a6fe9466c4f00bdfc9fe9bf00449sewardj   vassert(typeOfIRExpr(irsb->tyenv, t3) == Ity_I64);
929dd40fdf58cc8a6fe9466c4f00bdfc9fe9bf00449sewardj   vassert(typeOfIRExpr(irsb->tyenv, t2) == Ity_I64);
930dd40fdf58cc8a6fe9466c4f00bdfc9fe9bf00449sewardj   vassert(typeOfIRExpr(irsb->tyenv, t1) == Ity_I64);
931dd40fdf58cc8a6fe9466c4f00bdfc9fe9bf00449sewardj   vassert(typeOfIRExpr(irsb->tyenv, t0) == Ity_I64);
9324a49b0393204185f87664ea58f2b7a2ae1d37338cerion   return binop(Iop_64HLtoV128,
9334a49b0393204185f87664ea58f2b7a2ae1d37338cerion                binop(Iop_32HLto64,
9344a49b0393204185f87664ea58f2b7a2ae1d37338cerion                      mkQNarrow64Sto32( t3 ),
9354a49b0393204185f87664ea58f2b7a2ae1d37338cerion                      mkQNarrow64Sto32( t2 )),
9364a49b0393204185f87664ea58f2b7a2ae1d37338cerion                binop(Iop_32HLto64,
9374a49b0393204185f87664ea58f2b7a2ae1d37338cerion                      mkQNarrow64Sto32( t1 ),
9384a49b0393204185f87664ea58f2b7a2ae1d37338cerion                      mkQNarrow64Sto32( t0 )));
9394a49b0393204185f87664ea58f2b7a2ae1d37338cerion}
9404a49b0393204185f87664ea58f2b7a2ae1d37338cerion
9414a49b0393204185f87664ea58f2b7a2ae1d37338cerion/* Unsigned saturate narrow 64->32, combining to V128 */
9424a49b0393204185f87664ea58f2b7a2ae1d37338cerionstatic IRExpr* mkV128from4x64U ( IRExpr* t3, IRExpr* t2,
9434a49b0393204185f87664ea58f2b7a2ae1d37338cerion                                 IRExpr* t1, IRExpr* t0 )
9444a49b0393204185f87664ea58f2b7a2ae1d37338cerion{
945dd40fdf58cc8a6fe9466c4f00bdfc9fe9bf00449sewardj   vassert(typeOfIRExpr(irsb->tyenv, t3) == Ity_I64);
946dd40fdf58cc8a6fe9466c4f00bdfc9fe9bf00449sewardj   vassert(typeOfIRExpr(irsb->tyenv, t2) == Ity_I64);
947dd40fdf58cc8a6fe9466c4f00bdfc9fe9bf00449sewardj   vassert(typeOfIRExpr(irsb->tyenv, t1) == Ity_I64);
948dd40fdf58cc8a6fe9466c4f00bdfc9fe9bf00449sewardj   vassert(typeOfIRExpr(irsb->tyenv, t0) == Ity_I64);
9494a49b0393204185f87664ea58f2b7a2ae1d37338cerion   return binop(Iop_64HLtoV128,
9504a49b0393204185f87664ea58f2b7a2ae1d37338cerion                binop(Iop_32HLto64,
9514a49b0393204185f87664ea58f2b7a2ae1d37338cerion                      mkQNarrow64Uto32( t3 ),
9524a49b0393204185f87664ea58f2b7a2ae1d37338cerion                      mkQNarrow64Uto32( t2 )),
9534a49b0393204185f87664ea58f2b7a2ae1d37338cerion                binop(Iop_32HLto64,
9544a49b0393204185f87664ea58f2b7a2ae1d37338cerion                      mkQNarrow64Uto32( t1 ),
9554a49b0393204185f87664ea58f2b7a2ae1d37338cerion                      mkQNarrow64Uto32( t0 )));
9564a49b0393204185f87664ea58f2b7a2ae1d37338cerion}
9574a49b0393204185f87664ea58f2b7a2ae1d37338cerion
95824d06f124e3325e8edcc1c495d15736d5adcda96cerion/* Simulate irops Iop_MullOdd*, since we don't have them  */
95924d06f124e3325e8edcc1c495d15736d5adcda96cerion#define MK_Iop_MullOdd8Ux16( expr_vA, expr_vB ) \
96024d06f124e3325e8edcc1c495d15736d5adcda96cerion      binop(Iop_MullEven8Ux16, \
96124d06f124e3325e8edcc1c495d15736d5adcda96cerion            binop(Iop_ShrV128, expr_vA, mkU8(8)), \
96224d06f124e3325e8edcc1c495d15736d5adcda96cerion            binop(Iop_ShrV128, expr_vB, mkU8(8)))
96324d06f124e3325e8edcc1c495d15736d5adcda96cerion
96424d06f124e3325e8edcc1c495d15736d5adcda96cerion#define MK_Iop_MullOdd8Sx16( expr_vA, expr_vB ) \
96524d06f124e3325e8edcc1c495d15736d5adcda96cerion      binop(Iop_MullEven8Sx16, \
96624d06f124e3325e8edcc1c495d15736d5adcda96cerion            binop(Iop_ShrV128, expr_vA, mkU8(8)), \
96724d06f124e3325e8edcc1c495d15736d5adcda96cerion            binop(Iop_ShrV128, expr_vB, mkU8(8)))
96824d06f124e3325e8edcc1c495d15736d5adcda96cerion
96924d06f124e3325e8edcc1c495d15736d5adcda96cerion#define MK_Iop_MullOdd16Ux8( expr_vA, expr_vB ) \
97024d06f124e3325e8edcc1c495d15736d5adcda96cerion      binop(Iop_MullEven16Ux8, \
97124d06f124e3325e8edcc1c495d15736d5adcda96cerion            binop(Iop_ShrV128, expr_vA, mkU8(16)), \
97224d06f124e3325e8edcc1c495d15736d5adcda96cerion            binop(Iop_ShrV128, expr_vB, mkU8(16)))
97324d06f124e3325e8edcc1c495d15736d5adcda96cerion
97448ae46b56cef87c90638b25d6b2462c475033da8carll#define MK_Iop_MullOdd32Ux4( expr_vA, expr_vB ) \
97548ae46b56cef87c90638b25d6b2462c475033da8carll      binop(Iop_MullEven32Ux4, \
97648ae46b56cef87c90638b25d6b2462c475033da8carll            binop(Iop_ShrV128, expr_vA, mkU8(32)), \
97748ae46b56cef87c90638b25d6b2462c475033da8carll            binop(Iop_ShrV128, expr_vB, mkU8(32)))
97848ae46b56cef87c90638b25d6b2462c475033da8carll
97924d06f124e3325e8edcc1c495d15736d5adcda96cerion#define MK_Iop_MullOdd16Sx8( expr_vA, expr_vB ) \
98024d06f124e3325e8edcc1c495d15736d5adcda96cerion      binop(Iop_MullEven16Sx8, \
98124d06f124e3325e8edcc1c495d15736d5adcda96cerion            binop(Iop_ShrV128, expr_vA, mkU8(16)), \
98224d06f124e3325e8edcc1c495d15736d5adcda96cerion            binop(Iop_ShrV128, expr_vB, mkU8(16)))
98324d06f124e3325e8edcc1c495d15736d5adcda96cerion
98448ae46b56cef87c90638b25d6b2462c475033da8carll#define MK_Iop_MullOdd32Sx4( expr_vA, expr_vB ) \
98548ae46b56cef87c90638b25d6b2462c475033da8carll      binop(Iop_MullEven32Sx4, \
98648ae46b56cef87c90638b25d6b2462c475033da8carll            binop(Iop_ShrV128, expr_vA, mkU8(32)), \
98748ae46b56cef87c90638b25d6b2462c475033da8carll            binop(Iop_ShrV128, expr_vB, mkU8(32)))
98848ae46b56cef87c90638b25d6b2462c475033da8carll
98948ae46b56cef87c90638b25d6b2462c475033da8carll
99059b2c31da51314587b72a76430e766d6b7ec16cecerionstatic IRExpr* /* :: Ity_I64 */ mk64lo32Sto64 ( IRExpr* src )
991d953ebb9b04cbad6891676df597bf0c542b1ec89cerion{
992dd40fdf58cc8a6fe9466c4f00bdfc9fe9bf00449sewardj   vassert(typeOfIRExpr(irsb->tyenv, src) == Ity_I64);
993d953ebb9b04cbad6891676df597bf0c542b1ec89cerion   return unop(Iop_32Sto64, unop(Iop_64to32, src));
994d953ebb9b04cbad6891676df597bf0c542b1ec89cerion}
995d953ebb9b04cbad6891676df597bf0c542b1ec89cerion
99659b2c31da51314587b72a76430e766d6b7ec16cecerionstatic IRExpr* /* :: Ity_I64 */ mk64lo32Uto64 ( IRExpr* src )
997bb01b7cbfd84c27dd213f67a144ea5a99af36961cerion{
998dd40fdf58cc8a6fe9466c4f00bdfc9fe9bf00449sewardj   vassert(typeOfIRExpr(irsb->tyenv, src) == Ity_I64);
999bb01b7cbfd84c27dd213f67a144ea5a99af36961cerion   return unop(Iop_32Uto64, unop(Iop_64to32, src));
1000bb01b7cbfd84c27dd213f67a144ea5a99af36961cerion}
1001bb01b7cbfd84c27dd213f67a144ea5a99af36961cerion
10022831b00c4950d6c2b061def05fd67528fe132ececerionstatic IROp mkSzOp ( IRType ty, IROp op8 )
1003d953ebb9b04cbad6891676df597bf0c542b1ec89cerion{
1004d953ebb9b04cbad6891676df597bf0c542b1ec89cerion   Int adj;
1005d953ebb9b04cbad6891676df597bf0c542b1ec89cerion   vassert(ty == Ity_I8  || ty == Ity_I16 ||
1006d953ebb9b04cbad6891676df597bf0c542b1ec89cerion           ty == Ity_I32 || ty == Ity_I64);
1007d953ebb9b04cbad6891676df597bf0c542b1ec89cerion   vassert(op8 == Iop_Add8   || op8 == Iop_Sub8   || op8 == Iop_Mul8 ||
1008d953ebb9b04cbad6891676df597bf0c542b1ec89cerion           op8 == Iop_Or8    || op8 == Iop_And8   || op8 == Iop_Xor8 ||
1009d953ebb9b04cbad6891676df597bf0c542b1ec89cerion           op8 == Iop_Shl8   || op8 == Iop_Shr8   || op8 == Iop_Sar8 ||
1010d953ebb9b04cbad6891676df597bf0c542b1ec89cerion           op8 == Iop_CmpEQ8 || op8 == Iop_CmpNE8 ||
1011eb17e49565dd7867a56c8ba6e45fdca01a576bb3sewardj           op8 == Iop_Not8 );
1012d953ebb9b04cbad6891676df597bf0c542b1ec89cerion   adj = ty==Ity_I8 ? 0 : (ty==Ity_I16 ? 1 : (ty==Ity_I32 ? 2 : 3));
1013d953ebb9b04cbad6891676df597bf0c542b1ec89cerion   return adj + op8;
1014d953ebb9b04cbad6891676df597bf0c542b1ec89cerion}
1015d953ebb9b04cbad6891676df597bf0c542b1ec89cerion
10165b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion/* Make sure we get valid 32 and 64bit addresses */
10172831b00c4950d6c2b061def05fd67528fe132ececerionstatic Addr64 mkSzAddr ( IRType ty, Addr64 addr )
1018d953ebb9b04cbad6891676df597bf0c542b1ec89cerion{
1019d953ebb9b04cbad6891676df597bf0c542b1ec89cerion   vassert(ty == Ity_I32 || ty == Ity_I64);
1020d953ebb9b04cbad6891676df597bf0c542b1ec89cerion   return ( ty == Ity_I64 ?
1021d953ebb9b04cbad6891676df597bf0c542b1ec89cerion            (Addr64)addr :
1022d953ebb9b04cbad6891676df597bf0c542b1ec89cerion            (Addr64)extend_s_32to64( toUInt(addr) ) );
1023d953ebb9b04cbad6891676df597bf0c542b1ec89cerion}
1024d953ebb9b04cbad6891676df597bf0c542b1ec89cerion
1025d953ebb9b04cbad6891676df597bf0c542b1ec89cerion/* sz, ULong -> IRExpr */
10262831b00c4950d6c2b061def05fd67528fe132ececerionstatic IRExpr* mkSzImm ( IRType ty, ULong imm64 )
1027d953ebb9b04cbad6891676df597bf0c542b1ec89cerion{
1028d953ebb9b04cbad6891676df597bf0c542b1ec89cerion   vassert(ty == Ity_I32 || ty == Ity_I64);
1029d953ebb9b04cbad6891676df597bf0c542b1ec89cerion   return ty == Ity_I64 ? mkU64(imm64) : mkU32((UInt)imm64);
1030d953ebb9b04cbad6891676df597bf0c542b1ec89cerion}
1031d953ebb9b04cbad6891676df597bf0c542b1ec89cerion
1032d953ebb9b04cbad6891676df597bf0c542b1ec89cerion/* sz, ULong -> IRConst */
10332831b00c4950d6c2b061def05fd67528fe132ececerionstatic IRConst* mkSzConst ( IRType ty, ULong imm64 )
1034d953ebb9b04cbad6891676df597bf0c542b1ec89cerion{
1035d953ebb9b04cbad6891676df597bf0c542b1ec89cerion   vassert(ty == Ity_I32 || ty == Ity_I64);
1036d953ebb9b04cbad6891676df597bf0c542b1ec89cerion   return ( ty == Ity_I64 ?
1037d953ebb9b04cbad6891676df597bf0c542b1ec89cerion            IRConst_U64(imm64) :
1038d953ebb9b04cbad6891676df597bf0c542b1ec89cerion            IRConst_U32((UInt)imm64) );
1039d953ebb9b04cbad6891676df597bf0c542b1ec89cerion}
1040d953ebb9b04cbad6891676df597bf0c542b1ec89cerion
1041d953ebb9b04cbad6891676df597bf0c542b1ec89cerion/* Sign extend imm16 -> IRExpr* */
10422831b00c4950d6c2b061def05fd67528fe132ececerionstatic IRExpr* mkSzExtendS16 ( IRType ty, UInt imm16 )
1043d953ebb9b04cbad6891676df597bf0c542b1ec89cerion{
1044d953ebb9b04cbad6891676df597bf0c542b1ec89cerion   vassert(ty == Ity_I32 || ty == Ity_I64);
1045d953ebb9b04cbad6891676df597bf0c542b1ec89cerion   return ( ty == Ity_I64 ?
1046d953ebb9b04cbad6891676df597bf0c542b1ec89cerion            mkU64(extend_s_16to64(imm16)) :
1047d953ebb9b04cbad6891676df597bf0c542b1ec89cerion            mkU32(extend_s_16to32(imm16)) );
1048d953ebb9b04cbad6891676df597bf0c542b1ec89cerion}
1049d953ebb9b04cbad6891676df597bf0c542b1ec89cerion
1050d953ebb9b04cbad6891676df597bf0c542b1ec89cerion/* Sign extend imm32 -> IRExpr* */
10512831b00c4950d6c2b061def05fd67528fe132ececerionstatic IRExpr* mkSzExtendS32 ( IRType ty, UInt imm32 )
1052d953ebb9b04cbad6891676df597bf0c542b1ec89cerion{
1053d953ebb9b04cbad6891676df597bf0c542b1ec89cerion   vassert(ty == Ity_I32 || ty == Ity_I64);
1054d953ebb9b04cbad6891676df597bf0c542b1ec89cerion   return ( ty == Ity_I64 ?
1055d953ebb9b04cbad6891676df597bf0c542b1ec89cerion            mkU64(extend_s_32to64(imm32)) :
1056d953ebb9b04cbad6891676df597bf0c542b1ec89cerion            mkU32(imm32) );
1057d953ebb9b04cbad6891676df597bf0c542b1ec89cerion}
1058d953ebb9b04cbad6891676df597bf0c542b1ec89cerion
1059d953ebb9b04cbad6891676df597bf0c542b1ec89cerion/* IR narrows I32/I64 -> I8/I16/I32 */
1060e9d8a26b690c2561ac54ab0cd6ad83ecbadcbe76sewardjstatic IRExpr* mkNarrowTo8 ( IRType ty, IRExpr* src )
1061d953ebb9b04cbad6891676df597bf0c542b1ec89cerion{
1062d953ebb9b04cbad6891676df597bf0c542b1ec89cerion   vassert(ty == Ity_I32 || ty == Ity_I64);
1063d953ebb9b04cbad6891676df597bf0c542b1ec89cerion   return ty == Ity_I64 ? unop(Iop_64to8, src) : unop(Iop_32to8, src);
1064d953ebb9b04cbad6891676df597bf0c542b1ec89cerion}
1065d953ebb9b04cbad6891676df597bf0c542b1ec89cerion
1066e9d8a26b690c2561ac54ab0cd6ad83ecbadcbe76sewardjstatic IRExpr* mkNarrowTo16 ( IRType ty, IRExpr* src )
1067d953ebb9b04cbad6891676df597bf0c542b1ec89cerion{
1068d953ebb9b04cbad6891676df597bf0c542b1ec89cerion   vassert(ty == Ity_I32 || ty == Ity_I64);
1069d953ebb9b04cbad6891676df597bf0c542b1ec89cerion   return ty == Ity_I64 ? unop(Iop_64to16, src) : unop(Iop_32to16, src);
1070d953ebb9b04cbad6891676df597bf0c542b1ec89cerion}
1071d953ebb9b04cbad6891676df597bf0c542b1ec89cerion
1072e9d8a26b690c2561ac54ab0cd6ad83ecbadcbe76sewardjstatic IRExpr* mkNarrowTo32 ( IRType ty, IRExpr* src )
1073d953ebb9b04cbad6891676df597bf0c542b1ec89cerion{
1074d953ebb9b04cbad6891676df597bf0c542b1ec89cerion   vassert(ty == Ity_I32 || ty == Ity_I64);
1075d953ebb9b04cbad6891676df597bf0c542b1ec89cerion   return ty == Ity_I64 ? unop(Iop_64to32, src) : src;
1076d953ebb9b04cbad6891676df597bf0c542b1ec89cerion}
1077d953ebb9b04cbad6891676df597bf0c542b1ec89cerion
1078d953ebb9b04cbad6891676df597bf0c542b1ec89cerion/* Signed/Unsigned IR widens I8/I16/I32 -> I32/I64 */
1079e9d8a26b690c2561ac54ab0cd6ad83ecbadcbe76sewardjstatic IRExpr* mkWidenFrom8 ( IRType ty, IRExpr* src, Bool sined )
1080d953ebb9b04cbad6891676df597bf0c542b1ec89cerion{
1081d953ebb9b04cbad6891676df597bf0c542b1ec89cerion   IROp op;
1082633274098fafebdc79cf1c8a1ef7f9a9914669f1sewardj   vassert(ty == Ity_I32 || ty == Ity_I64);
1083d953ebb9b04cbad6891676df597bf0c542b1ec89cerion   if (sined) op = (ty==Ity_I32) ? Iop_8Sto32 : Iop_8Sto64;
1084d953ebb9b04cbad6891676df597bf0c542b1ec89cerion   else       op = (ty==Ity_I32) ? Iop_8Uto32 : Iop_8Uto64;
1085d953ebb9b04cbad6891676df597bf0c542b1ec89cerion   return unop(op, src);
1086d953ebb9b04cbad6891676df597bf0c542b1ec89cerion}
1087d953ebb9b04cbad6891676df597bf0c542b1ec89cerion
1088e9d8a26b690c2561ac54ab0cd6ad83ecbadcbe76sewardjstatic IRExpr* mkWidenFrom16 ( IRType ty, IRExpr* src, Bool sined )
1089d953ebb9b04cbad6891676df597bf0c542b1ec89cerion{
1090d953ebb9b04cbad6891676df597bf0c542b1ec89cerion   IROp op;
1091633274098fafebdc79cf1c8a1ef7f9a9914669f1sewardj   vassert(ty == Ity_I32 || ty == Ity_I64);
1092d953ebb9b04cbad6891676df597bf0c542b1ec89cerion   if (sined) op = (ty==Ity_I32) ? Iop_16Sto32 : Iop_16Sto64;
1093d953ebb9b04cbad6891676df597bf0c542b1ec89cerion   else       op = (ty==Ity_I32) ? Iop_16Uto32 : Iop_16Uto64;
1094d953ebb9b04cbad6891676df597bf0c542b1ec89cerion   return unop(op, src);
1095d953ebb9b04cbad6891676df597bf0c542b1ec89cerion}
1096d953ebb9b04cbad6891676df597bf0c542b1ec89cerion
1097e9d8a26b690c2561ac54ab0cd6ad83ecbadcbe76sewardjstatic IRExpr* mkWidenFrom32 ( IRType ty, IRExpr* src, Bool sined )
1098d953ebb9b04cbad6891676df597bf0c542b1ec89cerion{
1099d953ebb9b04cbad6891676df597bf0c542b1ec89cerion   vassert(ty == Ity_I32 || ty == Ity_I64);
1100d953ebb9b04cbad6891676df597bf0c542b1ec89cerion   if (ty == Ity_I32)
1101d953ebb9b04cbad6891676df597bf0c542b1ec89cerion      return src;
1102d953ebb9b04cbad6891676df597bf0c542b1ec89cerion   return (sined) ? unop(Iop_32Sto64, src) : unop(Iop_32Uto64, src);
1103d953ebb9b04cbad6891676df597bf0c542b1ec89cerion}
110424d06f124e3325e8edcc1c495d15736d5adcda96cerion
11054a49b0393204185f87664ea58f2b7a2ae1d37338cerion
1106896a1373cfdbaa25f4ab73ed4f27554016defecccerionstatic Int integerGuestRegOffset ( UInt archreg )
1107896a1373cfdbaa25f4ab73ed4f27554016defecccerion{
1108896a1373cfdbaa25f4ab73ed4f27554016defecccerion   vassert(archreg < 32);
1109b85e8bba97fdae7d892f7bfd12e4601307e4721dcerion
1110e9d361ab43518b6dfbd3d846f48859534659dee0cerion   // jrs: probably not necessary; only matters if we reference sub-parts
11115b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion   // of the ppc registers, but that isn't the case
11129e6491ab55324b8e45e187b1e1e9632ac3cb3e27sewardj   // later: this might affect Altivec though?
1113e9d361ab43518b6dfbd3d846f48859534659dee0cerion
11145b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion   switch (archreg) {
11155b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion   case  0: return offsetofPPCGuestState(guest_GPR0);
11165b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion   case  1: return offsetofPPCGuestState(guest_GPR1);
11175b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion   case  2: return offsetofPPCGuestState(guest_GPR2);
11185b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion   case  3: return offsetofPPCGuestState(guest_GPR3);
11195b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion   case  4: return offsetofPPCGuestState(guest_GPR4);
11205b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion   case  5: return offsetofPPCGuestState(guest_GPR5);
11215b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion   case  6: return offsetofPPCGuestState(guest_GPR6);
11225b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion   case  7: return offsetofPPCGuestState(guest_GPR7);
11235b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion   case  8: return offsetofPPCGuestState(guest_GPR8);
11245b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion   case  9: return offsetofPPCGuestState(guest_GPR9);
11255b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion   case 10: return offsetofPPCGuestState(guest_GPR10);
11265b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion   case 11: return offsetofPPCGuestState(guest_GPR11);
11275b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion   case 12: return offsetofPPCGuestState(guest_GPR12);
11285b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion   case 13: return offsetofPPCGuestState(guest_GPR13);
11295b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion   case 14: return offsetofPPCGuestState(guest_GPR14);
11305b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion   case 15: return offsetofPPCGuestState(guest_GPR15);
11315b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion   case 16: return offsetofPPCGuestState(guest_GPR16);
11325b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion   case 17: return offsetofPPCGuestState(guest_GPR17);
11335b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion   case 18: return offsetofPPCGuestState(guest_GPR18);
11345b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion   case 19: return offsetofPPCGuestState(guest_GPR19);
11355b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion   case 20: return offsetofPPCGuestState(guest_GPR20);
11365b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion   case 21: return offsetofPPCGuestState(guest_GPR21);
11375b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion   case 22: return offsetofPPCGuestState(guest_GPR22);
11385b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion   case 23: return offsetofPPCGuestState(guest_GPR23);
11395b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion   case 24: return offsetofPPCGuestState(guest_GPR24);
11405b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion   case 25: return offsetofPPCGuestState(guest_GPR25);
11415b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion   case 26: return offsetofPPCGuestState(guest_GPR26);
11425b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion   case 27: return offsetofPPCGuestState(guest_GPR27);
11435b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion   case 28: return offsetofPPCGuestState(guest_GPR28);
11445b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion   case 29: return offsetofPPCGuestState(guest_GPR29);
11455b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion   case 30: return offsetofPPCGuestState(guest_GPR30);
11465b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion   case 31: return offsetofPPCGuestState(guest_GPR31);
11475b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion   default: break;
11485b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion   }
11495b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion   vpanic("integerGuestRegOffset(ppc,be)"); /*notreached*/
1150896a1373cfdbaa25f4ab73ed4f27554016defecccerion}
1151896a1373cfdbaa25f4ab73ed4f27554016defecccerion
1152896a1373cfdbaa25f4ab73ed4f27554016defecccerionstatic IRExpr* getIReg ( UInt archreg )
1153896a1373cfdbaa25f4ab73ed4f27554016defecccerion{
1154d953ebb9b04cbad6891676df597bf0c542b1ec89cerion   IRType ty = mode64 ? Ity_I64 : Ity_I32;
1155896a1373cfdbaa25f4ab73ed4f27554016defecccerion   vassert(archreg < 32);
1156d953ebb9b04cbad6891676df597bf0c542b1ec89cerion   return IRExpr_Get( integerGuestRegOffset(archreg), ty );
1157896a1373cfdbaa25f4ab73ed4f27554016defecccerion}
1158896a1373cfdbaa25f4ab73ed4f27554016defecccerion
1159896a1373cfdbaa25f4ab73ed4f27554016defecccerion/* Ditto, but write to a reg instead. */
1160896a1373cfdbaa25f4ab73ed4f27554016defecccerionstatic void putIReg ( UInt archreg, IRExpr* e )
1161896a1373cfdbaa25f4ab73ed4f27554016defecccerion{
1162d953ebb9b04cbad6891676df597bf0c542b1ec89cerion   IRType ty = mode64 ? Ity_I64 : Ity_I32;
1163896a1373cfdbaa25f4ab73ed4f27554016defecccerion   vassert(archreg < 32);
1164dd40fdf58cc8a6fe9466c4f00bdfc9fe9bf00449sewardj   vassert(typeOfIRExpr(irsb->tyenv, e) == ty );
1165896a1373cfdbaa25f4ab73ed4f27554016defecccerion   stmt( IRStmt_Put(integerGuestRegOffset(archreg), e) );
1166896a1373cfdbaa25f4ab73ed4f27554016defecccerion}
1167896a1373cfdbaa25f4ab73ed4f27554016defecccerion
1168094d1397b3f69b1a538e80ab509ea8cd75f4be3bcerion
116966d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj/* Floating point egisters are mapped to VSX registers[0..31]. */
1170094d1397b3f69b1a538e80ab509ea8cd75f4be3bcerionstatic Int floatGuestRegOffset ( UInt archreg )
1171094d1397b3f69b1a538e80ab509ea8cd75f4be3bcerion{
1172094d1397b3f69b1a538e80ab509ea8cd75f4be3bcerion   vassert(archreg < 32);
1173094d1397b3f69b1a538e80ab509ea8cd75f4be3bcerion
11741f5fe1fc3a37ca729925e8eec25aa1025b4a6cdbcarll   if (host_endness == VexEndnessLE) {
11751f5fe1fc3a37ca729925e8eec25aa1025b4a6cdbcarll      switch (archreg) {
11762f93145a08ad90721cf267fc141eb6daebd53f46carll         case  0: return offsetofPPCGuestState(guest_VSR0) + 8;
11772f93145a08ad90721cf267fc141eb6daebd53f46carll         case  1: return offsetofPPCGuestState(guest_VSR1) + 8;
11782f93145a08ad90721cf267fc141eb6daebd53f46carll         case  2: return offsetofPPCGuestState(guest_VSR2) + 8;
11792f93145a08ad90721cf267fc141eb6daebd53f46carll         case  3: return offsetofPPCGuestState(guest_VSR3) + 8;
11802f93145a08ad90721cf267fc141eb6daebd53f46carll         case  4: return offsetofPPCGuestState(guest_VSR4) + 8;
11812f93145a08ad90721cf267fc141eb6daebd53f46carll         case  5: return offsetofPPCGuestState(guest_VSR5) + 8;
11822f93145a08ad90721cf267fc141eb6daebd53f46carll         case  6: return offsetofPPCGuestState(guest_VSR6) + 8;
11832f93145a08ad90721cf267fc141eb6daebd53f46carll         case  7: return offsetofPPCGuestState(guest_VSR7) + 8;
11842f93145a08ad90721cf267fc141eb6daebd53f46carll         case  8: return offsetofPPCGuestState(guest_VSR8) + 8;
11852f93145a08ad90721cf267fc141eb6daebd53f46carll         case  9: return offsetofPPCGuestState(guest_VSR9) + 8;
11862f93145a08ad90721cf267fc141eb6daebd53f46carll         case 10: return offsetofPPCGuestState(guest_VSR10) + 8;
11872f93145a08ad90721cf267fc141eb6daebd53f46carll         case 11: return offsetofPPCGuestState(guest_VSR11) + 8;
11882f93145a08ad90721cf267fc141eb6daebd53f46carll         case 12: return offsetofPPCGuestState(guest_VSR12) + 8;
11892f93145a08ad90721cf267fc141eb6daebd53f46carll         case 13: return offsetofPPCGuestState(guest_VSR13) + 8;
11902f93145a08ad90721cf267fc141eb6daebd53f46carll         case 14: return offsetofPPCGuestState(guest_VSR14) + 8;
11912f93145a08ad90721cf267fc141eb6daebd53f46carll         case 15: return offsetofPPCGuestState(guest_VSR15) + 8;
11922f93145a08ad90721cf267fc141eb6daebd53f46carll         case 16: return offsetofPPCGuestState(guest_VSR16) + 8;
11932f93145a08ad90721cf267fc141eb6daebd53f46carll         case 17: return offsetofPPCGuestState(guest_VSR17) + 8;
11942f93145a08ad90721cf267fc141eb6daebd53f46carll         case 18: return offsetofPPCGuestState(guest_VSR18) + 8;
11952f93145a08ad90721cf267fc141eb6daebd53f46carll         case 19: return offsetofPPCGuestState(guest_VSR19) + 8;
11962f93145a08ad90721cf267fc141eb6daebd53f46carll         case 20: return offsetofPPCGuestState(guest_VSR20) + 8;
11972f93145a08ad90721cf267fc141eb6daebd53f46carll         case 21: return offsetofPPCGuestState(guest_VSR21) + 8;
11982f93145a08ad90721cf267fc141eb6daebd53f46carll         case 22: return offsetofPPCGuestState(guest_VSR22) + 8;
11992f93145a08ad90721cf267fc141eb6daebd53f46carll         case 23: return offsetofPPCGuestState(guest_VSR23) + 8;
12002f93145a08ad90721cf267fc141eb6daebd53f46carll         case 24: return offsetofPPCGuestState(guest_VSR24) + 8;
12012f93145a08ad90721cf267fc141eb6daebd53f46carll         case 25: return offsetofPPCGuestState(guest_VSR25) + 8;
12022f93145a08ad90721cf267fc141eb6daebd53f46carll         case 26: return offsetofPPCGuestState(guest_VSR26) + 8;
12032f93145a08ad90721cf267fc141eb6daebd53f46carll         case 27: return offsetofPPCGuestState(guest_VSR27) + 8;
12042f93145a08ad90721cf267fc141eb6daebd53f46carll         case 28: return offsetofPPCGuestState(guest_VSR28) + 8;
12052f93145a08ad90721cf267fc141eb6daebd53f46carll         case 29: return offsetofPPCGuestState(guest_VSR29) + 8;
12062f93145a08ad90721cf267fc141eb6daebd53f46carll         case 30: return offsetofPPCGuestState(guest_VSR30) + 8;
12072f93145a08ad90721cf267fc141eb6daebd53f46carll         case 31: return offsetofPPCGuestState(guest_VSR31) + 8;
12081f5fe1fc3a37ca729925e8eec25aa1025b4a6cdbcarll         default: break;
12091f5fe1fc3a37ca729925e8eec25aa1025b4a6cdbcarll      }
12101f5fe1fc3a37ca729925e8eec25aa1025b4a6cdbcarll   } else {
12111f5fe1fc3a37ca729925e8eec25aa1025b4a6cdbcarll      switch (archreg) {
12121f5fe1fc3a37ca729925e8eec25aa1025b4a6cdbcarll         case  0: return offsetofPPCGuestState(guest_VSR0);
12131f5fe1fc3a37ca729925e8eec25aa1025b4a6cdbcarll         case  1: return offsetofPPCGuestState(guest_VSR1);
12141f5fe1fc3a37ca729925e8eec25aa1025b4a6cdbcarll         case  2: return offsetofPPCGuestState(guest_VSR2);
12151f5fe1fc3a37ca729925e8eec25aa1025b4a6cdbcarll         case  3: return offsetofPPCGuestState(guest_VSR3);
12161f5fe1fc3a37ca729925e8eec25aa1025b4a6cdbcarll         case  4: return offsetofPPCGuestState(guest_VSR4);
12171f5fe1fc3a37ca729925e8eec25aa1025b4a6cdbcarll         case  5: return offsetofPPCGuestState(guest_VSR5);
12181f5fe1fc3a37ca729925e8eec25aa1025b4a6cdbcarll         case  6: return offsetofPPCGuestState(guest_VSR6);
12191f5fe1fc3a37ca729925e8eec25aa1025b4a6cdbcarll         case  7: return offsetofPPCGuestState(guest_VSR7);
12201f5fe1fc3a37ca729925e8eec25aa1025b4a6cdbcarll         case  8: return offsetofPPCGuestState(guest_VSR8);
12211f5fe1fc3a37ca729925e8eec25aa1025b4a6cdbcarll         case  9: return offsetofPPCGuestState(guest_VSR9);
12221f5fe1fc3a37ca729925e8eec25aa1025b4a6cdbcarll         case 10: return offsetofPPCGuestState(guest_VSR10);
12231f5fe1fc3a37ca729925e8eec25aa1025b4a6cdbcarll         case 11: return offsetofPPCGuestState(guest_VSR11);
12241f5fe1fc3a37ca729925e8eec25aa1025b4a6cdbcarll         case 12: return offsetofPPCGuestState(guest_VSR12);
12251f5fe1fc3a37ca729925e8eec25aa1025b4a6cdbcarll         case 13: return offsetofPPCGuestState(guest_VSR13);
12261f5fe1fc3a37ca729925e8eec25aa1025b4a6cdbcarll         case 14: return offsetofPPCGuestState(guest_VSR14);
12271f5fe1fc3a37ca729925e8eec25aa1025b4a6cdbcarll         case 15: return offsetofPPCGuestState(guest_VSR15);
12281f5fe1fc3a37ca729925e8eec25aa1025b4a6cdbcarll         case 16: return offsetofPPCGuestState(guest_VSR16);
12291f5fe1fc3a37ca729925e8eec25aa1025b4a6cdbcarll         case 17: return offsetofPPCGuestState(guest_VSR17);
12301f5fe1fc3a37ca729925e8eec25aa1025b4a6cdbcarll         case 18: return offsetofPPCGuestState(guest_VSR18);
12311f5fe1fc3a37ca729925e8eec25aa1025b4a6cdbcarll         case 19: return offsetofPPCGuestState(guest_VSR19);
12321f5fe1fc3a37ca729925e8eec25aa1025b4a6cdbcarll         case 20: return offsetofPPCGuestState(guest_VSR20);
12331f5fe1fc3a37ca729925e8eec25aa1025b4a6cdbcarll         case 21: return offsetofPPCGuestState(guest_VSR21);
12341f5fe1fc3a37ca729925e8eec25aa1025b4a6cdbcarll         case 22: return offsetofPPCGuestState(guest_VSR22);
12351f5fe1fc3a37ca729925e8eec25aa1025b4a6cdbcarll         case 23: return offsetofPPCGuestState(guest_VSR23);
12361f5fe1fc3a37ca729925e8eec25aa1025b4a6cdbcarll         case 24: return offsetofPPCGuestState(guest_VSR24);
12371f5fe1fc3a37ca729925e8eec25aa1025b4a6cdbcarll         case 25: return offsetofPPCGuestState(guest_VSR25);
12381f5fe1fc3a37ca729925e8eec25aa1025b4a6cdbcarll         case 26: return offsetofPPCGuestState(guest_VSR26);
12391f5fe1fc3a37ca729925e8eec25aa1025b4a6cdbcarll         case 27: return offsetofPPCGuestState(guest_VSR27);
12401f5fe1fc3a37ca729925e8eec25aa1025b4a6cdbcarll         case 28: return offsetofPPCGuestState(guest_VSR28);
12411f5fe1fc3a37ca729925e8eec25aa1025b4a6cdbcarll         case 29: return offsetofPPCGuestState(guest_VSR29);
12421f5fe1fc3a37ca729925e8eec25aa1025b4a6cdbcarll         case 30: return offsetofPPCGuestState(guest_VSR30);
12431f5fe1fc3a37ca729925e8eec25aa1025b4a6cdbcarll         case 31: return offsetofPPCGuestState(guest_VSR31);
12441f5fe1fc3a37ca729925e8eec25aa1025b4a6cdbcarll         default: break;
12451f5fe1fc3a37ca729925e8eec25aa1025b4a6cdbcarll      }
12465b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion   }
12475b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion   vpanic("floatGuestRegOffset(ppc)"); /*notreached*/
1248094d1397b3f69b1a538e80ab509ea8cd75f4be3bcerion}
1249094d1397b3f69b1a538e80ab509ea8cd75f4be3bcerion
1250094d1397b3f69b1a538e80ab509ea8cd75f4be3bcerionstatic IRExpr* getFReg ( UInt archreg )
1251094d1397b3f69b1a538e80ab509ea8cd75f4be3bcerion{
1252094d1397b3f69b1a538e80ab509ea8cd75f4be3bcerion   vassert(archreg < 32);
1253094d1397b3f69b1a538e80ab509ea8cd75f4be3bcerion   return IRExpr_Get( floatGuestRegOffset(archreg), Ity_F64 );
1254094d1397b3f69b1a538e80ab509ea8cd75f4be3bcerion}
1255094d1397b3f69b1a538e80ab509ea8cd75f4be3bcerion
1256094d1397b3f69b1a538e80ab509ea8cd75f4be3bcerion/* Ditto, but write to a reg instead. */
1257094d1397b3f69b1a538e80ab509ea8cd75f4be3bcerionstatic void putFReg ( UInt archreg, IRExpr* e )
1258094d1397b3f69b1a538e80ab509ea8cd75f4be3bcerion{
1259094d1397b3f69b1a538e80ab509ea8cd75f4be3bcerion   vassert(archreg < 32);
1260dd40fdf58cc8a6fe9466c4f00bdfc9fe9bf00449sewardj   vassert(typeOfIRExpr(irsb->tyenv, e) == Ity_F64);
1261094d1397b3f69b1a538e80ab509ea8cd75f4be3bcerion   stmt( IRStmt_Put(floatGuestRegOffset(archreg), e) );
1262094d1397b3f69b1a538e80ab509ea8cd75f4be3bcerion}
1263094d1397b3f69b1a538e80ab509ea8cd75f4be3bcerion
1264c6bbd470e9bd9898b84959227a406d3972d95f3bsewardj/* get Decimal float value.  Note, they share floating point register file. */
1265c6bbd470e9bd9898b84959227a406d3972d95f3bsewardjstatic IRExpr* getDReg(UInt archreg) {
1266c6bbd470e9bd9898b84959227a406d3972d95f3bsewardj   IRExpr *e;
1267c6bbd470e9bd9898b84959227a406d3972d95f3bsewardj   vassert( archreg < 32 );
1268c6bbd470e9bd9898b84959227a406d3972d95f3bsewardj   e = IRExpr_Get( floatGuestRegOffset( archreg ), Ity_D64 );
1269c6bbd470e9bd9898b84959227a406d3972d95f3bsewardj   return e;
1270c6bbd470e9bd9898b84959227a406d3972d95f3bsewardj}
1271f704eb2bab3d06d983c850b0bcf243e178060f75carllstatic IRExpr* getDReg32(UInt archreg) {
1272f704eb2bab3d06d983c850b0bcf243e178060f75carll   IRExpr *e;
1273f704eb2bab3d06d983c850b0bcf243e178060f75carll   vassert( archreg < 32 );
1274f704eb2bab3d06d983c850b0bcf243e178060f75carll   e = IRExpr_Get( floatGuestRegOffset( archreg ), Ity_D32 );
1275f704eb2bab3d06d983c850b0bcf243e178060f75carll   return e;
1276f704eb2bab3d06d983c850b0bcf243e178060f75carll}
1277c6bbd470e9bd9898b84959227a406d3972d95f3bsewardj
1278c6bbd470e9bd9898b84959227a406d3972d95f3bsewardj/* Read a floating point register pair and combine their contents into a
1279c6bbd470e9bd9898b84959227a406d3972d95f3bsewardj 128-bit value */
1280c6bbd470e9bd9898b84959227a406d3972d95f3bsewardjstatic IRExpr *getDReg_pair(UInt archreg) {
1281c6bbd470e9bd9898b84959227a406d3972d95f3bsewardj   IRExpr *high = getDReg( archreg );
1282c6bbd470e9bd9898b84959227a406d3972d95f3bsewardj   IRExpr *low = getDReg( archreg + 1 );
1283c6bbd470e9bd9898b84959227a406d3972d95f3bsewardj
1284c6bbd470e9bd9898b84959227a406d3972d95f3bsewardj   return binop( Iop_D64HLtoD128, high, low );
1285c6bbd470e9bd9898b84959227a406d3972d95f3bsewardj}
1286c6bbd470e9bd9898b84959227a406d3972d95f3bsewardj
1287c6bbd470e9bd9898b84959227a406d3972d95f3bsewardj/* Ditto, but write to a reg instead. */
1288f704eb2bab3d06d983c850b0bcf243e178060f75carllstatic void putDReg32(UInt archreg, IRExpr* e) {
1289f704eb2bab3d06d983c850b0bcf243e178060f75carll   vassert( archreg < 32 );
1290f704eb2bab3d06d983c850b0bcf243e178060f75carll   vassert( typeOfIRExpr(irsb->tyenv, e) == Ity_D32 );
1291f704eb2bab3d06d983c850b0bcf243e178060f75carll   stmt( IRStmt_Put( floatGuestRegOffset( archreg ), e ) );
1292f704eb2bab3d06d983c850b0bcf243e178060f75carll}
1293f704eb2bab3d06d983c850b0bcf243e178060f75carll
1294c6bbd470e9bd9898b84959227a406d3972d95f3bsewardjstatic void putDReg(UInt archreg, IRExpr* e) {
1295c6bbd470e9bd9898b84959227a406d3972d95f3bsewardj   vassert( archreg < 32 );
1296c6bbd470e9bd9898b84959227a406d3972d95f3bsewardj   vassert( typeOfIRExpr(irsb->tyenv, e) == Ity_D64 );
1297c6bbd470e9bd9898b84959227a406d3972d95f3bsewardj   stmt( IRStmt_Put( floatGuestRegOffset( archreg ), e ) );
1298c6bbd470e9bd9898b84959227a406d3972d95f3bsewardj}
1299c6bbd470e9bd9898b84959227a406d3972d95f3bsewardj
1300c6bbd470e9bd9898b84959227a406d3972d95f3bsewardj/* Write a 128-bit floating point value into a register pair. */
1301c6bbd470e9bd9898b84959227a406d3972d95f3bsewardjstatic void putDReg_pair(UInt archreg, IRExpr *e) {
1302c6bbd470e9bd9898b84959227a406d3972d95f3bsewardj   IRTemp low = newTemp( Ity_D64 );
1303c6bbd470e9bd9898b84959227a406d3972d95f3bsewardj   IRTemp high = newTemp( Ity_D64 );
1304c6bbd470e9bd9898b84959227a406d3972d95f3bsewardj
1305c6bbd470e9bd9898b84959227a406d3972d95f3bsewardj   vassert( archreg < 32 );
1306c6bbd470e9bd9898b84959227a406d3972d95f3bsewardj   vassert( typeOfIRExpr(irsb->tyenv, e) == Ity_D128 );
1307c6bbd470e9bd9898b84959227a406d3972d95f3bsewardj
1308c6bbd470e9bd9898b84959227a406d3972d95f3bsewardj   assign( low, unop( Iop_D128LOtoD64, e ) );
1309c6bbd470e9bd9898b84959227a406d3972d95f3bsewardj   assign( high, unop( Iop_D128HItoD64, e ) );
1310c6bbd470e9bd9898b84959227a406d3972d95f3bsewardj
1311c6bbd470e9bd9898b84959227a406d3972d95f3bsewardj   stmt( IRStmt_Put( floatGuestRegOffset( archreg ), mkexpr( high ) ) );
1312c6bbd470e9bd9898b84959227a406d3972d95f3bsewardj   stmt( IRStmt_Put( floatGuestRegOffset( archreg + 1 ), mkexpr( low ) ) );
1313c6bbd470e9bd9898b84959227a406d3972d95f3bsewardj}
1314c6bbd470e9bd9898b84959227a406d3972d95f3bsewardj
131566d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardjstatic Int vsxGuestRegOffset ( UInt archreg )
131666d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj{
131766d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj   vassert(archreg < 64);
131866d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj   switch (archreg) {
131966d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj   case  0: return offsetofPPCGuestState(guest_VSR0);
132066d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj   case  1: return offsetofPPCGuestState(guest_VSR1);
132166d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj   case  2: return offsetofPPCGuestState(guest_VSR2);
132266d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj   case  3: return offsetofPPCGuestState(guest_VSR3);
132366d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj   case  4: return offsetofPPCGuestState(guest_VSR4);
132466d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj   case  5: return offsetofPPCGuestState(guest_VSR5);
132566d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj   case  6: return offsetofPPCGuestState(guest_VSR6);
132666d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj   case  7: return offsetofPPCGuestState(guest_VSR7);
132766d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj   case  8: return offsetofPPCGuestState(guest_VSR8);
132866d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj   case  9: return offsetofPPCGuestState(guest_VSR9);
132966d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj   case 10: return offsetofPPCGuestState(guest_VSR10);
133066d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj   case 11: return offsetofPPCGuestState(guest_VSR11);
133166d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj   case 12: return offsetofPPCGuestState(guest_VSR12);
133266d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj   case 13: return offsetofPPCGuestState(guest_VSR13);
133366d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj   case 14: return offsetofPPCGuestState(guest_VSR14);
133466d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj   case 15: return offsetofPPCGuestState(guest_VSR15);
133566d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj   case 16: return offsetofPPCGuestState(guest_VSR16);
133666d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj   case 17: return offsetofPPCGuestState(guest_VSR17);
133766d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj   case 18: return offsetofPPCGuestState(guest_VSR18);
133866d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj   case 19: return offsetofPPCGuestState(guest_VSR19);
133966d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj   case 20: return offsetofPPCGuestState(guest_VSR20);
134066d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj   case 21: return offsetofPPCGuestState(guest_VSR21);
134166d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj   case 22: return offsetofPPCGuestState(guest_VSR22);
134266d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj   case 23: return offsetofPPCGuestState(guest_VSR23);
134366d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj   case 24: return offsetofPPCGuestState(guest_VSR24);
134466d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj   case 25: return offsetofPPCGuestState(guest_VSR25);
134566d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj   case 26: return offsetofPPCGuestState(guest_VSR26);
134666d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj   case 27: return offsetofPPCGuestState(guest_VSR27);
134766d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj   case 28: return offsetofPPCGuestState(guest_VSR28);
134866d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj   case 29: return offsetofPPCGuestState(guest_VSR29);
134966d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj   case 30: return offsetofPPCGuestState(guest_VSR30);
135066d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj   case 31: return offsetofPPCGuestState(guest_VSR31);
135166d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj   case 32: return offsetofPPCGuestState(guest_VSR32);
135266d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj   case 33: return offsetofPPCGuestState(guest_VSR33);
135366d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj   case 34: return offsetofPPCGuestState(guest_VSR34);
135466d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj   case 35: return offsetofPPCGuestState(guest_VSR35);
135566d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj   case 36: return offsetofPPCGuestState(guest_VSR36);
135666d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj   case 37: return offsetofPPCGuestState(guest_VSR37);
135766d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj   case 38: return offsetofPPCGuestState(guest_VSR38);
135866d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj   case 39: return offsetofPPCGuestState(guest_VSR39);
135966d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj   case 40: return offsetofPPCGuestState(guest_VSR40);
136066d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj   case 41: return offsetofPPCGuestState(guest_VSR41);
136166d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj   case 42: return offsetofPPCGuestState(guest_VSR42);
136266d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj   case 43: return offsetofPPCGuestState(guest_VSR43);
136366d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj   case 44: return offsetofPPCGuestState(guest_VSR44);
136466d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj   case 45: return offsetofPPCGuestState(guest_VSR45);
136566d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj   case 46: return offsetofPPCGuestState(guest_VSR46);
136666d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj   case 47: return offsetofPPCGuestState(guest_VSR47);
136766d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj   case 48: return offsetofPPCGuestState(guest_VSR48);
136866d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj   case 49: return offsetofPPCGuestState(guest_VSR49);
136966d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj   case 50: return offsetofPPCGuestState(guest_VSR50);
137066d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj   case 51: return offsetofPPCGuestState(guest_VSR51);
137166d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj   case 52: return offsetofPPCGuestState(guest_VSR52);
137266d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj   case 53: return offsetofPPCGuestState(guest_VSR53);
137366d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj   case 54: return offsetofPPCGuestState(guest_VSR54);
137466d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj   case 55: return offsetofPPCGuestState(guest_VSR55);
137566d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj   case 56: return offsetofPPCGuestState(guest_VSR56);
137666d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj   case 57: return offsetofPPCGuestState(guest_VSR57);
137766d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj   case 58: return offsetofPPCGuestState(guest_VSR58);
137866d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj   case 59: return offsetofPPCGuestState(guest_VSR59);
137966d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj   case 60: return offsetofPPCGuestState(guest_VSR60);
138066d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj   case 61: return offsetofPPCGuestState(guest_VSR61);
138166d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj   case 62: return offsetofPPCGuestState(guest_VSR62);
138266d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj   case 63: return offsetofPPCGuestState(guest_VSR63);
138366d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj   default: break;
138466d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj   }
138566d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj   vpanic("vsxGuestRegOffset(ppc)"); /*notreached*/
138666d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj}
1387094d1397b3f69b1a538e80ab509ea8cd75f4be3bcerion
138866d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj/* Vector registers are mapped to VSX registers[32..63]. */
1389a982c0503d8c0c6069ae453bfe70657bd2c134aecerionstatic Int vectorGuestRegOffset ( UInt archreg )
1390a982c0503d8c0c6069ae453bfe70657bd2c134aecerion{
1391a982c0503d8c0c6069ae453bfe70657bd2c134aecerion   vassert(archreg < 32);
1392a982c0503d8c0c6069ae453bfe70657bd2c134aecerion
13935b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion   switch (archreg) {
139466d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj   case  0: return offsetofPPCGuestState(guest_VSR32);
139566d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj   case  1: return offsetofPPCGuestState(guest_VSR33);
139666d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj   case  2: return offsetofPPCGuestState(guest_VSR34);
139766d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj   case  3: return offsetofPPCGuestState(guest_VSR35);
139866d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj   case  4: return offsetofPPCGuestState(guest_VSR36);
139966d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj   case  5: return offsetofPPCGuestState(guest_VSR37);
140066d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj   case  6: return offsetofPPCGuestState(guest_VSR38);
140166d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj   case  7: return offsetofPPCGuestState(guest_VSR39);
140266d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj   case  8: return offsetofPPCGuestState(guest_VSR40);
140366d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj   case  9: return offsetofPPCGuestState(guest_VSR41);
140466d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj   case 10: return offsetofPPCGuestState(guest_VSR42);
140566d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj   case 11: return offsetofPPCGuestState(guest_VSR43);
140666d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj   case 12: return offsetofPPCGuestState(guest_VSR44);
140766d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj   case 13: return offsetofPPCGuestState(guest_VSR45);
140866d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj   case 14: return offsetofPPCGuestState(guest_VSR46);
140966d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj   case 15: return offsetofPPCGuestState(guest_VSR47);
141066d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj   case 16: return offsetofPPCGuestState(guest_VSR48);
141166d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj   case 17: return offsetofPPCGuestState(guest_VSR49);
141266d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj   case 18: return offsetofPPCGuestState(guest_VSR50);
141366d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj   case 19: return offsetofPPCGuestState(guest_VSR51);
141466d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj   case 20: return offsetofPPCGuestState(guest_VSR52);
141566d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj   case 21: return offsetofPPCGuestState(guest_VSR53);
141666d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj   case 22: return offsetofPPCGuestState(guest_VSR54);
141766d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj   case 23: return offsetofPPCGuestState(guest_VSR55);
141866d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj   case 24: return offsetofPPCGuestState(guest_VSR56);
141966d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj   case 25: return offsetofPPCGuestState(guest_VSR57);
142066d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj   case 26: return offsetofPPCGuestState(guest_VSR58);
142166d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj   case 27: return offsetofPPCGuestState(guest_VSR59);
142266d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj   case 28: return offsetofPPCGuestState(guest_VSR60);
142366d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj   case 29: return offsetofPPCGuestState(guest_VSR61);
142466d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj   case 30: return offsetofPPCGuestState(guest_VSR62);
142566d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj   case 31: return offsetofPPCGuestState(guest_VSR63);
14265b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion   default: break;
14275b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion   }
14285b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion   vpanic("vextorGuestRegOffset(ppc)"); /*notreached*/
1429a982c0503d8c0c6069ae453bfe70657bd2c134aecerion}
1430a982c0503d8c0c6069ae453bfe70657bd2c134aecerion
1431a982c0503d8c0c6069ae453bfe70657bd2c134aecerionstatic IRExpr* getVReg ( UInt archreg )
1432a982c0503d8c0c6069ae453bfe70657bd2c134aecerion{
1433a982c0503d8c0c6069ae453bfe70657bd2c134aecerion   vassert(archreg < 32);
1434a982c0503d8c0c6069ae453bfe70657bd2c134aecerion   return IRExpr_Get( vectorGuestRegOffset(archreg), Ity_V128 );
1435a982c0503d8c0c6069ae453bfe70657bd2c134aecerion}
1436a982c0503d8c0c6069ae453bfe70657bd2c134aecerion
1437a982c0503d8c0c6069ae453bfe70657bd2c134aecerion/* Ditto, but write to a reg instead. */
1438a982c0503d8c0c6069ae453bfe70657bd2c134aecerionstatic void putVReg ( UInt archreg, IRExpr* e )
1439a982c0503d8c0c6069ae453bfe70657bd2c134aecerion{
1440a982c0503d8c0c6069ae453bfe70657bd2c134aecerion   vassert(archreg < 32);
1441dd40fdf58cc8a6fe9466c4f00bdfc9fe9bf00449sewardj   vassert(typeOfIRExpr(irsb->tyenv, e) == Ity_V128);
1442a982c0503d8c0c6069ae453bfe70657bd2c134aecerion   stmt( IRStmt_Put(vectorGuestRegOffset(archreg), e) );
1443a982c0503d8c0c6069ae453bfe70657bd2c134aecerion}
1444a982c0503d8c0c6069ae453bfe70657bd2c134aecerion
144566d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj/* Get contents of VSX guest register */
144666d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardjstatic IRExpr* getVSReg ( UInt archreg )
144766d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj{
144866d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj   vassert(archreg < 64);
144966d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj   return IRExpr_Get( vsxGuestRegOffset(archreg), Ity_V128 );
145066d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj}
145166d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj
145266d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj/* Ditto, but write to a VSX reg instead. */
145366d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardjstatic void putVSReg ( UInt archreg, IRExpr* e )
145466d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj{
145566d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj   vassert(archreg < 64);
145666d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj   vassert(typeOfIRExpr(irsb->tyenv, e) == Ity_V128);
145766d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj   stmt( IRStmt_Put(vsxGuestRegOffset(archreg), e) );
145866d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj}
145966d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj
146066d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj
1461b51f0f4f33256638ed953156a2635aa739b232f1sewardjstatic Int guestCR321offset ( UInt cr )
1462896a1373cfdbaa25f4ab73ed4f27554016defecccerion{
14635b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion   switch (cr) {
14645b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion   case 0: return offsetofPPCGuestState(guest_CR0_321 );
14655b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion   case 1: return offsetofPPCGuestState(guest_CR1_321 );
14665b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion   case 2: return offsetofPPCGuestState(guest_CR2_321 );
14675b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion   case 3: return offsetofPPCGuestState(guest_CR3_321 );
14685b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion   case 4: return offsetofPPCGuestState(guest_CR4_321 );
14695b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion   case 5: return offsetofPPCGuestState(guest_CR5_321 );
14705b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion   case 6: return offsetofPPCGuestState(guest_CR6_321 );
14715b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion   case 7: return offsetofPPCGuestState(guest_CR7_321 );
14725b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion   default: vpanic("guestCR321offset(ppc)");
1473b51f0f4f33256638ed953156a2635aa739b232f1sewardj   }
1474b51f0f4f33256638ed953156a2635aa739b232f1sewardj}
1475896a1373cfdbaa25f4ab73ed4f27554016defecccerion
1476b51f0f4f33256638ed953156a2635aa739b232f1sewardjstatic Int guestCR0offset ( UInt cr )
1477896a1373cfdbaa25f4ab73ed4f27554016defecccerion{
14785b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion   switch (cr) {
14795b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion   case 0: return offsetofPPCGuestState(guest_CR0_0 );
14805b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion   case 1: return offsetofPPCGuestState(guest_CR1_0 );
14815b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion   case 2: return offsetofPPCGuestState(guest_CR2_0 );
14825b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion   case 3: return offsetofPPCGuestState(guest_CR3_0 );
14835b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion   case 4: return offsetofPPCGuestState(guest_CR4_0 );
14845b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion   case 5: return offsetofPPCGuestState(guest_CR5_0 );
14855b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion   case 6: return offsetofPPCGuestState(guest_CR6_0 );
14865b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion   case 7: return offsetofPPCGuestState(guest_CR7_0 );
14875b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion   default: vpanic("guestCR3offset(ppc)");
1488b51f0f4f33256638ed953156a2635aa739b232f1sewardj   }
1489896a1373cfdbaa25f4ab73ed4f27554016defecccerion}
1490896a1373cfdbaa25f4ab73ed4f27554016defecccerion
14917deaf9552b546b847528cf39b38898fb7742b5f5carlltypedef enum {
14927deaf9552b546b847528cf39b38898fb7742b5f5carll   _placeholder0,
14937deaf9552b546b847528cf39b38898fb7742b5f5carll   _placeholder1,
14947deaf9552b546b847528cf39b38898fb7742b5f5carll   _placeholder2,
14957deaf9552b546b847528cf39b38898fb7742b5f5carll   BYTE,
14967deaf9552b546b847528cf39b38898fb7742b5f5carll   HWORD,
14977deaf9552b546b847528cf39b38898fb7742b5f5carll   WORD,
14987deaf9552b546b847528cf39b38898fb7742b5f5carll   DWORD
14997deaf9552b546b847528cf39b38898fb7742b5f5carll} _popcount_data_type;
15007deaf9552b546b847528cf39b38898fb7742b5f5carll
150166d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj/* Generate an IR sequence to do a popcount operation on the supplied
1502e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj   IRTemp, and return a new IRTemp holding the result.  'ty' may be
1503e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj   Ity_I32 or Ity_I64 only. */
15047deaf9552b546b847528cf39b38898fb7742b5f5carllstatic IRTemp gen_POPCOUNT ( IRType ty, IRTemp src, _popcount_data_type data_type )
150566d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj{
15067deaf9552b546b847528cf39b38898fb7742b5f5carll  /* Do count across 2^data_type bits,
15077deaf9552b546b847528cf39b38898fb7742b5f5carll     byte:        data_type = 3
15087deaf9552b546b847528cf39b38898fb7742b5f5carll     half word:   data_type = 4
15097deaf9552b546b847528cf39b38898fb7742b5f5carll     word:        data_type = 5
15107deaf9552b546b847528cf39b38898fb7742b5f5carll     double word: data_type = 6  (not supported for 32-bit type)
15117deaf9552b546b847528cf39b38898fb7742b5f5carll    */
15127deaf9552b546b847528cf39b38898fb7742b5f5carll   Int shift[6];
15137deaf9552b546b847528cf39b38898fb7742b5f5carll   _popcount_data_type idx, i;
1514e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj   IRTemp mask[6];
151566d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj   IRTemp old = IRTemp_INVALID;
151666d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj   IRTemp nyu = IRTemp_INVALID;
151766d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj
1518e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj   vassert(ty == Ity_I64 || ty == Ity_I32);
1519e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj
1520e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj   if (ty == Ity_I32) {
1521738d9dddf788cd66fc04081f5fca872f38859813philippe
15227deaf9552b546b847528cf39b38898fb7742b5f5carll      for (idx = 0; idx < WORD; idx++) {
15237deaf9552b546b847528cf39b38898fb7742b5f5carll         mask[idx]  = newTemp(ty);
15247deaf9552b546b847528cf39b38898fb7742b5f5carll         shift[idx] = 1 << idx;
1525e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj      }
1526e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj      assign(mask[0], mkU32(0x55555555));
1527e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj      assign(mask[1], mkU32(0x33333333));
1528e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj      assign(mask[2], mkU32(0x0F0F0F0F));
1529e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj      assign(mask[3], mkU32(0x00FF00FF));
1530e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj      assign(mask[4], mkU32(0x0000FFFF));
1531e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj      old = src;
15327deaf9552b546b847528cf39b38898fb7742b5f5carll      for (i = 0; i < data_type; i++) {
1533e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj         nyu = newTemp(ty);
1534e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj         assign(nyu,
1535e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj                binop(Iop_Add32,
1536e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj                      binop(Iop_And32,
1537e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj                            mkexpr(old),
1538e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj                            mkexpr(mask[i])),
1539e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj                      binop(Iop_And32,
1540e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj                            binop(Iop_Shr32, mkexpr(old), mkU8(shift[i])),
1541e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj                            mkexpr(mask[i]))));
1542e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj         old = nyu;
1543e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj      }
1544e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj      return nyu;
1545e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj   }
15467deaf9552b546b847528cf39b38898fb7742b5f5carll
1547e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj// else, ty == Ity_I64
15487deaf9552b546b847528cf39b38898fb7742b5f5carll   vassert(mode64);
1549738d9dddf788cd66fc04081f5fca872f38859813philippe
15507deaf9552b546b847528cf39b38898fb7742b5f5carll   for (i = 0; i < DWORD; i++) {
155166d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj      mask[i] = newTemp( Ity_I64 );
155266d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj      shift[i] = 1 << i;
155366d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj   }
155466d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj   assign( mask[0], mkU64( 0x5555555555555555ULL ) );
155566d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj   assign( mask[1], mkU64( 0x3333333333333333ULL ) );
155666d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj   assign( mask[2], mkU64( 0x0F0F0F0F0F0F0F0FULL ) );
155766d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj   assign( mask[3], mkU64( 0x00FF00FF00FF00FFULL ) );
155866d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj   assign( mask[4], mkU64( 0x0000FFFF0000FFFFULL ) );
155966d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj   assign( mask[5], mkU64( 0x00000000FFFFFFFFULL ) );
156066d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj   old = src;
15617deaf9552b546b847528cf39b38898fb7742b5f5carll   for (i = 0; i < data_type; i++) {
156266d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj      nyu = newTemp( Ity_I64 );
156366d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj      assign( nyu,
156466d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj              binop( Iop_Add64,
156566d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj                     binop( Iop_And64, mkexpr( old ), mkexpr( mask[i] ) ),
156666d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj                     binop( Iop_And64,
156766d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj                            binop( Iop_Shr64, mkexpr( old ), mkU8( shift[i] ) ),
156866d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj                            mkexpr( mask[i] ) ) ) );
156966d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj      old = nyu;
157066d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj   }
157166d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj   return nyu;
157266d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj}
157366d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj
15747deaf9552b546b847528cf39b38898fb7742b5f5carll/* Special purpose population count function for
15757deaf9552b546b847528cf39b38898fb7742b5f5carll * vpopcntd in 32-bit mode.
15767deaf9552b546b847528cf39b38898fb7742b5f5carll */
15777deaf9552b546b847528cf39b38898fb7742b5f5carllstatic IRTemp gen_vpopcntd_mode32 ( IRTemp src1, IRTemp src2 )
15787deaf9552b546b847528cf39b38898fb7742b5f5carll{
15797deaf9552b546b847528cf39b38898fb7742b5f5carll   Int i, shift[6];
15807deaf9552b546b847528cf39b38898fb7742b5f5carll   IRTemp mask[6];
15817deaf9552b546b847528cf39b38898fb7742b5f5carll   IRTemp old = IRTemp_INVALID;
15827deaf9552b546b847528cf39b38898fb7742b5f5carll   IRTemp nyu1 = IRTemp_INVALID;
15837deaf9552b546b847528cf39b38898fb7742b5f5carll   IRTemp nyu2 = IRTemp_INVALID;
15847deaf9552b546b847528cf39b38898fb7742b5f5carll   IRTemp retval = newTemp(Ity_I64);
15857deaf9552b546b847528cf39b38898fb7742b5f5carll
15867deaf9552b546b847528cf39b38898fb7742b5f5carll   vassert(!mode64);
15877deaf9552b546b847528cf39b38898fb7742b5f5carll
15887deaf9552b546b847528cf39b38898fb7742b5f5carll   for (i = 0; i < WORD; i++) {
15897deaf9552b546b847528cf39b38898fb7742b5f5carll      mask[i]  = newTemp(Ity_I32);
15907deaf9552b546b847528cf39b38898fb7742b5f5carll      shift[i] = 1 << i;
15917deaf9552b546b847528cf39b38898fb7742b5f5carll   }
15927deaf9552b546b847528cf39b38898fb7742b5f5carll   assign(mask[0], mkU32(0x55555555));
15937deaf9552b546b847528cf39b38898fb7742b5f5carll   assign(mask[1], mkU32(0x33333333));
15947deaf9552b546b847528cf39b38898fb7742b5f5carll   assign(mask[2], mkU32(0x0F0F0F0F));
15957deaf9552b546b847528cf39b38898fb7742b5f5carll   assign(mask[3], mkU32(0x00FF00FF));
15967deaf9552b546b847528cf39b38898fb7742b5f5carll   assign(mask[4], mkU32(0x0000FFFF));
15977deaf9552b546b847528cf39b38898fb7742b5f5carll   old = src1;
15987deaf9552b546b847528cf39b38898fb7742b5f5carll   for (i = 0; i < WORD; i++) {
15997deaf9552b546b847528cf39b38898fb7742b5f5carll      nyu1 = newTemp(Ity_I32);
16007deaf9552b546b847528cf39b38898fb7742b5f5carll      assign(nyu1,
16017deaf9552b546b847528cf39b38898fb7742b5f5carll             binop(Iop_Add32,
16027deaf9552b546b847528cf39b38898fb7742b5f5carll                   binop(Iop_And32,
16037deaf9552b546b847528cf39b38898fb7742b5f5carll                         mkexpr(old),
16047deaf9552b546b847528cf39b38898fb7742b5f5carll                         mkexpr(mask[i])),
16057deaf9552b546b847528cf39b38898fb7742b5f5carll                   binop(Iop_And32,
16067deaf9552b546b847528cf39b38898fb7742b5f5carll                         binop(Iop_Shr32, mkexpr(old), mkU8(shift[i])),
16077deaf9552b546b847528cf39b38898fb7742b5f5carll                         mkexpr(mask[i]))));
16087deaf9552b546b847528cf39b38898fb7742b5f5carll      old = nyu1;
16097deaf9552b546b847528cf39b38898fb7742b5f5carll   }
16107deaf9552b546b847528cf39b38898fb7742b5f5carll
16117deaf9552b546b847528cf39b38898fb7742b5f5carll   old = src2;
16127deaf9552b546b847528cf39b38898fb7742b5f5carll   for (i = 0; i < WORD; i++) {
16137deaf9552b546b847528cf39b38898fb7742b5f5carll      nyu2 = newTemp(Ity_I32);
16147deaf9552b546b847528cf39b38898fb7742b5f5carll      assign(nyu2,
16157deaf9552b546b847528cf39b38898fb7742b5f5carll             binop(Iop_Add32,
16167deaf9552b546b847528cf39b38898fb7742b5f5carll                   binop(Iop_And32,
16177deaf9552b546b847528cf39b38898fb7742b5f5carll                         mkexpr(old),
16187deaf9552b546b847528cf39b38898fb7742b5f5carll                         mkexpr(mask[i])),
16197deaf9552b546b847528cf39b38898fb7742b5f5carll                   binop(Iop_And32,
16207deaf9552b546b847528cf39b38898fb7742b5f5carll                         binop(Iop_Shr32, mkexpr(old), mkU8(shift[i])),
16217deaf9552b546b847528cf39b38898fb7742b5f5carll                         mkexpr(mask[i]))));
16227deaf9552b546b847528cf39b38898fb7742b5f5carll      old = nyu2;
16237deaf9552b546b847528cf39b38898fb7742b5f5carll   }
16247deaf9552b546b847528cf39b38898fb7742b5f5carll   assign(retval, unop(Iop_32Uto64, binop(Iop_Add32, mkexpr(nyu1), mkexpr(nyu2))));
16257deaf9552b546b847528cf39b38898fb7742b5f5carll   return retval;
16267deaf9552b546b847528cf39b38898fb7742b5f5carll}
16277deaf9552b546b847528cf39b38898fb7742b5f5carll
162866d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj
162907b07a966a2fdbcf621251a0c1a8ab84807fb120cerion// ROTL(src32/64, rot_amt5/6)
1630d953ebb9b04cbad6891676df597bf0c542b1ec89cerionstatic IRExpr* /* :: Ity_I32/64 */ ROTL ( IRExpr* src,
1631d953ebb9b04cbad6891676df597bf0c542b1ec89cerion                                          IRExpr* rot_amt )
1632896a1373cfdbaa25f4ab73ed4f27554016defecccerion{
1633d953ebb9b04cbad6891676df597bf0c542b1ec89cerion   IRExpr *mask, *rot;
1634dd40fdf58cc8a6fe9466c4f00bdfc9fe9bf00449sewardj   vassert(typeOfIRExpr(irsb->tyenv,rot_amt) == Ity_I8);
1635d953ebb9b04cbad6891676df597bf0c542b1ec89cerion
1636dd40fdf58cc8a6fe9466c4f00bdfc9fe9bf00449sewardj   if (typeOfIRExpr(irsb->tyenv,src) == Ity_I64) {
1637d953ebb9b04cbad6891676df597bf0c542b1ec89cerion      // rot = (src << rot_amt) | (src >> (64-rot_amt))
1638d953ebb9b04cbad6891676df597bf0c542b1ec89cerion      mask = binop(Iop_And8, rot_amt, mkU8(63));
1639d953ebb9b04cbad6891676df597bf0c542b1ec89cerion      rot  = binop(Iop_Or64,
1640d953ebb9b04cbad6891676df597bf0c542b1ec89cerion                binop(Iop_Shl64, src, mask),
1641d953ebb9b04cbad6891676df597bf0c542b1ec89cerion                binop(Iop_Shr64, src, binop(Iop_Sub8, mkU8(64), mask)));
1642d953ebb9b04cbad6891676df597bf0c542b1ec89cerion   } else {
1643d953ebb9b04cbad6891676df597bf0c542b1ec89cerion      // rot = (src << rot_amt) | (src >> (32-rot_amt))
1644f0de28cf1a762b0d6f74c93d3532c89a230673bbcerion      mask = binop(Iop_And8, rot_amt, mkU8(31));
1645d953ebb9b04cbad6891676df597bf0c542b1ec89cerion      rot  = binop(Iop_Or32,
1646d953ebb9b04cbad6891676df597bf0c542b1ec89cerion                binop(Iop_Shl32, src, mask),
1647d953ebb9b04cbad6891676df597bf0c542b1ec89cerion                binop(Iop_Shr32, src, binop(Iop_Sub8, mkU8(32), mask)));
16482831b00c4950d6c2b061def05fd67528fe132ececerion   }
164999dd03e04a6914d90d5fee727d61d76905334becflorian   /* Note: the ITE not merely an optimisation; it's needed
1650f0de28cf1a762b0d6f74c93d3532c89a230673bbcerion      because otherwise the Shr is a shift by the word size when
1651d953ebb9b04cbad6891676df597bf0c542b1ec89cerion      mask denotes zero.  For rotates by immediates, a lot of
1652c965953e12be58c7d01cd6d024d6f42326b2b797sewardj      this junk gets folded out. */
165399dd03e04a6914d90d5fee727d61d76905334becflorian   return IRExpr_ITE( binop(Iop_CmpNE8, mask, mkU8(0)),
165499dd03e04a6914d90d5fee727d61d76905334becflorian                      /* non-zero rotate */ rot,
165599dd03e04a6914d90d5fee727d61d76905334becflorian                      /*     zero rotate */ src);
1656d953ebb9b04cbad6891676df597bf0c542b1ec89cerion}
1657d953ebb9b04cbad6891676df597bf0c542b1ec89cerion
1658d953ebb9b04cbad6891676df597bf0c542b1ec89cerion/* Standard effective address calc: (rA + rB) */
1659d953ebb9b04cbad6891676df597bf0c542b1ec89cerionstatic IRExpr* ea_rA_idxd ( UInt rA, UInt rB )
1660d953ebb9b04cbad6891676df597bf0c542b1ec89cerion{
1661d953ebb9b04cbad6891676df597bf0c542b1ec89cerion   IRType ty = mode64 ? Ity_I64 : Ity_I32;
1662d953ebb9b04cbad6891676df597bf0c542b1ec89cerion   vassert(rA < 32);
1663d953ebb9b04cbad6891676df597bf0c542b1ec89cerion   vassert(rB < 32);
16642831b00c4950d6c2b061def05fd67528fe132ececerion   return binop(mkSzOp(ty, Iop_Add8), getIReg(rA), getIReg(rB));
1665d953ebb9b04cbad6891676df597bf0c542b1ec89cerion}
1666d953ebb9b04cbad6891676df597bf0c542b1ec89cerion
1667d953ebb9b04cbad6891676df597bf0c542b1ec89cerion/* Standard effective address calc: (rA + simm) */
1668d953ebb9b04cbad6891676df597bf0c542b1ec89cerionstatic IRExpr* ea_rA_simm ( UInt rA, UInt simm16 )
1669d953ebb9b04cbad6891676df597bf0c542b1ec89cerion{
1670d953ebb9b04cbad6891676df597bf0c542b1ec89cerion   IRType ty = mode64 ? Ity_I64 : Ity_I32;
1671d953ebb9b04cbad6891676df597bf0c542b1ec89cerion   vassert(rA < 32);
16722831b00c4950d6c2b061def05fd67528fe132ececerion   return binop(mkSzOp(ty, Iop_Add8), getIReg(rA),
16732831b00c4950d6c2b061def05fd67528fe132ececerion                mkSzExtendS16(ty, simm16));
167445b70ff2e85482063232b4e7c6f47be2ddeeb5d9cerion}
1675896a1373cfdbaa25f4ab73ed4f27554016defecccerion
1676d953ebb9b04cbad6891676df597bf0c542b1ec89cerion/* Standard effective address calc: (rA|0) */
1677d953ebb9b04cbad6891676df597bf0c542b1ec89cerionstatic IRExpr* ea_rAor0 ( UInt rA )
167887e651f40360a8f1c9418710e79c482028759f8csewardj{
1679d953ebb9b04cbad6891676df597bf0c542b1ec89cerion   IRType ty = mode64 ? Ity_I64 : Ity_I32;
1680d953ebb9b04cbad6891676df597bf0c542b1ec89cerion   vassert(rA < 32);
168187e651f40360a8f1c9418710e79c482028759f8csewardj   if (rA == 0) {
16822831b00c4950d6c2b061def05fd67528fe132ececerion      return mkSzImm(ty, 0);
168387e651f40360a8f1c9418710e79c482028759f8csewardj   } else {
1684d953ebb9b04cbad6891676df597bf0c542b1ec89cerion      return getIReg(rA);
168587e651f40360a8f1c9418710e79c482028759f8csewardj   }
168687e651f40360a8f1c9418710e79c482028759f8csewardj}
168787e651f40360a8f1c9418710e79c482028759f8csewardj
1688d953ebb9b04cbad6891676df597bf0c542b1ec89cerion/* Standard effective address calc: (rA|0) + rB */
1689d953ebb9b04cbad6891676df597bf0c542b1ec89cerionstatic IRExpr* ea_rAor0_idxd ( UInt rA, UInt rB )
1690d953ebb9b04cbad6891676df597bf0c542b1ec89cerion{
1691d953ebb9b04cbad6891676df597bf0c542b1ec89cerion   vassert(rA < 32);
1692d953ebb9b04cbad6891676df597bf0c542b1ec89cerion   vassert(rB < 32);
1693d953ebb9b04cbad6891676df597bf0c542b1ec89cerion   return (rA == 0) ? getIReg(rB) : ea_rA_idxd( rA, rB );
1694d953ebb9b04cbad6891676df597bf0c542b1ec89cerion}
1695d953ebb9b04cbad6891676df597bf0c542b1ec89cerion
1696d953ebb9b04cbad6891676df597bf0c542b1ec89cerion/* Standard effective address calc: (rA|0) + simm16 */
1697d953ebb9b04cbad6891676df597bf0c542b1ec89cerionstatic IRExpr* ea_rAor0_simm ( UInt rA, UInt simm16 )
169887e651f40360a8f1c9418710e79c482028759f8csewardj{
1699d953ebb9b04cbad6891676df597bf0c542b1ec89cerion   IRType ty = mode64 ? Ity_I64 : Ity_I32;
1700d953ebb9b04cbad6891676df597bf0c542b1ec89cerion   vassert(rA < 32);
170187e651f40360a8f1c9418710e79c482028759f8csewardj   if (rA == 0) {
17022831b00c4950d6c2b061def05fd67528fe132ececerion      return mkSzExtendS16(ty, simm16);
170387e651f40360a8f1c9418710e79c482028759f8csewardj   } else {
1704d953ebb9b04cbad6891676df597bf0c542b1ec89cerion      return ea_rA_simm( rA, simm16 );
1705d953ebb9b04cbad6891676df597bf0c542b1ec89cerion   }
1706d953ebb9b04cbad6891676df597bf0c542b1ec89cerion}
1707d953ebb9b04cbad6891676df597bf0c542b1ec89cerion
1708d953ebb9b04cbad6891676df597bf0c542b1ec89cerion
1709d953ebb9b04cbad6891676df597bf0c542b1ec89cerion/* Align effective address */
1710d953ebb9b04cbad6891676df597bf0c542b1ec89cerionstatic IRExpr* addr_align( IRExpr* addr, UChar align )
1711d953ebb9b04cbad6891676df597bf0c542b1ec89cerion{
1712d953ebb9b04cbad6891676df597bf0c542b1ec89cerion   IRType ty = mode64 ? Ity_I64 : Ity_I32;
1713d953ebb9b04cbad6891676df597bf0c542b1ec89cerion   Long mask;
1714d953ebb9b04cbad6891676df597bf0c542b1ec89cerion   switch (align) {
17152831b00c4950d6c2b061def05fd67528fe132ececerion   case 1:  return addr;                    // byte aligned
1716d953ebb9b04cbad6891676df597bf0c542b1ec89cerion   case 2:  mask = ((Long)-1) << 1; break;  // half-word aligned
1717d953ebb9b04cbad6891676df597bf0c542b1ec89cerion   case 4:  mask = ((Long)-1) << 2; break;  // word aligned
1718d953ebb9b04cbad6891676df597bf0c542b1ec89cerion   case 16: mask = ((Long)-1) << 4; break;  // quad-word aligned
1719d953ebb9b04cbad6891676df597bf0c542b1ec89cerion   default:
1720d953ebb9b04cbad6891676df597bf0c542b1ec89cerion      vex_printf("addr_align: align = %u\n", align);
17215b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion      vpanic("addr_align(ppc)");
172287e651f40360a8f1c9418710e79c482028759f8csewardj   }
1723d953ebb9b04cbad6891676df597bf0c542b1ec89cerion
1724dd40fdf58cc8a6fe9466c4f00bdfc9fe9bf00449sewardj   vassert(typeOfIRExpr(irsb->tyenv,addr) == ty);
1725fb197c49c89d04987ef801657b2bedc4050e1539cerion   return binop( mkSzOp(ty, Iop_And8), addr, mkSzImm(ty, mask) );
172687e651f40360a8f1c9418710e79c482028759f8csewardj}
172787e651f40360a8f1c9418710e79c482028759f8csewardj
1728896a1373cfdbaa25f4ab73ed4f27554016defecccerion
1729e9d8a26b690c2561ac54ab0cd6ad83ecbadcbe76sewardj/* Exit the trace if ADDR (intended to be a guest memory address) is
1730e9d8a26b690c2561ac54ab0cd6ad83ecbadcbe76sewardj   not ALIGN-aligned, generating a request for a SIGBUS followed by a
1731e9d8a26b690c2561ac54ab0cd6ad83ecbadcbe76sewardj   restart of the current insn. */
1732e9d8a26b690c2561ac54ab0cd6ad83ecbadcbe76sewardjstatic void gen_SIGBUS_if_misaligned ( IRTemp addr, UChar align )
1733e9d8a26b690c2561ac54ab0cd6ad83ecbadcbe76sewardj{
1734d826889bd512ded2fbbc4781c595ecf0513f46f6carll   vassert(align == 2 || align == 4 || align == 8 || align == 16);
1735e9d8a26b690c2561ac54ab0cd6ad83ecbadcbe76sewardj   if (mode64) {
1736e9d8a26b690c2561ac54ab0cd6ad83ecbadcbe76sewardj      vassert(typeOfIRTemp(irsb->tyenv, addr) == Ity_I64);
1737e9d8a26b690c2561ac54ab0cd6ad83ecbadcbe76sewardj      stmt(
1738e9d8a26b690c2561ac54ab0cd6ad83ecbadcbe76sewardj         IRStmt_Exit(
1739e9d8a26b690c2561ac54ab0cd6ad83ecbadcbe76sewardj            binop(Iop_CmpNE64,
1740e9d8a26b690c2561ac54ab0cd6ad83ecbadcbe76sewardj                  binop(Iop_And64, mkexpr(addr), mkU64(align-1)),
1741e9d8a26b690c2561ac54ab0cd6ad83ecbadcbe76sewardj                  mkU64(0)),
1742e9d8a26b690c2561ac54ab0cd6ad83ecbadcbe76sewardj            Ijk_SigBUS,
17433dee849ec7c38746749065e67dc53b75daa7617dsewardj            IRConst_U64( guest_CIA_curr_instr ), OFFB_CIA
1744e9d8a26b690c2561ac54ab0cd6ad83ecbadcbe76sewardj         )
1745e9d8a26b690c2561ac54ab0cd6ad83ecbadcbe76sewardj      );
1746e9d8a26b690c2561ac54ab0cd6ad83ecbadcbe76sewardj   } else {
1747e9d8a26b690c2561ac54ab0cd6ad83ecbadcbe76sewardj      vassert(typeOfIRTemp(irsb->tyenv, addr) == Ity_I32);
1748e9d8a26b690c2561ac54ab0cd6ad83ecbadcbe76sewardj      stmt(
1749e9d8a26b690c2561ac54ab0cd6ad83ecbadcbe76sewardj         IRStmt_Exit(
1750e9d8a26b690c2561ac54ab0cd6ad83ecbadcbe76sewardj            binop(Iop_CmpNE32,
1751e9d8a26b690c2561ac54ab0cd6ad83ecbadcbe76sewardj                  binop(Iop_And32, mkexpr(addr), mkU32(align-1)),
1752e9d8a26b690c2561ac54ab0cd6ad83ecbadcbe76sewardj                  mkU32(0)),
1753e9d8a26b690c2561ac54ab0cd6ad83ecbadcbe76sewardj            Ijk_SigBUS,
17543dee849ec7c38746749065e67dc53b75daa7617dsewardj            IRConst_U32( guest_CIA_curr_instr ), OFFB_CIA
1755e9d8a26b690c2561ac54ab0cd6ad83ecbadcbe76sewardj         )
1756e9d8a26b690c2561ac54ab0cd6ad83ecbadcbe76sewardj      );
1757e9d8a26b690c2561ac54ab0cd6ad83ecbadcbe76sewardj   }
1758e9d8a26b690c2561ac54ab0cd6ad83ecbadcbe76sewardj}
1759e9d8a26b690c2561ac54ab0cd6ad83ecbadcbe76sewardj
1760e9d8a26b690c2561ac54ab0cd6ad83ecbadcbe76sewardj
1761aca070a5b3418a6a9b01e3c57a7eb0fbb5050908sewardj/* Generate AbiHints which mark points at which the ELF or PowerOpen
1762aca070a5b3418a6a9b01e3c57a7eb0fbb5050908sewardj   ABIs say that the stack red zone (viz, -N(r1) .. -1(r1), for some
1763aca070a5b3418a6a9b01e3c57a7eb0fbb5050908sewardj   N) becomes undefined.  That is at function calls and returns.  ELF
1764478646f54befaba01cbceb40fd5e46cdf562fdb5sewardj   ppc32 doesn't have this "feature" (how fortunate for it).  nia is
1765478646f54befaba01cbceb40fd5e46cdf562fdb5sewardj   the address of the next instruction to be executed.
1766cf8986c47a4c8c810566bb5b7b3da7a16a17dfe2sewardj*/
1767cacba8e675988fbf21b08feea1f317a9c896c053florianstatic void make_redzone_AbiHint ( const VexAbiInfo* vbi,
176855085f8680acc89d727e321f3b34cae1a8c4093aflorian                                   IRTemp nia, const HChar* who )
1769cf8986c47a4c8c810566bb5b7b3da7a16a17dfe2sewardj{
1770dd40fdf58cc8a6fe9466c4f00bdfc9fe9bf00449sewardj   Int szB = vbi->guest_stack_redzone_size;
1771cf8986c47a4c8c810566bb5b7b3da7a16a17dfe2sewardj   if (0) vex_printf("AbiHint: %s\n", who);
1772aca070a5b3418a6a9b01e3c57a7eb0fbb5050908sewardj   vassert(szB >= 0);
1773aca070a5b3418a6a9b01e3c57a7eb0fbb5050908sewardj   if (szB > 0) {
1774478646f54befaba01cbceb40fd5e46cdf562fdb5sewardj      if (mode64) {
1775478646f54befaba01cbceb40fd5e46cdf562fdb5sewardj         vassert(typeOfIRTemp(irsb->tyenv, nia) == Ity_I64);
1776aca070a5b3418a6a9b01e3c57a7eb0fbb5050908sewardj         stmt( IRStmt_AbiHint(
1777aca070a5b3418a6a9b01e3c57a7eb0fbb5050908sewardj                  binop(Iop_Sub64, getIReg(1), mkU64(szB)),
1778478646f54befaba01cbceb40fd5e46cdf562fdb5sewardj                  szB,
1779478646f54befaba01cbceb40fd5e46cdf562fdb5sewardj                  mkexpr(nia)
1780aca070a5b3418a6a9b01e3c57a7eb0fbb5050908sewardj         ));
1781478646f54befaba01cbceb40fd5e46cdf562fdb5sewardj      } else {
1782478646f54befaba01cbceb40fd5e46cdf562fdb5sewardj         vassert(typeOfIRTemp(irsb->tyenv, nia) == Ity_I32);
1783aca070a5b3418a6a9b01e3c57a7eb0fbb5050908sewardj         stmt( IRStmt_AbiHint(
1784aca070a5b3418a6a9b01e3c57a7eb0fbb5050908sewardj                  binop(Iop_Sub32, getIReg(1), mkU32(szB)),
1785478646f54befaba01cbceb40fd5e46cdf562fdb5sewardj                  szB,
1786478646f54befaba01cbceb40fd5e46cdf562fdb5sewardj                  mkexpr(nia)
1787aca070a5b3418a6a9b01e3c57a7eb0fbb5050908sewardj         ));
1788478646f54befaba01cbceb40fd5e46cdf562fdb5sewardj      }
1789aca070a5b3418a6a9b01e3c57a7eb0fbb5050908sewardj   }
1790cf8986c47a4c8c810566bb5b7b3da7a16a17dfe2sewardj}
1791cf8986c47a4c8c810566bb5b7b3da7a16a17dfe2sewardj
1792cf8986c47a4c8c810566bb5b7b3da7a16a17dfe2sewardj
1793b51f0f4f33256638ed953156a2635aa739b232f1sewardj/*------------------------------------------------------------*/
1794b51f0f4f33256638ed953156a2635aa739b232f1sewardj/*--- Helpers for condition codes.                         ---*/
1795b51f0f4f33256638ed953156a2635aa739b232f1sewardj/*------------------------------------------------------------*/
1796b51f0f4f33256638ed953156a2635aa739b232f1sewardj
1797b51f0f4f33256638ed953156a2635aa739b232f1sewardj/* Condition register layout.
1798896a1373cfdbaa25f4ab73ed4f27554016defecccerion
1799b51f0f4f33256638ed953156a2635aa739b232f1sewardj   In the hardware, CR is laid out like this.  The leftmost end is the
1800b51f0f4f33256638ed953156a2635aa739b232f1sewardj   most significant bit in the register; however the IBM documentation
1801b51f0f4f33256638ed953156a2635aa739b232f1sewardj   numbers the bits backwards for some reason.
1802896a1373cfdbaa25f4ab73ed4f27554016defecccerion
1803b51f0f4f33256638ed953156a2635aa739b232f1sewardj   CR0      CR1    ..........   CR6       CR7
1804b51f0f4f33256638ed953156a2635aa739b232f1sewardj   0 .. 3   .......................  28 .. 31    (IBM bit numbering)
1805b51f0f4f33256638ed953156a2635aa739b232f1sewardj   31  28                             3    0     (normal bit numbering)
1806896a1373cfdbaa25f4ab73ed4f27554016defecccerion
1807edf7fc572e2decb93e9143961e8739c8fe18899dcerion   Each CR field is 4 bits:  [<,>,==,SO]
1808896a1373cfdbaa25f4ab73ed4f27554016defecccerion
1809edf7fc572e2decb93e9143961e8739c8fe18899dcerion   Hence in IBM's notation, BI=0 is CR7[SO], BI=1 is CR7[==], etc.
1810b51f0f4f33256638ed953156a2635aa739b232f1sewardj
1811b51f0f4f33256638ed953156a2635aa739b232f1sewardj   Indexing from BI to guest state:
1812b51f0f4f33256638ed953156a2635aa739b232f1sewardj
1813b51f0f4f33256638ed953156a2635aa739b232f1sewardj     let    n = BI / 4
1814b51f0f4f33256638ed953156a2635aa739b232f1sewardj          off = BI % 4
1815b51f0f4f33256638ed953156a2635aa739b232f1sewardj     this references CR n:
1816b51f0f4f33256638ed953156a2635aa739b232f1sewardj
1817edf7fc572e2decb93e9143961e8739c8fe18899dcerion        off==0   ->  guest_CRn_321 >> 3
1818edf7fc572e2decb93e9143961e8739c8fe18899dcerion        off==1   ->  guest_CRn_321 >> 2
1819edf7fc572e2decb93e9143961e8739c8fe18899dcerion        off==2   ->  guest_CRn_321 >> 1
1820b51f0f4f33256638ed953156a2635aa739b232f1sewardj        off==3   ->  guest_CRn_SO
1821b51f0f4f33256638ed953156a2635aa739b232f1sewardj
1822b51f0f4f33256638ed953156a2635aa739b232f1sewardj   Bear in mind the only significant bit in guest_CRn_SO is bit 0
1823edf7fc572e2decb93e9143961e8739c8fe18899dcerion   (normal notation) and in guest_CRn_321 the significant bits are
1824b51f0f4f33256638ed953156a2635aa739b232f1sewardj   3, 2 and 1 (normal notation).
1825b51f0f4f33256638ed953156a2635aa739b232f1sewardj*/
1826edf7fc572e2decb93e9143961e8739c8fe18899dcerion
1827edf7fc572e2decb93e9143961e8739c8fe18899dcerionstatic void putCR321 ( UInt cr, IRExpr* e )
1828edf7fc572e2decb93e9143961e8739c8fe18899dcerion{
1829edf7fc572e2decb93e9143961e8739c8fe18899dcerion   vassert(cr < 8);
1830dd40fdf58cc8a6fe9466c4f00bdfc9fe9bf00449sewardj   vassert(typeOfIRExpr(irsb->tyenv, e) == Ity_I8);
1831edf7fc572e2decb93e9143961e8739c8fe18899dcerion   stmt( IRStmt_Put(guestCR321offset(cr), e) );
1832edf7fc572e2decb93e9143961e8739c8fe18899dcerion}
1833edf7fc572e2decb93e9143961e8739c8fe18899dcerion
1834edf7fc572e2decb93e9143961e8739c8fe18899dcerionstatic void putCR0 ( UInt cr, IRExpr* e )
1835edf7fc572e2decb93e9143961e8739c8fe18899dcerion{
1836edf7fc572e2decb93e9143961e8739c8fe18899dcerion   vassert(cr < 8);
1837dd40fdf58cc8a6fe9466c4f00bdfc9fe9bf00449sewardj   vassert(typeOfIRExpr(irsb->tyenv, e) == Ity_I8);
1838edf7fc572e2decb93e9143961e8739c8fe18899dcerion   stmt( IRStmt_Put(guestCR0offset(cr), e) );
1839edf7fc572e2decb93e9143961e8739c8fe18899dcerion}
1840edf7fc572e2decb93e9143961e8739c8fe18899dcerion
1841edf7fc572e2decb93e9143961e8739c8fe18899dcerionstatic IRExpr* /* :: Ity_I8 */ getCR0 ( UInt cr )
1842edf7fc572e2decb93e9143961e8739c8fe18899dcerion{
1843edf7fc572e2decb93e9143961e8739c8fe18899dcerion   vassert(cr < 8);
1844edf7fc572e2decb93e9143961e8739c8fe18899dcerion   return IRExpr_Get(guestCR0offset(cr), Ity_I8);
1845edf7fc572e2decb93e9143961e8739c8fe18899dcerion}
1846edf7fc572e2decb93e9143961e8739c8fe18899dcerion
1847edf7fc572e2decb93e9143961e8739c8fe18899dcerionstatic IRExpr* /* :: Ity_I8 */ getCR321 ( UInt cr )
1848edf7fc572e2decb93e9143961e8739c8fe18899dcerion{
1849edf7fc572e2decb93e9143961e8739c8fe18899dcerion   vassert(cr < 8);
1850edf7fc572e2decb93e9143961e8739c8fe18899dcerion   return IRExpr_Get(guestCR321offset(cr), Ity_I8);
1851edf7fc572e2decb93e9143961e8739c8fe18899dcerion}
1852edf7fc572e2decb93e9143961e8739c8fe18899dcerion
1853b51f0f4f33256638ed953156a2635aa739b232f1sewardj/* Fetch the specified CR bit (as per IBM/hardware notation) and
1854b51f0f4f33256638ed953156a2635aa739b232f1sewardj   return it at the bottom of an I32; the top 31 bits are guaranteed
1855b51f0f4f33256638ed953156a2635aa739b232f1sewardj   to be zero. */
1856b51f0f4f33256638ed953156a2635aa739b232f1sewardjstatic IRExpr* /* :: Ity_I32 */ getCRbit ( UInt bi )
1857896a1373cfdbaa25f4ab73ed4f27554016defecccerion{
1858b51f0f4f33256638ed953156a2635aa739b232f1sewardj   UInt n   = bi / 4;
1859b51f0f4f33256638ed953156a2635aa739b232f1sewardj   UInt off = bi % 4;
1860b51f0f4f33256638ed953156a2635aa739b232f1sewardj   vassert(bi < 32);
1861b51f0f4f33256638ed953156a2635aa739b232f1sewardj   if (off == 3) {
1862b51f0f4f33256638ed953156a2635aa739b232f1sewardj      /* Fetch the SO bit for this CR field */
1863b51f0f4f33256638ed953156a2635aa739b232f1sewardj      /* Note: And32 is redundant paranoia iff guest state only has 0
1864b51f0f4f33256638ed953156a2635aa739b232f1sewardj         or 1 in that slot. */
1865b51f0f4f33256638ed953156a2635aa739b232f1sewardj      return binop(Iop_And32, unop(Iop_8Uto32, getCR0(n)), mkU32(1));
1866b51f0f4f33256638ed953156a2635aa739b232f1sewardj   } else {
1867b51f0f4f33256638ed953156a2635aa739b232f1sewardj      /* Fetch the <, > or == bit for this CR field */
1868b51f0f4f33256638ed953156a2635aa739b232f1sewardj      return binop( Iop_And32,
1869b51f0f4f33256638ed953156a2635aa739b232f1sewardj                    binop( Iop_Shr32,
1870b51f0f4f33256638ed953156a2635aa739b232f1sewardj                           unop(Iop_8Uto32, getCR321(n)),
1871c7cd2142ff0172bd3702d0607426a8014d8842e5sewardj                           mkU8(toUChar(3-off)) ),
1872b51f0f4f33256638ed953156a2635aa739b232f1sewardj                    mkU32(1) );
1873b51f0f4f33256638ed953156a2635aa739b232f1sewardj   }
1874b51f0f4f33256638ed953156a2635aa739b232f1sewardj}
1875b51f0f4f33256638ed953156a2635aa739b232f1sewardj
1876b51f0f4f33256638ed953156a2635aa739b232f1sewardj/* Dually, write the least significant bit of BIT to the specified CR
1877b51f0f4f33256638ed953156a2635aa739b232f1sewardj   bit.  Indexing as per getCRbit. */
1878b51f0f4f33256638ed953156a2635aa739b232f1sewardjstatic void putCRbit ( UInt bi, IRExpr* bit )
1879b51f0f4f33256638ed953156a2635aa739b232f1sewardj{
1880197bd17d3ba8ac5204cd5c9ba5fab571249eb791sewardj   UInt    n, off;
1881b51f0f4f33256638ed953156a2635aa739b232f1sewardj   IRExpr* safe;
1882dd40fdf58cc8a6fe9466c4f00bdfc9fe9bf00449sewardj   vassert(typeOfIRExpr(irsb->tyenv,bit) == Ity_I32);
1883b51f0f4f33256638ed953156a2635aa739b232f1sewardj   safe = binop(Iop_And32, bit, mkU32(1));
1884197bd17d3ba8ac5204cd5c9ba5fab571249eb791sewardj   n   = bi / 4;
1885197bd17d3ba8ac5204cd5c9ba5fab571249eb791sewardj   off = bi % 4;
1886b51f0f4f33256638ed953156a2635aa739b232f1sewardj   vassert(bi < 32);
1887b51f0f4f33256638ed953156a2635aa739b232f1sewardj   if (off == 3) {
1888b51f0f4f33256638ed953156a2635aa739b232f1sewardj      /* This is the SO bit for this CR field */
1889b51f0f4f33256638ed953156a2635aa739b232f1sewardj      putCR0(n, unop(Iop_32to8, safe));
1890b51f0f4f33256638ed953156a2635aa739b232f1sewardj   } else {
1891b51f0f4f33256638ed953156a2635aa739b232f1sewardj      off = 3 - off;
1892b51f0f4f33256638ed953156a2635aa739b232f1sewardj      vassert(off == 1 || off == 2 || off == 3);
1893b51f0f4f33256638ed953156a2635aa739b232f1sewardj      putCR321(
1894b51f0f4f33256638ed953156a2635aa739b232f1sewardj         n,
1895b51f0f4f33256638ed953156a2635aa739b232f1sewardj         unop( Iop_32to8,
1896b51f0f4f33256638ed953156a2635aa739b232f1sewardj               binop( Iop_Or32,
1897b51f0f4f33256638ed953156a2635aa739b232f1sewardj                      /* old value with field masked out */
1898b51f0f4f33256638ed953156a2635aa739b232f1sewardj                      binop(Iop_And32, unop(Iop_8Uto32, getCR321(n)),
1899b51f0f4f33256638ed953156a2635aa739b232f1sewardj                                       mkU32(~(1 << off))),
1900b51f0f4f33256638ed953156a2635aa739b232f1sewardj                      /* new value in the right place */
1901c7cd2142ff0172bd3702d0607426a8014d8842e5sewardj                      binop(Iop_Shl32, safe, mkU8(toUChar(off)))
1902b51f0f4f33256638ed953156a2635aa739b232f1sewardj               )
1903b51f0f4f33256638ed953156a2635aa739b232f1sewardj         )
1904b51f0f4f33256638ed953156a2635aa739b232f1sewardj      );
1905b51f0f4f33256638ed953156a2635aa739b232f1sewardj   }
1906b51f0f4f33256638ed953156a2635aa739b232f1sewardj}
1907896a1373cfdbaa25f4ab73ed4f27554016defecccerion
1908b51f0f4f33256638ed953156a2635aa739b232f1sewardj/* Fetch the specified CR bit (as per IBM/hardware notation) and
1909b51f0f4f33256638ed953156a2635aa739b232f1sewardj   return it somewhere in an I32; it does not matter where, but
1910b51f0f4f33256638ed953156a2635aa739b232f1sewardj   whichever bit it is, all other bits are guaranteed to be zero.  In
1911b51f0f4f33256638ed953156a2635aa739b232f1sewardj   other words, the I32-typed expression will be zero if the bit is
1912b51f0f4f33256638ed953156a2635aa739b232f1sewardj   zero and nonzero if the bit is 1.  Write into *where the index
1913b51f0f4f33256638ed953156a2635aa739b232f1sewardj   of where the bit will be. */
191491ad5368eb6354ad4fabc86f2b2e641736997a38cerion
19155b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerionstatic
19165b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerionIRExpr* /* :: Ity_I32 */ getCRbit_anywhere ( UInt bi, Int* where )
1917b51f0f4f33256638ed953156a2635aa739b232f1sewardj{
1918b51f0f4f33256638ed953156a2635aa739b232f1sewardj   UInt n   = bi / 4;
1919b51f0f4f33256638ed953156a2635aa739b232f1sewardj   UInt off = bi % 4;
1920b51f0f4f33256638ed953156a2635aa739b232f1sewardj   vassert(bi < 32);
1921b51f0f4f33256638ed953156a2635aa739b232f1sewardj   if (off == 3) {
1922b51f0f4f33256638ed953156a2635aa739b232f1sewardj      /* Fetch the SO bit for this CR field */
1923b51f0f4f33256638ed953156a2635aa739b232f1sewardj      /* Note: And32 is redundant paranoia iff guest state only has 0
1924b51f0f4f33256638ed953156a2635aa739b232f1sewardj         or 1 in that slot. */
1925b51f0f4f33256638ed953156a2635aa739b232f1sewardj      *where = 0;
1926b51f0f4f33256638ed953156a2635aa739b232f1sewardj      return binop(Iop_And32, unop(Iop_8Uto32, getCR0(n)), mkU32(1));
1927b51f0f4f33256638ed953156a2635aa739b232f1sewardj   } else {
1928b51f0f4f33256638ed953156a2635aa739b232f1sewardj      /* Fetch the <, > or == bit for this CR field */
1929b51f0f4f33256638ed953156a2635aa739b232f1sewardj      *where = 3-off;
1930b51f0f4f33256638ed953156a2635aa739b232f1sewardj      return binop( Iop_And32,
1931b51f0f4f33256638ed953156a2635aa739b232f1sewardj                    unop(Iop_8Uto32, getCR321(n)),
1932b51f0f4f33256638ed953156a2635aa739b232f1sewardj                    mkU32(1 << (3-off)) );
1933b51f0f4f33256638ed953156a2635aa739b232f1sewardj   }
193491ad5368eb6354ad4fabc86f2b2e641736997a38cerion}
193591ad5368eb6354ad4fabc86f2b2e641736997a38cerion
1936edf7fc572e2decb93e9143961e8739c8fe18899dcerion/* Set the CR0 flags following an arithmetic operation.
1937edf7fc572e2decb93e9143961e8739c8fe18899dcerion   (Condition Register CR0 Field Definition, PPC32 p60)
1938edf7fc572e2decb93e9143961e8739c8fe18899dcerion*/
1939edf7fc572e2decb93e9143961e8739c8fe18899dcerionstatic IRExpr* getXER_SO ( void );
1940edf7fc572e2decb93e9143961e8739c8fe18899dcerionstatic void set_CR0 ( IRExpr* result )
1941edf7fc572e2decb93e9143961e8739c8fe18899dcerion{
1942dd40fdf58cc8a6fe9466c4f00bdfc9fe9bf00449sewardj   vassert(typeOfIRExpr(irsb->tyenv,result) == Ity_I32 ||
1943dd40fdf58cc8a6fe9466c4f00bdfc9fe9bf00449sewardj           typeOfIRExpr(irsb->tyenv,result) == Ity_I64);
1944d953ebb9b04cbad6891676df597bf0c542b1ec89cerion   if (mode64) {
1945d953ebb9b04cbad6891676df597bf0c542b1ec89cerion      putCR321( 0, unop(Iop_64to8,
19462831b00c4950d6c2b061def05fd67528fe132ececerion                        binop(Iop_CmpORD64S, result, mkU64(0))) );
1947d953ebb9b04cbad6891676df597bf0c542b1ec89cerion   } else {
1948d953ebb9b04cbad6891676df597bf0c542b1ec89cerion      putCR321( 0, unop(Iop_32to8,
1949d953ebb9b04cbad6891676df597bf0c542b1ec89cerion                        binop(Iop_CmpORD32S, result, mkU32(0))) );
1950d953ebb9b04cbad6891676df597bf0c542b1ec89cerion   }
1951edf7fc572e2decb93e9143961e8739c8fe18899dcerion   putCR0( 0, getXER_SO() );
1952edf7fc572e2decb93e9143961e8739c8fe18899dcerion}
1953edf7fc572e2decb93e9143961e8739c8fe18899dcerion
1954edf7fc572e2decb93e9143961e8739c8fe18899dcerion
19554aa412af1d8166cc11f39a6e721df49431d23618sewardj/* Set the CR6 flags following an AltiVec compare operation.
19564aa412af1d8166cc11f39a6e721df49431d23618sewardj * NOTE: This also works for VSX single-precision compares.
19574aa412af1d8166cc11f39a6e721df49431d23618sewardj * */
1958edf7fc572e2decb93e9143961e8739c8fe18899dcerionstatic void set_AV_CR6 ( IRExpr* result, Bool test_all_ones )
1959edf7fc572e2decb93e9143961e8739c8fe18899dcerion{
1960edf7fc572e2decb93e9143961e8739c8fe18899dcerion   /* CR6[0:3] = {all_ones, 0, all_zeros, 0}
1961edf7fc572e2decb93e9143961e8739c8fe18899dcerion      all_ones  = (v[0] && v[1] && v[2] && v[3])
1962edf7fc572e2decb93e9143961e8739c8fe18899dcerion      all_zeros = ~(v[0] || v[1] || v[2] || v[3])
1963edf7fc572e2decb93e9143961e8739c8fe18899dcerion   */
1964edf7fc572e2decb93e9143961e8739c8fe18899dcerion   IRTemp v0 = newTemp(Ity_V128);
1965edf7fc572e2decb93e9143961e8739c8fe18899dcerion   IRTemp v1 = newTemp(Ity_V128);
1966edf7fc572e2decb93e9143961e8739c8fe18899dcerion   IRTemp v2 = newTemp(Ity_V128);
1967edf7fc572e2decb93e9143961e8739c8fe18899dcerion   IRTemp v3 = newTemp(Ity_V128);
1968edf7fc572e2decb93e9143961e8739c8fe18899dcerion   IRTemp rOnes  = newTemp(Ity_I8);
1969edf7fc572e2decb93e9143961e8739c8fe18899dcerion   IRTemp rZeros = newTemp(Ity_I8);
1970edf7fc572e2decb93e9143961e8739c8fe18899dcerion
1971dd40fdf58cc8a6fe9466c4f00bdfc9fe9bf00449sewardj   vassert(typeOfIRExpr(irsb->tyenv,result) == Ity_V128);
1972edf7fc572e2decb93e9143961e8739c8fe18899dcerion
1973edf7fc572e2decb93e9143961e8739c8fe18899dcerion   assign( v0, result );
1974edf7fc572e2decb93e9143961e8739c8fe18899dcerion   assign( v1, binop(Iop_ShrV128, result, mkU8(32)) );
1975edf7fc572e2decb93e9143961e8739c8fe18899dcerion   assign( v2, binop(Iop_ShrV128, result, mkU8(64)) );
1976edf7fc572e2decb93e9143961e8739c8fe18899dcerion   assign( v3, binop(Iop_ShrV128, result, mkU8(96)) );
1977edf7fc572e2decb93e9143961e8739c8fe18899dcerion
1978edf7fc572e2decb93e9143961e8739c8fe18899dcerion   assign( rZeros, unop(Iop_1Uto8,
1979edf7fc572e2decb93e9143961e8739c8fe18899dcerion       binop(Iop_CmpEQ32, mkU32(0xFFFFFFFF),
1980edf7fc572e2decb93e9143961e8739c8fe18899dcerion             unop(Iop_Not32,
1981edf7fc572e2decb93e9143961e8739c8fe18899dcerion                  unop(Iop_V128to32,
1982edf7fc572e2decb93e9143961e8739c8fe18899dcerion                       binop(Iop_OrV128,
1983edf7fc572e2decb93e9143961e8739c8fe18899dcerion                             binop(Iop_OrV128, mkexpr(v0), mkexpr(v1)),
1984edf7fc572e2decb93e9143961e8739c8fe18899dcerion                             binop(Iop_OrV128, mkexpr(v2), mkexpr(v3))))
1985edf7fc572e2decb93e9143961e8739c8fe18899dcerion                  ))) );
1986edf7fc572e2decb93e9143961e8739c8fe18899dcerion
1987edf7fc572e2decb93e9143961e8739c8fe18899dcerion   if (test_all_ones) {
1988edf7fc572e2decb93e9143961e8739c8fe18899dcerion      assign( rOnes, unop(Iop_1Uto8,
1989edf7fc572e2decb93e9143961e8739c8fe18899dcerion         binop(Iop_CmpEQ32, mkU32(0xFFFFFFFF),
1990edf7fc572e2decb93e9143961e8739c8fe18899dcerion               unop(Iop_V128to32,
1991edf7fc572e2decb93e9143961e8739c8fe18899dcerion                    binop(Iop_AndV128,
1992edf7fc572e2decb93e9143961e8739c8fe18899dcerion                          binop(Iop_AndV128, mkexpr(v0), mkexpr(v1)),
19935b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion                          binop(Iop_AndV128, mkexpr(v2), mkexpr(v3)))
19945b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion                    ))) );
1995edf7fc572e2decb93e9143961e8739c8fe18899dcerion      putCR321( 6, binop(Iop_Or8,
1996edf7fc572e2decb93e9143961e8739c8fe18899dcerion                         binop(Iop_Shl8, mkexpr(rOnes),  mkU8(3)),
1997edf7fc572e2decb93e9143961e8739c8fe18899dcerion                         binop(Iop_Shl8, mkexpr(rZeros), mkU8(1))) );
1998edf7fc572e2decb93e9143961e8739c8fe18899dcerion   } else {
1999edf7fc572e2decb93e9143961e8739c8fe18899dcerion      putCR321( 6, binop(Iop_Shl8, mkexpr(rZeros), mkU8(1)) );
2000edf7fc572e2decb93e9143961e8739c8fe18899dcerion   }
2001edf7fc572e2decb93e9143961e8739c8fe18899dcerion   putCR0( 6, mkU8(0) );
2002edf7fc572e2decb93e9143961e8739c8fe18899dcerion}
2003edf7fc572e2decb93e9143961e8739c8fe18899dcerion
2004edf7fc572e2decb93e9143961e8739c8fe18899dcerion
2005edf7fc572e2decb93e9143961e8739c8fe18899dcerion
2006edf7fc572e2decb93e9143961e8739c8fe18899dcerion/*------------------------------------------------------------*/
2007edf7fc572e2decb93e9143961e8739c8fe18899dcerion/*--- Helpers for XER flags.                               ---*/
2008edf7fc572e2decb93e9143961e8739c8fe18899dcerion/*------------------------------------------------------------*/
2009edf7fc572e2decb93e9143961e8739c8fe18899dcerion
2010edf7fc572e2decb93e9143961e8739c8fe18899dcerionstatic void putXER_SO ( IRExpr* e )
2011edf7fc572e2decb93e9143961e8739c8fe18899dcerion{
2012633274098fafebdc79cf1c8a1ef7f9a9914669f1sewardj   IRExpr* so;
2013dd40fdf58cc8a6fe9466c4f00bdfc9fe9bf00449sewardj   vassert(typeOfIRExpr(irsb->tyenv, e) == Ity_I8);
2014633274098fafebdc79cf1c8a1ef7f9a9914669f1sewardj   so = binop(Iop_And8, e, mkU8(1));
20155b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion   stmt( IRStmt_Put( OFFB_XER_SO, so ) );
2016edf7fc572e2decb93e9143961e8739c8fe18899dcerion}
2017edf7fc572e2decb93e9143961e8739c8fe18899dcerion
2018edf7fc572e2decb93e9143961e8739c8fe18899dcerionstatic void putXER_OV ( IRExpr* e )
2019edf7fc572e2decb93e9143961e8739c8fe18899dcerion{
2020633274098fafebdc79cf1c8a1ef7f9a9914669f1sewardj   IRExpr* ov;
2021dd40fdf58cc8a6fe9466c4f00bdfc9fe9bf00449sewardj   vassert(typeOfIRExpr(irsb->tyenv, e) == Ity_I8);
2022633274098fafebdc79cf1c8a1ef7f9a9914669f1sewardj   ov = binop(Iop_And8, e, mkU8(1));
20235b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion   stmt( IRStmt_Put( OFFB_XER_OV, ov ) );
2024edf7fc572e2decb93e9143961e8739c8fe18899dcerion}
2025b51f0f4f33256638ed953156a2635aa739b232f1sewardj
2026edf7fc572e2decb93e9143961e8739c8fe18899dcerionstatic void putXER_CA ( IRExpr* e )
2027edf7fc572e2decb93e9143961e8739c8fe18899dcerion{
2028633274098fafebdc79cf1c8a1ef7f9a9914669f1sewardj   IRExpr* ca;
2029dd40fdf58cc8a6fe9466c4f00bdfc9fe9bf00449sewardj   vassert(typeOfIRExpr(irsb->tyenv, e) == Ity_I8);
2030633274098fafebdc79cf1c8a1ef7f9a9914669f1sewardj   ca = binop(Iop_And8, e, mkU8(1));
20315b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion   stmt( IRStmt_Put( OFFB_XER_CA, ca ) );
2032edf7fc572e2decb93e9143961e8739c8fe18899dcerion}
2033b51f0f4f33256638ed953156a2635aa739b232f1sewardj
2034edf7fc572e2decb93e9143961e8739c8fe18899dcerionstatic void putXER_BC ( IRExpr* e )
203591ad5368eb6354ad4fabc86f2b2e641736997a38cerion{
2036633274098fafebdc79cf1c8a1ef7f9a9914669f1sewardj   IRExpr* bc;
2037dd40fdf58cc8a6fe9466c4f00bdfc9fe9bf00449sewardj   vassert(typeOfIRExpr(irsb->tyenv, e) == Ity_I8);
2038633274098fafebdc79cf1c8a1ef7f9a9914669f1sewardj   bc = binop(Iop_And8, e, mkU8(0x7F));
20395b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion   stmt( IRStmt_Put( OFFB_XER_BC, bc ) );
2040b51f0f4f33256638ed953156a2635aa739b232f1sewardj}
204191ad5368eb6354ad4fabc86f2b2e641736997a38cerion
2042edf7fc572e2decb93e9143961e8739c8fe18899dcerionstatic IRExpr* /* :: Ity_I8 */ getXER_SO ( void )
2043b51f0f4f33256638ed953156a2635aa739b232f1sewardj{
20445b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion   return IRExpr_Get( OFFB_XER_SO, Ity_I8 );
2045edf7fc572e2decb93e9143961e8739c8fe18899dcerion}
2046edf7fc572e2decb93e9143961e8739c8fe18899dcerion
2047edf7fc572e2decb93e9143961e8739c8fe18899dcerionstatic IRExpr* /* :: Ity_I32 */ getXER_SO32 ( void )
2048edf7fc572e2decb93e9143961e8739c8fe18899dcerion{
2049edf7fc572e2decb93e9143961e8739c8fe18899dcerion   return binop( Iop_And32, unop(Iop_8Uto32, getXER_SO()), mkU32(1) );
205091ad5368eb6354ad4fabc86f2b2e641736997a38cerion}
205191ad5368eb6354ad4fabc86f2b2e641736997a38cerion
2052edf7fc572e2decb93e9143961e8739c8fe18899dcerionstatic IRExpr* /* :: Ity_I8 */ getXER_OV ( void )
2053edf7fc572e2decb93e9143961e8739c8fe18899dcerion{
20545b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion   return IRExpr_Get( OFFB_XER_OV, Ity_I8 );
2055edf7fc572e2decb93e9143961e8739c8fe18899dcerion}
2056b51f0f4f33256638ed953156a2635aa739b232f1sewardj
2057edf7fc572e2decb93e9143961e8739c8fe18899dcerionstatic IRExpr* /* :: Ity_I32 */ getXER_OV32 ( void )
2058896a1373cfdbaa25f4ab73ed4f27554016defecccerion{
2059edf7fc572e2decb93e9143961e8739c8fe18899dcerion   return binop( Iop_And32, unop(Iop_8Uto32, getXER_OV()), mkU32(1) );
2060edf7fc572e2decb93e9143961e8739c8fe18899dcerion}
2061edf7fc572e2decb93e9143961e8739c8fe18899dcerion
2062edf7fc572e2decb93e9143961e8739c8fe18899dcerionstatic IRExpr* /* :: Ity_I32 */ getXER_CA32 ( void )
2063edf7fc572e2decb93e9143961e8739c8fe18899dcerion{
20645b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion   IRExpr* ca = IRExpr_Get( OFFB_XER_CA, Ity_I8 );
2065d953ebb9b04cbad6891676df597bf0c542b1ec89cerion   return binop( Iop_And32, unop(Iop_8Uto32, ca ), mkU32(1) );
2066edf7fc572e2decb93e9143961e8739c8fe18899dcerion}
2067edf7fc572e2decb93e9143961e8739c8fe18899dcerion
2068edf7fc572e2decb93e9143961e8739c8fe18899dcerionstatic IRExpr* /* :: Ity_I8 */ getXER_BC ( void )
2069edf7fc572e2decb93e9143961e8739c8fe18899dcerion{
20705b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion   return IRExpr_Get( OFFB_XER_BC, Ity_I8 );
2071edf7fc572e2decb93e9143961e8739c8fe18899dcerion}
2072edf7fc572e2decb93e9143961e8739c8fe18899dcerion
2073edf7fc572e2decb93e9143961e8739c8fe18899dcerionstatic IRExpr* /* :: Ity_I32 */ getXER_BC32 ( void )
2074edf7fc572e2decb93e9143961e8739c8fe18899dcerion{
20755b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion   IRExpr* bc = IRExpr_Get( OFFB_XER_BC, Ity_I8 );
2076d953ebb9b04cbad6891676df597bf0c542b1ec89cerion   return binop( Iop_And32, unop(Iop_8Uto32, bc), mkU32(0x7F) );
207791ad5368eb6354ad4fabc86f2b2e641736997a38cerion}
2078896a1373cfdbaa25f4ab73ed4f27554016defecccerion
207920ef5472eac767474c93b7835364a23f24c0ec5dsewardj
208020ef5472eac767474c93b7835364a23f24c0ec5dsewardj/* RES is the result of doing OP on ARGL and ARGR.  Set %XER.OV and
208120ef5472eac767474c93b7835364a23f24c0ec5dsewardj   %XER.SO accordingly. */
208220ef5472eac767474c93b7835364a23f24c0ec5dsewardj
2083d953ebb9b04cbad6891676df597bf0c542b1ec89cerionstatic void set_XER_OV_32( UInt op, IRExpr* res,
2084d953ebb9b04cbad6891676df597bf0c542b1ec89cerion                           IRExpr* argL, IRExpr* argR )
208520ef5472eac767474c93b7835364a23f24c0ec5dsewardj{
208620ef5472eac767474c93b7835364a23f24c0ec5dsewardj   IRTemp  t64;
208720ef5472eac767474c93b7835364a23f24c0ec5dsewardj   IRExpr* xer_ov;
20885b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion   vassert(op < PPCG_FLAG_OP_NUMBER);
2089dd40fdf58cc8a6fe9466c4f00bdfc9fe9bf00449sewardj   vassert(typeOfIRExpr(irsb->tyenv,res)  == Ity_I32);
2090dd40fdf58cc8a6fe9466c4f00bdfc9fe9bf00449sewardj   vassert(typeOfIRExpr(irsb->tyenv,argL) == Ity_I32);
2091dd40fdf58cc8a6fe9466c4f00bdfc9fe9bf00449sewardj   vassert(typeOfIRExpr(irsb->tyenv,argR) == Ity_I32);
209220ef5472eac767474c93b7835364a23f24c0ec5dsewardj
209320ef5472eac767474c93b7835364a23f24c0ec5dsewardj#  define INT32_MIN 0x80000000
209420ef5472eac767474c93b7835364a23f24c0ec5dsewardj
209520ef5472eac767474c93b7835364a23f24c0ec5dsewardj#  define XOR2(_aa,_bb) \
209620ef5472eac767474c93b7835364a23f24c0ec5dsewardj      binop(Iop_Xor32,(_aa),(_bb))
209720ef5472eac767474c93b7835364a23f24c0ec5dsewardj
209820ef5472eac767474c93b7835364a23f24c0ec5dsewardj#  define XOR3(_cc,_dd,_ee) \
209920ef5472eac767474c93b7835364a23f24c0ec5dsewardj      binop(Iop_Xor32,binop(Iop_Xor32,(_cc),(_dd)),(_ee))
210020ef5472eac767474c93b7835364a23f24c0ec5dsewardj
210120ef5472eac767474c93b7835364a23f24c0ec5dsewardj#  define AND3(_ff,_gg,_hh) \
210220ef5472eac767474c93b7835364a23f24c0ec5dsewardj      binop(Iop_And32,binop(Iop_And32,(_ff),(_gg)),(_hh))
210320ef5472eac767474c93b7835364a23f24c0ec5dsewardj
210420ef5472eac767474c93b7835364a23f24c0ec5dsewardj#define NOT(_jj) \
210520ef5472eac767474c93b7835364a23f24c0ec5dsewardj      unop(Iop_Not32, (_jj))
210620ef5472eac767474c93b7835364a23f24c0ec5dsewardj
210720ef5472eac767474c93b7835364a23f24c0ec5dsewardj   switch (op) {
21085b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion   case /* 0  */ PPCG_FLAG_OP_ADD:
21095b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion   case /* 1  */ PPCG_FLAG_OP_ADDE:
2110d953ebb9b04cbad6891676df597bf0c542b1ec89cerion      /* (argL^argR^-1) & (argL^res) & (1<<31)  ?1:0 */
2111d953ebb9b04cbad6891676df597bf0c542b1ec89cerion      // i.e. ((both_same_sign) & (sign_changed) & (sign_mask))
2112d953ebb9b04cbad6891676df597bf0c542b1ec89cerion      xer_ov
2113d953ebb9b04cbad6891676df597bf0c542b1ec89cerion         = AND3( XOR3(argL,argR,mkU32(-1)),
2114d953ebb9b04cbad6891676df597bf0c542b1ec89cerion                 XOR2(argL,res),
2115d953ebb9b04cbad6891676df597bf0c542b1ec89cerion                 mkU32(INT32_MIN) );
2116d953ebb9b04cbad6891676df597bf0c542b1ec89cerion      /* xer_ov can only be 0 or 1<<31 */
2117d953ebb9b04cbad6891676df597bf0c542b1ec89cerion      xer_ov
2118d953ebb9b04cbad6891676df597bf0c542b1ec89cerion         = binop(Iop_Shr32, xer_ov, mkU8(31) );
2119d953ebb9b04cbad6891676df597bf0c542b1ec89cerion      break;
2120d953ebb9b04cbad6891676df597bf0c542b1ec89cerion
21215b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion   case /* 2  */ PPCG_FLAG_OP_DIVW:
2122d953ebb9b04cbad6891676df597bf0c542b1ec89cerion      /* (argL == INT32_MIN && argR == -1) || argR == 0 */
2123d953ebb9b04cbad6891676df597bf0c542b1ec89cerion      xer_ov
2124d953ebb9b04cbad6891676df597bf0c542b1ec89cerion         = mkOR1(
2125d953ebb9b04cbad6891676df597bf0c542b1ec89cerion              mkAND1(
2126d953ebb9b04cbad6891676df597bf0c542b1ec89cerion                 binop(Iop_CmpEQ32, argL, mkU32(INT32_MIN)),
2127d953ebb9b04cbad6891676df597bf0c542b1ec89cerion                 binop(Iop_CmpEQ32, argR, mkU32(-1))
2128d953ebb9b04cbad6891676df597bf0c542b1ec89cerion              ),
2129d953ebb9b04cbad6891676df597bf0c542b1ec89cerion              binop(Iop_CmpEQ32, argR, mkU32(0) )
2130d953ebb9b04cbad6891676df597bf0c542b1ec89cerion           );
2131d953ebb9b04cbad6891676df597bf0c542b1ec89cerion      xer_ov
2132d953ebb9b04cbad6891676df597bf0c542b1ec89cerion         = unop(Iop_1Uto32, xer_ov);
2133d953ebb9b04cbad6891676df597bf0c542b1ec89cerion      break;
2134d953ebb9b04cbad6891676df597bf0c542b1ec89cerion
21355b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion   case /* 3  */ PPCG_FLAG_OP_DIVWU:
2136d953ebb9b04cbad6891676df597bf0c542b1ec89cerion      /* argR == 0 */
2137d953ebb9b04cbad6891676df597bf0c542b1ec89cerion      xer_ov
2138d953ebb9b04cbad6891676df597bf0c542b1ec89cerion         = unop(Iop_1Uto32, binop(Iop_CmpEQ32, argR, mkU32(0)));
2139d953ebb9b04cbad6891676df597bf0c542b1ec89cerion      break;
2140d953ebb9b04cbad6891676df597bf0c542b1ec89cerion
21415b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion   case /* 4  */ PPCG_FLAG_OP_MULLW:
2142d953ebb9b04cbad6891676df597bf0c542b1ec89cerion      /* OV true if result can't be represented in 32 bits
2143d953ebb9b04cbad6891676df597bf0c542b1ec89cerion         i.e sHi != sign extension of sLo */
2144d953ebb9b04cbad6891676df597bf0c542b1ec89cerion      t64 = newTemp(Ity_I64);
2145d953ebb9b04cbad6891676df597bf0c542b1ec89cerion      assign( t64, binop(Iop_MullS32, argL, argR) );
2146d953ebb9b04cbad6891676df597bf0c542b1ec89cerion      xer_ov
2147d953ebb9b04cbad6891676df597bf0c542b1ec89cerion         = binop( Iop_CmpNE32,
2148d953ebb9b04cbad6891676df597bf0c542b1ec89cerion                  unop(Iop_64HIto32, mkexpr(t64)),
2149d953ebb9b04cbad6891676df597bf0c542b1ec89cerion                  binop( Iop_Sar32,
2150d953ebb9b04cbad6891676df597bf0c542b1ec89cerion                         unop(Iop_64to32, mkexpr(t64)),
2151d953ebb9b04cbad6891676df597bf0c542b1ec89cerion                         mkU8(31))
2152d953ebb9b04cbad6891676df597bf0c542b1ec89cerion                  );
2153d953ebb9b04cbad6891676df597bf0c542b1ec89cerion      xer_ov
2154d953ebb9b04cbad6891676df597bf0c542b1ec89cerion         = unop(Iop_1Uto32, xer_ov);
2155d953ebb9b04cbad6891676df597bf0c542b1ec89cerion      break;
2156d953ebb9b04cbad6891676df597bf0c542b1ec89cerion
21575b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion   case /* 5  */ PPCG_FLAG_OP_NEG:
2158d953ebb9b04cbad6891676df597bf0c542b1ec89cerion      /* argL == INT32_MIN */
2159d953ebb9b04cbad6891676df597bf0c542b1ec89cerion      xer_ov
2160d953ebb9b04cbad6891676df597bf0c542b1ec89cerion         = unop( Iop_1Uto32,
2161d953ebb9b04cbad6891676df597bf0c542b1ec89cerion                 binop(Iop_CmpEQ32, argL, mkU32(INT32_MIN)) );
2162d953ebb9b04cbad6891676df597bf0c542b1ec89cerion      break;
2163d953ebb9b04cbad6891676df597bf0c542b1ec89cerion
21645b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion   case /* 6  */ PPCG_FLAG_OP_SUBF:
21655b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion   case /* 7  */ PPCG_FLAG_OP_SUBFC:
21665b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion   case /* 8  */ PPCG_FLAG_OP_SUBFE:
2167d953ebb9b04cbad6891676df597bf0c542b1ec89cerion      /* ((~argL)^argR^-1) & ((~argL)^res) & (1<<31) ?1:0; */
2168d953ebb9b04cbad6891676df597bf0c542b1ec89cerion      xer_ov
2169d953ebb9b04cbad6891676df597bf0c542b1ec89cerion         = AND3( XOR3(NOT(argL),argR,mkU32(-1)),
2170d953ebb9b04cbad6891676df597bf0c542b1ec89cerion                 XOR2(NOT(argL),res),
2171d953ebb9b04cbad6891676df597bf0c542b1ec89cerion                 mkU32(INT32_MIN) );
2172d953ebb9b04cbad6891676df597bf0c542b1ec89cerion      /* xer_ov can only be 0 or 1<<31 */
2173d953ebb9b04cbad6891676df597bf0c542b1ec89cerion      xer_ov
2174d953ebb9b04cbad6891676df597bf0c542b1ec89cerion         = binop(Iop_Shr32, xer_ov, mkU8(31) );
2175d953ebb9b04cbad6891676df597bf0c542b1ec89cerion      break;
2176d953ebb9b04cbad6891676df597bf0c542b1ec89cerion
21774aa412af1d8166cc11f39a6e721df49431d23618sewardj   case PPCG_FLAG_OP_DIVWEU:
21784aa412af1d8166cc11f39a6e721df49431d23618sewardj      xer_ov
21794aa412af1d8166cc11f39a6e721df49431d23618sewardj               = binop( Iop_Or32,
21804aa412af1d8166cc11f39a6e721df49431d23618sewardj                        unop( Iop_1Uto32, binop( Iop_CmpEQ32, argR, mkU32( 0 ) ) ),
21814aa412af1d8166cc11f39a6e721df49431d23618sewardj                        unop( Iop_1Uto32, binop( Iop_CmpLT32U, argR, argL ) ) );
21824aa412af1d8166cc11f39a6e721df49431d23618sewardj      break;
21834aa412af1d8166cc11f39a6e721df49431d23618sewardj
2184e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj   case PPCG_FLAG_OP_DIVWE:
2185e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj
2186e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj      /* If argR == 0 of if the result cannot fit in the 32-bit destination register,
2187e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj       * then OV <- 1.   If dest reg is 0 AND both dividend and divisor are non-zero,
2188e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj       * an overflow is implied.
2189e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj       */
2190e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj      xer_ov = binop( Iop_Or32,
2191e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj                      unop( Iop_1Uto32, binop( Iop_CmpEQ32, argR, mkU32( 0 ) ) ),
2192e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj                      unop( Iop_1Uto32, mkAND1( binop( Iop_CmpEQ32, res, mkU32( 0 ) ),
2193e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj                              mkAND1( binop( Iop_CmpNE32, argL, mkU32( 0 ) ),
2194e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj                                      binop( Iop_CmpNE32, argR, mkU32( 0 ) ) ) ) ) );
2195e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj      break;
2196e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj
2197e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj
2198e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj
2199d953ebb9b04cbad6891676df597bf0c542b1ec89cerion   default:
2200d953ebb9b04cbad6891676df597bf0c542b1ec89cerion      vex_printf("set_XER_OV: op = %u\n", op);
22015b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion      vpanic("set_XER_OV(ppc)");
2202d953ebb9b04cbad6891676df597bf0c542b1ec89cerion   }
2203d953ebb9b04cbad6891676df597bf0c542b1ec89cerion
2204d953ebb9b04cbad6891676df597bf0c542b1ec89cerion   /* xer_ov MUST denote either 0 or 1, no other value allowed */
2205d953ebb9b04cbad6891676df597bf0c542b1ec89cerion   putXER_OV( unop(Iop_32to8, xer_ov) );
220620ef5472eac767474c93b7835364a23f24c0ec5dsewardj
2207d953ebb9b04cbad6891676df597bf0c542b1ec89cerion   /* Update the summary overflow */
2208d953ebb9b04cbad6891676df597bf0c542b1ec89cerion   putXER_SO( binop(Iop_Or8, getXER_SO(), getXER_OV()) );
220920ef5472eac767474c93b7835364a23f24c0ec5dsewardj
2210d953ebb9b04cbad6891676df597bf0c542b1ec89cerion#  undef INT32_MIN
2211d953ebb9b04cbad6891676df597bf0c542b1ec89cerion#  undef AND3
2212d953ebb9b04cbad6891676df597bf0c542b1ec89cerion#  undef XOR3
2213d953ebb9b04cbad6891676df597bf0c542b1ec89cerion#  undef XOR2
2214d953ebb9b04cbad6891676df597bf0c542b1ec89cerion#  undef NOT
2215d953ebb9b04cbad6891676df597bf0c542b1ec89cerion}
221620ef5472eac767474c93b7835364a23f24c0ec5dsewardj
2217d953ebb9b04cbad6891676df597bf0c542b1ec89cerionstatic void set_XER_OV_64( UInt op, IRExpr* res,
2218d953ebb9b04cbad6891676df597bf0c542b1ec89cerion                           IRExpr* argL, IRExpr* argR )
2219d953ebb9b04cbad6891676df597bf0c542b1ec89cerion{
2220d953ebb9b04cbad6891676df597bf0c542b1ec89cerion   IRExpr* xer_ov;
22215b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion   vassert(op < PPCG_FLAG_OP_NUMBER);
2222dd40fdf58cc8a6fe9466c4f00bdfc9fe9bf00449sewardj   vassert(typeOfIRExpr(irsb->tyenv,res)  == Ity_I64);
2223dd40fdf58cc8a6fe9466c4f00bdfc9fe9bf00449sewardj   vassert(typeOfIRExpr(irsb->tyenv,argL) == Ity_I64);
2224dd40fdf58cc8a6fe9466c4f00bdfc9fe9bf00449sewardj   vassert(typeOfIRExpr(irsb->tyenv,argR) == Ity_I64);
222520ef5472eac767474c93b7835364a23f24c0ec5dsewardj
22262831b00c4950d6c2b061def05fd67528fe132ececerion#  define INT64_MIN 0x8000000000000000ULL
222720ef5472eac767474c93b7835364a23f24c0ec5dsewardj
2228d953ebb9b04cbad6891676df597bf0c542b1ec89cerion#  define XOR2(_aa,_bb) \
2229d953ebb9b04cbad6891676df597bf0c542b1ec89cerion      binop(Iop_Xor64,(_aa),(_bb))
223020ef5472eac767474c93b7835364a23f24c0ec5dsewardj
2231d953ebb9b04cbad6891676df597bf0c542b1ec89cerion#  define XOR3(_cc,_dd,_ee) \
2232d953ebb9b04cbad6891676df597bf0c542b1ec89cerion      binop(Iop_Xor64,binop(Iop_Xor64,(_cc),(_dd)),(_ee))
2233d953ebb9b04cbad6891676df597bf0c542b1ec89cerion
2234d953ebb9b04cbad6891676df597bf0c542b1ec89cerion#  define AND3(_ff,_gg,_hh) \
2235d953ebb9b04cbad6891676df597bf0c542b1ec89cerion      binop(Iop_And64,binop(Iop_And64,(_ff),(_gg)),(_hh))
2236d953ebb9b04cbad6891676df597bf0c542b1ec89cerion
2237d953ebb9b04cbad6891676df597bf0c542b1ec89cerion#define NOT(_jj) \
2238d953ebb9b04cbad6891676df597bf0c542b1ec89cerion      unop(Iop_Not64, (_jj))
223920ef5472eac767474c93b7835364a23f24c0ec5dsewardj
2240d953ebb9b04cbad6891676df597bf0c542b1ec89cerion   switch (op) {
22415b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion   case /* 0  */ PPCG_FLAG_OP_ADD:
22425b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion   case /* 1  */ PPCG_FLAG_OP_ADDE:
2243d953ebb9b04cbad6891676df597bf0c542b1ec89cerion      /* (argL^argR^-1) & (argL^res) & (1<<63)  ? 1:0 */
2244d953ebb9b04cbad6891676df597bf0c542b1ec89cerion      // i.e. ((both_same_sign) & (sign_changed) & (sign_mask))
2245d953ebb9b04cbad6891676df597bf0c542b1ec89cerion      xer_ov
2246d953ebb9b04cbad6891676df597bf0c542b1ec89cerion         = AND3( XOR3(argL,argR,mkU64(-1)),
2247d953ebb9b04cbad6891676df597bf0c542b1ec89cerion                 XOR2(argL,res),
2248d953ebb9b04cbad6891676df597bf0c542b1ec89cerion                 mkU64(INT64_MIN) );
2249d953ebb9b04cbad6891676df597bf0c542b1ec89cerion      /* xer_ov can only be 0 or 1<<63 */
2250d953ebb9b04cbad6891676df597bf0c542b1ec89cerion      xer_ov
2251d953ebb9b04cbad6891676df597bf0c542b1ec89cerion         = unop(Iop_64to1, binop(Iop_Shr64, xer_ov, mkU8(63)));
2252d953ebb9b04cbad6891676df597bf0c542b1ec89cerion      break;
2253d953ebb9b04cbad6891676df597bf0c542b1ec89cerion
22545b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion   case /* 2  */ PPCG_FLAG_OP_DIVW:
2255d953ebb9b04cbad6891676df597bf0c542b1ec89cerion      /* (argL == INT64_MIN && argR == -1) || argR == 0 */
2256d953ebb9b04cbad6891676df597bf0c542b1ec89cerion      xer_ov
2257d953ebb9b04cbad6891676df597bf0c542b1ec89cerion         = mkOR1(
2258d953ebb9b04cbad6891676df597bf0c542b1ec89cerion              mkAND1(
2259d953ebb9b04cbad6891676df597bf0c542b1ec89cerion                 binop(Iop_CmpEQ64, argL, mkU64(INT64_MIN)),
2260d953ebb9b04cbad6891676df597bf0c542b1ec89cerion                 binop(Iop_CmpEQ64, argR, mkU64(-1))
2261d953ebb9b04cbad6891676df597bf0c542b1ec89cerion              ),
2262d953ebb9b04cbad6891676df597bf0c542b1ec89cerion              binop(Iop_CmpEQ64, argR, mkU64(0) )
2263d953ebb9b04cbad6891676df597bf0c542b1ec89cerion           );
2264d953ebb9b04cbad6891676df597bf0c542b1ec89cerion      break;
2265d953ebb9b04cbad6891676df597bf0c542b1ec89cerion
22665b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion   case /* 3  */ PPCG_FLAG_OP_DIVWU:
2267d953ebb9b04cbad6891676df597bf0c542b1ec89cerion      /* argR == 0 */
2268d953ebb9b04cbad6891676df597bf0c542b1ec89cerion      xer_ov
2269d953ebb9b04cbad6891676df597bf0c542b1ec89cerion         = binop(Iop_CmpEQ64, argR, mkU64(0));
2270d953ebb9b04cbad6891676df597bf0c542b1ec89cerion      break;
2271d953ebb9b04cbad6891676df597bf0c542b1ec89cerion
22725b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion   case /* 4  */ PPCG_FLAG_OP_MULLW: {
2273d953ebb9b04cbad6891676df597bf0c542b1ec89cerion      /* OV true if result can't be represented in 64 bits
2274d953ebb9b04cbad6891676df597bf0c542b1ec89cerion         i.e sHi != sign extension of sLo */
2275d953ebb9b04cbad6891676df597bf0c542b1ec89cerion      xer_ov
2276bb01b7cbfd84c27dd213f67a144ea5a99af36961cerion         = binop( Iop_CmpNE32,
2277bb01b7cbfd84c27dd213f67a144ea5a99af36961cerion                  unop(Iop_64HIto32, res),
2278bb01b7cbfd84c27dd213f67a144ea5a99af36961cerion                  binop( Iop_Sar32,
2279bb01b7cbfd84c27dd213f67a144ea5a99af36961cerion                         unop(Iop_64to32, res),
2280bb01b7cbfd84c27dd213f67a144ea5a99af36961cerion                         mkU8(31))
2281bb01b7cbfd84c27dd213f67a144ea5a99af36961cerion                  );
2282d953ebb9b04cbad6891676df597bf0c542b1ec89cerion      break;
228320ef5472eac767474c93b7835364a23f24c0ec5dsewardj   }
2284d953ebb9b04cbad6891676df597bf0c542b1ec89cerion
22855b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion   case /* 5  */ PPCG_FLAG_OP_NEG:
2286d953ebb9b04cbad6891676df597bf0c542b1ec89cerion      /* argL == INT64_MIN */
2287d953ebb9b04cbad6891676df597bf0c542b1ec89cerion      xer_ov
2288d953ebb9b04cbad6891676df597bf0c542b1ec89cerion         = binop(Iop_CmpEQ64, argL, mkU64(INT64_MIN));
2289d953ebb9b04cbad6891676df597bf0c542b1ec89cerion      break;
2290d953ebb9b04cbad6891676df597bf0c542b1ec89cerion
22915b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion   case /* 6  */ PPCG_FLAG_OP_SUBF:
22925b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion   case /* 7  */ PPCG_FLAG_OP_SUBFC:
22935b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion   case /* 8  */ PPCG_FLAG_OP_SUBFE:
2294d953ebb9b04cbad6891676df597bf0c542b1ec89cerion      /* ((~argL)^argR^-1) & ((~argL)^res) & (1<<63) ?1:0; */
2295d953ebb9b04cbad6891676df597bf0c542b1ec89cerion      xer_ov
2296d953ebb9b04cbad6891676df597bf0c542b1ec89cerion         = AND3( XOR3(NOT(argL),argR,mkU64(-1)),
2297d953ebb9b04cbad6891676df597bf0c542b1ec89cerion                 XOR2(NOT(argL),res),
2298d953ebb9b04cbad6891676df597bf0c542b1ec89cerion                 mkU64(INT64_MIN) );
2299d953ebb9b04cbad6891676df597bf0c542b1ec89cerion      /* xer_ov can only be 0 or 1<<63 */
2300d953ebb9b04cbad6891676df597bf0c542b1ec89cerion      xer_ov
2301d953ebb9b04cbad6891676df597bf0c542b1ec89cerion         = unop(Iop_64to1, binop(Iop_Shr64, xer_ov, mkU8(63)));
2302d953ebb9b04cbad6891676df597bf0c542b1ec89cerion      break;
2303d953ebb9b04cbad6891676df597bf0c542b1ec89cerion
23044aa412af1d8166cc11f39a6e721df49431d23618sewardj   case PPCG_FLAG_OP_DIVDE:
23054aa412af1d8166cc11f39a6e721df49431d23618sewardj
23064aa412af1d8166cc11f39a6e721df49431d23618sewardj      /* If argR == 0, we must set the OV bit.  But there's another condition
23074aa412af1d8166cc11f39a6e721df49431d23618sewardj       * where we can get overflow set for divde . . . when the
23084aa412af1d8166cc11f39a6e721df49431d23618sewardj       * result cannot fit in the 64-bit destination register.  If dest reg is 0 AND
23094aa412af1d8166cc11f39a6e721df49431d23618sewardj       * both dividend and divisor are non-zero, it implies an overflow.
23104aa412af1d8166cc11f39a6e721df49431d23618sewardj       */
23114aa412af1d8166cc11f39a6e721df49431d23618sewardj      xer_ov
23124aa412af1d8166cc11f39a6e721df49431d23618sewardj                  = mkOR1( binop( Iop_CmpEQ64, argR, mkU64( 0 ) ),
23134aa412af1d8166cc11f39a6e721df49431d23618sewardj                           mkAND1( binop( Iop_CmpEQ64, res, mkU64( 0 ) ),
23144aa412af1d8166cc11f39a6e721df49431d23618sewardj                                   mkAND1( binop( Iop_CmpNE64, argL, mkU64( 0 ) ),
23154aa412af1d8166cc11f39a6e721df49431d23618sewardj                                           binop( Iop_CmpNE64, argR, mkU64( 0 ) ) ) ) );
23164aa412af1d8166cc11f39a6e721df49431d23618sewardj      break;
23174aa412af1d8166cc11f39a6e721df49431d23618sewardj
2318e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj   case PPCG_FLAG_OP_DIVDEU:
2319e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj     /* If argR == 0 or if argL >= argR, set OV. */
2320e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj     xer_ov = mkOR1( binop( Iop_CmpEQ64, argR, mkU64( 0 ) ),
2321e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj                         binop( Iop_CmpLE64U, argR, argL ) );
2322e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj     break;
2323e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj
232438b79ace9613df76a5feb7a237226f4a4cc02ecdcarll   case /* 18 */ PPCG_FLAG_OP_MULLD: {
232538b79ace9613df76a5feb7a237226f4a4cc02ecdcarll      IRTemp  t128;
232638b79ace9613df76a5feb7a237226f4a4cc02ecdcarll      /* OV true if result can't be represented in 64 bits
232738b79ace9613df76a5feb7a237226f4a4cc02ecdcarll         i.e sHi != sign extension of sLo */
232838b79ace9613df76a5feb7a237226f4a4cc02ecdcarll      t128 = newTemp(Ity_I128);
232938b79ace9613df76a5feb7a237226f4a4cc02ecdcarll      assign( t128, binop(Iop_MullS64, argL, argR) );
233038b79ace9613df76a5feb7a237226f4a4cc02ecdcarll      xer_ov
233138b79ace9613df76a5feb7a237226f4a4cc02ecdcarll         = binop( Iop_CmpNE64,
233238b79ace9613df76a5feb7a237226f4a4cc02ecdcarll                  unop(Iop_128HIto64, mkexpr(t128)),
233338b79ace9613df76a5feb7a237226f4a4cc02ecdcarll                  binop( Iop_Sar64,
233438b79ace9613df76a5feb7a237226f4a4cc02ecdcarll                         unop(Iop_128to64, mkexpr(t128)),
233538b79ace9613df76a5feb7a237226f4a4cc02ecdcarll                         mkU8(63))
233638b79ace9613df76a5feb7a237226f4a4cc02ecdcarll                  );
233738b79ace9613df76a5feb7a237226f4a4cc02ecdcarll      break;
233838b79ace9613df76a5feb7a237226f4a4cc02ecdcarll   }
233938b79ace9613df76a5feb7a237226f4a4cc02ecdcarll
2340d953ebb9b04cbad6891676df597bf0c542b1ec89cerion   default:
2341d953ebb9b04cbad6891676df597bf0c542b1ec89cerion      vex_printf("set_XER_OV: op = %u\n", op);
23425b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion      vpanic("set_XER_OV(ppc64)");
2343d953ebb9b04cbad6891676df597bf0c542b1ec89cerion   }
2344d953ebb9b04cbad6891676df597bf0c542b1ec89cerion
234520ef5472eac767474c93b7835364a23f24c0ec5dsewardj   /* xer_ov MUST denote either 0 or 1, no other value allowed */
2346d953ebb9b04cbad6891676df597bf0c542b1ec89cerion   putXER_OV( unop(Iop_1Uto8, xer_ov) );
234720ef5472eac767474c93b7835364a23f24c0ec5dsewardj
234820ef5472eac767474c93b7835364a23f24c0ec5dsewardj   /* Update the summary overflow */
2349edf7fc572e2decb93e9143961e8739c8fe18899dcerion   putXER_SO( binop(Iop_Or8, getXER_SO(), getXER_OV()) );
235020ef5472eac767474c93b7835364a23f24c0ec5dsewardj
2351d953ebb9b04cbad6891676df597bf0c542b1ec89cerion#  undef INT64_MIN
235220ef5472eac767474c93b7835364a23f24c0ec5dsewardj#  undef AND3
235320ef5472eac767474c93b7835364a23f24c0ec5dsewardj#  undef XOR3
235420ef5472eac767474c93b7835364a23f24c0ec5dsewardj#  undef XOR2
235520ef5472eac767474c93b7835364a23f24c0ec5dsewardj#  undef NOT
235620ef5472eac767474c93b7835364a23f24c0ec5dsewardj}
235720ef5472eac767474c93b7835364a23f24c0ec5dsewardj
2358d953ebb9b04cbad6891676df597bf0c542b1ec89cerionstatic void set_XER_OV ( IRType ty, UInt op, IRExpr* res,
2359d953ebb9b04cbad6891676df597bf0c542b1ec89cerion                         IRExpr* argL, IRExpr* argR )
2360d953ebb9b04cbad6891676df597bf0c542b1ec89cerion{
2361d953ebb9b04cbad6891676df597bf0c542b1ec89cerion   if (ty == Ity_I32)
2362d953ebb9b04cbad6891676df597bf0c542b1ec89cerion      set_XER_OV_32( op, res, argL, argR );
2363d953ebb9b04cbad6891676df597bf0c542b1ec89cerion   else
2364d953ebb9b04cbad6891676df597bf0c542b1ec89cerion      set_XER_OV_64( op, res, argL, argR );
2365d953ebb9b04cbad6891676df597bf0c542b1ec89cerion}
2366d953ebb9b04cbad6891676df597bf0c542b1ec89cerion
2367d953ebb9b04cbad6891676df597bf0c542b1ec89cerion
2368d953ebb9b04cbad6891676df597bf0c542b1ec89cerion
2369b51f0f4f33256638ed953156a2635aa739b232f1sewardj/* RES is the result of doing OP on ARGL and ARGR with the old %XER.CA
2370b51f0f4f33256638ed953156a2635aa739b232f1sewardj   value being OLDCA.  Set %XER.CA accordingly. */
2371b51f0f4f33256638ed953156a2635aa739b232f1sewardj
23722831b00c4950d6c2b061def05fd67528fe132ececerionstatic void set_XER_CA_32 ( UInt op, IRExpr* res,
23732831b00c4950d6c2b061def05fd67528fe132ececerion                            IRExpr* argL, IRExpr* argR, IRExpr* oldca )
23743867460f7533d6dc4e2c85656664ee341ea81e7dcerion{
2375b51f0f4f33256638ed953156a2635aa739b232f1sewardj   IRExpr* xer_ca;
23765b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion   vassert(op < PPCG_FLAG_OP_NUMBER);
2377dd40fdf58cc8a6fe9466c4f00bdfc9fe9bf00449sewardj   vassert(typeOfIRExpr(irsb->tyenv,res)   == Ity_I32);
2378dd40fdf58cc8a6fe9466c4f00bdfc9fe9bf00449sewardj   vassert(typeOfIRExpr(irsb->tyenv,argL)  == Ity_I32);
2379dd40fdf58cc8a6fe9466c4f00bdfc9fe9bf00449sewardj   vassert(typeOfIRExpr(irsb->tyenv,argR)  == Ity_I32);
2380dd40fdf58cc8a6fe9466c4f00bdfc9fe9bf00449sewardj   vassert(typeOfIRExpr(irsb->tyenv,oldca) == Ity_I32);
2381b51f0f4f33256638ed953156a2635aa739b232f1sewardj
238220ef5472eac767474c93b7835364a23f24c0ec5dsewardj   /* Incoming oldca is assumed to hold the values 0 or 1 only.  This
238320ef5472eac767474c93b7835364a23f24c0ec5dsewardj      seems reasonable given that it's always generated by
2384edf7fc572e2decb93e9143961e8739c8fe18899dcerion      getXER_CA32(), which masks it accordingly.  In any case it being
23857594920259781fa292dd6a3b27beb63f5875c308cerion      0 or 1 is an invariant of the ppc guest state representation;
238620ef5472eac767474c93b7835364a23f24c0ec5dsewardj      if it has any other value, that invariant has been violated. */
238720ef5472eac767474c93b7835364a23f24c0ec5dsewardj
238820ef5472eac767474c93b7835364a23f24c0ec5dsewardj   switch (op) {
23895b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion   case /* 0 */ PPCG_FLAG_OP_ADD:
2390d953ebb9b04cbad6891676df597bf0c542b1ec89cerion      /* res <u argL */
2391d953ebb9b04cbad6891676df597bf0c542b1ec89cerion      xer_ca
2392d953ebb9b04cbad6891676df597bf0c542b1ec89cerion         = unop(Iop_1Uto32, binop(Iop_CmpLT32U, res, argL));
2393d953ebb9b04cbad6891676df597bf0c542b1ec89cerion      break;
2394d953ebb9b04cbad6891676df597bf0c542b1ec89cerion
23955b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion   case /* 1 */ PPCG_FLAG_OP_ADDE:
2396d953ebb9b04cbad6891676df597bf0c542b1ec89cerion      /* res <u argL || (old_ca==1 && res==argL) */
2397d953ebb9b04cbad6891676df597bf0c542b1ec89cerion      xer_ca
2398d953ebb9b04cbad6891676df597bf0c542b1ec89cerion         = mkOR1(
2399d953ebb9b04cbad6891676df597bf0c542b1ec89cerion              binop(Iop_CmpLT32U, res, argL),
2400d953ebb9b04cbad6891676df597bf0c542b1ec89cerion              mkAND1(
2401d953ebb9b04cbad6891676df597bf0c542b1ec89cerion                 binop(Iop_CmpEQ32, oldca, mkU32(1)),
2402d953ebb9b04cbad6891676df597bf0c542b1ec89cerion                 binop(Iop_CmpEQ32, res, argL)
2403d953ebb9b04cbad6891676df597bf0c542b1ec89cerion              )
2404d953ebb9b04cbad6891676df597bf0c542b1ec89cerion           );
2405d953ebb9b04cbad6891676df597bf0c542b1ec89cerion      xer_ca
2406d953ebb9b04cbad6891676df597bf0c542b1ec89cerion         = unop(Iop_1Uto32, xer_ca);
2407d953ebb9b04cbad6891676df597bf0c542b1ec89cerion      break;
2408d953ebb9b04cbad6891676df597bf0c542b1ec89cerion
24095b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion   case /* 8 */ PPCG_FLAG_OP_SUBFE:
2410d953ebb9b04cbad6891676df597bf0c542b1ec89cerion      /* res <u argR || (old_ca==1 && res==argR) */
2411d953ebb9b04cbad6891676df597bf0c542b1ec89cerion      xer_ca
2412d953ebb9b04cbad6891676df597bf0c542b1ec89cerion         = mkOR1(
2413d953ebb9b04cbad6891676df597bf0c542b1ec89cerion              binop(Iop_CmpLT32U, res, argR),
2414d953ebb9b04cbad6891676df597bf0c542b1ec89cerion              mkAND1(
2415d953ebb9b04cbad6891676df597bf0c542b1ec89cerion                 binop(Iop_CmpEQ32, oldca, mkU32(1)),
2416d953ebb9b04cbad6891676df597bf0c542b1ec89cerion                 binop(Iop_CmpEQ32, res, argR)
2417d953ebb9b04cbad6891676df597bf0c542b1ec89cerion              )
2418d953ebb9b04cbad6891676df597bf0c542b1ec89cerion           );
2419d953ebb9b04cbad6891676df597bf0c542b1ec89cerion      xer_ca
2420d953ebb9b04cbad6891676df597bf0c542b1ec89cerion         = unop(Iop_1Uto32, xer_ca);
2421d953ebb9b04cbad6891676df597bf0c542b1ec89cerion      break;
2422d953ebb9b04cbad6891676df597bf0c542b1ec89cerion
24235b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion   case /* 7 */ PPCG_FLAG_OP_SUBFC:
24245b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion   case /* 9 */ PPCG_FLAG_OP_SUBFI:
2425d953ebb9b04cbad6891676df597bf0c542b1ec89cerion      /* res <=u argR */
2426d953ebb9b04cbad6891676df597bf0c542b1ec89cerion      xer_ca
2427d953ebb9b04cbad6891676df597bf0c542b1ec89cerion         = unop(Iop_1Uto32, binop(Iop_CmpLE32U, res, argR));
2428d953ebb9b04cbad6891676df597bf0c542b1ec89cerion      break;
2429d953ebb9b04cbad6891676df597bf0c542b1ec89cerion
24305b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion   case /* 10 */ PPCG_FLAG_OP_SRAW:
2431d953ebb9b04cbad6891676df597bf0c542b1ec89cerion      /* The shift amount is guaranteed to be in 0 .. 63 inclusive.
2432d953ebb9b04cbad6891676df597bf0c542b1ec89cerion         If it is <= 31, behave like SRAWI; else XER.CA is the sign
2433d953ebb9b04cbad6891676df597bf0c542b1ec89cerion         bit of argL. */
2434d953ebb9b04cbad6891676df597bf0c542b1ec89cerion      /* This term valid for shift amount < 32 only */
2435d953ebb9b04cbad6891676df597bf0c542b1ec89cerion      xer_ca
2436d953ebb9b04cbad6891676df597bf0c542b1ec89cerion         = binop(
2437d953ebb9b04cbad6891676df597bf0c542b1ec89cerion              Iop_And32,
2438d953ebb9b04cbad6891676df597bf0c542b1ec89cerion              binop(Iop_Sar32, argL, mkU8(31)),
2439d953ebb9b04cbad6891676df597bf0c542b1ec89cerion              binop( Iop_And32,
2440d953ebb9b04cbad6891676df597bf0c542b1ec89cerion                     argL,
2441d953ebb9b04cbad6891676df597bf0c542b1ec89cerion                     binop( Iop_Sub32,
24425b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion                            binop(Iop_Shl32, mkU32(1),
24435b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion                                             unop(Iop_32to8,argR)),
2444d953ebb9b04cbad6891676df597bf0c542b1ec89cerion                            mkU32(1) )
2445d953ebb9b04cbad6891676df597bf0c542b1ec89cerion                     )
244620ef5472eac767474c93b7835364a23f24c0ec5dsewardj              );
2447d953ebb9b04cbad6891676df597bf0c542b1ec89cerion      xer_ca
244899dd03e04a6914d90d5fee727d61d76905334becflorian         = IRExpr_ITE(
2449d953ebb9b04cbad6891676df597bf0c542b1ec89cerion              /* shift amt > 31 ? */
2450009230b9758291b594e60d7c0243a73d53e81854sewardj              binop(Iop_CmpLT32U, mkU32(31), argR),
2451d953ebb9b04cbad6891676df597bf0c542b1ec89cerion              /* yes -- get sign bit of argL */
245299dd03e04a6914d90d5fee727d61d76905334becflorian              binop(Iop_Shr32, argL, mkU8(31)),
245399dd03e04a6914d90d5fee727d61d76905334becflorian              /* no -- be like srawi */
245499dd03e04a6914d90d5fee727d61d76905334becflorian              unop(Iop_1Uto32, binop(Iop_CmpNE32, xer_ca, mkU32(0)))
2455d953ebb9b04cbad6891676df597bf0c542b1ec89cerion           );
2456d953ebb9b04cbad6891676df597bf0c542b1ec89cerion      break;
2457d953ebb9b04cbad6891676df597bf0c542b1ec89cerion
24585b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion   case /* 11 */ PPCG_FLAG_OP_SRAWI:
2459d953ebb9b04cbad6891676df597bf0c542b1ec89cerion      /* xer_ca is 1 iff src was negative and bits_shifted_out !=
2460d953ebb9b04cbad6891676df597bf0c542b1ec89cerion         0.  Since the shift amount is known to be in the range
2461d953ebb9b04cbad6891676df597bf0c542b1ec89cerion         0 .. 31 inclusive the following seems viable:
2462d953ebb9b04cbad6891676df597bf0c542b1ec89cerion         xer.ca == 1 iff the following is nonzero:
2463d953ebb9b04cbad6891676df597bf0c542b1ec89cerion         (argL >>s 31)           -- either all 0s or all 1s
2464d953ebb9b04cbad6891676df597bf0c542b1ec89cerion         & (argL & (1<<argR)-1)  -- the stuff shifted out */
2465d953ebb9b04cbad6891676df597bf0c542b1ec89cerion      xer_ca
2466d953ebb9b04cbad6891676df597bf0c542b1ec89cerion         = binop(
2467d953ebb9b04cbad6891676df597bf0c542b1ec89cerion              Iop_And32,
2468d953ebb9b04cbad6891676df597bf0c542b1ec89cerion              binop(Iop_Sar32, argL, mkU8(31)),
2469d953ebb9b04cbad6891676df597bf0c542b1ec89cerion              binop( Iop_And32,
2470d953ebb9b04cbad6891676df597bf0c542b1ec89cerion                     argL,
2471d953ebb9b04cbad6891676df597bf0c542b1ec89cerion                     binop( Iop_Sub32,
24725b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion                            binop(Iop_Shl32, mkU32(1),
24735b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion                                             unop(Iop_32to8,argR)),
2474d953ebb9b04cbad6891676df597bf0c542b1ec89cerion                            mkU32(1) )
2475d953ebb9b04cbad6891676df597bf0c542b1ec89cerion                     )
247620ef5472eac767474c93b7835364a23f24c0ec5dsewardj              );
2477d953ebb9b04cbad6891676df597bf0c542b1ec89cerion      xer_ca
2478d953ebb9b04cbad6891676df597bf0c542b1ec89cerion         = unop(Iop_1Uto32, binop(Iop_CmpNE32, xer_ca, mkU32(0)));
2479d953ebb9b04cbad6891676df597bf0c542b1ec89cerion      break;
2480d953ebb9b04cbad6891676df597bf0c542b1ec89cerion
2481d953ebb9b04cbad6891676df597bf0c542b1ec89cerion   default:
2482d953ebb9b04cbad6891676df597bf0c542b1ec89cerion      vex_printf("set_XER_CA: op = %u\n", op);
24835b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion      vpanic("set_XER_CA(ppc)");
2484d953ebb9b04cbad6891676df597bf0c542b1ec89cerion   }
248520ef5472eac767474c93b7835364a23f24c0ec5dsewardj
2486d953ebb9b04cbad6891676df597bf0c542b1ec89cerion   /* xer_ca MUST denote either 0 or 1, no other value allowed */
2487d953ebb9b04cbad6891676df597bf0c542b1ec89cerion   putXER_CA( unop(Iop_32to8, xer_ca) );
2488d953ebb9b04cbad6891676df597bf0c542b1ec89cerion}
248920ef5472eac767474c93b7835364a23f24c0ec5dsewardj
24902831b00c4950d6c2b061def05fd67528fe132ececerionstatic void set_XER_CA_64 ( UInt op, IRExpr* res,
24912831b00c4950d6c2b061def05fd67528fe132ececerion                            IRExpr* argL, IRExpr* argR, IRExpr* oldca )
2492d953ebb9b04cbad6891676df597bf0c542b1ec89cerion{
2493d953ebb9b04cbad6891676df597bf0c542b1ec89cerion   IRExpr* xer_ca;
24945b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion   vassert(op < PPCG_FLAG_OP_NUMBER);
2495dd40fdf58cc8a6fe9466c4f00bdfc9fe9bf00449sewardj   vassert(typeOfIRExpr(irsb->tyenv,res)   == Ity_I64);
2496dd40fdf58cc8a6fe9466c4f00bdfc9fe9bf00449sewardj   vassert(typeOfIRExpr(irsb->tyenv,argL)  == Ity_I64);
2497dd40fdf58cc8a6fe9466c4f00bdfc9fe9bf00449sewardj   vassert(typeOfIRExpr(irsb->tyenv,argR)  == Ity_I64);
2498dd40fdf58cc8a6fe9466c4f00bdfc9fe9bf00449sewardj   vassert(typeOfIRExpr(irsb->tyenv,oldca) == Ity_I64);
249920ef5472eac767474c93b7835364a23f24c0ec5dsewardj
2500d953ebb9b04cbad6891676df597bf0c542b1ec89cerion   /* Incoming oldca is assumed to hold the values 0 or 1 only.  This
2501d953ebb9b04cbad6891676df597bf0c542b1ec89cerion      seems reasonable given that it's always generated by
2502d953ebb9b04cbad6891676df597bf0c542b1ec89cerion      getXER_CA32(), which masks it accordingly.  In any case it being
25037594920259781fa292dd6a3b27beb63f5875c308cerion      0 or 1 is an invariant of the ppc guest state representation;
2504d953ebb9b04cbad6891676df597bf0c542b1ec89cerion      if it has any other value, that invariant has been violated. */
2505d953ebb9b04cbad6891676df597bf0c542b1ec89cerion
2506d953ebb9b04cbad6891676df597bf0c542b1ec89cerion   switch (op) {
25075b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion   case /* 0 */ PPCG_FLAG_OP_ADD:
2508d953ebb9b04cbad6891676df597bf0c542b1ec89cerion      /* res <u argL */
2509d953ebb9b04cbad6891676df597bf0c542b1ec89cerion      xer_ca
2510f0de28cf1a762b0d6f74c93d3532c89a230673bbcerion         = unop(Iop_1Uto32, binop(Iop_CmpLT64U, res, argL));
2511d953ebb9b04cbad6891676df597bf0c542b1ec89cerion      break;
2512d953ebb9b04cbad6891676df597bf0c542b1ec89cerion
25135b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion   case /* 1 */ PPCG_FLAG_OP_ADDE:
2514d953ebb9b04cbad6891676df597bf0c542b1ec89cerion      /* res <u argL || (old_ca==1 && res==argL) */
2515d953ebb9b04cbad6891676df597bf0c542b1ec89cerion      xer_ca
2516d953ebb9b04cbad6891676df597bf0c542b1ec89cerion         = mkOR1(
2517d953ebb9b04cbad6891676df597bf0c542b1ec89cerion              binop(Iop_CmpLT64U, res, argL),
2518d953ebb9b04cbad6891676df597bf0c542b1ec89cerion              mkAND1(
2519f0de28cf1a762b0d6f74c93d3532c89a230673bbcerion                 binop(Iop_CmpEQ64, oldca, mkU64(1)),
2520d953ebb9b04cbad6891676df597bf0c542b1ec89cerion                 binop(Iop_CmpEQ64, res, argL)
2521d953ebb9b04cbad6891676df597bf0c542b1ec89cerion                 )
2522d953ebb9b04cbad6891676df597bf0c542b1ec89cerion              );
2523f0de28cf1a762b0d6f74c93d3532c89a230673bbcerion      xer_ca
2524f0de28cf1a762b0d6f74c93d3532c89a230673bbcerion         = unop(Iop_1Uto32, xer_ca);
2525d953ebb9b04cbad6891676df597bf0c542b1ec89cerion      break;
2526d953ebb9b04cbad6891676df597bf0c542b1ec89cerion
25275b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion   case /* 8 */ PPCG_FLAG_OP_SUBFE:
2528d953ebb9b04cbad6891676df597bf0c542b1ec89cerion      /* res <u argR || (old_ca==1 && res==argR) */
2529d953ebb9b04cbad6891676df597bf0c542b1ec89cerion      xer_ca
2530d953ebb9b04cbad6891676df597bf0c542b1ec89cerion         = mkOR1(
2531d953ebb9b04cbad6891676df597bf0c542b1ec89cerion              binop(Iop_CmpLT64U, res, argR),
2532d953ebb9b04cbad6891676df597bf0c542b1ec89cerion              mkAND1(
2533d953ebb9b04cbad6891676df597bf0c542b1ec89cerion                 binop(Iop_CmpEQ64, oldca, mkU64(1)),
2534d953ebb9b04cbad6891676df597bf0c542b1ec89cerion                 binop(Iop_CmpEQ64, res, argR)
2535d953ebb9b04cbad6891676df597bf0c542b1ec89cerion              )
2536d953ebb9b04cbad6891676df597bf0c542b1ec89cerion           );
2537f0de28cf1a762b0d6f74c93d3532c89a230673bbcerion      xer_ca
2538f0de28cf1a762b0d6f74c93d3532c89a230673bbcerion         = unop(Iop_1Uto32, xer_ca);
2539d953ebb9b04cbad6891676df597bf0c542b1ec89cerion      break;
2540d953ebb9b04cbad6891676df597bf0c542b1ec89cerion
25415b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion   case /* 7 */ PPCG_FLAG_OP_SUBFC:
25425b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion   case /* 9 */ PPCG_FLAG_OP_SUBFI:
2543d953ebb9b04cbad6891676df597bf0c542b1ec89cerion      /* res <=u argR */
2544d953ebb9b04cbad6891676df597bf0c542b1ec89cerion      xer_ca
2545f0de28cf1a762b0d6f74c93d3532c89a230673bbcerion         = unop(Iop_1Uto32, binop(Iop_CmpLE64U, res, argR));
2546d953ebb9b04cbad6891676df597bf0c542b1ec89cerion      break;
2547d953ebb9b04cbad6891676df597bf0c542b1ec89cerion
2548d953ebb9b04cbad6891676df597bf0c542b1ec89cerion
25495b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion   case /* 10 */ PPCG_FLAG_OP_SRAW:
2550f0de28cf1a762b0d6f74c93d3532c89a230673bbcerion      /* The shift amount is guaranteed to be in 0 .. 31 inclusive.
2551d953ebb9b04cbad6891676df597bf0c542b1ec89cerion         If it is <= 31, behave like SRAWI; else XER.CA is the sign
2552d953ebb9b04cbad6891676df597bf0c542b1ec89cerion         bit of argL. */
2553f0de28cf1a762b0d6f74c93d3532c89a230673bbcerion         /* This term valid for shift amount < 31 only */
2554f0de28cf1a762b0d6f74c93d3532c89a230673bbcerion
2555d953ebb9b04cbad6891676df597bf0c542b1ec89cerion      xer_ca
2556d953ebb9b04cbad6891676df597bf0c542b1ec89cerion         = binop(
2557f0de28cf1a762b0d6f74c93d3532c89a230673bbcerion              Iop_And64,
2558f0de28cf1a762b0d6f74c93d3532c89a230673bbcerion              binop(Iop_Sar64, argL, mkU8(31)),
2559f0de28cf1a762b0d6f74c93d3532c89a230673bbcerion              binop( Iop_And64,
2560d953ebb9b04cbad6891676df597bf0c542b1ec89cerion                     argL,
2561f0de28cf1a762b0d6f74c93d3532c89a230673bbcerion                     binop( Iop_Sub64,
25625b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion                            binop(Iop_Shl64, mkU64(1),
25635b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion                                             unop(Iop_64to8,argR)),
2564f0de28cf1a762b0d6f74c93d3532c89a230673bbcerion                            mkU64(1) )
2565d953ebb9b04cbad6891676df597bf0c542b1ec89cerion              )
2566d953ebb9b04cbad6891676df597bf0c542b1ec89cerion           );
2567d953ebb9b04cbad6891676df597bf0c542b1ec89cerion      xer_ca
256899dd03e04a6914d90d5fee727d61d76905334becflorian         = IRExpr_ITE(
2569d953ebb9b04cbad6891676df597bf0c542b1ec89cerion              /* shift amt > 31 ? */
2570009230b9758291b594e60d7c0243a73d53e81854sewardj              binop(Iop_CmpLT64U, mkU64(31), argR),
2571d953ebb9b04cbad6891676df597bf0c542b1ec89cerion              /* yes -- get sign bit of argL */
257299dd03e04a6914d90d5fee727d61d76905334becflorian              unop(Iop_64to32, binop(Iop_Shr64, argL, mkU8(63))),
257399dd03e04a6914d90d5fee727d61d76905334becflorian              /* no -- be like srawi */
257499dd03e04a6914d90d5fee727d61d76905334becflorian              unop(Iop_1Uto32, binop(Iop_CmpNE64, xer_ca, mkU64(0)))
257599dd03e04a6914d90d5fee727d61d76905334becflorian          );
2576d953ebb9b04cbad6891676df597bf0c542b1ec89cerion      break;
2577d953ebb9b04cbad6891676df597bf0c542b1ec89cerion
25785b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion   case /* 11 */ PPCG_FLAG_OP_SRAWI:
2579f0de28cf1a762b0d6f74c93d3532c89a230673bbcerion      /* xer_ca is 1 iff src was negative and bits_shifted_out != 0.
2580f0de28cf1a762b0d6f74c93d3532c89a230673bbcerion         Since the shift amount is known to be in the range 0 .. 31
2581f0de28cf1a762b0d6f74c93d3532c89a230673bbcerion         inclusive the following seems viable:
2582d953ebb9b04cbad6891676df597bf0c542b1ec89cerion         xer.ca == 1 iff the following is nonzero:
2583d953ebb9b04cbad6891676df597bf0c542b1ec89cerion         (argL >>s 31)           -- either all 0s or all 1s
2584d953ebb9b04cbad6891676df597bf0c542b1ec89cerion         & (argL & (1<<argR)-1)  -- the stuff shifted out */
2585f0de28cf1a762b0d6f74c93d3532c89a230673bbcerion
2586d953ebb9b04cbad6891676df597bf0c542b1ec89cerion      xer_ca
2587d953ebb9b04cbad6891676df597bf0c542b1ec89cerion         = binop(
2588f0de28cf1a762b0d6f74c93d3532c89a230673bbcerion              Iop_And64,
2589f0de28cf1a762b0d6f74c93d3532c89a230673bbcerion              binop(Iop_Sar64, argL, mkU8(31)),
2590f0de28cf1a762b0d6f74c93d3532c89a230673bbcerion              binop( Iop_And64,
2591d953ebb9b04cbad6891676df597bf0c542b1ec89cerion                     argL,
2592f0de28cf1a762b0d6f74c93d3532c89a230673bbcerion                     binop( Iop_Sub64,
25935b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion                            binop(Iop_Shl64, mkU64(1),
25945b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion                                             unop(Iop_64to8,argR)),
2595f0de28cf1a762b0d6f74c93d3532c89a230673bbcerion                            mkU64(1) )
2596d953ebb9b04cbad6891676df597bf0c542b1ec89cerion              )
2597d953ebb9b04cbad6891676df597bf0c542b1ec89cerion           );
2598d953ebb9b04cbad6891676df597bf0c542b1ec89cerion      xer_ca
2599f0de28cf1a762b0d6f74c93d3532c89a230673bbcerion         = unop(Iop_1Uto32, binop(Iop_CmpNE64, xer_ca, mkU64(0)));
2600d953ebb9b04cbad6891676df597bf0c542b1ec89cerion      break;
2601d953ebb9b04cbad6891676df597bf0c542b1ec89cerion
2602f0de28cf1a762b0d6f74c93d3532c89a230673bbcerion
26035b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion   case /* 12 */ PPCG_FLAG_OP_SRAD:
2604f0de28cf1a762b0d6f74c93d3532c89a230673bbcerion      /* The shift amount is guaranteed to be in 0 .. 63 inclusive.
2605f0de28cf1a762b0d6f74c93d3532c89a230673bbcerion         If it is <= 63, behave like SRADI; else XER.CA is the sign
2606f0de28cf1a762b0d6f74c93d3532c89a230673bbcerion         bit of argL. */
2607f0de28cf1a762b0d6f74c93d3532c89a230673bbcerion         /* This term valid for shift amount < 63 only */
2608f0de28cf1a762b0d6f74c93d3532c89a230673bbcerion
2609f0de28cf1a762b0d6f74c93d3532c89a230673bbcerion      xer_ca
2610f0de28cf1a762b0d6f74c93d3532c89a230673bbcerion         = binop(
2611f0de28cf1a762b0d6f74c93d3532c89a230673bbcerion              Iop_And64,
2612f0de28cf1a762b0d6f74c93d3532c89a230673bbcerion              binop(Iop_Sar64, argL, mkU8(63)),
2613f0de28cf1a762b0d6f74c93d3532c89a230673bbcerion              binop( Iop_And64,
2614f0de28cf1a762b0d6f74c93d3532c89a230673bbcerion                     argL,
2615f0de28cf1a762b0d6f74c93d3532c89a230673bbcerion                     binop( Iop_Sub64,
26165b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion                            binop(Iop_Shl64, mkU64(1),
26175b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion                                             unop(Iop_64to8,argR)),
2618f0de28cf1a762b0d6f74c93d3532c89a230673bbcerion                            mkU64(1) )
2619f0de28cf1a762b0d6f74c93d3532c89a230673bbcerion              )
2620f0de28cf1a762b0d6f74c93d3532c89a230673bbcerion           );
2621f0de28cf1a762b0d6f74c93d3532c89a230673bbcerion      xer_ca
262299dd03e04a6914d90d5fee727d61d76905334becflorian         = IRExpr_ITE(
2623f0de28cf1a762b0d6f74c93d3532c89a230673bbcerion              /* shift amt > 63 ? */
2624009230b9758291b594e60d7c0243a73d53e81854sewardj              binop(Iop_CmpLT64U, mkU64(63), argR),
2625f0de28cf1a762b0d6f74c93d3532c89a230673bbcerion              /* yes -- get sign bit of argL */
262699dd03e04a6914d90d5fee727d61d76905334becflorian              unop(Iop_64to32, binop(Iop_Shr64, argL, mkU8(63))),
262799dd03e04a6914d90d5fee727d61d76905334becflorian              /* no -- be like sradi */
262899dd03e04a6914d90d5fee727d61d76905334becflorian              unop(Iop_1Uto32, binop(Iop_CmpNE64, xer_ca, mkU64(0)))
2629f0de28cf1a762b0d6f74c93d3532c89a230673bbcerion           );
2630f0de28cf1a762b0d6f74c93d3532c89a230673bbcerion      break;
2631f0de28cf1a762b0d6f74c93d3532c89a230673bbcerion
2632f0de28cf1a762b0d6f74c93d3532c89a230673bbcerion
26335b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion   case /* 13 */ PPCG_FLAG_OP_SRADI:
2634f0de28cf1a762b0d6f74c93d3532c89a230673bbcerion      /* xer_ca is 1 iff src was negative and bits_shifted_out != 0.
2635f0de28cf1a762b0d6f74c93d3532c89a230673bbcerion         Since the shift amount is known to be in the range 0 .. 63
2636f0de28cf1a762b0d6f74c93d3532c89a230673bbcerion         inclusive, the following seems viable:
2637f0de28cf1a762b0d6f74c93d3532c89a230673bbcerion         xer.ca == 1 iff the following is nonzero:
2638f0de28cf1a762b0d6f74c93d3532c89a230673bbcerion         (argL >>s 63)           -- either all 0s or all 1s
2639f0de28cf1a762b0d6f74c93d3532c89a230673bbcerion         & (argL & (1<<argR)-1)  -- the stuff shifted out */
2640f0de28cf1a762b0d6f74c93d3532c89a230673bbcerion
2641f0de28cf1a762b0d6f74c93d3532c89a230673bbcerion      xer_ca
2642f0de28cf1a762b0d6f74c93d3532c89a230673bbcerion         = binop(
2643f0de28cf1a762b0d6f74c93d3532c89a230673bbcerion              Iop_And64,
2644f0de28cf1a762b0d6f74c93d3532c89a230673bbcerion              binop(Iop_Sar64, argL, mkU8(63)),
2645f0de28cf1a762b0d6f74c93d3532c89a230673bbcerion              binop( Iop_And64,
2646f0de28cf1a762b0d6f74c93d3532c89a230673bbcerion                     argL,
2647f0de28cf1a762b0d6f74c93d3532c89a230673bbcerion                     binop( Iop_Sub64,
26485b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion                            binop(Iop_Shl64, mkU64(1),
26495b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion                                             unop(Iop_64to8,argR)),
2650f0de28cf1a762b0d6f74c93d3532c89a230673bbcerion                            mkU64(1) )
2651f0de28cf1a762b0d6f74c93d3532c89a230673bbcerion              )
2652f0de28cf1a762b0d6f74c93d3532c89a230673bbcerion           );
2653f0de28cf1a762b0d6f74c93d3532c89a230673bbcerion      xer_ca
2654f0de28cf1a762b0d6f74c93d3532c89a230673bbcerion         = unop(Iop_1Uto32, binop(Iop_CmpNE64, xer_ca, mkU64(0)));
2655f0de28cf1a762b0d6f74c93d3532c89a230673bbcerion      break;
2656f0de28cf1a762b0d6f74c93d3532c89a230673bbcerion
2657d953ebb9b04cbad6891676df597bf0c542b1ec89cerion   default:
2658d953ebb9b04cbad6891676df597bf0c542b1ec89cerion      vex_printf("set_XER_CA: op = %u\n", op);
2659f0de28cf1a762b0d6f74c93d3532c89a230673bbcerion      vpanic("set_XER_CA(ppc64)");
266020ef5472eac767474c93b7835364a23f24c0ec5dsewardj   }
2661b51f0f4f33256638ed953156a2635aa739b232f1sewardj
266220ef5472eac767474c93b7835364a23f24c0ec5dsewardj   /* xer_ca MUST denote either 0 or 1, no other value allowed */
2663f0de28cf1a762b0d6f74c93d3532c89a230673bbcerion   putXER_CA( unop(Iop_32to8, xer_ca) );
2664d953ebb9b04cbad6891676df597bf0c542b1ec89cerion}
2665d953ebb9b04cbad6891676df597bf0c542b1ec89cerion
26662831b00c4950d6c2b061def05fd67528fe132ececerionstatic void set_XER_CA ( IRType ty, UInt op, IRExpr* res,
26672831b00c4950d6c2b061def05fd67528fe132ececerion                         IRExpr* argL, IRExpr* argR, IRExpr* oldca )
2668d953ebb9b04cbad6891676df597bf0c542b1ec89cerion{
26692831b00c4950d6c2b061def05fd67528fe132ececerion   if (ty == Ity_I32)
2670d953ebb9b04cbad6891676df597bf0c542b1ec89cerion      set_XER_CA_32( op, res, argL, argR, oldca );
2671d953ebb9b04cbad6891676df597bf0c542b1ec89cerion   else
2672d953ebb9b04cbad6891676df597bf0c542b1ec89cerion      set_XER_CA_64( op, res, argL, argR, oldca );
2673e9d361ab43518b6dfbd3d846f48859534659dee0cerion}
2674896a1373cfdbaa25f4ab73ed4f27554016defecccerion
2675896a1373cfdbaa25f4ab73ed4f27554016defecccerion
267662bec57d758aefcb5cb6265864f62fc33ad8391dcerion
2677e14bb9f862843c6b804097c124961b5567ded4f1sewardj/*------------------------------------------------------------*/
2678d953ebb9b04cbad6891676df597bf0c542b1ec89cerion/*--- Read/write to guest-state                           --- */
2679e14bb9f862843c6b804097c124961b5567ded4f1sewardj/*------------------------------------------------------------*/
2680e14bb9f862843c6b804097c124961b5567ded4f1sewardj
2681f0de28cf1a762b0d6f74c93d3532c89a230673bbcerionstatic IRExpr* /* :: Ity_I32/64 */ getGST ( PPC_GST reg )
2682d953ebb9b04cbad6891676df597bf0c542b1ec89cerion{
2683d953ebb9b04cbad6891676df597bf0c542b1ec89cerion   IRType ty = mode64 ? Ity_I64 : Ity_I32;
2684d953ebb9b04cbad6891676df597bf0c542b1ec89cerion   switch (reg) {
2685aca070a5b3418a6a9b01e3c57a7eb0fbb5050908sewardj   case PPC_GST_SPRG3_RO:
2686aca070a5b3418a6a9b01e3c57a7eb0fbb5050908sewardj      return IRExpr_Get( OFFB_SPRG3_RO, ty );
2687aca070a5b3418a6a9b01e3c57a7eb0fbb5050908sewardj
2688aca070a5b3418a6a9b01e3c57a7eb0fbb5050908sewardj   case PPC_GST_CIA:
2689aca070a5b3418a6a9b01e3c57a7eb0fbb5050908sewardj      return IRExpr_Get( OFFB_CIA, ty );
2690aca070a5b3418a6a9b01e3c57a7eb0fbb5050908sewardj
2691d953ebb9b04cbad6891676df597bf0c542b1ec89cerion   case PPC_GST_LR:
26925b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion      return IRExpr_Get( OFFB_LR, ty );
2693d953ebb9b04cbad6891676df597bf0c542b1ec89cerion
2694d953ebb9b04cbad6891676df597bf0c542b1ec89cerion   case PPC_GST_CTR:
26955b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion      return IRExpr_Get( OFFB_CTR, ty );
2696d953ebb9b04cbad6891676df597bf0c542b1ec89cerion
2697d953ebb9b04cbad6891676df597bf0c542b1ec89cerion   case PPC_GST_VRSAVE:
26985b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion      return IRExpr_Get( OFFB_VRSAVE, Ity_I32 );
2699d953ebb9b04cbad6891676df597bf0c542b1ec89cerion
2700d953ebb9b04cbad6891676df597bf0c542b1ec89cerion   case PPC_GST_VSCR:
27015b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion      return binop(Iop_And32, IRExpr_Get( OFFB_VSCR,Ity_I32 ),
27025b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion                              mkU32(MASK_VSCR_VALID));
2703d953ebb9b04cbad6891676df597bf0c542b1ec89cerion
2704d953ebb9b04cbad6891676df597bf0c542b1ec89cerion   case PPC_GST_CR: {
2705d953ebb9b04cbad6891676df597bf0c542b1ec89cerion      /* Synthesise the entire CR into a single word.  Expensive. */
2706d953ebb9b04cbad6891676df597bf0c542b1ec89cerion#     define FIELD(_n)                                               \
2707d953ebb9b04cbad6891676df597bf0c542b1ec89cerion         binop(Iop_Shl32,                                            \
2708d953ebb9b04cbad6891676df597bf0c542b1ec89cerion               unop(Iop_8Uto32,                                      \
2709d953ebb9b04cbad6891676df597bf0c542b1ec89cerion                    binop(Iop_Or8,                                   \
2710d953ebb9b04cbad6891676df597bf0c542b1ec89cerion                          binop(Iop_And8, getCR321(_n), mkU8(7<<1)), \
2711d953ebb9b04cbad6891676df597bf0c542b1ec89cerion                          binop(Iop_And8, getCR0(_n), mkU8(1))       \
2712d953ebb9b04cbad6891676df597bf0c542b1ec89cerion                    )                                                \
2713d953ebb9b04cbad6891676df597bf0c542b1ec89cerion               ),                                                    \
2714d953ebb9b04cbad6891676df597bf0c542b1ec89cerion               mkU8(4 * (7-(_n)))                                    \
2715d953ebb9b04cbad6891676df597bf0c542b1ec89cerion         )
2716d953ebb9b04cbad6891676df597bf0c542b1ec89cerion      return binop(Iop_Or32,
2717d953ebb9b04cbad6891676df597bf0c542b1ec89cerion                   binop(Iop_Or32,
2718d953ebb9b04cbad6891676df597bf0c542b1ec89cerion                         binop(Iop_Or32, FIELD(0), FIELD(1)),
2719d953ebb9b04cbad6891676df597bf0c542b1ec89cerion                         binop(Iop_Or32, FIELD(2), FIELD(3))
2720d953ebb9b04cbad6891676df597bf0c542b1ec89cerion                         ),
2721d953ebb9b04cbad6891676df597bf0c542b1ec89cerion                   binop(Iop_Or32,
2722d953ebb9b04cbad6891676df597bf0c542b1ec89cerion                         binop(Iop_Or32, FIELD(4), FIELD(5)),
2723d953ebb9b04cbad6891676df597bf0c542b1ec89cerion                         binop(Iop_Or32, FIELD(6), FIELD(7))
2724d953ebb9b04cbad6891676df597bf0c542b1ec89cerion                         )
2725d953ebb9b04cbad6891676df597bf0c542b1ec89cerion                   );
2726d953ebb9b04cbad6891676df597bf0c542b1ec89cerion#     undef FIELD
2727d953ebb9b04cbad6891676df597bf0c542b1ec89cerion   }
2728d953ebb9b04cbad6891676df597bf0c542b1ec89cerion
2729d953ebb9b04cbad6891676df597bf0c542b1ec89cerion   case PPC_GST_XER:
2730d953ebb9b04cbad6891676df597bf0c542b1ec89cerion      return binop(Iop_Or32,
2731d953ebb9b04cbad6891676df597bf0c542b1ec89cerion                   binop(Iop_Or32,
2732d953ebb9b04cbad6891676df597bf0c542b1ec89cerion                         binop( Iop_Shl32, getXER_SO32(), mkU8(31)),
2733d953ebb9b04cbad6891676df597bf0c542b1ec89cerion                         binop( Iop_Shl32, getXER_OV32(), mkU8(30))),
2734d953ebb9b04cbad6891676df597bf0c542b1ec89cerion                   binop(Iop_Or32,
2735d953ebb9b04cbad6891676df597bf0c542b1ec89cerion                         binop( Iop_Shl32, getXER_CA32(), mkU8(29)),
2736d953ebb9b04cbad6891676df597bf0c542b1ec89cerion                         getXER_BC32()));
2737d953ebb9b04cbad6891676df597bf0c542b1ec89cerion
27388943d02aa373f45c6e5fdcbe5947620285d442b1carll   case PPC_GST_TFHAR:
27398943d02aa373f45c6e5fdcbe5947620285d442b1carll      return IRExpr_Get( OFFB_TFHAR, ty );
27408943d02aa373f45c6e5fdcbe5947620285d442b1carll
27418943d02aa373f45c6e5fdcbe5947620285d442b1carll   case PPC_GST_TEXASR:
27428943d02aa373f45c6e5fdcbe5947620285d442b1carll      return IRExpr_Get( OFFB_TEXASR, ty );
27438943d02aa373f45c6e5fdcbe5947620285d442b1carll
2744486db12d4767b5c2cc5ae764616e758f30ce21f5carll   case PPC_GST_TEXASRU:
2745486db12d4767b5c2cc5ae764616e758f30ce21f5carll      return IRExpr_Get( OFFB_TEXASRU, ty );
2746486db12d4767b5c2cc5ae764616e758f30ce21f5carll
27478943d02aa373f45c6e5fdcbe5947620285d442b1carll   case PPC_GST_TFIAR:
27488943d02aa373f45c6e5fdcbe5947620285d442b1carll      return IRExpr_Get( OFFB_TFIAR, ty );
27498943d02aa373f45c6e5fdcbe5947620285d442b1carll
2750d953ebb9b04cbad6891676df597bf0c542b1ec89cerion   default:
27515b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion      vex_printf("getGST(ppc): reg = %u", reg);
27525b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion      vpanic("getGST(ppc)");
2753d953ebb9b04cbad6891676df597bf0c542b1ec89cerion   }
2754d953ebb9b04cbad6891676df597bf0c542b1ec89cerion}
2755d953ebb9b04cbad6891676df597bf0c542b1ec89cerion
2756e14bb9f862843c6b804097c124961b5567ded4f1sewardj/* Get a masked word from the given reg */
2757d953ebb9b04cbad6891676df597bf0c542b1ec89cerionstatic IRExpr* /* ::Ity_I32 */ getGST_masked ( PPC_GST reg, UInt mask )
2758e14bb9f862843c6b804097c124961b5567ded4f1sewardj{
2759e14bb9f862843c6b804097c124961b5567ded4f1sewardj   IRTemp val = newTemp(Ity_I32);
2760d953ebb9b04cbad6891676df597bf0c542b1ec89cerion   vassert( reg < PPC_GST_MAX );
2761e14bb9f862843c6b804097c124961b5567ded4f1sewardj
2762e14bb9f862843c6b804097c124961b5567ded4f1sewardj   switch (reg) {
2763e14bb9f862843c6b804097c124961b5567ded4f1sewardj
2764d953ebb9b04cbad6891676df597bf0c542b1ec89cerion   case PPC_GST_FPSCR: {
27655b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion      /* Vex-generated code expects the FPSCR to be set as follows:
276676de5cf615380b23b4b5bcced6541233cd4a93a0cerion         all exceptions masked, round-to-nearest.
276776de5cf615380b23b4b5bcced6541233cd4a93a0cerion         This corresponds to a FPSCR value of 0x0. */
2768e14bb9f862843c6b804097c124961b5567ded4f1sewardj
2769c6bbd470e9bd9898b84959227a406d3972d95f3bsewardj      /* In the lower 32 bits of FPSCR, we're only keeping track of
2770c6bbd470e9bd9898b84959227a406d3972d95f3bsewardj       * the binary floating point rounding mode, so if the mask isn't
2771c6bbd470e9bd9898b84959227a406d3972d95f3bsewardj       * asking for this, just return 0x0.
2772c6bbd470e9bd9898b84959227a406d3972d95f3bsewardj       */
2773c6bbd470e9bd9898b84959227a406d3972d95f3bsewardj      if (mask & MASK_FPSCR_RN) {
2774c6bbd470e9bd9898b84959227a406d3972d95f3bsewardj         assign( val, unop( Iop_8Uto32, IRExpr_Get( OFFB_FPROUND, Ity_I8 ) ) );
2775e14bb9f862843c6b804097c124961b5567ded4f1sewardj      } else {
2776e14bb9f862843c6b804097c124961b5567ded4f1sewardj         assign( val, mkU32(0x0) );
2777e14bb9f862843c6b804097c124961b5567ded4f1sewardj      }
2778225a034683024109da729a4d2f080364b9485007cerion      break;
2779edf7fc572e2decb93e9143961e8739c8fe18899dcerion   }
2780e14bb9f862843c6b804097c124961b5567ded4f1sewardj
2781e14bb9f862843c6b804097c124961b5567ded4f1sewardj   default:
27825b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion      vex_printf("getGST_masked(ppc): reg = %u", reg);
27835b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion      vpanic("getGST_masked(ppc)");
2784e14bb9f862843c6b804097c124961b5567ded4f1sewardj   }
2785e14bb9f862843c6b804097c124961b5567ded4f1sewardj
2786e14bb9f862843c6b804097c124961b5567ded4f1sewardj   if (mask != 0xFFFFFFFF) {
2787e14bb9f862843c6b804097c124961b5567ded4f1sewardj      return binop(Iop_And32, mkexpr(val), mkU32(mask));
2788e14bb9f862843c6b804097c124961b5567ded4f1sewardj   } else {
2789e14bb9f862843c6b804097c124961b5567ded4f1sewardj      return mkexpr(val);
2790e14bb9f862843c6b804097c124961b5567ded4f1sewardj   }
2791e14bb9f862843c6b804097c124961b5567ded4f1sewardj}
2792e14bb9f862843c6b804097c124961b5567ded4f1sewardj
2793c6bbd470e9bd9898b84959227a406d3972d95f3bsewardj/* Get a masked word from the given reg */
2794c6bbd470e9bd9898b84959227a406d3972d95f3bsewardjstatic IRExpr* /* ::Ity_I32 */getGST_masked_upper(PPC_GST reg, ULong mask) {
2795c6bbd470e9bd9898b84959227a406d3972d95f3bsewardj   IRExpr * val;
2796c6bbd470e9bd9898b84959227a406d3972d95f3bsewardj   vassert( reg < PPC_GST_MAX );
2797c6bbd470e9bd9898b84959227a406d3972d95f3bsewardj
2798c6bbd470e9bd9898b84959227a406d3972d95f3bsewardj   switch (reg) {
2799c6bbd470e9bd9898b84959227a406d3972d95f3bsewardj
2800c6bbd470e9bd9898b84959227a406d3972d95f3bsewardj   case PPC_GST_FPSCR: {
2801c6bbd470e9bd9898b84959227a406d3972d95f3bsewardj      /* In the upper 32 bits of FPSCR, we're only keeping track
2802c6bbd470e9bd9898b84959227a406d3972d95f3bsewardj       * of the decimal floating point rounding mode, so if the mask
2803c6bbd470e9bd9898b84959227a406d3972d95f3bsewardj       * isn't asking for this, just return 0x0.
2804c6bbd470e9bd9898b84959227a406d3972d95f3bsewardj       */
2805c6bbd470e9bd9898b84959227a406d3972d95f3bsewardj      if (mask & MASK_FPSCR_DRN) {
2806c6bbd470e9bd9898b84959227a406d3972d95f3bsewardj         val = binop( Iop_And32,
2807c6bbd470e9bd9898b84959227a406d3972d95f3bsewardj                      unop( Iop_8Uto32, IRExpr_Get( OFFB_DFPROUND, Ity_I8 ) ),
2808c6bbd470e9bd9898b84959227a406d3972d95f3bsewardj                      unop( Iop_64HIto32, mkU64( mask ) ) );
2809c6bbd470e9bd9898b84959227a406d3972d95f3bsewardj      } else {
2810c6bbd470e9bd9898b84959227a406d3972d95f3bsewardj         val = mkU32( 0x0ULL );
2811c6bbd470e9bd9898b84959227a406d3972d95f3bsewardj      }
2812c6bbd470e9bd9898b84959227a406d3972d95f3bsewardj      break;
2813c6bbd470e9bd9898b84959227a406d3972d95f3bsewardj   }
2814c6bbd470e9bd9898b84959227a406d3972d95f3bsewardj
2815c6bbd470e9bd9898b84959227a406d3972d95f3bsewardj   default:
2816c6bbd470e9bd9898b84959227a406d3972d95f3bsewardj      vex_printf( "getGST_masked_upper(ppc): reg = %u", reg );
2817c6bbd470e9bd9898b84959227a406d3972d95f3bsewardj      vpanic( "getGST_masked_upper(ppc)" );
2818c6bbd470e9bd9898b84959227a406d3972d95f3bsewardj   }
2819c6bbd470e9bd9898b84959227a406d3972d95f3bsewardj   return val;
2820c6bbd470e9bd9898b84959227a406d3972d95f3bsewardj}
2821c6bbd470e9bd9898b84959227a406d3972d95f3bsewardj
2822c6bbd470e9bd9898b84959227a406d3972d95f3bsewardj
2823edf7fc572e2decb93e9143961e8739c8fe18899dcerion/* Fetch the specified REG[FLD] nibble (as per IBM/hardware notation)
2824edf7fc572e2decb93e9143961e8739c8fe18899dcerion   and return it at the bottom of an I32; the top 27 bits are
2825edf7fc572e2decb93e9143961e8739c8fe18899dcerion   guaranteed to be zero. */
2826d953ebb9b04cbad6891676df597bf0c542b1ec89cerionstatic IRExpr* /* ::Ity_I32 */ getGST_field ( PPC_GST reg, UInt fld )
2827edf7fc572e2decb93e9143961e8739c8fe18899dcerion{
282841a7b70f888cf73cf3da6a53b31937ce0d26e8f4sewardj   UInt shft, mask;
282941a7b70f888cf73cf3da6a53b31937ce0d26e8f4sewardj
2830edf7fc572e2decb93e9143961e8739c8fe18899dcerion   vassert( fld < 8 );
2831d953ebb9b04cbad6891676df597bf0c542b1ec89cerion   vassert( reg < PPC_GST_MAX );
2832edf7fc572e2decb93e9143961e8739c8fe18899dcerion
283341a7b70f888cf73cf3da6a53b31937ce0d26e8f4sewardj   shft = 4*(7-fld);
283441a7b70f888cf73cf3da6a53b31937ce0d26e8f4sewardj   mask = 0xF<<shft;
2835e14bb9f862843c6b804097c124961b5567ded4f1sewardj
2836edf7fc572e2decb93e9143961e8739c8fe18899dcerion   switch (reg) {
2837d953ebb9b04cbad6891676df597bf0c542b1ec89cerion   case PPC_GST_XER:
2838edf7fc572e2decb93e9143961e8739c8fe18899dcerion      vassert(fld ==7);
2839edf7fc572e2decb93e9143961e8739c8fe18899dcerion      return binop(Iop_Or32,
2840edf7fc572e2decb93e9143961e8739c8fe18899dcerion                   binop(Iop_Or32,
2841edf7fc572e2decb93e9143961e8739c8fe18899dcerion                         binop(Iop_Shl32, getXER_SO32(), mkU8(3)),
2842edf7fc572e2decb93e9143961e8739c8fe18899dcerion                         binop(Iop_Shl32, getXER_OV32(), mkU8(2))),
2843edf7fc572e2decb93e9143961e8739c8fe18899dcerion                   binop(      Iop_Shl32, getXER_CA32(), mkU8(1)));
2844edf7fc572e2decb93e9143961e8739c8fe18899dcerion      break;
2845e14bb9f862843c6b804097c124961b5567ded4f1sewardj
2846edf7fc572e2decb93e9143961e8739c8fe18899dcerion   default:
2847edf7fc572e2decb93e9143961e8739c8fe18899dcerion      if (shft == 0)
2848d953ebb9b04cbad6891676df597bf0c542b1ec89cerion         return getGST_masked( reg, mask );
2849edf7fc572e2decb93e9143961e8739c8fe18899dcerion      else
2850edf7fc572e2decb93e9143961e8739c8fe18899dcerion         return binop(Iop_Shr32,
2851d953ebb9b04cbad6891676df597bf0c542b1ec89cerion                      getGST_masked( reg, mask ),
2852edf7fc572e2decb93e9143961e8739c8fe18899dcerion                      mkU8(toUChar( shft )));
2853edf7fc572e2decb93e9143961e8739c8fe18899dcerion   }
2854edf7fc572e2decb93e9143961e8739c8fe18899dcerion}
2855edf7fc572e2decb93e9143961e8739c8fe18899dcerion
2856d953ebb9b04cbad6891676df597bf0c542b1ec89cerionstatic void putGST ( PPC_GST reg, IRExpr* src )
2857edf7fc572e2decb93e9143961e8739c8fe18899dcerion{
28585b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion   IRType ty     = mode64 ? Ity_I64 : Ity_I32;
2859dd40fdf58cc8a6fe9466c4f00bdfc9fe9bf00449sewardj   IRType ty_src = typeOfIRExpr(irsb->tyenv,src );
2860d953ebb9b04cbad6891676df597bf0c542b1ec89cerion   vassert( reg < PPC_GST_MAX );
2861edf7fc572e2decb93e9143961e8739c8fe18899dcerion   switch (reg) {
2862e86310f555a233cc2ca02e1a5d0adb555f12bdcdsewardj   case PPC_GST_IP_AT_SYSCALL:
2863aca070a5b3418a6a9b01e3c57a7eb0fbb5050908sewardj      vassert( ty_src == ty );
2864e86310f555a233cc2ca02e1a5d0adb555f12bdcdsewardj      stmt( IRStmt_Put( OFFB_IP_AT_SYSCALL, src ) );
2865aca070a5b3418a6a9b01e3c57a7eb0fbb5050908sewardj      break;
2866d953ebb9b04cbad6891676df597bf0c542b1ec89cerion   case PPC_GST_CIA:
28675b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion      vassert( ty_src == ty );
28685b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion      stmt( IRStmt_Put( OFFB_CIA, src ) );
2869d953ebb9b04cbad6891676df597bf0c542b1ec89cerion      break;
2870d953ebb9b04cbad6891676df597bf0c542b1ec89cerion   case PPC_GST_LR:
28715b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion      vassert( ty_src == ty );
28725b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion      stmt( IRStmt_Put( OFFB_LR, src ) );
2873d953ebb9b04cbad6891676df597bf0c542b1ec89cerion      break;
2874d953ebb9b04cbad6891676df597bf0c542b1ec89cerion   case PPC_GST_CTR:
28755b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion      vassert( ty_src == ty );
28765b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion      stmt( IRStmt_Put( OFFB_CTR, src ) );
2877d953ebb9b04cbad6891676df597bf0c542b1ec89cerion      break;
2878d953ebb9b04cbad6891676df597bf0c542b1ec89cerion   case PPC_GST_VRSAVE:
28795b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion      vassert( ty_src == Ity_I32 );
28805b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion      stmt( IRStmt_Put( OFFB_VRSAVE,src));
2881d953ebb9b04cbad6891676df597bf0c542b1ec89cerion      break;
2882d953ebb9b04cbad6891676df597bf0c542b1ec89cerion   case PPC_GST_VSCR:
28835b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion      vassert( ty_src == Ity_I32 );
28845b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion      stmt( IRStmt_Put( OFFB_VSCR,
2885d953ebb9b04cbad6891676df597bf0c542b1ec89cerion                        binop(Iop_And32, src,
2886d953ebb9b04cbad6891676df597bf0c542b1ec89cerion                              mkU32(MASK_VSCR_VALID)) ) );
2887d953ebb9b04cbad6891676df597bf0c542b1ec89cerion      break;
2888d953ebb9b04cbad6891676df597bf0c542b1ec89cerion   case PPC_GST_XER:
28895b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion      vassert( ty_src == Ity_I32 );
2890d953ebb9b04cbad6891676df597bf0c542b1ec89cerion      putXER_SO( unop(Iop_32to8, binop(Iop_Shr32, src, mkU8(31))) );
2891d953ebb9b04cbad6891676df597bf0c542b1ec89cerion      putXER_OV( unop(Iop_32to8, binop(Iop_Shr32, src, mkU8(30))) );
2892d953ebb9b04cbad6891676df597bf0c542b1ec89cerion      putXER_CA( unop(Iop_32to8, binop(Iop_Shr32, src, mkU8(29))) );
2893d953ebb9b04cbad6891676df597bf0c542b1ec89cerion      putXER_BC( unop(Iop_32to8, src) );
2894d953ebb9b04cbad6891676df597bf0c542b1ec89cerion      break;
2895d953ebb9b04cbad6891676df597bf0c542b1ec89cerion
2896d953ebb9b04cbad6891676df597bf0c542b1ec89cerion   case PPC_GST_EMWARN:
28975b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion      vassert( ty_src == Ity_I32 );
28986ef84bed9bb3af22060eb1759788034602bbcc88florian      stmt( IRStmt_Put( OFFB_EMNOTE,src) );
2899d953ebb9b04cbad6891676df597bf0c542b1ec89cerion      break;
2900d953ebb9b04cbad6891676df597bf0c542b1ec89cerion
290105f5e0172384dd2983fb16fbb7deebd74d71cd35sewardj   case PPC_GST_CMSTART:
29025b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion      vassert( ty_src == ty );
290305f5e0172384dd2983fb16fbb7deebd74d71cd35sewardj      stmt( IRStmt_Put( OFFB_CMSTART, src) );
2904d953ebb9b04cbad6891676df597bf0c542b1ec89cerion      break;
2905d953ebb9b04cbad6891676df597bf0c542b1ec89cerion
290605f5e0172384dd2983fb16fbb7deebd74d71cd35sewardj   case PPC_GST_CMLEN:
29075b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion      vassert( ty_src == ty );
290805f5e0172384dd2983fb16fbb7deebd74d71cd35sewardj      stmt( IRStmt_Put( OFFB_CMLEN, src) );
2909d953ebb9b04cbad6891676df597bf0c542b1ec89cerion      break;
2910d953ebb9b04cbad6891676df597bf0c542b1ec89cerion
29118943d02aa373f45c6e5fdcbe5947620285d442b1carll   case PPC_GST_TEXASR:
29128943d02aa373f45c6e5fdcbe5947620285d442b1carll      vassert( ty_src == Ity_I64 );
29138943d02aa373f45c6e5fdcbe5947620285d442b1carll      stmt( IRStmt_Put( OFFB_TEXASR, src ) );
29148943d02aa373f45c6e5fdcbe5947620285d442b1carll      break;
2915486db12d4767b5c2cc5ae764616e758f30ce21f5carll
2916486db12d4767b5c2cc5ae764616e758f30ce21f5carll   case PPC_GST_TEXASRU:
2917486db12d4767b5c2cc5ae764616e758f30ce21f5carll      vassert( ty_src == Ity_I32 );
2918486db12d4767b5c2cc5ae764616e758f30ce21f5carll      stmt( IRStmt_Put( OFFB_TEXASRU, src ) );
2919486db12d4767b5c2cc5ae764616e758f30ce21f5carll      break;
2920486db12d4767b5c2cc5ae764616e758f30ce21f5carll
29218943d02aa373f45c6e5fdcbe5947620285d442b1carll   case PPC_GST_TFIAR:
29228943d02aa373f45c6e5fdcbe5947620285d442b1carll      vassert( ty_src == Ity_I64 );
29238943d02aa373f45c6e5fdcbe5947620285d442b1carll      stmt( IRStmt_Put( OFFB_TFIAR, src ) );
29248943d02aa373f45c6e5fdcbe5947620285d442b1carll      break;
29258943d02aa373f45c6e5fdcbe5947620285d442b1carll   case PPC_GST_TFHAR:
29268943d02aa373f45c6e5fdcbe5947620285d442b1carll      vassert( ty_src == Ity_I64 );
29278943d02aa373f45c6e5fdcbe5947620285d442b1carll      stmt( IRStmt_Put( OFFB_TFHAR, src ) );
29288943d02aa373f45c6e5fdcbe5947620285d442b1carll      break;
2929edf7fc572e2decb93e9143961e8739c8fe18899dcerion   default:
29305b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion      vex_printf("putGST(ppc): reg = %u", reg);
29315b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion      vpanic("putGST(ppc)");
2932edf7fc572e2decb93e9143961e8739c8fe18899dcerion   }
2933edf7fc572e2decb93e9143961e8739c8fe18899dcerion}
2934e14bb9f862843c6b804097c124961b5567ded4f1sewardj
2935e14bb9f862843c6b804097c124961b5567ded4f1sewardj/* Write masked src to the given reg */
2936c6bbd470e9bd9898b84959227a406d3972d95f3bsewardjstatic void putGST_masked ( PPC_GST reg, IRExpr* src, ULong mask )
2937e14bb9f862843c6b804097c124961b5567ded4f1sewardj{
2938d953ebb9b04cbad6891676df597bf0c542b1ec89cerion   IRType ty = mode64 ? Ity_I64 : Ity_I32;
2939d953ebb9b04cbad6891676df597bf0c542b1ec89cerion   vassert( reg < PPC_GST_MAX );
2940c6bbd470e9bd9898b84959227a406d3972d95f3bsewardj   vassert( typeOfIRExpr( irsb->tyenv,src ) == Ity_I64 );
2941c6bbd470e9bd9898b84959227a406d3972d95f3bsewardj
2942e14bb9f862843c6b804097c124961b5567ded4f1sewardj   switch (reg) {
2943d953ebb9b04cbad6891676df597bf0c542b1ec89cerion   case PPC_GST_FPSCR: {
2944c6bbd470e9bd9898b84959227a406d3972d95f3bsewardj      /* Allow writes to either binary or decimal floating point
2945150794d0aae744f36797e7727cfbbfc44a980bb5sewardj         Rounding Mode.
2946150794d0aae744f36797e7727cfbbfc44a980bb5sewardj      */
2947150794d0aae744f36797e7727cfbbfc44a980bb5sewardj      /* If any part of |mask| covers FPSCR.RN, update the bits of
2948150794d0aae744f36797e7727cfbbfc44a980bb5sewardj         FPSCR.RN by copying in |src| for locations where the
2949150794d0aae744f36797e7727cfbbfc44a980bb5sewardj         corresponding bit in |mask| is 1, and leaving it unchanged
2950150794d0aae744f36797e7727cfbbfc44a980bb5sewardj         for corresponding |mask| zero bits. */
2951c6bbd470e9bd9898b84959227a406d3972d95f3bsewardj      if (mask & MASK_FPSCR_RN) {
2952150794d0aae744f36797e7727cfbbfc44a980bb5sewardj         stmt(
2953150794d0aae744f36797e7727cfbbfc44a980bb5sewardj            IRStmt_Put(
2954150794d0aae744f36797e7727cfbbfc44a980bb5sewardj               OFFB_FPROUND,
2955150794d0aae744f36797e7727cfbbfc44a980bb5sewardj               unop(
2956150794d0aae744f36797e7727cfbbfc44a980bb5sewardj                  Iop_32to8,
2957150794d0aae744f36797e7727cfbbfc44a980bb5sewardj                  binop(
2958150794d0aae744f36797e7727cfbbfc44a980bb5sewardj                     Iop_Or32,
2959150794d0aae744f36797e7727cfbbfc44a980bb5sewardj                     binop(
2960150794d0aae744f36797e7727cfbbfc44a980bb5sewardj                        Iop_And32,
2961150794d0aae744f36797e7727cfbbfc44a980bb5sewardj                        unop(Iop_64to32, src),
2962150794d0aae744f36797e7727cfbbfc44a980bb5sewardj                        mkU32(MASK_FPSCR_RN & mask)
2963150794d0aae744f36797e7727cfbbfc44a980bb5sewardj                     ),
2964150794d0aae744f36797e7727cfbbfc44a980bb5sewardj                     binop(
2965150794d0aae744f36797e7727cfbbfc44a980bb5sewardj                        Iop_And32,
2966150794d0aae744f36797e7727cfbbfc44a980bb5sewardj                        unop(Iop_8Uto32, IRExpr_Get(OFFB_FPROUND,Ity_I8)),
2967150794d0aae744f36797e7727cfbbfc44a980bb5sewardj                        mkU32(MASK_FPSCR_RN & ~mask)
2968150794d0aae744f36797e7727cfbbfc44a980bb5sewardj                     )
2969150794d0aae744f36797e7727cfbbfc44a980bb5sewardj                  )
2970150794d0aae744f36797e7727cfbbfc44a980bb5sewardj               )
2971150794d0aae744f36797e7727cfbbfc44a980bb5sewardj            )
2972150794d0aae744f36797e7727cfbbfc44a980bb5sewardj         );
2973150794d0aae744f36797e7727cfbbfc44a980bb5sewardj      }
2974150794d0aae744f36797e7727cfbbfc44a980bb5sewardj      /* Similarly, update FPSCR.DRN if any bits of |mask|
2975150794d0aae744f36797e7727cfbbfc44a980bb5sewardj         corresponding to FPSCR.DRN are set. */
2976150794d0aae744f36797e7727cfbbfc44a980bb5sewardj      if (mask & MASK_FPSCR_DRN) {
2977150794d0aae744f36797e7727cfbbfc44a980bb5sewardj         stmt(
2978150794d0aae744f36797e7727cfbbfc44a980bb5sewardj            IRStmt_Put(
2979150794d0aae744f36797e7727cfbbfc44a980bb5sewardj               OFFB_DFPROUND,
2980150794d0aae744f36797e7727cfbbfc44a980bb5sewardj               unop(
2981150794d0aae744f36797e7727cfbbfc44a980bb5sewardj                  Iop_32to8,
2982150794d0aae744f36797e7727cfbbfc44a980bb5sewardj                  binop(
2983150794d0aae744f36797e7727cfbbfc44a980bb5sewardj                     Iop_Or32,
2984150794d0aae744f36797e7727cfbbfc44a980bb5sewardj                     binop(
2985150794d0aae744f36797e7727cfbbfc44a980bb5sewardj                        Iop_And32,
2986150794d0aae744f36797e7727cfbbfc44a980bb5sewardj                        unop(Iop_64HIto32, src),
2987150794d0aae744f36797e7727cfbbfc44a980bb5sewardj                        mkU32((MASK_FPSCR_DRN & mask) >> 32)
2988150794d0aae744f36797e7727cfbbfc44a980bb5sewardj                     ),
2989150794d0aae744f36797e7727cfbbfc44a980bb5sewardj                     binop(
2990150794d0aae744f36797e7727cfbbfc44a980bb5sewardj                        Iop_And32,
2991150794d0aae744f36797e7727cfbbfc44a980bb5sewardj                        unop(Iop_8Uto32, IRExpr_Get(OFFB_DFPROUND,Ity_I8)),
2992150794d0aae744f36797e7727cfbbfc44a980bb5sewardj                        mkU32((MASK_FPSCR_DRN & ~mask) >> 32)
2993150794d0aae744f36797e7727cfbbfc44a980bb5sewardj                     )
2994150794d0aae744f36797e7727cfbbfc44a980bb5sewardj                  )
2995150794d0aae744f36797e7727cfbbfc44a980bb5sewardj               )
2996150794d0aae744f36797e7727cfbbfc44a980bb5sewardj            )
2997150794d0aae744f36797e7727cfbbfc44a980bb5sewardj         );
2998e14bb9f862843c6b804097c124961b5567ded4f1sewardj      }
2999e14bb9f862843c6b804097c124961b5567ded4f1sewardj
30006ef84bed9bb3af22060eb1759788034602bbcc88florian      /* Give EmNote for attempted writes to:
3001e14bb9f862843c6b804097c124961b5567ded4f1sewardj         - Exception Controls
3002e14bb9f862843c6b804097c124961b5567ded4f1sewardj         - Non-IEEE Mode
3003e14bb9f862843c6b804097c124961b5567ded4f1sewardj      */
3004e14bb9f862843c6b804097c124961b5567ded4f1sewardj      if (mask & 0xFC) {  // Exception Control, Non-IEE mode
30056ef84bed9bb3af22060eb1759788034602bbcc88florian         VexEmNote ew = EmWarn_PPCexns;
3006e14bb9f862843c6b804097c124961b5567ded4f1sewardj
3007e14bb9f862843c6b804097c124961b5567ded4f1sewardj         /* If any of the src::exception_control bits are actually set,
3008e14bb9f862843c6b804097c124961b5567ded4f1sewardj            side-exit to the next insn, reporting the warning,
3009e14bb9f862843c6b804097c124961b5567ded4f1sewardj            so that Valgrind's dispatcher sees the warning. */
3010d953ebb9b04cbad6891676df597bf0c542b1ec89cerion         putGST( PPC_GST_EMWARN, mkU32(ew) );
3011e14bb9f862843c6b804097c124961b5567ded4f1sewardj         stmt(
3012e14bb9f862843c6b804097c124961b5567ded4f1sewardj            IRStmt_Exit(
30136ef84bed9bb3af22060eb1759788034602bbcc88florian               binop(Iop_CmpNE32, mkU32(ew), mkU32(EmNote_NONE)),
3014e14bb9f862843c6b804097c124961b5567ded4f1sewardj               Ijk_EmWarn,
30153dee849ec7c38746749065e67dc53b75daa7617dsewardj               mkSzConst( ty, nextInsnAddr()), OFFB_CIA ));
3016e14bb9f862843c6b804097c124961b5567ded4f1sewardj      }
3017e14bb9f862843c6b804097c124961b5567ded4f1sewardj
3018edf7fc572e2decb93e9143961e8739c8fe18899dcerion      /* Ignore all other writes */
3019e14bb9f862843c6b804097c124961b5567ded4f1sewardj      break;
3020edf7fc572e2decb93e9143961e8739c8fe18899dcerion   }
3021e14bb9f862843c6b804097c124961b5567ded4f1sewardj
3022edf7fc572e2decb93e9143961e8739c8fe18899dcerion   default:
30235b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion      vex_printf("putGST_masked(ppc): reg = %u", reg);
30245b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion      vpanic("putGST_masked(ppc)");
3025edf7fc572e2decb93e9143961e8739c8fe18899dcerion   }
3026edf7fc572e2decb93e9143961e8739c8fe18899dcerion}
3027225a034683024109da729a4d2f080364b9485007cerion
3028edf7fc572e2decb93e9143961e8739c8fe18899dcerion/* Write the least significant nibble of src to the specified
3029edf7fc572e2decb93e9143961e8739c8fe18899dcerion   REG[FLD] (as per IBM/hardware notation). */
3030d953ebb9b04cbad6891676df597bf0c542b1ec89cerionstatic void putGST_field ( PPC_GST reg, IRExpr* src, UInt fld )
3031edf7fc572e2decb93e9143961e8739c8fe18899dcerion{
3032c6bbd470e9bd9898b84959227a406d3972d95f3bsewardj   UInt shft;
3033c6bbd470e9bd9898b84959227a406d3972d95f3bsewardj   ULong mask;
303441a7b70f888cf73cf3da6a53b31937ce0d26e8f4sewardj
3035dd40fdf58cc8a6fe9466c4f00bdfc9fe9bf00449sewardj   vassert( typeOfIRExpr(irsb->tyenv,src ) == Ity_I32 );
3036c6bbd470e9bd9898b84959227a406d3972d95f3bsewardj   vassert( fld < 16 );
3037d953ebb9b04cbad6891676df597bf0c542b1ec89cerion   vassert( reg < PPC_GST_MAX );
3038edf7fc572e2decb93e9143961e8739c8fe18899dcerion
3039c6bbd470e9bd9898b84959227a406d3972d95f3bsewardj   if (fld < 8)
3040c6bbd470e9bd9898b84959227a406d3972d95f3bsewardj      shft = 4*(7-fld);
3041c6bbd470e9bd9898b84959227a406d3972d95f3bsewardj   else
3042c6bbd470e9bd9898b84959227a406d3972d95f3bsewardj      shft = 4*(15-fld);
3043654b7f977db549c2365a5d95f774db0748c0d29aflorian   mask = 0xF;
3044654b7f977db549c2365a5d95f774db0748c0d29aflorian   mask = mask << shft;
3045edf7fc572e2decb93e9143961e8739c8fe18899dcerion
3046edf7fc572e2decb93e9143961e8739c8fe18899dcerion   switch (reg) {
3047d953ebb9b04cbad6891676df597bf0c542b1ec89cerion   case PPC_GST_CR:
3048edf7fc572e2decb93e9143961e8739c8fe18899dcerion      putCR0  (fld, binop(Iop_And8, mkU8(1   ), unop(Iop_32to8, src)));
3049edf7fc572e2decb93e9143961e8739c8fe18899dcerion      putCR321(fld, binop(Iop_And8, mkU8(7<<1), unop(Iop_32to8, src)));
3050225a034683024109da729a4d2f080364b9485007cerion      break;
3051e14bb9f862843c6b804097c124961b5567ded4f1sewardj
3052e14bb9f862843c6b804097c124961b5567ded4f1sewardj   default:
3053c6bbd470e9bd9898b84959227a406d3972d95f3bsewardj      {
3054c6bbd470e9bd9898b84959227a406d3972d95f3bsewardj         IRExpr * src64 = unop( Iop_32Uto64, src );
3055c6bbd470e9bd9898b84959227a406d3972d95f3bsewardj
3056c6bbd470e9bd9898b84959227a406d3972d95f3bsewardj         if (shft == 0) {
3057c6bbd470e9bd9898b84959227a406d3972d95f3bsewardj            putGST_masked( reg, src64, mask );
3058c6bbd470e9bd9898b84959227a406d3972d95f3bsewardj         } else {
3059c6bbd470e9bd9898b84959227a406d3972d95f3bsewardj            putGST_masked( reg,
3060c6bbd470e9bd9898b84959227a406d3972d95f3bsewardj                           binop( Iop_Shl64, src64, mkU8( toUChar( shft ) ) ),
3061c6bbd470e9bd9898b84959227a406d3972d95f3bsewardj                           mask );
3062c6bbd470e9bd9898b84959227a406d3972d95f3bsewardj         }
3063edf7fc572e2decb93e9143961e8739c8fe18899dcerion      }
3064e14bb9f862843c6b804097c124961b5567ded4f1sewardj   }
3065e14bb9f862843c6b804097c124961b5567ded4f1sewardj}
3066e14bb9f862843c6b804097c124961b5567ded4f1sewardj
306766d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj/*------------------------------------------------------------*/
306866d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj/* Helpers for VSX instructions that do floating point
306966d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj * operations and need to determine if a src contains a
307066d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj * special FP value.
307166d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj *
307266d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj *------------------------------------------------------------*/
307366d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj
307466d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj#define NONZERO_FRAC_MASK 0x000fffffffffffffULL
307566d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj#define FP_FRAC_PART(x) binop( Iop_And64, \
307666d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj                               mkexpr( x ), \
307766d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj                               mkU64( NONZERO_FRAC_MASK ) )
307866d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj
3079e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj// Returns exponent part of a single precision floating point as I32
3080e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardjstatic IRExpr * fp_exp_part_sp(IRTemp src)
3081e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj{
3082e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj   return binop( Iop_And32,
3083e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj                 binop( Iop_Shr32, mkexpr( src ), mkU8( 23 ) ),
3084e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj                 mkU32( 0xff ) );
3085e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj}
3086e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj
308766d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj// Returns exponent part of floating point as I32
3088e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardjstatic IRExpr * fp_exp_part(IRTemp src, Bool sp)
308966d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj{
309066d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj   IRExpr * exp;
3091e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj   if (sp)
3092e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj      return fp_exp_part_sp(src);
3093e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj
309466d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj   if (!mode64)
309566d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj      exp = binop( Iop_And32, binop( Iop_Shr32, unop( Iop_64HIto32,
309666d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj                                                      mkexpr( src ) ),
309766d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj                                     mkU8( 20 ) ), mkU32( 0x7ff ) );
309866d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj   else
309966d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj      exp = unop( Iop_64to32,
310066d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj                  binop( Iop_And64,
310166d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj                         binop( Iop_Shr64, mkexpr( src ), mkU8( 52 ) ),
310266d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj                         mkU64( 0x7ff ) ) );
310366d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj   return exp;
310466d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj}
310566d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj
3106e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardjstatic IRExpr * is_Inf_sp(IRTemp src)
3107e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj{
3108e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj   IRTemp frac_part = newTemp(Ity_I32);
3109e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj   IRExpr * Inf_exp;
3110e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj
3111e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj   assign( frac_part, binop( Iop_And32, mkexpr(src), mkU32(0x007fffff)) );
3112e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj   Inf_exp = binop( Iop_CmpEQ32, fp_exp_part( src, True /*single precision*/ ), mkU32( 0xff ) );
3113e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj   return mkAND1( Inf_exp, binop( Iop_CmpEQ32, mkexpr( frac_part ), mkU32( 0 ) ) );
3114e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj}
3115e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj
311666d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj
311766d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj// Infinity: exp = 7ff and fraction is zero; s = 0/1
3118e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardjstatic IRExpr * is_Inf(IRTemp src, Bool sp)
311966d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj{
312066d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj   IRExpr * Inf_exp, * hi32, * low32;
3121e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj   IRTemp frac_part;
312266d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj
3123e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj   if (sp)
3124e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj      return is_Inf_sp(src);
3125e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj
3126e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj   frac_part = newTemp(Ity_I64);
312766d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj   assign( frac_part, FP_FRAC_PART(src) );
3128e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj   Inf_exp = binop( Iop_CmpEQ32, fp_exp_part( src, False /*not single precision*/  ), mkU32( 0x7ff ) );
312966d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj   hi32 = unop( Iop_64HIto32, mkexpr( frac_part ) );
313066d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj   low32 = unop( Iop_64to32, mkexpr( frac_part ) );
313166d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj   return mkAND1( Inf_exp, binop( Iop_CmpEQ32, binop( Iop_Or32, low32, hi32 ),
313266d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj                                  mkU32( 0 ) ) );
313366d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj}
313466d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj
3135e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardjstatic IRExpr * is_Zero_sp(IRTemp src)
3136e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj{
3137e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj   IRTemp sign_less_part = newTemp(Ity_I32);
3138e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj   assign( sign_less_part, binop( Iop_And32, mkexpr( src ), mkU32( SIGN_MASK32 ) ) );
3139e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj   return binop( Iop_CmpEQ32, mkexpr( sign_less_part ), mkU32( 0 ) );
3140e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj}
3141e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj
314266d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj// Zero: exp is zero and fraction is zero; s = 0/1
3143e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardjstatic IRExpr * is_Zero(IRTemp src, Bool sp)
314466d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj{
314566d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj   IRExpr * hi32, * low32;
3146e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj   IRTemp sign_less_part;
3147e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj   if (sp)
3148e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj      return is_Zero_sp(src);
3149e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj
3150e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj   sign_less_part = newTemp(Ity_I64);
315166d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj
315266d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj   assign( sign_less_part, binop( Iop_And64, mkexpr( src ), mkU64( SIGN_MASK ) ) );
315366d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj   hi32 = unop( Iop_64HIto32, mkexpr( sign_less_part ) );
315466d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj   low32 = unop( Iop_64to32, mkexpr( sign_less_part ) );
315566d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj   return binop( Iop_CmpEQ32, binop( Iop_Or32, low32, hi32 ),
315666d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj                              mkU32( 0 ) );
315766d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj}
315866d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj
315966d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj/*  SNAN: s = 1/0; exp = 0x7ff; fraction is nonzero, with highest bit '1'
316066d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj *  QNAN: s = 1/0; exp = 0x7ff; fraction is nonzero, with highest bit '0'
316166d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj *  This function returns an IRExpr value of '1' for any type of NaN.
316266d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj */
316366d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardjstatic IRExpr * is_NaN(IRTemp src)
316466d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj{
316566d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj   IRExpr * NaN_exp, * hi32, * low32;
316666d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj   IRTemp frac_part = newTemp(Ity_I64);
316766d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj
316866d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj   assign( frac_part, FP_FRAC_PART(src) );
316966d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj   hi32 = unop( Iop_64HIto32, mkexpr( frac_part ) );
317066d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj   low32 = unop( Iop_64to32, mkexpr( frac_part ) );
3171e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj   NaN_exp = binop( Iop_CmpEQ32, fp_exp_part( src, False /*not single precision*/ ),
3172e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj                    mkU32( 0x7ff ) );
317366d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj
317466d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj   return mkAND1( NaN_exp, binop( Iop_CmpNE32, binop( Iop_Or32, low32, hi32 ),
317566d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj                                               mkU32( 0 ) ) );
317666d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj}
31770e2cc67b30d1bb4d0515a1e09d944143becb3881sewardj
31784aa412af1d8166cc11f39a6e721df49431d23618sewardj/* This function returns an IRExpr value of '1' for any type of NaN.
31794aa412af1d8166cc11f39a6e721df49431d23618sewardj * The passed 'src' argument is assumed to be Ity_I32.
31804aa412af1d8166cc11f39a6e721df49431d23618sewardj */
31814aa412af1d8166cc11f39a6e721df49431d23618sewardjstatic IRExpr * is_NaN_32(IRTemp src)
31824aa412af1d8166cc11f39a6e721df49431d23618sewardj{
31834aa412af1d8166cc11f39a6e721df49431d23618sewardj#define NONZERO_FRAC_MASK32 0x007fffffULL
31844aa412af1d8166cc11f39a6e721df49431d23618sewardj#define FP_FRAC_PART32(x) binop( Iop_And32, \
31854aa412af1d8166cc11f39a6e721df49431d23618sewardj                                 mkexpr( x ), \
31864aa412af1d8166cc11f39a6e721df49431d23618sewardj                                 mkU32( NONZERO_FRAC_MASK32 ) )
31874aa412af1d8166cc11f39a6e721df49431d23618sewardj
31884aa412af1d8166cc11f39a6e721df49431d23618sewardj   IRExpr * frac_part = FP_FRAC_PART32(src);
31894aa412af1d8166cc11f39a6e721df49431d23618sewardj   IRExpr * exp_part = binop( Iop_And32,
31904aa412af1d8166cc11f39a6e721df49431d23618sewardj                              binop( Iop_Shr32, mkexpr( src ), mkU8( 23 ) ),
31914aa412af1d8166cc11f39a6e721df49431d23618sewardj                              mkU32( 0x0ff ) );
31924aa412af1d8166cc11f39a6e721df49431d23618sewardj   IRExpr * NaN_exp = binop( Iop_CmpEQ32, exp_part, mkU32( 0xff ) );
31934aa412af1d8166cc11f39a6e721df49431d23618sewardj
31944aa412af1d8166cc11f39a6e721df49431d23618sewardj   return mkAND1( NaN_exp, binop( Iop_CmpNE32, frac_part, mkU32( 0 ) ) );
31954aa412af1d8166cc11f39a6e721df49431d23618sewardj}
31964aa412af1d8166cc11f39a6e721df49431d23618sewardj
31976fef87a15cd79526ece8c38798e2d304b805a1f3carll/* This function takes an Ity_I32 input argument interpreted
31986fef87a15cd79526ece8c38798e2d304b805a1f3carll * as a single-precision floating point value. If src is a
31996fef87a15cd79526ece8c38798e2d304b805a1f3carll * SNaN, it is changed to a QNaN and returned; otherwise,
32006fef87a15cd79526ece8c38798e2d304b805a1f3carll * the original value is returned.
32016fef87a15cd79526ece8c38798e2d304b805a1f3carll */
32026fef87a15cd79526ece8c38798e2d304b805a1f3carllstatic IRExpr * handle_SNaN_to_QNaN_32(IRExpr * src)
32036fef87a15cd79526ece8c38798e2d304b805a1f3carll{
32046fef87a15cd79526ece8c38798e2d304b805a1f3carll#define SNAN_MASK32 0x00400000
32056fef87a15cd79526ece8c38798e2d304b805a1f3carll   IRTemp tmp = newTemp(Ity_I32);
32066fef87a15cd79526ece8c38798e2d304b805a1f3carll   IRTemp mask = newTemp(Ity_I32);
32076fef87a15cd79526ece8c38798e2d304b805a1f3carll   IRTemp is_SNAN = newTemp(Ity_I1);
32086fef87a15cd79526ece8c38798e2d304b805a1f3carll
32096fef87a15cd79526ece8c38798e2d304b805a1f3carll   vassert( typeOfIRExpr(irsb->tyenv, src ) == Ity_I32 );
32106fef87a15cd79526ece8c38798e2d304b805a1f3carll   assign(tmp, src);
32116fef87a15cd79526ece8c38798e2d304b805a1f3carll
32126fef87a15cd79526ece8c38798e2d304b805a1f3carll   /* check if input is SNaN, if it is convert to QNaN */
32136fef87a15cd79526ece8c38798e2d304b805a1f3carll   assign( is_SNAN,
32146fef87a15cd79526ece8c38798e2d304b805a1f3carll           mkAND1( is_NaN_32( tmp ),
32156fef87a15cd79526ece8c38798e2d304b805a1f3carll                   binop( Iop_CmpEQ32,
32166fef87a15cd79526ece8c38798e2d304b805a1f3carll                          binop( Iop_And32, mkexpr( tmp ),
32176fef87a15cd79526ece8c38798e2d304b805a1f3carll                                 mkU32( SNAN_MASK32 ) ),
32186fef87a15cd79526ece8c38798e2d304b805a1f3carll                          mkU32( 0 ) ) ) );
32196fef87a15cd79526ece8c38798e2d304b805a1f3carll   /* create mask with QNaN bit set to make it a QNaN if tmp is SNaN */
32206fef87a15cd79526ece8c38798e2d304b805a1f3carll   assign ( mask, binop( Iop_And32,
32216fef87a15cd79526ece8c38798e2d304b805a1f3carll                         unop( Iop_1Sto32, mkexpr( is_SNAN ) ),
32226fef87a15cd79526ece8c38798e2d304b805a1f3carll                         mkU32( SNAN_MASK32 ) ) );
32236fef87a15cd79526ece8c38798e2d304b805a1f3carll   return binop( Iop_Or32, mkexpr( mask ), mkexpr( tmp) );
32246fef87a15cd79526ece8c38798e2d304b805a1f3carll}
32256fef87a15cd79526ece8c38798e2d304b805a1f3carll
32266fef87a15cd79526ece8c38798e2d304b805a1f3carll
32274aa412af1d8166cc11f39a6e721df49431d23618sewardj/* This helper function performs the negation part of operations of the form:
32284aa412af1d8166cc11f39a6e721df49431d23618sewardj *    "Negate Multiply-<op>"
32294aa412af1d8166cc11f39a6e721df49431d23618sewardj *  where "<op>" is either "Add" or "Sub".
32304aa412af1d8166cc11f39a6e721df49431d23618sewardj *
32314aa412af1d8166cc11f39a6e721df49431d23618sewardj * This function takes one argument -- the floating point intermediate result (converted to
32324aa412af1d8166cc11f39a6e721df49431d23618sewardj * Ity_I64 via Iop_ReinterpF64asI64) that was obtained from the "Multip-<op>" part of
32334aa412af1d8166cc11f39a6e721df49431d23618sewardj * the operation described above.
32344aa412af1d8166cc11f39a6e721df49431d23618sewardj */
32354aa412af1d8166cc11f39a6e721df49431d23618sewardjstatic IRTemp getNegatedResult(IRTemp intermediateResult)
32364aa412af1d8166cc11f39a6e721df49431d23618sewardj{
32374aa412af1d8166cc11f39a6e721df49431d23618sewardj   ULong signbit_mask = 0x8000000000000000ULL;
32384aa412af1d8166cc11f39a6e721df49431d23618sewardj   IRTemp signbit_32 = newTemp(Ity_I32);
32394aa412af1d8166cc11f39a6e721df49431d23618sewardj   IRTemp resultantSignbit = newTemp(Ity_I1);
32404aa412af1d8166cc11f39a6e721df49431d23618sewardj   IRTemp negatedResult = newTemp(Ity_I64);
32414aa412af1d8166cc11f39a6e721df49431d23618sewardj   assign( signbit_32, binop( Iop_Shr32,
32424aa412af1d8166cc11f39a6e721df49431d23618sewardj                          unop( Iop_64HIto32,
32434aa412af1d8166cc11f39a6e721df49431d23618sewardj                                 binop( Iop_And64, mkexpr( intermediateResult ),
32444aa412af1d8166cc11f39a6e721df49431d23618sewardj                                        mkU64( signbit_mask ) ) ),
32454aa412af1d8166cc11f39a6e721df49431d23618sewardj                                 mkU8( 31 ) ) );
32464aa412af1d8166cc11f39a6e721df49431d23618sewardj   /* We negate the signbit if and only if the intermediate result from the
32474aa412af1d8166cc11f39a6e721df49431d23618sewardj    * multiply-<op> was NOT a NaN.  This is an XNOR predicate.
32484aa412af1d8166cc11f39a6e721df49431d23618sewardj    */
32494aa412af1d8166cc11f39a6e721df49431d23618sewardj   assign( resultantSignbit,
32504aa412af1d8166cc11f39a6e721df49431d23618sewardj        unop( Iop_Not1,
32514aa412af1d8166cc11f39a6e721df49431d23618sewardj              binop( Iop_CmpEQ32,
32524aa412af1d8166cc11f39a6e721df49431d23618sewardj                     binop( Iop_Xor32,
32534aa412af1d8166cc11f39a6e721df49431d23618sewardj                            mkexpr( signbit_32 ),
32544aa412af1d8166cc11f39a6e721df49431d23618sewardj                            unop( Iop_1Uto32, is_NaN( intermediateResult ) ) ),
32554aa412af1d8166cc11f39a6e721df49431d23618sewardj                     mkU32( 1 ) ) ) );
32564aa412af1d8166cc11f39a6e721df49431d23618sewardj
32574aa412af1d8166cc11f39a6e721df49431d23618sewardj   assign( negatedResult,
32584aa412af1d8166cc11f39a6e721df49431d23618sewardj        binop( Iop_Or64,
32594aa412af1d8166cc11f39a6e721df49431d23618sewardj               binop( Iop_And64,
32604aa412af1d8166cc11f39a6e721df49431d23618sewardj                      mkexpr( intermediateResult ),
32614aa412af1d8166cc11f39a6e721df49431d23618sewardj                      mkU64( ~signbit_mask ) ),
32624aa412af1d8166cc11f39a6e721df49431d23618sewardj               binop( Iop_32HLto64,
32634aa412af1d8166cc11f39a6e721df49431d23618sewardj                      binop( Iop_Shl32,
32644aa412af1d8166cc11f39a6e721df49431d23618sewardj                             unop( Iop_1Uto32, mkexpr( resultantSignbit ) ),
32654aa412af1d8166cc11f39a6e721df49431d23618sewardj                             mkU8( 31 ) ),
32664aa412af1d8166cc11f39a6e721df49431d23618sewardj                      mkU32( 0 ) ) ) );
32674aa412af1d8166cc11f39a6e721df49431d23618sewardj
32684aa412af1d8166cc11f39a6e721df49431d23618sewardj   return negatedResult;
32694aa412af1d8166cc11f39a6e721df49431d23618sewardj}
32704aa412af1d8166cc11f39a6e721df49431d23618sewardj
32714aa412af1d8166cc11f39a6e721df49431d23618sewardj/* This helper function performs the negation part of operations of the form:
32724aa412af1d8166cc11f39a6e721df49431d23618sewardj *    "Negate Multiply-<op>"
32734aa412af1d8166cc11f39a6e721df49431d23618sewardj *  where "<op>" is either "Add" or "Sub".
32744aa412af1d8166cc11f39a6e721df49431d23618sewardj *
32754aa412af1d8166cc11f39a6e721df49431d23618sewardj * This function takes one argument -- the floating point intermediate result (converted to
32764aa412af1d8166cc11f39a6e721df49431d23618sewardj * Ity_I32 via Iop_ReinterpF32asI32) that was obtained from the "Multip-<op>" part of
32774aa412af1d8166cc11f39a6e721df49431d23618sewardj * the operation described above.
32784aa412af1d8166cc11f39a6e721df49431d23618sewardj */
32794aa412af1d8166cc11f39a6e721df49431d23618sewardjstatic IRTemp getNegatedResult_32(IRTemp intermediateResult)
32804aa412af1d8166cc11f39a6e721df49431d23618sewardj{
32814aa412af1d8166cc11f39a6e721df49431d23618sewardj   UInt signbit_mask = 0x80000000;
32824aa412af1d8166cc11f39a6e721df49431d23618sewardj   IRTemp signbit_32 = newTemp(Ity_I32);
32834aa412af1d8166cc11f39a6e721df49431d23618sewardj   IRTemp resultantSignbit = newTemp(Ity_I1);
32844aa412af1d8166cc11f39a6e721df49431d23618sewardj   IRTemp negatedResult = newTemp(Ity_I32);
32854aa412af1d8166cc11f39a6e721df49431d23618sewardj   assign( signbit_32, binop( Iop_Shr32,
32864aa412af1d8166cc11f39a6e721df49431d23618sewardj                                 binop( Iop_And32, mkexpr( intermediateResult ),
32874aa412af1d8166cc11f39a6e721df49431d23618sewardj                                        mkU32( signbit_mask ) ),
32884aa412af1d8166cc11f39a6e721df49431d23618sewardj                                 mkU8( 31 ) ) );
32894aa412af1d8166cc11f39a6e721df49431d23618sewardj   /* We negate the signbit if and only if the intermediate result from the
32904aa412af1d8166cc11f39a6e721df49431d23618sewardj    * multiply-<op> was NOT a NaN.  This is an XNOR predicate.
32914aa412af1d8166cc11f39a6e721df49431d23618sewardj    */
32924aa412af1d8166cc11f39a6e721df49431d23618sewardj   assign( resultantSignbit,
32934aa412af1d8166cc11f39a6e721df49431d23618sewardj        unop( Iop_Not1,
32944aa412af1d8166cc11f39a6e721df49431d23618sewardj              binop( Iop_CmpEQ32,
32954aa412af1d8166cc11f39a6e721df49431d23618sewardj                     binop( Iop_Xor32,
32964aa412af1d8166cc11f39a6e721df49431d23618sewardj                            mkexpr( signbit_32 ),
32974aa412af1d8166cc11f39a6e721df49431d23618sewardj                            unop( Iop_1Uto32, is_NaN_32( intermediateResult ) ) ),
32984aa412af1d8166cc11f39a6e721df49431d23618sewardj                     mkU32( 1 ) ) ) );
32994aa412af1d8166cc11f39a6e721df49431d23618sewardj
33004aa412af1d8166cc11f39a6e721df49431d23618sewardj   assign( negatedResult,
33014aa412af1d8166cc11f39a6e721df49431d23618sewardj           binop( Iop_Or32,
33024aa412af1d8166cc11f39a6e721df49431d23618sewardj                  binop( Iop_And32,
33034aa412af1d8166cc11f39a6e721df49431d23618sewardj                         mkexpr( intermediateResult ),
33044aa412af1d8166cc11f39a6e721df49431d23618sewardj                         mkU32( ~signbit_mask ) ),
33054aa412af1d8166cc11f39a6e721df49431d23618sewardj                  binop( Iop_Shl32,
33064aa412af1d8166cc11f39a6e721df49431d23618sewardj                         unop( Iop_1Uto32, mkexpr( resultantSignbit ) ),
33074aa412af1d8166cc11f39a6e721df49431d23618sewardj                         mkU8( 31 ) ) ) );
33084aa412af1d8166cc11f39a6e721df49431d23618sewardj
33094aa412af1d8166cc11f39a6e721df49431d23618sewardj   return negatedResult;
33104aa412af1d8166cc11f39a6e721df49431d23618sewardj}
33113007c7fb4f226f2db7e250b0ebb114618ab1980ccerion
3312b51f0f4f33256638ed953156a2635aa739b232f1sewardj/*------------------------------------------------------------*/
33138943d02aa373f45c6e5fdcbe5947620285d442b1carll/* Transactional memory helpers
33148943d02aa373f45c6e5fdcbe5947620285d442b1carll *
33158943d02aa373f45c6e5fdcbe5947620285d442b1carll *------------------------------------------------------------*/
33168943d02aa373f45c6e5fdcbe5947620285d442b1carll
33178943d02aa373f45c6e5fdcbe5947620285d442b1carllstatic ULong generate_TMreason( UInt failure_code,
33188943d02aa373f45c6e5fdcbe5947620285d442b1carll                                             UInt persistant,
33198943d02aa373f45c6e5fdcbe5947620285d442b1carll                                             UInt nest_overflow,
33208943d02aa373f45c6e5fdcbe5947620285d442b1carll                                             UInt tm_exact )
33218943d02aa373f45c6e5fdcbe5947620285d442b1carll{
33228943d02aa373f45c6e5fdcbe5947620285d442b1carll   ULong tm_err_code =
33238943d02aa373f45c6e5fdcbe5947620285d442b1carll     ( (ULong) 0) << (63-6)   /* Failure code */
33248943d02aa373f45c6e5fdcbe5947620285d442b1carll     | ( (ULong) persistant) << (63-7)     /* Failure persistant */
33258943d02aa373f45c6e5fdcbe5947620285d442b1carll     | ( (ULong) 0) << (63-8)   /* Disallowed */
33268943d02aa373f45c6e5fdcbe5947620285d442b1carll     | ( (ULong) nest_overflow) << (63-9)   /* Nesting Overflow */
33278943d02aa373f45c6e5fdcbe5947620285d442b1carll     | ( (ULong) 0) << (63-10)  /* Footprint Overflow */
33288943d02aa373f45c6e5fdcbe5947620285d442b1carll     | ( (ULong) 0) << (63-11)  /* Self-Induced Conflict */
33298943d02aa373f45c6e5fdcbe5947620285d442b1carll     | ( (ULong) 0) << (63-12)  /* Non-Transactional Conflict */
33308943d02aa373f45c6e5fdcbe5947620285d442b1carll     | ( (ULong) 0) << (63-13)  /* Transactional Conflict */
33318943d02aa373f45c6e5fdcbe5947620285d442b1carll     | ( (ULong) 0) << (63-14)  /* Translation Invalidation Conflict */
33328943d02aa373f45c6e5fdcbe5947620285d442b1carll     | ( (ULong) 0) << (63-15)  /* Implementation-specific */
33338943d02aa373f45c6e5fdcbe5947620285d442b1carll     | ( (ULong) 0) << (63-16)  /* Instruction Fetch Conflict */
33348943d02aa373f45c6e5fdcbe5947620285d442b1carll     | ( (ULong) 0) << (63-30)  /* Reserved */
33358943d02aa373f45c6e5fdcbe5947620285d442b1carll     | ( (ULong) 0) << (63-31)  /* Abort */
33368943d02aa373f45c6e5fdcbe5947620285d442b1carll     | ( (ULong) 0) << (63-32)  /* Suspend */
33378943d02aa373f45c6e5fdcbe5947620285d442b1carll     | ( (ULong) 0) << (63-33)  /* Reserved */
33388943d02aa373f45c6e5fdcbe5947620285d442b1carll     | ( (ULong) 0) << (63-35)  /* Privilege */
33398943d02aa373f45c6e5fdcbe5947620285d442b1carll     | ( (ULong) 0) << (63-36)  /* Failure Summary */
33408943d02aa373f45c6e5fdcbe5947620285d442b1carll     | ( (ULong) tm_exact) << (63-37)  /* TFIAR Exact */
33418943d02aa373f45c6e5fdcbe5947620285d442b1carll     | ( (ULong) 0) << (63-38)  /* ROT */
33428943d02aa373f45c6e5fdcbe5947620285d442b1carll     | ( (ULong) 0) << (63-51)  /* Reserved */
33438943d02aa373f45c6e5fdcbe5947620285d442b1carll     | ( (ULong) 0) << (63-63);  /* Transaction Level */
33448943d02aa373f45c6e5fdcbe5947620285d442b1carll
33458943d02aa373f45c6e5fdcbe5947620285d442b1carll     return tm_err_code;
33468943d02aa373f45c6e5fdcbe5947620285d442b1carll}
33478943d02aa373f45c6e5fdcbe5947620285d442b1carll
33488943d02aa373f45c6e5fdcbe5947620285d442b1carllstatic void storeTMfailure( Addr64 err_address, ULong tm_reason,
33498943d02aa373f45c6e5fdcbe5947620285d442b1carll                            Addr64 handler_address )
33508943d02aa373f45c6e5fdcbe5947620285d442b1carll{
3351486db12d4767b5c2cc5ae764616e758f30ce21f5carll   putGST( PPC_GST_TFIAR,   mkU64( err_address ) );
3352486db12d4767b5c2cc5ae764616e758f30ce21f5carll   putGST( PPC_GST_TEXASR,  mkU64( tm_reason ) );
3353486db12d4767b5c2cc5ae764616e758f30ce21f5carll   putGST( PPC_GST_TEXASRU, mkU32( 0 ) );
3354486db12d4767b5c2cc5ae764616e758f30ce21f5carll   putGST( PPC_GST_TFHAR,   mkU64( handler_address ) );
33558943d02aa373f45c6e5fdcbe5947620285d442b1carll}
33568943d02aa373f45c6e5fdcbe5947620285d442b1carll
33578943d02aa373f45c6e5fdcbe5947620285d442b1carll/*------------------------------------------------------------*/
3358b51f0f4f33256638ed953156a2635aa739b232f1sewardj/*--- Integer Instruction Translation                     --- */
3359b51f0f4f33256638ed953156a2635aa739b232f1sewardj/*------------------------------------------------------------*/
33603007c7fb4f226f2db7e250b0ebb114618ab1980ccerion
3361b51f0f4f33256638ed953156a2635aa739b232f1sewardj/*
3362b51f0f4f33256638ed953156a2635aa739b232f1sewardj  Integer Arithmetic Instructions
3363b51f0f4f33256638ed953156a2635aa739b232f1sewardj*/
3364b51f0f4f33256638ed953156a2635aa739b232f1sewardjstatic Bool dis_int_arith ( UInt theInstr )
33657622226e8a2f15e2532a8cf5fb0e2f75a0aac128cerion{
336676de5cf615380b23b4b5bcced6541233cd4a93a0cerion   /* D-Form, XO-Form */
336776de5cf615380b23b4b5bcced6541233cd4a93a0cerion   UChar opc1    = ifieldOPC(theInstr);
336876de5cf615380b23b4b5bcced6541233cd4a93a0cerion   UChar rD_addr = ifieldRegDS(theInstr);
336976de5cf615380b23b4b5bcced6541233cd4a93a0cerion   UChar rA_addr = ifieldRegA(theInstr);
3370d953ebb9b04cbad6891676df597bf0c542b1ec89cerion   UInt  uimm16  = ifieldUIMM16(theInstr);
337176de5cf615380b23b4b5bcced6541233cd4a93a0cerion   UChar rB_addr = ifieldRegB(theInstr);
337276de5cf615380b23b4b5bcced6541233cd4a93a0cerion   UChar flag_OE = ifieldBIT10(theInstr);
337376de5cf615380b23b4b5bcced6541233cd4a93a0cerion   UInt  opc2    = ifieldOPClo9(theInstr);
337476de5cf615380b23b4b5bcced6541233cd4a93a0cerion   UChar flag_rC = ifieldBIT0(theInstr);
337576de5cf615380b23b4b5bcced6541233cd4a93a0cerion
3376d953ebb9b04cbad6891676df597bf0c542b1ec89cerion   Long   simm16 = extend_s_16to64(uimm16);
3377d953ebb9b04cbad6891676df597bf0c542b1ec89cerion   IRType ty     = mode64 ? Ity_I64 : Ity_I32;
3378d953ebb9b04cbad6891676df597bf0c542b1ec89cerion   IRTemp rA     = newTemp(ty);
3379d953ebb9b04cbad6891676df597bf0c542b1ec89cerion   IRTemp rB     = newTemp(ty);
3380d953ebb9b04cbad6891676df597bf0c542b1ec89cerion   IRTemp rD     = newTemp(ty);
338170e2412f623c955d7b199f09401732cf57417fc2cerion
3382b85e8bba97fdae7d892f7bfd12e4601307e4721dcerion   Bool do_rc = False;
3383b85e8bba97fdae7d892f7bfd12e4601307e4721dcerion
338476de5cf615380b23b4b5bcced6541233cd4a93a0cerion   assign( rA, getIReg(rA_addr) );
338576de5cf615380b23b4b5bcced6541233cd4a93a0cerion   assign( rB, getIReg(rB_addr) );         // XO-Form: rD, rA, rB
3386b51f0f4f33256638ed953156a2635aa739b232f1sewardj
3387b85e8bba97fdae7d892f7bfd12e4601307e4721dcerion   switch (opc1) {
3388b85e8bba97fdae7d892f7bfd12e4601307e4721dcerion   /* D-Form */
3389e9d361ab43518b6dfbd3d846f48859534659dee0cerion   case 0x0C: // addic  (Add Immediate Carrying, PPC32 p351
3390d953ebb9b04cbad6891676df597bf0c542b1ec89cerion      DIP("addic r%u,r%u,%d\n", rD_addr, rA_addr, (Int)simm16);
33912831b00c4950d6c2b061def05fd67528fe132ececerion      assign( rD, binop( mkSzOp(ty, Iop_Add8), mkexpr(rA),
33922831b00c4950d6c2b061def05fd67528fe132ececerion                         mkSzExtendS16(ty, uimm16) ) );
33935b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion      set_XER_CA( ty, PPCG_FLAG_OP_ADD,
33942831b00c4950d6c2b061def05fd67528fe132ececerion                  mkexpr(rD), mkexpr(rA), mkSzExtendS16(ty, uimm16),
33952831b00c4950d6c2b061def05fd67528fe132ececerion                  mkSzImm(ty, 0)/*old xer.ca, which is ignored*/ );
3396b85e8bba97fdae7d892f7bfd12e4601307e4721dcerion      break;
3397b51f0f4f33256638ed953156a2635aa739b232f1sewardj
3398e9d361ab43518b6dfbd3d846f48859534659dee0cerion   case 0x0D: // addic. (Add Immediate Carrying and Record, PPC32 p352)
3399d953ebb9b04cbad6891676df597bf0c542b1ec89cerion      DIP("addic. r%u,r%u,%d\n", rD_addr, rA_addr, (Int)simm16);
34002831b00c4950d6c2b061def05fd67528fe132ececerion      assign( rD, binop( mkSzOp(ty, Iop_Add8), mkexpr(rA),
34012831b00c4950d6c2b061def05fd67528fe132ececerion                         mkSzExtendS16(ty, uimm16) ) );
34025b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion      set_XER_CA( ty, PPCG_FLAG_OP_ADD,
34032831b00c4950d6c2b061def05fd67528fe132ececerion                  mkexpr(rD), mkexpr(rA), mkSzExtendS16(ty, uimm16),
34042831b00c4950d6c2b061def05fd67528fe132ececerion                  mkSzImm(ty, 0)/*old xer.ca, which is ignored*/ );
340570e2412f623c955d7b199f09401732cf57417fc2cerion      do_rc = True;  // Always record to CR
340676de5cf615380b23b4b5bcced6541233cd4a93a0cerion      flag_rC = 1;
3407b85e8bba97fdae7d892f7bfd12e4601307e4721dcerion      break;
3408b85e8bba97fdae7d892f7bfd12e4601307e4721dcerion
3409e9d361ab43518b6dfbd3d846f48859534659dee0cerion   case 0x0E: // addi   (Add Immediate, PPC32 p350)
34104561acb2fed3ea11b7b1f95a373da8ec62e6d483cerion      // li rD,val   == addi rD,0,val
34114561acb2fed3ea11b7b1f95a373da8ec62e6d483cerion      // la disp(rA) == addi rD,rA,disp
341276de5cf615380b23b4b5bcced6541233cd4a93a0cerion      if ( rA_addr == 0 ) {
3413d953ebb9b04cbad6891676df597bf0c542b1ec89cerion         DIP("li r%u,%d\n", rD_addr, (Int)simm16);
34142831b00c4950d6c2b061def05fd67528fe132ececerion         assign( rD, mkSzExtendS16(ty, uimm16) );
34154561acb2fed3ea11b7b1f95a373da8ec62e6d483cerion      } else {
3416d953ebb9b04cbad6891676df597bf0c542b1ec89cerion         DIP("addi r%u,r%u,%d\n", rD_addr, rA_addr, (Int)simm16);
34172831b00c4950d6c2b061def05fd67528fe132ececerion         assign( rD, binop( mkSzOp(ty, Iop_Add8), mkexpr(rA),
34182831b00c4950d6c2b061def05fd67528fe132ececerion                            mkSzExtendS16(ty, uimm16) ) );
34194561acb2fed3ea11b7b1f95a373da8ec62e6d483cerion      }
34204561acb2fed3ea11b7b1f95a373da8ec62e6d483cerion      break;
34214561acb2fed3ea11b7b1f95a373da8ec62e6d483cerion
3422e9d361ab43518b6dfbd3d846f48859534659dee0cerion   case 0x0F: // addis  (Add Immediate Shifted, PPC32 p353)
3423b85e8bba97fdae7d892f7bfd12e4601307e4721dcerion      // lis rD,val == addis rD,0,val
342476de5cf615380b23b4b5bcced6541233cd4a93a0cerion      if ( rA_addr == 0 ) {
3425d953ebb9b04cbad6891676df597bf0c542b1ec89cerion         DIP("lis r%u,%d\n", rD_addr, (Int)simm16);
34262831b00c4950d6c2b061def05fd67528fe132ececerion         assign( rD, mkSzExtendS32(ty, uimm16 << 16) );
3427b85e8bba97fdae7d892f7bfd12e4601307e4721dcerion      } else {
3428d953ebb9b04cbad6891676df597bf0c542b1ec89cerion         DIP("addis r%u,r%u,0x%x\n", rD_addr, rA_addr, (Int)simm16);
34292831b00c4950d6c2b061def05fd67528fe132ececerion         assign( rD, binop( mkSzOp(ty, Iop_Add8), mkexpr(rA),
34302831b00c4950d6c2b061def05fd67528fe132ececerion                            mkSzExtendS32(ty, uimm16 << 16) ) );
3431b85e8bba97fdae7d892f7bfd12e4601307e4721dcerion      }
3432b85e8bba97fdae7d892f7bfd12e4601307e4721dcerion      break;
3433b85e8bba97fdae7d892f7bfd12e4601307e4721dcerion
3434e9d361ab43518b6dfbd3d846f48859534659dee0cerion   case 0x07: // mulli    (Multiply Low Immediate, PPC32 p490)
3435d953ebb9b04cbad6891676df597bf0c542b1ec89cerion      DIP("mulli r%u,r%u,%d\n", rD_addr, rA_addr, (Int)simm16);
3436d953ebb9b04cbad6891676df597bf0c542b1ec89cerion      if (mode64)
3437d953ebb9b04cbad6891676df597bf0c542b1ec89cerion         assign( rD, unop(Iop_128to64,
3438d953ebb9b04cbad6891676df597bf0c542b1ec89cerion                          binop(Iop_MullS64, mkexpr(rA),
34392831b00c4950d6c2b061def05fd67528fe132ececerion                                mkSzExtendS16(ty, uimm16))) );
3440d953ebb9b04cbad6891676df597bf0c542b1ec89cerion      else
3441d953ebb9b04cbad6891676df597bf0c542b1ec89cerion         assign( rD, unop(Iop_64to32,
3442d953ebb9b04cbad6891676df597bf0c542b1ec89cerion                          binop(Iop_MullS32, mkexpr(rA),
34432831b00c4950d6c2b061def05fd67528fe132ececerion                                mkSzExtendS16(ty, uimm16))) );
3444b85e8bba97fdae7d892f7bfd12e4601307e4721dcerion      break;
3445b85e8bba97fdae7d892f7bfd12e4601307e4721dcerion
3446e9d361ab43518b6dfbd3d846f48859534659dee0cerion   case 0x08: // subfic   (Subtract from Immediate Carrying, PPC32 p540)
3447d953ebb9b04cbad6891676df597bf0c542b1ec89cerion      DIP("subfic r%u,r%u,%d\n", rD_addr, rA_addr, (Int)simm16);
344876de5cf615380b23b4b5bcced6541233cd4a93a0cerion      // rD = simm16 - rA
34492831b00c4950d6c2b061def05fd67528fe132ececerion      assign( rD, binop( mkSzOp(ty, Iop_Sub8),
34502831b00c4950d6c2b061def05fd67528fe132ececerion                         mkSzExtendS16(ty, uimm16),
3451d953ebb9b04cbad6891676df597bf0c542b1ec89cerion                         mkexpr(rA)) );
34525b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion      set_XER_CA( ty, PPCG_FLAG_OP_SUBFI,
34532831b00c4950d6c2b061def05fd67528fe132ececerion                  mkexpr(rD), mkexpr(rA), mkSzExtendS16(ty, uimm16),
34542831b00c4950d6c2b061def05fd67528fe132ececerion                  mkSzImm(ty, 0)/*old xer.ca, which is ignored*/ );
3455b85e8bba97fdae7d892f7bfd12e4601307e4721dcerion      break;
3456b85e8bba97fdae7d892f7bfd12e4601307e4721dcerion
3457b85e8bba97fdae7d892f7bfd12e4601307e4721dcerion   /* XO-Form */
3458b85e8bba97fdae7d892f7bfd12e4601307e4721dcerion   case 0x1F:
3459b85e8bba97fdae7d892f7bfd12e4601307e4721dcerion      do_rc = True;    // All below record to CR
3460b85e8bba97fdae7d892f7bfd12e4601307e4721dcerion
3461b85e8bba97fdae7d892f7bfd12e4601307e4721dcerion      switch (opc2) {
3462e9d361ab43518b6dfbd3d846f48859534659dee0cerion      case 0x10A: // add  (Add, PPC32 p347)
3463d953ebb9b04cbad6891676df597bf0c542b1ec89cerion         DIP("add%s%s r%u,r%u,r%u\n",
34645b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion             flag_OE ? "o" : "", flag_rC ? ".":"",
346576de5cf615380b23b4b5bcced6541233cd4a93a0cerion             rD_addr, rA_addr, rB_addr);
34662831b00c4950d6c2b061def05fd67528fe132ececerion         assign( rD, binop( mkSzOp(ty, Iop_Add8),
3467d953ebb9b04cbad6891676df597bf0c542b1ec89cerion                            mkexpr(rA), mkexpr(rB) ) );
346870e2412f623c955d7b199f09401732cf57417fc2cerion         if (flag_OE) {
34695b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion            set_XER_OV( ty, PPCG_FLAG_OP_ADD,
347076de5cf615380b23b4b5bcced6541233cd4a93a0cerion                        mkexpr(rD), mkexpr(rA), mkexpr(rB) );
347170e2412f623c955d7b199f09401732cf57417fc2cerion         }
3472b85e8bba97fdae7d892f7bfd12e4601307e4721dcerion         break;
3473b85e8bba97fdae7d892f7bfd12e4601307e4721dcerion
3474e9d361ab43518b6dfbd3d846f48859534659dee0cerion      case 0x00A: // addc      (Add Carrying, PPC32 p348)
3475d953ebb9b04cbad6891676df597bf0c542b1ec89cerion         DIP("addc%s%s r%u,r%u,r%u\n",
34765b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion             flag_OE ? "o" : "", flag_rC ? ".":"",
347776de5cf615380b23b4b5bcced6541233cd4a93a0cerion             rD_addr, rA_addr, rB_addr);
34782831b00c4950d6c2b061def05fd67528fe132ececerion         assign( rD, binop( mkSzOp(ty, Iop_Add8),
3479d953ebb9b04cbad6891676df597bf0c542b1ec89cerion                            mkexpr(rA), mkexpr(rB)) );
34805b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion         set_XER_CA( ty, PPCG_FLAG_OP_ADD,
348176de5cf615380b23b4b5bcced6541233cd4a93a0cerion                     mkexpr(rD), mkexpr(rA), mkexpr(rB),
34822831b00c4950d6c2b061def05fd67528fe132ececerion                     mkSzImm(ty, 0)/*old xer.ca, which is ignored*/ );
348370e2412f623c955d7b199f09401732cf57417fc2cerion         if (flag_OE) {
34845b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion            set_XER_OV( ty, PPCG_FLAG_OP_ADD,
348576de5cf615380b23b4b5bcced6541233cd4a93a0cerion                        mkexpr(rD), mkexpr(rA), mkexpr(rB) );
348670e2412f623c955d7b199f09401732cf57417fc2cerion         }
3487b85e8bba97fdae7d892f7bfd12e4601307e4721dcerion         break;
3488b85e8bba97fdae7d892f7bfd12e4601307e4721dcerion
3489b51f0f4f33256638ed953156a2635aa739b232f1sewardj      case 0x08A: { // adde      (Add Extended, PPC32 p349)
34902831b00c4950d6c2b061def05fd67528fe132ececerion         IRTemp old_xer_ca = newTemp(ty);
3491d953ebb9b04cbad6891676df597bf0c542b1ec89cerion         DIP("adde%s%s r%u,r%u,r%u\n",
34925b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion             flag_OE ? "o" : "", flag_rC ? ".":"",
349376de5cf615380b23b4b5bcced6541233cd4a93a0cerion             rD_addr, rA_addr, rB_addr);
3494b85e8bba97fdae7d892f7bfd12e4601307e4721dcerion         // rD = rA + rB + XER[CA]
3495e9d8a26b690c2561ac54ab0cd6ad83ecbadcbe76sewardj         assign( old_xer_ca, mkWidenFrom32(ty, getXER_CA32(), False) );
34962831b00c4950d6c2b061def05fd67528fe132ececerion         assign( rD, binop( mkSzOp(ty, Iop_Add8), mkexpr(rA),
34972831b00c4950d6c2b061def05fd67528fe132ececerion                            binop( mkSzOp(ty, Iop_Add8),
34982831b00c4950d6c2b061def05fd67528fe132ececerion                                   mkexpr(rB), mkexpr(old_xer_ca))) );
34995b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion         set_XER_CA( ty, PPCG_FLAG_OP_ADDE,
350076de5cf615380b23b4b5bcced6541233cd4a93a0cerion                     mkexpr(rD), mkexpr(rA), mkexpr(rB),
35012831b00c4950d6c2b061def05fd67528fe132ececerion                     mkexpr(old_xer_ca) );
350270e2412f623c955d7b199f09401732cf57417fc2cerion         if (flag_OE) {
35035b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion            set_XER_OV( ty, PPCG_FLAG_OP_ADDE,
350476de5cf615380b23b4b5bcced6541233cd4a93a0cerion                        mkexpr(rD), mkexpr(rA), mkexpr(rB) );
350570e2412f623c955d7b199f09401732cf57417fc2cerion         }
3506b85e8bba97fdae7d892f7bfd12e4601307e4721dcerion         break;
3507b51f0f4f33256638ed953156a2635aa739b232f1sewardj      }
3508b51f0f4f33256638ed953156a2635aa739b232f1sewardj
35095b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion      case 0x0EA: { // addme     (Add to Minus One Extended, PPC32 p354)
35102831b00c4950d6c2b061def05fd67528fe132ececerion         IRTemp old_xer_ca = newTemp(ty);
35112831b00c4950d6c2b061def05fd67528fe132ececerion         IRExpr *min_one;
351276de5cf615380b23b4b5bcced6541233cd4a93a0cerion         if (rB_addr != 0) {
35135b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion            vex_printf("dis_int_arith(ppc)(addme,rB_addr)\n");
3514b85e8bba97fdae7d892f7bfd12e4601307e4721dcerion            return False;
3515b85e8bba97fdae7d892f7bfd12e4601307e4721dcerion         }
3516d953ebb9b04cbad6891676df597bf0c542b1ec89cerion         DIP("addme%s%s r%u,r%u,r%u\n",
35175b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion             flag_OE ? "o" : "", flag_rC ? ".":"",
351876de5cf615380b23b4b5bcced6541233cd4a93a0cerion             rD_addr, rA_addr, rB_addr);
351970e2412f623c955d7b199f09401732cf57417fc2cerion         // rD = rA + (-1) + XER[CA]
352070e2412f623c955d7b199f09401732cf57417fc2cerion         // => Just another form of adde
3521e9d8a26b690c2561ac54ab0cd6ad83ecbadcbe76sewardj         assign( old_xer_ca, mkWidenFrom32(ty, getXER_CA32(), False) );
35222831b00c4950d6c2b061def05fd67528fe132ececerion         min_one = mkSzImm(ty, (Long)-1);
35232831b00c4950d6c2b061def05fd67528fe132ececerion         assign( rD, binop( mkSzOp(ty, Iop_Add8), mkexpr(rA),
35242831b00c4950d6c2b061def05fd67528fe132ececerion                            binop( mkSzOp(ty, Iop_Add8),
35252831b00c4950d6c2b061def05fd67528fe132ececerion                                   min_one, mkexpr(old_xer_ca)) ));
35265b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion         set_XER_CA( ty, PPCG_FLAG_OP_ADDE,
3527d953ebb9b04cbad6891676df597bf0c542b1ec89cerion                     mkexpr(rD), mkexpr(rA), min_one,
35282831b00c4950d6c2b061def05fd67528fe132ececerion                     mkexpr(old_xer_ca) );
352970e2412f623c955d7b199f09401732cf57417fc2cerion         if (flag_OE) {
35305b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion            set_XER_OV( ty, PPCG_FLAG_OP_ADDE,
3531d953ebb9b04cbad6891676df597bf0c542b1ec89cerion                        mkexpr(rD), mkexpr(rA), min_one );
353270e2412f623c955d7b199f09401732cf57417fc2cerion         }
3533b85e8bba97fdae7d892f7bfd12e4601307e4721dcerion         break;
3534b51f0f4f33256638ed953156a2635aa739b232f1sewardj      }
3535b51f0f4f33256638ed953156a2635aa739b232f1sewardj
3536b51f0f4f33256638ed953156a2635aa739b232f1sewardj      case 0x0CA: { // addze      (Add to Zero Extended, PPC32 p355)
35372831b00c4950d6c2b061def05fd67528fe132ececerion         IRTemp old_xer_ca = newTemp(ty);
353876de5cf615380b23b4b5bcced6541233cd4a93a0cerion         if (rB_addr != 0) {
35395b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion            vex_printf("dis_int_arith(ppc)(addze,rB_addr)\n");
3540b85e8bba97fdae7d892f7bfd12e4601307e4721dcerion            return False;
3541b85e8bba97fdae7d892f7bfd12e4601307e4721dcerion         }
3542d953ebb9b04cbad6891676df597bf0c542b1ec89cerion         DIP("addze%s%s r%u,r%u,r%u\n",
35435b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion             flag_OE ? "o" : "", flag_rC ? ".":"",
354476de5cf615380b23b4b5bcced6541233cd4a93a0cerion             rD_addr, rA_addr, rB_addr);
354570e2412f623c955d7b199f09401732cf57417fc2cerion         // rD = rA + (0) + XER[CA]
354670e2412f623c955d7b199f09401732cf57417fc2cerion         // => Just another form of adde
3547e9d8a26b690c2561ac54ab0cd6ad83ecbadcbe76sewardj         assign( old_xer_ca, mkWidenFrom32(ty, getXER_CA32(), False) );
35482831b00c4950d6c2b061def05fd67528fe132ececerion         assign( rD, binop( mkSzOp(ty, Iop_Add8),
35492831b00c4950d6c2b061def05fd67528fe132ececerion                            mkexpr(rA), mkexpr(old_xer_ca)) );
35505b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion         set_XER_CA( ty, PPCG_FLAG_OP_ADDE,
35512831b00c4950d6c2b061def05fd67528fe132ececerion                     mkexpr(rD), mkexpr(rA), mkSzImm(ty, 0),
35522831b00c4950d6c2b061def05fd67528fe132ececerion                     mkexpr(old_xer_ca) );
355370e2412f623c955d7b199f09401732cf57417fc2cerion         if (flag_OE) {
35545b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion            set_XER_OV( ty, PPCG_FLAG_OP_ADDE,
35552831b00c4950d6c2b061def05fd67528fe132ececerion                        mkexpr(rD), mkexpr(rA), mkSzImm(ty, 0) );
355670e2412f623c955d7b199f09401732cf57417fc2cerion         }
3557b85e8bba97fdae7d892f7bfd12e4601307e4721dcerion         break;
3558b51f0f4f33256638ed953156a2635aa739b232f1sewardj      }
3559b85e8bba97fdae7d892f7bfd12e4601307e4721dcerion
3560e9d361ab43518b6dfbd3d846f48859534659dee0cerion      case 0x1EB: // divw       (Divide Word, PPC32 p388)
3561d953ebb9b04cbad6891676df597bf0c542b1ec89cerion         DIP("divw%s%s r%u,r%u,r%u\n",
35625b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion             flag_OE ? "o" : "", flag_rC ? ".":"",
356376de5cf615380b23b4b5bcced6541233cd4a93a0cerion             rD_addr, rA_addr, rB_addr);
3564d953ebb9b04cbad6891676df597bf0c542b1ec89cerion         if (mode64) {
35652831b00c4950d6c2b061def05fd67528fe132ececerion            /* Note:
35662831b00c4950d6c2b061def05fd67528fe132ececerion               XER settings are mode independent, and reflect the
35672831b00c4950d6c2b061def05fd67528fe132ececerion               overflow of the low-order 32bit result
35682831b00c4950d6c2b061def05fd67528fe132ececerion               CR0[LT|GT|EQ] are undefined if flag_rC && mode64
35692831b00c4950d6c2b061def05fd67528fe132ececerion            */
3570bb01b7cbfd84c27dd213f67a144ea5a99af36961cerion            /* rD[hi32] are undefined: setting them to sign of lo32
3571bb01b7cbfd84c27dd213f67a144ea5a99af36961cerion                - makes set_CR0 happy */
3572bb01b7cbfd84c27dd213f67a144ea5a99af36961cerion            IRExpr* dividend = mk64lo32Sto64( mkexpr(rA) );
3573bb01b7cbfd84c27dd213f67a144ea5a99af36961cerion            IRExpr* divisor  = mk64lo32Sto64( mkexpr(rB) );
35745b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion            assign( rD, mk64lo32Uto64( binop(Iop_DivS64, dividend,
35755b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion                                                         divisor) ) );
3576d953ebb9b04cbad6891676df597bf0c542b1ec89cerion            if (flag_OE) {
35775b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion               set_XER_OV( ty, PPCG_FLAG_OP_DIVW,
3578f0de28cf1a762b0d6f74c93d3532c89a230673bbcerion                           mkexpr(rD), dividend, divisor );
3579d953ebb9b04cbad6891676df597bf0c542b1ec89cerion            }
3580d953ebb9b04cbad6891676df597bf0c542b1ec89cerion         } else {
3581d953ebb9b04cbad6891676df597bf0c542b1ec89cerion            assign( rD, binop(Iop_DivS32, mkexpr(rA), mkexpr(rB)) );
3582d953ebb9b04cbad6891676df597bf0c542b1ec89cerion            if (flag_OE) {
35835b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion               set_XER_OV( ty, PPCG_FLAG_OP_DIVW,
3584d953ebb9b04cbad6891676df597bf0c542b1ec89cerion                           mkexpr(rD), mkexpr(rA), mkexpr(rB) );
3585d953ebb9b04cbad6891676df597bf0c542b1ec89cerion            }
358670e2412f623c955d7b199f09401732cf57417fc2cerion         }
3587b85e8bba97fdae7d892f7bfd12e4601307e4721dcerion         /* Note:
3588b85e8bba97fdae7d892f7bfd12e4601307e4721dcerion            if (0x8000_0000 / -1) or (x / 0)
358976de5cf615380b23b4b5bcced6541233cd4a93a0cerion            => rD=undef, if(flag_rC) CR7=undef, if(flag_OE) XER_OV=1
3590b85e8bba97fdae7d892f7bfd12e4601307e4721dcerion            => But _no_ exception raised. */
3591b85e8bba97fdae7d892f7bfd12e4601307e4721dcerion         break;
3592b85e8bba97fdae7d892f7bfd12e4601307e4721dcerion
3593e9d361ab43518b6dfbd3d846f48859534659dee0cerion      case 0x1CB: // divwu      (Divide Word Unsigned, PPC32 p389)
3594d953ebb9b04cbad6891676df597bf0c542b1ec89cerion         DIP("divwu%s%s r%u,r%u,r%u\n",
35955b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion             flag_OE ? "o" : "", flag_rC ? ".":"",
359676de5cf615380b23b4b5bcced6541233cd4a93a0cerion             rD_addr, rA_addr, rB_addr);
3597d953ebb9b04cbad6891676df597bf0c542b1ec89cerion         if (mode64) {
35982831b00c4950d6c2b061def05fd67528fe132ececerion            /* Note:
35992831b00c4950d6c2b061def05fd67528fe132ececerion               XER settings are mode independent, and reflect the
36002831b00c4950d6c2b061def05fd67528fe132ececerion               overflow of the low-order 32bit result
36012831b00c4950d6c2b061def05fd67528fe132ececerion               CR0[LT|GT|EQ] are undefined if flag_rC && mode64
36022831b00c4950d6c2b061def05fd67528fe132ececerion            */
3603bb01b7cbfd84c27dd213f67a144ea5a99af36961cerion            IRExpr* dividend = mk64lo32Uto64( mkexpr(rA) );
3604bb01b7cbfd84c27dd213f67a144ea5a99af36961cerion            IRExpr* divisor  = mk64lo32Uto64( mkexpr(rB) );
36055b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion            assign( rD, mk64lo32Uto64( binop(Iop_DivU64, dividend,
36065b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion                                                         divisor) ) );
3607d953ebb9b04cbad6891676df597bf0c542b1ec89cerion            if (flag_OE) {
36085b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion               set_XER_OV( ty, PPCG_FLAG_OP_DIVWU,
3609f0de28cf1a762b0d6f74c93d3532c89a230673bbcerion                           mkexpr(rD), dividend, divisor );
3610d953ebb9b04cbad6891676df597bf0c542b1ec89cerion            }
36112831b00c4950d6c2b061def05fd67528fe132ececerion         } else {
3612d953ebb9b04cbad6891676df597bf0c542b1ec89cerion            assign( rD, binop(Iop_DivU32, mkexpr(rA), mkexpr(rB)) );
3613d953ebb9b04cbad6891676df597bf0c542b1ec89cerion            if (flag_OE) {
36145b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion               set_XER_OV( ty, PPCG_FLAG_OP_DIVWU,
3615d953ebb9b04cbad6891676df597bf0c542b1ec89cerion                           mkexpr(rD), mkexpr(rA), mkexpr(rB) );
3616d953ebb9b04cbad6891676df597bf0c542b1ec89cerion            }
361770e2412f623c955d7b199f09401732cf57417fc2cerion         }
3618b85e8bba97fdae7d892f7bfd12e4601307e4721dcerion         /* Note: ditto comment divw, for (x / 0) */
3619b85e8bba97fdae7d892f7bfd12e4601307e4721dcerion         break;
3620b85e8bba97fdae7d892f7bfd12e4601307e4721dcerion
3621e9d361ab43518b6dfbd3d846f48859534659dee0cerion      case 0x04B: // mulhw      (Multiply High Word, PPC32 p488)
3622b85e8bba97fdae7d892f7bfd12e4601307e4721dcerion         if (flag_OE != 0) {
36235b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion            vex_printf("dis_int_arith(ppc)(mulhw,flag_OE)\n");
3624b85e8bba97fdae7d892f7bfd12e4601307e4721dcerion            return False;
3625b85e8bba97fdae7d892f7bfd12e4601307e4721dcerion         }
36265b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion         DIP("mulhw%s r%u,r%u,r%u\n", flag_rC ? ".":"",
362776de5cf615380b23b4b5bcced6541233cd4a93a0cerion             rD_addr, rA_addr, rB_addr);
36282831b00c4950d6c2b061def05fd67528fe132ececerion         if (mode64) {
3629bb01b7cbfd84c27dd213f67a144ea5a99af36961cerion            /* rD[hi32] are undefined: setting them to sign of lo32
3630bb01b7cbfd84c27dd213f67a144ea5a99af36961cerion                - makes set_CR0 happy */
3631bb01b7cbfd84c27dd213f67a144ea5a99af36961cerion            assign( rD, binop(Iop_Sar64,
3632bb01b7cbfd84c27dd213f67a144ea5a99af36961cerion                           binop(Iop_Mul64,
3633bb01b7cbfd84c27dd213f67a144ea5a99af36961cerion                                 mk64lo32Sto64( mkexpr(rA) ),
3634bb01b7cbfd84c27dd213f67a144ea5a99af36961cerion                                 mk64lo32Sto64( mkexpr(rB) )),
3635bb01b7cbfd84c27dd213f67a144ea5a99af36961cerion                              mkU8(32)) );
36362831b00c4950d6c2b061def05fd67528fe132ececerion         } else {
3637d953ebb9b04cbad6891676df597bf0c542b1ec89cerion            assign( rD, unop(Iop_64HIto32,
3638d953ebb9b04cbad6891676df597bf0c542b1ec89cerion                             binop(Iop_MullS32,
3639d953ebb9b04cbad6891676df597bf0c542b1ec89cerion                                   mkexpr(rA), mkexpr(rB))) );
36402831b00c4950d6c2b061def05fd67528fe132ececerion         }
3641b85e8bba97fdae7d892f7bfd12e4601307e4721dcerion         break;
3642b85e8bba97fdae7d892f7bfd12e4601307e4721dcerion
36435b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion      case 0x00B: // mulhwu    (Multiply High Word Unsigned, PPC32 p489)
3644b85e8bba97fdae7d892f7bfd12e4601307e4721dcerion         if (flag_OE != 0) {
36455b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion            vex_printf("dis_int_arith(ppc)(mulhwu,flag_OE)\n");
3646b85e8bba97fdae7d892f7bfd12e4601307e4721dcerion            return False;
3647b85e8bba97fdae7d892f7bfd12e4601307e4721dcerion         }
36485b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion         DIP("mulhwu%s r%u,r%u,r%u\n", flag_rC ? ".":"",
364976de5cf615380b23b4b5bcced6541233cd4a93a0cerion             rD_addr, rA_addr, rB_addr);
36502831b00c4950d6c2b061def05fd67528fe132ececerion         if (mode64) {
3651bb01b7cbfd84c27dd213f67a144ea5a99af36961cerion            /* rD[hi32] are undefined: setting them to sign of lo32
3652bb01b7cbfd84c27dd213f67a144ea5a99af36961cerion                - makes set_CR0 happy */
3653bb01b7cbfd84c27dd213f67a144ea5a99af36961cerion            assign( rD, binop(Iop_Sar64,
3654bb01b7cbfd84c27dd213f67a144ea5a99af36961cerion                           binop(Iop_Mul64,
3655bb01b7cbfd84c27dd213f67a144ea5a99af36961cerion                                 mk64lo32Uto64( mkexpr(rA) ),
3656bb01b7cbfd84c27dd213f67a144ea5a99af36961cerion                                 mk64lo32Uto64( mkexpr(rB) ) ),
3657bb01b7cbfd84c27dd213f67a144ea5a99af36961cerion                              mkU8(32)) );
36582831b00c4950d6c2b061def05fd67528fe132ececerion         } else {
3659d953ebb9b04cbad6891676df597bf0c542b1ec89cerion            assign( rD, unop(Iop_64HIto32,
3660d953ebb9b04cbad6891676df597bf0c542b1ec89cerion                             binop(Iop_MullU32,
3661d953ebb9b04cbad6891676df597bf0c542b1ec89cerion                                   mkexpr(rA), mkexpr(rB))) );
36622831b00c4950d6c2b061def05fd67528fe132ececerion         }
3663b85e8bba97fdae7d892f7bfd12e4601307e4721dcerion         break;
3664b85e8bba97fdae7d892f7bfd12e4601307e4721dcerion
3665e9d361ab43518b6dfbd3d846f48859534659dee0cerion      case 0x0EB: // mullw      (Multiply Low Word, PPC32 p491)
3666d953ebb9b04cbad6891676df597bf0c542b1ec89cerion         DIP("mullw%s%s r%u,r%u,r%u\n",
36675b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion             flag_OE ? "o" : "", flag_rC ? ".":"",
366876de5cf615380b23b4b5bcced6541233cd4a93a0cerion             rD_addr, rA_addr, rB_addr);
36692831b00c4950d6c2b061def05fd67528fe132ececerion         if (mode64) {
3670bb01b7cbfd84c27dd213f67a144ea5a99af36961cerion            /* rD[hi32] are undefined: setting them to sign of lo32
3671bb01b7cbfd84c27dd213f67a144ea5a99af36961cerion                - set_XER_OV() and set_CR0() depend on this */
3672bb01b7cbfd84c27dd213f67a144ea5a99af36961cerion            IRExpr *a = unop(Iop_64to32, mkexpr(rA) );
3673bb01b7cbfd84c27dd213f67a144ea5a99af36961cerion            IRExpr *b = unop(Iop_64to32, mkexpr(rB) );
3674bb01b7cbfd84c27dd213f67a144ea5a99af36961cerion            assign( rD, binop(Iop_MullS32, a, b) );
3675bb01b7cbfd84c27dd213f67a144ea5a99af36961cerion            if (flag_OE) {
36765b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion               set_XER_OV( ty, PPCG_FLAG_OP_MULLW,
3677bb01b7cbfd84c27dd213f67a144ea5a99af36961cerion                           mkexpr(rD),
3678bb01b7cbfd84c27dd213f67a144ea5a99af36961cerion                           unop(Iop_32Uto64, a), unop(Iop_32Uto64, b) );
3679bb01b7cbfd84c27dd213f67a144ea5a99af36961cerion            }
36802831b00c4950d6c2b061def05fd67528fe132ececerion         } else {
3681d953ebb9b04cbad6891676df597bf0c542b1ec89cerion            assign( rD, unop(Iop_64to32,
3682d953ebb9b04cbad6891676df597bf0c542b1ec89cerion                             binop(Iop_MullU32,
3683d953ebb9b04cbad6891676df597bf0c542b1ec89cerion                                   mkexpr(rA), mkexpr(rB))) );
3684bb01b7cbfd84c27dd213f67a144ea5a99af36961cerion            if (flag_OE) {
36855b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion               set_XER_OV( ty, PPCG_FLAG_OP_MULLW,
3686bb01b7cbfd84c27dd213f67a144ea5a99af36961cerion                           mkexpr(rD), mkexpr(rA), mkexpr(rB) );
3687bb01b7cbfd84c27dd213f67a144ea5a99af36961cerion            }
368870e2412f623c955d7b199f09401732cf57417fc2cerion         }
3689b85e8bba97fdae7d892f7bfd12e4601307e4721dcerion         break;
3690b85e8bba97fdae7d892f7bfd12e4601307e4721dcerion
3691e9d361ab43518b6dfbd3d846f48859534659dee0cerion      case 0x068: // neg        (Negate, PPC32 p493)
369276de5cf615380b23b4b5bcced6541233cd4a93a0cerion         if (rB_addr != 0) {
36935b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion            vex_printf("dis_int_arith(ppc)(neg,rB_addr)\n");
3694b85e8bba97fdae7d892f7bfd12e4601307e4721dcerion            return False;
3695b85e8bba97fdae7d892f7bfd12e4601307e4721dcerion         }
3696d953ebb9b04cbad6891676df597bf0c542b1ec89cerion         DIP("neg%s%s r%u,r%u\n",
36975b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion             flag_OE ? "o" : "", flag_rC ? ".":"",
369876de5cf615380b23b4b5bcced6541233cd4a93a0cerion             rD_addr, rA_addr);
3699d953ebb9b04cbad6891676df597bf0c542b1ec89cerion         // rD = (~rA) + 1
37002831b00c4950d6c2b061def05fd67528fe132ececerion         assign( rD, binop( mkSzOp(ty, Iop_Add8),
37012831b00c4950d6c2b061def05fd67528fe132ececerion                            unop( mkSzOp(ty, Iop_Not8), mkexpr(rA) ),
37022831b00c4950d6c2b061def05fd67528fe132ececerion                            mkSzImm(ty, 1)) );
370370e2412f623c955d7b199f09401732cf57417fc2cerion         if (flag_OE) {
37045b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion            set_XER_OV( ty, PPCG_FLAG_OP_NEG,
370576de5cf615380b23b4b5bcced6541233cd4a93a0cerion                        mkexpr(rD), mkexpr(rA), mkexpr(rB) );
370670e2412f623c955d7b199f09401732cf57417fc2cerion         }
3707b85e8bba97fdae7d892f7bfd12e4601307e4721dcerion         break;
3708b85e8bba97fdae7d892f7bfd12e4601307e4721dcerion
3709e9d361ab43518b6dfbd3d846f48859534659dee0cerion      case 0x028: // subf       (Subtract From, PPC32 p537)
3710d953ebb9b04cbad6891676df597bf0c542b1ec89cerion         DIP("subf%s%s r%u,r%u,r%u\n",
37115b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion             flag_OE ? "o" : "", flag_rC ? ".":"",
371276de5cf615380b23b4b5bcced6541233cd4a93a0cerion             rD_addr, rA_addr, rB_addr);
371301908478d5402ff3f7a19780c8b37ec5c8bf8973cerion         // rD = rB - rA
37142831b00c4950d6c2b061def05fd67528fe132ececerion         assign( rD, binop( mkSzOp(ty, Iop_Sub8),
3715d953ebb9b04cbad6891676df597bf0c542b1ec89cerion                            mkexpr(rB), mkexpr(rA)) );
371670e2412f623c955d7b199f09401732cf57417fc2cerion         if (flag_OE) {
37175b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion            set_XER_OV( ty, PPCG_FLAG_OP_SUBF,
371876de5cf615380b23b4b5bcced6541233cd4a93a0cerion                        mkexpr(rD), mkexpr(rA), mkexpr(rB) );
371970e2412f623c955d7b199f09401732cf57417fc2cerion         }
3720b85e8bba97fdae7d892f7bfd12e4601307e4721dcerion         break;
3721b85e8bba97fdae7d892f7bfd12e4601307e4721dcerion
3722e9d361ab43518b6dfbd3d846f48859534659dee0cerion      case 0x008: // subfc      (Subtract from Carrying, PPC32 p538)
3723d953ebb9b04cbad6891676df597bf0c542b1ec89cerion         DIP("subfc%s%s r%u,r%u,r%u\n",
37245b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion             flag_OE ? "o" : "", flag_rC ? ".":"",
372576de5cf615380b23b4b5bcced6541233cd4a93a0cerion             rD_addr, rA_addr, rB_addr);
372601908478d5402ff3f7a19780c8b37ec5c8bf8973cerion         // rD = rB - rA
37272831b00c4950d6c2b061def05fd67528fe132ececerion         assign( rD, binop( mkSzOp(ty, Iop_Sub8),
3728d953ebb9b04cbad6891676df597bf0c542b1ec89cerion                            mkexpr(rB), mkexpr(rA)) );
37295b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion         set_XER_CA( ty, PPCG_FLAG_OP_SUBFC,
373076de5cf615380b23b4b5bcced6541233cd4a93a0cerion                     mkexpr(rD), mkexpr(rA), mkexpr(rB),
37312831b00c4950d6c2b061def05fd67528fe132ececerion                     mkSzImm(ty, 0)/*old xer.ca, which is ignored*/ );
373270e2412f623c955d7b199f09401732cf57417fc2cerion         if (flag_OE) {
37335b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion            set_XER_OV( ty, PPCG_FLAG_OP_SUBFC,
373476de5cf615380b23b4b5bcced6541233cd4a93a0cerion                        mkexpr(rD), mkexpr(rA), mkexpr(rB) );
373570e2412f623c955d7b199f09401732cf57417fc2cerion         }
3736b85e8bba97fdae7d892f7bfd12e4601307e4721dcerion         break;
3737b85e8bba97fdae7d892f7bfd12e4601307e4721dcerion
3738b51f0f4f33256638ed953156a2635aa739b232f1sewardj      case 0x088: {// subfe      (Subtract from Extended, PPC32 p539)
37392831b00c4950d6c2b061def05fd67528fe132ececerion         IRTemp old_xer_ca = newTemp(ty);
3740d953ebb9b04cbad6891676df597bf0c542b1ec89cerion         DIP("subfe%s%s r%u,r%u,r%u\n",
37415b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion             flag_OE ? "o" : "", flag_rC ? ".":"",
374276de5cf615380b23b4b5bcced6541233cd4a93a0cerion             rD_addr, rA_addr, rB_addr);
3743b85e8bba97fdae7d892f7bfd12e4601307e4721dcerion         // rD = (log not)rA + rB + XER[CA]
3744e9d8a26b690c2561ac54ab0cd6ad83ecbadcbe76sewardj         assign( old_xer_ca, mkWidenFrom32(ty, getXER_CA32(), False) );
37452831b00c4950d6c2b061def05fd67528fe132ececerion         assign( rD, binop( mkSzOp(ty, Iop_Add8),
37462831b00c4950d6c2b061def05fd67528fe132ececerion                            unop( mkSzOp(ty, Iop_Not8), mkexpr(rA)),
37472831b00c4950d6c2b061def05fd67528fe132ececerion                            binop( mkSzOp(ty, Iop_Add8),
37482831b00c4950d6c2b061def05fd67528fe132ececerion                                   mkexpr(rB), mkexpr(old_xer_ca))) );
37495b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion         set_XER_CA( ty, PPCG_FLAG_OP_SUBFE,
375076de5cf615380b23b4b5bcced6541233cd4a93a0cerion                     mkexpr(rD), mkexpr(rA), mkexpr(rB),
37512831b00c4950d6c2b061def05fd67528fe132ececerion                     mkexpr(old_xer_ca) );
375270e2412f623c955d7b199f09401732cf57417fc2cerion         if (flag_OE) {
37535b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion            set_XER_OV( ty, PPCG_FLAG_OP_SUBFE,
375476de5cf615380b23b4b5bcced6541233cd4a93a0cerion                        mkexpr(rD), mkexpr(rA), mkexpr(rB) );
375520ef5472eac767474c93b7835364a23f24c0ec5dsewardj         }
375620ef5472eac767474c93b7835364a23f24c0ec5dsewardj         break;
375720ef5472eac767474c93b7835364a23f24c0ec5dsewardj      }
375820ef5472eac767474c93b7835364a23f24c0ec5dsewardj
37595b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion      case 0x0E8: { // subfme    (Subtract from -1 Extended, PPC32 p541)
37602831b00c4950d6c2b061def05fd67528fe132ececerion         IRTemp old_xer_ca = newTemp(ty);
37612831b00c4950d6c2b061def05fd67528fe132ececerion         IRExpr *min_one;
376276de5cf615380b23b4b5bcced6541233cd4a93a0cerion         if (rB_addr != 0) {
37635b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion            vex_printf("dis_int_arith(ppc)(subfme,rB_addr)\n");
376420ef5472eac767474c93b7835364a23f24c0ec5dsewardj            return False;
376520ef5472eac767474c93b7835364a23f24c0ec5dsewardj         }
3766d953ebb9b04cbad6891676df597bf0c542b1ec89cerion         DIP("subfme%s%s r%u,r%u\n",
37675b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion             flag_OE ? "o" : "", flag_rC ? ".":"",
376876de5cf615380b23b4b5bcced6541233cd4a93a0cerion             rD_addr, rA_addr);
376920ef5472eac767474c93b7835364a23f24c0ec5dsewardj         // rD = (log not)rA + (-1) + XER[CA]
377020ef5472eac767474c93b7835364a23f24c0ec5dsewardj         // => Just another form of subfe
3771e9d8a26b690c2561ac54ab0cd6ad83ecbadcbe76sewardj         assign( old_xer_ca, mkWidenFrom32(ty, getXER_CA32(), False) );
37722831b00c4950d6c2b061def05fd67528fe132ececerion         min_one = mkSzImm(ty, (Long)-1);
37732831b00c4950d6c2b061def05fd67528fe132ececerion         assign( rD, binop( mkSzOp(ty, Iop_Add8),
37742831b00c4950d6c2b061def05fd67528fe132ececerion                            unop( mkSzOp(ty, Iop_Not8), mkexpr(rA)),
37752831b00c4950d6c2b061def05fd67528fe132ececerion                            binop( mkSzOp(ty, Iop_Add8),
37762831b00c4950d6c2b061def05fd67528fe132ececerion                                   min_one, mkexpr(old_xer_ca))) );
37775b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion         set_XER_CA( ty, PPCG_FLAG_OP_SUBFE,
3778d953ebb9b04cbad6891676df597bf0c542b1ec89cerion                     mkexpr(rD), mkexpr(rA), min_one,
37792831b00c4950d6c2b061def05fd67528fe132ececerion                     mkexpr(old_xer_ca) );
378020ef5472eac767474c93b7835364a23f24c0ec5dsewardj         if (flag_OE) {
37815b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion            set_XER_OV( ty, PPCG_FLAG_OP_SUBFE,
3782d953ebb9b04cbad6891676df597bf0c542b1ec89cerion                        mkexpr(rD), mkexpr(rA), min_one );
378370e2412f623c955d7b199f09401732cf57417fc2cerion         }
3784b85e8bba97fdae7d892f7bfd12e4601307e4721dcerion         break;
3785b51f0f4f33256638ed953156a2635aa739b232f1sewardj      }
3786b51f0f4f33256638ed953156a2635aa739b232f1sewardj
37875b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion      case 0x0C8: { // subfze  (Subtract from Zero Extended, PPC32 p542)
37882831b00c4950d6c2b061def05fd67528fe132ececerion         IRTemp old_xer_ca = newTemp(ty);
378976de5cf615380b23b4b5bcced6541233cd4a93a0cerion         if (rB_addr != 0) {
37905b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion            vex_printf("dis_int_arith(ppc)(subfze,rB_addr)\n");
3791b85e8bba97fdae7d892f7bfd12e4601307e4721dcerion            return False;
3792b85e8bba97fdae7d892f7bfd12e4601307e4721dcerion         }
3793d953ebb9b04cbad6891676df597bf0c542b1ec89cerion         DIP("subfze%s%s r%u,r%u\n",
37945b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion             flag_OE ? "o" : "", flag_rC ? ".":"",
379576de5cf615380b23b4b5bcced6541233cd4a93a0cerion             rD_addr, rA_addr);
379670e2412f623c955d7b199f09401732cf57417fc2cerion         // rD = (log not)rA + (0) + XER[CA]
379770e2412f623c955d7b199f09401732cf57417fc2cerion         // => Just another form of subfe
3798e9d8a26b690c2561ac54ab0cd6ad83ecbadcbe76sewardj         assign( old_xer_ca, mkWidenFrom32(ty, getXER_CA32(), False) );
37992831b00c4950d6c2b061def05fd67528fe132ececerion         assign( rD, binop( mkSzOp(ty, Iop_Add8),
38002831b00c4950d6c2b061def05fd67528fe132ececerion                           unop( mkSzOp(ty, Iop_Not8),
38012831b00c4950d6c2b061def05fd67528fe132ececerion                                 mkexpr(rA)), mkexpr(old_xer_ca)) );
38025b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion         set_XER_CA( ty, PPCG_FLAG_OP_SUBFE,
38032831b00c4950d6c2b061def05fd67528fe132ececerion                     mkexpr(rD), mkexpr(rA), mkSzImm(ty, 0),
38042831b00c4950d6c2b061def05fd67528fe132ececerion                     mkexpr(old_xer_ca) );
380570e2412f623c955d7b199f09401732cf57417fc2cerion         if (flag_OE) {
38065b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion            set_XER_OV( ty, PPCG_FLAG_OP_SUBFE,
38072831b00c4950d6c2b061def05fd67528fe132ececerion                        mkexpr(rD), mkexpr(rA), mkSzImm(ty, 0) );
380870e2412f623c955d7b199f09401732cf57417fc2cerion         }
3809b85e8bba97fdae7d892f7bfd12e4601307e4721dcerion         break;
3810b51f0f4f33256638ed953156a2635aa739b232f1sewardj      }
3811b85e8bba97fdae7d892f7bfd12e4601307e4721dcerion
3812f0de28cf1a762b0d6f74c93d3532c89a230673bbcerion
3813f0de28cf1a762b0d6f74c93d3532c89a230673bbcerion      /* 64bit Arithmetic */
38145b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion      case 0x49:  // mulhd (Multiply High DWord, PPC64 p539)
3815f0de28cf1a762b0d6f74c93d3532c89a230673bbcerion         if (flag_OE != 0) {
38165b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion            vex_printf("dis_int_arith(ppc)(mulhd,flagOE)\n");
3817f0de28cf1a762b0d6f74c93d3532c89a230673bbcerion            return False;
3818f0de28cf1a762b0d6f74c93d3532c89a230673bbcerion         }
38195b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion         DIP("mulhd%s r%u,r%u,r%u\n", flag_rC ? ".":"",
3820f0de28cf1a762b0d6f74c93d3532c89a230673bbcerion             rD_addr, rA_addr, rB_addr);
3821f0de28cf1a762b0d6f74c93d3532c89a230673bbcerion         assign( rD, unop(Iop_128HIto64,
382207b07a966a2fdbcf621251a0c1a8ab84807fb120cerion                          binop(Iop_MullS64,
3823f0de28cf1a762b0d6f74c93d3532c89a230673bbcerion                                mkexpr(rA), mkexpr(rB))) );
382407b07a966a2fdbcf621251a0c1a8ab84807fb120cerion
382507b07a966a2fdbcf621251a0c1a8ab84807fb120cerion         break;
3826f0de28cf1a762b0d6f74c93d3532c89a230673bbcerion
38275b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion      case 0x9:   // mulhdu  (Multiply High DWord Unsigned, PPC64 p540)
3828f0de28cf1a762b0d6f74c93d3532c89a230673bbcerion         if (flag_OE != 0) {
38295b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion            vex_printf("dis_int_arith(ppc)(mulhdu,flagOE)\n");
3830f0de28cf1a762b0d6f74c93d3532c89a230673bbcerion            return False;
3831f0de28cf1a762b0d6f74c93d3532c89a230673bbcerion         }
38325b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion         DIP("mulhdu%s r%u,r%u,r%u\n", flag_rC ? ".":"",
3833f0de28cf1a762b0d6f74c93d3532c89a230673bbcerion             rD_addr, rA_addr, rB_addr);
383407b07a966a2fdbcf621251a0c1a8ab84807fb120cerion         assign( rD, unop(Iop_128HIto64,
383507b07a966a2fdbcf621251a0c1a8ab84807fb120cerion                          binop(Iop_MullU64,
383607b07a966a2fdbcf621251a0c1a8ab84807fb120cerion                                mkexpr(rA), mkexpr(rB))) );
383707b07a966a2fdbcf621251a0c1a8ab84807fb120cerion         break;
3838f0de28cf1a762b0d6f74c93d3532c89a230673bbcerion
38395b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion      case 0xE9:  // mulld (Multiply Low DWord, PPC64 p543)
3840f0de28cf1a762b0d6f74c93d3532c89a230673bbcerion         DIP("mulld%s%s r%u,r%u,r%u\n",
38415b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion             flag_OE ? "o" : "", flag_rC ? ".":"",
3842f0de28cf1a762b0d6f74c93d3532c89a230673bbcerion             rD_addr, rA_addr, rB_addr);
3843f0de28cf1a762b0d6f74c93d3532c89a230673bbcerion         assign( rD, binop(Iop_Mul64, mkexpr(rA), mkexpr(rB)) );
3844f0de28cf1a762b0d6f74c93d3532c89a230673bbcerion         if (flag_OE) {
384538b79ace9613df76a5feb7a237226f4a4cc02ecdcarll            set_XER_OV( ty, PPCG_FLAG_OP_MULLD,
3846f0de28cf1a762b0d6f74c93d3532c89a230673bbcerion                        mkexpr(rD), mkexpr(rA), mkexpr(rB) );
3847f0de28cf1a762b0d6f74c93d3532c89a230673bbcerion         }
3848f0de28cf1a762b0d6f74c93d3532c89a230673bbcerion         break;
3849f0de28cf1a762b0d6f74c93d3532c89a230673bbcerion
38505b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion      case 0x1E9: // divd (Divide DWord, PPC64 p419)
3851f0de28cf1a762b0d6f74c93d3532c89a230673bbcerion         DIP("divd%s%s r%u,r%u,r%u\n",
38525b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion             flag_OE ? "o" : "", flag_rC ? ".":"",
3853f0de28cf1a762b0d6f74c93d3532c89a230673bbcerion             rD_addr, rA_addr, rB_addr);
385407b07a966a2fdbcf621251a0c1a8ab84807fb120cerion         assign( rD, binop(Iop_DivS64, mkexpr(rA), mkexpr(rB)) );
385507b07a966a2fdbcf621251a0c1a8ab84807fb120cerion         if (flag_OE) {
38565b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion            set_XER_OV( ty, PPCG_FLAG_OP_DIVW,
385707b07a966a2fdbcf621251a0c1a8ab84807fb120cerion                        mkexpr(rD), mkexpr(rA), mkexpr(rB) );
385807b07a966a2fdbcf621251a0c1a8ab84807fb120cerion         }
385907b07a966a2fdbcf621251a0c1a8ab84807fb120cerion         break;
3860f0de28cf1a762b0d6f74c93d3532c89a230673bbcerion         /* Note:
386107b07a966a2fdbcf621251a0c1a8ab84807fb120cerion            if (0x8000_0000_0000_0000 / -1) or (x / 0)
3862f0de28cf1a762b0d6f74c93d3532c89a230673bbcerion            => rD=undef, if(flag_rC) CR7=undef, if(flag_OE) XER_OV=1
3863f0de28cf1a762b0d6f74c93d3532c89a230673bbcerion            => But _no_ exception raised. */
3864f0de28cf1a762b0d6f74c93d3532c89a230673bbcerion
38655b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion      case 0x1C9: // divdu (Divide DWord Unsigned, PPC64 p420)
3866f0de28cf1a762b0d6f74c93d3532c89a230673bbcerion         DIP("divdu%s%s r%u,r%u,r%u\n",
38675b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion             flag_OE ? "o" : "", flag_rC ? ".":"",
3868f0de28cf1a762b0d6f74c93d3532c89a230673bbcerion             rD_addr, rA_addr, rB_addr);
386907b07a966a2fdbcf621251a0c1a8ab84807fb120cerion         assign( rD, binop(Iop_DivU64, mkexpr(rA), mkexpr(rB)) );
387007b07a966a2fdbcf621251a0c1a8ab84807fb120cerion         if (flag_OE) {
38715b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion            set_XER_OV( ty, PPCG_FLAG_OP_DIVWU,
387207b07a966a2fdbcf621251a0c1a8ab84807fb120cerion                        mkexpr(rD), mkexpr(rA), mkexpr(rB) );
387307b07a966a2fdbcf621251a0c1a8ab84807fb120cerion         }
387407b07a966a2fdbcf621251a0c1a8ab84807fb120cerion         break;
3875f0de28cf1a762b0d6f74c93d3532c89a230673bbcerion         /* Note: ditto comment divd, for (x / 0) */
3876f0de28cf1a762b0d6f74c93d3532c89a230673bbcerion
38774aa412af1d8166cc11f39a6e721df49431d23618sewardj      case 0x18B: // divweu (Divide Word Extended Unsigned)
38784aa412af1d8166cc11f39a6e721df49431d23618sewardj      {
38794aa412af1d8166cc11f39a6e721df49431d23618sewardj        /*
38804aa412af1d8166cc11f39a6e721df49431d23618sewardj         *  If (RA) >= (RB), or if an attempt is made to perform the division
38814aa412af1d8166cc11f39a6e721df49431d23618sewardj         *         <anything> / 0
38824aa412af1d8166cc11f39a6e721df49431d23618sewardj         * then the contents of register RD are undefined as are (if Rc=1) the contents of
38834aa412af1d8166cc11f39a6e721df49431d23618sewardj         * the LT, GT, and EQ bits of CR Field 0. In these cases, if OE=1 then OV is set
38844aa412af1d8166cc11f39a6e721df49431d23618sewardj         * to 1.
38854aa412af1d8166cc11f39a6e721df49431d23618sewardj         */
38864aa412af1d8166cc11f39a6e721df49431d23618sewardj         IRTemp res = newTemp(Ity_I32);
38874aa412af1d8166cc11f39a6e721df49431d23618sewardj         IRExpr * dividend, * divisor;
38884aa412af1d8166cc11f39a6e721df49431d23618sewardj         DIP("divweu%s%s r%u,r%u,r%u\n",
38894aa412af1d8166cc11f39a6e721df49431d23618sewardj             flag_OE ? "o" : "", flag_rC ? ".":"",
38904aa412af1d8166cc11f39a6e721df49431d23618sewardj                                         rD_addr, rA_addr, rB_addr);
38914aa412af1d8166cc11f39a6e721df49431d23618sewardj         if (mode64) {
38924aa412af1d8166cc11f39a6e721df49431d23618sewardj            dividend = unop( Iop_64to32, mkexpr( rA ) );
38934aa412af1d8166cc11f39a6e721df49431d23618sewardj            divisor = unop( Iop_64to32, mkexpr( rB ) );
38944aa412af1d8166cc11f39a6e721df49431d23618sewardj            assign( res, binop( Iop_DivU32E, dividend, divisor ) );
38954aa412af1d8166cc11f39a6e721df49431d23618sewardj            assign( rD, binop( Iop_32HLto64, mkU32( 0 ), mkexpr( res ) ) );
38964aa412af1d8166cc11f39a6e721df49431d23618sewardj         } else {
38974aa412af1d8166cc11f39a6e721df49431d23618sewardj            dividend = mkexpr( rA );
38984aa412af1d8166cc11f39a6e721df49431d23618sewardj            divisor =  mkexpr( rB );
38994aa412af1d8166cc11f39a6e721df49431d23618sewardj            assign( res, binop( Iop_DivU32E, dividend, divisor ) );
39004aa412af1d8166cc11f39a6e721df49431d23618sewardj            assign( rD, mkexpr( res) );
39014aa412af1d8166cc11f39a6e721df49431d23618sewardj         }
39024aa412af1d8166cc11f39a6e721df49431d23618sewardj
39034aa412af1d8166cc11f39a6e721df49431d23618sewardj         if (flag_OE) {
39044aa412af1d8166cc11f39a6e721df49431d23618sewardj            set_XER_OV_32( PPCG_FLAG_OP_DIVWEU,
39054aa412af1d8166cc11f39a6e721df49431d23618sewardj                           mkexpr(res), dividend, divisor );
39064aa412af1d8166cc11f39a6e721df49431d23618sewardj         }
39074aa412af1d8166cc11f39a6e721df49431d23618sewardj         break;
39084aa412af1d8166cc11f39a6e721df49431d23618sewardj      }
39094aa412af1d8166cc11f39a6e721df49431d23618sewardj
3910e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj      case 0x1AB: // divwe (Divide Word Extended)
3911e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj      {
3912e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj         /*
3913e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj          * If the quotient cannot be represented in 32 bits, or if an
3914e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj          * attempt is made to perform the division
3915e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj          *      <anything> / 0
3916e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj          * then the contents of register RD are undefined as are (if
3917e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj          * Rc=1) the contents of the LT, GT, and EQ bits of CR
3918e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj          * Field 0. In these cases, if OE=1 then OV is set to 1.
3919e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj          */
3920e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj
3921e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj         IRTemp res = newTemp(Ity_I32);
3922e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj         IRExpr * dividend, * divisor;
3923e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj         DIP("divwe%s%s r%u,r%u,r%u\n",
3924e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj             flag_OE ? "o" : "", flag_rC ? ".":"",
3925e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj                                         rD_addr, rA_addr, rB_addr);
3926e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj         if (mode64) {
3927e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj            dividend = unop( Iop_64to32, mkexpr( rA ) );
3928e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj            divisor = unop( Iop_64to32, mkexpr( rB ) );
3929e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj            assign( res, binop( Iop_DivS32E, dividend, divisor ) );
3930e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj            assign( rD, binop( Iop_32HLto64, mkU32( 0 ), mkexpr( res ) ) );
3931e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj         } else {
3932e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj            dividend = mkexpr( rA );
3933e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj            divisor =  mkexpr( rB );
3934e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj            assign( res, binop( Iop_DivS32E, dividend, divisor ) );
3935e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj            assign( rD, mkexpr( res) );
3936e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj         }
3937e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj
3938e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj         if (flag_OE) {
3939e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj            set_XER_OV_32( PPCG_FLAG_OP_DIVWE,
3940e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj                           mkexpr(res), dividend, divisor );
3941e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj         }
3942e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj         break;
3943e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj      }
3944e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj
3945e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj
39464aa412af1d8166cc11f39a6e721df49431d23618sewardj      case 0x1A9: // divde (Divide Doubleword Extended)
39474aa412af1d8166cc11f39a6e721df49431d23618sewardj        /*
39484aa412af1d8166cc11f39a6e721df49431d23618sewardj         * If the quotient cannot be represented in 64 bits, or if an
39494aa412af1d8166cc11f39a6e721df49431d23618sewardj         * attempt is made to perform the division
39504aa412af1d8166cc11f39a6e721df49431d23618sewardj         *      <anything> / 0
39514aa412af1d8166cc11f39a6e721df49431d23618sewardj         * then the contents of register RD are undefined as are (if
39524aa412af1d8166cc11f39a6e721df49431d23618sewardj         * Rc=1) the contents of the LT, GT, and EQ bits of CR
39534aa412af1d8166cc11f39a6e721df49431d23618sewardj         * Field 0. In these cases, if OE=1 then OV is set to 1.
39544aa412af1d8166cc11f39a6e721df49431d23618sewardj         */
39554aa412af1d8166cc11f39a6e721df49431d23618sewardj         DIP("divde%s%s r%u,r%u,r%u\n",
39564aa412af1d8166cc11f39a6e721df49431d23618sewardj             flag_OE ? "o" : "", flag_rC ? ".":"",
39574aa412af1d8166cc11f39a6e721df49431d23618sewardj             rD_addr, rA_addr, rB_addr);
39584aa412af1d8166cc11f39a6e721df49431d23618sewardj         assign( rD, binop(Iop_DivS64E, mkexpr(rA), mkexpr(rB)) );
39594aa412af1d8166cc11f39a6e721df49431d23618sewardj         if (flag_OE) {
39604aa412af1d8166cc11f39a6e721df49431d23618sewardj            set_XER_OV_64( PPCG_FLAG_OP_DIVDE, mkexpr( rD ),
39614aa412af1d8166cc11f39a6e721df49431d23618sewardj                           mkexpr( rA ), mkexpr( rB ) );
39624aa412af1d8166cc11f39a6e721df49431d23618sewardj         }
39634aa412af1d8166cc11f39a6e721df49431d23618sewardj         break;
39644aa412af1d8166cc11f39a6e721df49431d23618sewardj
3965e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj      case 0x189: //  divdeuo (Divide Doubleword Extended Unsigned)
3966e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj        // Same CR and OV rules as given for divweu above
3967e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj        DIP("divdeu%s%s r%u,r%u,r%u\n",
3968e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj            flag_OE ? "o" : "", flag_rC ? ".":"",
3969e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj            rD_addr, rA_addr, rB_addr);
3970e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj        assign( rD, binop(Iop_DivU64E, mkexpr(rA), mkexpr(rB)) );
3971e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj        if (flag_OE) {
3972e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj           set_XER_OV_64( PPCG_FLAG_OP_DIVDEU, mkexpr( rD ),
3973e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj                          mkexpr( rA ), mkexpr( rB ) );
3974e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj        }
3975e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj        break;
3976e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj
3977b85e8bba97fdae7d892f7bfd12e4601307e4721dcerion      default:
39785b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion         vex_printf("dis_int_arith(ppc)(opc2)\n");
3979b85e8bba97fdae7d892f7bfd12e4601307e4721dcerion         return False;
3980b85e8bba97fdae7d892f7bfd12e4601307e4721dcerion      }
3981b85e8bba97fdae7d892f7bfd12e4601307e4721dcerion      break;
3982f0de28cf1a762b0d6f74c93d3532c89a230673bbcerion
3983b85e8bba97fdae7d892f7bfd12e4601307e4721dcerion   default:
39845b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion      vex_printf("dis_int_arith(ppc)(opc1)\n");
3985b85e8bba97fdae7d892f7bfd12e4601307e4721dcerion      return False;
3986b85e8bba97fdae7d892f7bfd12e4601307e4721dcerion   }
3987b85e8bba97fdae7d892f7bfd12e4601307e4721dcerion
398876de5cf615380b23b4b5bcced6541233cd4a93a0cerion   putIReg( rD_addr, mkexpr(rD) );
398976de5cf615380b23b4b5bcced6541233cd4a93a0cerion
399076de5cf615380b23b4b5bcced6541233cd4a93a0cerion   if (do_rc && flag_rC) {
399176de5cf615380b23b4b5bcced6541233cd4a93a0cerion      set_CR0( mkexpr(rD) );
3992b85e8bba97fdae7d892f7bfd12e4601307e4721dcerion   }
3993b85e8bba97fdae7d892f7bfd12e4601307e4721dcerion   return True;
3994896a1373cfdbaa25f4ab73ed4f27554016defecccerion}
3995896a1373cfdbaa25f4ab73ed4f27554016defecccerion
3996896a1373cfdbaa25f4ab73ed4f27554016defecccerion
3997896a1373cfdbaa25f4ab73ed4f27554016defecccerion
39983d870a39e4d145e2f3d9f9a0eeed3475ec934ac1cerion/*
39993d870a39e4d145e2f3d9f9a0eeed3475ec934ac1cerion  Integer Compare Instructions
40003d870a39e4d145e2f3d9f9a0eeed3475ec934ac1cerion*/
40017aa4bbc850d2978cccd8e12cd7c4cfeaa5ab3e4dcerionstatic Bool dis_int_cmp ( UInt theInstr )
40027aa4bbc850d2978cccd8e12cd7c4cfeaa5ab3e4dcerion{
400376de5cf615380b23b4b5bcced6541233cd4a93a0cerion   /* D-Form, X-Form */
400476de5cf615380b23b4b5bcced6541233cd4a93a0cerion   UChar opc1    = ifieldOPC(theInstr);
400576de5cf615380b23b4b5bcced6541233cd4a93a0cerion   UChar crfD    = toUChar( IFIELD( theInstr, 23, 3 ) );
400676de5cf615380b23b4b5bcced6541233cd4a93a0cerion   UChar b22     = toUChar( IFIELD( theInstr, 22, 1 ) );
400776de5cf615380b23b4b5bcced6541233cd4a93a0cerion   UChar flag_L  = toUChar( IFIELD( theInstr, 21, 1 ) );
400876de5cf615380b23b4b5bcced6541233cd4a93a0cerion   UChar rA_addr = ifieldRegA(theInstr);
4009d953ebb9b04cbad6891676df597bf0c542b1ec89cerion   UInt  uimm16  = ifieldUIMM16(theInstr);
401076de5cf615380b23b4b5bcced6541233cd4a93a0cerion   UChar rB_addr = ifieldRegB(theInstr);
401176de5cf615380b23b4b5bcced6541233cd4a93a0cerion   UInt  opc2    = ifieldOPClo10(theInstr);
401276de5cf615380b23b4b5bcced6541233cd4a93a0cerion   UChar b0      = ifieldBIT0(theInstr);
401376de5cf615380b23b4b5bcced6541233cd4a93a0cerion
4014bb01b7cbfd84c27dd213f67a144ea5a99af36961cerion   IRType ty = mode64 ? Ity_I64 : Ity_I32;
4015bb01b7cbfd84c27dd213f67a144ea5a99af36961cerion   IRExpr *a = getIReg(rA_addr);
4016bb01b7cbfd84c27dd213f67a144ea5a99af36961cerion   IRExpr *b;
401776de5cf615380b23b4b5bcced6541233cd4a93a0cerion
4018d953ebb9b04cbad6891676df597bf0c542b1ec89cerion   if (!mode64 && flag_L==1) {  // L==1 invalid for 32 bit.
40195b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion      vex_printf("dis_int_cmp(ppc)(flag_L)\n");
4020b85e8bba97fdae7d892f7bfd12e4601307e4721dcerion      return False;
4021b85e8bba97fdae7d892f7bfd12e4601307e4721dcerion   }
4022b85e8bba97fdae7d892f7bfd12e4601307e4721dcerion
402376de5cf615380b23b4b5bcced6541233cd4a93a0cerion   if (b22 != 0) {
40245b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion      vex_printf("dis_int_cmp(ppc)(b22)\n");
4025b85e8bba97fdae7d892f7bfd12e4601307e4721dcerion      return False;
4026b85e8bba97fdae7d892f7bfd12e4601307e4721dcerion   }
4027b85e8bba97fdae7d892f7bfd12e4601307e4721dcerion
4028b85e8bba97fdae7d892f7bfd12e4601307e4721dcerion   switch (opc1) {
4029d953ebb9b04cbad6891676df597bf0c542b1ec89cerion   case 0x0B: // cmpi (Compare Immediate, PPC32 p368)
4030d953ebb9b04cbad6891676df597bf0c542b1ec89cerion      DIP("cmpi cr%u,%u,r%u,%d\n", crfD, flag_L, rA_addr,
4031d953ebb9b04cbad6891676df597bf0c542b1ec89cerion          (Int)extend_s_16to32(uimm16));
40322831b00c4950d6c2b061def05fd67528fe132ececerion      b = mkSzExtendS16( ty, uimm16 );
4033bb01b7cbfd84c27dd213f67a144ea5a99af36961cerion      if (flag_L == 1) {
40342831b00c4950d6c2b061def05fd67528fe132ececerion         putCR321(crfD, unop(Iop_64to8, binop(Iop_CmpORD64S, a, b)));
4035d953ebb9b04cbad6891676df597bf0c542b1ec89cerion      } else {
4036e9d8a26b690c2561ac54ab0cd6ad83ecbadcbe76sewardj         a = mkNarrowTo32( ty, a );
4037e9d8a26b690c2561ac54ab0cd6ad83ecbadcbe76sewardj         b = mkNarrowTo32( ty, b );
4038d953ebb9b04cbad6891676df597bf0c542b1ec89cerion         putCR321(crfD, unop(Iop_32to8, binop(Iop_CmpORD32S, a, b)));
4039d953ebb9b04cbad6891676df597bf0c542b1ec89cerion      }
4040d953ebb9b04cbad6891676df597bf0c542b1ec89cerion      putCR0( crfD, getXER_SO() );
4041d953ebb9b04cbad6891676df597bf0c542b1ec89cerion      break;
4042d953ebb9b04cbad6891676df597bf0c542b1ec89cerion
4043d953ebb9b04cbad6891676df597bf0c542b1ec89cerion   case 0x0A: // cmpli (Compare Logical Immediate, PPC32 p370)
4044d953ebb9b04cbad6891676df597bf0c542b1ec89cerion      DIP("cmpli cr%u,%u,r%u,0x%x\n", crfD, flag_L, rA_addr, uimm16);
40452831b00c4950d6c2b061def05fd67528fe132ececerion      b = mkSzImm( ty, uimm16 );
4046bb01b7cbfd84c27dd213f67a144ea5a99af36961cerion      if (flag_L == 1) {
40472831b00c4950d6c2b061def05fd67528fe132ececerion         putCR321(crfD, unop(Iop_64to8, binop(Iop_CmpORD64U, a, b)));
4048d953ebb9b04cbad6891676df597bf0c542b1ec89cerion      } else {
4049e9d8a26b690c2561ac54ab0cd6ad83ecbadcbe76sewardj         a = mkNarrowTo32( ty, a );
4050e9d8a26b690c2561ac54ab0cd6ad83ecbadcbe76sewardj         b = mkNarrowTo32( ty, b );
4051d953ebb9b04cbad6891676df597bf0c542b1ec89cerion         putCR321(crfD, unop(Iop_32to8, binop(Iop_CmpORD32U, a, b)));
4052d953ebb9b04cbad6891676df597bf0c542b1ec89cerion      }
4053d953ebb9b04cbad6891676df597bf0c542b1ec89cerion      putCR0( crfD, getXER_SO() );
4054d953ebb9b04cbad6891676df597bf0c542b1ec89cerion      break;
4055b85e8bba97fdae7d892f7bfd12e4601307e4721dcerion
4056b85e8bba97fdae7d892f7bfd12e4601307e4721dcerion   /* X Form */
4057b85e8bba97fdae7d892f7bfd12e4601307e4721dcerion   case 0x1F:
4058b85e8bba97fdae7d892f7bfd12e4601307e4721dcerion      if (b0 != 0) {
40595b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion         vex_printf("dis_int_cmp(ppc)(0x1F,b0)\n");
4060b85e8bba97fdae7d892f7bfd12e4601307e4721dcerion         return False;
4061b85e8bba97fdae7d892f7bfd12e4601307e4721dcerion      }
4062bb01b7cbfd84c27dd213f67a144ea5a99af36961cerion      b = getIReg(rB_addr);
4063c342f4ada40bc4c2c554d8ea69b325fe6f6439bacerion
4064b85e8bba97fdae7d892f7bfd12e4601307e4721dcerion      switch (opc2) {
4065d953ebb9b04cbad6891676df597bf0c542b1ec89cerion      case 0x000: // cmp (Compare, PPC32 p367)
4066d953ebb9b04cbad6891676df597bf0c542b1ec89cerion         DIP("cmp cr%u,%u,r%u,r%u\n", crfD, flag_L, rA_addr, rB_addr);
4067a9cb67bd4f3f27df6897a240d492bf17b798f10asewardj         /* Comparing a reg with itself produces a result which
4068a9cb67bd4f3f27df6897a240d492bf17b798f10asewardj            doesn't depend on the contents of the reg.  Therefore
4069a9cb67bd4f3f27df6897a240d492bf17b798f10asewardj            remove the false dependency, which has been known to cause
4070a9cb67bd4f3f27df6897a240d492bf17b798f10asewardj            memcheck to produce false errors. */
40719195aa111e0483b88cae8a4eb4e8455167b48942sewardj         if (rA_addr == rB_addr)
4072dd40fdf58cc8a6fe9466c4f00bdfc9fe9bf00449sewardj            a = b = typeOfIRExpr(irsb->tyenv,a) == Ity_I64
40739195aa111e0483b88cae8a4eb4e8455167b48942sewardj                    ? mkU64(0)  : mkU32(0);
4074bb01b7cbfd84c27dd213f67a144ea5a99af36961cerion         if (flag_L == 1) {
4075bb01b7cbfd84c27dd213f67a144ea5a99af36961cerion            putCR321(crfD, unop(Iop_64to8, binop(Iop_CmpORD64S, a, b)));
4076d953ebb9b04cbad6891676df597bf0c542b1ec89cerion         } else {
4077e9d8a26b690c2561ac54ab0cd6ad83ecbadcbe76sewardj            a = mkNarrowTo32( ty, a );
4078e9d8a26b690c2561ac54ab0cd6ad83ecbadcbe76sewardj            b = mkNarrowTo32( ty, b );
4079bb01b7cbfd84c27dd213f67a144ea5a99af36961cerion            putCR321(crfD, unop(Iop_32to8,binop(Iop_CmpORD32S, a, b)));
4080d953ebb9b04cbad6891676df597bf0c542b1ec89cerion         }
4081d953ebb9b04cbad6891676df597bf0c542b1ec89cerion         putCR0( crfD, getXER_SO() );
4082d953ebb9b04cbad6891676df597bf0c542b1ec89cerion         break;
4083b85e8bba97fdae7d892f7bfd12e4601307e4721dcerion
4084d953ebb9b04cbad6891676df597bf0c542b1ec89cerion      case 0x020: // cmpl (Compare Logical, PPC32 p369)
4085d953ebb9b04cbad6891676df597bf0c542b1ec89cerion         DIP("cmpl cr%u,%u,r%u,r%u\n", crfD, flag_L, rA_addr, rB_addr);
4086a9cb67bd4f3f27df6897a240d492bf17b798f10asewardj         /* Comparing a reg with itself produces a result which
4087a9cb67bd4f3f27df6897a240d492bf17b798f10asewardj            doesn't depend on the contents of the reg.  Therefore
4088a9cb67bd4f3f27df6897a240d492bf17b798f10asewardj            remove the false dependency, which has been known to cause
4089a9cb67bd4f3f27df6897a240d492bf17b798f10asewardj            memcheck to produce false errors. */
40909195aa111e0483b88cae8a4eb4e8455167b48942sewardj         if (rA_addr == rB_addr)
4091dd40fdf58cc8a6fe9466c4f00bdfc9fe9bf00449sewardj            a = b = typeOfIRExpr(irsb->tyenv,a) == Ity_I64
40929195aa111e0483b88cae8a4eb4e8455167b48942sewardj                    ? mkU64(0)  : mkU32(0);
4093bb01b7cbfd84c27dd213f67a144ea5a99af36961cerion         if (flag_L == 1) {
4094bb01b7cbfd84c27dd213f67a144ea5a99af36961cerion            putCR321(crfD, unop(Iop_64to8, binop(Iop_CmpORD64U, a, b)));
4095d953ebb9b04cbad6891676df597bf0c542b1ec89cerion         } else {
4096e9d8a26b690c2561ac54ab0cd6ad83ecbadcbe76sewardj            a = mkNarrowTo32( ty, a );
4097e9d8a26b690c2561ac54ab0cd6ad83ecbadcbe76sewardj            b = mkNarrowTo32( ty, b );
4098bb01b7cbfd84c27dd213f67a144ea5a99af36961cerion            putCR321(crfD, unop(Iop_32to8, binop(Iop_CmpORD32U, a, b)));
4099d953ebb9b04cbad6891676df597bf0c542b1ec89cerion         }
4100d953ebb9b04cbad6891676df597bf0c542b1ec89cerion         putCR0( crfD, getXER_SO() );
4101d953ebb9b04cbad6891676df597bf0c542b1ec89cerion         break;
4102b51f0f4f33256638ed953156a2635aa739b232f1sewardj
4103d953ebb9b04cbad6891676df597bf0c542b1ec89cerion      default:
41045b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion         vex_printf("dis_int_cmp(ppc)(opc2)\n");
4105d953ebb9b04cbad6891676df597bf0c542b1ec89cerion         return False;
4106b85e8bba97fdae7d892f7bfd12e4601307e4721dcerion      }
4107b85e8bba97fdae7d892f7bfd12e4601307e4721dcerion      break;
4108d953ebb9b04cbad6891676df597bf0c542b1ec89cerion
4109b85e8bba97fdae7d892f7bfd12e4601307e4721dcerion   default:
41105b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion      vex_printf("dis_int_cmp(ppc)(opc1)\n");
4111b85e8bba97fdae7d892f7bfd12e4601307e4721dcerion      return False;
4112b85e8bba97fdae7d892f7bfd12e4601307e4721dcerion   }
4113b85e8bba97fdae7d892f7bfd12e4601307e4721dcerion
4114b85e8bba97fdae7d892f7bfd12e4601307e4721dcerion   return True;
41157aa4bbc850d2978cccd8e12cd7c4cfeaa5ab3e4dcerion}
41167aa4bbc850d2978cccd8e12cd7c4cfeaa5ab3e4dcerion
41177aa4bbc850d2978cccd8e12cd7c4cfeaa5ab3e4dcerion
41183d870a39e4d145e2f3d9f9a0eeed3475ec934ac1cerion/*
41193d870a39e4d145e2f3d9f9a0eeed3475ec934ac1cerion  Integer Logical Instructions
41203d870a39e4d145e2f3d9f9a0eeed3475ec934ac1cerion*/
41217aa4bbc850d2978cccd8e12cd7c4cfeaa5ab3e4dcerionstatic Bool dis_int_logic ( UInt theInstr )
41227aa4bbc850d2978cccd8e12cd7c4cfeaa5ab3e4dcerion{
412376de5cf615380b23b4b5bcced6541233cd4a93a0cerion   /* D-Form, X-Form */
412476de5cf615380b23b4b5bcced6541233cd4a93a0cerion   UChar opc1    = ifieldOPC(theInstr);
412576de5cf615380b23b4b5bcced6541233cd4a93a0cerion   UChar rS_addr = ifieldRegDS(theInstr);
412676de5cf615380b23b4b5bcced6541233cd4a93a0cerion   UChar rA_addr = ifieldRegA(theInstr);
4127d953ebb9b04cbad6891676df597bf0c542b1ec89cerion   UInt  uimm16  = ifieldUIMM16(theInstr);
412876de5cf615380b23b4b5bcced6541233cd4a93a0cerion   UChar rB_addr = ifieldRegB(theInstr);
412976de5cf615380b23b4b5bcced6541233cd4a93a0cerion   UInt  opc2    = ifieldOPClo10(theInstr);
413076de5cf615380b23b4b5bcced6541233cd4a93a0cerion   UChar flag_rC = ifieldBIT0(theInstr);
4131b85e8bba97fdae7d892f7bfd12e4601307e4721dcerion
4132d953ebb9b04cbad6891676df597bf0c542b1ec89cerion   IRType ty     = mode64 ? Ity_I64 : Ity_I32;
4133d953ebb9b04cbad6891676df597bf0c542b1ec89cerion   IRTemp rS     = newTemp(ty);
4134d953ebb9b04cbad6891676df597bf0c542b1ec89cerion   IRTemp rA     = newTemp(ty);
4135d953ebb9b04cbad6891676df597bf0c542b1ec89cerion   IRTemp rB     = newTemp(ty);
4136e9d361ab43518b6dfbd3d846f48859534659dee0cerion   IRExpr* irx;
4137d953ebb9b04cbad6891676df597bf0c542b1ec89cerion   Bool do_rc    = False;
4138d953ebb9b04cbad6891676df597bf0c542b1ec89cerion
413976de5cf615380b23b4b5bcced6541233cd4a93a0cerion   assign( rS, getIReg(rS_addr) );
414076de5cf615380b23b4b5bcced6541233cd4a93a0cerion   assign( rB, getIReg(rB_addr) );
4141b85e8bba97fdae7d892f7bfd12e4601307e4721dcerion
4142b85e8bba97fdae7d892f7bfd12e4601307e4721dcerion   switch (opc1) {
4143e9d361ab43518b6dfbd3d846f48859534659dee0cerion   case 0x1C: // andi. (AND Immediate, PPC32 p358)
4144d953ebb9b04cbad6891676df597bf0c542b1ec89cerion      DIP("andi. r%u,r%u,0x%x\n", rA_addr, rS_addr, uimm16);
41452831b00c4950d6c2b061def05fd67528fe132ececerion      assign( rA, binop( mkSzOp(ty, Iop_And8), mkexpr(rS),
41462831b00c4950d6c2b061def05fd67528fe132ececerion                         mkSzImm(ty, uimm16)) );
414770e2412f623c955d7b199f09401732cf57417fc2cerion      do_rc = True;  // Always record to CR
414876de5cf615380b23b4b5bcced6541233cd4a93a0cerion      flag_rC = 1;
4149b85e8bba97fdae7d892f7bfd12e4601307e4721dcerion      break;
4150b85e8bba97fdae7d892f7bfd12e4601307e4721dcerion
4151e9d361ab43518b6dfbd3d846f48859534659dee0cerion   case 0x1D: // andis. (AND Immediate Shifted, PPC32 p359)
4152d953ebb9b04cbad6891676df597bf0c542b1ec89cerion      DIP("andis r%u,r%u,0x%x\n", rA_addr, rS_addr, uimm16);
41532831b00c4950d6c2b061def05fd67528fe132ececerion      assign( rA, binop( mkSzOp(ty, Iop_And8), mkexpr(rS),
41542831b00c4950d6c2b061def05fd67528fe132ececerion                         mkSzImm(ty, uimm16 << 16)) );
415570e2412f623c955d7b199f09401732cf57417fc2cerion      do_rc = True;  // Always record to CR
415676de5cf615380b23b4b5bcced6541233cd4a93a0cerion      flag_rC = 1;
4157b85e8bba97fdae7d892f7bfd12e4601307e4721dcerion      break;
4158b85e8bba97fdae7d892f7bfd12e4601307e4721dcerion
4159e9d361ab43518b6dfbd3d846f48859534659dee0cerion   case 0x18: // ori (OR Immediate, PPC32 p497)
4160d953ebb9b04cbad6891676df597bf0c542b1ec89cerion      DIP("ori r%u,r%u,0x%x\n", rA_addr, rS_addr, uimm16);
41612831b00c4950d6c2b061def05fd67528fe132ececerion      assign( rA, binop( mkSzOp(ty, Iop_Or8), mkexpr(rS),
41622831b00c4950d6c2b061def05fd67528fe132ececerion                         mkSzImm(ty, uimm16)) );
4163b85e8bba97fdae7d892f7bfd12e4601307e4721dcerion      break;
4164b85e8bba97fdae7d892f7bfd12e4601307e4721dcerion
4165e9d361ab43518b6dfbd3d846f48859534659dee0cerion   case 0x19: // oris (OR Immediate Shifted, PPC32 p498)
4166d953ebb9b04cbad6891676df597bf0c542b1ec89cerion      DIP("oris r%u,r%u,0x%x\n", rA_addr, rS_addr, uimm16);
41672831b00c4950d6c2b061def05fd67528fe132ececerion      assign( rA, binop( mkSzOp(ty, Iop_Or8), mkexpr(rS),
41682831b00c4950d6c2b061def05fd67528fe132ececerion                         mkSzImm(ty, uimm16 << 16)) );
4169b85e8bba97fdae7d892f7bfd12e4601307e4721dcerion      break;
4170b85e8bba97fdae7d892f7bfd12e4601307e4721dcerion
4171e9d361ab43518b6dfbd3d846f48859534659dee0cerion   case 0x1A: // xori (XOR Immediate, PPC32 p550)
4172d953ebb9b04cbad6891676df597bf0c542b1ec89cerion      DIP("xori r%u,r%u,0x%x\n", rA_addr, rS_addr, uimm16);
41732831b00c4950d6c2b061def05fd67528fe132ececerion      assign( rA, binop( mkSzOp(ty, Iop_Xor8), mkexpr(rS),
41742831b00c4950d6c2b061def05fd67528fe132ececerion                         mkSzImm(ty, uimm16)) );
4175b85e8bba97fdae7d892f7bfd12e4601307e4721dcerion      break;
4176b85e8bba97fdae7d892f7bfd12e4601307e4721dcerion
4177e9d361ab43518b6dfbd3d846f48859534659dee0cerion   case 0x1B: // xoris (XOR Immediate Shifted, PPC32 p551)
4178d953ebb9b04cbad6891676df597bf0c542b1ec89cerion      DIP("xoris r%u,r%u,0x%x\n", rA_addr, rS_addr, uimm16);
41792831b00c4950d6c2b061def05fd67528fe132ececerion      assign( rA, binop( mkSzOp(ty, Iop_Xor8), mkexpr(rS),
41802831b00c4950d6c2b061def05fd67528fe132ececerion                         mkSzImm(ty, uimm16 << 16)) );
4181b85e8bba97fdae7d892f7bfd12e4601307e4721dcerion      break;
4182b85e8bba97fdae7d892f7bfd12e4601307e4721dcerion
4183b85e8bba97fdae7d892f7bfd12e4601307e4721dcerion   /* X Form */
4184b85e8bba97fdae7d892f7bfd12e4601307e4721dcerion   case 0x1F:
41854aa412af1d8166cc11f39a6e721df49431d23618sewardj      do_rc = True; // All below record to CR, except for where we return at case end.
418670e2412f623c955d7b199f09401732cf57417fc2cerion
4187b85e8bba97fdae7d892f7bfd12e4601307e4721dcerion      switch (opc2) {
4188d953ebb9b04cbad6891676df597bf0c542b1ec89cerion      case 0x01C: // and (AND, PPC32 p356)
4189d953ebb9b04cbad6891676df597bf0c542b1ec89cerion         DIP("and%s r%u,r%u,r%u\n",
41905b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion             flag_rC ? ".":"", rA_addr, rS_addr, rB_addr);
41912831b00c4950d6c2b061def05fd67528fe132ececerion         assign(rA, binop( mkSzOp(ty, Iop_And8),
4192d953ebb9b04cbad6891676df597bf0c542b1ec89cerion                           mkexpr(rS), mkexpr(rB)));
4193d953ebb9b04cbad6891676df597bf0c542b1ec89cerion         break;
4194b85e8bba97fdae7d892f7bfd12e4601307e4721dcerion
4195d953ebb9b04cbad6891676df597bf0c542b1ec89cerion      case 0x03C: // andc (AND with Complement, PPC32 p357)
4196d953ebb9b04cbad6891676df597bf0c542b1ec89cerion         DIP("andc%s r%u,r%u,r%u\n",
41975b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion             flag_rC ? ".":"", rA_addr, rS_addr, rB_addr);
41982831b00c4950d6c2b061def05fd67528fe132ececerion         assign(rA, binop( mkSzOp(ty, Iop_And8), mkexpr(rS),
41992831b00c4950d6c2b061def05fd67528fe132ececerion                           unop( mkSzOp(ty, Iop_Not8),
4200d953ebb9b04cbad6891676df597bf0c542b1ec89cerion                                 mkexpr(rB))));
4201d953ebb9b04cbad6891676df597bf0c542b1ec89cerion         break;
4202d953ebb9b04cbad6891676df597bf0c542b1ec89cerion
4203d953ebb9b04cbad6891676df597bf0c542b1ec89cerion      case 0x01A: { // cntlzw (Count Leading Zeros Word, PPC32 p371)
4204d953ebb9b04cbad6891676df597bf0c542b1ec89cerion         IRExpr* lo32;
4205d953ebb9b04cbad6891676df597bf0c542b1ec89cerion         if (rB_addr!=0) {
42065b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion            vex_printf("dis_int_logic(ppc)(cntlzw,rB_addr)\n");
4207d953ebb9b04cbad6891676df597bf0c542b1ec89cerion            return False;
4208d953ebb9b04cbad6891676df597bf0c542b1ec89cerion         }
4209d953ebb9b04cbad6891676df597bf0c542b1ec89cerion         DIP("cntlzw%s r%u,r%u\n",
42105b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion             flag_rC ? ".":"", rA_addr, rS_addr);
4211d953ebb9b04cbad6891676df597bf0c542b1ec89cerion
4212d953ebb9b04cbad6891676df597bf0c542b1ec89cerion         // mode64: count in low word only
4213d953ebb9b04cbad6891676df597bf0c542b1ec89cerion         lo32 = mode64 ? unop(Iop_64to32, mkexpr(rS)) : mkexpr(rS);
4214d953ebb9b04cbad6891676df597bf0c542b1ec89cerion
4215d953ebb9b04cbad6891676df597bf0c542b1ec89cerion         // Iop_Clz32 undefined for arg==0, so deal with that case:
4216d953ebb9b04cbad6891676df597bf0c542b1ec89cerion         irx =  binop(Iop_CmpNE32, lo32, mkU32(0));
4217e9d8a26b690c2561ac54ab0cd6ad83ecbadcbe76sewardj         assign(rA, mkWidenFrom32(ty,
421899dd03e04a6914d90d5fee727d61d76905334becflorian                         IRExpr_ITE( irx,
421999dd03e04a6914d90d5fee727d61d76905334becflorian                                     unop(Iop_Clz32, lo32),
422099dd03e04a6914d90d5fee727d61d76905334becflorian                                     mkU32(32)),
42215b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion                         False));
42225b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion
4223d953ebb9b04cbad6891676df597bf0c542b1ec89cerion         // TODO: alternatively: assign(rA, verbose_Clz32(rS));
4224d953ebb9b04cbad6891676df597bf0c542b1ec89cerion         break;
4225d953ebb9b04cbad6891676df597bf0c542b1ec89cerion      }
4226b85e8bba97fdae7d892f7bfd12e4601307e4721dcerion
422720ef5472eac767474c93b7835364a23f24c0ec5dsewardj      case 0x11C: // eqv (Equivalent, PPC32 p396)
4228d953ebb9b04cbad6891676df597bf0c542b1ec89cerion         DIP("eqv%s r%u,r%u,r%u\n",
42295b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion             flag_rC ? ".":"", rA_addr, rS_addr, rB_addr);
42302831b00c4950d6c2b061def05fd67528fe132ececerion         assign( rA, unop( mkSzOp(ty, Iop_Not8),
42312831b00c4950d6c2b061def05fd67528fe132ececerion                           binop( mkSzOp(ty, Iop_Xor8),
4232d953ebb9b04cbad6891676df597bf0c542b1ec89cerion                                  mkexpr(rS), mkexpr(rB))) );
423320ef5472eac767474c93b7835364a23f24c0ec5dsewardj         break;
4234b85e8bba97fdae7d892f7bfd12e4601307e4721dcerion
4235e9d361ab43518b6dfbd3d846f48859534659dee0cerion      case 0x3BA: // extsb (Extend Sign Byte, PPC32 p397
423676de5cf615380b23b4b5bcced6541233cd4a93a0cerion         if (rB_addr!=0) {
42375b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion            vex_printf("dis_int_logic(ppc)(extsb,rB_addr)\n");
4238b85e8bba97fdae7d892f7bfd12e4601307e4721dcerion            return False;
4239b85e8bba97fdae7d892f7bfd12e4601307e4721dcerion         }
4240d953ebb9b04cbad6891676df597bf0c542b1ec89cerion         DIP("extsb%s r%u,r%u\n",
42415b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion             flag_rC ? ".":"", rA_addr, rS_addr);
4242d953ebb9b04cbad6891676df597bf0c542b1ec89cerion         if (mode64)
4243d953ebb9b04cbad6891676df597bf0c542b1ec89cerion            assign( rA, unop(Iop_8Sto64, unop(Iop_64to8, mkexpr(rS))) );
4244d953ebb9b04cbad6891676df597bf0c542b1ec89cerion         else
4245d953ebb9b04cbad6891676df597bf0c542b1ec89cerion            assign( rA, unop(Iop_8Sto32, unop(Iop_32to8, mkexpr(rS))) );
4246b85e8bba97fdae7d892f7bfd12e4601307e4721dcerion         break;
4247b85e8bba97fdae7d892f7bfd12e4601307e4721dcerion
4248e9d361ab43518b6dfbd3d846f48859534659dee0cerion      case 0x39A: // extsh (Extend Sign Half Word, PPC32 p398)
424976de5cf615380b23b4b5bcced6541233cd4a93a0cerion         if (rB_addr!=0) {
42505b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion            vex_printf("dis_int_logic(ppc)(extsh,rB_addr)\n");
4251b85e8bba97fdae7d892f7bfd12e4601307e4721dcerion            return False;
4252b85e8bba97fdae7d892f7bfd12e4601307e4721dcerion         }
4253d953ebb9b04cbad6891676df597bf0c542b1ec89cerion         DIP("extsh%s r%u,r%u\n",
42545b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion             flag_rC ? ".":"", rA_addr, rS_addr);
4255d953ebb9b04cbad6891676df597bf0c542b1ec89cerion         if (mode64)
42565b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion            assign( rA, unop(Iop_16Sto64,
42575b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion                             unop(Iop_64to16, mkexpr(rS))) );
4258d953ebb9b04cbad6891676df597bf0c542b1ec89cerion         else
42595b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion            assign( rA, unop(Iop_16Sto32,
42605b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion                             unop(Iop_32to16, mkexpr(rS))) );
4261b85e8bba97fdae7d892f7bfd12e4601307e4721dcerion         break;
4262b85e8bba97fdae7d892f7bfd12e4601307e4721dcerion
4263e9d361ab43518b6dfbd3d846f48859534659dee0cerion      case 0x1DC: // nand (NAND, PPC32 p492)
4264d953ebb9b04cbad6891676df597bf0c542b1ec89cerion         DIP("nand%s r%u,r%u,r%u\n",
42655b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion             flag_rC ? ".":"", rA_addr, rS_addr, rB_addr);
42662831b00c4950d6c2b061def05fd67528fe132ececerion         assign( rA, unop( mkSzOp(ty, Iop_Not8),
42672831b00c4950d6c2b061def05fd67528fe132ececerion                           binop( mkSzOp(ty, Iop_And8),
4268d953ebb9b04cbad6891676df597bf0c542b1ec89cerion                                  mkexpr(rS), mkexpr(rB))) );
4269b85e8bba97fdae7d892f7bfd12e4601307e4721dcerion         break;
4270b85e8bba97fdae7d892f7bfd12e4601307e4721dcerion
4271e9d361ab43518b6dfbd3d846f48859534659dee0cerion      case 0x07C: // nor (NOR, PPC32 p494)
4272d953ebb9b04cbad6891676df597bf0c542b1ec89cerion         DIP("nor%s r%u,r%u,r%u\n",
42735b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion             flag_rC ? ".":"", rA_addr, rS_addr, rB_addr);
42742831b00c4950d6c2b061def05fd67528fe132ececerion         assign( rA, unop( mkSzOp(ty, Iop_Not8),
42752831b00c4950d6c2b061def05fd67528fe132ececerion                           binop( mkSzOp(ty, Iop_Or8),
4276d953ebb9b04cbad6891676df597bf0c542b1ec89cerion                                  mkexpr(rS), mkexpr(rB))) );
4277b85e8bba97fdae7d892f7bfd12e4601307e4721dcerion         break;
4278b85e8bba97fdae7d892f7bfd12e4601307e4721dcerion
4279e9d361ab43518b6dfbd3d846f48859534659dee0cerion      case 0x1BC: // or (OR, PPC32 p495)
428076de5cf615380b23b4b5bcced6541233cd4a93a0cerion         if ((!flag_rC) && rS_addr == rB_addr) {
4281d953ebb9b04cbad6891676df597bf0c542b1ec89cerion            DIP("mr r%u,r%u\n", rA_addr, rS_addr);
428276de5cf615380b23b4b5bcced6541233cd4a93a0cerion            assign( rA, mkexpr(rS) );
4283b51f0f4f33256638ed953156a2635aa739b232f1sewardj         } else {
4284d953ebb9b04cbad6891676df597bf0c542b1ec89cerion            DIP("or%s r%u,r%u,r%u\n",
42855b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion                flag_rC ? ".":"", rA_addr, rS_addr, rB_addr);
42862831b00c4950d6c2b061def05fd67528fe132ececerion            assign( rA, binop( mkSzOp(ty, Iop_Or8),
4287d953ebb9b04cbad6891676df597bf0c542b1ec89cerion                               mkexpr(rS), mkexpr(rB)) );
4288b51f0f4f33256638ed953156a2635aa739b232f1sewardj         }
4289b85e8bba97fdae7d892f7bfd12e4601307e4721dcerion         break;
4290b85e8bba97fdae7d892f7bfd12e4601307e4721dcerion
4291e9d361ab43518b6dfbd3d846f48859534659dee0cerion      case 0x19C: // orc  (OR with Complement, PPC32 p496)
4292d953ebb9b04cbad6891676df597bf0c542b1ec89cerion         DIP("orc%s r%u,r%u,r%u\n",
42935b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion             flag_rC ? ".":"", rA_addr, rS_addr, rB_addr);
42942831b00c4950d6c2b061def05fd67528fe132ececerion         assign( rA, binop( mkSzOp(ty, Iop_Or8), mkexpr(rS),
42952831b00c4950d6c2b061def05fd67528fe132ececerion                            unop(mkSzOp(ty, Iop_Not8), mkexpr(rB))));
4296b85e8bba97fdae7d892f7bfd12e4601307e4721dcerion         break;
4297b85e8bba97fdae7d892f7bfd12e4601307e4721dcerion
4298e9d361ab43518b6dfbd3d846f48859534659dee0cerion      case 0x13C: // xor (XOR, PPC32 p549)
4299d953ebb9b04cbad6891676df597bf0c542b1ec89cerion         DIP("xor%s r%u,r%u,r%u\n",
43005b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion             flag_rC ? ".":"", rA_addr, rS_addr, rB_addr);
43012831b00c4950d6c2b061def05fd67528fe132ececerion         assign( rA, binop( mkSzOp(ty, Iop_Xor8),
4302d953ebb9b04cbad6891676df597bf0c542b1ec89cerion                            mkexpr(rS), mkexpr(rB)) );
4303b85e8bba97fdae7d892f7bfd12e4601307e4721dcerion         break;
4304b85e8bba97fdae7d892f7bfd12e4601307e4721dcerion
4305f0de28cf1a762b0d6f74c93d3532c89a230673bbcerion
4306f0de28cf1a762b0d6f74c93d3532c89a230673bbcerion      /* 64bit Integer Logical Instructions */
4307f0de28cf1a762b0d6f74c93d3532c89a230673bbcerion      case 0x3DA: // extsw (Extend Sign Word, PPC64 p430)
4308f0de28cf1a762b0d6f74c93d3532c89a230673bbcerion         if (rB_addr!=0) {
43095b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion            vex_printf("dis_int_logic(ppc)(extsw,rB_addr)\n");
4310f0de28cf1a762b0d6f74c93d3532c89a230673bbcerion            return False;
4311f0de28cf1a762b0d6f74c93d3532c89a230673bbcerion         }
43125b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion         DIP("extsw%s r%u,r%u\n", flag_rC ? ".":"", rA_addr, rS_addr);
4313f0de28cf1a762b0d6f74c93d3532c89a230673bbcerion         assign(rA, unop(Iop_32Sto64, unop(Iop_64to32, mkexpr(rS))));
4314f0de28cf1a762b0d6f74c93d3532c89a230673bbcerion         break;
4315f0de28cf1a762b0d6f74c93d3532c89a230673bbcerion
43165b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion      case 0x03A: // cntlzd (Count Leading Zeros DWord, PPC64 p401)
4317f0de28cf1a762b0d6f74c93d3532c89a230673bbcerion         if (rB_addr!=0) {
43185b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion            vex_printf("dis_int_logic(ppc)(cntlzd,rB_addr)\n");
4319f0de28cf1a762b0d6f74c93d3532c89a230673bbcerion            return False;
4320f0de28cf1a762b0d6f74c93d3532c89a230673bbcerion         }
43215b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion         DIP("cntlzd%s r%u,r%u\n",
43225b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion             flag_rC ? ".":"", rA_addr, rS_addr);
432307b07a966a2fdbcf621251a0c1a8ab84807fb120cerion         // Iop_Clz64 undefined for arg==0, so deal with that case:
432407b07a966a2fdbcf621251a0c1a8ab84807fb120cerion         irx =  binop(Iop_CmpNE64, mkexpr(rS), mkU64(0));
432599dd03e04a6914d90d5fee727d61d76905334becflorian         assign(rA, IRExpr_ITE( irx,
432699dd03e04a6914d90d5fee727d61d76905334becflorian                                unop(Iop_Clz64, mkexpr(rS)),
432799dd03e04a6914d90d5fee727d61d76905334becflorian                                mkU64(64) ));
43285b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion         // TODO: alternatively: assign(rA, verbose_Clz64(rS));
432907b07a966a2fdbcf621251a0c1a8ab84807fb120cerion         break;
4330f0de28cf1a762b0d6f74c93d3532c89a230673bbcerion
43317e84630580f89c1022dde97007bffbf6aef81814sewardj      case 0x1FC: // cmpb (Power6: compare bytes)
43327e84630580f89c1022dde97007bffbf6aef81814sewardj         DIP("cmpb r%u,r%u,r%u\n", rA_addr, rS_addr, rB_addr);
43337e84630580f89c1022dde97007bffbf6aef81814sewardj
43347e84630580f89c1022dde97007bffbf6aef81814sewardj         if (mode64)
43357e84630580f89c1022dde97007bffbf6aef81814sewardj            assign( rA, unop( Iop_V128to64,
43367e84630580f89c1022dde97007bffbf6aef81814sewardj                              binop( Iop_CmpEQ8x16,
43377e84630580f89c1022dde97007bffbf6aef81814sewardj                                     binop( Iop_64HLtoV128, mkU64(0), mkexpr(rS) ),
43387e84630580f89c1022dde97007bffbf6aef81814sewardj                                     binop( Iop_64HLtoV128, mkU64(0), mkexpr(rB) )
43397e84630580f89c1022dde97007bffbf6aef81814sewardj                                     )) );
43407e84630580f89c1022dde97007bffbf6aef81814sewardj         else
43417e84630580f89c1022dde97007bffbf6aef81814sewardj            assign( rA, unop( Iop_V128to32,
43427e84630580f89c1022dde97007bffbf6aef81814sewardj                              binop( Iop_CmpEQ8x16,
43437e84630580f89c1022dde97007bffbf6aef81814sewardj                                     unop( Iop_32UtoV128, mkexpr(rS) ),
43447e84630580f89c1022dde97007bffbf6aef81814sewardj                                     unop( Iop_32UtoV128, mkexpr(rB) )
43457e84630580f89c1022dde97007bffbf6aef81814sewardj                                     )) );
43467e84630580f89c1022dde97007bffbf6aef81814sewardj         break;
43477e84630580f89c1022dde97007bffbf6aef81814sewardj
43487e84630580f89c1022dde97007bffbf6aef81814sewardj      case 0x2DF: { // mftgpr (move floating-point to general purpose register)
43497e84630580f89c1022dde97007bffbf6aef81814sewardj         IRTemp frB = newTemp(Ity_F64);
43507e84630580f89c1022dde97007bffbf6aef81814sewardj         DIP("mftgpr r%u,fr%u\n", rS_addr, rB_addr);
43517e84630580f89c1022dde97007bffbf6aef81814sewardj
43527e84630580f89c1022dde97007bffbf6aef81814sewardj         assign( frB, getFReg(rB_addr));  // always F64
43537e84630580f89c1022dde97007bffbf6aef81814sewardj         if (mode64)
43547e84630580f89c1022dde97007bffbf6aef81814sewardj            assign( rA, unop( Iop_ReinterpF64asI64, mkexpr(frB)) );
43557e84630580f89c1022dde97007bffbf6aef81814sewardj         else
43567e84630580f89c1022dde97007bffbf6aef81814sewardj            assign( rA, unop( Iop_64to32, unop( Iop_ReinterpF64asI64, mkexpr(frB))) );
43577e84630580f89c1022dde97007bffbf6aef81814sewardj
43587e84630580f89c1022dde97007bffbf6aef81814sewardj         putIReg( rS_addr, mkexpr(rA));
43597e84630580f89c1022dde97007bffbf6aef81814sewardj         return True;
43607e84630580f89c1022dde97007bffbf6aef81814sewardj      }
43617e84630580f89c1022dde97007bffbf6aef81814sewardj
43627e84630580f89c1022dde97007bffbf6aef81814sewardj      case 0x25F: { // mffgpr (move floating-point from general purpose register)
43637e84630580f89c1022dde97007bffbf6aef81814sewardj         IRTemp frA = newTemp(Ity_F64);
43647e84630580f89c1022dde97007bffbf6aef81814sewardj         DIP("mffgpr fr%u,r%u\n", rS_addr, rB_addr);
43657e84630580f89c1022dde97007bffbf6aef81814sewardj
43667e84630580f89c1022dde97007bffbf6aef81814sewardj         if (mode64)
43677e84630580f89c1022dde97007bffbf6aef81814sewardj            assign( frA, unop( Iop_ReinterpI64asF64, mkexpr(rB)) );
43687e84630580f89c1022dde97007bffbf6aef81814sewardj         else
43697e84630580f89c1022dde97007bffbf6aef81814sewardj            assign( frA, unop( Iop_ReinterpI64asF64, unop( Iop_32Uto64, mkexpr(rB))) );
43707e84630580f89c1022dde97007bffbf6aef81814sewardj
43717e84630580f89c1022dde97007bffbf6aef81814sewardj         putFReg( rS_addr, mkexpr(frA));
43727e84630580f89c1022dde97007bffbf6aef81814sewardj         return True;
43737e84630580f89c1022dde97007bffbf6aef81814sewardj      }
437466d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj      case 0x1FA: // popcntd (population count doubleword
437566d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj      {
437666d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj    	  DIP("popcntd r%u,r%u\n", rA_addr, rS_addr);
43777deaf9552b546b847528cf39b38898fb7742b5f5carll    	  IRTemp result = gen_POPCOUNT(ty, rS, DWORD);
437866d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj    	  putIReg( rA_addr, mkexpr(result) );
437966d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj    	  return True;
438066d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj      }
4381e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj      case 0x17A: // popcntw (Population Count Words)
4382e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj      {
4383e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj         DIP("popcntw r%u,r%u\n", rA_addr, rS_addr);
4384e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj         if (mode64) {
4385e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj            IRTemp resultHi, resultLo;
4386e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj            IRTemp argLo = newTemp(Ity_I32);
4387e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj            IRTemp argHi = newTemp(Ity_I32);
4388e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj            assign(argLo, unop(Iop_64to32, mkexpr(rS)));
4389e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj            assign(argHi, unop(Iop_64HIto32, mkexpr(rS)));
43907deaf9552b546b847528cf39b38898fb7742b5f5carll            resultLo = gen_POPCOUNT(Ity_I32, argLo, WORD);
43917deaf9552b546b847528cf39b38898fb7742b5f5carll            resultHi = gen_POPCOUNT(Ity_I32, argHi, WORD);
4392e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj            putIReg( rA_addr, binop(Iop_32HLto64, mkexpr(resultHi), mkexpr(resultLo)));
4393e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj         } else {
43947deaf9552b546b847528cf39b38898fb7742b5f5carll            IRTemp result = gen_POPCOUNT(ty, rS, WORD);
4395738d9dddf788cd66fc04081f5fca872f38859813philippe            putIReg( rA_addr, mkexpr(result) );
4396738d9dddf788cd66fc04081f5fca872f38859813philippe         }
4397738d9dddf788cd66fc04081f5fca872f38859813philippe         return True;
4398738d9dddf788cd66fc04081f5fca872f38859813philippe      }
4399738d9dddf788cd66fc04081f5fca872f38859813philippe      case 0x7A: // popcntb (Population Count Byte)
4400738d9dddf788cd66fc04081f5fca872f38859813philippe      {
4401738d9dddf788cd66fc04081f5fca872f38859813philippe         DIP("popcntb r%u,r%u\n", rA_addr, rS_addr);
4402738d9dddf788cd66fc04081f5fca872f38859813philippe
4403738d9dddf788cd66fc04081f5fca872f38859813philippe         if (mode64) {
4404738d9dddf788cd66fc04081f5fca872f38859813philippe            IRTemp resultHi, resultLo;
4405738d9dddf788cd66fc04081f5fca872f38859813philippe            IRTemp argLo = newTemp(Ity_I32);
4406738d9dddf788cd66fc04081f5fca872f38859813philippe            IRTemp argHi = newTemp(Ity_I32);
4407738d9dddf788cd66fc04081f5fca872f38859813philippe            assign(argLo, unop(Iop_64to32, mkexpr(rS)));
4408738d9dddf788cd66fc04081f5fca872f38859813philippe            assign(argHi, unop(Iop_64HIto32, mkexpr(rS)));
44097deaf9552b546b847528cf39b38898fb7742b5f5carll            resultLo = gen_POPCOUNT(Ity_I32, argLo, BYTE);
44107deaf9552b546b847528cf39b38898fb7742b5f5carll            resultHi = gen_POPCOUNT(Ity_I32, argHi, BYTE);
4411738d9dddf788cd66fc04081f5fca872f38859813philippe            putIReg( rA_addr, binop(Iop_32HLto64, mkexpr(resultHi),
4412738d9dddf788cd66fc04081f5fca872f38859813philippe                                    mkexpr(resultLo)));
4413738d9dddf788cd66fc04081f5fca872f38859813philippe         } else {
44147deaf9552b546b847528cf39b38898fb7742b5f5carll            IRTemp result = gen_POPCOUNT(ty, rS, BYTE);
4415e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj            putIReg( rA_addr, mkexpr(result) );
4416e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj         }
4417e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj         return True;
4418e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj      }
44194aa412af1d8166cc11f39a6e721df49431d23618sewardj       case 0x0FC: // bpermd (Bit Permute Doubleword)
44204aa412af1d8166cc11f39a6e721df49431d23618sewardj       {
44214aa412af1d8166cc11f39a6e721df49431d23618sewardj          /* This is a lot of rigmarole to emulate bpermd like this, as it
44224aa412af1d8166cc11f39a6e721df49431d23618sewardj           * could be done much faster by implementing a call to the native
44234aa412af1d8166cc11f39a6e721df49431d23618sewardj           * instruction.  However, where possible I want to avoid using new
44244aa412af1d8166cc11f39a6e721df49431d23618sewardj           * native instructions so that we can use valgrind to emulate those
44254aa412af1d8166cc11f39a6e721df49431d23618sewardj           * instructions on older PPC64 hardware.
44264aa412af1d8166cc11f39a6e721df49431d23618sewardj           */
44274aa412af1d8166cc11f39a6e721df49431d23618sewardj #define BPERMD_IDX_MASK 0x00000000000000FFULL
44284aa412af1d8166cc11f39a6e721df49431d23618sewardj #define BPERMD_BIT_MASK 0x8000000000000000ULL
44294aa412af1d8166cc11f39a6e721df49431d23618sewardj          int i;
44304aa412af1d8166cc11f39a6e721df49431d23618sewardj          IRExpr * rS_expr = mkexpr(rS);
44314aa412af1d8166cc11f39a6e721df49431d23618sewardj          IRExpr * res = binop(Iop_And64, mkU64(0), mkU64(0));
44324aa412af1d8166cc11f39a6e721df49431d23618sewardj          DIP("bpermd r%u,r%u,r%u\n", rA_addr, rS_addr, rB_addr);
44334aa412af1d8166cc11f39a6e721df49431d23618sewardj          for (i = 0; i < 8; i++) {
44344aa412af1d8166cc11f39a6e721df49431d23618sewardj             IRTemp idx_tmp = newTemp( Ity_I64 );
44354aa412af1d8166cc11f39a6e721df49431d23618sewardj             IRTemp perm_bit = newTemp( Ity_I64 );
44364aa412af1d8166cc11f39a6e721df49431d23618sewardj             IRTemp idx = newTemp( Ity_I8 );
44374aa412af1d8166cc11f39a6e721df49431d23618sewardj             IRTemp idx_LT64 = newTemp( Ity_I1 );
44384aa412af1d8166cc11f39a6e721df49431d23618sewardj             IRTemp idx_LT64_ity64 = newTemp( Ity_I64 );
44394aa412af1d8166cc11f39a6e721df49431d23618sewardj
44404aa412af1d8166cc11f39a6e721df49431d23618sewardj             assign( idx_tmp,
44414aa412af1d8166cc11f39a6e721df49431d23618sewardj                     binop( Iop_And64, mkU64( BPERMD_IDX_MASK ), rS_expr ) );
44424aa412af1d8166cc11f39a6e721df49431d23618sewardj             assign( idx_LT64,
44434aa412af1d8166cc11f39a6e721df49431d23618sewardj                           binop( Iop_CmpLT64U, mkexpr( idx_tmp ), mkU64( 64 ) ) );
44444aa412af1d8166cc11f39a6e721df49431d23618sewardj             assign( idx,
44454aa412af1d8166cc11f39a6e721df49431d23618sewardj                           binop( Iop_And8,
44464aa412af1d8166cc11f39a6e721df49431d23618sewardj                                  unop( Iop_1Sto8,
44474aa412af1d8166cc11f39a6e721df49431d23618sewardj                                        mkexpr(idx_LT64) ),
44484aa412af1d8166cc11f39a6e721df49431d23618sewardj                                  unop( Iop_64to8, mkexpr( idx_tmp ) ) ) );
44494aa412af1d8166cc11f39a6e721df49431d23618sewardj             /* If idx_LT64 == 0, we must force the perm bit to '0'. Below, we se idx
44504aa412af1d8166cc11f39a6e721df49431d23618sewardj              * to determine which bit of rB to use for the perm bit, and then we shift
44514aa412af1d8166cc11f39a6e721df49431d23618sewardj              * that bit to the MSB position.  We AND that with a 64-bit-ized idx_LT64
44524aa412af1d8166cc11f39a6e721df49431d23618sewardj              * to set the final perm bit.
44534aa412af1d8166cc11f39a6e721df49431d23618sewardj              */
44544aa412af1d8166cc11f39a6e721df49431d23618sewardj             assign( idx_LT64_ity64,
44554aa412af1d8166cc11f39a6e721df49431d23618sewardj                           unop( Iop_32Uto64, unop( Iop_1Uto32, mkexpr(idx_LT64 ) ) ) );
44564aa412af1d8166cc11f39a6e721df49431d23618sewardj             assign( perm_bit,
44574aa412af1d8166cc11f39a6e721df49431d23618sewardj                           binop( Iop_And64,
44584aa412af1d8166cc11f39a6e721df49431d23618sewardj                                  mkexpr( idx_LT64_ity64 ),
44594aa412af1d8166cc11f39a6e721df49431d23618sewardj                                  binop( Iop_Shr64,
44604aa412af1d8166cc11f39a6e721df49431d23618sewardj                                         binop( Iop_And64,
44614aa412af1d8166cc11f39a6e721df49431d23618sewardj                                                mkU64( BPERMD_BIT_MASK ),
44624aa412af1d8166cc11f39a6e721df49431d23618sewardj                                                binop( Iop_Shl64,
44634aa412af1d8166cc11f39a6e721df49431d23618sewardj                                                       mkexpr( rB ),
44644aa412af1d8166cc11f39a6e721df49431d23618sewardj                                                       mkexpr( idx ) ) ),
44654aa412af1d8166cc11f39a6e721df49431d23618sewardj                                         mkU8( 63 ) ) ) );
44664aa412af1d8166cc11f39a6e721df49431d23618sewardj             res = binop( Iop_Or64,
44674aa412af1d8166cc11f39a6e721df49431d23618sewardj                                res,
44684aa412af1d8166cc11f39a6e721df49431d23618sewardj                                binop( Iop_Shl64,
44694aa412af1d8166cc11f39a6e721df49431d23618sewardj                                       mkexpr( perm_bit ),
44704aa412af1d8166cc11f39a6e721df49431d23618sewardj                                       mkU8( i ) ) );
44714aa412af1d8166cc11f39a6e721df49431d23618sewardj             rS_expr = binop( Iop_Shr64, rS_expr, mkU8( 8 ) );
44724aa412af1d8166cc11f39a6e721df49431d23618sewardj          }
44734aa412af1d8166cc11f39a6e721df49431d23618sewardj          putIReg(rA_addr, res);
44744aa412af1d8166cc11f39a6e721df49431d23618sewardj          return True;
44754aa412af1d8166cc11f39a6e721df49431d23618sewardj       }
44764aa412af1d8166cc11f39a6e721df49431d23618sewardj
4477b85e8bba97fdae7d892f7bfd12e4601307e4721dcerion      default:
44785b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion         vex_printf("dis_int_logic(ppc)(opc2)\n");
4479b85e8bba97fdae7d892f7bfd12e4601307e4721dcerion         return False;
4480b85e8bba97fdae7d892f7bfd12e4601307e4721dcerion      }
4481b85e8bba97fdae7d892f7bfd12e4601307e4721dcerion      break;
4482b85e8bba97fdae7d892f7bfd12e4601307e4721dcerion
4483b85e8bba97fdae7d892f7bfd12e4601307e4721dcerion   default:
44845b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion      vex_printf("dis_int_logic(ppc)(opc1)\n");
4485b85e8bba97fdae7d892f7bfd12e4601307e4721dcerion      return False;
4486b85e8bba97fdae7d892f7bfd12e4601307e4721dcerion   }
448770e2412f623c955d7b199f09401732cf57417fc2cerion
448876de5cf615380b23b4b5bcced6541233cd4a93a0cerion   putIReg( rA_addr, mkexpr(rA) );
448976de5cf615380b23b4b5bcced6541233cd4a93a0cerion
449076de5cf615380b23b4b5bcced6541233cd4a93a0cerion   if (do_rc && flag_rC) {
449176de5cf615380b23b4b5bcced6541233cd4a93a0cerion      set_CR0( mkexpr(rA) );
4492b85e8bba97fdae7d892f7bfd12e4601307e4721dcerion   }
4493b85e8bba97fdae7d892f7bfd12e4601307e4721dcerion   return True;
4494645c930b1a61f4493ee2d472b34fbb439233a874cerion}
4495645c930b1a61f4493ee2d472b34fbb439233a874cerion
44967e84630580f89c1022dde97007bffbf6aef81814sewardj/*
44977e84630580f89c1022dde97007bffbf6aef81814sewardj  Integer Parity Instructions
44987e84630580f89c1022dde97007bffbf6aef81814sewardj*/
44997e84630580f89c1022dde97007bffbf6aef81814sewardjstatic Bool dis_int_parity ( UInt theInstr )
45007e84630580f89c1022dde97007bffbf6aef81814sewardj{
45017e84630580f89c1022dde97007bffbf6aef81814sewardj   /* X-Form */
45027e84630580f89c1022dde97007bffbf6aef81814sewardj   UChar opc1    = ifieldOPC(theInstr);
45037e84630580f89c1022dde97007bffbf6aef81814sewardj   UChar rS_addr = ifieldRegDS(theInstr);
45047e84630580f89c1022dde97007bffbf6aef81814sewardj   UChar rA_addr = ifieldRegA(theInstr);
45057e84630580f89c1022dde97007bffbf6aef81814sewardj   UChar rB_addr = ifieldRegB(theInstr);
45067e84630580f89c1022dde97007bffbf6aef81814sewardj   UInt  opc2    = ifieldOPClo10(theInstr);
45077e84630580f89c1022dde97007bffbf6aef81814sewardj   UChar b0      = ifieldBIT0(theInstr);
45087e84630580f89c1022dde97007bffbf6aef81814sewardj   IRType ty     = mode64 ? Ity_I64 : Ity_I32;
45097e84630580f89c1022dde97007bffbf6aef81814sewardj
45107e84630580f89c1022dde97007bffbf6aef81814sewardj   IRTemp rS     = newTemp(ty);
45117e84630580f89c1022dde97007bffbf6aef81814sewardj   IRTemp rA     = newTemp(ty);
45127e84630580f89c1022dde97007bffbf6aef81814sewardj   IRTemp iTot1  = newTemp(Ity_I32);
45137e84630580f89c1022dde97007bffbf6aef81814sewardj   IRTemp iTot2  = newTemp(Ity_I32);
45147e84630580f89c1022dde97007bffbf6aef81814sewardj   IRTemp iTot3  = newTemp(Ity_I32);
45157e84630580f89c1022dde97007bffbf6aef81814sewardj   IRTemp iTot4  = newTemp(Ity_I32);
45167e84630580f89c1022dde97007bffbf6aef81814sewardj   IRTemp iTot5  = newTemp(Ity_I32);
45177e84630580f89c1022dde97007bffbf6aef81814sewardj   IRTemp iTot6  = newTemp(Ity_I32);
45187e84630580f89c1022dde97007bffbf6aef81814sewardj   IRTemp iTot7  = newTemp(Ity_I32);
45197e84630580f89c1022dde97007bffbf6aef81814sewardj   IRTemp iTot8  = newTemp(Ity_I32);
45207e84630580f89c1022dde97007bffbf6aef81814sewardj   IRTemp rS1    = newTemp(ty);
45217e84630580f89c1022dde97007bffbf6aef81814sewardj   IRTemp rS2    = newTemp(ty);
45227e84630580f89c1022dde97007bffbf6aef81814sewardj   IRTemp rS3    = newTemp(ty);
45237e84630580f89c1022dde97007bffbf6aef81814sewardj   IRTemp rS4    = newTemp(ty);
45247e84630580f89c1022dde97007bffbf6aef81814sewardj   IRTemp rS5    = newTemp(ty);
45257e84630580f89c1022dde97007bffbf6aef81814sewardj   IRTemp rS6    = newTemp(ty);
45267e84630580f89c1022dde97007bffbf6aef81814sewardj   IRTemp rS7    = newTemp(ty);
45277e84630580f89c1022dde97007bffbf6aef81814sewardj   IRTemp iHi    = newTemp(Ity_I32);
45287e84630580f89c1022dde97007bffbf6aef81814sewardj   IRTemp iLo    = newTemp(Ity_I32);
45297e84630580f89c1022dde97007bffbf6aef81814sewardj   IROp to_bit   = (mode64 ? Iop_64to1 : Iop_32to1);
45307e84630580f89c1022dde97007bffbf6aef81814sewardj   IROp shr_op   = (mode64 ? Iop_Shr64 : Iop_Shr32);
45317e84630580f89c1022dde97007bffbf6aef81814sewardj
45327e84630580f89c1022dde97007bffbf6aef81814sewardj   if (opc1 != 0x1f || rB_addr || b0) {
45337e84630580f89c1022dde97007bffbf6aef81814sewardj      vex_printf("dis_int_parity(ppc)(0x1F,opc1:rB|b0)\n");
45347e84630580f89c1022dde97007bffbf6aef81814sewardj      return False;
45357e84630580f89c1022dde97007bffbf6aef81814sewardj   }
45367e84630580f89c1022dde97007bffbf6aef81814sewardj
45377e84630580f89c1022dde97007bffbf6aef81814sewardj   assign( rS, getIReg(rS_addr) );
45387e84630580f89c1022dde97007bffbf6aef81814sewardj
45397e84630580f89c1022dde97007bffbf6aef81814sewardj   switch (opc2) {
45407e84630580f89c1022dde97007bffbf6aef81814sewardj   case 0xba:  // prtyd (Parity Doubleword, ISA 2.05 p320)
45417e84630580f89c1022dde97007bffbf6aef81814sewardj      DIP("prtyd r%u,r%u\n", rA_addr, rS_addr);
45427e84630580f89c1022dde97007bffbf6aef81814sewardj      assign( iTot1, unop(Iop_1Uto32, unop(to_bit, mkexpr(rS))) );
45437e84630580f89c1022dde97007bffbf6aef81814sewardj      assign( rS1, binop(shr_op, mkexpr(rS), mkU8(8)) );
45447e84630580f89c1022dde97007bffbf6aef81814sewardj      assign( iTot2, binop(Iop_Add32,
45457e84630580f89c1022dde97007bffbf6aef81814sewardj                           unop(Iop_1Uto32, unop(to_bit, mkexpr(rS1))),
45467e84630580f89c1022dde97007bffbf6aef81814sewardj                           mkexpr(iTot1)) );
45477e84630580f89c1022dde97007bffbf6aef81814sewardj      assign( rS2, binop(shr_op, mkexpr(rS1), mkU8(8)) );
45487e84630580f89c1022dde97007bffbf6aef81814sewardj      assign( iTot3, binop(Iop_Add32,
45497e84630580f89c1022dde97007bffbf6aef81814sewardj                           unop(Iop_1Uto32, unop(to_bit, mkexpr(rS2))),
45507e84630580f89c1022dde97007bffbf6aef81814sewardj                           mkexpr(iTot2)) );
45517e84630580f89c1022dde97007bffbf6aef81814sewardj      assign( rS3, binop(shr_op, mkexpr(rS2), mkU8(8)) );
45527e84630580f89c1022dde97007bffbf6aef81814sewardj      assign( iTot4, binop(Iop_Add32,
45537e84630580f89c1022dde97007bffbf6aef81814sewardj                           unop(Iop_1Uto32, unop(to_bit, mkexpr(rS3))),
45547e84630580f89c1022dde97007bffbf6aef81814sewardj                           mkexpr(iTot3)) );
45557e84630580f89c1022dde97007bffbf6aef81814sewardj      if (mode64) {
45567e84630580f89c1022dde97007bffbf6aef81814sewardj         assign( rS4, binop(shr_op, mkexpr(rS3), mkU8(8)) );
45577e84630580f89c1022dde97007bffbf6aef81814sewardj         assign( iTot5, binop(Iop_Add32,
45587e84630580f89c1022dde97007bffbf6aef81814sewardj                              unop(Iop_1Uto32, unop(to_bit, mkexpr(rS4))),
45597e84630580f89c1022dde97007bffbf6aef81814sewardj                              mkexpr(iTot4)) );
45607e84630580f89c1022dde97007bffbf6aef81814sewardj         assign( rS5, binop(shr_op, mkexpr(rS4), mkU8(8)) );
45617e84630580f89c1022dde97007bffbf6aef81814sewardj         assign( iTot6, binop(Iop_Add32,
45627e84630580f89c1022dde97007bffbf6aef81814sewardj                              unop(Iop_1Uto32, unop(to_bit, mkexpr(rS5))),
45637e84630580f89c1022dde97007bffbf6aef81814sewardj                              mkexpr(iTot5)) );
45647e84630580f89c1022dde97007bffbf6aef81814sewardj         assign( rS6, binop(shr_op, mkexpr(rS5), mkU8(8)) );
45657e84630580f89c1022dde97007bffbf6aef81814sewardj         assign( iTot7, binop(Iop_Add32,
45667e84630580f89c1022dde97007bffbf6aef81814sewardj                              unop(Iop_1Uto32, unop(to_bit, mkexpr(rS6))),
45677e84630580f89c1022dde97007bffbf6aef81814sewardj                              mkexpr(iTot6)) );
45687e84630580f89c1022dde97007bffbf6aef81814sewardj         assign( rS7, binop(shr_op, mkexpr(rS6), mkU8(8)) );
45697e84630580f89c1022dde97007bffbf6aef81814sewardj         assign( iTot8, binop(Iop_Add32,
45707e84630580f89c1022dde97007bffbf6aef81814sewardj                              unop(Iop_1Uto32, unop(to_bit, mkexpr(rS7))),
45717e84630580f89c1022dde97007bffbf6aef81814sewardj                              mkexpr(iTot7)) );
45727e84630580f89c1022dde97007bffbf6aef81814sewardj         assign( rA, unop(Iop_32Uto64,
45737e84630580f89c1022dde97007bffbf6aef81814sewardj                          binop(Iop_And32, mkexpr(iTot8), mkU32(1))) );
45747e84630580f89c1022dde97007bffbf6aef81814sewardj      } else
45757e84630580f89c1022dde97007bffbf6aef81814sewardj         assign( rA, mkexpr(iTot4) );
45767e84630580f89c1022dde97007bffbf6aef81814sewardj
45777e84630580f89c1022dde97007bffbf6aef81814sewardj      break;
45787e84630580f89c1022dde97007bffbf6aef81814sewardj   case 0x9a:  // prtyw (Parity Word, ISA 2.05 p320)
45797e84630580f89c1022dde97007bffbf6aef81814sewardj      assign( iTot1, unop(Iop_1Uto32, unop(to_bit, mkexpr(rS))) );
45807e84630580f89c1022dde97007bffbf6aef81814sewardj      assign( rS1, binop(shr_op, mkexpr(rS), mkU8(8)) );
45817e84630580f89c1022dde97007bffbf6aef81814sewardj      assign( iTot2, binop(Iop_Add32,
45827e84630580f89c1022dde97007bffbf6aef81814sewardj                           unop(Iop_1Uto32, unop(to_bit, mkexpr(rS1))),
45837e84630580f89c1022dde97007bffbf6aef81814sewardj                           mkexpr(iTot1)) );
45847e84630580f89c1022dde97007bffbf6aef81814sewardj      assign( rS2, binop(shr_op, mkexpr(rS1), mkU8(8)) );
45857e84630580f89c1022dde97007bffbf6aef81814sewardj      assign( iTot3, binop(Iop_Add32,
45867e84630580f89c1022dde97007bffbf6aef81814sewardj                           unop(Iop_1Uto32, unop(to_bit, mkexpr(rS2))),
45877e84630580f89c1022dde97007bffbf6aef81814sewardj                           mkexpr(iTot2)) );
45887e84630580f89c1022dde97007bffbf6aef81814sewardj      assign( rS3, binop(shr_op, mkexpr(rS2), mkU8(8)) );
45897e84630580f89c1022dde97007bffbf6aef81814sewardj      assign( iTot4, binop(Iop_Add32,
45907e84630580f89c1022dde97007bffbf6aef81814sewardj                           unop(Iop_1Uto32, unop(to_bit, mkexpr(rS3))),
45917e84630580f89c1022dde97007bffbf6aef81814sewardj                           mkexpr(iTot3)) );
45927e84630580f89c1022dde97007bffbf6aef81814sewardj      assign( iLo, unop(Iop_1Uto32, unop(Iop_32to1, mkexpr(iTot4) )) );
45937e84630580f89c1022dde97007bffbf6aef81814sewardj
45947e84630580f89c1022dde97007bffbf6aef81814sewardj      if (mode64) {
45957e84630580f89c1022dde97007bffbf6aef81814sewardj         assign( rS4, binop(shr_op, mkexpr(rS3), mkU8(8)) );
45967e84630580f89c1022dde97007bffbf6aef81814sewardj         assign( iTot5, unop(Iop_1Uto32, unop(to_bit, mkexpr(rS4))) );
45977e84630580f89c1022dde97007bffbf6aef81814sewardj         assign( rS5, binop(shr_op, mkexpr(rS4), mkU8(8)) );
45987e84630580f89c1022dde97007bffbf6aef81814sewardj         assign( iTot6, binop(Iop_Add32,
45997e84630580f89c1022dde97007bffbf6aef81814sewardj                              unop(Iop_1Uto32, unop(to_bit, mkexpr(rS5))),
46007e84630580f89c1022dde97007bffbf6aef81814sewardj                              mkexpr(iTot5)) );
46017e84630580f89c1022dde97007bffbf6aef81814sewardj         assign( rS6, binop(shr_op, mkexpr(rS5), mkU8(8)) );
46027e84630580f89c1022dde97007bffbf6aef81814sewardj         assign( iTot7, binop(Iop_Add32,
46037e84630580f89c1022dde97007bffbf6aef81814sewardj                              unop(Iop_1Uto32, unop(to_bit, mkexpr(rS6))),
46047e84630580f89c1022dde97007bffbf6aef81814sewardj                              mkexpr(iTot6)) );
46057e84630580f89c1022dde97007bffbf6aef81814sewardj         assign( rS7, binop(shr_op, mkexpr(rS6), mkU8(8)));
46067e84630580f89c1022dde97007bffbf6aef81814sewardj         assign( iTot8, binop(Iop_Add32,
46077e84630580f89c1022dde97007bffbf6aef81814sewardj                              unop(Iop_1Uto32, unop(to_bit, mkexpr(rS7))),
46087e84630580f89c1022dde97007bffbf6aef81814sewardj                              mkexpr(iTot7)) );
46097e84630580f89c1022dde97007bffbf6aef81814sewardj         assign( iHi, binop(Iop_And32, mkU32(1), mkexpr(iTot8)) ),
46107e84630580f89c1022dde97007bffbf6aef81814sewardj            assign( rA, binop(Iop_32HLto64, mkexpr(iHi), mkexpr(iLo)) );
46117e84630580f89c1022dde97007bffbf6aef81814sewardj      } else
46127e84630580f89c1022dde97007bffbf6aef81814sewardj         assign( rA, binop(Iop_Or32, mkU32(0), mkexpr(iLo)) );
46137e84630580f89c1022dde97007bffbf6aef81814sewardj      break;
46147e84630580f89c1022dde97007bffbf6aef81814sewardj   default:
46157e84630580f89c1022dde97007bffbf6aef81814sewardj      vex_printf("dis_int_parity(ppc)(opc2)\n");
46167e84630580f89c1022dde97007bffbf6aef81814sewardj      return False;
46177e84630580f89c1022dde97007bffbf6aef81814sewardj   }
46187e84630580f89c1022dde97007bffbf6aef81814sewardj
46197e84630580f89c1022dde97007bffbf6aef81814sewardj   putIReg( rA_addr, mkexpr(rA) );
46207e84630580f89c1022dde97007bffbf6aef81814sewardj
46217e84630580f89c1022dde97007bffbf6aef81814sewardj   return True;
46227e84630580f89c1022dde97007bffbf6aef81814sewardj}
4623645c930b1a61f4493ee2d472b34fbb439233a874cerion
4624645c930b1a61f4493ee2d472b34fbb439233a874cerion
46253d870a39e4d145e2f3d9f9a0eeed3475ec934ac1cerion/*
46263d870a39e4d145e2f3d9f9a0eeed3475ec934ac1cerion  Integer Rotate Instructions
46273d870a39e4d145e2f3d9f9a0eeed3475ec934ac1cerion*/
4628645c930b1a61f4493ee2d472b34fbb439233a874cerionstatic Bool dis_int_rot ( UInt theInstr )
4629645c930b1a61f4493ee2d472b34fbb439233a874cerion{
4630f0de28cf1a762b0d6f74c93d3532c89a230673bbcerion   /* M-Form, MDS-Form */
4631d953ebb9b04cbad6891676df597bf0c542b1ec89cerion   UChar opc1    = ifieldOPC(theInstr);
4632d953ebb9b04cbad6891676df597bf0c542b1ec89cerion   UChar rS_addr = ifieldRegDS(theInstr);
4633d953ebb9b04cbad6891676df597bf0c542b1ec89cerion   UChar rA_addr = ifieldRegA(theInstr);
4634d953ebb9b04cbad6891676df597bf0c542b1ec89cerion   UChar rB_addr = ifieldRegB(theInstr);
4635d953ebb9b04cbad6891676df597bf0c542b1ec89cerion   UChar sh_imm  = rB_addr;
4636d953ebb9b04cbad6891676df597bf0c542b1ec89cerion   UChar MaskBeg = toUChar( IFIELD( theInstr, 6, 5 ) );
4637d953ebb9b04cbad6891676df597bf0c542b1ec89cerion   UChar MaskEnd = toUChar( IFIELD( theInstr, 1, 5 ) );
4638f0de28cf1a762b0d6f74c93d3532c89a230673bbcerion   UChar msk_imm = toUChar( IFIELD( theInstr, 5, 6 ) );
4639f0de28cf1a762b0d6f74c93d3532c89a230673bbcerion   UChar opc2    = toUChar( IFIELD( theInstr, 2, 3 ) );
4640f0de28cf1a762b0d6f74c93d3532c89a230673bbcerion   UChar b1      = ifieldBIT1(theInstr);
4641d953ebb9b04cbad6891676df597bf0c542b1ec89cerion   UChar flag_rC = ifieldBIT0(theInstr);
4642d953ebb9b04cbad6891676df597bf0c542b1ec89cerion
4643d953ebb9b04cbad6891676df597bf0c542b1ec89cerion   IRType ty     = mode64 ? Ity_I64 : Ity_I32;
4644d953ebb9b04cbad6891676df597bf0c542b1ec89cerion   IRTemp rS     = newTemp(ty);
4645d953ebb9b04cbad6891676df597bf0c542b1ec89cerion   IRTemp rA     = newTemp(ty);
4646d953ebb9b04cbad6891676df597bf0c542b1ec89cerion   IRTemp rB     = newTemp(ty);
4647bb01b7cbfd84c27dd213f67a144ea5a99af36961cerion   IRTemp rot    = newTemp(ty);
4648d953ebb9b04cbad6891676df597bf0c542b1ec89cerion   IRExpr *r;
4649f0de28cf1a762b0d6f74c93d3532c89a230673bbcerion   UInt   mask32;
4650f0de28cf1a762b0d6f74c93d3532c89a230673bbcerion   ULong  mask64;
465176de5cf615380b23b4b5bcced6541233cd4a93a0cerion
465276de5cf615380b23b4b5bcced6541233cd4a93a0cerion   assign( rS, getIReg(rS_addr) );
465376de5cf615380b23b4b5bcced6541233cd4a93a0cerion   assign( rB, getIReg(rB_addr) );
4654d953ebb9b04cbad6891676df597bf0c542b1ec89cerion
4655b85e8bba97fdae7d892f7bfd12e4601307e4721dcerion   switch (opc1) {
4656d953ebb9b04cbad6891676df597bf0c542b1ec89cerion   case 0x14: {
46575b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion      // rlwimi (Rotate Left Word Imm then Mask Insert, PPC32 p500)
46585b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion      DIP("rlwimi%s r%u,r%u,%d,%d,%d\n", flag_rC ? ".":"",
4659d953ebb9b04cbad6891676df597bf0c542b1ec89cerion          rA_addr, rS_addr, sh_imm, MaskBeg, MaskEnd);
4660d953ebb9b04cbad6891676df597bf0c542b1ec89cerion      if (mode64) {
4661d953ebb9b04cbad6891676df597bf0c542b1ec89cerion         // tmp32 = (ROTL(rS_Lo32, Imm)
4662d953ebb9b04cbad6891676df597bf0c542b1ec89cerion         // rA = ((tmp32 || tmp32) & mask64) | (rA & ~mask64)
4663f0de28cf1a762b0d6f74c93d3532c89a230673bbcerion         mask64 = MASK64(31-MaskEnd, 31-MaskBeg);
4664d953ebb9b04cbad6891676df597bf0c542b1ec89cerion         r = ROTL( unop(Iop_64to32, mkexpr(rS) ), mkU8(sh_imm) );
4665d953ebb9b04cbad6891676df597bf0c542b1ec89cerion         r = unop(Iop_32Uto64, r);
46665b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion         assign( rot, binop(Iop_Or64, r,
46675b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion                            binop(Iop_Shl64, r, mkU8(32))) );
4668d953ebb9b04cbad6891676df597bf0c542b1ec89cerion         assign( rA,
4669d953ebb9b04cbad6891676df597bf0c542b1ec89cerion            binop(Iop_Or64,
4670bb01b7cbfd84c27dd213f67a144ea5a99af36961cerion                  binop(Iop_And64, mkexpr(rot), mkU64(mask64)),
4671f0de28cf1a762b0d6f74c93d3532c89a230673bbcerion                  binop(Iop_And64, getIReg(rA_addr), mkU64(~mask64))) );
4672d953ebb9b04cbad6891676df597bf0c542b1ec89cerion      }
4673d953ebb9b04cbad6891676df597bf0c542b1ec89cerion      else {
4674d953ebb9b04cbad6891676df597bf0c542b1ec89cerion         // rA = (ROTL(rS, Imm) & mask) | (rA & ~mask);
4675f0de28cf1a762b0d6f74c93d3532c89a230673bbcerion         mask32 = MASK32(31-MaskEnd, 31-MaskBeg);
4676f0de28cf1a762b0d6f74c93d3532c89a230673bbcerion         r = ROTL(mkexpr(rS), mkU8(sh_imm));
4677d953ebb9b04cbad6891676df597bf0c542b1ec89cerion         assign( rA,
4678d953ebb9b04cbad6891676df597bf0c542b1ec89cerion            binop(Iop_Or32,
4679f0de28cf1a762b0d6f74c93d3532c89a230673bbcerion                  binop(Iop_And32, mkU32(mask32), r),
4680f0de28cf1a762b0d6f74c93d3532c89a230673bbcerion                  binop(Iop_And32, getIReg(rA_addr), mkU32(~mask32))) );
4681d953ebb9b04cbad6891676df597bf0c542b1ec89cerion      }
4682b85e8bba97fdae7d892f7bfd12e4601307e4721dcerion      break;
4683d953ebb9b04cbad6891676df597bf0c542b1ec89cerion   }
4684b85e8bba97fdae7d892f7bfd12e4601307e4721dcerion
4685d953ebb9b04cbad6891676df597bf0c542b1ec89cerion   case 0x15: {
46865b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion      // rlwinm (Rotate Left Word Imm then AND with Mask, PPC32 p501)
4687d953ebb9b04cbad6891676df597bf0c542b1ec89cerion      vassert(MaskBeg < 32);
4688d953ebb9b04cbad6891676df597bf0c542b1ec89cerion      vassert(MaskEnd < 32);
4689d953ebb9b04cbad6891676df597bf0c542b1ec89cerion      vassert(sh_imm  < 32);
4690d953ebb9b04cbad6891676df597bf0c542b1ec89cerion
4691d953ebb9b04cbad6891676df597bf0c542b1ec89cerion      if (mode64) {
4692ef4433b5487a1a639af07883417a1d5cb75eee89sewardj         IRTemp rTmp = newTemp(Ity_I64);
4693f0de28cf1a762b0d6f74c93d3532c89a230673bbcerion         mask64 = MASK64(31-MaskEnd, 31-MaskBeg);
46945b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion         DIP("rlwinm%s r%u,r%u,%d,%d,%d\n", flag_rC ? ".":"",
4695d953ebb9b04cbad6891676df597bf0c542b1ec89cerion             rA_addr, rS_addr, sh_imm, MaskBeg, MaskEnd);
4696d953ebb9b04cbad6891676df597bf0c542b1ec89cerion         // tmp32 = (ROTL(rS_Lo32, Imm)
4697d953ebb9b04cbad6891676df597bf0c542b1ec89cerion         // rA = ((tmp32 || tmp32) & mask64)
4698d953ebb9b04cbad6891676df597bf0c542b1ec89cerion         r = ROTL( unop(Iop_64to32, mkexpr(rS) ), mkU8(sh_imm) );
4699d953ebb9b04cbad6891676df597bf0c542b1ec89cerion         r = unop(Iop_32Uto64, r);
4700ef4433b5487a1a639af07883417a1d5cb75eee89sewardj         assign( rTmp, r );
4701ef4433b5487a1a639af07883417a1d5cb75eee89sewardj         r = NULL;
4702ef4433b5487a1a639af07883417a1d5cb75eee89sewardj         assign( rot, binop(Iop_Or64, mkexpr(rTmp),
4703ef4433b5487a1a639af07883417a1d5cb75eee89sewardj                            binop(Iop_Shl64, mkexpr(rTmp), mkU8(32))) );
4704bb01b7cbfd84c27dd213f67a144ea5a99af36961cerion         assign( rA, binop(Iop_And64, mkexpr(rot), mkU64(mask64)) );
470526b3320973ccdd634fc5461d832e86b3b6aa878fsewardj      }
470626b3320973ccdd634fc5461d832e86b3b6aa878fsewardj      else {
4707d953ebb9b04cbad6891676df597bf0c542b1ec89cerion         if (MaskBeg == 0 && sh_imm+MaskEnd == 31) {
4708d953ebb9b04cbad6891676df597bf0c542b1ec89cerion            /* Special-case the ,n,0,31-n form as that is just n-bit
47095b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion               shift left, PPC32 p501 */
47105b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion            DIP("slwi%s r%u,r%u,%d\n", flag_rC ? ".":"",
4711d953ebb9b04cbad6891676df597bf0c542b1ec89cerion                rA_addr, rS_addr, sh_imm);
4712d953ebb9b04cbad6891676df597bf0c542b1ec89cerion            assign( rA, binop(Iop_Shl32, mkexpr(rS), mkU8(sh_imm)) );
4713d953ebb9b04cbad6891676df597bf0c542b1ec89cerion         }
47142831b00c4950d6c2b061def05fd67528fe132ececerion         else if (MaskEnd == 31 && sh_imm+MaskBeg == 32) {
47152831b00c4950d6c2b061def05fd67528fe132ececerion            /* Special-case the ,32-n,n,31 form as that is just n-bit
47165b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion               unsigned shift right, PPC32 p501 */
47175b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion            DIP("srwi%s r%u,r%u,%d\n", flag_rC ? ".":"",
4718ee4a859c6da6539f6c6df225cb920dc6fc37facdsewardj                rA_addr, rS_addr, MaskBeg);
47192831b00c4950d6c2b061def05fd67528fe132ececerion            assign( rA, binop(Iop_Shr32, mkexpr(rS), mkU8(MaskBeg)) );
47202831b00c4950d6c2b061def05fd67528fe132ececerion         }
47212831b00c4950d6c2b061def05fd67528fe132ececerion         else {
47222831b00c4950d6c2b061def05fd67528fe132ececerion            /* General case. */
4723f0de28cf1a762b0d6f74c93d3532c89a230673bbcerion            mask32 = MASK32(31-MaskEnd, 31-MaskBeg);
47245b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion            DIP("rlwinm%s r%u,r%u,%d,%d,%d\n", flag_rC ? ".":"",
47252831b00c4950d6c2b061def05fd67528fe132ececerion                rA_addr, rS_addr, sh_imm, MaskBeg, MaskEnd);
47262831b00c4950d6c2b061def05fd67528fe132ececerion            // rA = ROTL(rS, Imm) & mask
47275b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion            assign( rA, binop(Iop_And32,
47285b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion                              ROTL(mkexpr(rS), mkU8(sh_imm)),
4729f0de28cf1a762b0d6f74c93d3532c89a230673bbcerion                              mkU32(mask32)) );
47302831b00c4950d6c2b061def05fd67528fe132ececerion         }
473126b3320973ccdd634fc5461d832e86b3b6aa878fsewardj      }
4732b85e8bba97fdae7d892f7bfd12e4601307e4721dcerion      break;
4733d953ebb9b04cbad6891676df597bf0c542b1ec89cerion   }
4734b85e8bba97fdae7d892f7bfd12e4601307e4721dcerion
4735d953ebb9b04cbad6891676df597bf0c542b1ec89cerion   case 0x17: {
4736c965953e12be58c7d01cd6d024d6f42326b2b797sewardj      // rlwnm (Rotate Left Word then AND with Mask, PPC32 p503
47375b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion      DIP("rlwnm%s r%u,r%u,r%u,%d,%d\n", flag_rC ? ".":"",
4738d953ebb9b04cbad6891676df597bf0c542b1ec89cerion          rA_addr, rS_addr, rB_addr, MaskBeg, MaskEnd);
4739d953ebb9b04cbad6891676df597bf0c542b1ec89cerion      if (mode64) {
4740f0de28cf1a762b0d6f74c93d3532c89a230673bbcerion         mask64 = MASK64(31-MaskEnd, 31-MaskBeg);
4741bb01b7cbfd84c27dd213f67a144ea5a99af36961cerion         /* weird insn alert!
4742bb01b7cbfd84c27dd213f67a144ea5a99af36961cerion            tmp32 = (ROTL(rS_Lo32, rB[0-4])
4743bb01b7cbfd84c27dd213f67a144ea5a99af36961cerion            rA = ((tmp32 || tmp32) & mask64)
4744bb01b7cbfd84c27dd213f67a144ea5a99af36961cerion         */
4745d953ebb9b04cbad6891676df597bf0c542b1ec89cerion         // note, ROTL does the masking, so we don't do it here
4746d953ebb9b04cbad6891676df597bf0c542b1ec89cerion         r = ROTL( unop(Iop_64to32, mkexpr(rS)),
4747bb01b7cbfd84c27dd213f67a144ea5a99af36961cerion                   unop(Iop_64to8, mkexpr(rB)) );
4748d953ebb9b04cbad6891676df597bf0c542b1ec89cerion         r = unop(Iop_32Uto64, r);
4749bb01b7cbfd84c27dd213f67a144ea5a99af36961cerion         assign(rot, binop(Iop_Or64, r, binop(Iop_Shl64, r, mkU8(32))));
4750bb01b7cbfd84c27dd213f67a144ea5a99af36961cerion         assign( rA, binop(Iop_And64, mkexpr(rot), mkU64(mask64)) );
4751d953ebb9b04cbad6891676df597bf0c542b1ec89cerion      } else {
4752f0de28cf1a762b0d6f74c93d3532c89a230673bbcerion         mask32 = MASK32(31-MaskEnd, 31-MaskBeg);
4753d953ebb9b04cbad6891676df597bf0c542b1ec89cerion         // rA = ROTL(rS, rB[0-4]) & mask
4754d953ebb9b04cbad6891676df597bf0c542b1ec89cerion         // note, ROTL does the masking, so we don't do it here
4755d953ebb9b04cbad6891676df597bf0c542b1ec89cerion         assign( rA, binop(Iop_And32,
47565b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion                           ROTL(mkexpr(rS),
47575b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion                                unop(Iop_32to8, mkexpr(rB))),
4758f0de28cf1a762b0d6f74c93d3532c89a230673bbcerion                           mkU32(mask32)) );
4759d953ebb9b04cbad6891676df597bf0c542b1ec89cerion      }
4760c965953e12be58c7d01cd6d024d6f42326b2b797sewardj      break;
4761d953ebb9b04cbad6891676df597bf0c542b1ec89cerion   }
4762645c930b1a61f4493ee2d472b34fbb439233a874cerion
4763f0de28cf1a762b0d6f74c93d3532c89a230673bbcerion   /* 64bit Integer Rotates */
4764f0de28cf1a762b0d6f74c93d3532c89a230673bbcerion   case 0x1E: {
4765f0de28cf1a762b0d6f74c93d3532c89a230673bbcerion      msk_imm = ((msk_imm & 1) << 5) | (msk_imm >> 1);
4766f0de28cf1a762b0d6f74c93d3532c89a230673bbcerion      sh_imm |= b1 << 5;
4767f0de28cf1a762b0d6f74c93d3532c89a230673bbcerion
4768f0de28cf1a762b0d6f74c93d3532c89a230673bbcerion      vassert( msk_imm < 64 );
4769f0de28cf1a762b0d6f74c93d3532c89a230673bbcerion      vassert( sh_imm < 64 );
4770f0de28cf1a762b0d6f74c93d3532c89a230673bbcerion
4771f0de28cf1a762b0d6f74c93d3532c89a230673bbcerion      switch (opc2) {
477207b07a966a2fdbcf621251a0c1a8ab84807fb120cerion      case 0x4: {
477307b07a966a2fdbcf621251a0c1a8ab84807fb120cerion         /* r = ROTL64( rS, rB_lo6) */
477407b07a966a2fdbcf621251a0c1a8ab84807fb120cerion         r = ROTL( mkexpr(rS), unop(Iop_64to8, mkexpr(rB)) );
477507b07a966a2fdbcf621251a0c1a8ab84807fb120cerion
47765b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion         if (b1 == 0) { // rldcl (Rotl DWord, Clear Left, PPC64 p555)
47775b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion            DIP("rldcl%s r%u,r%u,r%u,%u\n", flag_rC ? ".":"",
4778f0de28cf1a762b0d6f74c93d3532c89a230673bbcerion                rA_addr, rS_addr, rB_addr, msk_imm);
477907b07a966a2fdbcf621251a0c1a8ab84807fb120cerion            // note, ROTL does the masking, so we don't do it here
4780f0de28cf1a762b0d6f74c93d3532c89a230673bbcerion            mask64 = MASK64(0, 63-msk_imm);
4781f0de28cf1a762b0d6f74c93d3532c89a230673bbcerion            assign( rA, binop(Iop_And64, r, mkU64(mask64)) );
4782f0de28cf1a762b0d6f74c93d3532c89a230673bbcerion            break;
47835b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion         } else {       // rldcr (Rotl DWord, Clear Right, PPC64 p556)
47845b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion            DIP("rldcr%s r%u,r%u,r%u,%u\n", flag_rC ? ".":"",
4785f0de28cf1a762b0d6f74c93d3532c89a230673bbcerion                rA_addr, rS_addr, rB_addr, msk_imm);
4786f0de28cf1a762b0d6f74c93d3532c89a230673bbcerion            mask64 = MASK64(63-msk_imm, 63);
4787f0de28cf1a762b0d6f74c93d3532c89a230673bbcerion            assign( rA, binop(Iop_And64, r, mkU64(mask64)) );
4788f0de28cf1a762b0d6f74c93d3532c89a230673bbcerion            break;
4789f0de28cf1a762b0d6f74c93d3532c89a230673bbcerion         }
4790f0de28cf1a762b0d6f74c93d3532c89a230673bbcerion         break;
479107b07a966a2fdbcf621251a0c1a8ab84807fb120cerion      }
47925b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion      case 0x2: // rldic (Rotl DWord Imm, Clear, PPC64 p557)
47935b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion         DIP("rldic%s r%u,r%u,%u,%u\n", flag_rC ? ".":"",
4794f0de28cf1a762b0d6f74c93d3532c89a230673bbcerion             rA_addr, rS_addr, sh_imm, msk_imm);
4795f0de28cf1a762b0d6f74c93d3532c89a230673bbcerion         r = ROTL(mkexpr(rS), mkU8(sh_imm));
4796f0de28cf1a762b0d6f74c93d3532c89a230673bbcerion         mask64 = MASK64(sh_imm, 63-msk_imm);
4797f0de28cf1a762b0d6f74c93d3532c89a230673bbcerion         assign( rA, binop(Iop_And64, r, mkU64(mask64)) );
4798f0de28cf1a762b0d6f74c93d3532c89a230673bbcerion         break;
4799f0de28cf1a762b0d6f74c93d3532c89a230673bbcerion         // later: deal with special case: (msk_imm==0) => SHL(sh_imm)
4800f0de28cf1a762b0d6f74c93d3532c89a230673bbcerion         /*
4801f0de28cf1a762b0d6f74c93d3532c89a230673bbcerion           Hmm... looks like this'll do the job more simply:
4802f0de28cf1a762b0d6f74c93d3532c89a230673bbcerion           r = SHL(rS, sh_imm)
4803f0de28cf1a762b0d6f74c93d3532c89a230673bbcerion           m = ~(1 << (63-msk_imm))
4804f0de28cf1a762b0d6f74c93d3532c89a230673bbcerion           assign(rA, r & m);
4805f0de28cf1a762b0d6f74c93d3532c89a230673bbcerion         */
4806f0de28cf1a762b0d6f74c93d3532c89a230673bbcerion
48075b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion      case 0x0: // rldicl (Rotl DWord Imm, Clear Left, PPC64 p558)
4808ee4a859c6da6539f6c6df225cb920dc6fc37facdsewardj         if (mode64
4809ee4a859c6da6539f6c6df225cb920dc6fc37facdsewardj             && sh_imm + msk_imm == 64 && msk_imm >= 1 && msk_imm <= 63) {
4810ee4a859c6da6539f6c6df225cb920dc6fc37facdsewardj            /* special-case the ,64-n,n form as that is just
4811ee4a859c6da6539f6c6df225cb920dc6fc37facdsewardj               unsigned shift-right by n */
4812ee4a859c6da6539f6c6df225cb920dc6fc37facdsewardj            DIP("srdi%s r%u,r%u,%u\n",
4813ee4a859c6da6539f6c6df225cb920dc6fc37facdsewardj                flag_rC ? ".":"", rA_addr, rS_addr, msk_imm);
4814ee4a859c6da6539f6c6df225cb920dc6fc37facdsewardj            assign( rA, binop(Iop_Shr64, mkexpr(rS), mkU8(msk_imm)) );
4815ee4a859c6da6539f6c6df225cb920dc6fc37facdsewardj         } else {
4816ee4a859c6da6539f6c6df225cb920dc6fc37facdsewardj            DIP("rldicl%s r%u,r%u,%u,%u\n", flag_rC ? ".":"",
4817ee4a859c6da6539f6c6df225cb920dc6fc37facdsewardj                rA_addr, rS_addr, sh_imm, msk_imm);
4818ee4a859c6da6539f6c6df225cb920dc6fc37facdsewardj            r = ROTL(mkexpr(rS), mkU8(sh_imm));
4819ee4a859c6da6539f6c6df225cb920dc6fc37facdsewardj            mask64 = MASK64(0, 63-msk_imm);
4820ee4a859c6da6539f6c6df225cb920dc6fc37facdsewardj            assign( rA, binop(Iop_And64, r, mkU64(mask64)) );
4821ee4a859c6da6539f6c6df225cb920dc6fc37facdsewardj         }
4822f0de28cf1a762b0d6f74c93d3532c89a230673bbcerion         break;
4823f0de28cf1a762b0d6f74c93d3532c89a230673bbcerion
48245b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion      case 0x1: // rldicr (Rotl DWord Imm, Clear Right, PPC64 p559)
4825ee4a859c6da6539f6c6df225cb920dc6fc37facdsewardj         if (mode64
4826ee4a859c6da6539f6c6df225cb920dc6fc37facdsewardj             && sh_imm + msk_imm == 63 && sh_imm >= 1 && sh_imm <= 63) {
4827ee4a859c6da6539f6c6df225cb920dc6fc37facdsewardj            /* special-case the ,n,63-n form as that is just
4828ee4a859c6da6539f6c6df225cb920dc6fc37facdsewardj               shift-left by n */
4829ee4a859c6da6539f6c6df225cb920dc6fc37facdsewardj            DIP("sldi%s r%u,r%u,%u\n",
4830ee4a859c6da6539f6c6df225cb920dc6fc37facdsewardj                flag_rC ? ".":"", rA_addr, rS_addr, sh_imm);
4831ee4a859c6da6539f6c6df225cb920dc6fc37facdsewardj            assign( rA, binop(Iop_Shl64, mkexpr(rS), mkU8(sh_imm)) );
4832ee4a859c6da6539f6c6df225cb920dc6fc37facdsewardj         } else {
4833ee4a859c6da6539f6c6df225cb920dc6fc37facdsewardj            DIP("rldicr%s r%u,r%u,%u,%u\n", flag_rC ? ".":"",
4834ee4a859c6da6539f6c6df225cb920dc6fc37facdsewardj                rA_addr, rS_addr, sh_imm, msk_imm);
4835ee4a859c6da6539f6c6df225cb920dc6fc37facdsewardj            r = ROTL(mkexpr(rS), mkU8(sh_imm));
4836ee4a859c6da6539f6c6df225cb920dc6fc37facdsewardj            mask64 = MASK64(63-msk_imm, 63);
4837ee4a859c6da6539f6c6df225cb920dc6fc37facdsewardj            assign( rA, binop(Iop_And64, r, mkU64(mask64)) );
4838ee4a859c6da6539f6c6df225cb920dc6fc37facdsewardj         }
4839f0de28cf1a762b0d6f74c93d3532c89a230673bbcerion         break;
4840f0de28cf1a762b0d6f74c93d3532c89a230673bbcerion
48415b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion      case 0x3: { // rldimi (Rotl DWord Imm, Mask Insert, PPC64 p560)
484207b07a966a2fdbcf621251a0c1a8ab84807fb120cerion         IRTemp rA_orig = newTemp(ty);
48435b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion         DIP("rldimi%s r%u,r%u,%u,%u\n", flag_rC ? ".":"",
4844f0de28cf1a762b0d6f74c93d3532c89a230673bbcerion             rA_addr, rS_addr, sh_imm, msk_imm);
4845f0de28cf1a762b0d6f74c93d3532c89a230673bbcerion         r = ROTL(mkexpr(rS), mkU8(sh_imm));
4846f0de28cf1a762b0d6f74c93d3532c89a230673bbcerion         mask64 = MASK64(sh_imm, 63-msk_imm);
484707b07a966a2fdbcf621251a0c1a8ab84807fb120cerion         assign( rA_orig, getIReg(rA_addr) );
4848f0de28cf1a762b0d6f74c93d3532c89a230673bbcerion         assign( rA, binop(Iop_Or64,
4849f0de28cf1a762b0d6f74c93d3532c89a230673bbcerion                           binop(Iop_And64, mkU64(mask64),  r),
48505b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion                           binop(Iop_And64, mkU64(~mask64),
48515b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion                                            mkexpr(rA_orig))) );
4852f0de28cf1a762b0d6f74c93d3532c89a230673bbcerion         break;
485307b07a966a2fdbcf621251a0c1a8ab84807fb120cerion      }
4854f0de28cf1a762b0d6f74c93d3532c89a230673bbcerion      default:
48555b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion         vex_printf("dis_int_rot(ppc)(opc2)\n");
4856f0de28cf1a762b0d6f74c93d3532c89a230673bbcerion         return False;
4857f0de28cf1a762b0d6f74c93d3532c89a230673bbcerion      }
4858f0de28cf1a762b0d6f74c93d3532c89a230673bbcerion      break;
4859f0de28cf1a762b0d6f74c93d3532c89a230673bbcerion   }
4860f0de28cf1a762b0d6f74c93d3532c89a230673bbcerion
4861b85e8bba97fdae7d892f7bfd12e4601307e4721dcerion   default:
48625b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion      vex_printf("dis_int_rot(ppc)(opc1)\n");
4863b85e8bba97fdae7d892f7bfd12e4601307e4721dcerion      return False;
4864b85e8bba97fdae7d892f7bfd12e4601307e4721dcerion   }
4865b85e8bba97fdae7d892f7bfd12e4601307e4721dcerion
486676de5cf615380b23b4b5bcced6541233cd4a93a0cerion   putIReg( rA_addr, mkexpr(rA) );
486776de5cf615380b23b4b5bcced6541233cd4a93a0cerion
486876de5cf615380b23b4b5bcced6541233cd4a93a0cerion   if (flag_rC) {
486976de5cf615380b23b4b5bcced6541233cd4a93a0cerion      set_CR0( mkexpr(rA) );
4870b85e8bba97fdae7d892f7bfd12e4601307e4721dcerion   }
4871b85e8bba97fdae7d892f7bfd12e4601307e4721dcerion   return True;
4872645c930b1a61f4493ee2d472b34fbb439233a874cerion}
4873645c930b1a61f4493ee2d472b34fbb439233a874cerion
4874645c930b1a61f4493ee2d472b34fbb439233a874cerion
48753d870a39e4d145e2f3d9f9a0eeed3475ec934ac1cerion/*
48763d870a39e4d145e2f3d9f9a0eeed3475ec934ac1cerion  Integer Load Instructions
48773d870a39e4d145e2f3d9f9a0eeed3475ec934ac1cerion*/
4878645c930b1a61f4493ee2d472b34fbb439233a874cerionstatic Bool dis_int_load ( UInt theInstr )
4879645c930b1a61f4493ee2d472b34fbb439233a874cerion{
4880f0de28cf1a762b0d6f74c93d3532c89a230673bbcerion   /* D-Form, X-Form, DS-Form */
488176de5cf615380b23b4b5bcced6541233cd4a93a0cerion   UChar opc1     = ifieldOPC(theInstr);
488276de5cf615380b23b4b5bcced6541233cd4a93a0cerion   UChar rD_addr  = ifieldRegDS(theInstr);
488376de5cf615380b23b4b5bcced6541233cd4a93a0cerion   UChar rA_addr  = ifieldRegA(theInstr);
4884d953ebb9b04cbad6891676df597bf0c542b1ec89cerion   UInt  uimm16   = ifieldUIMM16(theInstr);
488576de5cf615380b23b4b5bcced6541233cd4a93a0cerion   UChar rB_addr  = ifieldRegB(theInstr);
488676de5cf615380b23b4b5bcced6541233cd4a93a0cerion   UInt  opc2     = ifieldOPClo10(theInstr);
4887f0de28cf1a762b0d6f74c93d3532c89a230673bbcerion   UChar b1       = ifieldBIT1(theInstr);
488876de5cf615380b23b4b5bcced6541233cd4a93a0cerion   UChar b0       = ifieldBIT0(theInstr);
488976de5cf615380b23b4b5bcced6541233cd4a93a0cerion
4890d953ebb9b04cbad6891676df597bf0c542b1ec89cerion   Int     simm16 = extend_s_16to32(uimm16);
4891d953ebb9b04cbad6891676df597bf0c542b1ec89cerion   IRType  ty     = mode64 ? Ity_I64 : Ity_I32;
4892d953ebb9b04cbad6891676df597bf0c542b1ec89cerion   IRTemp  EA     = newTemp(ty);
4893d953ebb9b04cbad6891676df597bf0c542b1ec89cerion   IRExpr* val;
4894edf7fc572e2decb93e9143961e8739c8fe18899dcerion
4895f0de28cf1a762b0d6f74c93d3532c89a230673bbcerion   switch (opc1) {
4896f0de28cf1a762b0d6f74c93d3532c89a230673bbcerion   case 0x1F: // register offset
4897d953ebb9b04cbad6891676df597bf0c542b1ec89cerion      assign( EA, ea_rAor0_idxd( rA_addr, rB_addr ) );
4898f0de28cf1a762b0d6f74c93d3532c89a230673bbcerion      break;
489978850ae9874a90ea625fcee1fd4c359375b7b538carll   case 0x38: // immediate offset: 64bit: lq: maskoff
490078850ae9874a90ea625fcee1fd4c359375b7b538carll              // lowest 4 bits of immediate before forming EA
490178850ae9874a90ea625fcee1fd4c359375b7b538carll      simm16 = simm16 & 0xFFFFFFF0;
490278850ae9874a90ea625fcee1fd4c359375b7b538carll      assign( EA, ea_rAor0_simm( rA_addr, simm16  ) );
490378850ae9874a90ea625fcee1fd4c359375b7b538carll      break;
49046d83422ba5b685adc40fdc97651bcca4ecd47d1dsewardj   case 0x3A: // immediate offset: 64bit: ld/ldu/lwa: mask off
49056d83422ba5b685adc40fdc97651bcca4ecd47d1dsewardj              // lowest 2 bits of immediate before forming EA
4906f0de28cf1a762b0d6f74c93d3532c89a230673bbcerion      simm16 = simm16 & 0xFFFFFFFC;
490778850ae9874a90ea625fcee1fd4c359375b7b538carll      assign( EA, ea_rAor0_simm( rA_addr, simm16  ) );
490878850ae9874a90ea625fcee1fd4c359375b7b538carll      break;
4909f0de28cf1a762b0d6f74c93d3532c89a230673bbcerion   default:   // immediate offset
4910f0de28cf1a762b0d6f74c93d3532c89a230673bbcerion      assign( EA, ea_rAor0_simm( rA_addr, simm16  ) );
4911f0de28cf1a762b0d6f74c93d3532c89a230673bbcerion      break;
4912d953ebb9b04cbad6891676df597bf0c542b1ec89cerion   }
4913e9d361ab43518b6dfbd3d846f48859534659dee0cerion
4914b85e8bba97fdae7d892f7bfd12e4601307e4721dcerion   switch (opc1) {
4915e9d361ab43518b6dfbd3d846f48859534659dee0cerion   case 0x22: // lbz (Load B & Zero, PPC32 p433)
4916d953ebb9b04cbad6891676df597bf0c542b1ec89cerion      DIP("lbz r%u,%d(r%u)\n", rD_addr, (Int)simm16, rA_addr);
49171f5fe1fc3a37ca729925e8eec25aa1025b4a6cdbcarll      val = load(Ity_I8, mkexpr(EA));
4918e9d8a26b690c2561ac54ab0cd6ad83ecbadcbe76sewardj      putIReg( rD_addr, mkWidenFrom8(ty, val, False) );
4919b85e8bba97fdae7d892f7bfd12e4601307e4721dcerion      break;
4920b85e8bba97fdae7d892f7bfd12e4601307e4721dcerion
49215b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion   case 0x23: // lbzu (Load B & Zero, Update, PPC32 p434)
492276de5cf615380b23b4b5bcced6541233cd4a93a0cerion      if (rA_addr == 0 || rA_addr == rD_addr) {
49235b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion         vex_printf("dis_int_load(ppc)(lbzu,rA_addr|rD_addr)\n");
4924b85e8bba97fdae7d892f7bfd12e4601307e4721dcerion         return False;
4925b85e8bba97fdae7d892f7bfd12e4601307e4721dcerion      }
4926d953ebb9b04cbad6891676df597bf0c542b1ec89cerion      DIP("lbzu r%u,%d(r%u)\n", rD_addr, (Int)simm16, rA_addr);
49271f5fe1fc3a37ca729925e8eec25aa1025b4a6cdbcarll      val = load(Ity_I8, mkexpr(EA));
4928e9d8a26b690c2561ac54ab0cd6ad83ecbadcbe76sewardj      putIReg( rD_addr, mkWidenFrom8(ty, val, False) );
4929d953ebb9b04cbad6891676df597bf0c542b1ec89cerion      putIReg( rA_addr, mkexpr(EA) );
4930b85e8bba97fdae7d892f7bfd12e4601307e4721dcerion      break;
4931b85e8bba97fdae7d892f7bfd12e4601307e4721dcerion
49325b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion   case 0x2A: // lha (Load HW Alg, PPC32 p445)
4933d953ebb9b04cbad6891676df597bf0c542b1ec89cerion      DIP("lha r%u,%d(r%u)\n", rD_addr, (Int)simm16, rA_addr);
49341f5fe1fc3a37ca729925e8eec25aa1025b4a6cdbcarll      val = load(Ity_I16, mkexpr(EA));
4935e9d8a26b690c2561ac54ab0cd6ad83ecbadcbe76sewardj      putIReg( rD_addr, mkWidenFrom16(ty, val, True) );
4936b85e8bba97fdae7d892f7bfd12e4601307e4721dcerion      break;
4937b85e8bba97fdae7d892f7bfd12e4601307e4721dcerion
49385b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion   case 0x2B: // lhau (Load HW Alg, Update, PPC32 p446)
493976de5cf615380b23b4b5bcced6541233cd4a93a0cerion      if (rA_addr == 0 || rA_addr == rD_addr) {
49405b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion         vex_printf("dis_int_load(ppc)(lhau,rA_addr|rD_addr)\n");
4941cb14e73e1556145a29ae2c8f4f7ab73cf2963864cerion         return False;
4942cb14e73e1556145a29ae2c8f4f7ab73cf2963864cerion      }
4943d953ebb9b04cbad6891676df597bf0c542b1ec89cerion      DIP("lhau r%u,%d(r%u)\n", rD_addr, (Int)simm16, rA_addr);
49441f5fe1fc3a37ca729925e8eec25aa1025b4a6cdbcarll      val = load(Ity_I16, mkexpr(EA));
4945e9d8a26b690c2561ac54ab0cd6ad83ecbadcbe76sewardj      putIReg( rD_addr, mkWidenFrom16(ty, val, True) );
4946d953ebb9b04cbad6891676df597bf0c542b1ec89cerion      putIReg( rA_addr, mkexpr(EA) );
4947cb14e73e1556145a29ae2c8f4f7ab73cf2963864cerion      break;
4948b85e8bba97fdae7d892f7bfd12e4601307e4721dcerion
4949e9d361ab43518b6dfbd3d846f48859534659dee0cerion   case 0x28: // lhz (Load HW & Zero, PPC32 p450)
4950d953ebb9b04cbad6891676df597bf0c542b1ec89cerion      DIP("lhz r%u,%d(r%u)\n", rD_addr, (Int)simm16, rA_addr);
49511f5fe1fc3a37ca729925e8eec25aa1025b4a6cdbcarll      val = load(Ity_I16, mkexpr(EA));
4952e9d8a26b690c2561ac54ab0cd6ad83ecbadcbe76sewardj      putIReg( rD_addr, mkWidenFrom16(ty, val, False) );
4953b85e8bba97fdae7d892f7bfd12e4601307e4721dcerion      break;
4954b85e8bba97fdae7d892f7bfd12e4601307e4721dcerion
49555b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion   case 0x29: // lhzu (Load HW & and Zero, Update, PPC32 p451)
495676de5cf615380b23b4b5bcced6541233cd4a93a0cerion      if (rA_addr == 0 || rA_addr == rD_addr) {
49575b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion         vex_printf("dis_int_load(ppc)(lhzu,rA_addr|rD_addr)\n");
49580e2cc67b30d1bb4d0515a1e09d944143becb3881sewardj         return False;
49590e2cc67b30d1bb4d0515a1e09d944143becb3881sewardj      }
4960d953ebb9b04cbad6891676df597bf0c542b1ec89cerion      DIP("lhzu r%u,%d(r%u)\n", rD_addr, (Int)simm16, rA_addr);
49611f5fe1fc3a37ca729925e8eec25aa1025b4a6cdbcarll      val = load(Ity_I16, mkexpr(EA));
4962e9d8a26b690c2561ac54ab0cd6ad83ecbadcbe76sewardj      putIReg( rD_addr, mkWidenFrom16(ty, val, False) );
4963d953ebb9b04cbad6891676df597bf0c542b1ec89cerion      putIReg( rA_addr, mkexpr(EA) );
49640e2cc67b30d1bb4d0515a1e09d944143becb3881sewardj      break;
4965b85e8bba97fdae7d892f7bfd12e4601307e4721dcerion
4966e9d361ab43518b6dfbd3d846f48859534659dee0cerion   case 0x20: // lwz (Load W & Zero, PPC32 p460)
4967d953ebb9b04cbad6891676df597bf0c542b1ec89cerion      DIP("lwz r%u,%d(r%u)\n", rD_addr, (Int)simm16, rA_addr);
49681f5fe1fc3a37ca729925e8eec25aa1025b4a6cdbcarll      val = load(Ity_I32, mkexpr(EA));
4969e9d8a26b690c2561ac54ab0cd6ad83ecbadcbe76sewardj      putIReg( rD_addr, mkWidenFrom32(ty, val, False) );
4970b85e8bba97fdae7d892f7bfd12e4601307e4721dcerion      break;
4971b85e8bba97fdae7d892f7bfd12e4601307e4721dcerion
49725b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion   case 0x21: // lwzu (Load W & Zero, Update, PPC32 p461))
497376de5cf615380b23b4b5bcced6541233cd4a93a0cerion      if (rA_addr == 0 || rA_addr == rD_addr) {
49745b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion         vex_printf("dis_int_load(ppc)(lwzu,rA_addr|rD_addr)\n");
4975b85e8bba97fdae7d892f7bfd12e4601307e4721dcerion         return False;
4976b85e8bba97fdae7d892f7bfd12e4601307e4721dcerion      }
4977d953ebb9b04cbad6891676df597bf0c542b1ec89cerion      DIP("lwzu r%u,%d(r%u)\n", rD_addr, (Int)simm16, rA_addr);
49781f5fe1fc3a37ca729925e8eec25aa1025b4a6cdbcarll      val = load(Ity_I32, mkexpr(EA));
4979e9d8a26b690c2561ac54ab0cd6ad83ecbadcbe76sewardj      putIReg( rD_addr, mkWidenFrom32(ty, val, False) );
4980d953ebb9b04cbad6891676df597bf0c542b1ec89cerion      putIReg( rA_addr, mkexpr(EA) );
4981b85e8bba97fdae7d892f7bfd12e4601307e4721dcerion      break;
4982b85e8bba97fdae7d892f7bfd12e4601307e4721dcerion
4983b85e8bba97fdae7d892f7bfd12e4601307e4721dcerion   /* X Form */
4984b85e8bba97fdae7d892f7bfd12e4601307e4721dcerion   case 0x1F:
4985b85e8bba97fdae7d892f7bfd12e4601307e4721dcerion      if (b0 != 0) {
49865b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion         vex_printf("dis_int_load(ppc)(Ox1F,b0)\n");
4987b85e8bba97fdae7d892f7bfd12e4601307e4721dcerion         return False;
4988b85e8bba97fdae7d892f7bfd12e4601307e4721dcerion      }
4989b85e8bba97fdae7d892f7bfd12e4601307e4721dcerion
4990b85e8bba97fdae7d892f7bfd12e4601307e4721dcerion      switch (opc2) {
49915b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion      case 0x077: // lbzux (Load B & Zero, Update Indexed, PPC32 p435)
4992d953ebb9b04cbad6891676df597bf0c542b1ec89cerion         DIP("lbzux r%u,r%u,r%u\n", rD_addr, rA_addr, rB_addr);
499376de5cf615380b23b4b5bcced6541233cd4a93a0cerion         if (rA_addr == 0 || rA_addr == rD_addr) {
49945b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion            vex_printf("dis_int_load(ppc)(lwzux,rA_addr|rD_addr)\n");
4995b85e8bba97fdae7d892f7bfd12e4601307e4721dcerion            return False;
4996b85e8bba97fdae7d892f7bfd12e4601307e4721dcerion         }
49971f5fe1fc3a37ca729925e8eec25aa1025b4a6cdbcarll         val = load(Ity_I8, mkexpr(EA));
4998e9d8a26b690c2561ac54ab0cd6ad83ecbadcbe76sewardj         putIReg( rD_addr, mkWidenFrom8(ty, val, False) );
4999d953ebb9b04cbad6891676df597bf0c542b1ec89cerion         putIReg( rA_addr, mkexpr(EA) );
5000b85e8bba97fdae7d892f7bfd12e4601307e4721dcerion         break;
5001b85e8bba97fdae7d892f7bfd12e4601307e4721dcerion
50025b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion      case 0x057: // lbzx (Load B & Zero, Indexed, PPC32 p436)
5003d953ebb9b04cbad6891676df597bf0c542b1ec89cerion         DIP("lbzx r%u,r%u,r%u\n", rD_addr, rA_addr, rB_addr);
50041f5fe1fc3a37ca729925e8eec25aa1025b4a6cdbcarll         val = load(Ity_I8, mkexpr(EA));
5005e9d8a26b690c2561ac54ab0cd6ad83ecbadcbe76sewardj         putIReg( rD_addr, mkWidenFrom8(ty, val, False) );
5006b85e8bba97fdae7d892f7bfd12e4601307e4721dcerion         break;
5007b85e8bba97fdae7d892f7bfd12e4601307e4721dcerion
50085b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion      case 0x177: // lhaux (Load HW Alg, Update Indexed, PPC32 p447)
500976de5cf615380b23b4b5bcced6541233cd4a93a0cerion         if (rA_addr == 0 || rA_addr == rD_addr) {
50105b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion            vex_printf("dis_int_load(ppc)(lhaux,rA_addr|rD_addr)\n");
5011cb14e73e1556145a29ae2c8f4f7ab73cf2963864cerion            return False;
5012cb14e73e1556145a29ae2c8f4f7ab73cf2963864cerion         }
5013d953ebb9b04cbad6891676df597bf0c542b1ec89cerion         DIP("lhaux r%u,r%u,r%u\n", rD_addr, rA_addr, rB_addr);
50141f5fe1fc3a37ca729925e8eec25aa1025b4a6cdbcarll         val = load(Ity_I16, mkexpr(EA));
5015e9d8a26b690c2561ac54ab0cd6ad83ecbadcbe76sewardj         putIReg( rD_addr, mkWidenFrom16(ty, val, True) );
5016d953ebb9b04cbad6891676df597bf0c542b1ec89cerion         putIReg( rA_addr, mkexpr(EA) );
5017cb14e73e1556145a29ae2c8f4f7ab73cf2963864cerion         break;
5018b85e8bba97fdae7d892f7bfd12e4601307e4721dcerion
50195b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion      case 0x157: // lhax (Load HW Alg, Indexed, PPC32 p448)
5020d953ebb9b04cbad6891676df597bf0c542b1ec89cerion         DIP("lhax r%u,r%u,r%u\n", rD_addr, rA_addr, rB_addr);
50211f5fe1fc3a37ca729925e8eec25aa1025b4a6cdbcarll         val = load(Ity_I16, mkexpr(EA));
5022e9d8a26b690c2561ac54ab0cd6ad83ecbadcbe76sewardj         putIReg( rD_addr, mkWidenFrom16(ty, val, True) );
5023b85e8bba97fdae7d892f7bfd12e4601307e4721dcerion         break;
5024b85e8bba97fdae7d892f7bfd12e4601307e4721dcerion
50255b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion      case 0x137: // lhzux (Load HW & Zero, Update Indexed, PPC32 p452)
502676de5cf615380b23b4b5bcced6541233cd4a93a0cerion         if (rA_addr == 0 || rA_addr == rD_addr) {
50275b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion            vex_printf("dis_int_load(ppc)(lhzux,rA_addr|rD_addr)\n");
5028b85e8bba97fdae7d892f7bfd12e4601307e4721dcerion            return False;
5029b85e8bba97fdae7d892f7bfd12e4601307e4721dcerion         }
5030d953ebb9b04cbad6891676df597bf0c542b1ec89cerion         DIP("lhzux r%u,r%u,r%u\n", rD_addr, rA_addr, rB_addr);
50311f5fe1fc3a37ca729925e8eec25aa1025b4a6cdbcarll         val = load(Ity_I16, mkexpr(EA));
5032e9d8a26b690c2561ac54ab0cd6ad83ecbadcbe76sewardj         putIReg( rD_addr, mkWidenFrom16(ty, val, False) );
5033d953ebb9b04cbad6891676df597bf0c542b1ec89cerion         putIReg( rA_addr, mkexpr(EA) );
5034b85e8bba97fdae7d892f7bfd12e4601307e4721dcerion         break;
5035b85e8bba97fdae7d892f7bfd12e4601307e4721dcerion
50365b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion      case 0x117: // lhzx (Load HW & Zero, Indexed, PPC32 p453)
5037d953ebb9b04cbad6891676df597bf0c542b1ec89cerion         DIP("lhzx r%u,r%u,r%u\n", rD_addr, rA_addr, rB_addr);
50381f5fe1fc3a37ca729925e8eec25aa1025b4a6cdbcarll         val = load(Ity_I16, mkexpr(EA));
5039e9d8a26b690c2561ac54ab0cd6ad83ecbadcbe76sewardj         putIReg( rD_addr, mkWidenFrom16(ty, val, False) );
5040b85e8bba97fdae7d892f7bfd12e4601307e4721dcerion         break;
5041b85e8bba97fdae7d892f7bfd12e4601307e4721dcerion
50425b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion      case 0x037: // lwzux (Load W & Zero, Update Indexed, PPC32 p462)
504376de5cf615380b23b4b5bcced6541233cd4a93a0cerion         if (rA_addr == 0 || rA_addr == rD_addr) {
50445b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion            vex_printf("dis_int_load(ppc)(lwzux,rA_addr|rD_addr)\n");
50457787af415a9104b601c2f0ce5b56749e4fd86691sewardj            return False;
50467787af415a9104b601c2f0ce5b56749e4fd86691sewardj         }
5047d953ebb9b04cbad6891676df597bf0c542b1ec89cerion         DIP("lwzux r%u,r%u,r%u\n", rD_addr, rA_addr, rB_addr);
50481f5fe1fc3a37ca729925e8eec25aa1025b4a6cdbcarll         val = load(Ity_I32, mkexpr(EA));
5049e9d8a26b690c2561ac54ab0cd6ad83ecbadcbe76sewardj         putIReg( rD_addr, mkWidenFrom32(ty, val, False) );
5050d953ebb9b04cbad6891676df597bf0c542b1ec89cerion         putIReg( rA_addr, mkexpr(EA) );
50517787af415a9104b601c2f0ce5b56749e4fd86691sewardj         break;
5052b85e8bba97fdae7d892f7bfd12e4601307e4721dcerion
50535b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion      case 0x017: // lwzx (Load W & Zero, Indexed, PPC32 p463)
5054d953ebb9b04cbad6891676df597bf0c542b1ec89cerion         DIP("lwzx r%u,r%u,r%u\n", rD_addr, rA_addr, rB_addr);
50551f5fe1fc3a37ca729925e8eec25aa1025b4a6cdbcarll         val = load(Ity_I32, mkexpr(EA));
5056e9d8a26b690c2561ac54ab0cd6ad83ecbadcbe76sewardj         putIReg( rD_addr, mkWidenFrom32(ty, val, False) );
5057b85e8bba97fdae7d892f7bfd12e4601307e4721dcerion         break;
5058b85e8bba97fdae7d892f7bfd12e4601307e4721dcerion
5059f0de28cf1a762b0d6f74c93d3532c89a230673bbcerion
5060f0de28cf1a762b0d6f74c93d3532c89a230673bbcerion      /* 64bit Loads */
50615b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion      case 0x035: // ldux (Load DWord, Update Indexed, PPC64 p475)
5062f0de28cf1a762b0d6f74c93d3532c89a230673bbcerion         if (rA_addr == 0 || rA_addr == rD_addr) {
50635b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion            vex_printf("dis_int_load(ppc)(ldux,rA_addr|rD_addr)\n");
5064f0de28cf1a762b0d6f74c93d3532c89a230673bbcerion            return False;
5065f0de28cf1a762b0d6f74c93d3532c89a230673bbcerion         }
5066f0de28cf1a762b0d6f74c93d3532c89a230673bbcerion         DIP("ldux r%u,r%u,r%u\n", rD_addr, rA_addr, rB_addr);
50671f5fe1fc3a37ca729925e8eec25aa1025b4a6cdbcarll         putIReg( rD_addr, load(Ity_I64, mkexpr(EA)) );
5068f0de28cf1a762b0d6f74c93d3532c89a230673bbcerion         putIReg( rA_addr, mkexpr(EA) );
5069f0de28cf1a762b0d6f74c93d3532c89a230673bbcerion         break;
5070f0de28cf1a762b0d6f74c93d3532c89a230673bbcerion
50715b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion      case 0x015: // ldx (Load DWord, Indexed, PPC64 p476)
5072f0de28cf1a762b0d6f74c93d3532c89a230673bbcerion         DIP("ldx r%u,r%u,r%u\n", rD_addr, rA_addr, rB_addr);
50731f5fe1fc3a37ca729925e8eec25aa1025b4a6cdbcarll         putIReg( rD_addr, load(Ity_I64, mkexpr(EA)) );
5074f0de28cf1a762b0d6f74c93d3532c89a230673bbcerion         break;
5075f0de28cf1a762b0d6f74c93d3532c89a230673bbcerion
50765b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion      case 0x175: // lwaux (Load W Alg, Update Indexed, PPC64 p501)
5077f0de28cf1a762b0d6f74c93d3532c89a230673bbcerion         if (rA_addr == 0 || rA_addr == rD_addr) {
50785b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion            vex_printf("dis_int_load(ppc)(lwaux,rA_addr|rD_addr)\n");
5079f0de28cf1a762b0d6f74c93d3532c89a230673bbcerion            return False;
5080f0de28cf1a762b0d6f74c93d3532c89a230673bbcerion         }
5081f0de28cf1a762b0d6f74c93d3532c89a230673bbcerion         DIP("lwaux r%u,r%u,r%u\n", rD_addr, rA_addr, rB_addr);
50825b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion         putIReg( rD_addr,
50831f5fe1fc3a37ca729925e8eec25aa1025b4a6cdbcarll                  unop(Iop_32Sto64, load(Ity_I32, mkexpr(EA))) );
5084f0de28cf1a762b0d6f74c93d3532c89a230673bbcerion         putIReg( rA_addr, mkexpr(EA) );
5085f0de28cf1a762b0d6f74c93d3532c89a230673bbcerion         break;
5086f0de28cf1a762b0d6f74c93d3532c89a230673bbcerion
50875b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion      case 0x155: // lwax (Load W Alg, Indexed, PPC64 p502)
5088f0de28cf1a762b0d6f74c93d3532c89a230673bbcerion         DIP("lwax r%u,r%u,r%u\n", rD_addr, rA_addr, rB_addr);
50895b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion         putIReg( rD_addr,
50901f5fe1fc3a37ca729925e8eec25aa1025b4a6cdbcarll                  unop(Iop_32Sto64, load(Ity_I32, mkexpr(EA))) );
5091f0de28cf1a762b0d6f74c93d3532c89a230673bbcerion         break;
5092f0de28cf1a762b0d6f74c93d3532c89a230673bbcerion
5093b85e8bba97fdae7d892f7bfd12e4601307e4721dcerion      default:
50945b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion         vex_printf("dis_int_load(ppc)(opc2)\n");
5095b85e8bba97fdae7d892f7bfd12e4601307e4721dcerion         return False;
5096b85e8bba97fdae7d892f7bfd12e4601307e4721dcerion      }
5097b85e8bba97fdae7d892f7bfd12e4601307e4721dcerion      break;
5098f0de28cf1a762b0d6f74c93d3532c89a230673bbcerion
50996d83422ba5b685adc40fdc97651bcca4ecd47d1dsewardj   /* DS Form - 64bit Loads.  In each case EA will have been formed
51006d83422ba5b685adc40fdc97651bcca4ecd47d1dsewardj      with the lowest 2 bits masked off the immediate offset. */
5101f0de28cf1a762b0d6f74c93d3532c89a230673bbcerion   case 0x3A:
51026d83422ba5b685adc40fdc97651bcca4ecd47d1dsewardj      switch ((b1<<1) | b0) {
51035b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion      case 0x0: // ld (Load DWord, PPC64 p472)
5104f0de28cf1a762b0d6f74c93d3532c89a230673bbcerion         DIP("ld r%u,%d(r%u)\n", rD_addr, simm16, rA_addr);
51051f5fe1fc3a37ca729925e8eec25aa1025b4a6cdbcarll         putIReg( rD_addr, load(Ity_I64, mkexpr(EA)) );
5106f0de28cf1a762b0d6f74c93d3532c89a230673bbcerion         break;
5107f0de28cf1a762b0d6f74c93d3532c89a230673bbcerion
51085b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion      case 0x1: // ldu (Load DWord, Update, PPC64 p474)
5109f0de28cf1a762b0d6f74c93d3532c89a230673bbcerion         if (rA_addr == 0 || rA_addr == rD_addr) {
51105b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion            vex_printf("dis_int_load(ppc)(ldu,rA_addr|rD_addr)\n");
5111f0de28cf1a762b0d6f74c93d3532c89a230673bbcerion            return False;
5112f0de28cf1a762b0d6f74c93d3532c89a230673bbcerion         }
5113f0de28cf1a762b0d6f74c93d3532c89a230673bbcerion         DIP("ldu r%u,%d(r%u)\n", rD_addr, simm16, rA_addr);
51141f5fe1fc3a37ca729925e8eec25aa1025b4a6cdbcarll         putIReg( rD_addr, load(Ity_I64, mkexpr(EA)) );
5115f0de28cf1a762b0d6f74c93d3532c89a230673bbcerion         putIReg( rA_addr, mkexpr(EA) );
5116f0de28cf1a762b0d6f74c93d3532c89a230673bbcerion         break;
5117f0de28cf1a762b0d6f74c93d3532c89a230673bbcerion
51185b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion      case 0x2: // lwa (Load Word Alg, PPC64 p499)
5119f0de28cf1a762b0d6f74c93d3532c89a230673bbcerion         DIP("lwa r%u,%d(r%u)\n", rD_addr, simm16, rA_addr);
51205b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion         putIReg( rD_addr,
51211f5fe1fc3a37ca729925e8eec25aa1025b4a6cdbcarll                  unop(Iop_32Sto64, load(Ity_I32, mkexpr(EA))) );
5122f0de28cf1a762b0d6f74c93d3532c89a230673bbcerion         break;
5123f0de28cf1a762b0d6f74c93d3532c89a230673bbcerion
5124f0de28cf1a762b0d6f74c93d3532c89a230673bbcerion      default:
51255b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion         vex_printf("dis_int_load(ppc)(0x3A, opc2)\n");
5126f0de28cf1a762b0d6f74c93d3532c89a230673bbcerion         return False;
5127f0de28cf1a762b0d6f74c93d3532c89a230673bbcerion      }
5128f0de28cf1a762b0d6f74c93d3532c89a230673bbcerion      break;
5129f0de28cf1a762b0d6f74c93d3532c89a230673bbcerion
513078850ae9874a90ea625fcee1fd4c359375b7b538carll   case 0x38: {
513178850ae9874a90ea625fcee1fd4c359375b7b538carll      IRTemp  high = newTemp(ty);
513278850ae9874a90ea625fcee1fd4c359375b7b538carll      IRTemp  low  = newTemp(ty);
513378850ae9874a90ea625fcee1fd4c359375b7b538carll      /* DQ Form - 128bit Loads. Lowest bits [1:0] are the PT field. */
513478850ae9874a90ea625fcee1fd4c359375b7b538carll      DIP("lq r%u,%d(r%u)\n", rD_addr, simm16, rA_addr);
513578850ae9874a90ea625fcee1fd4c359375b7b538carll      /* NOTE: there are some changes to XER[41:42] that have not been
513678850ae9874a90ea625fcee1fd4c359375b7b538carll       * implemented.
513778850ae9874a90ea625fcee1fd4c359375b7b538carll       */
513878850ae9874a90ea625fcee1fd4c359375b7b538carll      // trap if EA misaligned on 16 byte address
513978850ae9874a90ea625fcee1fd4c359375b7b538carll      if (mode64) {
5140999ef56da3e4426c5f6bf74de40d23ff02dafb34carll         if (host_endness == VexEndnessBE) {
5141999ef56da3e4426c5f6bf74de40d23ff02dafb34carll            assign(high, load(ty, mkexpr( EA ) ) );
5142999ef56da3e4426c5f6bf74de40d23ff02dafb34carll            assign(low, load(ty, binop( Iop_Add64,
5143999ef56da3e4426c5f6bf74de40d23ff02dafb34carll                                        mkexpr( EA ),
5144999ef56da3e4426c5f6bf74de40d23ff02dafb34carll                                        mkU64( 8 ) ) ) );
5145999ef56da3e4426c5f6bf74de40d23ff02dafb34carll	 } else {
5146999ef56da3e4426c5f6bf74de40d23ff02dafb34carll            assign(low, load(ty, mkexpr( EA ) ) );
5147999ef56da3e4426c5f6bf74de40d23ff02dafb34carll            assign(high, load(ty, binop( Iop_Add64,
5148999ef56da3e4426c5f6bf74de40d23ff02dafb34carll                                         mkexpr( EA ),
5149999ef56da3e4426c5f6bf74de40d23ff02dafb34carll                                         mkU64( 8 ) ) ) );
5150999ef56da3e4426c5f6bf74de40d23ff02dafb34carll	 }
515178850ae9874a90ea625fcee1fd4c359375b7b538carll      } else {
51521f5fe1fc3a37ca729925e8eec25aa1025b4a6cdbcarll         assign(high, load(ty, binop( Iop_Add32,
51531f5fe1fc3a37ca729925e8eec25aa1025b4a6cdbcarll                                      mkexpr( EA ),
51541f5fe1fc3a37ca729925e8eec25aa1025b4a6cdbcarll                                      mkU32( 4 ) ) ) );
51551f5fe1fc3a37ca729925e8eec25aa1025b4a6cdbcarll         assign(low, load(ty, binop( Iop_Add32,
51561f5fe1fc3a37ca729925e8eec25aa1025b4a6cdbcarll                                      mkexpr( EA ),
51571f5fe1fc3a37ca729925e8eec25aa1025b4a6cdbcarll                                      mkU32( 12 ) ) ) );
515878850ae9874a90ea625fcee1fd4c359375b7b538carll      }
515978850ae9874a90ea625fcee1fd4c359375b7b538carll      gen_SIGBUS_if_misaligned( EA, 16 );
516078850ae9874a90ea625fcee1fd4c359375b7b538carll      putIReg( rD_addr,  mkexpr( high) );
516178850ae9874a90ea625fcee1fd4c359375b7b538carll      putIReg( rD_addr+1,  mkexpr( low) );
516278850ae9874a90ea625fcee1fd4c359375b7b538carll      break;
516378850ae9874a90ea625fcee1fd4c359375b7b538carll   }
5164b85e8bba97fdae7d892f7bfd12e4601307e4721dcerion   default:
51655b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion      vex_printf("dis_int_load(ppc)(opc1)\n");
5166b85e8bba97fdae7d892f7bfd12e4601307e4721dcerion      return False;
5167b85e8bba97fdae7d892f7bfd12e4601307e4721dcerion   }
5168b85e8bba97fdae7d892f7bfd12e4601307e4721dcerion   return True;
51697aa4bbc850d2978cccd8e12cd7c4cfeaa5ab3e4dcerion}
51707aa4bbc850d2978cccd8e12cd7c4cfeaa5ab3e4dcerion
51717aa4bbc850d2978cccd8e12cd7c4cfeaa5ab3e4dcerion
51727aa4bbc850d2978cccd8e12cd7c4cfeaa5ab3e4dcerion
51733d870a39e4d145e2f3d9f9a0eeed3475ec934ac1cerion/*
51743d870a39e4d145e2f3d9f9a0eeed3475ec934ac1cerion  Integer Store Instructions
51753d870a39e4d145e2f3d9f9a0eeed3475ec934ac1cerion*/
5176cacba8e675988fbf21b08feea1f317a9c896c053florianstatic Bool dis_int_store ( UInt theInstr, const VexAbiInfo* vbi )
5177d23be4e26c2d35c60cdf2fce0dfe0e9b1fa6d008cerion{
5178f0de28cf1a762b0d6f74c93d3532c89a230673bbcerion   /* D-Form, X-Form, DS-Form */
5179edf7fc572e2decb93e9143961e8739c8fe18899dcerion   UChar opc1    = ifieldOPC(theInstr);
518076de5cf615380b23b4b5bcced6541233cd4a93a0cerion   UInt  rS_addr = ifieldRegDS(theInstr);
518176de5cf615380b23b4b5bcced6541233cd4a93a0cerion   UInt  rA_addr = ifieldRegA(theInstr);
5182d953ebb9b04cbad6891676df597bf0c542b1ec89cerion   UInt  uimm16  = ifieldUIMM16(theInstr);
518376de5cf615380b23b4b5bcced6541233cd4a93a0cerion   UInt  rB_addr = ifieldRegB(theInstr);
518476de5cf615380b23b4b5bcced6541233cd4a93a0cerion   UInt  opc2    = ifieldOPClo10(theInstr);
5185f0de28cf1a762b0d6f74c93d3532c89a230673bbcerion   UChar b1      = ifieldBIT1(theInstr);
518676de5cf615380b23b4b5bcced6541233cd4a93a0cerion   UChar b0      = ifieldBIT0(theInstr);
518776de5cf615380b23b4b5bcced6541233cd4a93a0cerion
5188d953ebb9b04cbad6891676df597bf0c542b1ec89cerion   Int    simm16 = extend_s_16to32(uimm16);
5189d953ebb9b04cbad6891676df597bf0c542b1ec89cerion   IRType ty     = mode64 ? Ity_I64 : Ity_I32;
5190d953ebb9b04cbad6891676df597bf0c542b1ec89cerion   IRTemp rS     = newTemp(ty);
5191d953ebb9b04cbad6891676df597bf0c542b1ec89cerion   IRTemp rB     = newTemp(ty);
5192d953ebb9b04cbad6891676df597bf0c542b1ec89cerion   IRTemp EA     = newTemp(ty);
5193b85e8bba97fdae7d892f7bfd12e4601307e4721dcerion
519476de5cf615380b23b4b5bcced6541233cd4a93a0cerion   assign( rB, getIReg(rB_addr) );
519576de5cf615380b23b4b5bcced6541233cd4a93a0cerion   assign( rS, getIReg(rS_addr) );
5196b85e8bba97fdae7d892f7bfd12e4601307e4721dcerion
5197f0de28cf1a762b0d6f74c93d3532c89a230673bbcerion   switch (opc1) {
5198f0de28cf1a762b0d6f74c93d3532c89a230673bbcerion   case 0x1F: // register offset
5199d953ebb9b04cbad6891676df597bf0c542b1ec89cerion      assign( EA, ea_rAor0_idxd( rA_addr, rB_addr ) );
5200f0de28cf1a762b0d6f74c93d3532c89a230673bbcerion      break;
520178850ae9874a90ea625fcee1fd4c359375b7b538carll   case 0x3E: // immediate offset: 64bit: std/stdu/stq: mask off
52026d83422ba5b685adc40fdc97651bcca4ecd47d1dsewardj              // lowest 2 bits of immediate before forming EA
5203f0de28cf1a762b0d6f74c93d3532c89a230673bbcerion      simm16 = simm16 & 0xFFFFFFFC;
5204f0de28cf1a762b0d6f74c93d3532c89a230673bbcerion   default:   // immediate offset
5205f0de28cf1a762b0d6f74c93d3532c89a230673bbcerion      assign( EA, ea_rAor0_simm( rA_addr, simm16  ) );
5206f0de28cf1a762b0d6f74c93d3532c89a230673bbcerion      break;
5207d953ebb9b04cbad6891676df597bf0c542b1ec89cerion   }
5208d953ebb9b04cbad6891676df597bf0c542b1ec89cerion
5209b85e8bba97fdae7d892f7bfd12e4601307e4721dcerion   switch (opc1) {
5210afe85831d73e546e483dfc51964409b7ecd7c5fesewardj   case 0x26: // stb (Store B, PPC32 p509)
521176de5cf615380b23b4b5bcced6541233cd4a93a0cerion      DIP("stb r%u,%d(r%u)\n", rS_addr, simm16, rA_addr);
52121f5fe1fc3a37ca729925e8eec25aa1025b4a6cdbcarll      store( mkexpr(EA), mkNarrowTo8(ty, mkexpr(rS)) );
5213afe85831d73e546e483dfc51964409b7ecd7c5fesewardj      break;
5214b51f0f4f33256638ed953156a2635aa739b232f1sewardj
52155b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion   case 0x27: // stbu (Store B, Update, PPC32 p510)
521676de5cf615380b23b4b5bcced6541233cd4a93a0cerion      if (rA_addr == 0 ) {
52175b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion         vex_printf("dis_int_store(ppc)(stbu,rA_addr)\n");
5218b85e8bba97fdae7d892f7bfd12e4601307e4721dcerion         return False;
5219b85e8bba97fdae7d892f7bfd12e4601307e4721dcerion      }
522076de5cf615380b23b4b5bcced6541233cd4a93a0cerion      DIP("stbu r%u,%d(r%u)\n", rS_addr, simm16, rA_addr);
5221d953ebb9b04cbad6891676df597bf0c542b1ec89cerion      putIReg( rA_addr, mkexpr(EA) );
52221f5fe1fc3a37ca729925e8eec25aa1025b4a6cdbcarll      store( mkexpr(EA), mkNarrowTo8(ty, mkexpr(rS)) );
5223b85e8bba97fdae7d892f7bfd12e4601307e4721dcerion      break;
5224b85e8bba97fdae7d892f7bfd12e4601307e4721dcerion
5225e9d361ab43518b6dfbd3d846f48859534659dee0cerion   case 0x2C: // sth (Store HW, PPC32 p522)
522676de5cf615380b23b4b5bcced6541233cd4a93a0cerion      DIP("sth r%u,%d(r%u)\n", rS_addr, simm16, rA_addr);
52271f5fe1fc3a37ca729925e8eec25aa1025b4a6cdbcarll      store( mkexpr(EA), mkNarrowTo16(ty, mkexpr(rS)) );
5228b85e8bba97fdae7d892f7bfd12e4601307e4721dcerion      break;
5229b85e8bba97fdae7d892f7bfd12e4601307e4721dcerion
52305b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion   case 0x2D: // sthu (Store HW, Update, PPC32 p524)
523176de5cf615380b23b4b5bcced6541233cd4a93a0cerion      if (rA_addr == 0) {
52325b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion         vex_printf("dis_int_store(ppc)(sthu,rA_addr)\n");
5233b85e8bba97fdae7d892f7bfd12e4601307e4721dcerion         return False;
5234b85e8bba97fdae7d892f7bfd12e4601307e4721dcerion      }
523576de5cf615380b23b4b5bcced6541233cd4a93a0cerion      DIP("sthu r%u,%d(r%u)\n", rS_addr, simm16, rA_addr);
5236d953ebb9b04cbad6891676df597bf0c542b1ec89cerion      putIReg( rA_addr, mkexpr(EA) );
52371f5fe1fc3a37ca729925e8eec25aa1025b4a6cdbcarll      store( mkexpr(EA), mkNarrowTo16(ty, mkexpr(rS)) );
5238b85e8bba97fdae7d892f7bfd12e4601307e4721dcerion      break;
5239b85e8bba97fdae7d892f7bfd12e4601307e4721dcerion
5240e9d361ab43518b6dfbd3d846f48859534659dee0cerion   case 0x24: // stw (Store W, PPC32 p530)
524176de5cf615380b23b4b5bcced6541233cd4a93a0cerion      DIP("stw r%u,%d(r%u)\n", rS_addr, simm16, rA_addr);
52421f5fe1fc3a37ca729925e8eec25aa1025b4a6cdbcarll      store( mkexpr(EA), mkNarrowTo32(ty, mkexpr(rS)) );
5243b85e8bba97fdae7d892f7bfd12e4601307e4721dcerion      break;
5244b85e8bba97fdae7d892f7bfd12e4601307e4721dcerion
52455b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion   case 0x25: // stwu (Store W, Update, PPC32 p534)
524676de5cf615380b23b4b5bcced6541233cd4a93a0cerion      if (rA_addr == 0) {
52475b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion         vex_printf("dis_int_store(ppc)(stwu,rA_addr)\n");
5248b85e8bba97fdae7d892f7bfd12e4601307e4721dcerion         return False;
5249b85e8bba97fdae7d892f7bfd12e4601307e4721dcerion      }
525076de5cf615380b23b4b5bcced6541233cd4a93a0cerion      DIP("stwu r%u,%d(r%u)\n", rS_addr, simm16, rA_addr);
5251d953ebb9b04cbad6891676df597bf0c542b1ec89cerion      putIReg( rA_addr, mkexpr(EA) );
52521f5fe1fc3a37ca729925e8eec25aa1025b4a6cdbcarll      store( mkexpr(EA), mkNarrowTo32(ty, mkexpr(rS)) );
5253b85e8bba97fdae7d892f7bfd12e4601307e4721dcerion      break;
5254b85e8bba97fdae7d892f7bfd12e4601307e4721dcerion
5255f0de28cf1a762b0d6f74c93d3532c89a230673bbcerion   /* X Form : all these use EA_indexed */
5256b85e8bba97fdae7d892f7bfd12e4601307e4721dcerion   case 0x1F:
5257b85e8bba97fdae7d892f7bfd12e4601307e4721dcerion      if (b0 != 0) {
52585b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion         vex_printf("dis_int_store(ppc)(0x1F,b0)\n");
5259b85e8bba97fdae7d892f7bfd12e4601307e4721dcerion         return False;
5260b85e8bba97fdae7d892f7bfd12e4601307e4721dcerion      }
5261b85e8bba97fdae7d892f7bfd12e4601307e4721dcerion
5262b85e8bba97fdae7d892f7bfd12e4601307e4721dcerion      switch (opc2) {
52635b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion      case 0x0F7: // stbux (Store B, Update Indexed, PPC32 p511)
526476de5cf615380b23b4b5bcced6541233cd4a93a0cerion         if (rA_addr == 0) {
52655b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion            vex_printf("dis_int_store(ppc)(stbux,rA_addr)\n");
5266b85e8bba97fdae7d892f7bfd12e4601307e4721dcerion            return False;
5267b85e8bba97fdae7d892f7bfd12e4601307e4721dcerion         }
526876de5cf615380b23b4b5bcced6541233cd4a93a0cerion         DIP("stbux r%u,r%u,r%u\n", rS_addr, rA_addr, rB_addr);
5269d953ebb9b04cbad6891676df597bf0c542b1ec89cerion         putIReg( rA_addr, mkexpr(EA) );
52701f5fe1fc3a37ca729925e8eec25aa1025b4a6cdbcarll         store( mkexpr(EA), mkNarrowTo8(ty, mkexpr(rS)) );
5271b85e8bba97fdae7d892f7bfd12e4601307e4721dcerion         break;
5272b85e8bba97fdae7d892f7bfd12e4601307e4721dcerion
5273e9d361ab43518b6dfbd3d846f48859534659dee0cerion      case 0x0D7: // stbx (Store B Indexed, PPC32 p512)
527476de5cf615380b23b4b5bcced6541233cd4a93a0cerion         DIP("stbx r%u,r%u,r%u\n", rS_addr, rA_addr, rB_addr);
52751f5fe1fc3a37ca729925e8eec25aa1025b4a6cdbcarll         store( mkexpr(EA), mkNarrowTo8(ty, mkexpr(rS)) );
5276b85e8bba97fdae7d892f7bfd12e4601307e4721dcerion         break;
5277b85e8bba97fdae7d892f7bfd12e4601307e4721dcerion
52785b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion      case 0x1B7: // sthux (Store HW, Update Indexed, PPC32 p525)
527976de5cf615380b23b4b5bcced6541233cd4a93a0cerion         if (rA_addr == 0) {
52805b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion            vex_printf("dis_int_store(ppc)(sthux,rA_addr)\n");
5281cb14e73e1556145a29ae2c8f4f7ab73cf2963864cerion            return False;
5282cb14e73e1556145a29ae2c8f4f7ab73cf2963864cerion         }
528376de5cf615380b23b4b5bcced6541233cd4a93a0cerion         DIP("sthux r%u,r%u,r%u\n", rS_addr, rA_addr, rB_addr);
5284d953ebb9b04cbad6891676df597bf0c542b1ec89cerion         putIReg( rA_addr, mkexpr(EA) );
52851f5fe1fc3a37ca729925e8eec25aa1025b4a6cdbcarll         store( mkexpr(EA), mkNarrowTo16(ty, mkexpr(rS)) );
5286cb14e73e1556145a29ae2c8f4f7ab73cf2963864cerion         break;
5287b85e8bba97fdae7d892f7bfd12e4601307e4721dcerion
5288e9d361ab43518b6dfbd3d846f48859534659dee0cerion      case 0x197: // sthx (Store HW Indexed, PPC32 p526)
528976de5cf615380b23b4b5bcced6541233cd4a93a0cerion         DIP("sthx r%u,r%u,r%u\n", rS_addr, rA_addr, rB_addr);
52901f5fe1fc3a37ca729925e8eec25aa1025b4a6cdbcarll         store( mkexpr(EA), mkNarrowTo16(ty, mkexpr(rS)) );
5291b85e8bba97fdae7d892f7bfd12e4601307e4721dcerion         break;
5292b85e8bba97fdae7d892f7bfd12e4601307e4721dcerion
52935b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion      case 0x0B7: // stwux (Store W, Update Indexed, PPC32 p535)
529476de5cf615380b23b4b5bcced6541233cd4a93a0cerion         if (rA_addr == 0) {
52955b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion            vex_printf("dis_int_store(ppc)(stwux,rA_addr)\n");
5296b85e8bba97fdae7d892f7bfd12e4601307e4721dcerion            return False;
5297b85e8bba97fdae7d892f7bfd12e4601307e4721dcerion         }
529876de5cf615380b23b4b5bcced6541233cd4a93a0cerion         DIP("stwux r%u,r%u,r%u\n", rS_addr, rA_addr, rB_addr);
5299d953ebb9b04cbad6891676df597bf0c542b1ec89cerion         putIReg( rA_addr, mkexpr(EA) );
53001f5fe1fc3a37ca729925e8eec25aa1025b4a6cdbcarll         store( mkexpr(EA), mkNarrowTo32(ty, mkexpr(rS)) );
5301b85e8bba97fdae7d892f7bfd12e4601307e4721dcerion         break;
5302b85e8bba97fdae7d892f7bfd12e4601307e4721dcerion
5303e9d361ab43518b6dfbd3d846f48859534659dee0cerion      case 0x097: // stwx (Store W Indexed, PPC32 p536)
530476de5cf615380b23b4b5bcced6541233cd4a93a0cerion         DIP("stwx r%u,r%u,r%u\n", rS_addr, rA_addr, rB_addr);
53051f5fe1fc3a37ca729925e8eec25aa1025b4a6cdbcarll         store( mkexpr(EA), mkNarrowTo32(ty, mkexpr(rS)) );
5306b85e8bba97fdae7d892f7bfd12e4601307e4721dcerion         break;
5307b85e8bba97fdae7d892f7bfd12e4601307e4721dcerion
5308f0de28cf1a762b0d6f74c93d3532c89a230673bbcerion
5309f0de28cf1a762b0d6f74c93d3532c89a230673bbcerion      /* 64bit Stores */
53105b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion      case 0x0B5: // stdux (Store DWord, Update Indexed, PPC64 p584)
5311f0de28cf1a762b0d6f74c93d3532c89a230673bbcerion         if (rA_addr == 0) {
53125b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion            vex_printf("dis_int_store(ppc)(stdux,rA_addr)\n");
5313f0de28cf1a762b0d6f74c93d3532c89a230673bbcerion            return False;
5314f0de28cf1a762b0d6f74c93d3532c89a230673bbcerion         }
5315f0de28cf1a762b0d6f74c93d3532c89a230673bbcerion         DIP("stdux r%u,r%u,r%u\n", rS_addr, rA_addr, rB_addr);
5316f0de28cf1a762b0d6f74c93d3532c89a230673bbcerion         putIReg( rA_addr, mkexpr(EA) );
53171f5fe1fc3a37ca729925e8eec25aa1025b4a6cdbcarll         store( mkexpr(EA), mkexpr(rS) );
5318f0de28cf1a762b0d6f74c93d3532c89a230673bbcerion         break;
5319f0de28cf1a762b0d6f74c93d3532c89a230673bbcerion
53205b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion      case 0x095: // stdx (Store DWord Indexed, PPC64 p585)
5321f0de28cf1a762b0d6f74c93d3532c89a230673bbcerion         DIP("stdx r%u,r%u,r%u\n", rS_addr, rA_addr, rB_addr);
53221f5fe1fc3a37ca729925e8eec25aa1025b4a6cdbcarll         store( mkexpr(EA), mkexpr(rS) );
5323f0de28cf1a762b0d6f74c93d3532c89a230673bbcerion         break;
5324f0de28cf1a762b0d6f74c93d3532c89a230673bbcerion
5325b85e8bba97fdae7d892f7bfd12e4601307e4721dcerion      default:
53265b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion         vex_printf("dis_int_store(ppc)(opc2)\n");
5327b85e8bba97fdae7d892f7bfd12e4601307e4721dcerion         return False;
5328b85e8bba97fdae7d892f7bfd12e4601307e4721dcerion      }
5329b85e8bba97fdae7d892f7bfd12e4601307e4721dcerion      break;
5330f0de28cf1a762b0d6f74c93d3532c89a230673bbcerion
53316d83422ba5b685adc40fdc97651bcca4ecd47d1dsewardj   /* DS Form - 64bit Stores.  In each case EA will have been formed
53326d83422ba5b685adc40fdc97651bcca4ecd47d1dsewardj      with the lowest 2 bits masked off the immediate offset. */
5333f0de28cf1a762b0d6f74c93d3532c89a230673bbcerion   case 0x3E:
53346d83422ba5b685adc40fdc97651bcca4ecd47d1dsewardj      switch ((b1<<1) | b0) {
53355b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion      case 0x0: // std (Store DWord, PPC64 p580)
53360c74bb5aa3240f693df0568d578baabf0c376dc4carll         if (!mode64)
53370c74bb5aa3240f693df0568d578baabf0c376dc4carll            return False;
53380c74bb5aa3240f693df0568d578baabf0c376dc4carll
5339f0de28cf1a762b0d6f74c93d3532c89a230673bbcerion         DIP("std r%u,%d(r%u)\n", rS_addr, simm16, rA_addr);
53401f5fe1fc3a37ca729925e8eec25aa1025b4a6cdbcarll         store( mkexpr(EA), mkexpr(rS) );
5341f0de28cf1a762b0d6f74c93d3532c89a230673bbcerion         break;
5342f0de28cf1a762b0d6f74c93d3532c89a230673bbcerion
53435b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion      case 0x1: // stdu (Store DWord, Update, PPC64 p583)
53440c74bb5aa3240f693df0568d578baabf0c376dc4carll         if (!mode64)
53450c74bb5aa3240f693df0568d578baabf0c376dc4carll            return False;
53460c74bb5aa3240f693df0568d578baabf0c376dc4carll
5347f0de28cf1a762b0d6f74c93d3532c89a230673bbcerion         DIP("stdu r%u,%d(r%u)\n", rS_addr, simm16, rA_addr);
5348f0de28cf1a762b0d6f74c93d3532c89a230673bbcerion         putIReg( rA_addr, mkexpr(EA) );
53491f5fe1fc3a37ca729925e8eec25aa1025b4a6cdbcarll         store( mkexpr(EA), mkexpr(rS) );
5350f0de28cf1a762b0d6f74c93d3532c89a230673bbcerion         break;
5351f0de28cf1a762b0d6f74c93d3532c89a230673bbcerion
535278850ae9874a90ea625fcee1fd4c359375b7b538carll      case 0x2: { // stq (Store QuadWord, Update, PPC64 p583)
535378850ae9874a90ea625fcee1fd4c359375b7b538carll         IRTemp EA_hi = newTemp(ty);
535478850ae9874a90ea625fcee1fd4c359375b7b538carll         IRTemp EA_lo = newTemp(ty);
535578850ae9874a90ea625fcee1fd4c359375b7b538carll         DIP("stq r%u,%d(r%u)\n", rS_addr, simm16, rA_addr);
535678850ae9874a90ea625fcee1fd4c359375b7b538carll
535778850ae9874a90ea625fcee1fd4c359375b7b538carll         if (mode64) {
5358999ef56da3e4426c5f6bf74de40d23ff02dafb34carll            if (host_endness == VexEndnessBE) {
5359999ef56da3e4426c5f6bf74de40d23ff02dafb34carll
5360999ef56da3e4426c5f6bf74de40d23ff02dafb34carll               /* upper 64-bits */
5361999ef56da3e4426c5f6bf74de40d23ff02dafb34carll               assign( EA_hi, ea_rAor0_simm( rA_addr, simm16 ) );
536278850ae9874a90ea625fcee1fd4c359375b7b538carll
5363999ef56da3e4426c5f6bf74de40d23ff02dafb34carll               /* lower 64-bits */
5364999ef56da3e4426c5f6bf74de40d23ff02dafb34carll               assign( EA_lo, ea_rAor0_simm( rA_addr, simm16+8 ) );
5365999ef56da3e4426c5f6bf74de40d23ff02dafb34carll	    } else {
5366999ef56da3e4426c5f6bf74de40d23ff02dafb34carll               /* upper 64-bits */
5367999ef56da3e4426c5f6bf74de40d23ff02dafb34carll               assign( EA_hi, ea_rAor0_simm( rA_addr, simm16+8 ) );
5368999ef56da3e4426c5f6bf74de40d23ff02dafb34carll
5369999ef56da3e4426c5f6bf74de40d23ff02dafb34carll               /* lower 64-bits */
5370999ef56da3e4426c5f6bf74de40d23ff02dafb34carll               assign( EA_lo, ea_rAor0_simm( rA_addr, simm16 ) );
5371999ef56da3e4426c5f6bf74de40d23ff02dafb34carll	    }
537278850ae9874a90ea625fcee1fd4c359375b7b538carll         } else {
537378850ae9874a90ea625fcee1fd4c359375b7b538carll            /* upper half of upper 64-bits */
537478850ae9874a90ea625fcee1fd4c359375b7b538carll            assign( EA_hi, ea_rAor0_simm( rA_addr, simm16+4 ) );
537578850ae9874a90ea625fcee1fd4c359375b7b538carll
537678850ae9874a90ea625fcee1fd4c359375b7b538carll            /* lower half of upper 64-bits */
537778850ae9874a90ea625fcee1fd4c359375b7b538carll            assign( EA_lo, ea_rAor0_simm( rA_addr, simm16+12 ) );
537878850ae9874a90ea625fcee1fd4c359375b7b538carll         }
53791f5fe1fc3a37ca729925e8eec25aa1025b4a6cdbcarll         store( mkexpr(EA_hi), mkexpr(rS) );
53801f5fe1fc3a37ca729925e8eec25aa1025b4a6cdbcarll         store( mkexpr(EA_lo), getIReg( rS_addr+1 ) );
538178850ae9874a90ea625fcee1fd4c359375b7b538carll         break;
538278850ae9874a90ea625fcee1fd4c359375b7b538carll      }
5383f0de28cf1a762b0d6f74c93d3532c89a230673bbcerion      default:
53845b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion         vex_printf("dis_int_load(ppc)(0x3A, opc2)\n");
5385f0de28cf1a762b0d6f74c93d3532c89a230673bbcerion         return False;
5386f0de28cf1a762b0d6f74c93d3532c89a230673bbcerion      }
5387f0de28cf1a762b0d6f74c93d3532c89a230673bbcerion      break;
5388f0de28cf1a762b0d6f74c93d3532c89a230673bbcerion
5389b85e8bba97fdae7d892f7bfd12e4601307e4721dcerion   default:
53905b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion      vex_printf("dis_int_store(ppc)(opc1)\n");
5391b85e8bba97fdae7d892f7bfd12e4601307e4721dcerion      return False;
5392b85e8bba97fdae7d892f7bfd12e4601307e4721dcerion   }
5393b85e8bba97fdae7d892f7bfd12e4601307e4721dcerion   return True;
5394d23be4e26c2d35c60cdf2fce0dfe0e9b1fa6d008cerion}
5395d23be4e26c2d35c60cdf2fce0dfe0e9b1fa6d008cerion
5396d23be4e26c2d35c60cdf2fce0dfe0e9b1fa6d008cerion
5397d23be4e26c2d35c60cdf2fce0dfe0e9b1fa6d008cerion
53987787af415a9104b601c2f0ce5b56749e4fd86691sewardj/*
53997787af415a9104b601c2f0ce5b56749e4fd86691sewardj  Integer Load/Store Multiple Instructions
54007787af415a9104b601c2f0ce5b56749e4fd86691sewardj*/
54017787af415a9104b601c2f0ce5b56749e4fd86691sewardjstatic Bool dis_int_ldst_mult ( UInt theInstr )
54027787af415a9104b601c2f0ce5b56749e4fd86691sewardj{
54037787af415a9104b601c2f0ce5b56749e4fd86691sewardj   /* D-Form */
540476de5cf615380b23b4b5bcced6541233cd4a93a0cerion   UChar opc1     = ifieldOPC(theInstr);
540576de5cf615380b23b4b5bcced6541233cd4a93a0cerion   UChar rD_addr  = ifieldRegDS(theInstr);
540676de5cf615380b23b4b5bcced6541233cd4a93a0cerion   UChar rS_addr  = rD_addr;
540776de5cf615380b23b4b5bcced6541233cd4a93a0cerion   UChar rA_addr  = ifieldRegA(theInstr);
54082831b00c4950d6c2b061def05fd67528fe132ececerion   UInt  uimm16   = ifieldUIMM16(theInstr);
5409edf7fc572e2decb93e9143961e8739c8fe18899dcerion
5410d953ebb9b04cbad6891676df597bf0c542b1ec89cerion   Int     simm16 = extend_s_16to32(uimm16);
5411d953ebb9b04cbad6891676df597bf0c542b1ec89cerion   IRType  ty     = mode64 ? Ity_I64 : Ity_I32;
54129fcbb9a82f6f263626aa5a432ab7e94f37476181carll   IROp    mkAdd  = mode64 ? Iop_Add64 : Iop_Add32;
5413d953ebb9b04cbad6891676df597bf0c542b1ec89cerion   IRTemp  EA     = newTemp(ty);
5414d953ebb9b04cbad6891676df597bf0c542b1ec89cerion   UInt    r      = 0;
5415d953ebb9b04cbad6891676df597bf0c542b1ec89cerion   UInt    ea_off = 0;
54167787af415a9104b601c2f0ce5b56749e4fd86691sewardj   IRExpr* irx_addr;
5417edf7fc572e2decb93e9143961e8739c8fe18899dcerion
5418d953ebb9b04cbad6891676df597bf0c542b1ec89cerion   assign( EA, ea_rAor0_simm( rA_addr, simm16 ) );
5419d953ebb9b04cbad6891676df597bf0c542b1ec89cerion
54207787af415a9104b601c2f0ce5b56749e4fd86691sewardj   switch (opc1) {
5421d953ebb9b04cbad6891676df597bf0c542b1ec89cerion   case 0x2E: // lmw (Load Multiple Word, PPC32 p454)
5422d953ebb9b04cbad6891676df597bf0c542b1ec89cerion      if (rA_addr >= rD_addr) {
54235b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion         vex_printf("dis_int_ldst_mult(ppc)(lmw,rA_addr)\n");
5424d953ebb9b04cbad6891676df597bf0c542b1ec89cerion         return False;
5425d953ebb9b04cbad6891676df597bf0c542b1ec89cerion      }
5426d953ebb9b04cbad6891676df597bf0c542b1ec89cerion      DIP("lmw r%u,%d(r%u)\n", rD_addr, simm16, rA_addr);
5427d953ebb9b04cbad6891676df597bf0c542b1ec89cerion      for (r = rD_addr; r <= 31; r++) {
54289fcbb9a82f6f263626aa5a432ab7e94f37476181carll         irx_addr = binop(mkAdd, mkexpr(EA), mode64 ? mkU64(ea_off) : mkU32(ea_off));
54291f5fe1fc3a37ca729925e8eec25aa1025b4a6cdbcarll         putIReg( r, mkWidenFrom32(ty, load(Ity_I32, irx_addr ),
5430e9d8a26b690c2561ac54ab0cd6ad83ecbadcbe76sewardj                                       False) );
5431d953ebb9b04cbad6891676df597bf0c542b1ec89cerion         ea_off += 4;
5432d953ebb9b04cbad6891676df597bf0c542b1ec89cerion      }
5433d953ebb9b04cbad6891676df597bf0c542b1ec89cerion      break;
54347787af415a9104b601c2f0ce5b56749e4fd86691sewardj
5435d953ebb9b04cbad6891676df597bf0c542b1ec89cerion   case 0x2F: // stmw (Store Multiple Word, PPC32 p527)
5436d953ebb9b04cbad6891676df597bf0c542b1ec89cerion      DIP("stmw r%u,%d(r%u)\n", rS_addr, simm16, rA_addr);
5437d953ebb9b04cbad6891676df597bf0c542b1ec89cerion      for (r = rS_addr; r <= 31; r++) {
54389fcbb9a82f6f263626aa5a432ab7e94f37476181carll         irx_addr = binop(mkAdd, mkexpr(EA), mode64 ? mkU64(ea_off) : mkU32(ea_off));
54391f5fe1fc3a37ca729925e8eec25aa1025b4a6cdbcarll         store( irx_addr, mkNarrowTo32(ty, getIReg(r)) );
5440d953ebb9b04cbad6891676df597bf0c542b1ec89cerion         ea_off += 4;
5441d953ebb9b04cbad6891676df597bf0c542b1ec89cerion      }
5442d953ebb9b04cbad6891676df597bf0c542b1ec89cerion      break;
54437787af415a9104b601c2f0ce5b56749e4fd86691sewardj
5444d953ebb9b04cbad6891676df597bf0c542b1ec89cerion   default:
54455b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion      vex_printf("dis_int_ldst_mult(ppc)(opc1)\n");
5446d953ebb9b04cbad6891676df597bf0c542b1ec89cerion      return False;
54477787af415a9104b601c2f0ce5b56749e4fd86691sewardj   }
54487787af415a9104b601c2f0ce5b56749e4fd86691sewardj   return True;
54497787af415a9104b601c2f0ce5b56749e4fd86691sewardj}
54507787af415a9104b601c2f0ce5b56749e4fd86691sewardj
54517787af415a9104b601c2f0ce5b56749e4fd86691sewardj
54527787af415a9104b601c2f0ce5b56749e4fd86691sewardj
545387e651f40360a8f1c9418710e79c482028759f8csewardj/*
545487e651f40360a8f1c9418710e79c482028759f8csewardj  Integer Load/Store String Instructions
545587e651f40360a8f1c9418710e79c482028759f8csewardj*/
545687e651f40360a8f1c9418710e79c482028759f8csewardjstatic
545787e651f40360a8f1c9418710e79c482028759f8csewardjvoid generate_lsw_sequence ( IRTemp tNBytes,   // # bytes, :: Ity_I32
545887e651f40360a8f1c9418710e79c482028759f8csewardj                             IRTemp EA,        // EA
545987e651f40360a8f1c9418710e79c482028759f8csewardj                             Int    rD,        // first dst register
5460d953ebb9b04cbad6891676df597bf0c542b1ec89cerion                             Int    maxBytes ) // 32 or 128
546187e651f40360a8f1c9418710e79c482028759f8csewardj{
546287e651f40360a8f1c9418710e79c482028759f8csewardj   Int     i, shift = 24;
546387e651f40360a8f1c9418710e79c482028759f8csewardj   IRExpr* e_nbytes = mkexpr(tNBytes);
5464d953ebb9b04cbad6891676df597bf0c542b1ec89cerion   IRExpr* e_EA     = mkexpr(EA);
5465d953ebb9b04cbad6891676df597bf0c542b1ec89cerion   IRType  ty       = mode64 ? Ity_I64 : Ity_I32;
546687e651f40360a8f1c9418710e79c482028759f8csewardj
54675876fa100009ff1179c6e4aae0838176b9685794sewardj   vassert(rD >= 0 && rD < 32);
546887e651f40360a8f1c9418710e79c482028759f8csewardj   rD--; if (rD < 0) rD = 31;
546987e651f40360a8f1c9418710e79c482028759f8csewardj
547087e651f40360a8f1c9418710e79c482028759f8csewardj   for (i = 0; i < maxBytes; i++) {
547187e651f40360a8f1c9418710e79c482028759f8csewardj      /* if (nBytes < (i+1)) goto NIA; */
547287e651f40360a8f1c9418710e79c482028759f8csewardj      stmt( IRStmt_Exit( binop(Iop_CmpLT32U, e_nbytes, mkU32(i+1)),
547387e651f40360a8f1c9418710e79c482028759f8csewardj                         Ijk_Boring,
54743dee849ec7c38746749065e67dc53b75daa7617dsewardj                         mkSzConst( ty, nextInsnAddr()), OFFB_CIA ));
547587e651f40360a8f1c9418710e79c482028759f8csewardj      /* when crossing into a new dest register, set it to zero. */
547687e651f40360a8f1c9418710e79c482028759f8csewardj      if ((i % 4) == 0) {
547787e651f40360a8f1c9418710e79c482028759f8csewardj         rD++; if (rD == 32) rD = 0;
54782831b00c4950d6c2b061def05fd67528fe132ececerion         putIReg(rD, mkSzImm(ty, 0));
547987e651f40360a8f1c9418710e79c482028759f8csewardj         shift = 24;
548087e651f40360a8f1c9418710e79c482028759f8csewardj      }
548187e651f40360a8f1c9418710e79c482028759f8csewardj      /* rD |=  (8Uto32(*(EA+i))) << shift */
548287e651f40360a8f1c9418710e79c482028759f8csewardj      vassert(shift == 0 || shift == 8 || shift == 16 || shift == 24);
54832ef8a37484a9d027b19aa024b8e364645f04c2b8sewardj      putIReg(
54842ef8a37484a9d027b19aa024b8e364645f04c2b8sewardj         rD,
5485e9d8a26b690c2561ac54ab0cd6ad83ecbadcbe76sewardj         mkWidenFrom32(
54862ef8a37484a9d027b19aa024b8e364645f04c2b8sewardj            ty,
54872ef8a37484a9d027b19aa024b8e364645f04c2b8sewardj            binop(
54882ef8a37484a9d027b19aa024b8e364645f04c2b8sewardj               Iop_Or32,
5489e9d8a26b690c2561ac54ab0cd6ad83ecbadcbe76sewardj               mkNarrowTo32(ty, getIReg(rD)),
54902ef8a37484a9d027b19aa024b8e364645f04c2b8sewardj               binop(
54912ef8a37484a9d027b19aa024b8e364645f04c2b8sewardj                  Iop_Shl32,
54922ef8a37484a9d027b19aa024b8e364645f04c2b8sewardj                  unop(
54932ef8a37484a9d027b19aa024b8e364645f04c2b8sewardj                     Iop_8Uto32,
54941f5fe1fc3a37ca729925e8eec25aa1025b4a6cdbcarll                     load( Ity_I8,
54951f5fe1fc3a37ca729925e8eec25aa1025b4a6cdbcarll                           binop( mkSzOp(ty,Iop_Add8),
54961f5fe1fc3a37ca729925e8eec25aa1025b4a6cdbcarll                                  e_EA, mkSzImm(ty,i)))
54972ef8a37484a9d027b19aa024b8e364645f04c2b8sewardj                  ),
54982ef8a37484a9d027b19aa024b8e364645f04c2b8sewardj                  mkU8(toUChar(shift))
54992ef8a37484a9d027b19aa024b8e364645f04c2b8sewardj               )
55002ef8a37484a9d027b19aa024b8e364645f04c2b8sewardj            ),
55012ef8a37484a9d027b19aa024b8e364645f04c2b8sewardj            /*Signed*/False
55022ef8a37484a9d027b19aa024b8e364645f04c2b8sewardj	 )
55032ef8a37484a9d027b19aa024b8e364645f04c2b8sewardj      );
550487e651f40360a8f1c9418710e79c482028759f8csewardj      shift -= 8;
550587e651f40360a8f1c9418710e79c482028759f8csewardj   }
550687e651f40360a8f1c9418710e79c482028759f8csewardj}
550787e651f40360a8f1c9418710e79c482028759f8csewardj
55085876fa100009ff1179c6e4aae0838176b9685794sewardjstatic
55095876fa100009ff1179c6e4aae0838176b9685794sewardjvoid generate_stsw_sequence ( IRTemp tNBytes,   // # bytes, :: Ity_I32
55105876fa100009ff1179c6e4aae0838176b9685794sewardj                              IRTemp EA,        // EA
55115876fa100009ff1179c6e4aae0838176b9685794sewardj                              Int    rS,        // first src register
5512d953ebb9b04cbad6891676df597bf0c542b1ec89cerion                              Int    maxBytes ) // 32 or 128
55135876fa100009ff1179c6e4aae0838176b9685794sewardj{
55145876fa100009ff1179c6e4aae0838176b9685794sewardj   Int     i, shift = 24;
55155876fa100009ff1179c6e4aae0838176b9685794sewardj   IRExpr* e_nbytes = mkexpr(tNBytes);
5516d953ebb9b04cbad6891676df597bf0c542b1ec89cerion   IRExpr* e_EA     = mkexpr(EA);
5517d953ebb9b04cbad6891676df597bf0c542b1ec89cerion   IRType  ty       = mode64 ? Ity_I64 : Ity_I32;
55185876fa100009ff1179c6e4aae0838176b9685794sewardj
55195876fa100009ff1179c6e4aae0838176b9685794sewardj   vassert(rS >= 0 && rS < 32);
55205876fa100009ff1179c6e4aae0838176b9685794sewardj   rS--; if (rS < 0) rS = 31;
55215876fa100009ff1179c6e4aae0838176b9685794sewardj
55225876fa100009ff1179c6e4aae0838176b9685794sewardj   for (i = 0; i < maxBytes; i++) {
55235876fa100009ff1179c6e4aae0838176b9685794sewardj      /* if (nBytes < (i+1)) goto NIA; */
55245876fa100009ff1179c6e4aae0838176b9685794sewardj      stmt( IRStmt_Exit( binop(Iop_CmpLT32U, e_nbytes, mkU32(i+1)),
55255876fa100009ff1179c6e4aae0838176b9685794sewardj                         Ijk_Boring,
55263dee849ec7c38746749065e67dc53b75daa7617dsewardj                         mkSzConst( ty, nextInsnAddr() ), OFFB_CIA ));
55275876fa100009ff1179c6e4aae0838176b9685794sewardj      /* check for crossing into a new src register. */
55285876fa100009ff1179c6e4aae0838176b9685794sewardj      if ((i % 4) == 0) {
55295876fa100009ff1179c6e4aae0838176b9685794sewardj         rS++; if (rS == 32) rS = 0;
55305876fa100009ff1179c6e4aae0838176b9685794sewardj         shift = 24;
55315876fa100009ff1179c6e4aae0838176b9685794sewardj      }
55325876fa100009ff1179c6e4aae0838176b9685794sewardj      /* *(EA+i) = 32to8(rS >> shift) */
55335876fa100009ff1179c6e4aae0838176b9685794sewardj      vassert(shift == 0 || shift == 8 || shift == 16 || shift == 24);
55341f5fe1fc3a37ca729925e8eec25aa1025b4a6cdbcarll      store(
55351f5fe1fc3a37ca729925e8eec25aa1025b4a6cdbcarll            binop( mkSzOp(ty,Iop_Add8), e_EA, mkSzImm(ty,i)),
55361f5fe1fc3a37ca729925e8eec25aa1025b4a6cdbcarll            unop( Iop_32to8,
55371f5fe1fc3a37ca729925e8eec25aa1025b4a6cdbcarll                  binop( Iop_Shr32,
55381f5fe1fc3a37ca729925e8eec25aa1025b4a6cdbcarll                         mkNarrowTo32( ty, getIReg(rS) ),
55391f5fe1fc3a37ca729925e8eec25aa1025b4a6cdbcarll                         mkU8( toUChar(shift) )))
55405876fa100009ff1179c6e4aae0838176b9685794sewardj      );
55415876fa100009ff1179c6e4aae0838176b9685794sewardj      shift -= 8;
55425876fa100009ff1179c6e4aae0838176b9685794sewardj   }
55435876fa100009ff1179c6e4aae0838176b9685794sewardj}
55445876fa100009ff1179c6e4aae0838176b9685794sewardj
554587e651f40360a8f1c9418710e79c482028759f8csewardjstatic Bool dis_int_ldst_str ( UInt theInstr, /*OUT*/Bool* stopHere )
554687e651f40360a8f1c9418710e79c482028759f8csewardj{
554787e651f40360a8f1c9418710e79c482028759f8csewardj   /* X-Form */
554876de5cf615380b23b4b5bcced6541233cd4a93a0cerion   UChar opc1     = ifieldOPC(theInstr);
554976de5cf615380b23b4b5bcced6541233cd4a93a0cerion   UChar rD_addr  = ifieldRegDS(theInstr);
555076de5cf615380b23b4b5bcced6541233cd4a93a0cerion   UChar rS_addr  = rD_addr;
555176de5cf615380b23b4b5bcced6541233cd4a93a0cerion   UChar rA_addr  = ifieldRegA(theInstr);
555276de5cf615380b23b4b5bcced6541233cd4a93a0cerion   UChar rB_addr  = ifieldRegB(theInstr);
555376de5cf615380b23b4b5bcced6541233cd4a93a0cerion   UChar NumBytes = rB_addr;
555476de5cf615380b23b4b5bcced6541233cd4a93a0cerion   UInt  opc2     = ifieldOPClo10(theInstr);
555576de5cf615380b23b4b5bcced6541233cd4a93a0cerion   UChar b0       = ifieldBIT0(theInstr);
5556edf7fc572e2decb93e9143961e8739c8fe18899dcerion
5557d953ebb9b04cbad6891676df597bf0c542b1ec89cerion   IRType ty      = mode64 ? Ity_I64 : Ity_I32;
5558d953ebb9b04cbad6891676df597bf0c542b1ec89cerion   IRTemp t_EA    = newTemp(ty);
555987e651f40360a8f1c9418710e79c482028759f8csewardj   IRTemp t_nbytes = IRTemp_INVALID;
5560edf7fc572e2decb93e9143961e8739c8fe18899dcerion
556187e651f40360a8f1c9418710e79c482028759f8csewardj   *stopHere = False;
5562edf7fc572e2decb93e9143961e8739c8fe18899dcerion
556387e651f40360a8f1c9418710e79c482028759f8csewardj   if (opc1 != 0x1F || b0 != 0) {
55645b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion      vex_printf("dis_int_ldst_str(ppc)(opc1)\n");
556587e651f40360a8f1c9418710e79c482028759f8csewardj      return False;
556687e651f40360a8f1c9418710e79c482028759f8csewardj   }
556787e651f40360a8f1c9418710e79c482028759f8csewardj
556887e651f40360a8f1c9418710e79c482028759f8csewardj   switch (opc2) {
556987e651f40360a8f1c9418710e79c482028759f8csewardj   case 0x255: // lswi (Load String Word Immediate, PPC32 p455)
557087e651f40360a8f1c9418710e79c482028759f8csewardj      /* NB: does not reject the case where RA is in the range of
557187e651f40360a8f1c9418710e79c482028759f8csewardj         registers to be loaded.  It should. */
5572d953ebb9b04cbad6891676df597bf0c542b1ec89cerion      DIP("lswi r%u,r%u,%d\n", rD_addr, rA_addr, NumBytes);
5573d953ebb9b04cbad6891676df597bf0c542b1ec89cerion      assign( t_EA, ea_rAor0(rA_addr) );
55742ef8a37484a9d027b19aa024b8e364645f04c2b8sewardj      if (NumBytes == 8 && !mode64) {
557587e651f40360a8f1c9418710e79c482028759f8csewardj         /* Special case hack */
557676de5cf615380b23b4b5bcced6541233cd4a93a0cerion         /* rD = Mem[EA]; (rD+1)%32 = Mem[EA+4] */
557776de5cf615380b23b4b5bcced6541233cd4a93a0cerion         putIReg( rD_addr,
55781f5fe1fc3a37ca729925e8eec25aa1025b4a6cdbcarll                  load(Ity_I32, mkexpr(t_EA)) );
557976de5cf615380b23b4b5bcced6541233cd4a93a0cerion         putIReg( (rD_addr+1) % 32,
55801f5fe1fc3a37ca729925e8eec25aa1025b4a6cdbcarll                  load(Ity_I32,
55811f5fe1fc3a37ca729925e8eec25aa1025b4a6cdbcarll                       binop(Iop_Add32, mkexpr(t_EA), mkU32(4))) );
558287e651f40360a8f1c9418710e79c482028759f8csewardj      } else {
558387e651f40360a8f1c9418710e79c482028759f8csewardj         t_nbytes = newTemp(Ity_I32);
558476de5cf615380b23b4b5bcced6541233cd4a93a0cerion         assign( t_nbytes, mkU32(NumBytes==0 ? 32 : NumBytes) );
5585d953ebb9b04cbad6891676df597bf0c542b1ec89cerion         generate_lsw_sequence( t_nbytes, t_EA, rD_addr, 32 );
558687e651f40360a8f1c9418710e79c482028759f8csewardj         *stopHere = True;
558787e651f40360a8f1c9418710e79c482028759f8csewardj      }
558887e651f40360a8f1c9418710e79c482028759f8csewardj      return True;
558987e651f40360a8f1c9418710e79c482028759f8csewardj
559087e651f40360a8f1c9418710e79c482028759f8csewardj   case 0x215: // lswx (Load String Word Indexed, PPC32 p456)
559187e651f40360a8f1c9418710e79c482028759f8csewardj      /* NB: does not reject the case where RA is in the range of
559287e651f40360a8f1c9418710e79c482028759f8csewardj         registers to be loaded.  It should.  Although considering
559387e651f40360a8f1c9418710e79c482028759f8csewardj         that that can only be detected at run time, it's not easy to
559487e651f40360a8f1c9418710e79c482028759f8csewardj         do so. */
559576de5cf615380b23b4b5bcced6541233cd4a93a0cerion      if (rD_addr == rA_addr || rD_addr == rB_addr)
559687e651f40360a8f1c9418710e79c482028759f8csewardj         return False;
559776de5cf615380b23b4b5bcced6541233cd4a93a0cerion      if (rD_addr == 0 && rA_addr == 0)
559887e651f40360a8f1c9418710e79c482028759f8csewardj         return False;
5599d953ebb9b04cbad6891676df597bf0c542b1ec89cerion      DIP("lswx r%u,r%u,r%u\n", rD_addr, rA_addr, rB_addr);
560087e651f40360a8f1c9418710e79c482028759f8csewardj      t_nbytes = newTemp(Ity_I32);
5601d953ebb9b04cbad6891676df597bf0c542b1ec89cerion      assign( t_EA, ea_rAor0_idxd(rA_addr,rB_addr) );
5602edf7fc572e2decb93e9143961e8739c8fe18899dcerion      assign( t_nbytes, unop( Iop_8Uto32, getXER_BC() ) );
5603d953ebb9b04cbad6891676df597bf0c542b1ec89cerion      generate_lsw_sequence( t_nbytes, t_EA, rD_addr, 128 );
560487e651f40360a8f1c9418710e79c482028759f8csewardj      *stopHere = True;
560587e651f40360a8f1c9418710e79c482028759f8csewardj      return True;
560687e651f40360a8f1c9418710e79c482028759f8csewardj
56075876fa100009ff1179c6e4aae0838176b9685794sewardj   case 0x2D5: // stswi (Store String Word Immediate, PPC32 p528)
5608d953ebb9b04cbad6891676df597bf0c542b1ec89cerion      DIP("stswi r%u,r%u,%d\n", rS_addr, rA_addr, NumBytes);
5609d953ebb9b04cbad6891676df597bf0c542b1ec89cerion      assign( t_EA, ea_rAor0(rA_addr) );
56102ef8a37484a9d027b19aa024b8e364645f04c2b8sewardj      if (NumBytes == 8 && !mode64) {
56115876fa100009ff1179c6e4aae0838176b9685794sewardj         /* Special case hack */
561276de5cf615380b23b4b5bcced6541233cd4a93a0cerion         /* Mem[EA] = rD; Mem[EA+4] = (rD+1)%32 */
56131f5fe1fc3a37ca729925e8eec25aa1025b4a6cdbcarll         store( mkexpr(t_EA),
56141f5fe1fc3a37ca729925e8eec25aa1025b4a6cdbcarll                getIReg(rD_addr) );
56151f5fe1fc3a37ca729925e8eec25aa1025b4a6cdbcarll         store( binop(Iop_Add32, mkexpr(t_EA), mkU32(4)),
56161f5fe1fc3a37ca729925e8eec25aa1025b4a6cdbcarll                getIReg((rD_addr+1) % 32) );
56175876fa100009ff1179c6e4aae0838176b9685794sewardj      } else {
56185876fa100009ff1179c6e4aae0838176b9685794sewardj         t_nbytes = newTemp(Ity_I32);
561976de5cf615380b23b4b5bcced6541233cd4a93a0cerion         assign( t_nbytes, mkU32(NumBytes==0 ? 32 : NumBytes) );
5620d953ebb9b04cbad6891676df597bf0c542b1ec89cerion         generate_stsw_sequence( t_nbytes, t_EA, rD_addr, 32 );
56215876fa100009ff1179c6e4aae0838176b9685794sewardj         *stopHere = True;
56225876fa100009ff1179c6e4aae0838176b9685794sewardj      }
56235876fa100009ff1179c6e4aae0838176b9685794sewardj      return True;
56245876fa100009ff1179c6e4aae0838176b9685794sewardj
56255876fa100009ff1179c6e4aae0838176b9685794sewardj   case 0x295: // stswx (Store String Word Indexed, PPC32 p529)
5626d953ebb9b04cbad6891676df597bf0c542b1ec89cerion      DIP("stswx r%u,r%u,r%u\n", rS_addr, rA_addr, rB_addr);
56275876fa100009ff1179c6e4aae0838176b9685794sewardj      t_nbytes = newTemp(Ity_I32);
5628d953ebb9b04cbad6891676df597bf0c542b1ec89cerion      assign( t_EA, ea_rAor0_idxd(rA_addr,rB_addr) );
5629edf7fc572e2decb93e9143961e8739c8fe18899dcerion      assign( t_nbytes, unop( Iop_8Uto32, getXER_BC() ) );
5630d953ebb9b04cbad6891676df597bf0c542b1ec89cerion      generate_stsw_sequence( t_nbytes, t_EA, rS_addr, 128 );
56315876fa100009ff1179c6e4aae0838176b9685794sewardj      *stopHere = True;
56325876fa100009ff1179c6e4aae0838176b9685794sewardj      return True;
563387e651f40360a8f1c9418710e79c482028759f8csewardj
563487e651f40360a8f1c9418710e79c482028759f8csewardj   default:
56355b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion      vex_printf("dis_int_ldst_str(ppc)(opc2)\n");
563687e651f40360a8f1c9418710e79c482028759f8csewardj      return False;
563787e651f40360a8f1c9418710e79c482028759f8csewardj   }
563887e651f40360a8f1c9418710e79c482028759f8csewardj   return True;
563987e651f40360a8f1c9418710e79c482028759f8csewardj}
564087e651f40360a8f1c9418710e79c482028759f8csewardj
5641b51f0f4f33256638ed953156a2635aa739b232f1sewardj
5642b51f0f4f33256638ed953156a2635aa739b232f1sewardj/* ------------------------------------------------------------------
5643b51f0f4f33256638ed953156a2635aa739b232f1sewardj   Integer Branch Instructions
5644b51f0f4f33256638ed953156a2635aa739b232f1sewardj   ------------------------------------------------------------------ */
5645b51f0f4f33256638ed953156a2635aa739b232f1sewardj
56463d870a39e4d145e2f3d9f9a0eeed3475ec934ac1cerion/*
5647b51f0f4f33256638ed953156a2635aa739b232f1sewardj  Branch helper function
5648b51f0f4f33256638ed953156a2635aa739b232f1sewardj  ok = BO[2] | ((CTR[0] != 0) ^ BO[1])
5649b51f0f4f33256638ed953156a2635aa739b232f1sewardj  Returns an I32 which is 0x00000000 if the ctr condition failed
5650b51f0f4f33256638ed953156a2635aa739b232f1sewardj  and 0xFFFFFFFF otherwise.
56513d870a39e4d145e2f3d9f9a0eeed3475ec934ac1cerion*/
5652b51f0f4f33256638ed953156a2635aa739b232f1sewardjstatic IRExpr* /* :: Ity_I32 */ branch_ctr_ok( UInt BO )
5653645c930b1a61f4493ee2d472b34fbb439233a874cerion{
5654d953ebb9b04cbad6891676df597bf0c542b1ec89cerion   IRType ty = mode64 ? Ity_I64 : Ity_I32;
5655b51f0f4f33256638ed953156a2635aa739b232f1sewardj   IRTemp ok = newTemp(Ity_I32);
5656b51f0f4f33256638ed953156a2635aa739b232f1sewardj
5657f0de28cf1a762b0d6f74c93d3532c89a230673bbcerion   if ((BO >> 2) & 1) {     // independent of ctr
5658b51f0f4f33256638ed953156a2635aa739b232f1sewardj      assign( ok, mkU32(0xFFFFFFFF) );
5659b85e8bba97fdae7d892f7bfd12e4601307e4721dcerion   } else {
5660f0de28cf1a762b0d6f74c93d3532c89a230673bbcerion      if ((BO >> 1) & 1) {  // ctr == 0 ?
5661d953ebb9b04cbad6891676df597bf0c542b1ec89cerion         assign( ok, unop( Iop_1Sto32,
56624e2c2b3cacdc79a993f4cec9249d9bffd82e4978cerion                           binop( mkSzOp(ty, Iop_CmpEQ8),
56634e2c2b3cacdc79a993f4cec9249d9bffd82e4978cerion                                  getGST( PPC_GST_CTR ),
56644e2c2b3cacdc79a993f4cec9249d9bffd82e4978cerion                                  mkSzImm(ty,0))) );
5665f0de28cf1a762b0d6f74c93d3532c89a230673bbcerion      } else {              // ctr != 0 ?
5666b51f0f4f33256638ed953156a2635aa739b232f1sewardj         assign( ok, unop( Iop_1Sto32,
56674e2c2b3cacdc79a993f4cec9249d9bffd82e4978cerion                           binop( mkSzOp(ty, Iop_CmpNE8),
56684e2c2b3cacdc79a993f4cec9249d9bffd82e4978cerion                                  getGST( PPC_GST_CTR ),
56694e2c2b3cacdc79a993f4cec9249d9bffd82e4978cerion                                  mkSzImm(ty,0))) );
5670b51f0f4f33256638ed953156a2635aa739b232f1sewardj      }
5671b85e8bba97fdae7d892f7bfd12e4601307e4721dcerion   }
5672b51f0f4f33256638ed953156a2635aa739b232f1sewardj   return mkexpr(ok);
5673b51f0f4f33256638ed953156a2635aa739b232f1sewardj}
5674b51f0f4f33256638ed953156a2635aa739b232f1sewardj
5675b51f0f4f33256638ed953156a2635aa739b232f1sewardj
5676b51f0f4f33256638ed953156a2635aa739b232f1sewardj/*
5677b51f0f4f33256638ed953156a2635aa739b232f1sewardj  Branch helper function cond_ok = BO[4] | (CR[BI] == BO[3])
5678b51f0f4f33256638ed953156a2635aa739b232f1sewardj  Returns an I32 which is either 0 if the condition failed or
5679b51f0f4f33256638ed953156a2635aa739b232f1sewardj  some arbitrary nonzero value otherwise. */
5680b51f0f4f33256638ed953156a2635aa739b232f1sewardj
5681b51f0f4f33256638ed953156a2635aa739b232f1sewardjstatic IRExpr* /* :: Ity_I32 */ branch_cond_ok( UInt BO, UInt BI )
5682b51f0f4f33256638ed953156a2635aa739b232f1sewardj{
5683b51f0f4f33256638ed953156a2635aa739b232f1sewardj   Int where;
5684b51f0f4f33256638ed953156a2635aa739b232f1sewardj   IRTemp res   = newTemp(Ity_I32);
5685b51f0f4f33256638ed953156a2635aa739b232f1sewardj   IRTemp cr_bi = newTemp(Ity_I32);
5686b85e8bba97fdae7d892f7bfd12e4601307e4721dcerion
5687b51f0f4f33256638ed953156a2635aa739b232f1sewardj   if ((BO >> 4) & 1) {
5688b51f0f4f33256638ed953156a2635aa739b232f1sewardj      assign( res, mkU32(1) );
5689b51f0f4f33256638ed953156a2635aa739b232f1sewardj   } else {
5690b51f0f4f33256638ed953156a2635aa739b232f1sewardj      // ok = (CR[BI] == BO[3]) Note, the following relies on
5691b51f0f4f33256638ed953156a2635aa739b232f1sewardj      // getCRbit_anywhere returning a value which
5692b51f0f4f33256638ed953156a2635aa739b232f1sewardj      // is either zero or has exactly 1 bit set.
5693b51f0f4f33256638ed953156a2635aa739b232f1sewardj      assign( cr_bi, getCRbit_anywhere( BI, &where ) );
5694094d1397b3f69b1a538e80ab509ea8cd75f4be3bcerion
5695b51f0f4f33256638ed953156a2635aa739b232f1sewardj      if ((BO >> 3) & 1) {
5696b51f0f4f33256638ed953156a2635aa739b232f1sewardj         /* We can use cr_bi as-is. */
5697b51f0f4f33256638ed953156a2635aa739b232f1sewardj         assign( res, mkexpr(cr_bi) );
5698b51f0f4f33256638ed953156a2635aa739b232f1sewardj      } else {
5699b51f0f4f33256638ed953156a2635aa739b232f1sewardj         /* We have to invert the sense of the information held in
5700b51f0f4f33256638ed953156a2635aa739b232f1sewardj            cr_bi.  For that we need to know which bit
570176de5cf615380b23b4b5bcced6541233cd4a93a0cerion            getCRbit_anywhere regards as significant. */
57025b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion         assign( res, binop(Iop_Xor32, mkexpr(cr_bi),
57035b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion                                       mkU32(1<<where)) );
5704b85e8bba97fdae7d892f7bfd12e4601307e4721dcerion      }
5705b85e8bba97fdae7d892f7bfd12e4601307e4721dcerion   }
5706b51f0f4f33256638ed953156a2635aa739b232f1sewardj   return mkexpr(res);
5707645c930b1a61f4493ee2d472b34fbb439233a874cerion}
5708645c930b1a61f4493ee2d472b34fbb439233a874cerion
5709645c930b1a61f4493ee2d472b34fbb439233a874cerion
57103d870a39e4d145e2f3d9f9a0eeed3475ec934ac1cerion/*
5711b51f0f4f33256638ed953156a2635aa739b232f1sewardj  Integer Branch Instructions
57123d870a39e4d145e2f3d9f9a0eeed3475ec934ac1cerion*/
57139d540e52976d5b6afac33b276e13c5c40f81db90sewardjstatic Bool dis_branch ( UInt theInstr,
5714cacba8e675988fbf21b08feea1f317a9c896c053florian                         const VexAbiInfo* vbi,
57159d540e52976d5b6afac33b276e13c5c40f81db90sewardj                         /*OUT*/DisResult* dres,
5716beac530a718fcc646bc61fe60a86f599df54e1d7florian                         Bool (*resteerOkFn)(void*,Addr),
5717c716aea1cafe66ee431dc7d6909c98f18788a028sewardj                         void* callback_opaque )
5718645c930b1a61f4493ee2d472b34fbb439233a874cerion{
5719d953ebb9b04cbad6891676df597bf0c542b1ec89cerion   UChar opc1    = ifieldOPC(theInstr);
5720d953ebb9b04cbad6891676df597bf0c542b1ec89cerion   UChar BO      = ifieldRegDS(theInstr);
5721d953ebb9b04cbad6891676df597bf0c542b1ec89cerion   UChar BI      = ifieldRegA(theInstr);
5722d953ebb9b04cbad6891676df597bf0c542b1ec89cerion   UInt  BD_u16  = ifieldUIMM16(theInstr) & 0xFFFFFFFC; /* mask off */
5723d953ebb9b04cbad6891676df597bf0c542b1ec89cerion   UChar b11to15 = ifieldRegB(theInstr);
5724d953ebb9b04cbad6891676df597bf0c542b1ec89cerion   UInt  opc2    = ifieldOPClo10(theInstr);
5725d953ebb9b04cbad6891676df597bf0c542b1ec89cerion   UInt  LI_u26  = ifieldUIMM26(theInstr) & 0xFFFFFFFC; /* mask off */
5726d953ebb9b04cbad6891676df597bf0c542b1ec89cerion   UChar flag_AA = ifieldBIT1(theInstr);
5727d953ebb9b04cbad6891676df597bf0c542b1ec89cerion   UChar flag_LK = ifieldBIT0(theInstr);
5728d953ebb9b04cbad6891676df597bf0c542b1ec89cerion
57292831b00c4950d6c2b061def05fd67528fe132ececerion   IRType   ty        = mode64 ? Ity_I64 : Ity_I32;
5730d953ebb9b04cbad6891676df597bf0c542b1ec89cerion   Addr64   tgt       = 0;
5731d953ebb9b04cbad6891676df597bf0c542b1ec89cerion   Int      BD        = extend_s_16to32(BD_u16);
57322831b00c4950d6c2b061def05fd67528fe132ececerion   IRTemp   do_branch = newTemp(Ity_I32);
57332831b00c4950d6c2b061def05fd67528fe132ececerion   IRTemp   ctr_ok    = newTemp(Ity_I32);
57342831b00c4950d6c2b061def05fd67528fe132ececerion   IRTemp   cond_ok   = newTemp(Ity_I32);
57352831b00c4950d6c2b061def05fd67528fe132ececerion   IRExpr*  e_nia     = mkSzImm(ty, nextInsnAddr());
57362831b00c4950d6c2b061def05fd67528fe132ececerion   IRConst* c_nia     = mkSzConst(ty, nextInsnAddr());
5737df07b8888302214ac6c647dca016417a2388f0c3sewardj   IRTemp   lr_old    = newTemp(ty);
5738d953ebb9b04cbad6891676df597bf0c542b1ec89cerion
5739b51f0f4f33256638ed953156a2635aa739b232f1sewardj   /* Hack to pass through code that just wants to read the PC */
5740b51f0f4f33256638ed953156a2635aa739b232f1sewardj   if (theInstr == 0x429F0005) {
5741b51f0f4f33256638ed953156a2635aa739b232f1sewardj      DIP("bcl 0x%x, 0x%x (a.k.a mr lr,cia+4)\n", BO, BI);
5742d953ebb9b04cbad6891676df597bf0c542b1ec89cerion      putGST( PPC_GST_LR, e_nia );
5743b51f0f4f33256638ed953156a2635aa739b232f1sewardj      return True;
5744b51f0f4f33256638ed953156a2635aa739b232f1sewardj   }
57459d540e52976d5b6afac33b276e13c5c40f81db90sewardj
57469d540e52976d5b6afac33b276e13c5c40f81db90sewardj   /* The default what-next.  Individual cases can override it. */
57479d540e52976d5b6afac33b276e13c5c40f81db90sewardj   dres->whatNext = Dis_StopHere;
57483dee849ec7c38746749065e67dc53b75daa7617dsewardj   vassert(dres->jk_StopHere == Ijk_INVALID);
57499d540e52976d5b6afac33b276e13c5c40f81db90sewardj
5750b51f0f4f33256638ed953156a2635aa739b232f1sewardj   switch (opc1) {
5751b51f0f4f33256638ed953156a2635aa739b232f1sewardj   case 0x12: // b     (Branch, PPC32 p360)
5752b51f0f4f33256638ed953156a2635aa739b232f1sewardj      if (flag_AA) {
57532831b00c4950d6c2b061def05fd67528fe132ececerion         tgt = mkSzAddr( ty, extend_s_26to64(LI_u26) );
5754b51f0f4f33256638ed953156a2635aa739b232f1sewardj      } else {
57552831b00c4950d6c2b061def05fd67528fe132ececerion         tgt = mkSzAddr( ty, guest_CIA_curr_instr +
57562831b00c4950d6c2b061def05fd67528fe132ececerion                             (Long)extend_s_26to64(LI_u26) );
57578ea677178e964717135e7c2b039af26875276e84sewardj      }
5758d953ebb9b04cbad6891676df597bf0c542b1ec89cerion      if (mode64) {
5759d953ebb9b04cbad6891676df597bf0c542b1ec89cerion         DIP("b%s%s 0x%llx\n",
5760d953ebb9b04cbad6891676df597bf0c542b1ec89cerion             flag_LK ? "l" : "", flag_AA ? "a" : "", tgt);
5761d953ebb9b04cbad6891676df597bf0c542b1ec89cerion      } else {
5762d953ebb9b04cbad6891676df597bf0c542b1ec89cerion         DIP("b%s%s 0x%x\n",
5763d953ebb9b04cbad6891676df597bf0c542b1ec89cerion             flag_LK ? "l" : "", flag_AA ? "a" : "", (Addr32)tgt);
57649d540e52976d5b6afac33b276e13c5c40f81db90sewardj      }
57659d540e52976d5b6afac33b276e13c5c40f81db90sewardj
5766cf8986c47a4c8c810566bb5b7b3da7a16a17dfe2sewardj      if (flag_LK) {
5767d953ebb9b04cbad6891676df597bf0c542b1ec89cerion         putGST( PPC_GST_LR, e_nia );
5768dd40fdf58cc8a6fe9466c4f00bdfc9fe9bf00449sewardj         if (vbi->guest_ppc_zap_RZ_at_bl
5769478646f54befaba01cbceb40fd5e46cdf562fdb5sewardj             && vbi->guest_ppc_zap_RZ_at_bl( (ULong)tgt) ) {
5770478646f54befaba01cbceb40fd5e46cdf562fdb5sewardj            IRTemp t_tgt = newTemp(ty);
5771478646f54befaba01cbceb40fd5e46cdf562fdb5sewardj            assign(t_tgt, mode64 ? mkU64(tgt) : mkU32(tgt) );
5772478646f54befaba01cbceb40fd5e46cdf562fdb5sewardj            make_redzone_AbiHint( vbi, t_tgt,
5773aca070a5b3418a6a9b01e3c57a7eb0fbb5050908sewardj                                  "branch-and-link (unconditional call)" );
5774478646f54befaba01cbceb40fd5e46cdf562fdb5sewardj         }
5775cf8986c47a4c8c810566bb5b7b3da7a16a17dfe2sewardj      }
5776d953ebb9b04cbad6891676df597bf0c542b1ec89cerion
5777c716aea1cafe66ee431dc7d6909c98f18788a028sewardj      if (resteerOkFn( callback_opaque, tgt )) {
5778984d9b164dd17f07e603c41fe1e506e641e57d18sewardj         dres->whatNext   = Dis_ResteerU;
5779d953ebb9b04cbad6891676df597bf0c542b1ec89cerion         dres->continueAt = tgt;
57809d540e52976d5b6afac33b276e13c5c40f81db90sewardj      } else {
57813dee849ec7c38746749065e67dc53b75daa7617dsewardj         dres->jk_StopHere = flag_LK ? Ijk_Call : Ijk_Boring; ;
57823dee849ec7c38746749065e67dc53b75daa7617dsewardj         putGST( PPC_GST_CIA, mkSzImm(ty, tgt) );
57839d540e52976d5b6afac33b276e13c5c40f81db90sewardj      }
5784b51f0f4f33256638ed953156a2635aa739b232f1sewardj      break;
5785b85e8bba97fdae7d892f7bfd12e4601307e4721dcerion
5786e9d361ab43518b6dfbd3d846f48859534659dee0cerion   case 0x10: // bc    (Branch Conditional, PPC32 p361)
5787b85e8bba97fdae7d892f7bfd12e4601307e4721dcerion      DIP("bc%s%s 0x%x, 0x%x, 0x%x\n",
5788d953ebb9b04cbad6891676df597bf0c542b1ec89cerion          flag_LK ? "l" : "", flag_AA ? "a" : "", BO, BI, BD);
5789b85e8bba97fdae7d892f7bfd12e4601307e4721dcerion
5790b85e8bba97fdae7d892f7bfd12e4601307e4721dcerion      if (!(BO & 0x4)) {
5791d953ebb9b04cbad6891676df597bf0c542b1ec89cerion         putGST( PPC_GST_CTR,
57922831b00c4950d6c2b061def05fd67528fe132ececerion                 binop(mkSzOp(ty, Iop_Sub8),
57932831b00c4950d6c2b061def05fd67528fe132ececerion                       getGST( PPC_GST_CTR ), mkSzImm(ty, 1)) );
5794b85e8bba97fdae7d892f7bfd12e4601307e4721dcerion      }
5795b51f0f4f33256638ed953156a2635aa739b232f1sewardj
5796b51f0f4f33256638ed953156a2635aa739b232f1sewardj      /* This is a bit subtle.  ctr_ok is either all 0s or all 1s.
579776de5cf615380b23b4b5bcced6541233cd4a93a0cerion         cond_ok is either zero or nonzero, since that's the cheapest
579876de5cf615380b23b4b5bcced6541233cd4a93a0cerion         way to compute it.  Anding them together gives a value which
579976de5cf615380b23b4b5bcced6541233cd4a93a0cerion         is either zero or non zero and so that's what we must test
580076de5cf615380b23b4b5bcced6541233cd4a93a0cerion         for in the IRStmt_Exit. */
5801b51f0f4f33256638ed953156a2635aa739b232f1sewardj      assign( ctr_ok,  branch_ctr_ok( BO ) );
5802b85e8bba97fdae7d892f7bfd12e4601307e4721dcerion      assign( cond_ok, branch_cond_ok( BO, BI ) );
5803b51f0f4f33256638ed953156a2635aa739b232f1sewardj      assign( do_branch,
5804b51f0f4f33256638ed953156a2635aa739b232f1sewardj              binop(Iop_And32, mkexpr(cond_ok), mkexpr(ctr_ok)) );
5805b51f0f4f33256638ed953156a2635aa739b232f1sewardj
58064561acb2fed3ea11b7b1f95a373da8ec62e6d483cerion      if (flag_AA) {
58072831b00c4950d6c2b061def05fd67528fe132ececerion         tgt = mkSzAddr(ty, extend_s_16to64(BD_u16));
58084561acb2fed3ea11b7b1f95a373da8ec62e6d483cerion      } else {
58092831b00c4950d6c2b061def05fd67528fe132ececerion         tgt = mkSzAddr(ty, guest_CIA_curr_instr +
58102831b00c4950d6c2b061def05fd67528fe132ececerion                            (Long)extend_s_16to64(BD_u16));
5811b85e8bba97fdae7d892f7bfd12e4601307e4721dcerion      }
5812d953ebb9b04cbad6891676df597bf0c542b1ec89cerion      if (flag_LK)
5813d953ebb9b04cbad6891676df597bf0c542b1ec89cerion         putGST( PPC_GST_LR, e_nia );
5814b85e8bba97fdae7d892f7bfd12e4601307e4721dcerion
5815d953ebb9b04cbad6891676df597bf0c542b1ec89cerion      stmt( IRStmt_Exit(
5816d953ebb9b04cbad6891676df597bf0c542b1ec89cerion               binop(Iop_CmpNE32, mkexpr(do_branch), mkU32(0)),
5817d953ebb9b04cbad6891676df597bf0c542b1ec89cerion               flag_LK ? Ijk_Call : Ijk_Boring,
58183dee849ec7c38746749065e67dc53b75daa7617dsewardj               mkSzConst(ty, tgt), OFFB_CIA ) );
58193dee849ec7c38746749065e67dc53b75daa7617dsewardj
58203dee849ec7c38746749065e67dc53b75daa7617dsewardj      dres->jk_StopHere = Ijk_Boring;
58213dee849ec7c38746749065e67dc53b75daa7617dsewardj      putGST( PPC_GST_CIA, e_nia );
5822b85e8bba97fdae7d892f7bfd12e4601307e4721dcerion      break;
5823b85e8bba97fdae7d892f7bfd12e4601307e4721dcerion
5824b85e8bba97fdae7d892f7bfd12e4601307e4721dcerion   case 0x13:
58256be67235ba2829b0bc34c3a0876cee4eac340d95sewardj      /* For bclr and bcctr, it appears that the lowest two bits of
58266be67235ba2829b0bc34c3a0876cee4eac340d95sewardj         b11to15 are a branch hint, and so we only need to ensure it's
58276be67235ba2829b0bc34c3a0876cee4eac340d95sewardj         of the form 000XX. */
58286be67235ba2829b0bc34c3a0876cee4eac340d95sewardj      if ((b11to15 & ~3) != 0) {
58296be67235ba2829b0bc34c3a0876cee4eac340d95sewardj         vex_printf("dis_int_branch(ppc)(0x13,b11to15)(%d)\n", (Int)b11to15);
5830b85e8bba97fdae7d892f7bfd12e4601307e4721dcerion         return False;
5831b85e8bba97fdae7d892f7bfd12e4601307e4721dcerion      }
5832b85e8bba97fdae7d892f7bfd12e4601307e4721dcerion
5833b85e8bba97fdae7d892f7bfd12e4601307e4721dcerion      switch (opc2) {
5834e9d361ab43518b6dfbd3d846f48859534659dee0cerion      case 0x210: // bcctr (Branch Cond. to Count Register, PPC32 p363)
58355b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion         if ((BO & 0x4) == 0) { // "decr and test CTR" option invalid
58365b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion            vex_printf("dis_int_branch(ppc)(bcctr,BO)\n");
5837b85e8bba97fdae7d892f7bfd12e4601307e4721dcerion            return False;
5838b85e8bba97fdae7d892f7bfd12e4601307e4721dcerion         }
5839a31e8b578565058187814bcb2d1bb77c09da6adccerion         DIP("bcctr%s 0x%x, 0x%x\n", flag_LK ? "l" : "", BO, BI);
5840b85e8bba97fdae7d892f7bfd12e4601307e4721dcerion
5841b85e8bba97fdae7d892f7bfd12e4601307e4721dcerion         assign( cond_ok, branch_cond_ok( BO, BI ) );
5842d953ebb9b04cbad6891676df597bf0c542b1ec89cerion
5843478646f54befaba01cbceb40fd5e46cdf562fdb5sewardj         /* FIXME: this is confusing.  lr_old holds the old value
5844478646f54befaba01cbceb40fd5e46cdf562fdb5sewardj            of ctr, not lr :-) */
58452831b00c4950d6c2b061def05fd67528fe132ececerion         assign( lr_old, addr_align( getGST( PPC_GST_CTR ), 4 ));
5846df07b8888302214ac6c647dca016417a2388f0c3sewardj
5847d953ebb9b04cbad6891676df597bf0c542b1ec89cerion         if (flag_LK)
5848d953ebb9b04cbad6891676df597bf0c542b1ec89cerion            putGST( PPC_GST_LR, e_nia );
5849b85e8bba97fdae7d892f7bfd12e4601307e4721dcerion
5850b51f0f4f33256638ed953156a2635aa739b232f1sewardj         stmt( IRStmt_Exit(
5851b51f0f4f33256638ed953156a2635aa739b232f1sewardj                  binop(Iop_CmpEQ32, mkexpr(cond_ok), mkU32(0)),
5852b51f0f4f33256638ed953156a2635aa739b232f1sewardj                  Ijk_Boring,
58533dee849ec7c38746749065e67dc53b75daa7617dsewardj                  c_nia, OFFB_CIA ));
5854478646f54befaba01cbceb40fd5e46cdf562fdb5sewardj
5855478646f54befaba01cbceb40fd5e46cdf562fdb5sewardj         if (flag_LK && vbi->guest_ppc_zap_RZ_at_bl) {
5856478646f54befaba01cbceb40fd5e46cdf562fdb5sewardj            make_redzone_AbiHint( vbi, lr_old,
5857478646f54befaba01cbceb40fd5e46cdf562fdb5sewardj                                  "b-ctr-l (indirect call)" );
5858478646f54befaba01cbceb40fd5e46cdf562fdb5sewardj	 }
5859478646f54befaba01cbceb40fd5e46cdf562fdb5sewardj
58603dee849ec7c38746749065e67dc53b75daa7617dsewardj         dres->jk_StopHere = flag_LK ? Ijk_Call : Ijk_Boring;;
58613dee849ec7c38746749065e67dc53b75daa7617dsewardj         putGST( PPC_GST_CIA, mkexpr(lr_old) );
5862b85e8bba97fdae7d892f7bfd12e4601307e4721dcerion         break;
5863b85e8bba97fdae7d892f7bfd12e4601307e4721dcerion
5864cf8986c47a4c8c810566bb5b7b3da7a16a17dfe2sewardj      case 0x010: { // bclr (Branch Cond. to Link Register, PPC32 p365)
5865cf8986c47a4c8c810566bb5b7b3da7a16a17dfe2sewardj         Bool vanilla_return = False;
5866b51f0f4f33256638ed953156a2635aa739b232f1sewardj         if ((BO & 0x14 /* 1z1zz */) == 0x14 && flag_LK == 0) {
5867225a034683024109da729a4d2f080364b9485007cerion            DIP("blr\n");
5868cf8986c47a4c8c810566bb5b7b3da7a16a17dfe2sewardj            vanilla_return = True;
5869b51f0f4f33256638ed953156a2635aa739b232f1sewardj         } else {
5870b51f0f4f33256638ed953156a2635aa739b232f1sewardj            DIP("bclr%s 0x%x, 0x%x\n", flag_LK ? "l" : "", BO, BI);
5871b51f0f4f33256638ed953156a2635aa739b232f1sewardj         }
5872b85e8bba97fdae7d892f7bfd12e4601307e4721dcerion
5873b85e8bba97fdae7d892f7bfd12e4601307e4721dcerion         if (!(BO & 0x4)) {
5874d953ebb9b04cbad6891676df597bf0c542b1ec89cerion            putGST( PPC_GST_CTR,
58752831b00c4950d6c2b061def05fd67528fe132ececerion                    binop(mkSzOp(ty, Iop_Sub8),
58762831b00c4950d6c2b061def05fd67528fe132ececerion                          getGST( PPC_GST_CTR ), mkSzImm(ty, 1)) );
5877b85e8bba97fdae7d892f7bfd12e4601307e4721dcerion         }
5878b85e8bba97fdae7d892f7bfd12e4601307e4721dcerion
5879b51f0f4f33256638ed953156a2635aa739b232f1sewardj         /* See comments above for 'bc' about this */
5880b51f0f4f33256638ed953156a2635aa739b232f1sewardj         assign( ctr_ok,  branch_ctr_ok( BO ) );
5881b51f0f4f33256638ed953156a2635aa739b232f1sewardj         assign( cond_ok, branch_cond_ok( BO, BI ) );
5882b51f0f4f33256638ed953156a2635aa739b232f1sewardj         assign( do_branch,
5883b51f0f4f33256638ed953156a2635aa739b232f1sewardj                 binop(Iop_And32, mkexpr(cond_ok), mkexpr(ctr_ok)) );
58842831b00c4950d6c2b061def05fd67528fe132ececerion
5885df07b8888302214ac6c647dca016417a2388f0c3sewardj         assign( lr_old, addr_align( getGST( PPC_GST_LR ), 4 ));
5886df07b8888302214ac6c647dca016417a2388f0c3sewardj
5887d953ebb9b04cbad6891676df597bf0c542b1ec89cerion         if (flag_LK)
5888d953ebb9b04cbad6891676df597bf0c542b1ec89cerion            putGST( PPC_GST_LR,  e_nia );
5889b51f0f4f33256638ed953156a2635aa739b232f1sewardj
5890b51f0f4f33256638ed953156a2635aa739b232f1sewardj         stmt( IRStmt_Exit(
5891b51f0f4f33256638ed953156a2635aa739b232f1sewardj                  binop(Iop_CmpEQ32, mkexpr(do_branch), mkU32(0)),
5892b51f0f4f33256638ed953156a2635aa739b232f1sewardj                  Ijk_Boring,
58933dee849ec7c38746749065e67dc53b75daa7617dsewardj                  c_nia, OFFB_CIA ));
5894b51f0f4f33256638ed953156a2635aa739b232f1sewardj
5895478646f54befaba01cbceb40fd5e46cdf562fdb5sewardj         if (vanilla_return && vbi->guest_ppc_zap_RZ_at_blr) {
5896478646f54befaba01cbceb40fd5e46cdf562fdb5sewardj            make_redzone_AbiHint( vbi, lr_old,
5897478646f54befaba01cbceb40fd5e46cdf562fdb5sewardj                                  "branch-to-lr (unconditional return)" );
5898478646f54befaba01cbceb40fd5e46cdf562fdb5sewardj         }
5899cf8986c47a4c8c810566bb5b7b3da7a16a17dfe2sewardj
5900d37be0323036e01ffafa3286d893aa953f109191sewardj         /* blrl is pretty strange; it's like a return that sets the
5901d37be0323036e01ffafa3286d893aa953f109191sewardj            return address of its caller to the insn following this
5902d37be0323036e01ffafa3286d893aa953f109191sewardj            one.  Mark it as a return. */
59033dee849ec7c38746749065e67dc53b75daa7617dsewardj         dres->jk_StopHere = Ijk_Ret;  /* was flag_LK ? Ijk_Call : Ijk_Ret; */
59043dee849ec7c38746749065e67dc53b75daa7617dsewardj         putGST( PPC_GST_CIA, mkexpr(lr_old) );
5905b85e8bba97fdae7d892f7bfd12e4601307e4721dcerion         break;
5906cf8986c47a4c8c810566bb5b7b3da7a16a17dfe2sewardj      }
5907b85e8bba97fdae7d892f7bfd12e4601307e4721dcerion      default:
59085b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion         vex_printf("dis_int_branch(ppc)(opc2)\n");
5909b85e8bba97fdae7d892f7bfd12e4601307e4721dcerion         return False;
5910b85e8bba97fdae7d892f7bfd12e4601307e4721dcerion      }
5911b85e8bba97fdae7d892f7bfd12e4601307e4721dcerion      break;
59122831b00c4950d6c2b061def05fd67528fe132ececerion
5913b85e8bba97fdae7d892f7bfd12e4601307e4721dcerion   default:
59145b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion      vex_printf("dis_int_branch(ppc)(opc1)\n");
5915b85e8bba97fdae7d892f7bfd12e4601307e4721dcerion      return False;
5916b85e8bba97fdae7d892f7bfd12e4601307e4721dcerion   }
59172831b00c4950d6c2b061def05fd67528fe132ececerion
5918b85e8bba97fdae7d892f7bfd12e4601307e4721dcerion   return True;
591991ad5368eb6354ad4fabc86f2b2e641736997a38cerion}
5920896a1373cfdbaa25f4ab73ed4f27554016defecccerion
5921896a1373cfdbaa25f4ab73ed4f27554016defecccerion
5922896a1373cfdbaa25f4ab73ed4f27554016defecccerion
59233d870a39e4d145e2f3d9f9a0eeed3475ec934ac1cerion/*
59243d870a39e4d145e2f3d9f9a0eeed3475ec934ac1cerion  Condition Register Logical Instructions
59253d870a39e4d145e2f3d9f9a0eeed3475ec934ac1cerion*/
59263007c7fb4f226f2db7e250b0ebb114618ab1980ccerionstatic Bool dis_cond_logic ( UInt theInstr )
59273007c7fb4f226f2db7e250b0ebb114618ab1980ccerion{
59283007c7fb4f226f2db7e250b0ebb114618ab1980ccerion   /* XL-Form */
592976de5cf615380b23b4b5bcced6541233cd4a93a0cerion   UChar opc1      = ifieldOPC(theInstr);
593076de5cf615380b23b4b5bcced6541233cd4a93a0cerion   UChar crbD_addr = ifieldRegDS(theInstr);
593176de5cf615380b23b4b5bcced6541233cd4a93a0cerion   UChar crfD_addr = toUChar( IFIELD(theInstr, 23, 3) );
593276de5cf615380b23b4b5bcced6541233cd4a93a0cerion   UChar crbA_addr = ifieldRegA(theInstr);
593376de5cf615380b23b4b5bcced6541233cd4a93a0cerion   UChar crfS_addr = toUChar( IFIELD(theInstr, 18, 3) );
593476de5cf615380b23b4b5bcced6541233cd4a93a0cerion   UChar crbB_addr = ifieldRegB(theInstr);
593576de5cf615380b23b4b5bcced6541233cd4a93a0cerion   UInt  opc2      = ifieldOPClo10(theInstr);
593676de5cf615380b23b4b5bcced6541233cd4a93a0cerion   UChar b0        = ifieldBIT0(theInstr);
59373007c7fb4f226f2db7e250b0ebb114618ab1980ccerion
5938f0de28cf1a762b0d6f74c93d3532c89a230673bbcerion   IRTemp crbD     = newTemp(Ity_I32);
5939f0de28cf1a762b0d6f74c93d3532c89a230673bbcerion   IRTemp crbA     = newTemp(Ity_I32);
5940f0de28cf1a762b0d6f74c93d3532c89a230673bbcerion   IRTemp crbB     = newTemp(Ity_I32);
59413007c7fb4f226f2db7e250b0ebb114618ab1980ccerion
59423007c7fb4f226f2db7e250b0ebb114618ab1980ccerion   if (opc1 != 19 || b0 != 0) {
59435b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion      vex_printf("dis_cond_logic(ppc)(opc1)\n");
59443007c7fb4f226f2db7e250b0ebb114618ab1980ccerion      return False;
59453007c7fb4f226f2db7e250b0ebb114618ab1980ccerion   }
59463007c7fb4f226f2db7e250b0ebb114618ab1980ccerion
5947e9d361ab43518b6dfbd3d846f48859534659dee0cerion   if (opc2 == 0) {  // mcrf    (Move Cond Reg Field, PPC32 p464)
59483007c7fb4f226f2db7e250b0ebb114618ab1980ccerion      if (((crbD_addr & 0x3) != 0) ||
594976de5cf615380b23b4b5bcced6541233cd4a93a0cerion          ((crbA_addr & 0x3) != 0) || (crbB_addr != 0)) {
59505b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion         vex_printf("dis_cond_logic(ppc)(crbD|crbA|crbB != 0)\n");
59513007c7fb4f226f2db7e250b0ebb114618ab1980ccerion         return False;
595276de5cf615380b23b4b5bcced6541233cd4a93a0cerion      }
5953d953ebb9b04cbad6891676df597bf0c542b1ec89cerion      DIP("mcrf cr%u,cr%u\n", crfD_addr, crfS_addr);
5954b51f0f4f33256638ed953156a2635aa739b232f1sewardj      putCR0(   crfD_addr, getCR0(  crfS_addr) );
5955b51f0f4f33256638ed953156a2635aa739b232f1sewardj      putCR321( crfD_addr, getCR321(crfS_addr) );
59563007c7fb4f226f2db7e250b0ebb114618ab1980ccerion   } else {
5957b51f0f4f33256638ed953156a2635aa739b232f1sewardj      assign( crbA, getCRbit(crbA_addr) );
5958a50fde5504e829e5154113d7e507f12707089f48cerion      if (crbA_addr == crbB_addr)
5959b51f0f4f33256638ed953156a2635aa739b232f1sewardj         crbB = crbA;
5960a50fde5504e829e5154113d7e507f12707089f48cerion      else
5961b51f0f4f33256638ed953156a2635aa739b232f1sewardj         assign( crbB, getCRbit(crbB_addr) );
59623007c7fb4f226f2db7e250b0ebb114618ab1980ccerion
59633007c7fb4f226f2db7e250b0ebb114618ab1980ccerion      switch (opc2) {
59647c2dc7122cd7767e59112254183cf9babd4a1cb3sewardj      case 0x101: // crand   (Cond Reg AND, PPC32 p372)
59657c2dc7122cd7767e59112254183cf9babd4a1cb3sewardj         DIP("crand crb%d,crb%d,crb%d\n", crbD_addr, crbA_addr, crbB_addr);
59667c2dc7122cd7767e59112254183cf9babd4a1cb3sewardj         assign( crbD, binop(Iop_And32, mkexpr(crbA), mkexpr(crbB)) );
59677c2dc7122cd7767e59112254183cf9babd4a1cb3sewardj         break;
59687787af415a9104b601c2f0ce5b56749e4fd86691sewardj      case 0x081: // crandc  (Cond Reg AND w. Complement, PPC32 p373)
59697787af415a9104b601c2f0ce5b56749e4fd86691sewardj         DIP("crandc crb%d,crb%d,crb%d\n", crbD_addr, crbA_addr, crbB_addr);
59707787af415a9104b601c2f0ce5b56749e4fd86691sewardj         assign( crbD, binop(Iop_And32,
59717787af415a9104b601c2f0ce5b56749e4fd86691sewardj                             mkexpr(crbA),
59727787af415a9104b601c2f0ce5b56749e4fd86691sewardj                             unop(Iop_Not32, mkexpr(crbB))) );
59737787af415a9104b601c2f0ce5b56749e4fd86691sewardj         break;
5974e14bb9f862843c6b804097c124961b5567ded4f1sewardj      case 0x121: // creqv   (Cond Reg Equivalent, PPC32 p374)
5975e14bb9f862843c6b804097c124961b5567ded4f1sewardj         DIP("creqv crb%d,crb%d,crb%d\n", crbD_addr, crbA_addr, crbB_addr);
5976e14bb9f862843c6b804097c124961b5567ded4f1sewardj         assign( crbD, unop(Iop_Not32,
5977e14bb9f862843c6b804097c124961b5567ded4f1sewardj                            binop(Iop_Xor32, mkexpr(crbA), mkexpr(crbB))) );
5978e14bb9f862843c6b804097c124961b5567ded4f1sewardj         break;
59797c2dc7122cd7767e59112254183cf9babd4a1cb3sewardj      case 0x0E1: // crnand  (Cond Reg NAND, PPC32 p375)
59807c2dc7122cd7767e59112254183cf9babd4a1cb3sewardj         DIP("crnand crb%d,crb%d,crb%d\n", crbD_addr, crbA_addr, crbB_addr);
59817c2dc7122cd7767e59112254183cf9babd4a1cb3sewardj         assign( crbD, unop(Iop_Not32,
59827c2dc7122cd7767e59112254183cf9babd4a1cb3sewardj                            binop(Iop_And32, mkexpr(crbA), mkexpr(crbB))) );
59837c2dc7122cd7767e59112254183cf9babd4a1cb3sewardj         break;
5984e9d361ab43518b6dfbd3d846f48859534659dee0cerion      case 0x021: // crnor   (Cond Reg NOR, PPC32 p376)
59853007c7fb4f226f2db7e250b0ebb114618ab1980ccerion         DIP("crnor crb%d,crb%d,crb%d\n", crbD_addr, crbA_addr, crbB_addr);
59863007c7fb4f226f2db7e250b0ebb114618ab1980ccerion         assign( crbD, unop(Iop_Not32,
59873007c7fb4f226f2db7e250b0ebb114618ab1980ccerion                            binop(Iop_Or32, mkexpr(crbA), mkexpr(crbB))) );
59883007c7fb4f226f2db7e250b0ebb114618ab1980ccerion         break;
5989e9d361ab43518b6dfbd3d846f48859534659dee0cerion      case 0x1C1: // cror    (Cond Reg OR, PPC32 p377)
59903007c7fb4f226f2db7e250b0ebb114618ab1980ccerion         DIP("cror crb%d,crb%d,crb%d\n", crbD_addr, crbA_addr, crbB_addr);
59913007c7fb4f226f2db7e250b0ebb114618ab1980ccerion         assign( crbD, binop(Iop_Or32, mkexpr(crbA), mkexpr(crbB)) );
59923007c7fb4f226f2db7e250b0ebb114618ab1980ccerion         break;
59937c2dc7122cd7767e59112254183cf9babd4a1cb3sewardj      case 0x1A1: // crorc   (Cond Reg OR w. Complement, PPC32 p378)
59947c2dc7122cd7767e59112254183cf9babd4a1cb3sewardj         DIP("crorc crb%d,crb%d,crb%d\n", crbD_addr, crbA_addr, crbB_addr);
59957c2dc7122cd7767e59112254183cf9babd4a1cb3sewardj         assign( crbD, binop(Iop_Or32,
59967c2dc7122cd7767e59112254183cf9babd4a1cb3sewardj                             mkexpr(crbA),
59977c2dc7122cd7767e59112254183cf9babd4a1cb3sewardj                             unop(Iop_Not32, mkexpr(crbB))) );
59987c2dc7122cd7767e59112254183cf9babd4a1cb3sewardj         break;
5999e9d361ab43518b6dfbd3d846f48859534659dee0cerion      case 0x0C1: // crxor   (Cond Reg XOR, PPC32 p379)
60003007c7fb4f226f2db7e250b0ebb114618ab1980ccerion         DIP("crxor crb%d,crb%d,crb%d\n", crbD_addr, crbA_addr, crbB_addr);
60013007c7fb4f226f2db7e250b0ebb114618ab1980ccerion         assign( crbD, binop(Iop_Xor32, mkexpr(crbA), mkexpr(crbB)) );
60023007c7fb4f226f2db7e250b0ebb114618ab1980ccerion         break;
60033007c7fb4f226f2db7e250b0ebb114618ab1980ccerion      default:
60045b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion         vex_printf("dis_cond_logic(ppc)(opc2)\n");
60053007c7fb4f226f2db7e250b0ebb114618ab1980ccerion         return False;
60063007c7fb4f226f2db7e250b0ebb114618ab1980ccerion      }
60073007c7fb4f226f2db7e250b0ebb114618ab1980ccerion
6008b51f0f4f33256638ed953156a2635aa739b232f1sewardj      putCRbit( crbD_addr, mkexpr(crbD) );
60093007c7fb4f226f2db7e250b0ebb114618ab1980ccerion   }
60103007c7fb4f226f2db7e250b0ebb114618ab1980ccerion   return True;
60113007c7fb4f226f2db7e250b0ebb114618ab1980ccerion}
60123007c7fb4f226f2db7e250b0ebb114618ab1980ccerion
60133007c7fb4f226f2db7e250b0ebb114618ab1980ccerion
6014334870db22c2eadcaaa48ef8e47337134d150efdsewardj/*
6015334870db22c2eadcaaa48ef8e47337134d150efdsewardj  Trap instructions
6016334870db22c2eadcaaa48ef8e47337134d150efdsewardj*/
6017334870db22c2eadcaaa48ef8e47337134d150efdsewardj
6018334870db22c2eadcaaa48ef8e47337134d150efdsewardj/* Do the code generation for a trap.  Returned Bool is true iff
601959c0d8f0997bd03e0f8d90b9144dc0aeb6fe9a3asewardj   this is an unconditional trap.  If the two arg IRExpr*s are
602059c0d8f0997bd03e0f8d90b9144dc0aeb6fe9a3asewardj   Ity_I32s then the comparison is 32-bit.  If they are Ity_I64s
602159c0d8f0997bd03e0f8d90b9144dc0aeb6fe9a3asewardj   then they are 64-bit, and we must be disassembling 64-bit
602259c0d8f0997bd03e0f8d90b9144dc0aeb6fe9a3asewardj   instructions. */
602359c0d8f0997bd03e0f8d90b9144dc0aeb6fe9a3asewardjstatic Bool do_trap ( UChar TO,
602459c0d8f0997bd03e0f8d90b9144dc0aeb6fe9a3asewardj                      IRExpr* argL0, IRExpr* argR0, Addr64 cia )
6025334870db22c2eadcaaa48ef8e47337134d150efdsewardj{
6026334870db22c2eadcaaa48ef8e47337134d150efdsewardj   IRTemp argL, argR;
6027334870db22c2eadcaaa48ef8e47337134d150efdsewardj   IRExpr *argLe, *argRe, *cond, *tmp;
6028334870db22c2eadcaaa48ef8e47337134d150efdsewardj
602959c0d8f0997bd03e0f8d90b9144dc0aeb6fe9a3asewardj   Bool    is32bit = typeOfIRExpr(irsb->tyenv, argL0 ) == Ity_I32;
603059c0d8f0997bd03e0f8d90b9144dc0aeb6fe9a3asewardj
603159c0d8f0997bd03e0f8d90b9144dc0aeb6fe9a3asewardj   IROp    opAND     = is32bit ? Iop_And32     : Iop_And64;
603259c0d8f0997bd03e0f8d90b9144dc0aeb6fe9a3asewardj   IROp    opOR      = is32bit ? Iop_Or32      : Iop_Or64;
603359c0d8f0997bd03e0f8d90b9144dc0aeb6fe9a3asewardj   IROp    opCMPORDS = is32bit ? Iop_CmpORD32S : Iop_CmpORD64S;
603459c0d8f0997bd03e0f8d90b9144dc0aeb6fe9a3asewardj   IROp    opCMPORDU = is32bit ? Iop_CmpORD32U : Iop_CmpORD64U;
603559c0d8f0997bd03e0f8d90b9144dc0aeb6fe9a3asewardj   IROp    opCMPNE   = is32bit ? Iop_CmpNE32   : Iop_CmpNE64;
603659c0d8f0997bd03e0f8d90b9144dc0aeb6fe9a3asewardj   IROp    opCMPEQ   = is32bit ? Iop_CmpEQ32   : Iop_CmpEQ64;
603759c0d8f0997bd03e0f8d90b9144dc0aeb6fe9a3asewardj   IRExpr* const0    = is32bit ? mkU32(0)      : mkU64(0);
603859c0d8f0997bd03e0f8d90b9144dc0aeb6fe9a3asewardj   IRExpr* const2    = is32bit ? mkU32(2)      : mkU64(2);
603959c0d8f0997bd03e0f8d90b9144dc0aeb6fe9a3asewardj   IRExpr* const4    = is32bit ? mkU32(4)      : mkU64(4);
604059c0d8f0997bd03e0f8d90b9144dc0aeb6fe9a3asewardj   IRExpr* const8    = is32bit ? mkU32(8)      : mkU64(8);
6041334870db22c2eadcaaa48ef8e47337134d150efdsewardj
6042334870db22c2eadcaaa48ef8e47337134d150efdsewardj   const UChar b11100 = 0x1C;
6043334870db22c2eadcaaa48ef8e47337134d150efdsewardj   const UChar b00111 = 0x07;
6044334870db22c2eadcaaa48ef8e47337134d150efdsewardj
604559c0d8f0997bd03e0f8d90b9144dc0aeb6fe9a3asewardj   if (is32bit) {
604659c0d8f0997bd03e0f8d90b9144dc0aeb6fe9a3asewardj      vassert( typeOfIRExpr(irsb->tyenv, argL0) == Ity_I32 );
604759c0d8f0997bd03e0f8d90b9144dc0aeb6fe9a3asewardj      vassert( typeOfIRExpr(irsb->tyenv, argR0) == Ity_I32 );
604859c0d8f0997bd03e0f8d90b9144dc0aeb6fe9a3asewardj   } else {
604959c0d8f0997bd03e0f8d90b9144dc0aeb6fe9a3asewardj      vassert( typeOfIRExpr(irsb->tyenv, argL0) == Ity_I64 );
605059c0d8f0997bd03e0f8d90b9144dc0aeb6fe9a3asewardj      vassert( typeOfIRExpr(irsb->tyenv, argR0) == Ity_I64 );
605159c0d8f0997bd03e0f8d90b9144dc0aeb6fe9a3asewardj      vassert( mode64 );
605259c0d8f0997bd03e0f8d90b9144dc0aeb6fe9a3asewardj   }
605359c0d8f0997bd03e0f8d90b9144dc0aeb6fe9a3asewardj
6054334870db22c2eadcaaa48ef8e47337134d150efdsewardj   if ((TO & b11100) == b11100 || (TO & b00111) == b00111) {
6055334870db22c2eadcaaa48ef8e47337134d150efdsewardj      /* Unconditional trap.  Just do the exit without
6056334870db22c2eadcaaa48ef8e47337134d150efdsewardj         testing the arguments. */
6057334870db22c2eadcaaa48ef8e47337134d150efdsewardj      stmt( IRStmt_Exit(
6058334870db22c2eadcaaa48ef8e47337134d150efdsewardj               binop(opCMPEQ, const0, const0),
60590f50004eefdf1066682a016efb4a57c092ae2da2sewardj               Ijk_SigTRAP,
60603dee849ec7c38746749065e67dc53b75daa7617dsewardj               mode64 ? IRConst_U64(cia) : IRConst_U32((UInt)cia),
60613dee849ec7c38746749065e67dc53b75daa7617dsewardj               OFFB_CIA
6062334870db22c2eadcaaa48ef8e47337134d150efdsewardj      ));
6063334870db22c2eadcaaa48ef8e47337134d150efdsewardj      return True; /* unconditional trap */
6064334870db22c2eadcaaa48ef8e47337134d150efdsewardj   }
6065334870db22c2eadcaaa48ef8e47337134d150efdsewardj
606659c0d8f0997bd03e0f8d90b9144dc0aeb6fe9a3asewardj   if (is32bit) {
60672d19fe35849aa0acb74ee30836b9566999fb53e0sewardj      argL = newTemp(Ity_I32);
60682d19fe35849aa0acb74ee30836b9566999fb53e0sewardj      argR = newTemp(Ity_I32);
6069334870db22c2eadcaaa48ef8e47337134d150efdsewardj   } else {
60702d19fe35849aa0acb74ee30836b9566999fb53e0sewardj      argL = newTemp(Ity_I64);
60712d19fe35849aa0acb74ee30836b9566999fb53e0sewardj      argR = newTemp(Ity_I64);
6072334870db22c2eadcaaa48ef8e47337134d150efdsewardj   }
607359c0d8f0997bd03e0f8d90b9144dc0aeb6fe9a3asewardj
607459c0d8f0997bd03e0f8d90b9144dc0aeb6fe9a3asewardj   assign( argL, argL0 );
607559c0d8f0997bd03e0f8d90b9144dc0aeb6fe9a3asewardj   assign( argR, argR0 );
607659c0d8f0997bd03e0f8d90b9144dc0aeb6fe9a3asewardj
6077334870db22c2eadcaaa48ef8e47337134d150efdsewardj   argLe = mkexpr(argL);
6078334870db22c2eadcaaa48ef8e47337134d150efdsewardj   argRe = mkexpr(argR);
607959c0d8f0997bd03e0f8d90b9144dc0aeb6fe9a3asewardj
6080334870db22c2eadcaaa48ef8e47337134d150efdsewardj   cond = const0;
6081334870db22c2eadcaaa48ef8e47337134d150efdsewardj   if (TO & 16) { // L <s R
6082334870db22c2eadcaaa48ef8e47337134d150efdsewardj      tmp = binop(opAND, binop(opCMPORDS, argLe, argRe), const8);
6083334870db22c2eadcaaa48ef8e47337134d150efdsewardj      cond = binop(opOR, tmp, cond);
6084334870db22c2eadcaaa48ef8e47337134d150efdsewardj   }
6085334870db22c2eadcaaa48ef8e47337134d150efdsewardj   if (TO & 8) { // L >s R
6086334870db22c2eadcaaa48ef8e47337134d150efdsewardj      tmp = binop(opAND, binop(opCMPORDS, argLe, argRe), const4);
6087334870db22c2eadcaaa48ef8e47337134d150efdsewardj      cond = binop(opOR, tmp, cond);
6088334870db22c2eadcaaa48ef8e47337134d150efdsewardj   }
6089334870db22c2eadcaaa48ef8e47337134d150efdsewardj   if (TO & 4) { // L == R
6090334870db22c2eadcaaa48ef8e47337134d150efdsewardj      tmp = binop(opAND, binop(opCMPORDS, argLe, argRe), const2);
6091334870db22c2eadcaaa48ef8e47337134d150efdsewardj      cond = binop(opOR, tmp, cond);
6092334870db22c2eadcaaa48ef8e47337134d150efdsewardj   }
6093334870db22c2eadcaaa48ef8e47337134d150efdsewardj   if (TO & 2) { // L <u R
6094334870db22c2eadcaaa48ef8e47337134d150efdsewardj      tmp = binop(opAND, binop(opCMPORDU, argLe, argRe), const8);
6095334870db22c2eadcaaa48ef8e47337134d150efdsewardj      cond = binop(opOR, tmp, cond);
6096334870db22c2eadcaaa48ef8e47337134d150efdsewardj   }
6097334870db22c2eadcaaa48ef8e47337134d150efdsewardj   if (TO & 1) { // L >u R
6098334870db22c2eadcaaa48ef8e47337134d150efdsewardj      tmp = binop(opAND, binop(opCMPORDU, argLe, argRe), const4);
6099334870db22c2eadcaaa48ef8e47337134d150efdsewardj      cond = binop(opOR, tmp, cond);
6100334870db22c2eadcaaa48ef8e47337134d150efdsewardj   }
6101334870db22c2eadcaaa48ef8e47337134d150efdsewardj   stmt( IRStmt_Exit(
6102334870db22c2eadcaaa48ef8e47337134d150efdsewardj            binop(opCMPNE, cond, const0),
61030f50004eefdf1066682a016efb4a57c092ae2da2sewardj            Ijk_SigTRAP,
61043dee849ec7c38746749065e67dc53b75daa7617dsewardj            mode64 ? IRConst_U64(cia) : IRConst_U32((UInt)cia),
61053dee849ec7c38746749065e67dc53b75daa7617dsewardj            OFFB_CIA
6106334870db22c2eadcaaa48ef8e47337134d150efdsewardj   ));
6107334870db22c2eadcaaa48ef8e47337134d150efdsewardj   return False; /* not an unconditional trap */
6108334870db22c2eadcaaa48ef8e47337134d150efdsewardj}
6109334870db22c2eadcaaa48ef8e47337134d150efdsewardj
6110334870db22c2eadcaaa48ef8e47337134d150efdsewardjstatic Bool dis_trapi ( UInt theInstr,
6111334870db22c2eadcaaa48ef8e47337134d150efdsewardj                        /*OUT*/DisResult* dres )
6112334870db22c2eadcaaa48ef8e47337134d150efdsewardj{
6113334870db22c2eadcaaa48ef8e47337134d150efdsewardj   /* D-Form */
6114334870db22c2eadcaaa48ef8e47337134d150efdsewardj   UChar  opc1    = ifieldOPC(theInstr);
6115334870db22c2eadcaaa48ef8e47337134d150efdsewardj   UChar  TO      = ifieldRegDS(theInstr);
6116334870db22c2eadcaaa48ef8e47337134d150efdsewardj   UChar  rA_addr = ifieldRegA(theInstr);
6117334870db22c2eadcaaa48ef8e47337134d150efdsewardj   UInt   uimm16  = ifieldUIMM16(theInstr);
6118334870db22c2eadcaaa48ef8e47337134d150efdsewardj   ULong  simm16  = extend_s_16to64(uimm16);
6119334870db22c2eadcaaa48ef8e47337134d150efdsewardj   Addr64 cia     = guest_CIA_curr_instr;
6120334870db22c2eadcaaa48ef8e47337134d150efdsewardj   IRType ty      = mode64 ? Ity_I64 : Ity_I32;
6121334870db22c2eadcaaa48ef8e47337134d150efdsewardj   Bool   uncond  = False;
6122334870db22c2eadcaaa48ef8e47337134d150efdsewardj
6123334870db22c2eadcaaa48ef8e47337134d150efdsewardj   switch (opc1) {
6124334870db22c2eadcaaa48ef8e47337134d150efdsewardj   case 0x03: // twi  (Trap Word Immediate, PPC32 p548)
612559c0d8f0997bd03e0f8d90b9144dc0aeb6fe9a3asewardj      uncond = do_trap( TO,
612659c0d8f0997bd03e0f8d90b9144dc0aeb6fe9a3asewardj                        mode64 ? unop(Iop_64to32, getIReg(rA_addr))
612759c0d8f0997bd03e0f8d90b9144dc0aeb6fe9a3asewardj                               : getIReg(rA_addr),
6128b4f6d6b956f46b7aad27a0ff694d17ae9f34a2f0sewardj                        mkU32( (UInt)simm16 ),
612959c0d8f0997bd03e0f8d90b9144dc0aeb6fe9a3asewardj                        cia );
6130334870db22c2eadcaaa48ef8e47337134d150efdsewardj      if (TO == 4) {
6131334870db22c2eadcaaa48ef8e47337134d150efdsewardj         DIP("tweqi r%u,%d\n", (UInt)rA_addr, (Int)simm16);
6132334870db22c2eadcaaa48ef8e47337134d150efdsewardj      } else {
6133334870db22c2eadcaaa48ef8e47337134d150efdsewardj         DIP("tw%di r%u,%d\n", (Int)TO, (UInt)rA_addr, (Int)simm16);
6134334870db22c2eadcaaa48ef8e47337134d150efdsewardj      }
6135334870db22c2eadcaaa48ef8e47337134d150efdsewardj      break;
6136334870db22c2eadcaaa48ef8e47337134d150efdsewardj   case 0x02: // tdi
6137334870db22c2eadcaaa48ef8e47337134d150efdsewardj      if (!mode64)
6138334870db22c2eadcaaa48ef8e47337134d150efdsewardj         return False;
613959c0d8f0997bd03e0f8d90b9144dc0aeb6fe9a3asewardj      uncond = do_trap( TO, getIReg(rA_addr), mkU64( (ULong)simm16 ), cia );
61402d19fe35849aa0acb74ee30836b9566999fb53e0sewardj      if (TO == 4) {
61412d19fe35849aa0acb74ee30836b9566999fb53e0sewardj         DIP("tdeqi r%u,%d\n", (UInt)rA_addr, (Int)simm16);
61422d19fe35849aa0acb74ee30836b9566999fb53e0sewardj      } else {
61432d19fe35849aa0acb74ee30836b9566999fb53e0sewardj         DIP("td%di r%u,%d\n", (Int)TO, (UInt)rA_addr, (Int)simm16);
61442d19fe35849aa0acb74ee30836b9566999fb53e0sewardj      }
6145334870db22c2eadcaaa48ef8e47337134d150efdsewardj      break;
6146334870db22c2eadcaaa48ef8e47337134d150efdsewardj   default:
6147334870db22c2eadcaaa48ef8e47337134d150efdsewardj      return False;
6148334870db22c2eadcaaa48ef8e47337134d150efdsewardj   }
6149334870db22c2eadcaaa48ef8e47337134d150efdsewardj
6150334870db22c2eadcaaa48ef8e47337134d150efdsewardj   if (uncond) {
6151334870db22c2eadcaaa48ef8e47337134d150efdsewardj      /* If the trap shows signs of being unconditional, don't
6152334870db22c2eadcaaa48ef8e47337134d150efdsewardj         continue decoding past it. */
61533dee849ec7c38746749065e67dc53b75daa7617dsewardj      putGST( PPC_GST_CIA, mkSzImm( ty, nextInsnAddr() ));
61543dee849ec7c38746749065e67dc53b75daa7617dsewardj      dres->jk_StopHere = Ijk_Boring;
61553dee849ec7c38746749065e67dc53b75daa7617dsewardj      dres->whatNext    = Dis_StopHere;
6156334870db22c2eadcaaa48ef8e47337134d150efdsewardj   }
6157334870db22c2eadcaaa48ef8e47337134d150efdsewardj
6158334870db22c2eadcaaa48ef8e47337134d150efdsewardj   return True;
6159334870db22c2eadcaaa48ef8e47337134d150efdsewardj}
6160334870db22c2eadcaaa48ef8e47337134d150efdsewardj
616159c0d8f0997bd03e0f8d90b9144dc0aeb6fe9a3asewardjstatic Bool dis_trap ( UInt theInstr,
616259c0d8f0997bd03e0f8d90b9144dc0aeb6fe9a3asewardj                        /*OUT*/DisResult* dres )
616359c0d8f0997bd03e0f8d90b9144dc0aeb6fe9a3asewardj{
616459c0d8f0997bd03e0f8d90b9144dc0aeb6fe9a3asewardj   /* X-Form */
616559c0d8f0997bd03e0f8d90b9144dc0aeb6fe9a3asewardj   UInt   opc2    = ifieldOPClo10(theInstr);
616659c0d8f0997bd03e0f8d90b9144dc0aeb6fe9a3asewardj   UChar  TO      = ifieldRegDS(theInstr);
616759c0d8f0997bd03e0f8d90b9144dc0aeb6fe9a3asewardj   UChar  rA_addr = ifieldRegA(theInstr);
616859c0d8f0997bd03e0f8d90b9144dc0aeb6fe9a3asewardj   UChar  rB_addr = ifieldRegB(theInstr);
616959c0d8f0997bd03e0f8d90b9144dc0aeb6fe9a3asewardj   Addr64 cia     = guest_CIA_curr_instr;
617059c0d8f0997bd03e0f8d90b9144dc0aeb6fe9a3asewardj   IRType ty      = mode64 ? Ity_I64 : Ity_I32;
617159c0d8f0997bd03e0f8d90b9144dc0aeb6fe9a3asewardj   Bool   uncond  = False;
617259c0d8f0997bd03e0f8d90b9144dc0aeb6fe9a3asewardj
617359c0d8f0997bd03e0f8d90b9144dc0aeb6fe9a3asewardj   if (ifieldBIT0(theInstr) != 0)
617459c0d8f0997bd03e0f8d90b9144dc0aeb6fe9a3asewardj      return False;
617559c0d8f0997bd03e0f8d90b9144dc0aeb6fe9a3asewardj
617659c0d8f0997bd03e0f8d90b9144dc0aeb6fe9a3asewardj   switch (opc2) {
617759c0d8f0997bd03e0f8d90b9144dc0aeb6fe9a3asewardj   case 0x004: // tw  (Trap Word, PPC64 p540)
617859c0d8f0997bd03e0f8d90b9144dc0aeb6fe9a3asewardj      uncond = do_trap( TO,
617959c0d8f0997bd03e0f8d90b9144dc0aeb6fe9a3asewardj                        mode64 ? unop(Iop_64to32, getIReg(rA_addr))
618059c0d8f0997bd03e0f8d90b9144dc0aeb6fe9a3asewardj                               : getIReg(rA_addr),
618159c0d8f0997bd03e0f8d90b9144dc0aeb6fe9a3asewardj                        mode64 ? unop(Iop_64to32, getIReg(rB_addr))
618259c0d8f0997bd03e0f8d90b9144dc0aeb6fe9a3asewardj                               : getIReg(rB_addr),
618359c0d8f0997bd03e0f8d90b9144dc0aeb6fe9a3asewardj                        cia );
618459c0d8f0997bd03e0f8d90b9144dc0aeb6fe9a3asewardj      if (TO == 4) {
618559c0d8f0997bd03e0f8d90b9144dc0aeb6fe9a3asewardj         DIP("tweq r%u,r%u\n", (UInt)rA_addr, (UInt)rB_addr);
618659c0d8f0997bd03e0f8d90b9144dc0aeb6fe9a3asewardj      } else {
618759c0d8f0997bd03e0f8d90b9144dc0aeb6fe9a3asewardj         DIP("tw%d r%u,r%u\n", (Int)TO, (UInt)rA_addr, (UInt)rB_addr);
618859c0d8f0997bd03e0f8d90b9144dc0aeb6fe9a3asewardj      }
618959c0d8f0997bd03e0f8d90b9144dc0aeb6fe9a3asewardj      break;
6190b4f6d6b956f46b7aad27a0ff694d17ae9f34a2f0sewardj   case 0x044: // td (Trap Doubleword, PPC64 p534)
6191b4f6d6b956f46b7aad27a0ff694d17ae9f34a2f0sewardj      if (!mode64)
6192b4f6d6b956f46b7aad27a0ff694d17ae9f34a2f0sewardj         return False;
6193b4f6d6b956f46b7aad27a0ff694d17ae9f34a2f0sewardj      uncond = do_trap( TO, getIReg(rA_addr), getIReg(rB_addr), cia );
6194b4f6d6b956f46b7aad27a0ff694d17ae9f34a2f0sewardj      if (TO == 4) {
6195b4f6d6b956f46b7aad27a0ff694d17ae9f34a2f0sewardj         DIP("tdeq r%u,r%u\n", (UInt)rA_addr, (UInt)rB_addr);
6196b4f6d6b956f46b7aad27a0ff694d17ae9f34a2f0sewardj      } else {
6197b4f6d6b956f46b7aad27a0ff694d17ae9f34a2f0sewardj         DIP("td%d r%u,r%u\n", (Int)TO, (UInt)rA_addr, (UInt)rB_addr);
6198b4f6d6b956f46b7aad27a0ff694d17ae9f34a2f0sewardj      }
6199b4f6d6b956f46b7aad27a0ff694d17ae9f34a2f0sewardj      break;
620059c0d8f0997bd03e0f8d90b9144dc0aeb6fe9a3asewardj   default:
620159c0d8f0997bd03e0f8d90b9144dc0aeb6fe9a3asewardj      return False;
620259c0d8f0997bd03e0f8d90b9144dc0aeb6fe9a3asewardj   }
620359c0d8f0997bd03e0f8d90b9144dc0aeb6fe9a3asewardj
620459c0d8f0997bd03e0f8d90b9144dc0aeb6fe9a3asewardj   if (uncond) {
620559c0d8f0997bd03e0f8d90b9144dc0aeb6fe9a3asewardj      /* If the trap shows signs of being unconditional, don't
620659c0d8f0997bd03e0f8d90b9144dc0aeb6fe9a3asewardj         continue decoding past it. */
62073dee849ec7c38746749065e67dc53b75daa7617dsewardj      putGST( PPC_GST_CIA, mkSzImm( ty, nextInsnAddr() ));
62083dee849ec7c38746749065e67dc53b75daa7617dsewardj      dres->jk_StopHere = Ijk_Boring;
62093dee849ec7c38746749065e67dc53b75daa7617dsewardj      dres->whatNext    = Dis_StopHere;
621059c0d8f0997bd03e0f8d90b9144dc0aeb6fe9a3asewardj   }
621159c0d8f0997bd03e0f8d90b9144dc0aeb6fe9a3asewardj
621259c0d8f0997bd03e0f8d90b9144dc0aeb6fe9a3asewardj   return True;
621359c0d8f0997bd03e0f8d90b9144dc0aeb6fe9a3asewardj}
621459c0d8f0997bd03e0f8d90b9144dc0aeb6fe9a3asewardj
6215334870db22c2eadcaaa48ef8e47337134d150efdsewardj
62163d870a39e4d145e2f3d9f9a0eeed3475ec934ac1cerion/*
62173d870a39e4d145e2f3d9f9a0eeed3475ec934ac1cerion  System Linkage Instructions
62183d870a39e4d145e2f3d9f9a0eeed3475ec934ac1cerion*/
6219aca070a5b3418a6a9b01e3c57a7eb0fbb5050908sewardjstatic Bool dis_syslink ( UInt theInstr,
6220cacba8e675988fbf21b08feea1f317a9c896c053florian                          const VexAbiInfo* abiinfo, DisResult* dres )
62218c3addacc8343f5d1504379e303934f8ed88903ecerion{
6222d953ebb9b04cbad6891676df597bf0c542b1ec89cerion   IRType ty = mode64 ? Ity_I64 : Ity_I32;
6223d953ebb9b04cbad6891676df597bf0c542b1ec89cerion
6224b85e8bba97fdae7d892f7bfd12e4601307e4721dcerion   if (theInstr != 0x44000002) {
62255b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion      vex_printf("dis_syslink(ppc)(theInstr)\n");
6226b85e8bba97fdae7d892f7bfd12e4601307e4721dcerion      return False;
6227b85e8bba97fdae7d892f7bfd12e4601307e4721dcerion   }
622826d07b26a184d98e37e872f129f0755567f5a966cerion
6229e9d361ab43518b6dfbd3d846f48859534659dee0cerion   // sc  (System Call, PPC32 p504)
6230b85e8bba97fdae7d892f7bfd12e4601307e4721dcerion   DIP("sc\n");
6231aca070a5b3418a6a9b01e3c57a7eb0fbb5050908sewardj
62322322360949754bdcaa87e5ea704480e0b267b09aflorian   /* Copy CIA into the IP_AT_SYSCALL pseudo-register, so that on Darwin
6233aca070a5b3418a6a9b01e3c57a7eb0fbb5050908sewardj      Valgrind can back the guest up to this instruction if it needs
6234aca070a5b3418a6a9b01e3c57a7eb0fbb5050908sewardj      to restart the syscall. */
6235e86310f555a233cc2ca02e1a5d0adb555f12bdcdsewardj   putGST( PPC_GST_IP_AT_SYSCALL, getGST( PPC_GST_CIA ) );
6236aca070a5b3418a6a9b01e3c57a7eb0fbb5050908sewardj
6237b85e8bba97fdae7d892f7bfd12e4601307e4721dcerion   /* It's important that all ArchRegs carry their up-to-date value
6238b85e8bba97fdae7d892f7bfd12e4601307e4721dcerion      at this point.  So we declare an end-of-block here, which
6239b85e8bba97fdae7d892f7bfd12e4601307e4721dcerion      forces any TempRegs caching ArchRegs to be flushed. */
6240d1526f226f529c916d2868d10d52194f7e6b7235sewardj   putGST( PPC_GST_CIA, mkSzImm( ty, nextInsnAddr() ));
6241d953ebb9b04cbad6891676df597bf0c542b1ec89cerion
62423dee849ec7c38746749065e67dc53b75daa7617dsewardj   dres->whatNext    = Dis_StopHere;
62433dee849ec7c38746749065e67dc53b75daa7617dsewardj   dres->jk_StopHere = Ijk_Sys_syscall;
6244b85e8bba97fdae7d892f7bfd12e4601307e4721dcerion   return True;
624526d07b26a184d98e37e872f129f0755567f5a966cerion}
62468c3addacc8343f5d1504379e303934f8ed88903ecerion
62473d870a39e4d145e2f3d9f9a0eeed3475ec934ac1cerion
62483d870a39e4d145e2f3d9f9a0eeed3475ec934ac1cerion/*
62493d870a39e4d145e2f3d9f9a0eeed3475ec934ac1cerion  Memory Synchronization Instructions
625007b07a966a2fdbcf621251a0c1a8ab84807fb120cerion
625107b07a966a2fdbcf621251a0c1a8ab84807fb120cerion  Note on Reservations:
625207b07a966a2fdbcf621251a0c1a8ab84807fb120cerion  We rely on the assumption that V will in fact only allow one thread at
625307b07a966a2fdbcf621251a0c1a8ab84807fb120cerion  once to run.  In effect, a thread can make a reservation, but we don't
625407b07a966a2fdbcf621251a0c1a8ab84807fb120cerion  check any stores it does.  Instead, the reservation is cancelled when
625507b07a966a2fdbcf621251a0c1a8ab84807fb120cerion  the scheduler switches to another thread (run_thread_for_a_while()).
62563d870a39e4d145e2f3d9f9a0eeed3475ec934ac1cerion*/
62578c3addacc8343f5d1504379e303934f8ed88903ecerionstatic Bool dis_memsync ( UInt theInstr )
62588c3addacc8343f5d1504379e303934f8ed88903ecerion{
6259b85e8bba97fdae7d892f7bfd12e4601307e4721dcerion   /* X-Form, XL-Form */
6260d953ebb9b04cbad6891676df597bf0c542b1ec89cerion   UChar opc1    = ifieldOPC(theInstr);
6261d953ebb9b04cbad6891676df597bf0c542b1ec89cerion   UInt  b11to25 = IFIELD(theInstr, 11, 15);
6262e43bc8814b02d099f5758845b9ce10049b14dab3cerion   UChar flag_L  = ifieldRegDS(theInstr);
6263e43bc8814b02d099f5758845b9ce10049b14dab3cerion   UInt  b11to20 = IFIELD(theInstr, 11, 10);
6264d953ebb9b04cbad6891676df597bf0c542b1ec89cerion   UChar rD_addr = ifieldRegDS(theInstr);
6265d953ebb9b04cbad6891676df597bf0c542b1ec89cerion   UChar rS_addr = rD_addr;
6266d953ebb9b04cbad6891676df597bf0c542b1ec89cerion   UChar rA_addr = ifieldRegA(theInstr);
6267d953ebb9b04cbad6891676df597bf0c542b1ec89cerion   UChar rB_addr = ifieldRegB(theInstr);
6268d953ebb9b04cbad6891676df597bf0c542b1ec89cerion   UInt  opc2    = ifieldOPClo10(theInstr);
6269d953ebb9b04cbad6891676df597bf0c542b1ec89cerion   UChar b0      = ifieldBIT0(theInstr);
6270d953ebb9b04cbad6891676df597bf0c542b1ec89cerion
6271d953ebb9b04cbad6891676df597bf0c542b1ec89cerion   IRType ty     = mode64 ? Ity_I64 : Ity_I32;
6272d953ebb9b04cbad6891676df597bf0c542b1ec89cerion   IRTemp EA     = newTemp(ty);
6273d953ebb9b04cbad6891676df597bf0c542b1ec89cerion
6274d953ebb9b04cbad6891676df597bf0c542b1ec89cerion   assign( EA, ea_rAor0_idxd( rA_addr, rB_addr ) );
6275edf7fc572e2decb93e9143961e8739c8fe18899dcerion
6276b85e8bba97fdae7d892f7bfd12e4601307e4721dcerion   switch (opc1) {
6277afe85831d73e546e483dfc51964409b7ecd7c5fesewardj   /* XL-Form */
6278e9d361ab43518b6dfbd3d846f48859534659dee0cerion   case 0x13:   // isync (Instruction Synchronize, PPC32 p432)
6279b85e8bba97fdae7d892f7bfd12e4601307e4721dcerion      if (opc2 != 0x096) {
62805b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion         vex_printf("dis_memsync(ppc)(0x13,opc2)\n");
6281b85e8bba97fdae7d892f7bfd12e4601307e4721dcerion         return False;
6282b85e8bba97fdae7d892f7bfd12e4601307e4721dcerion      }
6283b85e8bba97fdae7d892f7bfd12e4601307e4721dcerion      if (b11to25 != 0 || b0 != 0) {
62845b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion         vex_printf("dis_memsync(ppc)(0x13,b11to25|b0)\n");
6285b85e8bba97fdae7d892f7bfd12e4601307e4721dcerion         return False;
6286b85e8bba97fdae7d892f7bfd12e4601307e4721dcerion      }
6287b85e8bba97fdae7d892f7bfd12e4601307e4721dcerion      DIP("isync\n");
6288c4356f0d3c74fc2622dbeed79c6c1045fc519f72sewardj      stmt( IRStmt_MBE(Imbe_Fence) );
6289b85e8bba97fdae7d892f7bfd12e4601307e4721dcerion      break;
6290b85e8bba97fdae7d892f7bfd12e4601307e4721dcerion
6291b85e8bba97fdae7d892f7bfd12e4601307e4721dcerion   /* X-Form */
6292b85e8bba97fdae7d892f7bfd12e4601307e4721dcerion   case 0x1F:
6293b85e8bba97fdae7d892f7bfd12e4601307e4721dcerion      switch (opc2) {
62945b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion      case 0x356: // eieio (Enforce In-Order Exec of I/O, PPC32 p394)
62957787af415a9104b601c2f0ce5b56749e4fd86691sewardj         if (b11to25 != 0 || b0 != 0) {
62965b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion            vex_printf("dis_memsync(ppc)(eiei0,b11to25|b0)\n");
62977787af415a9104b601c2f0ce5b56749e4fd86691sewardj            return False;
62987787af415a9104b601c2f0ce5b56749e4fd86691sewardj         }
62997787af415a9104b601c2f0ce5b56749e4fd86691sewardj         DIP("eieio\n");
63007787af415a9104b601c2f0ce5b56749e4fd86691sewardj         /* Insert a memory fence, just to be on the safe side. */
6301c4356f0d3c74fc2622dbeed79c6c1045fc519f72sewardj         stmt( IRStmt_MBE(Imbe_Fence) );
63027787af415a9104b601c2f0ce5b56749e4fd86691sewardj         break;
6303b85e8bba97fdae7d892f7bfd12e4601307e4721dcerion
6304e768e92e054cde495849a5c842a477d287677f78sewardj      case 0x014: { // lwarx (Load Word and Reserve Indexed, PPC32 p458)
6305e768e92e054cde495849a5c842a477d287677f78sewardj         IRTemp res;
6306fe397a2c1c7f6594f305a90c51f9859778348760sewardj         /* According to the PowerPC ISA version 2.05, b0 (called EH
6307fe397a2c1c7f6594f305a90c51f9859778348760sewardj            in the documentation) is merely a hint bit to the
6308fe397a2c1c7f6594f305a90c51f9859778348760sewardj            hardware, I think as to whether or not contention is
6309fe397a2c1c7f6594f305a90c51f9859778348760sewardj            likely.  So we can just ignore it. */
6310fe397a2c1c7f6594f305a90c51f9859778348760sewardj         DIP("lwarx r%u,r%u,r%u,EH=%u\n", rD_addr, rA_addr, rB_addr, (UInt)b0);
6311e9d8a26b690c2561ac54ab0cd6ad83ecbadcbe76sewardj
6312e9d8a26b690c2561ac54ab0cd6ad83ecbadcbe76sewardj         // trap if misaligned
6313e9d8a26b690c2561ac54ab0cd6ad83ecbadcbe76sewardj         gen_SIGBUS_if_misaligned( EA, 4 );
6314e9d8a26b690c2561ac54ab0cd6ad83ecbadcbe76sewardj
6315e9d8a26b690c2561ac54ab0cd6ad83ecbadcbe76sewardj         // and actually do the load
6316e768e92e054cde495849a5c842a477d287677f78sewardj         res = newTemp(Ity_I32);
63171f5fe1fc3a37ca729925e8eec25aa1025b4a6cdbcarll         stmt( stmt_load(res, mkexpr(EA), NULL/*this is a load*/) );
6318e768e92e054cde495849a5c842a477d287677f78sewardj
6319e768e92e054cde495849a5c842a477d287677f78sewardj         putIReg( rD_addr, mkWidenFrom32(ty, mkexpr(res), False) );
6320b85e8bba97fdae7d892f7bfd12e4601307e4721dcerion         break;
6321e768e92e054cde495849a5c842a477d287677f78sewardj      }
6322e768e92e054cde495849a5c842a477d287677f78sewardj
6323d826889bd512ded2fbbc4781c595ecf0513f46f6carll      case 0x034: { // lbarx (Load Word and Reserve Indexed)
6324d826889bd512ded2fbbc4781c595ecf0513f46f6carll         IRTemp res;
6325d826889bd512ded2fbbc4781c595ecf0513f46f6carll         /* According to the PowerPC ISA version 2.05, b0 (called EH
6326d826889bd512ded2fbbc4781c595ecf0513f46f6carll            in the documentation) is merely a hint bit to the
6327d826889bd512ded2fbbc4781c595ecf0513f46f6carll            hardware, I think as to whether or not contention is
6328d826889bd512ded2fbbc4781c595ecf0513f46f6carll            likely.  So we can just ignore it. */
6329d826889bd512ded2fbbc4781c595ecf0513f46f6carll         DIP("lbarx r%u,r%u,r%u,EH=%u\n", rD_addr, rA_addr, rB_addr, (UInt)b0);
6330d826889bd512ded2fbbc4781c595ecf0513f46f6carll
6331d826889bd512ded2fbbc4781c595ecf0513f46f6carll         // and actually do the load
6332d826889bd512ded2fbbc4781c595ecf0513f46f6carll         res = newTemp(Ity_I8);
6333d826889bd512ded2fbbc4781c595ecf0513f46f6carll         stmt( stmt_load(res, mkexpr(EA), NULL/*this is a load*/) );
6334d826889bd512ded2fbbc4781c595ecf0513f46f6carll
6335d826889bd512ded2fbbc4781c595ecf0513f46f6carll         putIReg( rD_addr, mkWidenFrom8(ty, mkexpr(res), False) );
6336d826889bd512ded2fbbc4781c595ecf0513f46f6carll         break;
6337d826889bd512ded2fbbc4781c595ecf0513f46f6carll     }
6338d826889bd512ded2fbbc4781c595ecf0513f46f6carll
6339d826889bd512ded2fbbc4781c595ecf0513f46f6carll      case 0x074: { // lharx (Load Word and Reserve Indexed)
6340d826889bd512ded2fbbc4781c595ecf0513f46f6carll         IRTemp res;
6341d826889bd512ded2fbbc4781c595ecf0513f46f6carll         /* According to the PowerPC ISA version 2.05, b0 (called EH
6342d826889bd512ded2fbbc4781c595ecf0513f46f6carll            in the documentation) is merely a hint bit to the
6343d826889bd512ded2fbbc4781c595ecf0513f46f6carll            hardware, I think as to whether or not contention is
6344d826889bd512ded2fbbc4781c595ecf0513f46f6carll            likely.  So we can just ignore it. */
6345d826889bd512ded2fbbc4781c595ecf0513f46f6carll         DIP("lharx r%u,r%u,r%u,EH=%u\n", rD_addr, rA_addr, rB_addr, (UInt)b0);
6346d826889bd512ded2fbbc4781c595ecf0513f46f6carll
6347d826889bd512ded2fbbc4781c595ecf0513f46f6carll         // trap if misaligned
6348d826889bd512ded2fbbc4781c595ecf0513f46f6carll         gen_SIGBUS_if_misaligned( EA, 2 );
6349d826889bd512ded2fbbc4781c595ecf0513f46f6carll
6350d826889bd512ded2fbbc4781c595ecf0513f46f6carll         // and actually do the load
6351d826889bd512ded2fbbc4781c595ecf0513f46f6carll         res = newTemp(Ity_I16);
6352d826889bd512ded2fbbc4781c595ecf0513f46f6carll         stmt( stmt_load(res, mkexpr(EA), NULL/*this is a load*/) );
6353d826889bd512ded2fbbc4781c595ecf0513f46f6carll
6354d826889bd512ded2fbbc4781c595ecf0513f46f6carll         putIReg( rD_addr, mkWidenFrom16(ty, mkexpr(res), False) );
6355d826889bd512ded2fbbc4781c595ecf0513f46f6carll         break;
6356d826889bd512ded2fbbc4781c595ecf0513f46f6carll      }
6357d826889bd512ded2fbbc4781c595ecf0513f46f6carll
63587787af415a9104b601c2f0ce5b56749e4fd86691sewardj      case 0x096: {
63597787af415a9104b601c2f0ce5b56749e4fd86691sewardj         // stwcx. (Store Word Conditional Indexed, PPC32 p532)
6360e9d8a26b690c2561ac54ab0cd6ad83ecbadcbe76sewardj         // Note this has to handle stwcx. in both 32- and 64-bit modes,
6361e9d8a26b690c2561ac54ab0cd6ad83ecbadcbe76sewardj         // so isn't quite as straightforward as it might otherwise be.
6362e9d8a26b690c2561ac54ab0cd6ad83ecbadcbe76sewardj         IRTemp rS = newTemp(Ity_I32);
6363e9d8a26b690c2561ac54ab0cd6ad83ecbadcbe76sewardj         IRTemp resSC;
6364b85e8bba97fdae7d892f7bfd12e4601307e4721dcerion         if (b0 != 1) {
63655b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion            vex_printf("dis_memsync(ppc)(stwcx.,b0)\n");
6366b85e8bba97fdae7d892f7bfd12e4601307e4721dcerion            return False;
6367b85e8bba97fdae7d892f7bfd12e4601307e4721dcerion         }
6368d953ebb9b04cbad6891676df597bf0c542b1ec89cerion         DIP("stwcx. r%u,r%u,r%u\n", rS_addr, rA_addr, rB_addr);
6369afe85831d73e546e483dfc51964409b7ecd7c5fesewardj
6370e9d8a26b690c2561ac54ab0cd6ad83ecbadcbe76sewardj         // trap if misaligned
6371e9d8a26b690c2561ac54ab0cd6ad83ecbadcbe76sewardj         gen_SIGBUS_if_misaligned( EA, 4 );
63727787af415a9104b601c2f0ce5b56749e4fd86691sewardj
6373e9d8a26b690c2561ac54ab0cd6ad83ecbadcbe76sewardj         // Get the data to be stored, and narrow to 32 bits if necessary
6374e9d8a26b690c2561ac54ab0cd6ad83ecbadcbe76sewardj         assign( rS, mkNarrowTo32(ty, getIReg(rS_addr)) );
63757787af415a9104b601c2f0ce5b56749e4fd86691sewardj
6376e9d8a26b690c2561ac54ab0cd6ad83ecbadcbe76sewardj         // Do the store, and get success/failure bit into resSC
6377e9d8a26b690c2561ac54ab0cd6ad83ecbadcbe76sewardj         resSC = newTemp(Ity_I1);
63781f5fe1fc3a37ca729925e8eec25aa1025b4a6cdbcarll         stmt( stmt_load( resSC, mkexpr(EA), mkexpr(rS)) );
6379e9d8a26b690c2561ac54ab0cd6ad83ecbadcbe76sewardj
6380e9d8a26b690c2561ac54ab0cd6ad83ecbadcbe76sewardj         // Set CR0[LT GT EQ S0] = 0b000 || XER[SO]  on failure
6381e9d8a26b690c2561ac54ab0cd6ad83ecbadcbe76sewardj         // Set CR0[LT GT EQ S0] = 0b001 || XER[SO]  on success
6382e9d8a26b690c2561ac54ab0cd6ad83ecbadcbe76sewardj         putCR321(0, binop(Iop_Shl8, unop(Iop_1Uto8, mkexpr(resSC)), mkU8(1)));
6383e9d8a26b690c2561ac54ab0cd6ad83ecbadcbe76sewardj         putCR0(0, getXER_SO());
6384d953ebb9b04cbad6891676df597bf0c542b1ec89cerion
6385e9d8a26b690c2561ac54ab0cd6ad83ecbadcbe76sewardj         /* Note:
6386d953ebb9b04cbad6891676df597bf0c542b1ec89cerion            If resaddr != lwarx_resaddr, CR0[EQ] is undefined, and
6387d953ebb9b04cbad6891676df597bf0c542b1ec89cerion            whether rS is stored is dependent on that value. */
6388e9d8a26b690c2561ac54ab0cd6ad83ecbadcbe76sewardj         /* So I guess we can just ignore this case? */
6389b85e8bba97fdae7d892f7bfd12e4601307e4721dcerion         break;
63907787af415a9104b601c2f0ce5b56749e4fd86691sewardj      }
63917787af415a9104b601c2f0ce5b56749e4fd86691sewardj
6392d826889bd512ded2fbbc4781c595ecf0513f46f6carll      case 0x2B6: {
6393d826889bd512ded2fbbc4781c595ecf0513f46f6carll         // stbcx. (Store Byte Conditional Indexed)
6394d826889bd512ded2fbbc4781c595ecf0513f46f6carll         // Note this has to handle stbcx. in both 32- and 64-bit modes,
6395d826889bd512ded2fbbc4781c595ecf0513f46f6carll         // so isn't quite as straightforward as it might otherwise be.
6396d826889bd512ded2fbbc4781c595ecf0513f46f6carll         IRTemp rS = newTemp(Ity_I8);
6397d826889bd512ded2fbbc4781c595ecf0513f46f6carll         IRTemp resSC;
6398d826889bd512ded2fbbc4781c595ecf0513f46f6carll         if (b0 != 1) {
6399d826889bd512ded2fbbc4781c595ecf0513f46f6carll            vex_printf("dis_memsync(ppc)(stbcx.,b0)\n");
6400d826889bd512ded2fbbc4781c595ecf0513f46f6carll            return False;
6401d826889bd512ded2fbbc4781c595ecf0513f46f6carll         }
6402d826889bd512ded2fbbc4781c595ecf0513f46f6carll         DIP("stbcx. r%u,r%u,r%u\n", rS_addr, rA_addr, rB_addr);
6403d826889bd512ded2fbbc4781c595ecf0513f46f6carll
6404d826889bd512ded2fbbc4781c595ecf0513f46f6carll         // Get the data to be stored, and narrow to 32 bits if necessary
6405d826889bd512ded2fbbc4781c595ecf0513f46f6carll         assign( rS, mkNarrowTo8(ty, getIReg(rS_addr)) );
6406d826889bd512ded2fbbc4781c595ecf0513f46f6carll
6407d826889bd512ded2fbbc4781c595ecf0513f46f6carll         // Do the store, and get success/failure bit into resSC
6408d826889bd512ded2fbbc4781c595ecf0513f46f6carll         resSC = newTemp(Ity_I1);
6409d826889bd512ded2fbbc4781c595ecf0513f46f6carll         stmt( stmt_load( resSC, mkexpr(EA), mkexpr(rS)) );
6410d826889bd512ded2fbbc4781c595ecf0513f46f6carll
6411d826889bd512ded2fbbc4781c595ecf0513f46f6carll         // Set CR0[LT GT EQ S0] = 0b000 || XER[SO]  on failure
6412d826889bd512ded2fbbc4781c595ecf0513f46f6carll         // Set CR0[LT GT EQ S0] = 0b001 || XER[SO]  on success
6413d826889bd512ded2fbbc4781c595ecf0513f46f6carll         putCR321(0, binop(Iop_Shl8, unop(Iop_1Uto8, mkexpr(resSC)), mkU8(1)));
6414d826889bd512ded2fbbc4781c595ecf0513f46f6carll         putCR0(0, getXER_SO());
6415d826889bd512ded2fbbc4781c595ecf0513f46f6carll
6416d826889bd512ded2fbbc4781c595ecf0513f46f6carll         /* Note:
6417d826889bd512ded2fbbc4781c595ecf0513f46f6carll            If resaddr != lbarx_resaddr, CR0[EQ] is undefined, and
6418d826889bd512ded2fbbc4781c595ecf0513f46f6carll            whether rS is stored is dependent on that value. */
6419d826889bd512ded2fbbc4781c595ecf0513f46f6carll         /* So I guess we can just ignore this case? */
6420d826889bd512ded2fbbc4781c595ecf0513f46f6carll         break;
6421d826889bd512ded2fbbc4781c595ecf0513f46f6carll      }
6422d826889bd512ded2fbbc4781c595ecf0513f46f6carll
6423d826889bd512ded2fbbc4781c595ecf0513f46f6carll      case 0x2D6: {
6424d826889bd512ded2fbbc4781c595ecf0513f46f6carll         // sthcx. (Store Word Conditional Indexed, PPC32 p532)
6425d826889bd512ded2fbbc4781c595ecf0513f46f6carll         // Note this has to handle sthcx. in both 32- and 64-bit modes,
6426d826889bd512ded2fbbc4781c595ecf0513f46f6carll         // so isn't quite as straightforward as it might otherwise be.
6427d826889bd512ded2fbbc4781c595ecf0513f46f6carll         IRTemp rS = newTemp(Ity_I16);
6428d826889bd512ded2fbbc4781c595ecf0513f46f6carll         IRTemp resSC;
6429d826889bd512ded2fbbc4781c595ecf0513f46f6carll         if (b0 != 1) {
6430d826889bd512ded2fbbc4781c595ecf0513f46f6carll            vex_printf("dis_memsync(ppc)(stwcx.,b0)\n");
6431d826889bd512ded2fbbc4781c595ecf0513f46f6carll            return False;
6432d826889bd512ded2fbbc4781c595ecf0513f46f6carll         }
6433d826889bd512ded2fbbc4781c595ecf0513f46f6carll         DIP("sthcx. r%u,r%u,r%u\n", rS_addr, rA_addr, rB_addr);
6434d826889bd512ded2fbbc4781c595ecf0513f46f6carll
6435d826889bd512ded2fbbc4781c595ecf0513f46f6carll         // trap if misaligned
6436d826889bd512ded2fbbc4781c595ecf0513f46f6carll         gen_SIGBUS_if_misaligned( EA, 2 );
6437d826889bd512ded2fbbc4781c595ecf0513f46f6carll
6438d826889bd512ded2fbbc4781c595ecf0513f46f6carll         // Get the data to be stored, and narrow to 16 bits if necessary
6439d826889bd512ded2fbbc4781c595ecf0513f46f6carll         assign( rS, mkNarrowTo16(ty, getIReg(rS_addr)) );
6440d826889bd512ded2fbbc4781c595ecf0513f46f6carll
6441d826889bd512ded2fbbc4781c595ecf0513f46f6carll         // Do the store, and get success/failure bit into resSC
6442d826889bd512ded2fbbc4781c595ecf0513f46f6carll         resSC = newTemp(Ity_I1);
6443d826889bd512ded2fbbc4781c595ecf0513f46f6carll         stmt( stmt_load( resSC, mkexpr(EA), mkexpr(rS)) );
6444d826889bd512ded2fbbc4781c595ecf0513f46f6carll
6445d826889bd512ded2fbbc4781c595ecf0513f46f6carll         // Set CR0[LT GT EQ S0] = 0b000 || XER[SO]  on failure
6446d826889bd512ded2fbbc4781c595ecf0513f46f6carll         // Set CR0[LT GT EQ S0] = 0b001 || XER[SO]  on success
6447d826889bd512ded2fbbc4781c595ecf0513f46f6carll         putCR321(0, binop(Iop_Shl8, unop(Iop_1Uto8, mkexpr(resSC)), mkU8(1)));
6448d826889bd512ded2fbbc4781c595ecf0513f46f6carll         putCR0(0, getXER_SO());
6449d826889bd512ded2fbbc4781c595ecf0513f46f6carll
6450d826889bd512ded2fbbc4781c595ecf0513f46f6carll         /* Note:
6451d826889bd512ded2fbbc4781c595ecf0513f46f6carll            If resaddr != lharx_resaddr, CR0[EQ] is undefined, and
6452d826889bd512ded2fbbc4781c595ecf0513f46f6carll            whether rS is stored is dependent on that value. */
6453d826889bd512ded2fbbc4781c595ecf0513f46f6carll         /* So I guess we can just ignore this case? */
6454d826889bd512ded2fbbc4781c595ecf0513f46f6carll         break;
6455d826889bd512ded2fbbc4781c595ecf0513f46f6carll      }
6456d826889bd512ded2fbbc4781c595ecf0513f46f6carll
6457b029a61119a84c9a7e32443f14c051c705cc73a0sewardj      case 0x256: // sync (Synchronize, PPC32 p543),
6458e43bc8814b02d099f5758845b9ce10049b14dab3cerion                  // also lwsync (L==1), ptesync (L==2)
6459b029a61119a84c9a7e32443f14c051c705cc73a0sewardj         /* http://sources.redhat.com/ml/binutils/2000-12/msg00311.html
6460b029a61119a84c9a7e32443f14c051c705cc73a0sewardj
6461b029a61119a84c9a7e32443f14c051c705cc73a0sewardj            The PowerPC architecture used in IBM chips has expanded
6462b029a61119a84c9a7e32443f14c051c705cc73a0sewardj            the sync instruction into two variants: lightweight sync
6463b029a61119a84c9a7e32443f14c051c705cc73a0sewardj            and heavyweight sync.  The original sync instruction is
6464b029a61119a84c9a7e32443f14c051c705cc73a0sewardj            the new heavyweight sync and lightweight sync is a strict
6465b029a61119a84c9a7e32443f14c051c705cc73a0sewardj            subset of the heavyweight sync functionality. This allows
6466b029a61119a84c9a7e32443f14c051c705cc73a0sewardj            the programmer to specify a less expensive operation on
6467b029a61119a84c9a7e32443f14c051c705cc73a0sewardj            high-end systems when the full sync functionality is not
6468b029a61119a84c9a7e32443f14c051c705cc73a0sewardj            necessary.
6469b029a61119a84c9a7e32443f14c051c705cc73a0sewardj
6470b029a61119a84c9a7e32443f14c051c705cc73a0sewardj            The basic "sync" mnemonic now utilizes an operand. "sync"
6471b029a61119a84c9a7e32443f14c051c705cc73a0sewardj            without an operand now becomes a extended mnemonic for
6472b029a61119a84c9a7e32443f14c051c705cc73a0sewardj            heavyweight sync.  Processors without the lwsync
6473b029a61119a84c9a7e32443f14c051c705cc73a0sewardj            instruction will not decode the L field and will perform a
6474b029a61119a84c9a7e32443f14c051c705cc73a0sewardj            heavyweight sync.  Everything is backward compatible.
6475b029a61119a84c9a7e32443f14c051c705cc73a0sewardj
6476b029a61119a84c9a7e32443f14c051c705cc73a0sewardj            sync    =       sync 0
6477b029a61119a84c9a7e32443f14c051c705cc73a0sewardj            lwsync  =       sync 1
6478e43bc8814b02d099f5758845b9ce10049b14dab3cerion            ptesync =       sync 2    *** TODO - not implemented ***
64794e2c2b3cacdc79a993f4cec9249d9bffd82e4978cerion         */
6480e43bc8814b02d099f5758845b9ce10049b14dab3cerion         if (b11to20 != 0 || b0 != 0) {
6481e43bc8814b02d099f5758845b9ce10049b14dab3cerion            vex_printf("dis_memsync(ppc)(sync/lwsync,b11to20|b0)\n");
6482b85e8bba97fdae7d892f7bfd12e4601307e4721dcerion            return False;
6483b85e8bba97fdae7d892f7bfd12e4601307e4721dcerion         }
6484e43bc8814b02d099f5758845b9ce10049b14dab3cerion         if (flag_L != 0/*sync*/ && flag_L != 1/*lwsync*/) {
6485e43bc8814b02d099f5758845b9ce10049b14dab3cerion            vex_printf("dis_memsync(ppc)(sync/lwsync,flag_L)\n");
6486e43bc8814b02d099f5758845b9ce10049b14dab3cerion            return False;
6487e43bc8814b02d099f5758845b9ce10049b14dab3cerion         }
6488e43bc8814b02d099f5758845b9ce10049b14dab3cerion         DIP("%ssync\n", flag_L == 1 ? "lw" : "");
6489b85e8bba97fdae7d892f7bfd12e4601307e4721dcerion         /* Insert a memory fence.  It's sometimes important that these
6490b85e8bba97fdae7d892f7bfd12e4601307e4721dcerion            are carried through to the generated code. */
6491c4356f0d3c74fc2622dbeed79c6c1045fc519f72sewardj         stmt( IRStmt_MBE(Imbe_Fence) );
6492b85e8bba97fdae7d892f7bfd12e4601307e4721dcerion         break;
6493f0de28cf1a762b0d6f74c93d3532c89a230673bbcerion
6494f0de28cf1a762b0d6f74c93d3532c89a230673bbcerion      /* 64bit Memsync */
6495e768e92e054cde495849a5c842a477d287677f78sewardj      case 0x054: { // ldarx (Load DWord and Reserve Indexed, PPC64 p473)
6496e768e92e054cde495849a5c842a477d287677f78sewardj         IRTemp res;
6497fe397a2c1c7f6594f305a90c51f9859778348760sewardj         /* According to the PowerPC ISA version 2.05, b0 (called EH
6498fe397a2c1c7f6594f305a90c51f9859778348760sewardj            in the documentation) is merely a hint bit to the
6499fe397a2c1c7f6594f305a90c51f9859778348760sewardj            hardware, I think as to whether or not contention is
6500fe397a2c1c7f6594f305a90c51f9859778348760sewardj            likely.  So we can just ignore it. */
6501e9d8a26b690c2561ac54ab0cd6ad83ecbadcbe76sewardj         if (!mode64)
6502e9d8a26b690c2561ac54ab0cd6ad83ecbadcbe76sewardj            return False;
6503fe397a2c1c7f6594f305a90c51f9859778348760sewardj         DIP("ldarx r%u,r%u,r%u,EH=%u\n", rD_addr, rA_addr, rB_addr, (UInt)b0);
6504e9d8a26b690c2561ac54ab0cd6ad83ecbadcbe76sewardj
6505e9d8a26b690c2561ac54ab0cd6ad83ecbadcbe76sewardj         // trap if misaligned
6506e9d8a26b690c2561ac54ab0cd6ad83ecbadcbe76sewardj         gen_SIGBUS_if_misaligned( EA, 8 );
6507e9d8a26b690c2561ac54ab0cd6ad83ecbadcbe76sewardj
6508e9d8a26b690c2561ac54ab0cd6ad83ecbadcbe76sewardj         // and actually do the load
6509e768e92e054cde495849a5c842a477d287677f78sewardj         res = newTemp(Ity_I64);
65101f5fe1fc3a37ca729925e8eec25aa1025b4a6cdbcarll         stmt( stmt_load( res, mkexpr(EA), NULL/*this is a load*/) );
6511e768e92e054cde495849a5c842a477d287677f78sewardj
6512e768e92e054cde495849a5c842a477d287677f78sewardj         putIReg( rD_addr, mkexpr(res) );
651307b07a966a2fdbcf621251a0c1a8ab84807fb120cerion         break;
6514e768e92e054cde495849a5c842a477d287677f78sewardj      }
6515e768e92e054cde495849a5c842a477d287677f78sewardj
65165b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion      case 0x0D6: { // stdcx. (Store DWord Condition Indexd, PPC64 p581)
6517e9d8a26b690c2561ac54ab0cd6ad83ecbadcbe76sewardj         // A marginally simplified version of the stwcx. case
6518e9d8a26b690c2561ac54ab0cd6ad83ecbadcbe76sewardj         IRTemp rS = newTemp(Ity_I64);
6519e9d8a26b690c2561ac54ab0cd6ad83ecbadcbe76sewardj         IRTemp resSC;
6520f0de28cf1a762b0d6f74c93d3532c89a230673bbcerion         if (b0 != 1) {
65215b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion            vex_printf("dis_memsync(ppc)(stdcx.,b0)\n");
6522f0de28cf1a762b0d6f74c93d3532c89a230673bbcerion            return False;
6523f0de28cf1a762b0d6f74c93d3532c89a230673bbcerion         }
6524e9d8a26b690c2561ac54ab0cd6ad83ecbadcbe76sewardj         if (!mode64)
6525e9d8a26b690c2561ac54ab0cd6ad83ecbadcbe76sewardj            return False;
6526f0de28cf1a762b0d6f74c93d3532c89a230673bbcerion         DIP("stdcx. r%u,r%u,r%u\n", rS_addr, rA_addr, rB_addr);
6527e9d8a26b690c2561ac54ab0cd6ad83ecbadcbe76sewardj
6528e9d8a26b690c2561ac54ab0cd6ad83ecbadcbe76sewardj         // trap if misaligned
6529e9d8a26b690c2561ac54ab0cd6ad83ecbadcbe76sewardj         gen_SIGBUS_if_misaligned( EA, 8 );
6530e9d8a26b690c2561ac54ab0cd6ad83ecbadcbe76sewardj
6531e9d8a26b690c2561ac54ab0cd6ad83ecbadcbe76sewardj         // Get the data to be stored
653207b07a966a2fdbcf621251a0c1a8ab84807fb120cerion         assign( rS, getIReg(rS_addr) );
6533f0de28cf1a762b0d6f74c93d3532c89a230673bbcerion
6534e9d8a26b690c2561ac54ab0cd6ad83ecbadcbe76sewardj         // Do the store, and get success/failure bit into resSC
6535e9d8a26b690c2561ac54ab0cd6ad83ecbadcbe76sewardj         resSC = newTemp(Ity_I1);
65361f5fe1fc3a37ca729925e8eec25aa1025b4a6cdbcarll         stmt( stmt_load( resSC, mkexpr(EA), mkexpr(rS)) );
6537e9d8a26b690c2561ac54ab0cd6ad83ecbadcbe76sewardj
6538e9d8a26b690c2561ac54ab0cd6ad83ecbadcbe76sewardj         // Set CR0[LT GT EQ S0] = 0b000 || XER[SO]  on failure
6539e9d8a26b690c2561ac54ab0cd6ad83ecbadcbe76sewardj         // Set CR0[LT GT EQ S0] = 0b001 || XER[SO]  on success
6540e9d8a26b690c2561ac54ab0cd6ad83ecbadcbe76sewardj         putCR321(0, binop(Iop_Shl8, unop(Iop_1Uto8, mkexpr(resSC)), mkU8(1)));
654107b07a966a2fdbcf621251a0c1a8ab84807fb120cerion         putCR0(0, getXER_SO());
6542e9d8a26b690c2561ac54ab0cd6ad83ecbadcbe76sewardj
6543e9d8a26b690c2561ac54ab0cd6ad83ecbadcbe76sewardj         /* Note:
6544e9d8a26b690c2561ac54ab0cd6ad83ecbadcbe76sewardj            If resaddr != lwarx_resaddr, CR0[EQ] is undefined, and
6545e9d8a26b690c2561ac54ab0cd6ad83ecbadcbe76sewardj            whether rS is stored is dependent on that value. */
6546e9d8a26b690c2561ac54ab0cd6ad83ecbadcbe76sewardj         /* So I guess we can just ignore this case? */
654707b07a966a2fdbcf621251a0c1a8ab84807fb120cerion         break;
654807b07a966a2fdbcf621251a0c1a8ab84807fb120cerion      }
654907b07a966a2fdbcf621251a0c1a8ab84807fb120cerion
655078850ae9874a90ea625fcee1fd4c359375b7b538carll      /* 128bit Memsync */
655178850ae9874a90ea625fcee1fd4c359375b7b538carll      case 0x114: { // lqarx (Load QuadWord and Reserve Indexed)
655278850ae9874a90ea625fcee1fd4c359375b7b538carll         IRTemp res_hi = newTemp(ty);
655378850ae9874a90ea625fcee1fd4c359375b7b538carll         IRTemp res_lo = newTemp(ty);
655478850ae9874a90ea625fcee1fd4c359375b7b538carll
655578850ae9874a90ea625fcee1fd4c359375b7b538carll         /* According to the PowerPC ISA version 2.07, b0 (called EH
655678850ae9874a90ea625fcee1fd4c359375b7b538carll            in the documentation) is merely a hint bit to the
655778850ae9874a90ea625fcee1fd4c359375b7b538carll            hardware, I think as to whether or not contention is
655878850ae9874a90ea625fcee1fd4c359375b7b538carll            likely.  So we can just ignore it. */
655978850ae9874a90ea625fcee1fd4c359375b7b538carll         DIP("lqarx r%u,r%u,r%u,EH=%u\n", rD_addr, rA_addr, rB_addr, (UInt)b0);
656078850ae9874a90ea625fcee1fd4c359375b7b538carll
656178850ae9874a90ea625fcee1fd4c359375b7b538carll         // trap if misaligned
656278850ae9874a90ea625fcee1fd4c359375b7b538carll         gen_SIGBUS_if_misaligned( EA, 16 );
656378850ae9874a90ea625fcee1fd4c359375b7b538carll
656478850ae9874a90ea625fcee1fd4c359375b7b538carll         // and actually do the load
656578850ae9874a90ea625fcee1fd4c359375b7b538carll         if (mode64) {
6566999ef56da3e4426c5f6bf74de40d23ff02dafb34carll            if (host_endness == VexEndnessBE) {
6567999ef56da3e4426c5f6bf74de40d23ff02dafb34carll               stmt( stmt_load( res_hi,
6568999ef56da3e4426c5f6bf74de40d23ff02dafb34carll                                mkexpr(EA), NULL/*this is a load*/) );
6569999ef56da3e4426c5f6bf74de40d23ff02dafb34carll               stmt( stmt_load( res_lo,
6570999ef56da3e4426c5f6bf74de40d23ff02dafb34carll                                binop(Iop_Add64, mkexpr(EA), mkU64(8) ),
6571999ef56da3e4426c5f6bf74de40d23ff02dafb34carll                                NULL/*this is a load*/) );
6572999ef56da3e4426c5f6bf74de40d23ff02dafb34carll	    } else {
6573999ef56da3e4426c5f6bf74de40d23ff02dafb34carll               stmt( stmt_load( res_lo,
6574999ef56da3e4426c5f6bf74de40d23ff02dafb34carll                                mkexpr(EA), NULL/*this is a load*/) );
6575999ef56da3e4426c5f6bf74de40d23ff02dafb34carll               stmt( stmt_load( res_hi,
6576999ef56da3e4426c5f6bf74de40d23ff02dafb34carll                                binop(Iop_Add64, mkexpr(EA), mkU64(8) ),
6577999ef56da3e4426c5f6bf74de40d23ff02dafb34carll                                NULL/*this is a load*/) );
6578999ef56da3e4426c5f6bf74de40d23ff02dafb34carll            }
657978850ae9874a90ea625fcee1fd4c359375b7b538carll         } else {
65801f5fe1fc3a37ca729925e8eec25aa1025b4a6cdbcarll            stmt( stmt_load( res_hi,
65811f5fe1fc3a37ca729925e8eec25aa1025b4a6cdbcarll                             binop( Iop_Add32, mkexpr(EA), mkU32(4) ),
65821f5fe1fc3a37ca729925e8eec25aa1025b4a6cdbcarll                             NULL/*this is a load*/) );
65831f5fe1fc3a37ca729925e8eec25aa1025b4a6cdbcarll            stmt( stmt_load( res_lo,
65841f5fe1fc3a37ca729925e8eec25aa1025b4a6cdbcarll                             binop( Iop_Add32, mkexpr(EA), mkU32(12) ),
65851f5fe1fc3a37ca729925e8eec25aa1025b4a6cdbcarll                             NULL/*this is a load*/) );
658678850ae9874a90ea625fcee1fd4c359375b7b538carll         }
658778850ae9874a90ea625fcee1fd4c359375b7b538carll         putIReg( rD_addr,   mkexpr(res_hi) );
658878850ae9874a90ea625fcee1fd4c359375b7b538carll         putIReg( rD_addr+1, mkexpr(res_lo) );
658978850ae9874a90ea625fcee1fd4c359375b7b538carll         break;
659078850ae9874a90ea625fcee1fd4c359375b7b538carll      }
659178850ae9874a90ea625fcee1fd4c359375b7b538carll
659278850ae9874a90ea625fcee1fd4c359375b7b538carll      case 0x0B6: { // stqcx. (Store QuadWord Condition Indexd, PPC64)
659378850ae9874a90ea625fcee1fd4c359375b7b538carll         // A marginally simplified version of the stwcx. case
659478850ae9874a90ea625fcee1fd4c359375b7b538carll         IRTemp rS_hi = newTemp(ty);
659578850ae9874a90ea625fcee1fd4c359375b7b538carll         IRTemp rS_lo = newTemp(ty);
659678850ae9874a90ea625fcee1fd4c359375b7b538carll         IRTemp resSC;
659778850ae9874a90ea625fcee1fd4c359375b7b538carll         if (b0 != 1) {
659878850ae9874a90ea625fcee1fd4c359375b7b538carll            vex_printf("dis_memsync(ppc)(stqcx.,b0)\n");
659978850ae9874a90ea625fcee1fd4c359375b7b538carll            return False;
660078850ae9874a90ea625fcee1fd4c359375b7b538carll         }
660178850ae9874a90ea625fcee1fd4c359375b7b538carll
660278850ae9874a90ea625fcee1fd4c359375b7b538carll         DIP("stqcx. r%u,r%u,r%u\n", rS_addr, rA_addr, rB_addr);
660378850ae9874a90ea625fcee1fd4c359375b7b538carll
660478850ae9874a90ea625fcee1fd4c359375b7b538carll         // trap if misaligned
660578850ae9874a90ea625fcee1fd4c359375b7b538carll         gen_SIGBUS_if_misaligned( EA, 16 );
660678850ae9874a90ea625fcee1fd4c359375b7b538carll         // Get the data to be stored
660778850ae9874a90ea625fcee1fd4c359375b7b538carll         assign( rS_hi, getIReg(rS_addr) );
660878850ae9874a90ea625fcee1fd4c359375b7b538carll         assign( rS_lo, getIReg(rS_addr+1) );
660978850ae9874a90ea625fcee1fd4c359375b7b538carll
661078850ae9874a90ea625fcee1fd4c359375b7b538carll         // Do the store, and get success/failure bit into resSC
661178850ae9874a90ea625fcee1fd4c359375b7b538carll         resSC = newTemp(Ity_I1);
661278850ae9874a90ea625fcee1fd4c359375b7b538carll
661378850ae9874a90ea625fcee1fd4c359375b7b538carll         if (mode64) {
6614999ef56da3e4426c5f6bf74de40d23ff02dafb34carll            if (host_endness == VexEndnessBE) {
6615999ef56da3e4426c5f6bf74de40d23ff02dafb34carll               stmt( stmt_load( resSC, mkexpr(EA), mkexpr(rS_hi) ) );
6616999ef56da3e4426c5f6bf74de40d23ff02dafb34carll               store( binop( Iop_Add64, mkexpr(EA), mkU64(8) ),
6617999ef56da3e4426c5f6bf74de40d23ff02dafb34carll                      mkexpr(rS_lo) );
6618999ef56da3e4426c5f6bf74de40d23ff02dafb34carll	    } else {
6619999ef56da3e4426c5f6bf74de40d23ff02dafb34carll               stmt( stmt_load( resSC, mkexpr(EA), mkexpr(rS_lo) ) );
6620999ef56da3e4426c5f6bf74de40d23ff02dafb34carll               store( binop( Iop_Add64, mkexpr(EA), mkU64(8) ),
6621999ef56da3e4426c5f6bf74de40d23ff02dafb34carll                      mkexpr(rS_hi) );
6622999ef56da3e4426c5f6bf74de40d23ff02dafb34carll	    }
662378850ae9874a90ea625fcee1fd4c359375b7b538carll         } else {
66241f5fe1fc3a37ca729925e8eec25aa1025b4a6cdbcarll            stmt( stmt_load( resSC, binop( Iop_Add32,
66251f5fe1fc3a37ca729925e8eec25aa1025b4a6cdbcarll                                           mkexpr(EA),
66261f5fe1fc3a37ca729925e8eec25aa1025b4a6cdbcarll                                           mkU32(4) ),
66271f5fe1fc3a37ca729925e8eec25aa1025b4a6cdbcarll                                           mkexpr(rS_hi) ) );
66281f5fe1fc3a37ca729925e8eec25aa1025b4a6cdbcarll            store( binop(Iop_Add32, mkexpr(EA), mkU32(12) ), mkexpr(rS_lo) );
662978850ae9874a90ea625fcee1fd4c359375b7b538carll         }
663078850ae9874a90ea625fcee1fd4c359375b7b538carll
663178850ae9874a90ea625fcee1fd4c359375b7b538carll         // Set CR0[LT GT EQ S0] = 0b000 || XER[SO]  on failure
663278850ae9874a90ea625fcee1fd4c359375b7b538carll         // Set CR0[LT GT EQ S0] = 0b001 || XER[SO]  on success
663378850ae9874a90ea625fcee1fd4c359375b7b538carll         putCR321(0, binop( Iop_Shl8,
663478850ae9874a90ea625fcee1fd4c359375b7b538carll                            unop(Iop_1Uto8, mkexpr(resSC) ),
663578850ae9874a90ea625fcee1fd4c359375b7b538carll                            mkU8(1)));
663678850ae9874a90ea625fcee1fd4c359375b7b538carll         putCR0(0, getXER_SO());
663778850ae9874a90ea625fcee1fd4c359375b7b538carll         break;
663878850ae9874a90ea625fcee1fd4c359375b7b538carll      }
663978850ae9874a90ea625fcee1fd4c359375b7b538carll
6640b85e8bba97fdae7d892f7bfd12e4601307e4721dcerion      default:
66415b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion         vex_printf("dis_memsync(ppc)(opc2)\n");
6642b85e8bba97fdae7d892f7bfd12e4601307e4721dcerion         return False;
6643b85e8bba97fdae7d892f7bfd12e4601307e4721dcerion      }
6644b85e8bba97fdae7d892f7bfd12e4601307e4721dcerion      break;
6645995bc3600091747f64a3ac2d9a7fed6b41c3c88dcerion
6646b85e8bba97fdae7d892f7bfd12e4601307e4721dcerion   default:
66475b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion      vex_printf("dis_memsync(ppc)(opc1)\n");
6648b85e8bba97fdae7d892f7bfd12e4601307e4721dcerion      return False;
6649b85e8bba97fdae7d892f7bfd12e4601307e4721dcerion   }
6650b85e8bba97fdae7d892f7bfd12e4601307e4721dcerion   return True;
66518c3addacc8343f5d1504379e303934f8ed88903ecerion}
66528c3addacc8343f5d1504379e303934f8ed88903ecerion
66538c3addacc8343f5d1504379e303934f8ed88903ecerion
66548c3addacc8343f5d1504379e303934f8ed88903ecerion
66553d870a39e4d145e2f3d9f9a0eeed3475ec934ac1cerion/*
66563d870a39e4d145e2f3d9f9a0eeed3475ec934ac1cerion  Integer Shift Instructions
66573d870a39e4d145e2f3d9f9a0eeed3475ec934ac1cerion*/
6658645c930b1a61f4493ee2d472b34fbb439233a874cerionstatic Bool dis_int_shift ( UInt theInstr )
6659645c930b1a61f4493ee2d472b34fbb439233a874cerion{
6660f0de28cf1a762b0d6f74c93d3532c89a230673bbcerion   /* X-Form, XS-Form */
666176de5cf615380b23b4b5bcced6541233cd4a93a0cerion   UChar opc1    = ifieldOPC(theInstr);
666276de5cf615380b23b4b5bcced6541233cd4a93a0cerion   UChar rS_addr = ifieldRegDS(theInstr);
666376de5cf615380b23b4b5bcced6541233cd4a93a0cerion   UChar rA_addr = ifieldRegA(theInstr);
666476de5cf615380b23b4b5bcced6541233cd4a93a0cerion   UChar rB_addr = ifieldRegB(theInstr);
666576de5cf615380b23b4b5bcced6541233cd4a93a0cerion   UChar sh_imm  = rB_addr;
666676de5cf615380b23b4b5bcced6541233cd4a93a0cerion   UInt  opc2    = ifieldOPClo10(theInstr);
6667f0de28cf1a762b0d6f74c93d3532c89a230673bbcerion   UChar b1      = ifieldBIT1(theInstr);
666876de5cf615380b23b4b5bcced6541233cd4a93a0cerion   UChar flag_rC = ifieldBIT0(theInstr);
666976de5cf615380b23b4b5bcced6541233cd4a93a0cerion
6670d953ebb9b04cbad6891676df597bf0c542b1ec89cerion   IRType  ty         = mode64 ? Ity_I64 : Ity_I32;
6671d953ebb9b04cbad6891676df597bf0c542b1ec89cerion   IRTemp  rA         = newTemp(ty);
667207b07a966a2fdbcf621251a0c1a8ab84807fb120cerion   IRTemp  rS         = newTemp(ty);
667307b07a966a2fdbcf621251a0c1a8ab84807fb120cerion   IRTemp  rB         = newTemp(ty);
6674009230b9758291b594e60d7c0243a73d53e81854sewardj   IRTemp  outofrange = newTemp(Ity_I1);
6675d953ebb9b04cbad6891676df597bf0c542b1ec89cerion   IRTemp  rS_lo32    = newTemp(Ity_I32);
6676d953ebb9b04cbad6891676df597bf0c542b1ec89cerion   IRTemp  rB_lo32    = newTemp(Ity_I32);
6677d953ebb9b04cbad6891676df597bf0c542b1ec89cerion   IRExpr* e_tmp;
6678d953ebb9b04cbad6891676df597bf0c542b1ec89cerion
667907b07a966a2fdbcf621251a0c1a8ab84807fb120cerion   assign( rS, getIReg(rS_addr) );
668007b07a966a2fdbcf621251a0c1a8ab84807fb120cerion   assign( rB, getIReg(rB_addr) );
6681e9d8a26b690c2561ac54ab0cd6ad83ecbadcbe76sewardj   assign( rS_lo32, mkNarrowTo32(ty, mkexpr(rS)) );
6682e9d8a26b690c2561ac54ab0cd6ad83ecbadcbe76sewardj   assign( rB_lo32, mkNarrowTo32(ty, mkexpr(rB)) );
6683b85e8bba97fdae7d892f7bfd12e4601307e4721dcerion
6684b85e8bba97fdae7d892f7bfd12e4601307e4721dcerion   if (opc1 == 0x1F) {
6685b85e8bba97fdae7d892f7bfd12e4601307e4721dcerion      switch (opc2) {
6686d953ebb9b04cbad6891676df597bf0c542b1ec89cerion      case 0x018: { // slw (Shift Left Word, PPC32 p505)
66875b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion         DIP("slw%s r%u,r%u,r%u\n", flag_rC ? ".":"",
668876de5cf615380b23b4b5bcced6541233cd4a93a0cerion             rA_addr, rS_addr, rB_addr);
668976de5cf615380b23b4b5bcced6541233cd4a93a0cerion         /* rA = rS << rB */
669076de5cf615380b23b4b5bcced6541233cd4a93a0cerion         /* ppc32 semantics are:
6691dfb1144e36547976f6493d761051dd4a9e1cf6bfsewardj            slw(x,y) = (x << (y & 31))         -- primary result
6692dfb1144e36547976f6493d761051dd4a9e1cf6bfsewardj                       & ~((y << 26) >>s 31)   -- make result 0
6693dfb1144e36547976f6493d761051dd4a9e1cf6bfsewardj                                                  for y in 32 .. 63
6694dfb1144e36547976f6493d761051dd4a9e1cf6bfsewardj         */
6695d953ebb9b04cbad6891676df597bf0c542b1ec89cerion         e_tmp =
6696d953ebb9b04cbad6891676df597bf0c542b1ec89cerion            binop( Iop_And32,
6697d953ebb9b04cbad6891676df597bf0c542b1ec89cerion               binop( Iop_Shl32,
6698d953ebb9b04cbad6891676df597bf0c542b1ec89cerion                      mkexpr(rS_lo32),
6699d953ebb9b04cbad6891676df597bf0c542b1ec89cerion                      unop( Iop_32to8,
6700d953ebb9b04cbad6891676df597bf0c542b1ec89cerion                            binop(Iop_And32,
6701d953ebb9b04cbad6891676df597bf0c542b1ec89cerion                                  mkexpr(rB_lo32), mkU32(31)))),
6702d953ebb9b04cbad6891676df597bf0c542b1ec89cerion               unop( Iop_Not32,
6703d953ebb9b04cbad6891676df597bf0c542b1ec89cerion                     binop( Iop_Sar32,
6704d953ebb9b04cbad6891676df597bf0c542b1ec89cerion                            binop(Iop_Shl32, mkexpr(rB_lo32), mkU8(26)),
6705d953ebb9b04cbad6891676df597bf0c542b1ec89cerion                            mkU8(31))) );
6706e9d8a26b690c2561ac54ab0cd6ad83ecbadcbe76sewardj         assign( rA, mkWidenFrom32(ty, e_tmp, /* Signed */False) );
6707b85e8bba97fdae7d892f7bfd12e4601307e4721dcerion         break;
6708d953ebb9b04cbad6891676df597bf0c542b1ec89cerion      }
6709d953ebb9b04cbad6891676df597bf0c542b1ec89cerion
67105b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion      case 0x318: { // sraw (Shift Right Alg Word, PPC32 p506)
671107b07a966a2fdbcf621251a0c1a8ab84807fb120cerion         IRTemp sh_amt = newTemp(Ity_I32);
67125b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion         DIP("sraw%s r%u,r%u,r%u\n", flag_rC ? ".":"",
671376de5cf615380b23b4b5bcced6541233cd4a93a0cerion             rA_addr, rS_addr, rB_addr);
671476de5cf615380b23b4b5bcced6541233cd4a93a0cerion         /* JRS: my reading of the (poorly worded) PPC32 doc p506 is:
671576de5cf615380b23b4b5bcced6541233cd4a93a0cerion            amt = rB & 63
671676de5cf615380b23b4b5bcced6541233cd4a93a0cerion            rA = Sar32( rS, amt > 31 ? 31 : amt )
671776de5cf615380b23b4b5bcced6541233cd4a93a0cerion            XER.CA = amt > 31 ? sign-of-rS : (computation as per srawi)
671876de5cf615380b23b4b5bcced6541233cd4a93a0cerion         */
67195b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion         assign( sh_amt, binop(Iop_And32, mkU32(0x3F),
67205b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion                                          mkexpr(rB_lo32)) );
672176de5cf615380b23b4b5bcced6541233cd4a93a0cerion         assign( outofrange,
6722009230b9758291b594e60d7c0243a73d53e81854sewardj                 binop(Iop_CmpLT32U, mkU32(31), mkexpr(sh_amt)) );
6723d953ebb9b04cbad6891676df597bf0c542b1ec89cerion         e_tmp = binop( Iop_Sar32,
6724d953ebb9b04cbad6891676df597bf0c542b1ec89cerion                        mkexpr(rS_lo32),
672520ef5472eac767474c93b7835364a23f24c0ec5dsewardj                        unop( Iop_32to8,
672699dd03e04a6914d90d5fee727d61d76905334becflorian                              IRExpr_ITE( mkexpr(outofrange),
672799dd03e04a6914d90d5fee727d61d76905334becflorian                                          mkU32(31),
672899dd03e04a6914d90d5fee727d61d76905334becflorian                                          mkexpr(sh_amt)) ) );
6729e9d8a26b690c2561ac54ab0cd6ad83ecbadcbe76sewardj         assign( rA, mkWidenFrom32(ty, e_tmp, /* Signed */True) );
67302831b00c4950d6c2b061def05fd67528fe132ececerion
67315b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion         set_XER_CA( ty, PPCG_FLAG_OP_SRAW,
6732f0de28cf1a762b0d6f74c93d3532c89a230673bbcerion                     mkexpr(rA),
6733e9d8a26b690c2561ac54ab0cd6ad83ecbadcbe76sewardj                     mkWidenFrom32(ty, mkexpr(rS_lo32), True),
6734e9d8a26b690c2561ac54ab0cd6ad83ecbadcbe76sewardj                     mkWidenFrom32(ty, mkexpr(sh_amt), True ),
6735e9d8a26b690c2561ac54ab0cd6ad83ecbadcbe76sewardj                     mkWidenFrom32(ty, getXER_CA32(), True) );
6736b85e8bba97fdae7d892f7bfd12e4601307e4721dcerion         break;
673707b07a966a2fdbcf621251a0c1a8ab84807fb120cerion      }
6738b85e8bba97fdae7d892f7bfd12e4601307e4721dcerion
67395b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion      case 0x338: // srawi (Shift Right Alg Word Immediate, PPC32 p507)
67405b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion         DIP("srawi%s r%u,r%u,%d\n", flag_rC ? ".":"",
674176de5cf615380b23b4b5bcced6541233cd4a93a0cerion             rA_addr, rS_addr, sh_imm);
674276de5cf615380b23b4b5bcced6541233cd4a93a0cerion         vassert(sh_imm < 32);
6743f0de28cf1a762b0d6f74c93d3532c89a230673bbcerion         if (mode64) {
6744f0de28cf1a762b0d6f74c93d3532c89a230673bbcerion            assign( rA, binop(Iop_Sar64,
67455b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion                              binop(Iop_Shl64, getIReg(rS_addr),
67465b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion                                               mkU8(32)),
6747f0de28cf1a762b0d6f74c93d3532c89a230673bbcerion                              mkU8(32 + sh_imm)) );
6748f0de28cf1a762b0d6f74c93d3532c89a230673bbcerion         } else {
67495b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion            assign( rA, binop(Iop_Sar32, mkexpr(rS_lo32),
67505b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion                                         mkU8(sh_imm)) );
6751f0de28cf1a762b0d6f74c93d3532c89a230673bbcerion         }
67522831b00c4950d6c2b061def05fd67528fe132ececerion
67535b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion         set_XER_CA( ty, PPCG_FLAG_OP_SRAWI,
6754f0de28cf1a762b0d6f74c93d3532c89a230673bbcerion                     mkexpr(rA),
6755e9d8a26b690c2561ac54ab0cd6ad83ecbadcbe76sewardj                     mkWidenFrom32(ty, mkexpr(rS_lo32), /* Syned */True),
6756f0de28cf1a762b0d6f74c93d3532c89a230673bbcerion                     mkSzImm(ty, sh_imm),
6757e9d8a26b690c2561ac54ab0cd6ad83ecbadcbe76sewardj                     mkWidenFrom32(ty, getXER_CA32(), /* Syned */False) );
6758b85e8bba97fdae7d892f7bfd12e4601307e4721dcerion         break;
6759b85e8bba97fdae7d892f7bfd12e4601307e4721dcerion
6760e9d361ab43518b6dfbd3d846f48859534659dee0cerion      case 0x218: // srw (Shift Right Word, PPC32 p508)
67615b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion         DIP("srw%s r%u,r%u,r%u\n", flag_rC ? ".":"",
676276de5cf615380b23b4b5bcced6541233cd4a93a0cerion             rA_addr, rS_addr, rB_addr);
676376de5cf615380b23b4b5bcced6541233cd4a93a0cerion         /* rA = rS >>u rB */
676476de5cf615380b23b4b5bcced6541233cd4a93a0cerion         /* ppc32 semantics are:
6765f0de28cf1a762b0d6f74c93d3532c89a230673bbcerion            srw(x,y) = (x >>u (y & 31))        -- primary result
6766dfb1144e36547976f6493d761051dd4a9e1cf6bfsewardj                       & ~((y << 26) >>s 31)   -- make result 0
6767dfb1144e36547976f6493d761051dd4a9e1cf6bfsewardj                                                  for y in 32 .. 63
6768dfb1144e36547976f6493d761051dd4a9e1cf6bfsewardj         */
6769d953ebb9b04cbad6891676df597bf0c542b1ec89cerion         e_tmp =
6770dfb1144e36547976f6493d761051dd4a9e1cf6bfsewardj            binop(
6771dfb1144e36547976f6493d761051dd4a9e1cf6bfsewardj               Iop_And32,
6772dfb1144e36547976f6493d761051dd4a9e1cf6bfsewardj               binop( Iop_Shr32,
6773d953ebb9b04cbad6891676df597bf0c542b1ec89cerion                      mkexpr(rS_lo32),
6774dfb1144e36547976f6493d761051dd4a9e1cf6bfsewardj                      unop( Iop_32to8,
67755b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion                            binop(Iop_And32, mkexpr(rB_lo32),
67765b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion                                             mkU32(31)))),
6777dfb1144e36547976f6493d761051dd4a9e1cf6bfsewardj               unop( Iop_Not32,
6778dfb1144e36547976f6493d761051dd4a9e1cf6bfsewardj                     binop( Iop_Sar32,
67795b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion                            binop(Iop_Shl32, mkexpr(rB_lo32),
67805b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion                                             mkU8(26)),
6781d953ebb9b04cbad6891676df597bf0c542b1ec89cerion                            mkU8(31))));
6782e9d8a26b690c2561ac54ab0cd6ad83ecbadcbe76sewardj         assign( rA, mkWidenFrom32(ty, e_tmp, /* Signed */False) );
6783b85e8bba97fdae7d892f7bfd12e4601307e4721dcerion         break;
6784f0de28cf1a762b0d6f74c93d3532c89a230673bbcerion
6785f0de28cf1a762b0d6f74c93d3532c89a230673bbcerion
6786f0de28cf1a762b0d6f74c93d3532c89a230673bbcerion      /* 64bit Shifts */
67875b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion      case 0x01B: // sld (Shift Left DWord, PPC64 p568)
67885b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion         DIP("sld%s r%u,r%u,r%u\n",
67895b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion             flag_rC ? ".":"", rA_addr, rS_addr, rB_addr);
6790f0de28cf1a762b0d6f74c93d3532c89a230673bbcerion         /* rA = rS << rB */
679107b07a966a2fdbcf621251a0c1a8ab84807fb120cerion         /* ppc64 semantics are:
6792f0de28cf1a762b0d6f74c93d3532c89a230673bbcerion            slw(x,y) = (x << (y & 63))         -- primary result
6793f0de28cf1a762b0d6f74c93d3532c89a230673bbcerion                       & ~((y << 57) >>s 63)   -- make result 0
6794f0de28cf1a762b0d6f74c93d3532c89a230673bbcerion                                                  for y in 64 ..
6795f0de28cf1a762b0d6f74c93d3532c89a230673bbcerion         */
6796f0de28cf1a762b0d6f74c93d3532c89a230673bbcerion         assign( rA,
6797f0de28cf1a762b0d6f74c93d3532c89a230673bbcerion            binop(
6798f0de28cf1a762b0d6f74c93d3532c89a230673bbcerion               Iop_And64,
6799f0de28cf1a762b0d6f74c93d3532c89a230673bbcerion               binop( Iop_Shl64,
6800f0de28cf1a762b0d6f74c93d3532c89a230673bbcerion                      mkexpr(rS),
6801f0de28cf1a762b0d6f74c93d3532c89a230673bbcerion                      unop( Iop_64to8,
6802f0de28cf1a762b0d6f74c93d3532c89a230673bbcerion                            binop(Iop_And64, mkexpr(rB), mkU64(63)))),
6803f0de28cf1a762b0d6f74c93d3532c89a230673bbcerion               unop( Iop_Not64,
6804f0de28cf1a762b0d6f74c93d3532c89a230673bbcerion                     binop( Iop_Sar64,
6805f0de28cf1a762b0d6f74c93d3532c89a230673bbcerion                            binop(Iop_Shl64, mkexpr(rB), mkU8(57)),
6806f0de28cf1a762b0d6f74c93d3532c89a230673bbcerion                            mkU8(63)))) );
680707b07a966a2fdbcf621251a0c1a8ab84807fb120cerion         break;
6808f0de28cf1a762b0d6f74c93d3532c89a230673bbcerion
68095b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion      case 0x31A: { // srad (Shift Right Alg DWord, PPC64 p570)
681007b07a966a2fdbcf621251a0c1a8ab84807fb120cerion         IRTemp sh_amt = newTemp(Ity_I64);
68115b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion         DIP("srad%s r%u,r%u,r%u\n",
68125b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion             flag_rC ? ".":"", rA_addr, rS_addr, rB_addr);
6813f0de28cf1a762b0d6f74c93d3532c89a230673bbcerion         /* amt = rB & 127
6814f0de28cf1a762b0d6f74c93d3532c89a230673bbcerion            rA = Sar64( rS, amt > 63 ? 63 : amt )
6815f0de28cf1a762b0d6f74c93d3532c89a230673bbcerion            XER.CA = amt > 63 ? sign-of-rS : (computation as per srawi)
6816f0de28cf1a762b0d6f74c93d3532c89a230673bbcerion         */
681707b07a966a2fdbcf621251a0c1a8ab84807fb120cerion         assign( sh_amt, binop(Iop_And64, mkU64(0x7F), mkexpr(rB)) );
6818f0de28cf1a762b0d6f74c93d3532c89a230673bbcerion         assign( outofrange,
6819009230b9758291b594e60d7c0243a73d53e81854sewardj                 binop(Iop_CmpLT64U, mkU64(63), mkexpr(sh_amt)) );
6820f0de28cf1a762b0d6f74c93d3532c89a230673bbcerion         assign( rA,
6821f0de28cf1a762b0d6f74c93d3532c89a230673bbcerion                 binop( Iop_Sar64,
6822f0de28cf1a762b0d6f74c93d3532c89a230673bbcerion                        mkexpr(rS),
6823f0de28cf1a762b0d6f74c93d3532c89a230673bbcerion                        unop( Iop_64to8,
682499dd03e04a6914d90d5fee727d61d76905334becflorian                              IRExpr_ITE( mkexpr(outofrange),
682599dd03e04a6914d90d5fee727d61d76905334becflorian                                          mkU64(63),
682699dd03e04a6914d90d5fee727d61d76905334becflorian                                          mkexpr(sh_amt)) ))
6827f0de28cf1a762b0d6f74c93d3532c89a230673bbcerion               );
68285b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion         set_XER_CA( ty, PPCG_FLAG_OP_SRAD,
682907b07a966a2fdbcf621251a0c1a8ab84807fb120cerion                     mkexpr(rA), mkexpr(rS), mkexpr(sh_amt),
6830e9d8a26b690c2561ac54ab0cd6ad83ecbadcbe76sewardj                     mkWidenFrom32(ty, getXER_CA32(), /* Syned */False) );
683107b07a966a2fdbcf621251a0c1a8ab84807fb120cerion         break;
683207b07a966a2fdbcf621251a0c1a8ab84807fb120cerion      }
683307b07a966a2fdbcf621251a0c1a8ab84807fb120cerion
68345b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion      case 0x33A: case 0x33B: // sradi (Shr Alg DWord Imm, PPC64 p571)
6835f0de28cf1a762b0d6f74c93d3532c89a230673bbcerion         sh_imm |= b1<<5;
6836f0de28cf1a762b0d6f74c93d3532c89a230673bbcerion         vassert(sh_imm < 64);
68375b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion         DIP("sradi%s r%u,r%u,%u\n",
68385b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion             flag_rC ? ".":"", rA_addr, rS_addr, sh_imm);
6839f0de28cf1a762b0d6f74c93d3532c89a230673bbcerion         assign( rA, binop(Iop_Sar64, getIReg(rS_addr), mkU8(sh_imm)) );
6840f0de28cf1a762b0d6f74c93d3532c89a230673bbcerion
68415b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion         set_XER_CA( ty, PPCG_FLAG_OP_SRADI,
6842f0de28cf1a762b0d6f74c93d3532c89a230673bbcerion                     mkexpr(rA),
6843f0de28cf1a762b0d6f74c93d3532c89a230673bbcerion                     getIReg(rS_addr),
6844f0de28cf1a762b0d6f74c93d3532c89a230673bbcerion                     mkU64(sh_imm),
6845e9d8a26b690c2561ac54ab0cd6ad83ecbadcbe76sewardj                     mkWidenFrom32(ty, getXER_CA32(), /* Syned */False) );
6846f0de28cf1a762b0d6f74c93d3532c89a230673bbcerion         break;
6847f0de28cf1a762b0d6f74c93d3532c89a230673bbcerion
68485b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion      case 0x21B: // srd (Shift Right DWord, PPC64 p574)
68495b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion         DIP("srd%s r%u,r%u,r%u\n",
68505b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion             flag_rC ? ".":"", rA_addr, rS_addr, rB_addr);
6851f0de28cf1a762b0d6f74c93d3532c89a230673bbcerion         /* rA = rS >>u rB */
685207b07a966a2fdbcf621251a0c1a8ab84807fb120cerion         /* ppc semantics are:
6853f0de28cf1a762b0d6f74c93d3532c89a230673bbcerion            srw(x,y) = (x >>u (y & 63))        -- primary result
6854f0de28cf1a762b0d6f74c93d3532c89a230673bbcerion                       & ~((y << 57) >>s 63)   -- make result 0
6855f0de28cf1a762b0d6f74c93d3532c89a230673bbcerion                                                  for y in 64 .. 127
6856f0de28cf1a762b0d6f74c93d3532c89a230673bbcerion         */
6857f0de28cf1a762b0d6f74c93d3532c89a230673bbcerion         assign( rA,
6858f0de28cf1a762b0d6f74c93d3532c89a230673bbcerion            binop(
6859f0de28cf1a762b0d6f74c93d3532c89a230673bbcerion               Iop_And64,
6860f0de28cf1a762b0d6f74c93d3532c89a230673bbcerion               binop( Iop_Shr64,
6861f0de28cf1a762b0d6f74c93d3532c89a230673bbcerion                      mkexpr(rS),
6862f0de28cf1a762b0d6f74c93d3532c89a230673bbcerion                      unop( Iop_64to8,
6863f0de28cf1a762b0d6f74c93d3532c89a230673bbcerion                            binop(Iop_And64, mkexpr(rB), mkU64(63)))),
6864f0de28cf1a762b0d6f74c93d3532c89a230673bbcerion               unop( Iop_Not64,
6865f0de28cf1a762b0d6f74c93d3532c89a230673bbcerion                     binop( Iop_Sar64,
6866f0de28cf1a762b0d6f74c93d3532c89a230673bbcerion                            binop(Iop_Shl64, mkexpr(rB), mkU8(57)),
6867f0de28cf1a762b0d6f74c93d3532c89a230673bbcerion                            mkU8(63)))) );
686807b07a966a2fdbcf621251a0c1a8ab84807fb120cerion         break;
6869f0de28cf1a762b0d6f74c93d3532c89a230673bbcerion
6870b85e8bba97fdae7d892f7bfd12e4601307e4721dcerion      default:
68715b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion         vex_printf("dis_int_shift(ppc)(opc2)\n");
6872b85e8bba97fdae7d892f7bfd12e4601307e4721dcerion         return False;
6873b85e8bba97fdae7d892f7bfd12e4601307e4721dcerion      }
6874b85e8bba97fdae7d892f7bfd12e4601307e4721dcerion   } else {
68755b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion      vex_printf("dis_int_shift(ppc)(opc1)\n");
6876b85e8bba97fdae7d892f7bfd12e4601307e4721dcerion      return False;
6877b85e8bba97fdae7d892f7bfd12e4601307e4721dcerion   }
68780d330c5a910b71c8f4b2ec149d1a88a06acd784bcerion
687976de5cf615380b23b4b5bcced6541233cd4a93a0cerion   putIReg( rA_addr, mkexpr(rA) );
6880b85e8bba97fdae7d892f7bfd12e4601307e4721dcerion
688176de5cf615380b23b4b5bcced6541233cd4a93a0cerion   if (flag_rC) {
688276de5cf615380b23b4b5bcced6541233cd4a93a0cerion      set_CR0( mkexpr(rA) );
6883b85e8bba97fdae7d892f7bfd12e4601307e4721dcerion   }
6884b85e8bba97fdae7d892f7bfd12e4601307e4721dcerion   return True;
6885645c930b1a61f4493ee2d472b34fbb439233a874cerion}
6886645c930b1a61f4493ee2d472b34fbb439233a874cerion
6887645c930b1a61f4493ee2d472b34fbb439233a874cerion
6888645c930b1a61f4493ee2d472b34fbb439233a874cerion
6889602857d30b8aa87c202517e2be6c7df6d40ee922sewardj/*
6890602857d30b8aa87c202517e2be6c7df6d40ee922sewardj  Integer Load/Store Reverse Instructions
6891602857d30b8aa87c202517e2be6c7df6d40ee922sewardj*/
689240d8c09304469b6d1a03c7840d5c33d174b64c1csewardj/* Generates code to swap the byte order in an Ity_I32. */
6893fb957970740ff6c1a21020e6716ab9e25852fec2sewardjstatic IRExpr* /* :: Ity_I32 */ gen_byterev32 ( IRTemp t )
6894fb957970740ff6c1a21020e6716ab9e25852fec2sewardj{
6895dd40fdf58cc8a6fe9466c4f00bdfc9fe9bf00449sewardj   vassert(typeOfIRTemp(irsb->tyenv, t) == Ity_I32);
6896fb957970740ff6c1a21020e6716ab9e25852fec2sewardj   return
6897fb957970740ff6c1a21020e6716ab9e25852fec2sewardj      binop(Iop_Or32,
6898fb957970740ff6c1a21020e6716ab9e25852fec2sewardj         binop(Iop_Shl32, mkexpr(t), mkU8(24)),
6899fb957970740ff6c1a21020e6716ab9e25852fec2sewardj      binop(Iop_Or32,
6900fb957970740ff6c1a21020e6716ab9e25852fec2sewardj         binop(Iop_And32, binop(Iop_Shl32, mkexpr(t), mkU8(8)),
6901fb957970740ff6c1a21020e6716ab9e25852fec2sewardj                          mkU32(0x00FF0000)),
6902fb957970740ff6c1a21020e6716ab9e25852fec2sewardj      binop(Iop_Or32,
6903fb957970740ff6c1a21020e6716ab9e25852fec2sewardj         binop(Iop_And32, binop(Iop_Shr32, mkexpr(t), mkU8(8)),
6904fb957970740ff6c1a21020e6716ab9e25852fec2sewardj                          mkU32(0x0000FF00)),
6905fb957970740ff6c1a21020e6716ab9e25852fec2sewardj         binop(Iop_And32, binop(Iop_Shr32, mkexpr(t), mkU8(24)),
6906fb957970740ff6c1a21020e6716ab9e25852fec2sewardj                          mkU32(0x000000FF) )
6907fb957970740ff6c1a21020e6716ab9e25852fec2sewardj      )));
6908fb957970740ff6c1a21020e6716ab9e25852fec2sewardj}
6909fb957970740ff6c1a21020e6716ab9e25852fec2sewardj
691040d8c09304469b6d1a03c7840d5c33d174b64c1csewardj/* Generates code to swap the byte order in the lower half of an Ity_I32,
691140d8c09304469b6d1a03c7840d5c33d174b64c1csewardj   and zeroes the upper half. */
691240d8c09304469b6d1a03c7840d5c33d174b64c1csewardjstatic IRExpr* /* :: Ity_I32 */ gen_byterev16 ( IRTemp t )
691340d8c09304469b6d1a03c7840d5c33d174b64c1csewardj{
6914dd40fdf58cc8a6fe9466c4f00bdfc9fe9bf00449sewardj   vassert(typeOfIRTemp(irsb->tyenv, t) == Ity_I32);
691540d8c09304469b6d1a03c7840d5c33d174b64c1csewardj   return
691640d8c09304469b6d1a03c7840d5c33d174b64c1csewardj      binop(Iop_Or32,
691740d8c09304469b6d1a03c7840d5c33d174b64c1csewardj         binop(Iop_And32, binop(Iop_Shl32, mkexpr(t), mkU8(8)),
691840d8c09304469b6d1a03c7840d5c33d174b64c1csewardj                          mkU32(0x0000FF00)),
691940d8c09304469b6d1a03c7840d5c33d174b64c1csewardj         binop(Iop_And32, binop(Iop_Shr32, mkexpr(t), mkU8(8)),
692040d8c09304469b6d1a03c7840d5c33d174b64c1csewardj                          mkU32(0x000000FF))
692140d8c09304469b6d1a03c7840d5c33d174b64c1csewardj      );
692240d8c09304469b6d1a03c7840d5c33d174b64c1csewardj}
692340d8c09304469b6d1a03c7840d5c33d174b64c1csewardj
6924602857d30b8aa87c202517e2be6c7df6d40ee922sewardjstatic Bool dis_int_ldst_rev ( UInt theInstr )
6925602857d30b8aa87c202517e2be6c7df6d40ee922sewardj{
6926602857d30b8aa87c202517e2be6c7df6d40ee922sewardj   /* X-Form */
692776de5cf615380b23b4b5bcced6541233cd4a93a0cerion   UChar opc1    = ifieldOPC(theInstr);
692876de5cf615380b23b4b5bcced6541233cd4a93a0cerion   UChar rD_addr = ifieldRegDS(theInstr);
692976de5cf615380b23b4b5bcced6541233cd4a93a0cerion   UChar rS_addr = rD_addr;
693076de5cf615380b23b4b5bcced6541233cd4a93a0cerion   UChar rA_addr = ifieldRegA(theInstr);
693176de5cf615380b23b4b5bcced6541233cd4a93a0cerion   UChar rB_addr = ifieldRegB(theInstr);
693276de5cf615380b23b4b5bcced6541233cd4a93a0cerion   UInt  opc2    = ifieldOPClo10(theInstr);
693376de5cf615380b23b4b5bcced6541233cd4a93a0cerion   UChar b0      = ifieldBIT0(theInstr);
6934edf7fc572e2decb93e9143961e8739c8fe18899dcerion
6935d953ebb9b04cbad6891676df597bf0c542b1ec89cerion   IRType ty = mode64 ? Ity_I64 : Ity_I32;
6936d953ebb9b04cbad6891676df597bf0c542b1ec89cerion   IRTemp EA = newTemp(ty);
6937edf7fc572e2decb93e9143961e8739c8fe18899dcerion   IRTemp w1 = newTemp(Ity_I32);
6938edf7fc572e2decb93e9143961e8739c8fe18899dcerion   IRTemp w2 = newTemp(Ity_I32);
6939602857d30b8aa87c202517e2be6c7df6d40ee922sewardj
6940602857d30b8aa87c202517e2be6c7df6d40ee922sewardj   if (opc1 != 0x1F || b0 != 0) {
69415b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion      vex_printf("dis_int_ldst_rev(ppc)(opc1|b0)\n");
6942602857d30b8aa87c202517e2be6c7df6d40ee922sewardj      return False;
6943602857d30b8aa87c202517e2be6c7df6d40ee922sewardj   }
6944afe85831d73e546e483dfc51964409b7ecd7c5fesewardj
6945d953ebb9b04cbad6891676df597bf0c542b1ec89cerion   assign( EA, ea_rAor0_idxd( rA_addr, rB_addr ) );
6946602857d30b8aa87c202517e2be6c7df6d40ee922sewardj
6947602857d30b8aa87c202517e2be6c7df6d40ee922sewardj   switch (opc2) {
694840d8c09304469b6d1a03c7840d5c33d174b64c1csewardj
694940d8c09304469b6d1a03c7840d5c33d174b64c1csewardj      case 0x316: // lhbrx (Load Halfword Byte-Reverse Indexed, PPC32 p449)
695040d8c09304469b6d1a03c7840d5c33d174b64c1csewardj         DIP("lhbrx r%u,r%u,r%u\n", rD_addr, rA_addr, rB_addr);
69511f5fe1fc3a37ca729925e8eec25aa1025b4a6cdbcarll         assign( w1, unop(Iop_16Uto32, load(Ity_I16, mkexpr(EA))) );
695240d8c09304469b6d1a03c7840d5c33d174b64c1csewardj         assign( w2, gen_byterev16(w1) );
6953e9d8a26b690c2561ac54ab0cd6ad83ecbadcbe76sewardj         putIReg( rD_addr, mkWidenFrom32(ty, mkexpr(w2),
6954e9d8a26b690c2561ac54ab0cd6ad83ecbadcbe76sewardj                                         /* Signed */False) );
695540d8c09304469b6d1a03c7840d5c33d174b64c1csewardj         break;
695640d8c09304469b6d1a03c7840d5c33d174b64c1csewardj
6957fb957970740ff6c1a21020e6716ab9e25852fec2sewardj      case 0x216: // lwbrx (Load Word Byte-Reverse Indexed, PPC32 p459)
6958d953ebb9b04cbad6891676df597bf0c542b1ec89cerion         DIP("lwbrx r%u,r%u,r%u\n", rD_addr, rA_addr, rB_addr);
69591f5fe1fc3a37ca729925e8eec25aa1025b4a6cdbcarll         assign( w1, load(Ity_I32, mkexpr(EA)) );
6960fb957970740ff6c1a21020e6716ab9e25852fec2sewardj         assign( w2, gen_byterev32(w1) );
6961e9d8a26b690c2561ac54ab0cd6ad83ecbadcbe76sewardj         putIReg( rD_addr, mkWidenFrom32(ty, mkexpr(w2),
6962e9d8a26b690c2561ac54ab0cd6ad83ecbadcbe76sewardj                                         /* Signed */False) );
6963fb957970740ff6c1a21020e6716ab9e25852fec2sewardj         break;
696466d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj
696566d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj      case 0x214: // ldbrx (Load Doubleword Byte-Reverse Indexed)
696666d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj      {
696766d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj         IRExpr * nextAddr;
696866d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj         IRTemp w3 = newTemp( Ity_I32 );
696966d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj         IRTemp w4 = newTemp( Ity_I32 );
697066d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj         DIP("ldbrx r%u,r%u,r%u\n", rD_addr, rA_addr, rB_addr);
69711f5fe1fc3a37ca729925e8eec25aa1025b4a6cdbcarll         assign( w1, load( Ity_I32, mkexpr( EA ) ) );
697266d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj         assign( w2, gen_byterev32( w1 ) );
697366d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj         nextAddr = binop( mkSzOp( ty, Iop_Add8 ), mkexpr( EA ),
697466d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj                           ty == Ity_I64 ? mkU64( 4 ) : mkU32( 4 ) );
69751f5fe1fc3a37ca729925e8eec25aa1025b4a6cdbcarll         assign( w3, load( Ity_I32, nextAddr ) );
697666d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj         assign( w4, gen_byterev32( w3 ) );
69771f5fe1fc3a37ca729925e8eec25aa1025b4a6cdbcarll         if (host_endness == VexEndnessLE)
69781f5fe1fc3a37ca729925e8eec25aa1025b4a6cdbcarll            putIReg( rD_addr, binop( Iop_32HLto64, mkexpr( w2 ), mkexpr( w4 ) ) );
69791f5fe1fc3a37ca729925e8eec25aa1025b4a6cdbcarll         else
69801f5fe1fc3a37ca729925e8eec25aa1025b4a6cdbcarll            putIReg( rD_addr, binop( Iop_32HLto64, mkexpr( w4 ), mkexpr( w2 ) ) );
698166d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj         break;
698266d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj      }
698366d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj
6984413a468a761b63846e805c0987b07c4d7a28cf12sewardj      case 0x396: // sthbrx (Store Half Word Byte-Reverse Indexed, PPC32 p523)
6985413a468a761b63846e805c0987b07c4d7a28cf12sewardj         DIP("sthbrx r%u,r%u,r%u\n", rS_addr, rA_addr, rB_addr);
6986e9d8a26b690c2561ac54ab0cd6ad83ecbadcbe76sewardj         assign( w1, mkNarrowTo32(ty, getIReg(rS_addr)) );
69871f5fe1fc3a37ca729925e8eec25aa1025b4a6cdbcarll         store( mkexpr(EA), unop(Iop_32to16, gen_byterev16(w1)) );
6988413a468a761b63846e805c0987b07c4d7a28cf12sewardj         break;
6989602857d30b8aa87c202517e2be6c7df6d40ee922sewardj
69905b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion      case 0x296: // stwbrx (Store Word Byte-Reverse Indxd, PPC32 p531)
6991d953ebb9b04cbad6891676df597bf0c542b1ec89cerion         DIP("stwbrx r%u,r%u,r%u\n", rS_addr, rA_addr, rB_addr);
6992e9d8a26b690c2561ac54ab0cd6ad83ecbadcbe76sewardj         assign( w1, mkNarrowTo32(ty, getIReg(rS_addr)) );
69931f5fe1fc3a37ca729925e8eec25aa1025b4a6cdbcarll         store( mkexpr(EA), gen_byterev32(w1) );
6994fb957970740ff6c1a21020e6716ab9e25852fec2sewardj         break;
69954aa412af1d8166cc11f39a6e721df49431d23618sewardj
69964aa412af1d8166cc11f39a6e721df49431d23618sewardj      case 0x294: // stdbrx (Store Doubleword Byte-Reverse Indexed)
69974aa412af1d8166cc11f39a6e721df49431d23618sewardj      {
69984aa412af1d8166cc11f39a6e721df49431d23618sewardj         IRTemp lo = newTemp(Ity_I32);
69994aa412af1d8166cc11f39a6e721df49431d23618sewardj         IRTemp hi = newTemp(Ity_I32);
70004aa412af1d8166cc11f39a6e721df49431d23618sewardj         IRTemp rS = newTemp(Ity_I64);
70014aa412af1d8166cc11f39a6e721df49431d23618sewardj         assign( rS, getIReg( rS_addr ) );
70024aa412af1d8166cc11f39a6e721df49431d23618sewardj         DIP("stdbrx r%u,r%u,r%u\n", rS_addr, rA_addr, rB_addr);
70034aa412af1d8166cc11f39a6e721df49431d23618sewardj         assign(lo, unop(Iop_64HIto32, mkexpr(rS)));
70044aa412af1d8166cc11f39a6e721df49431d23618sewardj         assign(hi, unop(Iop_64to32, mkexpr(rS)));
70051f5fe1fc3a37ca729925e8eec25aa1025b4a6cdbcarll         store( mkexpr( EA ),
70061f5fe1fc3a37ca729925e8eec25aa1025b4a6cdbcarll                binop( Iop_32HLto64, gen_byterev32( hi ),
70071f5fe1fc3a37ca729925e8eec25aa1025b4a6cdbcarll                       gen_byterev32( lo ) ) );
70084aa412af1d8166cc11f39a6e721df49431d23618sewardj         break;
70094aa412af1d8166cc11f39a6e721df49431d23618sewardj      }
70104aa412af1d8166cc11f39a6e721df49431d23618sewardj
7011fb957970740ff6c1a21020e6716ab9e25852fec2sewardj      default:
70125b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion         vex_printf("dis_int_ldst_rev(ppc)(opc2)\n");
7013fb957970740ff6c1a21020e6716ab9e25852fec2sewardj         return False;
7014602857d30b8aa87c202517e2be6c7df6d40ee922sewardj   }
7015602857d30b8aa87c202517e2be6c7df6d40ee922sewardj   return True;
7016602857d30b8aa87c202517e2be6c7df6d40ee922sewardj}
7017645c930b1a61f4493ee2d472b34fbb439233a874cerion
7018645c930b1a61f4493ee2d472b34fbb439233a874cerion
7019645c930b1a61f4493ee2d472b34fbb439233a874cerion
70203d870a39e4d145e2f3d9f9a0eeed3475ec934ac1cerion/*
70213d870a39e4d145e2f3d9f9a0eeed3475ec934ac1cerion  Processor Control Instructions
70223d870a39e4d145e2f3d9f9a0eeed3475ec934ac1cerion*/
7023cacba8e675988fbf21b08feea1f317a9c896c053florianstatic Bool dis_proc_ctl ( const VexAbiInfo* vbi, UInt theInstr )
70248c3addacc8343f5d1504379e303934f8ed88903ecerion{
702576de5cf615380b23b4b5bcced6541233cd4a93a0cerion   UChar opc1     = ifieldOPC(theInstr);
7026b85e8bba97fdae7d892f7bfd12e4601307e4721dcerion
7027b85e8bba97fdae7d892f7bfd12e4601307e4721dcerion   /* X-Form */
702876de5cf615380b23b4b5bcced6541233cd4a93a0cerion   UChar crfD     = toUChar( IFIELD( theInstr, 23, 3 ) );
702976de5cf615380b23b4b5bcced6541233cd4a93a0cerion   UChar b21to22  = toUChar( IFIELD( theInstr, 21, 2 ) );
703076de5cf615380b23b4b5bcced6541233cd4a93a0cerion   UChar rD_addr  = ifieldRegDS(theInstr);
703176de5cf615380b23b4b5bcced6541233cd4a93a0cerion   UInt  b11to20  = IFIELD( theInstr, 11, 10 );
703276de5cf615380b23b4b5bcced6541233cd4a93a0cerion
7033b85e8bba97fdae7d892f7bfd12e4601307e4721dcerion   /* XFX-Form */
703476de5cf615380b23b4b5bcced6541233cd4a93a0cerion   UChar rS_addr  = rD_addr;
703576de5cf615380b23b4b5bcced6541233cd4a93a0cerion   UInt  SPR      = b11to20;
7036edf7fc572e2decb93e9143961e8739c8fe18899dcerion   UInt  TBR      = b11to20;
703776de5cf615380b23b4b5bcced6541233cd4a93a0cerion   UChar b20      = toUChar( IFIELD( theInstr, 20, 1 ) );
703876de5cf615380b23b4b5bcced6541233cd4a93a0cerion   UInt  CRM      = IFIELD( theInstr, 12, 8 );
703976de5cf615380b23b4b5bcced6541233cd4a93a0cerion   UChar b11      = toUChar( IFIELD( theInstr, 11, 1 ) );
7040e9d361ab43518b6dfbd3d846f48859534659dee0cerion
704176de5cf615380b23b4b5bcced6541233cd4a93a0cerion   UInt  opc2     = ifieldOPClo10(theInstr);
704276de5cf615380b23b4b5bcced6541233cd4a93a0cerion   UChar b0       = ifieldBIT0(theInstr);
704376de5cf615380b23b4b5bcced6541233cd4a93a0cerion
70442831b00c4950d6c2b061def05fd67528fe132ececerion   IRType ty = mode64 ? Ity_I64 : Ity_I32;
7045f0de28cf1a762b0d6f74c93d3532c89a230673bbcerion   IRTemp rS = newTemp(ty);
7046d953ebb9b04cbad6891676df597bf0c542b1ec89cerion   assign( rS, getIReg(rS_addr) );
704741a7b70f888cf73cf3da6a53b31937ce0d26e8f4sewardj
704876de5cf615380b23b4b5bcced6541233cd4a93a0cerion   /* Reorder SPR field as per PPC32 p470 */
704976de5cf615380b23b4b5bcced6541233cd4a93a0cerion   SPR = ((SPR & 0x1F) << 5) | ((SPR >> 5) & 0x1F);
705073a9197285975856fd3cc577216237afb3612b09sewardj   /* Reorder TBR field as per PPC32 p475 */
705173a9197285975856fd3cc577216237afb3612b09sewardj   TBR = ((TBR & 31) << 5) | ((TBR >> 5) & 31);
7052b85e8bba97fdae7d892f7bfd12e4601307e4721dcerion
705348ae46b56cef87c90638b25d6b2462c475033da8carll   /* b0 = 0, inst is treated as floating point inst for reservation purposes
705448ae46b56cef87c90638b25d6b2462c475033da8carll    * b0 = 1, inst is treated as vector inst for reservation purposes
705548ae46b56cef87c90638b25d6b2462c475033da8carll    */
705648ae46b56cef87c90638b25d6b2462c475033da8carll   if (opc1 != 0x1F) {
705748ae46b56cef87c90638b25d6b2462c475033da8carll      vex_printf("dis_proc_ctl(ppc)(opc1|b%d)\n", b0);
7058b85e8bba97fdae7d892f7bfd12e4601307e4721dcerion      return False;
7059b85e8bba97fdae7d892f7bfd12e4601307e4721dcerion   }
7060b85e8bba97fdae7d892f7bfd12e4601307e4721dcerion
7061b85e8bba97fdae7d892f7bfd12e4601307e4721dcerion   switch (opc2) {
7062cb14e73e1556145a29ae2c8f4f7ab73cf2963864cerion   /* X-Form */
70635b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion   case 0x200: { // mcrxr (Move to Cond Register from XER, PPC32 p466)
7064cb14e73e1556145a29ae2c8f4f7ab73cf2963864cerion      if (b21to22 != 0 || b11to20 != 0) {
70655b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion         vex_printf("dis_proc_ctl(ppc)(mcrxr,b21to22|b11to20)\n");
7066cb14e73e1556145a29ae2c8f4f7ab73cf2963864cerion         return False;
7067cb14e73e1556145a29ae2c8f4f7ab73cf2963864cerion      }
7068cb14e73e1556145a29ae2c8f4f7ab73cf2963864cerion      DIP("mcrxr crf%d\n", crfD);
7069edf7fc572e2decb93e9143961e8739c8fe18899dcerion      /* Move XER[0-3] (the top 4 bits of XER) to CR[crfD] */
7070d953ebb9b04cbad6891676df597bf0c542b1ec89cerion      putGST_field( PPC_GST_CR,
7071d953ebb9b04cbad6891676df597bf0c542b1ec89cerion                    getGST_field( PPC_GST_XER, 7 ),
7072edf7fc572e2decb93e9143961e8739c8fe18899dcerion                    crfD );
707355ccc3ea848c351639321085df6a41cf6149d030sewardj
707455ccc3ea848c351639321085df6a41cf6149d030sewardj      // Clear XER[0-3]
7075edf7fc572e2decb93e9143961e8739c8fe18899dcerion      putXER_SO( mkU8(0) );
7076edf7fc572e2decb93e9143961e8739c8fe18899dcerion      putXER_OV( mkU8(0) );
7077edf7fc572e2decb93e9143961e8739c8fe18899dcerion      putXER_CA( mkU8(0) );
7078cb14e73e1556145a29ae2c8f4f7ab73cf2963864cerion      break;
707955ccc3ea848c351639321085df6a41cf6149d030sewardj   }
7080b85e8bba97fdae7d892f7bfd12e4601307e4721dcerion
708172aefb29456a7a9c10f943f9557347d93b778530sewardj   case 0x013:
708272aefb29456a7a9c10f943f9557347d93b778530sewardj      // b11to20==0:      mfcr (Move from Cond Register, PPC32 p467)
708372aefb29456a7a9c10f943f9557347d93b778530sewardj      // b20==1 & b11==0: mfocrf (Move from One CR Field)
708472aefb29456a7a9c10f943f9557347d93b778530sewardj      // However it seems that the 'mfcr' behaviour is an acceptable
708572aefb29456a7a9c10f943f9557347d93b778530sewardj      // implementation of mfocr (from the 2.02 arch spec)
708672aefb29456a7a9c10f943f9557347d93b778530sewardj      if (b11to20 == 0) {
708772aefb29456a7a9c10f943f9557347d93b778530sewardj         DIP("mfcr r%u\n", rD_addr);
7088e9d8a26b690c2561ac54ab0cd6ad83ecbadcbe76sewardj         putIReg( rD_addr, mkWidenFrom32(ty, getGST( PPC_GST_CR ),
7089e9d8a26b690c2561ac54ab0cd6ad83ecbadcbe76sewardj                                         /* Signed */False) );
709072aefb29456a7a9c10f943f9557347d93b778530sewardj         break;
7091b85e8bba97fdae7d892f7bfd12e4601307e4721dcerion      }
709272aefb29456a7a9c10f943f9557347d93b778530sewardj      if (b20 == 1 && b11 == 0) {
709372aefb29456a7a9c10f943f9557347d93b778530sewardj         DIP("mfocrf r%u,%u\n", rD_addr, CRM);
7094e9d8a26b690c2561ac54ab0cd6ad83ecbadcbe76sewardj         putIReg( rD_addr, mkWidenFrom32(ty, getGST( PPC_GST_CR ),
7095e9d8a26b690c2561ac54ab0cd6ad83ecbadcbe76sewardj                                         /* Signed */False) );
709672aefb29456a7a9c10f943f9557347d93b778530sewardj         break;
709772aefb29456a7a9c10f943f9557347d93b778530sewardj      }
709872aefb29456a7a9c10f943f9557347d93b778530sewardj      /* not decodable */
709972aefb29456a7a9c10f943f9557347d93b778530sewardj      return False;
71000c74bb5aa3240f693df0568d578baabf0c376dc4carll
7101b85e8bba97fdae7d892f7bfd12e4601307e4721dcerion   /* XFX-Form */
7102e9d361ab43518b6dfbd3d846f48859534659dee0cerion   case 0x153: // mfspr (Move from Special-Purpose Register, PPC32 p470)
7103b85e8bba97fdae7d892f7bfd12e4601307e4721dcerion
710476de5cf615380b23b4b5bcced6541233cd4a93a0cerion      switch (SPR) {  // Choose a register...
7105d953ebb9b04cbad6891676df597bf0c542b1ec89cerion      case 0x1:
7106d953ebb9b04cbad6891676df597bf0c542b1ec89cerion         DIP("mfxer r%u\n", rD_addr);
7107e9d8a26b690c2561ac54ab0cd6ad83ecbadcbe76sewardj         putIReg( rD_addr, mkWidenFrom32(ty, getGST( PPC_GST_XER ),
7108e9d8a26b690c2561ac54ab0cd6ad83ecbadcbe76sewardj                                         /* Signed */False) );
7109d953ebb9b04cbad6891676df597bf0c542b1ec89cerion         break;
7110d953ebb9b04cbad6891676df597bf0c542b1ec89cerion      case 0x8:
7111d953ebb9b04cbad6891676df597bf0c542b1ec89cerion         DIP("mflr r%u\n", rD_addr);
7112d953ebb9b04cbad6891676df597bf0c542b1ec89cerion         putIReg( rD_addr, getGST( PPC_GST_LR ) );
7113d953ebb9b04cbad6891676df597bf0c542b1ec89cerion         break;
7114d953ebb9b04cbad6891676df597bf0c542b1ec89cerion      case 0x9:
7115d953ebb9b04cbad6891676df597bf0c542b1ec89cerion         DIP("mfctr r%u\n", rD_addr);
7116d953ebb9b04cbad6891676df597bf0c542b1ec89cerion         putIReg( rD_addr, getGST( PPC_GST_CTR ) );
7117d953ebb9b04cbad6891676df597bf0c542b1ec89cerion         break;
71188943d02aa373f45c6e5fdcbe5947620285d442b1carll      case 0x80:  // 128
71198943d02aa373f45c6e5fdcbe5947620285d442b1carll         DIP("mfspr r%u (TFHAR)\n", rD_addr);
71208943d02aa373f45c6e5fdcbe5947620285d442b1carll         putIReg( rD_addr, getGST( PPC_GST_TFHAR) );
71218943d02aa373f45c6e5fdcbe5947620285d442b1carll         break;
71228943d02aa373f45c6e5fdcbe5947620285d442b1carll      case 0x81:  // 129
71238943d02aa373f45c6e5fdcbe5947620285d442b1carll         DIP("mfspr r%u (TFIAR)\n", rD_addr);
71248943d02aa373f45c6e5fdcbe5947620285d442b1carll         putIReg( rD_addr, getGST( PPC_GST_TFIAR) );
71258943d02aa373f45c6e5fdcbe5947620285d442b1carll         break;
71268943d02aa373f45c6e5fdcbe5947620285d442b1carll      case 0x82:  // 130
71278943d02aa373f45c6e5fdcbe5947620285d442b1carll         DIP("mfspr r%u (TEXASR)\n", rD_addr);
71288943d02aa373f45c6e5fdcbe5947620285d442b1carll         putIReg( rD_addr, getGST( PPC_GST_TEXASR) );
71298943d02aa373f45c6e5fdcbe5947620285d442b1carll         break;
7130486db12d4767b5c2cc5ae764616e758f30ce21f5carll      case 0x83:  // 131
7131486db12d4767b5c2cc5ae764616e758f30ce21f5carll         DIP("mfspr r%u (TEXASRU)\n", rD_addr);
7132486db12d4767b5c2cc5ae764616e758f30ce21f5carll         putIReg( rD_addr, getGST( PPC_GST_TEXASRU) );
7133486db12d4767b5c2cc5ae764616e758f30ce21f5carll         break;
7134d953ebb9b04cbad6891676df597bf0c542b1ec89cerion      case 0x100:
7135d953ebb9b04cbad6891676df597bf0c542b1ec89cerion         DIP("mfvrsave r%u\n", rD_addr);
7136e9d8a26b690c2561ac54ab0cd6ad83ecbadcbe76sewardj         putIReg( rD_addr, mkWidenFrom32(ty, getGST( PPC_GST_VRSAVE ),
7137e9d8a26b690c2561ac54ab0cd6ad83ecbadcbe76sewardj                                         /* Signed */False) );
7138d953ebb9b04cbad6891676df597bf0c542b1ec89cerion         break;
7139aca070a5b3418a6a9b01e3c57a7eb0fbb5050908sewardj
7140aca070a5b3418a6a9b01e3c57a7eb0fbb5050908sewardj      case 0x103:
7141aca070a5b3418a6a9b01e3c57a7eb0fbb5050908sewardj         DIP("mfspr r%u, SPRG3(readonly)\n", rD_addr);
7142aca070a5b3418a6a9b01e3c57a7eb0fbb5050908sewardj         putIReg( rD_addr, getGST( PPC_GST_SPRG3_RO ) );
7143aca070a5b3418a6a9b01e3c57a7eb0fbb5050908sewardj         break;
7144aca070a5b3418a6a9b01e3c57a7eb0fbb5050908sewardj
7145abb321cf9ad44ad0ac445250c31128452e316547sewardj      /* Even a lowly PPC7400 can run the associated helper, so no
7146abb321cf9ad44ad0ac445250c31128452e316547sewardj         obvious need for feature testing at this point. */
7147abb321cf9ad44ad0ac445250c31128452e316547sewardj      case 268 /* 0x10C */:
7148abb321cf9ad44ad0ac445250c31128452e316547sewardj      case 269 /* 0x10D */: {
7149abb321cf9ad44ad0ac445250c31128452e316547sewardj         UInt     arg  = SPR==268 ? 0 : 1;
7150abb321cf9ad44ad0ac445250c31128452e316547sewardj         IRTemp   val  = newTemp(Ity_I32);
7151abb321cf9ad44ad0ac445250c31128452e316547sewardj         IRExpr** args = mkIRExprVec_1( mkU32(arg) );
7152abb321cf9ad44ad0ac445250c31128452e316547sewardj         IRDirty* d    = unsafeIRDirty_1_N(
7153abb321cf9ad44ad0ac445250c31128452e316547sewardj                            val,
7154abb321cf9ad44ad0ac445250c31128452e316547sewardj                            0/*regparms*/,
7155abb321cf9ad44ad0ac445250c31128452e316547sewardj                            "ppc32g_dirtyhelper_MFSPR_268_269",
7156abb321cf9ad44ad0ac445250c31128452e316547sewardj                            fnptr_to_fnentry
7157abb321cf9ad44ad0ac445250c31128452e316547sewardj                               (vbi, &ppc32g_dirtyhelper_MFSPR_268_269),
7158abb321cf9ad44ad0ac445250c31128452e316547sewardj                            args
7159abb321cf9ad44ad0ac445250c31128452e316547sewardj                         );
7160abb321cf9ad44ad0ac445250c31128452e316547sewardj         /* execute the dirty call, dumping the result in val. */
7161abb321cf9ad44ad0ac445250c31128452e316547sewardj         stmt( IRStmt_Dirty(d) );
716237b2ee8724691d97860726ea2c59005b6b654892sewardj         putIReg( rD_addr,
716337b2ee8724691d97860726ea2c59005b6b654892sewardj                  mkWidenFrom32(ty, mkexpr(val), False/*unsigned*/) );
716437b2ee8724691d97860726ea2c59005b6b654892sewardj         DIP("mfspr r%u,%u", rD_addr, (UInt)SPR);
716537b2ee8724691d97860726ea2c59005b6b654892sewardj         break;
716637b2ee8724691d97860726ea2c59005b6b654892sewardj      }
716737b2ee8724691d97860726ea2c59005b6b654892sewardj
716837b2ee8724691d97860726ea2c59005b6b654892sewardj      /* Again, runs natively on PPC7400 (7447, really).  Not
716937b2ee8724691d97860726ea2c59005b6b654892sewardj         bothering with a feature test. */
717037b2ee8724691d97860726ea2c59005b6b654892sewardj      case 287: /* 0x11F */ {
717137b2ee8724691d97860726ea2c59005b6b654892sewardj         IRTemp   val  = newTemp(Ity_I32);
717237b2ee8724691d97860726ea2c59005b6b654892sewardj         IRExpr** args = mkIRExprVec_0();
717337b2ee8724691d97860726ea2c59005b6b654892sewardj         IRDirty* d    = unsafeIRDirty_1_N(
717437b2ee8724691d97860726ea2c59005b6b654892sewardj                            val,
717537b2ee8724691d97860726ea2c59005b6b654892sewardj                            0/*regparms*/,
717637b2ee8724691d97860726ea2c59005b6b654892sewardj                            "ppc32g_dirtyhelper_MFSPR_287",
717737b2ee8724691d97860726ea2c59005b6b654892sewardj                            fnptr_to_fnentry
717837b2ee8724691d97860726ea2c59005b6b654892sewardj                               (vbi, &ppc32g_dirtyhelper_MFSPR_287),
717937b2ee8724691d97860726ea2c59005b6b654892sewardj                            args
718037b2ee8724691d97860726ea2c59005b6b654892sewardj                         );
718137b2ee8724691d97860726ea2c59005b6b654892sewardj         /* execute the dirty call, dumping the result in val. */
718237b2ee8724691d97860726ea2c59005b6b654892sewardj         stmt( IRStmt_Dirty(d) );
718337b2ee8724691d97860726ea2c59005b6b654892sewardj         putIReg( rD_addr,
718437b2ee8724691d97860726ea2c59005b6b654892sewardj                  mkWidenFrom32(ty, mkexpr(val), False/*unsigned*/) );
7185abb321cf9ad44ad0ac445250c31128452e316547sewardj         DIP("mfspr r%u,%u", rD_addr, (UInt)SPR);
7186abb321cf9ad44ad0ac445250c31128452e316547sewardj         break;
7187abb321cf9ad44ad0ac445250c31128452e316547sewardj      }
7188abb321cf9ad44ad0ac445250c31128452e316547sewardj
7189d953ebb9b04cbad6891676df597bf0c542b1ec89cerion      default:
71905b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion         vex_printf("dis_proc_ctl(ppc)(mfspr,SPR)(0x%x)\n", SPR);
7191d953ebb9b04cbad6891676df597bf0c542b1ec89cerion         return False;
7192b85e8bba97fdae7d892f7bfd12e4601307e4721dcerion      }
7193b85e8bba97fdae7d892f7bfd12e4601307e4721dcerion      break;
7194b85e8bba97fdae7d892f7bfd12e4601307e4721dcerion
719573a9197285975856fd3cc577216237afb3612b09sewardj   case 0x173: { // mftb (Move from Time Base, PPC32 p475)
719673a9197285975856fd3cc577216237afb3612b09sewardj      IRTemp   val  = newTemp(Ity_I64);
719773a9197285975856fd3cc577216237afb3612b09sewardj      IRExpr** args = mkIRExprVec_0();
71984c4f5ef69f89a19844a22a34b7a0cb717f83f033cerion      IRDirty* d    = unsafeIRDirty_1_N(
71994c4f5ef69f89a19844a22a34b7a0cb717f83f033cerion                              val,
72004c4f5ef69f89a19844a22a34b7a0cb717f83f033cerion                              0/*regparms*/,
72014c4f5ef69f89a19844a22a34b7a0cb717f83f033cerion                              "ppcg_dirtyhelper_MFTB",
7202dd40fdf58cc8a6fe9466c4f00bdfc9fe9bf00449sewardj                              fnptr_to_fnentry(vbi, &ppcg_dirtyhelper_MFTB),
72034c4f5ef69f89a19844a22a34b7a0cb717f83f033cerion                              args );
720473a9197285975856fd3cc577216237afb3612b09sewardj      /* execute the dirty call, dumping the result in val. */
720573a9197285975856fd3cc577216237afb3612b09sewardj      stmt( IRStmt_Dirty(d) );
720673a9197285975856fd3cc577216237afb3612b09sewardj
720773a9197285975856fd3cc577216237afb3612b09sewardj      switch (TBR) {
7208d953ebb9b04cbad6891676df597bf0c542b1ec89cerion      case 269:
7209d953ebb9b04cbad6891676df597bf0c542b1ec89cerion         DIP("mftbu r%u", rD_addr);
72102831b00c4950d6c2b061def05fd67528fe132ececerion         putIReg( rD_addr,
7211e9d8a26b690c2561ac54ab0cd6ad83ecbadcbe76sewardj                  mkWidenFrom32(ty, unop(Iop_64HIto32, mkexpr(val)),
7212e9d8a26b690c2561ac54ab0cd6ad83ecbadcbe76sewardj                                /* Signed */False) );
7213d953ebb9b04cbad6891676df597bf0c542b1ec89cerion         break;
7214d953ebb9b04cbad6891676df597bf0c542b1ec89cerion      case 268:
7215d953ebb9b04cbad6891676df597bf0c542b1ec89cerion         DIP("mftb r%u", rD_addr);
72162831b00c4950d6c2b061def05fd67528fe132ececerion         putIReg( rD_addr, (mode64) ? mkexpr(val) :
72172831b00c4950d6c2b061def05fd67528fe132ececerion                                      unop(Iop_64to32, mkexpr(val)) );
7218d953ebb9b04cbad6891676df597bf0c542b1ec89cerion         break;
7219d953ebb9b04cbad6891676df597bf0c542b1ec89cerion      default:
7220d953ebb9b04cbad6891676df597bf0c542b1ec89cerion         return False; /* illegal instruction */
722173a9197285975856fd3cc577216237afb3612b09sewardj      }
722273a9197285975856fd3cc577216237afb3612b09sewardj      break;
722373a9197285975856fd3cc577216237afb3612b09sewardj   }
722473a9197285975856fd3cc577216237afb3612b09sewardj
722572aefb29456a7a9c10f943f9557347d93b778530sewardj   case 0x090: {
722672aefb29456a7a9c10f943f9557347d93b778530sewardj      // b20==0: mtcrf (Move to Cond Register Fields, PPC32 p477)
722772aefb29456a7a9c10f943f9557347d93b778530sewardj      // b20==1: mtocrf (Move to One Cond Reg Field)
7228edf7fc572e2decb93e9143961e8739c8fe18899dcerion      Int   cr;
7229edf7fc572e2decb93e9143961e8739c8fe18899dcerion      UChar shft;
723072aefb29456a7a9c10f943f9557347d93b778530sewardj      if (b11 != 0)
7231b85e8bba97fdae7d892f7bfd12e4601307e4721dcerion         return False;
723272aefb29456a7a9c10f943f9557347d93b778530sewardj      if (b20 == 1) {
723372aefb29456a7a9c10f943f9557347d93b778530sewardj         /* ppc64 v2.02 spec says mtocrf gives undefined outcome if >
723472aefb29456a7a9c10f943f9557347d93b778530sewardj            1 field is written.  It seems more robust to decline to
723572aefb29456a7a9c10f943f9557347d93b778530sewardj            decode the insn if so. */
723672aefb29456a7a9c10f943f9557347d93b778530sewardj         switch (CRM) {
723772aefb29456a7a9c10f943f9557347d93b778530sewardj            case 0x01: case 0x02: case 0x04: case 0x08:
723872aefb29456a7a9c10f943f9557347d93b778530sewardj            case 0x10: case 0x20: case 0x40: case 0x80:
723972aefb29456a7a9c10f943f9557347d93b778530sewardj               break;
724072aefb29456a7a9c10f943f9557347d93b778530sewardj            default:
724172aefb29456a7a9c10f943f9557347d93b778530sewardj               return False;
724272aefb29456a7a9c10f943f9557347d93b778530sewardj         }
7243b85e8bba97fdae7d892f7bfd12e4601307e4721dcerion      }
724472aefb29456a7a9c10f943f9557347d93b778530sewardj      DIP("%s 0x%x,r%u\n", b20==1 ? "mtocrf" : "mtcrf",
724572aefb29456a7a9c10f943f9557347d93b778530sewardj                           CRM, rS_addr);
7246edf7fc572e2decb93e9143961e8739c8fe18899dcerion      /* Write to each field specified by CRM */
7247edf7fc572e2decb93e9143961e8739c8fe18899dcerion      for (cr = 0; cr < 8; cr++) {
7248edf7fc572e2decb93e9143961e8739c8fe18899dcerion         if ((CRM & (1 << (7-cr))) == 0)
7249edf7fc572e2decb93e9143961e8739c8fe18899dcerion            continue;
7250edf7fc572e2decb93e9143961e8739c8fe18899dcerion         shft = 4*(7-cr);
7251d953ebb9b04cbad6891676df597bf0c542b1ec89cerion         putGST_field( PPC_GST_CR,
72522831b00c4950d6c2b061def05fd67528fe132ececerion                       binop(Iop_Shr32,
7253e9d8a26b690c2561ac54ab0cd6ad83ecbadcbe76sewardj                             mkNarrowTo32(ty, mkexpr(rS)),
72542831b00c4950d6c2b061def05fd67528fe132ececerion                             mkU8(shft)), cr );
7255edf7fc572e2decb93e9143961e8739c8fe18899dcerion      }
7256b85e8bba97fdae7d892f7bfd12e4601307e4721dcerion      break;
7257edf7fc572e2decb93e9143961e8739c8fe18899dcerion   }
7258e9d361ab43518b6dfbd3d846f48859534659dee0cerion
7259e9d361ab43518b6dfbd3d846f48859534659dee0cerion   case 0x1D3: // mtspr (Move to Special-Purpose Register, PPC32 p483)
7260b85e8bba97fdae7d892f7bfd12e4601307e4721dcerion
726176de5cf615380b23b4b5bcced6541233cd4a93a0cerion      switch (SPR) {  // Choose a register...
7262d953ebb9b04cbad6891676df597bf0c542b1ec89cerion      case 0x1:
7263d953ebb9b04cbad6891676df597bf0c542b1ec89cerion         DIP("mtxer r%u\n", rS_addr);
7264e9d8a26b690c2561ac54ab0cd6ad83ecbadcbe76sewardj         putGST( PPC_GST_XER, mkNarrowTo32(ty, mkexpr(rS)) );
7265d953ebb9b04cbad6891676df597bf0c542b1ec89cerion         break;
7266d953ebb9b04cbad6891676df597bf0c542b1ec89cerion      case 0x8:
7267d953ebb9b04cbad6891676df597bf0c542b1ec89cerion         DIP("mtlr r%u\n", rS_addr);
7268d953ebb9b04cbad6891676df597bf0c542b1ec89cerion         putGST( PPC_GST_LR, mkexpr(rS) );
7269d953ebb9b04cbad6891676df597bf0c542b1ec89cerion         break;
7270d953ebb9b04cbad6891676df597bf0c542b1ec89cerion      case 0x9:
7271d953ebb9b04cbad6891676df597bf0c542b1ec89cerion         DIP("mtctr r%u\n", rS_addr);
7272d953ebb9b04cbad6891676df597bf0c542b1ec89cerion         putGST( PPC_GST_CTR, mkexpr(rS) );
7273d953ebb9b04cbad6891676df597bf0c542b1ec89cerion         break;
7274d953ebb9b04cbad6891676df597bf0c542b1ec89cerion      case 0x100:
7275d953ebb9b04cbad6891676df597bf0c542b1ec89cerion         DIP("mtvrsave r%u\n", rS_addr);
7276e9d8a26b690c2561ac54ab0cd6ad83ecbadcbe76sewardj         putGST( PPC_GST_VRSAVE, mkNarrowTo32(ty, mkexpr(rS)) );
7277d953ebb9b04cbad6891676df597bf0c542b1ec89cerion         break;
72788943d02aa373f45c6e5fdcbe5947620285d442b1carll      case 0x80:  // 128
72798943d02aa373f45c6e5fdcbe5947620285d442b1carll         DIP("mtspr r%u (TFHAR)\n", rS_addr);
72808943d02aa373f45c6e5fdcbe5947620285d442b1carll         putGST( PPC_GST_TFHAR, mkexpr(rS) );
72818943d02aa373f45c6e5fdcbe5947620285d442b1carll         break;
72828943d02aa373f45c6e5fdcbe5947620285d442b1carll      case 0x81:  // 129
72838943d02aa373f45c6e5fdcbe5947620285d442b1carll         DIP("mtspr r%u (TFIAR)\n", rS_addr);
72848943d02aa373f45c6e5fdcbe5947620285d442b1carll         putGST( PPC_GST_TFIAR, mkexpr(rS) );
72858943d02aa373f45c6e5fdcbe5947620285d442b1carll         break;
72868943d02aa373f45c6e5fdcbe5947620285d442b1carll      case 0x82:  // 130
72878943d02aa373f45c6e5fdcbe5947620285d442b1carll         DIP("mtspr r%u (TEXASR)\n", rS_addr);
72888943d02aa373f45c6e5fdcbe5947620285d442b1carll         putGST( PPC_GST_TEXASR, mkexpr(rS) );
72898943d02aa373f45c6e5fdcbe5947620285d442b1carll         break;
7290d953ebb9b04cbad6891676df597bf0c542b1ec89cerion      default:
72915b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion         vex_printf("dis_proc_ctl(ppc)(mtspr,SPR)(%u)\n", SPR);
7292d953ebb9b04cbad6891676df597bf0c542b1ec89cerion         return False;
7293b85e8bba97fdae7d892f7bfd12e4601307e4721dcerion      }
7294b85e8bba97fdae7d892f7bfd12e4601307e4721dcerion      break;
72950c74bb5aa3240f693df0568d578baabf0c376dc4carll
72960c74bb5aa3240f693df0568d578baabf0c376dc4carll   case 0x33:                // mfvsrd
72970c74bb5aa3240f693df0568d578baabf0c376dc4carll   {
72980c74bb5aa3240f693df0568d578baabf0c376dc4carll      UChar XS = ifieldRegXS( theInstr );
72990c74bb5aa3240f693df0568d578baabf0c376dc4carll      UChar rA_addr = ifieldRegA(theInstr);
73000c74bb5aa3240f693df0568d578baabf0c376dc4carll      IRExpr * high64;
73010c74bb5aa3240f693df0568d578baabf0c376dc4carll      IRTemp vS = newTemp( Ity_V128 );
73020c74bb5aa3240f693df0568d578baabf0c376dc4carll      DIP("mfvsrd r%u,vsr%d\n", rA_addr, (UInt)XS);
73030c74bb5aa3240f693df0568d578baabf0c376dc4carll
73040c74bb5aa3240f693df0568d578baabf0c376dc4carll      /*  XS = SX || S
73050c74bb5aa3240f693df0568d578baabf0c376dc4carll       *  For SX=0, mfvsrd is treated as a Floating-Point
73060c74bb5aa3240f693df0568d578baabf0c376dc4carll       *            instruction in terms of resource availability.
73070c74bb5aa3240f693df0568d578baabf0c376dc4carll       *  For SX=1, mfvsrd is treated as a Vector instruction in
73080c74bb5aa3240f693df0568d578baabf0c376dc4carll       *            terms of resource availability.
730978850ae9874a90ea625fcee1fd4c359375b7b538carll       * FIXME: NEED TO FIGURE OUT HOW TO IMPLEMENT THE RESOURCE AVAILABILITY PART
73100c74bb5aa3240f693df0568d578baabf0c376dc4carll       */
73110c74bb5aa3240f693df0568d578baabf0c376dc4carll      assign( vS, getVSReg( XS ) );
73120c74bb5aa3240f693df0568d578baabf0c376dc4carll      high64 = unop( Iop_V128HIto64, mkexpr( vS ) );
73130c74bb5aa3240f693df0568d578baabf0c376dc4carll      putIReg( rA_addr, (mode64) ? high64 :
73140c74bb5aa3240f693df0568d578baabf0c376dc4carll      unop( Iop_64to32, high64 ) );
73150c74bb5aa3240f693df0568d578baabf0c376dc4carll      break;
73160c74bb5aa3240f693df0568d578baabf0c376dc4carll   }
73170c74bb5aa3240f693df0568d578baabf0c376dc4carll
731878850ae9874a90ea625fcee1fd4c359375b7b538carll   case 0x73:                // mfvsrwz
731978850ae9874a90ea625fcee1fd4c359375b7b538carll   {
732078850ae9874a90ea625fcee1fd4c359375b7b538carll      UChar XS = ifieldRegXS( theInstr );
732178850ae9874a90ea625fcee1fd4c359375b7b538carll      UChar rA_addr = ifieldRegA(theInstr);
732278850ae9874a90ea625fcee1fd4c359375b7b538carll      IRExpr * high64;
732378850ae9874a90ea625fcee1fd4c359375b7b538carll      IRTemp vS = newTemp( Ity_V128 );
732478850ae9874a90ea625fcee1fd4c359375b7b538carll      DIP("mfvsrwz r%u,vsr%d\n", rA_addr, (UInt)XS);
732578850ae9874a90ea625fcee1fd4c359375b7b538carll      /*  XS = SX || S
732678850ae9874a90ea625fcee1fd4c359375b7b538carll       *  For SX=0, mfvsrwz is treated as a Floating-Point
732778850ae9874a90ea625fcee1fd4c359375b7b538carll       *            instruction in terms of resource availability.
732878850ae9874a90ea625fcee1fd4c359375b7b538carll       *  For SX=1, mfvsrwz is treated as a Vector instruction in
732978850ae9874a90ea625fcee1fd4c359375b7b538carll       *            terms of resource availability.
733078850ae9874a90ea625fcee1fd4c359375b7b538carll       * FIXME: NEED TO FIGURE OUT HOW TO IMPLEMENT THE RESOURCE AVAILABILITY PART
733178850ae9874a90ea625fcee1fd4c359375b7b538carll       */
733278850ae9874a90ea625fcee1fd4c359375b7b538carll
733378850ae9874a90ea625fcee1fd4c359375b7b538carll      assign( vS, getVSReg( XS ) );
733478850ae9874a90ea625fcee1fd4c359375b7b538carll      high64 = unop( Iop_V128HIto64, mkexpr( vS ) );
733578850ae9874a90ea625fcee1fd4c359375b7b538carll      /* move value to the destination setting the upper 32-bits to zero */
733678850ae9874a90ea625fcee1fd4c359375b7b538carll      putIReg( rA_addr, (mode64) ?
733778850ae9874a90ea625fcee1fd4c359375b7b538carll                                  binop( Iop_And64, high64, mkU64( 0xFFFFFFFF ) ) :
733878850ae9874a90ea625fcee1fd4c359375b7b538carll                                  unop(  Iop_64to32,
733978850ae9874a90ea625fcee1fd4c359375b7b538carll                                         binop( Iop_And64, high64, mkU64( 0xFFFFFFFF ) ) ) );
734078850ae9874a90ea625fcee1fd4c359375b7b538carll      break;
734178850ae9874a90ea625fcee1fd4c359375b7b538carll   }
734278850ae9874a90ea625fcee1fd4c359375b7b538carll
73430c74bb5aa3240f693df0568d578baabf0c376dc4carll   case 0xB3:                // mtvsrd
73440c74bb5aa3240f693df0568d578baabf0c376dc4carll   {
73450c74bb5aa3240f693df0568d578baabf0c376dc4carll      UChar XT = ifieldRegXT( theInstr );
73460c74bb5aa3240f693df0568d578baabf0c376dc4carll      UChar rA_addr = ifieldRegA(theInstr);
73470c74bb5aa3240f693df0568d578baabf0c376dc4carll      IRTemp rA = newTemp(ty);
73480c74bb5aa3240f693df0568d578baabf0c376dc4carll      DIP("mtvsrd vsr%d,r%u\n", (UInt)XT, rA_addr);
73490c74bb5aa3240f693df0568d578baabf0c376dc4carll      /*  XS = SX || S
73500c74bb5aa3240f693df0568d578baabf0c376dc4carll       *  For SX=0, mfvsrd is treated as a Floating-Point
73510c74bb5aa3240f693df0568d578baabf0c376dc4carll       *            instruction in terms of resource availability.
73520c74bb5aa3240f693df0568d578baabf0c376dc4carll       *  For SX=1, mfvsrd is treated as a Vector instruction in
73530c74bb5aa3240f693df0568d578baabf0c376dc4carll       *            terms of resource availability.
735478850ae9874a90ea625fcee1fd4c359375b7b538carll       * FIXME: NEED TO FIGURE OUT HOW TO IMPLEMENT THE RESOURCE AVAILABILITY PART
73550c74bb5aa3240f693df0568d578baabf0c376dc4carll       */
73560c74bb5aa3240f693df0568d578baabf0c376dc4carll      assign( rA, getIReg(rA_addr) );
73570c74bb5aa3240f693df0568d578baabf0c376dc4carll
73580c74bb5aa3240f693df0568d578baabf0c376dc4carll      if (mode64)
73590c74bb5aa3240f693df0568d578baabf0c376dc4carll         putVSReg( XT, binop( Iop_64HLtoV128, mkexpr( rA ), mkU64( 0 ) ) );
73600c74bb5aa3240f693df0568d578baabf0c376dc4carll      else
73610c74bb5aa3240f693df0568d578baabf0c376dc4carll         putVSReg( XT, binop( Iop_64HLtoV128,
73620c74bb5aa3240f693df0568d578baabf0c376dc4carll                              binop( Iop_32HLto64,
73630c74bb5aa3240f693df0568d578baabf0c376dc4carll                                     mkU32( 0 ),
73640c74bb5aa3240f693df0568d578baabf0c376dc4carll                                     mkexpr( rA ) ),
73650c74bb5aa3240f693df0568d578baabf0c376dc4carll                                     mkU64( 0 ) ) );
73660c74bb5aa3240f693df0568d578baabf0c376dc4carll      break;
73670c74bb5aa3240f693df0568d578baabf0c376dc4carll   }
73680c74bb5aa3240f693df0568d578baabf0c376dc4carll
73690c74bb5aa3240f693df0568d578baabf0c376dc4carll   case 0xD3:                // mtvsrwa
73700c74bb5aa3240f693df0568d578baabf0c376dc4carll   {
73710c74bb5aa3240f693df0568d578baabf0c376dc4carll      UChar XT = ifieldRegXT( theInstr );
73720c74bb5aa3240f693df0568d578baabf0c376dc4carll      UChar rA_addr = ifieldRegA(theInstr);
73730c74bb5aa3240f693df0568d578baabf0c376dc4carll      IRTemp rA = newTemp( Ity_I32 );
73740c74bb5aa3240f693df0568d578baabf0c376dc4carll      DIP("mtvsrwa vsr%d,r%u\n", (UInt)XT, rA_addr);
73750c74bb5aa3240f693df0568d578baabf0c376dc4carll      /*  XS = SX || S
73760c74bb5aa3240f693df0568d578baabf0c376dc4carll       *  For SX=0, mtvsrwa is treated as a Floating-Point
73770c74bb5aa3240f693df0568d578baabf0c376dc4carll       *            instruction in terms of resource availability.
73780c74bb5aa3240f693df0568d578baabf0c376dc4carll       *  For SX=1, mtvsrwa is treated as a Vector instruction in
73790c74bb5aa3240f693df0568d578baabf0c376dc4carll       *            terms of resource availability.
738078850ae9874a90ea625fcee1fd4c359375b7b538carll       * FIXME: NEED TO FIGURE OUT HOW TO IMPLEMENT THE RESOURCE AVAILABILITY PART
73810c74bb5aa3240f693df0568d578baabf0c376dc4carll       */
73820c74bb5aa3240f693df0568d578baabf0c376dc4carll      if (mode64)
73830c74bb5aa3240f693df0568d578baabf0c376dc4carll         assign( rA, unop( Iop_64to32, getIReg( rA_addr ) ) );
73840c74bb5aa3240f693df0568d578baabf0c376dc4carll      else
73850c74bb5aa3240f693df0568d578baabf0c376dc4carll         assign( rA, getIReg(rA_addr) );
73860c74bb5aa3240f693df0568d578baabf0c376dc4carll
73870c74bb5aa3240f693df0568d578baabf0c376dc4carll      putVSReg( XT, binop( Iop_64HLtoV128,
73880c74bb5aa3240f693df0568d578baabf0c376dc4carll                           unop( Iop_32Sto64, mkexpr( rA ) ),
73890c74bb5aa3240f693df0568d578baabf0c376dc4carll                           mkU64( 0 ) ) );
73900c74bb5aa3240f693df0568d578baabf0c376dc4carll      break;
73910c74bb5aa3240f693df0568d578baabf0c376dc4carll   }
73920c74bb5aa3240f693df0568d578baabf0c376dc4carll
739378850ae9874a90ea625fcee1fd4c359375b7b538carll   case 0xF3:                // mtvsrwz
739478850ae9874a90ea625fcee1fd4c359375b7b538carll      {
739578850ae9874a90ea625fcee1fd4c359375b7b538carll         UChar XT = ifieldRegXT( theInstr );
739678850ae9874a90ea625fcee1fd4c359375b7b538carll         UChar rA_addr = ifieldRegA(theInstr);
739778850ae9874a90ea625fcee1fd4c359375b7b538carll         IRTemp rA = newTemp( Ity_I32 );
739878850ae9874a90ea625fcee1fd4c359375b7b538carll         DIP("mtvsrwz vsr%d,r%u\n", rA_addr, (UInt)XT);
739978850ae9874a90ea625fcee1fd4c359375b7b538carll         /*  XS = SX || S
740078850ae9874a90ea625fcee1fd4c359375b7b538carll          *  For SX=0, mtvsrwz is treated as a Floating-Point
740178850ae9874a90ea625fcee1fd4c359375b7b538carll          *            instruction in terms of resource availability.
740278850ae9874a90ea625fcee1fd4c359375b7b538carll          *  For SX=1, mtvsrwz is treated as a Vector instruction in
740378850ae9874a90ea625fcee1fd4c359375b7b538carll          *            terms of resource availability.
740478850ae9874a90ea625fcee1fd4c359375b7b538carll          * FIXME: NEED TO FIGURE OUT HOW TO IMPLEMENT THE RESOURCE AVAILABILITY PART
740578850ae9874a90ea625fcee1fd4c359375b7b538carll          */
740678850ae9874a90ea625fcee1fd4c359375b7b538carll         if (mode64)
740778850ae9874a90ea625fcee1fd4c359375b7b538carll             assign( rA, unop( Iop_64to32, getIReg( rA_addr ) ) );
740878850ae9874a90ea625fcee1fd4c359375b7b538carll         else
740978850ae9874a90ea625fcee1fd4c359375b7b538carll             assign( rA, getIReg(rA_addr) );
741078850ae9874a90ea625fcee1fd4c359375b7b538carll
741178850ae9874a90ea625fcee1fd4c359375b7b538carll         putVSReg( XT, binop( Iop_64HLtoV128,
741278850ae9874a90ea625fcee1fd4c359375b7b538carll                              binop( Iop_32HLto64, mkU32( 0 ), mkexpr ( rA ) ),
741378850ae9874a90ea625fcee1fd4c359375b7b538carll                              mkU64( 0 ) ) );
741478850ae9874a90ea625fcee1fd4c359375b7b538carll         break;
741578850ae9874a90ea625fcee1fd4c359375b7b538carll      }
741678850ae9874a90ea625fcee1fd4c359375b7b538carll
7417b85e8bba97fdae7d892f7bfd12e4601307e4721dcerion   default:
74185b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion      vex_printf("dis_proc_ctl(ppc)(opc2)\n");
7419b85e8bba97fdae7d892f7bfd12e4601307e4721dcerion      return False;
7420b85e8bba97fdae7d892f7bfd12e4601307e4721dcerion   }
7421b85e8bba97fdae7d892f7bfd12e4601307e4721dcerion   return True;
74228c3addacc8343f5d1504379e303934f8ed88903ecerion}
74238c3addacc8343f5d1504379e303934f8ed88903ecerion
74248c3addacc8343f5d1504379e303934f8ed88903ecerion
74253d870a39e4d145e2f3d9f9a0eeed3475ec934ac1cerion/*
74263d870a39e4d145e2f3d9f9a0eeed3475ec934ac1cerion  Cache Management Instructions
74273d870a39e4d145e2f3d9f9a0eeed3475ec934ac1cerion*/
7428d94b73a4ece194130f7a59cca9262d44cf9dbb91sewardjstatic Bool dis_cache_manage ( UInt         theInstr,
74299e6491ab55324b8e45e187b1e1e9632ac3cb3e27sewardj                               DisResult*   dres,
7430cacba8e675988fbf21b08feea1f317a9c896c053florian                               const VexArchInfo* guest_archinfo )
74318c3addacc8343f5d1504379e303934f8ed88903ecerion{
7432b85e8bba97fdae7d892f7bfd12e4601307e4721dcerion   /* X-Form */
743376de5cf615380b23b4b5bcced6541233cd4a93a0cerion   UChar opc1    = ifieldOPC(theInstr);
743476de5cf615380b23b4b5bcced6541233cd4a93a0cerion   UChar b21to25 = ifieldRegDS(theInstr);
743576de5cf615380b23b4b5bcced6541233cd4a93a0cerion   UChar rA_addr = ifieldRegA(theInstr);
743676de5cf615380b23b4b5bcced6541233cd4a93a0cerion   UChar rB_addr = ifieldRegB(theInstr);
743776de5cf615380b23b4b5bcced6541233cd4a93a0cerion   UInt  opc2    = ifieldOPClo10(theInstr);
743876de5cf615380b23b4b5bcced6541233cd4a93a0cerion   UChar b0      = ifieldBIT0(theInstr);
74399138b1779efcff4b12896ccd10744d8118e89a70florian   UInt  lineszB = guest_archinfo->ppc_icache_line_szB;
7440e971c6a8b613ab2ea92a34f802a0e39c01e84b19sewardj   Bool  is_dcbzl = False;
7441d953ebb9b04cbad6891676df597bf0c542b1ec89cerion
7442d953ebb9b04cbad6891676df597bf0c542b1ec89cerion   IRType ty     = mode64 ? Ity_I64 : Ity_I32;
7443094d1397b3f69b1a538e80ab509ea8cd75f4be3bcerion
7444b77db0e0f00084ea3437887f835f502ef0dcbc88carll   // Check for valid hint values for dcbt and dcbtst as currently described in
7445b77db0e0f00084ea3437887f835f502ef0dcbc88carll   // ISA 2.07.  If valid, then we simply set b21to25 to zero since we have no
7446b77db0e0f00084ea3437887f835f502ef0dcbc88carll   // means of modeling the hint anyway.
7447b77db0e0f00084ea3437887f835f502ef0dcbc88carll   if (opc1 == 0x1F && ((opc2 == 0x116) || (opc2 == 0xF6))) {
74489708b6ac7026b33277e01044d6ab82666048eedacarll      if (b21to25 == 0x10 || b21to25 < 0x10)
7449b77db0e0f00084ea3437887f835f502ef0dcbc88carll         b21to25 = 0;
74506be67235ba2829b0bc34c3a0876cee4eac340d95sewardj   }
74519708b6ac7026b33277e01044d6ab82666048eedacarll   if (opc1 == 0x1F && opc2 == 0x116 && b21to25 == 0x11)
7452b77db0e0f00084ea3437887f835f502ef0dcbc88carll      b21to25 = 0;
7453b77db0e0f00084ea3437887f835f502ef0dcbc88carll
7454e971c6a8b613ab2ea92a34f802a0e39c01e84b19sewardj   if (opc1 == 0x1F && opc2 == 0x3F6) { // dcbz
7455e971c6a8b613ab2ea92a34f802a0e39c01e84b19sewardj      if (b21to25 == 1) {
7456e971c6a8b613ab2ea92a34f802a0e39c01e84b19sewardj         is_dcbzl = True;
7457e971c6a8b613ab2ea92a34f802a0e39c01e84b19sewardj         b21to25 = 0;
7458e971c6a8b613ab2ea92a34f802a0e39c01e84b19sewardj         if (!(guest_archinfo->ppc_dcbzl_szB)) {
7459e971c6a8b613ab2ea92a34f802a0e39c01e84b19sewardj            vex_printf("dis_cache_manage(ppc)(dcbzl not supported by host)\n");
7460e971c6a8b613ab2ea92a34f802a0e39c01e84b19sewardj            return False;
7461e971c6a8b613ab2ea92a34f802a0e39c01e84b19sewardj         }
7462e971c6a8b613ab2ea92a34f802a0e39c01e84b19sewardj      }
7463e971c6a8b613ab2ea92a34f802a0e39c01e84b19sewardj   }
74646be67235ba2829b0bc34c3a0876cee4eac340d95sewardj
7465b85e8bba97fdae7d892f7bfd12e4601307e4721dcerion   if (opc1 != 0x1F || b21to25 != 0 || b0 != 0) {
74666be67235ba2829b0bc34c3a0876cee4eac340d95sewardj      if (0) vex_printf("dis_cache_manage %d %d %d\n",
74676be67235ba2829b0bc34c3a0876cee4eac340d95sewardj                        (Int)opc1, (Int)b21to25, (Int)b0);
74685b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion      vex_printf("dis_cache_manage(ppc)(opc1|b21to25|b0)\n");
7469b85e8bba97fdae7d892f7bfd12e4601307e4721dcerion      return False;
7470b85e8bba97fdae7d892f7bfd12e4601307e4721dcerion   }
7471d94b73a4ece194130f7a59cca9262d44cf9dbb91sewardj
7472d94b73a4ece194130f7a59cca9262d44cf9dbb91sewardj   /* stay sane .. */
74732691a61715853cb3e3ca7b4a1abb0e986ced5e66sewardj   vassert(lineszB == 16 || lineszB == 32 || lineszB == 64 || lineszB == 128);
7474b85e8bba97fdae7d892f7bfd12e4601307e4721dcerion
7475b85e8bba97fdae7d892f7bfd12e4601307e4721dcerion   switch (opc2) {
7476b51f0f4f33256638ed953156a2635aa739b232f1sewardj//zz    case 0x2F6: // dcba (Data Cache Block Allocate, PPC32 p380)
7477b51f0f4f33256638ed953156a2635aa739b232f1sewardj//zz       vassert(0); /* AWAITING TEST CASE */
7478d953ebb9b04cbad6891676df597bf0c542b1ec89cerion//zz       DIP("dcba r%u,r%u\n", rA_addr, rB_addr);
74795b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion//zz       if (0) vex_printf("vex ppc->IR: kludged dcba\n");
7480b51f0f4f33256638ed953156a2635aa739b232f1sewardj//zz       break;
748120ef5472eac767474c93b7835364a23f24c0ec5dsewardj
748220ef5472eac767474c93b7835364a23f24c0ec5dsewardj   case 0x056: // dcbf (Data Cache Block Flush, PPC32 p382)
7483d953ebb9b04cbad6891676df597bf0c542b1ec89cerion      DIP("dcbf r%u,r%u\n", rA_addr, rB_addr);
748420ef5472eac767474c93b7835364a23f24c0ec5dsewardj      /* nop as far as vex is concerned */
748520ef5472eac767474c93b7835364a23f24c0ec5dsewardj      break;
7486b85e8bba97fdae7d892f7bfd12e4601307e4721dcerion
7487e9d361ab43518b6dfbd3d846f48859534659dee0cerion   case 0x036: // dcbst (Data Cache Block Store, PPC32 p384)
7488d953ebb9b04cbad6891676df597bf0c542b1ec89cerion      DIP("dcbst r%u,r%u\n", rA_addr, rB_addr);
7489b51f0f4f33256638ed953156a2635aa739b232f1sewardj      /* nop as far as vex is concerned */
7490b85e8bba97fdae7d892f7bfd12e4601307e4721dcerion      break;
7491b85e8bba97fdae7d892f7bfd12e4601307e4721dcerion
7492e9d361ab43518b6dfbd3d846f48859534659dee0cerion   case 0x116: // dcbt (Data Cache Block Touch, PPC32 p385)
7493d953ebb9b04cbad6891676df597bf0c542b1ec89cerion      DIP("dcbt r%u,r%u\n", rA_addr, rB_addr);
7494b51f0f4f33256638ed953156a2635aa739b232f1sewardj      /* nop as far as vex is concerned */
7495b85e8bba97fdae7d892f7bfd12e4601307e4721dcerion      break;
7496b85e8bba97fdae7d892f7bfd12e4601307e4721dcerion
7497e9d361ab43518b6dfbd3d846f48859534659dee0cerion   case 0x0F6: // dcbtst (Data Cache Block Touch for Store, PPC32 p386)
7498d953ebb9b04cbad6891676df597bf0c542b1ec89cerion      DIP("dcbtst r%u,r%u\n", rA_addr, rB_addr);
7499b51f0f4f33256638ed953156a2635aa739b232f1sewardj      /* nop as far as vex is concerned */
7500b85e8bba97fdae7d892f7bfd12e4601307e4721dcerion      break;
7501b85e8bba97fdae7d892f7bfd12e4601307e4721dcerion
7502094d1397b3f69b1a538e80ab509ea8cd75f4be3bcerion   case 0x3F6: { // dcbz (Data Cache Block Clear to Zero, PPC32 p387)
7503e971c6a8b613ab2ea92a34f802a0e39c01e84b19sewardj                 // dcbzl (Data Cache Block Clear to Zero Long, bug#135264)
7504d94b73a4ece194130f7a59cca9262d44cf9dbb91sewardj      /* Clear all bytes in cache block at (rA|0) + rB. */
75052831b00c4950d6c2b061def05fd67528fe132ececerion      IRTemp  EA   = newTemp(ty);
75062831b00c4950d6c2b061def05fd67528fe132ececerion      IRTemp  addr = newTemp(ty);
7507094d1397b3f69b1a538e80ab509ea8cd75f4be3bcerion      IRExpr* irx_addr;
7508094d1397b3f69b1a538e80ab509ea8cd75f4be3bcerion      UInt    i;
7509e971c6a8b613ab2ea92a34f802a0e39c01e84b19sewardj      UInt clearszB;
7510e971c6a8b613ab2ea92a34f802a0e39c01e84b19sewardj      if (is_dcbzl) {
7511e971c6a8b613ab2ea92a34f802a0e39c01e84b19sewardj          clearszB = guest_archinfo->ppc_dcbzl_szB;
7512e971c6a8b613ab2ea92a34f802a0e39c01e84b19sewardj          DIP("dcbzl r%u,r%u\n", rA_addr, rB_addr);
7513e971c6a8b613ab2ea92a34f802a0e39c01e84b19sewardj      }
7514e971c6a8b613ab2ea92a34f802a0e39c01e84b19sewardj      else {
7515e971c6a8b613ab2ea92a34f802a0e39c01e84b19sewardj          clearszB = guest_archinfo->ppc_dcbz_szB;
7516e971c6a8b613ab2ea92a34f802a0e39c01e84b19sewardj          DIP("dcbz r%u,r%u\n", rA_addr, rB_addr);
7517e971c6a8b613ab2ea92a34f802a0e39c01e84b19sewardj      }
7518cb1f68e013416507adf513072d602f747773e3d7sewardj
7519d953ebb9b04cbad6891676df597bf0c542b1ec89cerion      assign( EA, ea_rAor0_idxd(rA_addr, rB_addr) );
7520094d1397b3f69b1a538e80ab509ea8cd75f4be3bcerion
75212831b00c4950d6c2b061def05fd67528fe132ececerion      if (mode64) {
75222831b00c4950d6c2b061def05fd67528fe132ececerion         /* Round EA down to the start of the containing block. */
75232831b00c4950d6c2b061def05fd67528fe132ececerion         assign( addr, binop( Iop_And64,
75242831b00c4950d6c2b061def05fd67528fe132ececerion                              mkexpr(EA),
7525e971c6a8b613ab2ea92a34f802a0e39c01e84b19sewardj                              mkU64( ~((ULong)clearszB-1) )) );
75262831b00c4950d6c2b061def05fd67528fe132ececerion
7527e971c6a8b613ab2ea92a34f802a0e39c01e84b19sewardj         for (i = 0; i < clearszB / 8; i++) {
75282831b00c4950d6c2b061def05fd67528fe132ececerion            irx_addr = binop( Iop_Add64, mkexpr(addr), mkU64(i*8) );
75291f5fe1fc3a37ca729925e8eec25aa1025b4a6cdbcarll            store( irx_addr, mkU64(0) );
75302831b00c4950d6c2b061def05fd67528fe132ececerion         }
75312831b00c4950d6c2b061def05fd67528fe132ececerion      } else {
75322831b00c4950d6c2b061def05fd67528fe132ececerion         /* Round EA down to the start of the containing block. */
75332831b00c4950d6c2b061def05fd67528fe132ececerion         assign( addr, binop( Iop_And32,
75342831b00c4950d6c2b061def05fd67528fe132ececerion                              mkexpr(EA),
7535e971c6a8b613ab2ea92a34f802a0e39c01e84b19sewardj                              mkU32( ~(clearszB-1) )) );
75362831b00c4950d6c2b061def05fd67528fe132ececerion
7537e971c6a8b613ab2ea92a34f802a0e39c01e84b19sewardj         for (i = 0; i < clearszB / 4; i++) {
75382831b00c4950d6c2b061def05fd67528fe132ececerion            irx_addr = binop( Iop_Add32, mkexpr(addr), mkU32(i*4) );
75391f5fe1fc3a37ca729925e8eec25aa1025b4a6cdbcarll            store( irx_addr, mkU32(0) );
75402831b00c4950d6c2b061def05fd67528fe132ececerion         }
7541094d1397b3f69b1a538e80ab509ea8cd75f4be3bcerion      }
7542b85e8bba97fdae7d892f7bfd12e4601307e4721dcerion      break;
7543094d1397b3f69b1a538e80ab509ea8cd75f4be3bcerion   }
7544b85e8bba97fdae7d892f7bfd12e4601307e4721dcerion
75457ce9d15f4208aa08dfb1e605b3cad53ff03a84e4sewardj   case 0x3D6: {
75467ce9d15f4208aa08dfb1e605b3cad53ff03a84e4sewardj      // icbi (Instruction Cache Block Invalidate, PPC32 p431)
75477ce9d15f4208aa08dfb1e605b3cad53ff03a84e4sewardj      /* Invalidate all translations containing code from the cache
7548d94b73a4ece194130f7a59cca9262d44cf9dbb91sewardj         block at (rA|0) + rB. */
7549d953ebb9b04cbad6891676df597bf0c542b1ec89cerion      IRTemp EA   = newTemp(ty);
7550d953ebb9b04cbad6891676df597bf0c542b1ec89cerion      IRTemp addr = newTemp(ty);
7551d953ebb9b04cbad6891676df597bf0c542b1ec89cerion      DIP("icbi r%u,r%u\n", rA_addr, rB_addr);
7552d953ebb9b04cbad6891676df597bf0c542b1ec89cerion      assign( EA, ea_rAor0_idxd(rA_addr, rB_addr) );
75537ce9d15f4208aa08dfb1e605b3cad53ff03a84e4sewardj
75542831b00c4950d6c2b061def05fd67528fe132ececerion      /* Round EA down to the start of the containing block. */
75552831b00c4950d6c2b061def05fd67528fe132ececerion      assign( addr, binop( mkSzOp(ty, Iop_And8),
7556d953ebb9b04cbad6891676df597bf0c542b1ec89cerion                           mkexpr(EA),
75572831b00c4950d6c2b061def05fd67528fe132ececerion                           mkSzImm(ty, ~(((ULong)lineszB)-1) )) );
755805f5e0172384dd2983fb16fbb7deebd74d71cd35sewardj      putGST( PPC_GST_CMSTART, mkexpr(addr) );
755905f5e0172384dd2983fb16fbb7deebd74d71cd35sewardj      putGST( PPC_GST_CMLEN, mkSzImm(ty, lineszB) );
75607ce9d15f4208aa08dfb1e605b3cad53ff03a84e4sewardj
7561a8078f66b2c4043e5f099cfeb3ebf01e4cc21953sewardj      /* be paranoid ... */
7562c4356f0d3c74fc2622dbeed79c6c1045fc519f72sewardj      stmt( IRStmt_MBE(Imbe_Fence) );
7563a8078f66b2c4043e5f099cfeb3ebf01e4cc21953sewardj
75643dee849ec7c38746749065e67dc53b75daa7617dsewardj      putGST( PPC_GST_CIA, mkSzImm(ty, nextInsnAddr()));
756505f5e0172384dd2983fb16fbb7deebd74d71cd35sewardj      dres->jk_StopHere = Ijk_InvalICache;
75663dee849ec7c38746749065e67dc53b75daa7617dsewardj      dres->whatNext    = Dis_StopHere;
7567b85e8bba97fdae7d892f7bfd12e4601307e4721dcerion      break;
75687ce9d15f4208aa08dfb1e605b3cad53ff03a84e4sewardj   }
75698c3addacc8343f5d1504379e303934f8ed88903ecerion
7570b85e8bba97fdae7d892f7bfd12e4601307e4721dcerion   default:
75715b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion      vex_printf("dis_cache_manage(ppc)(opc2)\n");
7572b85e8bba97fdae7d892f7bfd12e4601307e4721dcerion      return False;
7573b85e8bba97fdae7d892f7bfd12e4601307e4721dcerion   }
7574b85e8bba97fdae7d892f7bfd12e4601307e4721dcerion   return True;
75758c3addacc8343f5d1504379e303934f8ed88903ecerion}
75768c3addacc8343f5d1504379e303934f8ed88903ecerion
75778c3addacc8343f5d1504379e303934f8ed88903ecerion
7578e14bb9f862843c6b804097c124961b5567ded4f1sewardj/*------------------------------------------------------------*/
7579e14bb9f862843c6b804097c124961b5567ded4f1sewardj/*--- Floating Point Helpers                               ---*/
7580e14bb9f862843c6b804097c124961b5567ded4f1sewardj/*------------------------------------------------------------*/
7581e14bb9f862843c6b804097c124961b5567ded4f1sewardj
7582e14bb9f862843c6b804097c124961b5567ded4f1sewardj/* --------- Synthesise a 2-bit FPU rounding mode. --------- */
7583e14bb9f862843c6b804097c124961b5567ded4f1sewardj/* Produces a value in 0 .. 3, which is encoded as per the type
75845b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion   IRRoundingMode.  PPCRoundingMode encoding is different to
7585e14bb9f862843c6b804097c124961b5567ded4f1sewardj   IRRoundingMode, so need to map it.
7586e14bb9f862843c6b804097c124961b5567ded4f1sewardj*/
7587b183b8571b4ec98866ce2b3653a9d066cf5f16f4sewardjstatic IRExpr* /* :: Ity_I32 */ get_IR_roundingmode ( void )
7588e14bb9f862843c6b804097c124961b5567ded4f1sewardj{
7589e14bb9f862843c6b804097c124961b5567ded4f1sewardj/*
7590e14bb9f862843c6b804097c124961b5567ded4f1sewardj   rounding mode | PPC | IR
7591e14bb9f862843c6b804097c124961b5567ded4f1sewardj   ------------------------
7592e14bb9f862843c6b804097c124961b5567ded4f1sewardj   to nearest    | 00  | 00
7593e14bb9f862843c6b804097c124961b5567ded4f1sewardj   to zero       | 01  | 11
7594e14bb9f862843c6b804097c124961b5567ded4f1sewardj   to +infinity  | 10  | 10
7595e14bb9f862843c6b804097c124961b5567ded4f1sewardj   to -infinity  | 11  | 01
7596e14bb9f862843c6b804097c124961b5567ded4f1sewardj*/
7597e14bb9f862843c6b804097c124961b5567ded4f1sewardj   IRTemp rm_PPC32 = newTemp(Ity_I32);
7598d953ebb9b04cbad6891676df597bf0c542b1ec89cerion   assign( rm_PPC32, getGST_masked( PPC_GST_FPSCR, MASK_FPSCR_RN ) );
7599e14bb9f862843c6b804097c124961b5567ded4f1sewardj
7600e14bb9f862843c6b804097c124961b5567ded4f1sewardj   // rm_IR = XOR( rm_PPC32, (rm_PPC32 << 1) & 2)
7601b183b8571b4ec98866ce2b3653a9d066cf5f16f4sewardj   return binop( Iop_Xor32,
7602b183b8571b4ec98866ce2b3653a9d066cf5f16f4sewardj                 mkexpr(rm_PPC32),
7603b183b8571b4ec98866ce2b3653a9d066cf5f16f4sewardj                 binop( Iop_And32,
7604b183b8571b4ec98866ce2b3653a9d066cf5f16f4sewardj                        binop(Iop_Shl32, mkexpr(rm_PPC32), mkU8(1)),
7605b183b8571b4ec98866ce2b3653a9d066cf5f16f4sewardj                        mkU32(2) ));
7606e14bb9f862843c6b804097c124961b5567ded4f1sewardj}
7607094d1397b3f69b1a538e80ab509ea8cd75f4be3bcerion
7608c6bbd470e9bd9898b84959227a406d3972d95f3bsewardj/* The DFP IR rounding modes were chosen such that the existing PPC to IR
7609c6bbd470e9bd9898b84959227a406d3972d95f3bsewardj * mapping would still work with the extended three bit DFP rounding
7610c6bbd470e9bd9898b84959227a406d3972d95f3bsewardj * mode designator.
7611c6bbd470e9bd9898b84959227a406d3972d95f3bsewardj
7612c6bbd470e9bd9898b84959227a406d3972d95f3bsewardj *  rounding mode                     | PPC  |  IR
7613c6bbd470e9bd9898b84959227a406d3972d95f3bsewardj *  -----------------------------------------------
7614c6bbd470e9bd9898b84959227a406d3972d95f3bsewardj *  to nearest, ties to even          | 000  | 000
7615c6bbd470e9bd9898b84959227a406d3972d95f3bsewardj *  to zero                           | 001  | 011
7616c6bbd470e9bd9898b84959227a406d3972d95f3bsewardj *  to +infinity                      | 010  | 010
7617c6bbd470e9bd9898b84959227a406d3972d95f3bsewardj *  to -infinity                      | 011  | 001
7618c6bbd470e9bd9898b84959227a406d3972d95f3bsewardj *  to nearest, ties away from 0      | 100  | 100
7619c6bbd470e9bd9898b84959227a406d3972d95f3bsewardj *  to nearest, ties toward 0         | 101  | 111
7620c6bbd470e9bd9898b84959227a406d3972d95f3bsewardj *  to away from 0                    | 110  | 110
7621c6bbd470e9bd9898b84959227a406d3972d95f3bsewardj *  to prepare for shorter precision  | 111  | 101
7622c6bbd470e9bd9898b84959227a406d3972d95f3bsewardj */
7623c6bbd470e9bd9898b84959227a406d3972d95f3bsewardjstatic IRExpr* /* :: Ity_I32 */ get_IR_roundingmode_DFP( void )
7624c6bbd470e9bd9898b84959227a406d3972d95f3bsewardj{
7625c6bbd470e9bd9898b84959227a406d3972d95f3bsewardj   IRTemp rm_PPC32 = newTemp( Ity_I32 );
7626c6bbd470e9bd9898b84959227a406d3972d95f3bsewardj   assign( rm_PPC32, getGST_masked_upper( PPC_GST_FPSCR, MASK_FPSCR_DRN ) );
7627c6bbd470e9bd9898b84959227a406d3972d95f3bsewardj
7628c6bbd470e9bd9898b84959227a406d3972d95f3bsewardj   // rm_IR = XOR( rm_PPC32, (rm_PPC32 << 1) & 2)
7629c6bbd470e9bd9898b84959227a406d3972d95f3bsewardj   return binop( Iop_Xor32,
7630c6bbd470e9bd9898b84959227a406d3972d95f3bsewardj                 mkexpr( rm_PPC32 ),
7631c6bbd470e9bd9898b84959227a406d3972d95f3bsewardj                 binop( Iop_And32,
7632c6bbd470e9bd9898b84959227a406d3972d95f3bsewardj                        binop( Iop_Shl32, mkexpr( rm_PPC32 ), mkU8( 1 ) ),
7633c6bbd470e9bd9898b84959227a406d3972d95f3bsewardj                        mkU32( 2 ) ) );
7634c6bbd470e9bd9898b84959227a406d3972d95f3bsewardj}
7635094d1397b3f69b1a538e80ab509ea8cd75f4be3bcerion
76362bcdd653612c726da0b7203b579b8f6114703be4sewardj#define NANmaskSingle   0x7F800000
76372bcdd653612c726da0b7203b579b8f6114703be4sewardj#define NANmaskDouble   0x7FF00000
76382bcdd653612c726da0b7203b579b8f6114703be4sewardj
76392bcdd653612c726da0b7203b579b8f6114703be4sewardjstatic IRExpr * Check_NaN( IRExpr * value, IRExpr * Hi32Mask )
76402bcdd653612c726da0b7203b579b8f6114703be4sewardj{
76412bcdd653612c726da0b7203b579b8f6114703be4sewardj   IRTemp exp_zero  = newTemp(Ity_I8);
76422bcdd653612c726da0b7203b579b8f6114703be4sewardj   IRTemp frac_mask = newTemp(Ity_I32);
76432bcdd653612c726da0b7203b579b8f6114703be4sewardj   IRTemp frac_not_zero = newTemp(Ity_I8);
76442bcdd653612c726da0b7203b579b8f6114703be4sewardj
76452bcdd653612c726da0b7203b579b8f6114703be4sewardj   /* Check if the result is QNAN or SNAN and not +infinity or -infinity.
76462bcdd653612c726da0b7203b579b8f6114703be4sewardj    * The input value is always 64-bits, for single precision values, the
76472bcdd653612c726da0b7203b579b8f6114703be4sewardj    * lower 32 bits must be zero.
76482bcdd653612c726da0b7203b579b8f6114703be4sewardj    *
76492bcdd653612c726da0b7203b579b8f6114703be4sewardj    * Single Pricision
76502bcdd653612c726da0b7203b579b8f6114703be4sewardj    *  [62:54] exponent field is equal to 0xFF for NAN and Infinity.
76512bcdd653612c726da0b7203b579b8f6114703be4sewardj    *  [53:32] fraction field is zero for Infinity and non-zero for NAN
76522bcdd653612c726da0b7203b579b8f6114703be4sewardj    *  [31:0]  unused for single precision representation
76532bcdd653612c726da0b7203b579b8f6114703be4sewardj    *
76542bcdd653612c726da0b7203b579b8f6114703be4sewardj    * Double Pricision
76552bcdd653612c726da0b7203b579b8f6114703be4sewardj    *  [62:51] exponent field is equal to 0xFF for NAN and Infinity.
76562bcdd653612c726da0b7203b579b8f6114703be4sewardj    *  [50:0]  fraction field is zero for Infinity and non-zero for NAN
76572bcdd653612c726da0b7203b579b8f6114703be4sewardj    *
76582bcdd653612c726da0b7203b579b8f6114703be4sewardj    * Returned result is a U32 value of 0xFFFFFFFF for NaN and 0 otherwise.
76592bcdd653612c726da0b7203b579b8f6114703be4sewardj    */
76602bcdd653612c726da0b7203b579b8f6114703be4sewardj   assign( frac_mask, unop( Iop_Not32,
76612bcdd653612c726da0b7203b579b8f6114703be4sewardj                            binop( Iop_Or32,
76622bcdd653612c726da0b7203b579b8f6114703be4sewardj                                   mkU32( 0x80000000ULL ), Hi32Mask) ) );
76632bcdd653612c726da0b7203b579b8f6114703be4sewardj
76642bcdd653612c726da0b7203b579b8f6114703be4sewardj   assign( exp_zero,
76652bcdd653612c726da0b7203b579b8f6114703be4sewardj           unop( Iop_1Sto8,
76662bcdd653612c726da0b7203b579b8f6114703be4sewardj                 binop( Iop_CmpEQ32,
76672bcdd653612c726da0b7203b579b8f6114703be4sewardj                        binop( Iop_And32,
76682bcdd653612c726da0b7203b579b8f6114703be4sewardj                               unop( Iop_64HIto32,
76692bcdd653612c726da0b7203b579b8f6114703be4sewardj                                     unop( Iop_ReinterpF64asI64,
76702bcdd653612c726da0b7203b579b8f6114703be4sewardj                                           value ) ),
76712bcdd653612c726da0b7203b579b8f6114703be4sewardj                               Hi32Mask ),
76722bcdd653612c726da0b7203b579b8f6114703be4sewardj                        Hi32Mask ) ) );
76732bcdd653612c726da0b7203b579b8f6114703be4sewardj   assign( frac_not_zero,
76742bcdd653612c726da0b7203b579b8f6114703be4sewardj           binop( Iop_Or8,
76752bcdd653612c726da0b7203b579b8f6114703be4sewardj                  unop( Iop_1Sto8,
76762bcdd653612c726da0b7203b579b8f6114703be4sewardj                        binop( Iop_CmpNE32,
76772bcdd653612c726da0b7203b579b8f6114703be4sewardj                               binop( Iop_And32,
76782bcdd653612c726da0b7203b579b8f6114703be4sewardj                                      unop( Iop_64HIto32,
76792bcdd653612c726da0b7203b579b8f6114703be4sewardj                                            unop( Iop_ReinterpF64asI64,
76802bcdd653612c726da0b7203b579b8f6114703be4sewardj                                                  value ) ),
76812bcdd653612c726da0b7203b579b8f6114703be4sewardj                                      mkexpr( frac_mask ) ),
76822bcdd653612c726da0b7203b579b8f6114703be4sewardj                               mkU32( 0x0 ) ) ),
76832bcdd653612c726da0b7203b579b8f6114703be4sewardj                  unop( Iop_1Sto8,
76842bcdd653612c726da0b7203b579b8f6114703be4sewardj                        binop( Iop_CmpNE32,
76852bcdd653612c726da0b7203b579b8f6114703be4sewardj                               binop( Iop_And32,
76862bcdd653612c726da0b7203b579b8f6114703be4sewardj                                      unop( Iop_64to32,
76872bcdd653612c726da0b7203b579b8f6114703be4sewardj                                            unop( Iop_ReinterpF64asI64,
76882bcdd653612c726da0b7203b579b8f6114703be4sewardj                                                  value ) ),
76892bcdd653612c726da0b7203b579b8f6114703be4sewardj                                      mkU32( 0xFFFFFFFF ) ),
76902bcdd653612c726da0b7203b579b8f6114703be4sewardj                               mkU32( 0x0 ) ) ) ) );
76912bcdd653612c726da0b7203b579b8f6114703be4sewardj   return unop( Iop_8Sto32,
76922bcdd653612c726da0b7203b579b8f6114703be4sewardj                binop( Iop_And8,
76932bcdd653612c726da0b7203b579b8f6114703be4sewardj                       mkexpr( exp_zero ),
76942bcdd653612c726da0b7203b579b8f6114703be4sewardj                       mkexpr( frac_not_zero ) ) );
76952bcdd653612c726da0b7203b579b8f6114703be4sewardj}
76962bcdd653612c726da0b7203b579b8f6114703be4sewardj
76972bcdd653612c726da0b7203b579b8f6114703be4sewardjstatic IRExpr * Complement_non_NaN( IRExpr * value, IRExpr * nan_mask )
76982bcdd653612c726da0b7203b579b8f6114703be4sewardj{
76992bcdd653612c726da0b7203b579b8f6114703be4sewardj   /* This function will only complement the 64-bit floating point value if it
77002bcdd653612c726da0b7203b579b8f6114703be4sewardj    * is not Nan.  NaN is not a signed value.  Need to do computations using
77012bcdd653612c726da0b7203b579b8f6114703be4sewardj    * 32-bit operands to ensure it will run in 32-bit mode.
77022bcdd653612c726da0b7203b579b8f6114703be4sewardj    */
77032bcdd653612c726da0b7203b579b8f6114703be4sewardj   return  binop( Iop_32HLto64,
77042bcdd653612c726da0b7203b579b8f6114703be4sewardj                  binop( Iop_Or32,
77052bcdd653612c726da0b7203b579b8f6114703be4sewardj                         binop( Iop_And32,
77062bcdd653612c726da0b7203b579b8f6114703be4sewardj                                nan_mask,
77072bcdd653612c726da0b7203b579b8f6114703be4sewardj                                unop( Iop_64HIto32,
77082bcdd653612c726da0b7203b579b8f6114703be4sewardj                                      unop( Iop_ReinterpF64asI64,
77092bcdd653612c726da0b7203b579b8f6114703be4sewardj                                            value ) ) ),
77102bcdd653612c726da0b7203b579b8f6114703be4sewardj                         binop( Iop_And32,
77112bcdd653612c726da0b7203b579b8f6114703be4sewardj                                unop( Iop_Not32,
77122bcdd653612c726da0b7203b579b8f6114703be4sewardj                                      nan_mask ),
77132bcdd653612c726da0b7203b579b8f6114703be4sewardj                                unop( Iop_64HIto32,
77142bcdd653612c726da0b7203b579b8f6114703be4sewardj                                      unop( Iop_ReinterpF64asI64,
77152bcdd653612c726da0b7203b579b8f6114703be4sewardj                                            unop( Iop_NegF64,
77162bcdd653612c726da0b7203b579b8f6114703be4sewardj                                                  value ) ) ) ) ),
77172bcdd653612c726da0b7203b579b8f6114703be4sewardj                  unop( Iop_64to32,
77182bcdd653612c726da0b7203b579b8f6114703be4sewardj                        unop( Iop_ReinterpF64asI64, value ) ) );
77192bcdd653612c726da0b7203b579b8f6114703be4sewardj}
77202bcdd653612c726da0b7203b579b8f6114703be4sewardj
77213d870a39e4d145e2f3d9f9a0eeed3475ec934ac1cerion/*------------------------------------------------------------*/
77223d870a39e4d145e2f3d9f9a0eeed3475ec934ac1cerion/*--- Floating Point Instruction Translation               ---*/
77233d870a39e4d145e2f3d9f9a0eeed3475ec934ac1cerion/*------------------------------------------------------------*/
77243d870a39e4d145e2f3d9f9a0eeed3475ec934ac1cerion
77253d870a39e4d145e2f3d9f9a0eeed3475ec934ac1cerion/*
77263d870a39e4d145e2f3d9f9a0eeed3475ec934ac1cerion  Floating Point Load Instructions
77273d870a39e4d145e2f3d9f9a0eeed3475ec934ac1cerion*/
77283d870a39e4d145e2f3d9f9a0eeed3475ec934ac1cerionstatic Bool dis_fp_load ( UInt theInstr )
77293d870a39e4d145e2f3d9f9a0eeed3475ec934ac1cerion{
773076de5cf615380b23b4b5bcced6541233cd4a93a0cerion   /* X-Form, D-Form */
773176de5cf615380b23b4b5bcced6541233cd4a93a0cerion   UChar opc1      = ifieldOPC(theInstr);
773276de5cf615380b23b4b5bcced6541233cd4a93a0cerion   UChar frD_addr  = ifieldRegDS(theInstr);
773376de5cf615380b23b4b5bcced6541233cd4a93a0cerion   UChar rA_addr   = ifieldRegA(theInstr);
773476de5cf615380b23b4b5bcced6541233cd4a93a0cerion   UChar rB_addr   = ifieldRegB(theInstr);
773576de5cf615380b23b4b5bcced6541233cd4a93a0cerion   UInt  opc2      = ifieldOPClo10(theInstr);
773676de5cf615380b23b4b5bcced6541233cd4a93a0cerion   UChar b0        = ifieldBIT0(theInstr);
77372831b00c4950d6c2b061def05fd67528fe132ececerion   UInt  uimm16    = ifieldUIMM16(theInstr);
7738d953ebb9b04cbad6891676df597bf0c542b1ec89cerion
77392831b00c4950d6c2b061def05fd67528fe132ececerion   Int    simm16 = extend_s_16to32(uimm16);
77402831b00c4950d6c2b061def05fd67528fe132ececerion   IRType ty     = mode64 ? Ity_I64 : Ity_I32;
77412831b00c4950d6c2b061def05fd67528fe132ececerion   IRTemp EA     = newTemp(ty);
77422831b00c4950d6c2b061def05fd67528fe132ececerion   IRTemp rA     = newTemp(ty);
77432831b00c4950d6c2b061def05fd67528fe132ececerion   IRTemp rB     = newTemp(ty);
77447e84630580f89c1022dde97007bffbf6aef81814sewardj   IRTemp iHi    = newTemp(Ity_I32);
77457e84630580f89c1022dde97007bffbf6aef81814sewardj   IRTemp iLo    = newTemp(Ity_I32);
7746094d1397b3f69b1a538e80ab509ea8cd75f4be3bcerion
7747094d1397b3f69b1a538e80ab509ea8cd75f4be3bcerion   assign( rA, getIReg(rA_addr) );
7748094d1397b3f69b1a538e80ab509ea8cd75f4be3bcerion   assign( rB, getIReg(rB_addr) );
7749d953ebb9b04cbad6891676df597bf0c542b1ec89cerion
7750b183b8571b4ec98866ce2b3653a9d066cf5f16f4sewardj   /* These are completely straightforward from a rounding and status
7751b183b8571b4ec98866ce2b3653a9d066cf5f16f4sewardj      bits perspective: no rounding involved and no funny status or CR
7752b183b8571b4ec98866ce2b3653a9d066cf5f16f4sewardj      bits affected. */
77533d870a39e4d145e2f3d9f9a0eeed3475ec934ac1cerion
7754b183b8571b4ec98866ce2b3653a9d066cf5f16f4sewardj   switch (opc1) {
7755e14bb9f862843c6b804097c124961b5567ded4f1sewardj   case 0x30: // lfs (Load Float Single, PPC32 p441)
7756d953ebb9b04cbad6891676df597bf0c542b1ec89cerion      DIP("lfs fr%u,%d(r%u)\n", frD_addr, simm16, rA_addr);
7757d953ebb9b04cbad6891676df597bf0c542b1ec89cerion      assign( EA, ea_rAor0_simm(rA_addr, simm16) );
77585b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion      putFReg( frD_addr,
77591f5fe1fc3a37ca729925e8eec25aa1025b4a6cdbcarll               unop(Iop_F32toF64, load(Ity_F32, mkexpr(EA))) );
7760e14bb9f862843c6b804097c124961b5567ded4f1sewardj      break;
7761e14bb9f862843c6b804097c124961b5567ded4f1sewardj
77625b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion   case 0x31: // lfsu (Load Float Single, Update, PPC32 p442)
7763b183b8571b4ec98866ce2b3653a9d066cf5f16f4sewardj      if (rA_addr == 0)
7764729edb7804bac750fe5fb0ce079e8fb965653e67cerion         return False;
7765729edb7804bac750fe5fb0ce079e8fb965653e67cerion      DIP("lfsu fr%u,%d(r%u)\n", frD_addr, simm16, rA_addr);
7766729edb7804bac750fe5fb0ce079e8fb965653e67cerion      assign( EA, ea_rA_simm(rA_addr, simm16) );
77675b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion      putFReg( frD_addr,
77681f5fe1fc3a37ca729925e8eec25aa1025b4a6cdbcarll               unop(Iop_F32toF64, load(Ity_F32, mkexpr(EA))) );
7769729edb7804bac750fe5fb0ce079e8fb965653e67cerion      putIReg( rA_addr, mkexpr(EA) );
7770729edb7804bac750fe5fb0ce079e8fb965653e67cerion      break;
7771094d1397b3f69b1a538e80ab509ea8cd75f4be3bcerion
7772094d1397b3f69b1a538e80ab509ea8cd75f4be3bcerion   case 0x32: // lfd (Load Float Double, PPC32 p437)
7773d953ebb9b04cbad6891676df597bf0c542b1ec89cerion      DIP("lfd fr%u,%d(r%u)\n", frD_addr, simm16, rA_addr);
7774d953ebb9b04cbad6891676df597bf0c542b1ec89cerion      assign( EA, ea_rAor0_simm(rA_addr, simm16) );
77751f5fe1fc3a37ca729925e8eec25aa1025b4a6cdbcarll      putFReg( frD_addr, load(Ity_F64, mkexpr(EA)) );
7776094d1397b3f69b1a538e80ab509ea8cd75f4be3bcerion      break;
77773d870a39e4d145e2f3d9f9a0eeed3475ec934ac1cerion
77785b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion   case 0x33: // lfdu (Load Float Double, Update, PPC32 p438)
7779b183b8571b4ec98866ce2b3653a9d066cf5f16f4sewardj      if (rA_addr == 0)
77800e2cc67b30d1bb4d0515a1e09d944143becb3881sewardj         return False;
7781d953ebb9b04cbad6891676df597bf0c542b1ec89cerion      DIP("lfdu fr%u,%d(r%u)\n", frD_addr, simm16, rA_addr);
7782d953ebb9b04cbad6891676df597bf0c542b1ec89cerion      assign( EA, ea_rA_simm(rA_addr, simm16) );
77831f5fe1fc3a37ca729925e8eec25aa1025b4a6cdbcarll      putFReg( frD_addr, load(Ity_F64, mkexpr(EA)) );
77840e2cc67b30d1bb4d0515a1e09d944143becb3881sewardj      putIReg( rA_addr, mkexpr(EA) );
77850e2cc67b30d1bb4d0515a1e09d944143becb3881sewardj      break;
7786e14bb9f862843c6b804097c124961b5567ded4f1sewardj
7787e14bb9f862843c6b804097c124961b5567ded4f1sewardj   case 0x1F:
7788e14bb9f862843c6b804097c124961b5567ded4f1sewardj      if (b0 != 0) {
77895b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion         vex_printf("dis_fp_load(ppc)(instr,b0)\n");
7790e14bb9f862843c6b804097c124961b5567ded4f1sewardj         return False;
7791e14bb9f862843c6b804097c124961b5567ded4f1sewardj      }
7792e14bb9f862843c6b804097c124961b5567ded4f1sewardj
7793e14bb9f862843c6b804097c124961b5567ded4f1sewardj      switch(opc2) {
7794d953ebb9b04cbad6891676df597bf0c542b1ec89cerion      case 0x217: // lfsx (Load Float Single Indexed, PPC32 p444)
7795d953ebb9b04cbad6891676df597bf0c542b1ec89cerion         DIP("lfsx fr%u,r%u,r%u\n", frD_addr, rA_addr, rB_addr);
7796d953ebb9b04cbad6891676df597bf0c542b1ec89cerion         assign( EA, ea_rAor0_idxd(rA_addr, rB_addr) );
7797d953ebb9b04cbad6891676df597bf0c542b1ec89cerion         putFReg( frD_addr, unop( Iop_F32toF64,
77981f5fe1fc3a37ca729925e8eec25aa1025b4a6cdbcarll                                  load(Ity_F32, mkexpr(EA))) );
7799d953ebb9b04cbad6891676df597bf0c542b1ec89cerion         break;
7800d953ebb9b04cbad6891676df597bf0c542b1ec89cerion
78015b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion      case 0x237: // lfsux (Load Float Single, Update Indxd, PPC32 p443)
7802b183b8571b4ec98866ce2b3653a9d066cf5f16f4sewardj         if (rA_addr == 0)
7803d953ebb9b04cbad6891676df597bf0c542b1ec89cerion            return False;
7804d953ebb9b04cbad6891676df597bf0c542b1ec89cerion         DIP("lfsux fr%u,r%u,r%u\n", frD_addr, rA_addr, rB_addr);
7805d953ebb9b04cbad6891676df597bf0c542b1ec89cerion         assign( EA, ea_rA_idxd(rA_addr, rB_addr) );
78065b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion         putFReg( frD_addr,
78071f5fe1fc3a37ca729925e8eec25aa1025b4a6cdbcarll                  unop(Iop_F32toF64, load(Ity_F32, mkexpr(EA))) );
7808d953ebb9b04cbad6891676df597bf0c542b1ec89cerion         putIReg( rA_addr, mkexpr(EA) );
7809d953ebb9b04cbad6891676df597bf0c542b1ec89cerion         break;
7810d953ebb9b04cbad6891676df597bf0c542b1ec89cerion
7811d953ebb9b04cbad6891676df597bf0c542b1ec89cerion      case 0x257: // lfdx (Load Float Double Indexed, PPC32 p440)
7812d953ebb9b04cbad6891676df597bf0c542b1ec89cerion         DIP("lfdx fr%u,r%u,r%u\n", frD_addr, rA_addr, rB_addr);
7813d953ebb9b04cbad6891676df597bf0c542b1ec89cerion         assign( EA, ea_rAor0_idxd(rA_addr, rB_addr) );
78141f5fe1fc3a37ca729925e8eec25aa1025b4a6cdbcarll         putFReg( frD_addr, load(Ity_F64, mkexpr(EA)) );
7815d953ebb9b04cbad6891676df597bf0c542b1ec89cerion         break;
7816d953ebb9b04cbad6891676df597bf0c542b1ec89cerion
78175b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion      case 0x277: // lfdux (Load Float Double, Update Indxd, PPC32 p439)
7818b183b8571b4ec98866ce2b3653a9d066cf5f16f4sewardj         if (rA_addr == 0)
7819e14bb9f862843c6b804097c124961b5567ded4f1sewardj            return False;
7820d953ebb9b04cbad6891676df597bf0c542b1ec89cerion         DIP("lfdux fr%u,r%u,r%u\n", frD_addr, rA_addr, rB_addr);
7821d953ebb9b04cbad6891676df597bf0c542b1ec89cerion         assign( EA, ea_rA_idxd(rA_addr, rB_addr) );
78221f5fe1fc3a37ca729925e8eec25aa1025b4a6cdbcarll         putFReg( frD_addr, load(Ity_F64, mkexpr(EA)) );
7823d953ebb9b04cbad6891676df597bf0c542b1ec89cerion         putIReg( rA_addr, mkexpr(EA) );
7824d953ebb9b04cbad6891676df597bf0c542b1ec89cerion         break;
7825d953ebb9b04cbad6891676df597bf0c542b1ec89cerion
78267e84630580f89c1022dde97007bffbf6aef81814sewardj      case 0x357: // lfiwax (Load Float As Integer, Indxd, ISA 2.05 p120)
78277e84630580f89c1022dde97007bffbf6aef81814sewardj         DIP("lfiwax fr%u,r%u,r%u\n", frD_addr, rA_addr, rB_addr);
78287e84630580f89c1022dde97007bffbf6aef81814sewardj         assign( EA, ea_rAor0_idxd( rA_addr, rB_addr ) );
78291f5fe1fc3a37ca729925e8eec25aa1025b4a6cdbcarll         assign( iLo, load(Ity_I32, mkexpr(EA)) );
78307e84630580f89c1022dde97007bffbf6aef81814sewardj         assign( iHi, binop(Iop_Sub32,
78317e84630580f89c1022dde97007bffbf6aef81814sewardj                            mkU32(0),
78327e84630580f89c1022dde97007bffbf6aef81814sewardj                            binop(Iop_Shr32, mkexpr(iLo), mkU8(31)))  );
78337e84630580f89c1022dde97007bffbf6aef81814sewardj         putFReg( frD_addr, unop(Iop_ReinterpI64asF64,
78347e84630580f89c1022dde97007bffbf6aef81814sewardj                                 binop(Iop_32HLto64, mkexpr(iHi), mkexpr(iLo))) );
78357e84630580f89c1022dde97007bffbf6aef81814sewardj         break;
78367e84630580f89c1022dde97007bffbf6aef81814sewardj
783766d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj      case 0x377: // lfiwzx (Load floating-point as integer word, zero indexed
783866d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj      {
783966d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj         IRTemp dw = newTemp( Ity_I64 );
784066d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj         DIP("lfiwzx fr%u,r%u,r%u\n", frD_addr, rA_addr, rB_addr);
784166d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj         assign( EA, ea_rAor0_idxd( rA_addr, rB_addr ) );
78421f5fe1fc3a37ca729925e8eec25aa1025b4a6cdbcarll         assign( iLo, load(Ity_I32, mkexpr(EA)) );
784366d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj         assign( dw, binop( Iop_32HLto64, mkU32( 0 ), mkexpr( iLo ) ) );
784466d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj         putFReg( frD_addr, unop( Iop_ReinterpI64asF64, mkexpr( dw ) ) );
784566d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj         break;
784666d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj      }
784766d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj
7848d953ebb9b04cbad6891676df597bf0c542b1ec89cerion      default:
78495b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion         vex_printf("dis_fp_load(ppc)(opc2)\n");
7850d953ebb9b04cbad6891676df597bf0c542b1ec89cerion         return False;
7851e14bb9f862843c6b804097c124961b5567ded4f1sewardj      }
7852e14bb9f862843c6b804097c124961b5567ded4f1sewardj      break;
78533d870a39e4d145e2f3d9f9a0eeed3475ec934ac1cerion
78543d870a39e4d145e2f3d9f9a0eeed3475ec934ac1cerion   default:
78555b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion      vex_printf("dis_fp_load(ppc)(opc1)\n");
78563d870a39e4d145e2f3d9f9a0eeed3475ec934ac1cerion      return False;
78573d870a39e4d145e2f3d9f9a0eeed3475ec934ac1cerion   }
78583d870a39e4d145e2f3d9f9a0eeed3475ec934ac1cerion   return True;
78593d870a39e4d145e2f3d9f9a0eeed3475ec934ac1cerion}
78603d870a39e4d145e2f3d9f9a0eeed3475ec934ac1cerion
78613d870a39e4d145e2f3d9f9a0eeed3475ec934ac1cerion
78623d870a39e4d145e2f3d9f9a0eeed3475ec934ac1cerion
78633d870a39e4d145e2f3d9f9a0eeed3475ec934ac1cerion/*
78643d870a39e4d145e2f3d9f9a0eeed3475ec934ac1cerion  Floating Point Store Instructions
78653d870a39e4d145e2f3d9f9a0eeed3475ec934ac1cerion*/
78663d870a39e4d145e2f3d9f9a0eeed3475ec934ac1cerionstatic Bool dis_fp_store ( UInt theInstr )
78673d870a39e4d145e2f3d9f9a0eeed3475ec934ac1cerion{
786876de5cf615380b23b4b5bcced6541233cd4a93a0cerion   /* X-Form, D-Form */
786976de5cf615380b23b4b5bcced6541233cd4a93a0cerion   UChar opc1      = ifieldOPC(theInstr);
787076de5cf615380b23b4b5bcced6541233cd4a93a0cerion   UChar frS_addr  = ifieldRegDS(theInstr);
787176de5cf615380b23b4b5bcced6541233cd4a93a0cerion   UChar rA_addr   = ifieldRegA(theInstr);
787276de5cf615380b23b4b5bcced6541233cd4a93a0cerion   UChar rB_addr   = ifieldRegB(theInstr);
787376de5cf615380b23b4b5bcced6541233cd4a93a0cerion   UInt  opc2      = ifieldOPClo10(theInstr);
787476de5cf615380b23b4b5bcced6541233cd4a93a0cerion   UChar b0        = ifieldBIT0(theInstr);
7875d953ebb9b04cbad6891676df597bf0c542b1ec89cerion   Int   uimm16    = ifieldUIMM16(theInstr);
7876094d1397b3f69b1a538e80ab509ea8cd75f4be3bcerion
78772831b00c4950d6c2b061def05fd67528fe132ececerion   Int    simm16 = extend_s_16to32(uimm16);
78782831b00c4950d6c2b061def05fd67528fe132ececerion   IRTemp frS    = newTemp(Ity_F64);
78792831b00c4950d6c2b061def05fd67528fe132ececerion   IRType ty     = mode64 ? Ity_I64 : Ity_I32;
78802831b00c4950d6c2b061def05fd67528fe132ececerion   IRTemp EA     = newTemp(ty);
78812831b00c4950d6c2b061def05fd67528fe132ececerion   IRTemp rA     = newTemp(ty);
78822831b00c4950d6c2b061def05fd67528fe132ececerion   IRTemp rB     = newTemp(ty);
7883a982c0503d8c0c6069ae453bfe70657bd2c134aecerion
7884b51f0f4f33256638ed953156a2635aa739b232f1sewardj   assign( frS, getFReg(frS_addr) );
7885edf7fc572e2decb93e9143961e8739c8fe18899dcerion   assign( rA,  getIReg(rA_addr) );
7886edf7fc572e2decb93e9143961e8739c8fe18899dcerion   assign( rB,  getIReg(rB_addr) );
7887a982c0503d8c0c6069ae453bfe70657bd2c134aecerion
7888b183b8571b4ec98866ce2b3653a9d066cf5f16f4sewardj   /* These are straightforward from a status bits perspective: no
7889b183b8571b4ec98866ce2b3653a9d066cf5f16f4sewardj      funny status or CR bits affected.  For single precision stores,
7890b183b8571b4ec98866ce2b3653a9d066cf5f16f4sewardj      the values are truncated and denormalised (not rounded) to turn
7891b183b8571b4ec98866ce2b3653a9d066cf5f16f4sewardj      them into single precision values. */
7892b183b8571b4ec98866ce2b3653a9d066cf5f16f4sewardj
7893b183b8571b4ec98866ce2b3653a9d066cf5f16f4sewardj   switch (opc1) {
7894e14bb9f862843c6b804097c124961b5567ded4f1sewardj
7895e14bb9f862843c6b804097c124961b5567ded4f1sewardj   case 0x34: // stfs (Store Float Single, PPC32 p518)
7896d953ebb9b04cbad6891676df597bf0c542b1ec89cerion      DIP("stfs fr%u,%d(r%u)\n", frS_addr, simm16, rA_addr);
7897d953ebb9b04cbad6891676df597bf0c542b1ec89cerion      assign( EA, ea_rAor0_simm(rA_addr, simm16) );
7898b183b8571b4ec98866ce2b3653a9d066cf5f16f4sewardj      /* Use Iop_TruncF64asF32 to truncate and possible denormalise
7899b183b8571b4ec98866ce2b3653a9d066cf5f16f4sewardj         the value to be stored in the correct way, without any
7900b183b8571b4ec98866ce2b3653a9d066cf5f16f4sewardj         rounding. */
79011f5fe1fc3a37ca729925e8eec25aa1025b4a6cdbcarll      store( mkexpr(EA), unop(Iop_TruncF64asF32, mkexpr(frS)) );
7902e14bb9f862843c6b804097c124961b5567ded4f1sewardj      break;
7903e14bb9f862843c6b804097c124961b5567ded4f1sewardj
79045b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion   case 0x35: // stfsu (Store Float Single, Update, PPC32 p519)
7905b183b8571b4ec98866ce2b3653a9d066cf5f16f4sewardj      if (rA_addr == 0)
7906729edb7804bac750fe5fb0ce079e8fb965653e67cerion         return False;
7907729edb7804bac750fe5fb0ce079e8fb965653e67cerion      DIP("stfsu fr%u,%d(r%u)\n", frS_addr, simm16, rA_addr);
7908729edb7804bac750fe5fb0ce079e8fb965653e67cerion      assign( EA, ea_rA_simm(rA_addr, simm16) );
7909b183b8571b4ec98866ce2b3653a9d066cf5f16f4sewardj      /* See comment for stfs */
79101f5fe1fc3a37ca729925e8eec25aa1025b4a6cdbcarll      store( mkexpr(EA), unop(Iop_TruncF64asF32, mkexpr(frS)) );
7911729edb7804bac750fe5fb0ce079e8fb965653e67cerion      putIReg( rA_addr, mkexpr(EA) );
7912729edb7804bac750fe5fb0ce079e8fb965653e67cerion      break;
7913a982c0503d8c0c6069ae453bfe70657bd2c134aecerion
7914b51f0f4f33256638ed953156a2635aa739b232f1sewardj   case 0x36: // stfd (Store Float Double, PPC32 p513)
7915d953ebb9b04cbad6891676df597bf0c542b1ec89cerion      DIP("stfd fr%u,%d(r%u)\n", frS_addr, simm16, rA_addr);
7916d953ebb9b04cbad6891676df597bf0c542b1ec89cerion      assign( EA, ea_rAor0_simm(rA_addr, simm16) );
79171f5fe1fc3a37ca729925e8eec25aa1025b4a6cdbcarll      store( mkexpr(EA), mkexpr(frS) );
7918b51f0f4f33256638ed953156a2635aa739b232f1sewardj      break;
7919a982c0503d8c0c6069ae453bfe70657bd2c134aecerion
79205b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion   case 0x37: // stfdu (Store Float Double, Update, PPC32 p514)
7921b183b8571b4ec98866ce2b3653a9d066cf5f16f4sewardj      if (rA_addr == 0)
7922e14bb9f862843c6b804097c124961b5567ded4f1sewardj         return False;
7923d953ebb9b04cbad6891676df597bf0c542b1ec89cerion      DIP("stfdu fr%u,%d(r%u)\n", frS_addr, simm16, rA_addr);
7924d953ebb9b04cbad6891676df597bf0c542b1ec89cerion      assign( EA, ea_rA_simm(rA_addr, simm16) );
79251f5fe1fc3a37ca729925e8eec25aa1025b4a6cdbcarll      store( mkexpr(EA), mkexpr(frS) );
7926e14bb9f862843c6b804097c124961b5567ded4f1sewardj      putIReg( rA_addr, mkexpr(EA) );
7927e14bb9f862843c6b804097c124961b5567ded4f1sewardj      break;
7928e14bb9f862843c6b804097c124961b5567ded4f1sewardj
7929e14bb9f862843c6b804097c124961b5567ded4f1sewardj   case 0x1F:
7930e14bb9f862843c6b804097c124961b5567ded4f1sewardj      if (b0 != 0) {
79315b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion         vex_printf("dis_fp_store(ppc)(instr,b0)\n");
7932e14bb9f862843c6b804097c124961b5567ded4f1sewardj         return False;
7933e14bb9f862843c6b804097c124961b5567ded4f1sewardj      }
7934e14bb9f862843c6b804097c124961b5567ded4f1sewardj      switch(opc2) {
7935d953ebb9b04cbad6891676df597bf0c542b1ec89cerion      case 0x297: // stfsx (Store Float Single Indexed, PPC32 p521)
7936d953ebb9b04cbad6891676df597bf0c542b1ec89cerion         DIP("stfsx fr%u,r%u,r%u\n", frS_addr, rA_addr, rB_addr);
7937d953ebb9b04cbad6891676df597bf0c542b1ec89cerion         assign( EA, ea_rAor0_idxd(rA_addr, rB_addr) );
7938b183b8571b4ec98866ce2b3653a9d066cf5f16f4sewardj         /* See note for stfs */
79391f5fe1fc3a37ca729925e8eec25aa1025b4a6cdbcarll         store( mkexpr(EA),
79401f5fe1fc3a37ca729925e8eec25aa1025b4a6cdbcarll                unop(Iop_TruncF64asF32, mkexpr(frS)) );
7941d953ebb9b04cbad6891676df597bf0c542b1ec89cerion         break;
7942d953ebb9b04cbad6891676df597bf0c542b1ec89cerion
79435b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion      case 0x2B7: // stfsux (Store Float Sgl, Update Indxd, PPC32 p520)
7944b183b8571b4ec98866ce2b3653a9d066cf5f16f4sewardj         if (rA_addr == 0)
7945729edb7804bac750fe5fb0ce079e8fb965653e67cerion            return False;
7946729edb7804bac750fe5fb0ce079e8fb965653e67cerion         DIP("stfsux fr%u,r%u,r%u\n", frS_addr, rA_addr, rB_addr);
7947729edb7804bac750fe5fb0ce079e8fb965653e67cerion         assign( EA, ea_rA_idxd(rA_addr, rB_addr) );
7948b183b8571b4ec98866ce2b3653a9d066cf5f16f4sewardj         /* See note for stfs */
79491f5fe1fc3a37ca729925e8eec25aa1025b4a6cdbcarll         store( mkexpr(EA), unop(Iop_TruncF64asF32, mkexpr(frS)) );
7950729edb7804bac750fe5fb0ce079e8fb965653e67cerion         putIReg( rA_addr, mkexpr(EA) );
7951729edb7804bac750fe5fb0ce079e8fb965653e67cerion         break;
7952e14bb9f862843c6b804097c124961b5567ded4f1sewardj
7953d953ebb9b04cbad6891676df597bf0c542b1ec89cerion      case 0x2D7: // stfdx (Store Float Double Indexed, PPC32 p516)
7954d953ebb9b04cbad6891676df597bf0c542b1ec89cerion         DIP("stfdx fr%u,r%u,r%u\n", frS_addr, rA_addr, rB_addr);
7955d953ebb9b04cbad6891676df597bf0c542b1ec89cerion         assign( EA, ea_rAor0_idxd(rA_addr, rB_addr) );
79561f5fe1fc3a37ca729925e8eec25aa1025b4a6cdbcarll         store( mkexpr(EA), mkexpr(frS) );
7957d953ebb9b04cbad6891676df597bf0c542b1ec89cerion         break;
7958e14bb9f862843c6b804097c124961b5567ded4f1sewardj
79595b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion      case 0x2F7: // stfdux (Store Float Dbl, Update Indxd, PPC32 p515)
7960b183b8571b4ec98866ce2b3653a9d066cf5f16f4sewardj         if (rA_addr == 0)
7961d953ebb9b04cbad6891676df597bf0c542b1ec89cerion            return False;
7962d953ebb9b04cbad6891676df597bf0c542b1ec89cerion         DIP("stfdux fr%u,r%u,r%u\n", frS_addr, rA_addr, rB_addr);
7963d953ebb9b04cbad6891676df597bf0c542b1ec89cerion         assign( EA, ea_rA_idxd(rA_addr, rB_addr) );
79641f5fe1fc3a37ca729925e8eec25aa1025b4a6cdbcarll         store( mkexpr(EA), mkexpr(frS) );
7965d953ebb9b04cbad6891676df597bf0c542b1ec89cerion         putIReg( rA_addr, mkexpr(EA) );
7966d953ebb9b04cbad6891676df597bf0c542b1ec89cerion         break;
79675f63c0ca784e4d23aca807ebd967ca46bdf95132sewardj
796809e88d11fceef4483f7803414b939e4173fe7f54sewardj      case 0x3D7: // stfiwx (Store Float as Int, Indexed, PPC32 p517)
79695117ce116f47141cb23d1b49cc826e19323add97sewardj         // NOTE: POWERPC OPTIONAL, "Graphics Group" (PPC32_GX)
797009e88d11fceef4483f7803414b939e4173fe7f54sewardj         DIP("stfiwx fr%u,r%u,r%u\n", frS_addr, rA_addr, rB_addr);
797109e88d11fceef4483f7803414b939e4173fe7f54sewardj         assign( EA, ea_rAor0_idxd(rA_addr, rB_addr) );
79721f5fe1fc3a37ca729925e8eec25aa1025b4a6cdbcarll         store( mkexpr(EA),
79731f5fe1fc3a37ca729925e8eec25aa1025b4a6cdbcarll                unop(Iop_64to32, unop(Iop_ReinterpF64asI64, mkexpr(frS))) );
797409e88d11fceef4483f7803414b939e4173fe7f54sewardj         break;
7975e14bb9f862843c6b804097c124961b5567ded4f1sewardj
7976d953ebb9b04cbad6891676df597bf0c542b1ec89cerion      default:
79775b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion         vex_printf("dis_fp_store(ppc)(opc2)\n");
7978d953ebb9b04cbad6891676df597bf0c542b1ec89cerion         return False;
7979e14bb9f862843c6b804097c124961b5567ded4f1sewardj      }
7980e14bb9f862843c6b804097c124961b5567ded4f1sewardj      break;
7981a982c0503d8c0c6069ae453bfe70657bd2c134aecerion
7982a982c0503d8c0c6069ae453bfe70657bd2c134aecerion   default:
79835b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion      vex_printf("dis_fp_store(ppc)(opc1)\n");
7984a982c0503d8c0c6069ae453bfe70657bd2c134aecerion      return False;
7985a982c0503d8c0c6069ae453bfe70657bd2c134aecerion   }
7986a982c0503d8c0c6069ae453bfe70657bd2c134aecerion   return True;
7987a982c0503d8c0c6069ae453bfe70657bd2c134aecerion}
7988a982c0503d8c0c6069ae453bfe70657bd2c134aecerion
7989a982c0503d8c0c6069ae453bfe70657bd2c134aecerion
7990b51f0f4f33256638ed953156a2635aa739b232f1sewardj
7991a982c0503d8c0c6069ae453bfe70657bd2c134aecerion/*
7992b51f0f4f33256638ed953156a2635aa739b232f1sewardj  Floating Point Arith Instructions
7993a982c0503d8c0c6069ae453bfe70657bd2c134aecerion*/
7994b51f0f4f33256638ed953156a2635aa739b232f1sewardjstatic Bool dis_fp_arith ( UInt theInstr )
7995a982c0503d8c0c6069ae453bfe70657bd2c134aecerion{
7996b51f0f4f33256638ed953156a2635aa739b232f1sewardj   /* A-Form */
799776de5cf615380b23b4b5bcced6541233cd4a93a0cerion   UChar opc1     = ifieldOPC(theInstr);
799876de5cf615380b23b4b5bcced6541233cd4a93a0cerion   UChar frD_addr = ifieldRegDS(theInstr);
799976de5cf615380b23b4b5bcced6541233cd4a93a0cerion   UChar frA_addr = ifieldRegA(theInstr);
800076de5cf615380b23b4b5bcced6541233cd4a93a0cerion   UChar frB_addr = ifieldRegB(theInstr);
800176de5cf615380b23b4b5bcced6541233cd4a93a0cerion   UChar frC_addr = ifieldRegC(theInstr);
800276de5cf615380b23b4b5bcced6541233cd4a93a0cerion   UChar opc2     = ifieldOPClo5(theInstr);
800376de5cf615380b23b4b5bcced6541233cd4a93a0cerion   UChar flag_rC  = ifieldBIT0(theInstr);
8004a982c0503d8c0c6069ae453bfe70657bd2c134aecerion
8005b183b8571b4ec98866ce2b3653a9d066cf5f16f4sewardj   IRTemp  frD = newTemp(Ity_F64);
8006b183b8571b4ec98866ce2b3653a9d066cf5f16f4sewardj   IRTemp  frA = newTemp(Ity_F64);
8007b183b8571b4ec98866ce2b3653a9d066cf5f16f4sewardj   IRTemp  frB = newTemp(Ity_F64);
8008b183b8571b4ec98866ce2b3653a9d066cf5f16f4sewardj   IRTemp  frC = newTemp(Ity_F64);
8009b183b8571b4ec98866ce2b3653a9d066cf5f16f4sewardj   IRExpr* rm  = get_IR_roundingmode();
8010b183b8571b4ec98866ce2b3653a9d066cf5f16f4sewardj
8011b183b8571b4ec98866ce2b3653a9d066cf5f16f4sewardj   /* By default, we will examine the results of the operation and set
8012b183b8571b4ec98866ce2b3653a9d066cf5f16f4sewardj      fpscr[FPRF] accordingly. */
8013b183b8571b4ec98866ce2b3653a9d066cf5f16f4sewardj   Bool set_FPRF = True;
8014b183b8571b4ec98866ce2b3653a9d066cf5f16f4sewardj
8015b183b8571b4ec98866ce2b3653a9d066cf5f16f4sewardj   /* By default, if flag_RC is set, we will clear cr1 after the
8016b183b8571b4ec98866ce2b3653a9d066cf5f16f4sewardj      operation.  In reality we should set cr1 to indicate the
8017b183b8571b4ec98866ce2b3653a9d066cf5f16f4sewardj      exception status of the operation, but since we're not
8018b183b8571b4ec98866ce2b3653a9d066cf5f16f4sewardj      simulating exceptions, the exception status will appear to be
8019b183b8571b4ec98866ce2b3653a9d066cf5f16f4sewardj      zero.  Hence cr1 should be cleared if this is a . form insn. */
8020b183b8571b4ec98866ce2b3653a9d066cf5f16f4sewardj   Bool clear_CR1 = True;
8021a982c0503d8c0c6069ae453bfe70657bd2c134aecerion
8022b51f0f4f33256638ed953156a2635aa739b232f1sewardj   assign( frA, getFReg(frA_addr));
8023b51f0f4f33256638ed953156a2635aa739b232f1sewardj   assign( frB, getFReg(frB_addr));
8024b51f0f4f33256638ed953156a2635aa739b232f1sewardj   assign( frC, getFReg(frC_addr));
8025a982c0503d8c0c6069ae453bfe70657bd2c134aecerion
8026b51f0f4f33256638ed953156a2635aa739b232f1sewardj   switch (opc1) {
8027e14bb9f862843c6b804097c124961b5567ded4f1sewardj   case 0x3B:
8028e14bb9f862843c6b804097c124961b5567ded4f1sewardj      switch (opc2) {
8029e14bb9f862843c6b804097c124961b5567ded4f1sewardj      case 0x12: // fdivs (Floating Divide Single, PPC32 p407)
8030b183b8571b4ec98866ce2b3653a9d066cf5f16f4sewardj         if (frC_addr != 0)
8031e14bb9f862843c6b804097c124961b5567ded4f1sewardj            return False;
80325b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion         DIP("fdivs%s fr%u,fr%u,fr%u\n", flag_rC ? ".":"",
8033e14bb9f862843c6b804097c124961b5567ded4f1sewardj             frD_addr, frA_addr, frB_addr);
8034b183b8571b4ec98866ce2b3653a9d066cf5f16f4sewardj         assign( frD, triop( Iop_DivF64r32,
8035b183b8571b4ec98866ce2b3653a9d066cf5f16f4sewardj                             rm, mkexpr(frA), mkexpr(frB) ));
8036e14bb9f862843c6b804097c124961b5567ded4f1sewardj         break;
8037e14bb9f862843c6b804097c124961b5567ded4f1sewardj
8038e14bb9f862843c6b804097c124961b5567ded4f1sewardj      case 0x14: // fsubs (Floating Subtract Single, PPC32 p430)
8039b183b8571b4ec98866ce2b3653a9d066cf5f16f4sewardj         if (frC_addr != 0)
8040e14bb9f862843c6b804097c124961b5567ded4f1sewardj            return False;
80415b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion         DIP("fsubs%s fr%u,fr%u,fr%u\n", flag_rC ? ".":"",
8042e14bb9f862843c6b804097c124961b5567ded4f1sewardj             frD_addr, frA_addr, frB_addr);
8043b183b8571b4ec98866ce2b3653a9d066cf5f16f4sewardj         assign( frD, triop( Iop_SubF64r32,
8044b183b8571b4ec98866ce2b3653a9d066cf5f16f4sewardj                             rm, mkexpr(frA), mkexpr(frB) ));
8045e14bb9f862843c6b804097c124961b5567ded4f1sewardj         break;
8046e14bb9f862843c6b804097c124961b5567ded4f1sewardj
8047e14bb9f862843c6b804097c124961b5567ded4f1sewardj      case 0x15: // fadds (Floating Add Single, PPC32 p401)
8048b183b8571b4ec98866ce2b3653a9d066cf5f16f4sewardj         if (frC_addr != 0)
8049e14bb9f862843c6b804097c124961b5567ded4f1sewardj            return False;
80505b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion         DIP("fadds%s fr%u,fr%u,fr%u\n", flag_rC ? ".":"",
8051e14bb9f862843c6b804097c124961b5567ded4f1sewardj             frD_addr, frA_addr, frB_addr);
8052b183b8571b4ec98866ce2b3653a9d066cf5f16f4sewardj         assign( frD, triop( Iop_AddF64r32,
8053b183b8571b4ec98866ce2b3653a9d066cf5f16f4sewardj                             rm, mkexpr(frA), mkexpr(frB) ));
8054e14bb9f862843c6b804097c124961b5567ded4f1sewardj         break;
8055e14bb9f862843c6b804097c124961b5567ded4f1sewardj
8056870c84bfeeda8ee31755e04ba548136d36dd3941sewardj      case 0x16: // fsqrts (Floating SqRt (Single-Precision), PPC32 p428)
80575117ce116f47141cb23d1b49cc826e19323add97sewardj         // NOTE: POWERPC OPTIONAL, "General-Purpose Group" (PPC32_FX)
8058b183b8571b4ec98866ce2b3653a9d066cf5f16f4sewardj         if (frA_addr != 0 || frC_addr != 0)
8059870c84bfeeda8ee31755e04ba548136d36dd3941sewardj            return False;
8060870c84bfeeda8ee31755e04ba548136d36dd3941sewardj         DIP("fsqrts%s fr%u,fr%u\n", flag_rC ? ".":"",
8061870c84bfeeda8ee31755e04ba548136d36dd3941sewardj             frD_addr, frB_addr);
806279fd33f4e243276b8109fe56c3eb1d4c9ccea7ccsewardj         // however illogically, on ppc970 this insn behaves identically
8063b183b8571b4ec98866ce2b3653a9d066cf5f16f4sewardj         // to fsqrt (double-precision).  So use SqrtF64, not SqrtF64r32.
8064b183b8571b4ec98866ce2b3653a9d066cf5f16f4sewardj         assign( frD, binop( Iop_SqrtF64, rm, mkexpr(frB) ));
8065870c84bfeeda8ee31755e04ba548136d36dd3941sewardj         break;
8066e14bb9f862843c6b804097c124961b5567ded4f1sewardj
8067baf971ad7f6e005109f3301ec9d19c98066b3840sewardj      case 0x18: // fres (Floating Reciprocal Estimate Single, PPC32 p421)
80685117ce116f47141cb23d1b49cc826e19323add97sewardj         // NOTE: POWERPC OPTIONAL, "Graphics Group" (PPC32_GX)
8069b183b8571b4ec98866ce2b3653a9d066cf5f16f4sewardj         if (frA_addr != 0 || frC_addr != 0)
8070baf971ad7f6e005109f3301ec9d19c98066b3840sewardj            return False;
8071baf971ad7f6e005109f3301ec9d19c98066b3840sewardj         DIP("fres%s fr%u,fr%u\n", flag_rC ? ".":"",
8072baf971ad7f6e005109f3301ec9d19c98066b3840sewardj             frD_addr, frB_addr);
8073157b19b5ad19287b29939250c00765a426070174sewardj         { IRExpr* ieee_one
8074157b19b5ad19287b29939250c00765a426070174sewardj              = IRExpr_Const(IRConst_F64i(0x3ff0000000000000ULL));
8075b183b8571b4ec98866ce2b3653a9d066cf5f16f4sewardj           assign( frD, triop( Iop_DivF64r32,
8076b183b8571b4ec98866ce2b3653a9d066cf5f16f4sewardj                               rm,
8077b183b8571b4ec98866ce2b3653a9d066cf5f16f4sewardj                               ieee_one, mkexpr(frB) ));
8078157b19b5ad19287b29939250c00765a426070174sewardj         }
8079baf971ad7f6e005109f3301ec9d19c98066b3840sewardj         break;
8080e14bb9f862843c6b804097c124961b5567ded4f1sewardj
8081e14bb9f862843c6b804097c124961b5567ded4f1sewardj      case 0x19: // fmuls (Floating Multiply Single, PPC32 p414)
8082b183b8571b4ec98866ce2b3653a9d066cf5f16f4sewardj         if (frB_addr != 0)
8083e14bb9f862843c6b804097c124961b5567ded4f1sewardj            return False;
80845b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion         DIP("fmuls%s fr%u,fr%u,fr%u\n", flag_rC ? ".":"",
8085e14bb9f862843c6b804097c124961b5567ded4f1sewardj             frD_addr, frA_addr, frC_addr);
8086b183b8571b4ec98866ce2b3653a9d066cf5f16f4sewardj         assign( frD, triop( Iop_MulF64r32,
8087b183b8571b4ec98866ce2b3653a9d066cf5f16f4sewardj                             rm, mkexpr(frA), mkexpr(frC) ));
8088e14bb9f862843c6b804097c124961b5567ded4f1sewardj         break;
8089e14bb9f862843c6b804097c124961b5567ded4f1sewardj
809079fd33f4e243276b8109fe56c3eb1d4c9ccea7ccsewardj      case 0x1A: // frsqrtes (Floating Recip SqRt Est Single)
809179fd33f4e243276b8109fe56c3eb1d4c9ccea7ccsewardj         // NOTE: POWERPC OPTIONAL, "Graphics Group" (PPC32_GX)
809279fd33f4e243276b8109fe56c3eb1d4c9ccea7ccsewardj         // Undocumented instruction?
8093b183b8571b4ec98866ce2b3653a9d066cf5f16f4sewardj         if (frA_addr != 0 || frC_addr != 0)
809479fd33f4e243276b8109fe56c3eb1d4c9ccea7ccsewardj            return False;
809579fd33f4e243276b8109fe56c3eb1d4c9ccea7ccsewardj         DIP("frsqrtes%s fr%u,fr%u\n", flag_rC ? ".":"",
809679fd33f4e243276b8109fe56c3eb1d4c9ccea7ccsewardj             frD_addr, frB_addr);
80971ddee21008ffdb2ac7f8e6a73445f150f753606fsewardj         assign( frD, unop(Iop_RSqrtEst5GoodF64, mkexpr(frB)) );
809879fd33f4e243276b8109fe56c3eb1d4c9ccea7ccsewardj         break;
809979fd33f4e243276b8109fe56c3eb1d4c9ccea7ccsewardj
8100e14bb9f862843c6b804097c124961b5567ded4f1sewardj      default:
81015b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion         vex_printf("dis_fp_arith(ppc)(3B: opc2)\n");
8102e14bb9f862843c6b804097c124961b5567ded4f1sewardj         return False;
8103e14bb9f862843c6b804097c124961b5567ded4f1sewardj      }
8104e14bb9f862843c6b804097c124961b5567ded4f1sewardj      break;
8105a982c0503d8c0c6069ae453bfe70657bd2c134aecerion
8106b51f0f4f33256638ed953156a2635aa739b232f1sewardj   case 0x3F:
8107b51f0f4f33256638ed953156a2635aa739b232f1sewardj      switch (opc2) {
81085b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion      case 0x12: // fdiv (Floating Div (Double-Precision), PPC32 p406)
8109b183b8571b4ec98866ce2b3653a9d066cf5f16f4sewardj         if (frC_addr != 0)
8110e14bb9f862843c6b804097c124961b5567ded4f1sewardj            return False;
81115b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion         DIP("fdiv%s fr%u,fr%u,fr%u\n", flag_rC ? ".":"",
8112e14bb9f862843c6b804097c124961b5567ded4f1sewardj             frD_addr, frA_addr, frB_addr);
8113b183b8571b4ec98866ce2b3653a9d066cf5f16f4sewardj         assign( frD, triop(Iop_DivF64, rm, mkexpr(frA), mkexpr(frB)) );
8114e14bb9f862843c6b804097c124961b5567ded4f1sewardj         break;
8115e14bb9f862843c6b804097c124961b5567ded4f1sewardj
81165b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion      case 0x14: // fsub (Floating Sub (Double-Precision), PPC32 p429)
8117b183b8571b4ec98866ce2b3653a9d066cf5f16f4sewardj         if (frC_addr != 0)
8118e14bb9f862843c6b804097c124961b5567ded4f1sewardj            return False;
81195b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion         DIP("fsub%s fr%u,fr%u,fr%u\n", flag_rC ? ".":"",
8120e14bb9f862843c6b804097c124961b5567ded4f1sewardj             frD_addr, frA_addr, frB_addr);
8121b183b8571b4ec98866ce2b3653a9d066cf5f16f4sewardj         assign( frD, triop(Iop_SubF64, rm, mkexpr(frA), mkexpr(frB)) );
8122e14bb9f862843c6b804097c124961b5567ded4f1sewardj         break;
8123a982c0503d8c0c6069ae453bfe70657bd2c134aecerion
8124b51f0f4f33256638ed953156a2635aa739b232f1sewardj      case 0x15: // fadd (Floating Add (Double-Precision), PPC32 p400)
8125b183b8571b4ec98866ce2b3653a9d066cf5f16f4sewardj         if (frC_addr != 0)
8126b51f0f4f33256638ed953156a2635aa739b232f1sewardj            return False;
81275b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion         DIP("fadd%s fr%u,fr%u,fr%u\n", flag_rC ? ".":"",
8128b51f0f4f33256638ed953156a2635aa739b232f1sewardj             frD_addr, frA_addr, frB_addr);
8129b183b8571b4ec98866ce2b3653a9d066cf5f16f4sewardj         assign( frD, triop(Iop_AddF64, rm, mkexpr(frA), mkexpr(frB)) );
8130b51f0f4f33256638ed953156a2635aa739b232f1sewardj         break;
8131a982c0503d8c0c6069ae453bfe70657bd2c134aecerion
8132876ef41aec4bba650f92c4601c26d8f76738e26acerion      case 0x16: // fsqrt (Floating SqRt (Double-Precision), PPC32 p427)
81335117ce116f47141cb23d1b49cc826e19323add97sewardj         // NOTE: POWERPC OPTIONAL, "General-Purpose Group" (PPC32_FX)
8134b183b8571b4ec98866ce2b3653a9d066cf5f16f4sewardj         if (frA_addr != 0 || frC_addr != 0)
8135876ef41aec4bba650f92c4601c26d8f76738e26acerion            return False;
81365b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion         DIP("fsqrt%s fr%u,fr%u\n", flag_rC ? ".":"",
8137876ef41aec4bba650f92c4601c26d8f76738e26acerion             frD_addr, frB_addr);
8138b183b8571b4ec98866ce2b3653a9d066cf5f16f4sewardj         assign( frD, binop(Iop_SqrtF64, rm, mkexpr(frB)) );
8139876ef41aec4bba650f92c4601c26d8f76738e26acerion         break;
8140e14bb9f862843c6b804097c124961b5567ded4f1sewardj
8141e14bb9f862843c6b804097c124961b5567ded4f1sewardj      case 0x17: { // fsel (Floating Select, PPC32 p426)
81425117ce116f47141cb23d1b49cc826e19323add97sewardj         // NOTE: POWERPC OPTIONAL, "Graphics Group" (PPC32_GX)
8143e14bb9f862843c6b804097c124961b5567ded4f1sewardj         IRTemp cc    = newTemp(Ity_I32);
8144e14bb9f862843c6b804097c124961b5567ded4f1sewardj         IRTemp cc_b0 = newTemp(Ity_I32);
8145e14bb9f862843c6b804097c124961b5567ded4f1sewardj
81465b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion         DIP("fsel%s fr%u,fr%u,fr%u,fr%u\n", flag_rC ? ".":"",
8147e14bb9f862843c6b804097c124961b5567ded4f1sewardj             frD_addr, frA_addr, frC_addr, frB_addr);
8148e14bb9f862843c6b804097c124961b5567ded4f1sewardj
8149e14bb9f862843c6b804097c124961b5567ded4f1sewardj         // cc: UN == 0x41, LT == 0x01, GT == 0x00, EQ == 0x40
8150e14bb9f862843c6b804097c124961b5567ded4f1sewardj         // => GT|EQ == (cc & 0x1 == 0)
81515b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion         assign( cc, binop(Iop_CmpF64, mkexpr(frA),
81525b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion                                       IRExpr_Const(IRConst_F64(0))) );
8153e14bb9f862843c6b804097c124961b5567ded4f1sewardj         assign( cc_b0, binop(Iop_And32, mkexpr(cc), mkU32(1)) );
8154e14bb9f862843c6b804097c124961b5567ded4f1sewardj
8155e14bb9f862843c6b804097c124961b5567ded4f1sewardj         // frD = (frA >= 0.0) ? frC : frB
8156e14bb9f862843c6b804097c124961b5567ded4f1sewardj         //     = (cc_b0 == 0) ? frC : frB
8157e14bb9f862843c6b804097c124961b5567ded4f1sewardj         assign( frD,
815899dd03e04a6914d90d5fee727d61d76905334becflorian                 IRExpr_ITE(
8159009230b9758291b594e60d7c0243a73d53e81854sewardj                    binop(Iop_CmpEQ32, mkexpr(cc_b0), mkU32(0)),
816099dd03e04a6914d90d5fee727d61d76905334becflorian                    mkexpr(frC),
816199dd03e04a6914d90d5fee727d61d76905334becflorian                    mkexpr(frB) ));
8162b183b8571b4ec98866ce2b3653a9d066cf5f16f4sewardj
8163b183b8571b4ec98866ce2b3653a9d066cf5f16f4sewardj         /* One of the rare ones which don't mess with FPRF */
8164b183b8571b4ec98866ce2b3653a9d066cf5f16f4sewardj         set_FPRF = False;
8165e14bb9f862843c6b804097c124961b5567ded4f1sewardj         break;
8166e14bb9f862843c6b804097c124961b5567ded4f1sewardj      }
8167e14bb9f862843c6b804097c124961b5567ded4f1sewardj
816879fd33f4e243276b8109fe56c3eb1d4c9ccea7ccsewardj      case 0x18: // fre (Floating Reciprocal Estimate)
816979fd33f4e243276b8109fe56c3eb1d4c9ccea7ccsewardj         // NOTE: POWERPC OPTIONAL, "Graphics Group" (PPC32_GX)
817079fd33f4e243276b8109fe56c3eb1d4c9ccea7ccsewardj         // Note: unclear whether this insn really exists or not
817179fd33f4e243276b8109fe56c3eb1d4c9ccea7ccsewardj         // ppc970 doesn't have it, but POWER5 does
8172b183b8571b4ec98866ce2b3653a9d066cf5f16f4sewardj         if (frA_addr != 0 || frC_addr != 0)
817379fd33f4e243276b8109fe56c3eb1d4c9ccea7ccsewardj            return False;
817479fd33f4e243276b8109fe56c3eb1d4c9ccea7ccsewardj         DIP("fre%s fr%u,fr%u\n", flag_rC ? ".":"",
817579fd33f4e243276b8109fe56c3eb1d4c9ccea7ccsewardj             frD_addr, frB_addr);
8176157b19b5ad19287b29939250c00765a426070174sewardj         { IRExpr* ieee_one
8177157b19b5ad19287b29939250c00765a426070174sewardj              = IRExpr_Const(IRConst_F64i(0x3ff0000000000000ULL));
8178b183b8571b4ec98866ce2b3653a9d066cf5f16f4sewardj           assign( frD, triop( Iop_DivF64,
817956de421a90e9b68ad96894e731932d10aaf0636dsewardj                               rm,
8180b183b8571b4ec98866ce2b3653a9d066cf5f16f4sewardj                               ieee_one, mkexpr(frB) ));
8181157b19b5ad19287b29939250c00765a426070174sewardj         }
818279fd33f4e243276b8109fe56c3eb1d4c9ccea7ccsewardj         break;
818379fd33f4e243276b8109fe56c3eb1d4c9ccea7ccsewardj
81845b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion      case 0x19: // fmul (Floating Mult (Double Precision), PPC32 p413)
8185b183b8571b4ec98866ce2b3653a9d066cf5f16f4sewardj         if (frB_addr != 0)
81865b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion            vex_printf("dis_fp_arith(ppc)(instr,fmul)\n");
81875b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion         DIP("fmul%s fr%u,fr%u,fr%u\n", flag_rC ? ".":"",
8188e14bb9f862843c6b804097c124961b5567ded4f1sewardj             frD_addr, frA_addr, frC_addr);
8189b183b8571b4ec98866ce2b3653a9d066cf5f16f4sewardj         assign( frD, triop(Iop_MulF64, rm, mkexpr(frA), mkexpr(frC)) );
8190e14bb9f862843c6b804097c124961b5567ded4f1sewardj         break;
8191e14bb9f862843c6b804097c124961b5567ded4f1sewardj
8192baf971ad7f6e005109f3301ec9d19c98066b3840sewardj      case 0x1A: // frsqrte (Floating Recip SqRt Est., PPC32 p424)
81935117ce116f47141cb23d1b49cc826e19323add97sewardj         // NOTE: POWERPC OPTIONAL, "Graphics Group" (PPC32_GX)
8194b183b8571b4ec98866ce2b3653a9d066cf5f16f4sewardj         if (frA_addr != 0 || frC_addr != 0)
8195baf971ad7f6e005109f3301ec9d19c98066b3840sewardj            return False;
8196baf971ad7f6e005109f3301ec9d19c98066b3840sewardj         DIP("frsqrte%s fr%u,fr%u\n", flag_rC ? ".":"",
8197baf971ad7f6e005109f3301ec9d19c98066b3840sewardj             frD_addr, frB_addr);
81981ddee21008ffdb2ac7f8e6a73445f150f753606fsewardj         assign( frD, unop(Iop_RSqrtEst5GoodF64, mkexpr(frB)) );
8199baf971ad7f6e005109f3301ec9d19c98066b3840sewardj         break;
8200a982c0503d8c0c6069ae453bfe70657bd2c134aecerion
8201b51f0f4f33256638ed953156a2635aa739b232f1sewardj      default:
82025b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion         vex_printf("dis_fp_arith(ppc)(3F: opc2)\n");
8203b51f0f4f33256638ed953156a2635aa739b232f1sewardj         return False;
8204b51f0f4f33256638ed953156a2635aa739b232f1sewardj      }
8205b51f0f4f33256638ed953156a2635aa739b232f1sewardj      break;
8206a982c0503d8c0c6069ae453bfe70657bd2c134aecerion
8207a982c0503d8c0c6069ae453bfe70657bd2c134aecerion   default:
82085b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion      vex_printf("dis_fp_arith(ppc)(opc1)\n");
8209a982c0503d8c0c6069ae453bfe70657bd2c134aecerion      return False;
8210a982c0503d8c0c6069ae453bfe70657bd2c134aecerion   }
8211a982c0503d8c0c6069ae453bfe70657bd2c134aecerion
8212b51f0f4f33256638ed953156a2635aa739b232f1sewardj   putFReg( frD_addr, mkexpr(frD) );
8213b183b8571b4ec98866ce2b3653a9d066cf5f16f4sewardj
8214b183b8571b4ec98866ce2b3653a9d066cf5f16f4sewardj   if (set_FPRF) {
8215b183b8571b4ec98866ce2b3653a9d066cf5f16f4sewardj      // XXX XXX XXX FIXME
8216b183b8571b4ec98866ce2b3653a9d066cf5f16f4sewardj      // set FPRF from frD
8217b183b8571b4ec98866ce2b3653a9d066cf5f16f4sewardj   }
8218b183b8571b4ec98866ce2b3653a9d066cf5f16f4sewardj
8219b183b8571b4ec98866ce2b3653a9d066cf5f16f4sewardj   if (flag_rC && clear_CR1) {
8220b183b8571b4ec98866ce2b3653a9d066cf5f16f4sewardj      putCR321( 1, mkU8(0) );
8221b183b8571b4ec98866ce2b3653a9d066cf5f16f4sewardj      putCR0( 1, mkU8(0) );
8222b183b8571b4ec98866ce2b3653a9d066cf5f16f4sewardj   }
8223b183b8571b4ec98866ce2b3653a9d066cf5f16f4sewardj
8224b51f0f4f33256638ed953156a2635aa739b232f1sewardj   return True;
8225b51f0f4f33256638ed953156a2635aa739b232f1sewardj}
8226a982c0503d8c0c6069ae453bfe70657bd2c134aecerion
8227a982c0503d8c0c6069ae453bfe70657bd2c134aecerion
8228a982c0503d8c0c6069ae453bfe70657bd2c134aecerion
8229e14bb9f862843c6b804097c124961b5567ded4f1sewardj/*
8230e14bb9f862843c6b804097c124961b5567ded4f1sewardj  Floating Point Mult-Add Instructions
8231e14bb9f862843c6b804097c124961b5567ded4f1sewardj*/
8232e14bb9f862843c6b804097c124961b5567ded4f1sewardjstatic Bool dis_fp_multadd ( UInt theInstr )
8233e14bb9f862843c6b804097c124961b5567ded4f1sewardj{
8234e14bb9f862843c6b804097c124961b5567ded4f1sewardj   /* A-Form */
823576de5cf615380b23b4b5bcced6541233cd4a93a0cerion   UChar opc1     = ifieldOPC(theInstr);
823676de5cf615380b23b4b5bcced6541233cd4a93a0cerion   UChar frD_addr = ifieldRegDS(theInstr);
823776de5cf615380b23b4b5bcced6541233cd4a93a0cerion   UChar frA_addr = ifieldRegA(theInstr);
823876de5cf615380b23b4b5bcced6541233cd4a93a0cerion   UChar frB_addr = ifieldRegB(theInstr);
823976de5cf615380b23b4b5bcced6541233cd4a93a0cerion   UChar frC_addr = ifieldRegC(theInstr);
824076de5cf615380b23b4b5bcced6541233cd4a93a0cerion   UChar opc2     = ifieldOPClo5(theInstr);
824176de5cf615380b23b4b5bcced6541233cd4a93a0cerion   UChar flag_rC  = ifieldBIT0(theInstr);
8242e14bb9f862843c6b804097c124961b5567ded4f1sewardj
8243b183b8571b4ec98866ce2b3653a9d066cf5f16f4sewardj   IRTemp  frD = newTemp(Ity_F64);
8244b183b8571b4ec98866ce2b3653a9d066cf5f16f4sewardj   IRTemp  frA = newTemp(Ity_F64);
8245b183b8571b4ec98866ce2b3653a9d066cf5f16f4sewardj   IRTemp  frB = newTemp(Ity_F64);
8246b183b8571b4ec98866ce2b3653a9d066cf5f16f4sewardj   IRTemp  frC = newTemp(Ity_F64);
8247b183b8571b4ec98866ce2b3653a9d066cf5f16f4sewardj   IRTemp  rmt = newTemp(Ity_I32);
82482bcdd653612c726da0b7203b579b8f6114703be4sewardj   IRTemp  tmp = newTemp(Ity_F64);
82492bcdd653612c726da0b7203b579b8f6114703be4sewardj   IRTemp  sign_tmp = newTemp(Ity_I64);
82502bcdd653612c726da0b7203b579b8f6114703be4sewardj   IRTemp  nan_mask = newTemp(Ity_I32);
8251b183b8571b4ec98866ce2b3653a9d066cf5f16f4sewardj   IRExpr* rm;
8252b183b8571b4ec98866ce2b3653a9d066cf5f16f4sewardj
8253b183b8571b4ec98866ce2b3653a9d066cf5f16f4sewardj   /* By default, we will examine the results of the operation and set
8254b183b8571b4ec98866ce2b3653a9d066cf5f16f4sewardj      fpscr[FPRF] accordingly. */
8255b183b8571b4ec98866ce2b3653a9d066cf5f16f4sewardj   Bool set_FPRF = True;
8256b183b8571b4ec98866ce2b3653a9d066cf5f16f4sewardj
8257b183b8571b4ec98866ce2b3653a9d066cf5f16f4sewardj   /* By default, if flag_RC is set, we will clear cr1 after the
8258b183b8571b4ec98866ce2b3653a9d066cf5f16f4sewardj      operation.  In reality we should set cr1 to indicate the
8259b183b8571b4ec98866ce2b3653a9d066cf5f16f4sewardj      exception status of the operation, but since we're not
8260b183b8571b4ec98866ce2b3653a9d066cf5f16f4sewardj      simulating exceptions, the exception status will appear to be
8261b183b8571b4ec98866ce2b3653a9d066cf5f16f4sewardj      zero.  Hence cr1 should be cleared if this is a . form insn. */
8262b183b8571b4ec98866ce2b3653a9d066cf5f16f4sewardj   Bool clear_CR1 = True;
8263b183b8571b4ec98866ce2b3653a9d066cf5f16f4sewardj
8264b183b8571b4ec98866ce2b3653a9d066cf5f16f4sewardj   /* Bind the rounding mode expression to a temp; there's no
8265b183b8571b4ec98866ce2b3653a9d066cf5f16f4sewardj      point in creating gratuitous CSEs, as we know we'll need
8266b183b8571b4ec98866ce2b3653a9d066cf5f16f4sewardj      to use it twice. */
8267b183b8571b4ec98866ce2b3653a9d066cf5f16f4sewardj   assign( rmt, get_IR_roundingmode() );
8268b183b8571b4ec98866ce2b3653a9d066cf5f16f4sewardj   rm = mkexpr(rmt);
8269e14bb9f862843c6b804097c124961b5567ded4f1sewardj
8270e14bb9f862843c6b804097c124961b5567ded4f1sewardj   assign( frA, getFReg(frA_addr));
8271e14bb9f862843c6b804097c124961b5567ded4f1sewardj   assign( frB, getFReg(frB_addr));
8272e14bb9f862843c6b804097c124961b5567ded4f1sewardj   assign( frC, getFReg(frC_addr));
8273e14bb9f862843c6b804097c124961b5567ded4f1sewardj
8274b183b8571b4ec98866ce2b3653a9d066cf5f16f4sewardj   /* The rounding in this is all a bit dodgy.  The idea is to only do
8275b183b8571b4ec98866ce2b3653a9d066cf5f16f4sewardj      one rounding.  That clearly isn't achieveable without dedicated
8276b183b8571b4ec98866ce2b3653a9d066cf5f16f4sewardj      four-input IR primops, although in the single precision case we
8277b183b8571b4ec98866ce2b3653a9d066cf5f16f4sewardj      can sort-of simulate it by doing the inner multiply in double
8278b183b8571b4ec98866ce2b3653a9d066cf5f16f4sewardj      precision.
8279b183b8571b4ec98866ce2b3653a9d066cf5f16f4sewardj
8280b183b8571b4ec98866ce2b3653a9d066cf5f16f4sewardj      In the negated cases, the negation happens after rounding. */
8281b183b8571b4ec98866ce2b3653a9d066cf5f16f4sewardj
8282e14bb9f862843c6b804097c124961b5567ded4f1sewardj   switch (opc1) {
8283e14bb9f862843c6b804097c124961b5567ded4f1sewardj   case 0x3B:
8284e14bb9f862843c6b804097c124961b5567ded4f1sewardj      switch (opc2) {
8285e14bb9f862843c6b804097c124961b5567ded4f1sewardj      case 0x1C: // fmsubs (Floating Mult-Subtr Single, PPC32 p412)
82865b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion         DIP("fmsubs%s fr%u,fr%u,fr%u,fr%u\n", flag_rC ? ".":"",
8287e14bb9f862843c6b804097c124961b5567ded4f1sewardj             frD_addr, frA_addr, frC_addr, frB_addr);
828840c802659108a96bb87cbc1a30b7b77e2abd0829sewardj         assign( frD, qop( Iop_MSubF64r32, rm,
828940c802659108a96bb87cbc1a30b7b77e2abd0829sewardj                           mkexpr(frA), mkexpr(frC), mkexpr(frB) ));
8290b183b8571b4ec98866ce2b3653a9d066cf5f16f4sewardj         break;
8291e14bb9f862843c6b804097c124961b5567ded4f1sewardj
8292e14bb9f862843c6b804097c124961b5567ded4f1sewardj      case 0x1D: // fmadds (Floating Mult-Add Single, PPC32 p409)
82935b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion         DIP("fmadds%s fr%u,fr%u,fr%u,fr%u\n", flag_rC ? ".":"",
8294e14bb9f862843c6b804097c124961b5567ded4f1sewardj             frD_addr, frA_addr, frC_addr, frB_addr);
829540c802659108a96bb87cbc1a30b7b77e2abd0829sewardj         assign( frD, qop( Iop_MAddF64r32, rm,
829640c802659108a96bb87cbc1a30b7b77e2abd0829sewardj                           mkexpr(frA), mkexpr(frC), mkexpr(frB) ));
8297e14bb9f862843c6b804097c124961b5567ded4f1sewardj         break;
8298e14bb9f862843c6b804097c124961b5567ded4f1sewardj
8299e14bb9f862843c6b804097c124961b5567ded4f1sewardj      case 0x1E: // fnmsubs (Float Neg Mult-Subtr Single, PPC32 p420)
8300e14bb9f862843c6b804097c124961b5567ded4f1sewardj      case 0x1F: // fnmadds (Floating Negative Multiply-Add Single, PPC32 p418)
83012bcdd653612c726da0b7203b579b8f6114703be4sewardj
83022bcdd653612c726da0b7203b579b8f6114703be4sewardj         if (opc2 == 0x1E) {
83032bcdd653612c726da0b7203b579b8f6114703be4sewardj            DIP("fnmsubs%s fr%u,fr%u,fr%u,fr%u\n", flag_rC ? ".":"",
83042bcdd653612c726da0b7203b579b8f6114703be4sewardj                     frD_addr, frA_addr, frC_addr, frB_addr);
83052bcdd653612c726da0b7203b579b8f6114703be4sewardj            assign( tmp, qop( Iop_MSubF64r32, rm,
83062bcdd653612c726da0b7203b579b8f6114703be4sewardj                              mkexpr(frA), mkexpr(frC), mkexpr(frB) ) );
83072bcdd653612c726da0b7203b579b8f6114703be4sewardj         } else {
83082bcdd653612c726da0b7203b579b8f6114703be4sewardj            DIP("fnmadds%s fr%u,fr%u,fr%u,fr%u\n", flag_rC ? ".":"",
83092bcdd653612c726da0b7203b579b8f6114703be4sewardj                     frD_addr, frA_addr, frC_addr, frB_addr);
83102bcdd653612c726da0b7203b579b8f6114703be4sewardj            assign( tmp, qop( Iop_MAddF64r32, rm,
83112bcdd653612c726da0b7203b579b8f6114703be4sewardj                              mkexpr(frA), mkexpr(frC), mkexpr(frB) ) );
83122bcdd653612c726da0b7203b579b8f6114703be4sewardj         }
83132bcdd653612c726da0b7203b579b8f6114703be4sewardj
83142bcdd653612c726da0b7203b579b8f6114703be4sewardj         assign( nan_mask, Check_NaN( mkexpr( tmp ),
83152bcdd653612c726da0b7203b579b8f6114703be4sewardj                                      mkU32( NANmaskSingle ) ) );
83162bcdd653612c726da0b7203b579b8f6114703be4sewardj         assign( sign_tmp, Complement_non_NaN( mkexpr( tmp ),
83172bcdd653612c726da0b7203b579b8f6114703be4sewardj                                               mkexpr( nan_mask ) ) );
83182bcdd653612c726da0b7203b579b8f6114703be4sewardj         assign( frD, unop( Iop_ReinterpI64asF64, mkexpr( sign_tmp ) ) );
8319e14bb9f862843c6b804097c124961b5567ded4f1sewardj         break;
8320e14bb9f862843c6b804097c124961b5567ded4f1sewardj
8321e14bb9f862843c6b804097c124961b5567ded4f1sewardj      default:
83225b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion         vex_printf("dis_fp_multadd(ppc)(3B: opc2)\n");
8323e14bb9f862843c6b804097c124961b5567ded4f1sewardj         return False;
8324e14bb9f862843c6b804097c124961b5567ded4f1sewardj      }
8325e14bb9f862843c6b804097c124961b5567ded4f1sewardj      break;
8326e14bb9f862843c6b804097c124961b5567ded4f1sewardj
8327e14bb9f862843c6b804097c124961b5567ded4f1sewardj   case 0x3F:
8328e14bb9f862843c6b804097c124961b5567ded4f1sewardj      switch (opc2) {
83295b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion      case 0x1C: // fmsub (Float Mult-Sub (Dbl Precision), PPC32 p411)
83305b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion         DIP("fmsub%s fr%u,fr%u,fr%u,fr%u\n", flag_rC ? ".":"",
8331e14bb9f862843c6b804097c124961b5567ded4f1sewardj             frD_addr, frA_addr, frC_addr, frB_addr);
833240c802659108a96bb87cbc1a30b7b77e2abd0829sewardj         assign( frD, qop( Iop_MSubF64, rm,
833340c802659108a96bb87cbc1a30b7b77e2abd0829sewardj                           mkexpr(frA), mkexpr(frC), mkexpr(frB) ));
8334e14bb9f862843c6b804097c124961b5567ded4f1sewardj         break;
8335e14bb9f862843c6b804097c124961b5567ded4f1sewardj
83365b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion      case 0x1D: // fmadd (Float Mult-Add (Dbl Precision), PPC32 p408)
83375b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion         DIP("fmadd%s fr%u,fr%u,fr%u,fr%u\n", flag_rC ? ".":"",
8338e14bb9f862843c6b804097c124961b5567ded4f1sewardj             frD_addr, frA_addr, frC_addr, frB_addr);
833940c802659108a96bb87cbc1a30b7b77e2abd0829sewardj         assign( frD, qop( Iop_MAddF64, rm,
834040c802659108a96bb87cbc1a30b7b77e2abd0829sewardj                           mkexpr(frA), mkexpr(frC), mkexpr(frB) ));
8341e14bb9f862843c6b804097c124961b5567ded4f1sewardj         break;
8342e14bb9f862843c6b804097c124961b5567ded4f1sewardj
83435b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion      case 0x1E: // fnmsub (Float Neg Mult-Subtr (Dbl Precision), PPC32 p419)
83445b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion      case 0x1F: // fnmadd (Float Neg Mult-Add (Dbl Precision), PPC32 p417)
83452bcdd653612c726da0b7203b579b8f6114703be4sewardj
83462bcdd653612c726da0b7203b579b8f6114703be4sewardj         if (opc2 == 0x1E) {
83472bcdd653612c726da0b7203b579b8f6114703be4sewardj            DIP("fnmsub%s fr%u,fr%u,fr%u,fr%u\n", flag_rC ? ".":"",
83482bcdd653612c726da0b7203b579b8f6114703be4sewardj                     frD_addr, frA_addr, frC_addr, frB_addr);
83492bcdd653612c726da0b7203b579b8f6114703be4sewardj            assign( tmp, qop( Iop_MSubF64, rm,
83502bcdd653612c726da0b7203b579b8f6114703be4sewardj                              mkexpr(frA), mkexpr(frC), mkexpr(frB) ) );
83512bcdd653612c726da0b7203b579b8f6114703be4sewardj         } else {
83522bcdd653612c726da0b7203b579b8f6114703be4sewardj            DIP("fnmadd%s fr%u,fr%u,fr%u,fr%u\n", flag_rC ? ".":"",
83532bcdd653612c726da0b7203b579b8f6114703be4sewardj                     frD_addr, frA_addr, frC_addr, frB_addr);
83542bcdd653612c726da0b7203b579b8f6114703be4sewardj            assign( tmp, qop( Iop_MAddF64, rm,
83552bcdd653612c726da0b7203b579b8f6114703be4sewardj                              mkexpr(frA), mkexpr(frC), mkexpr(frB) ));
83562bcdd653612c726da0b7203b579b8f6114703be4sewardj         }
83572bcdd653612c726da0b7203b579b8f6114703be4sewardj
83582bcdd653612c726da0b7203b579b8f6114703be4sewardj         assign( nan_mask, Check_NaN( mkexpr( tmp ),
83592bcdd653612c726da0b7203b579b8f6114703be4sewardj                                      mkU32( NANmaskDouble ) ) );
83602bcdd653612c726da0b7203b579b8f6114703be4sewardj         assign( sign_tmp, Complement_non_NaN( mkexpr( tmp ),
83612bcdd653612c726da0b7203b579b8f6114703be4sewardj                                               mkexpr( nan_mask ) ) );
83622bcdd653612c726da0b7203b579b8f6114703be4sewardj         assign( frD, unop( Iop_ReinterpI64asF64, mkexpr( sign_tmp ) ) );
83630e2cc67b30d1bb4d0515a1e09d944143becb3881sewardj         break;
8364e14bb9f862843c6b804097c124961b5567ded4f1sewardj
8365e14bb9f862843c6b804097c124961b5567ded4f1sewardj      default:
83665b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion         vex_printf("dis_fp_multadd(ppc)(3F: opc2)\n");
8367e14bb9f862843c6b804097c124961b5567ded4f1sewardj         return False;
8368e14bb9f862843c6b804097c124961b5567ded4f1sewardj      }
8369e14bb9f862843c6b804097c124961b5567ded4f1sewardj      break;
8370e14bb9f862843c6b804097c124961b5567ded4f1sewardj
8371e14bb9f862843c6b804097c124961b5567ded4f1sewardj   default:
83725b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion      vex_printf("dis_fp_multadd(ppc)(opc1)\n");
8373e14bb9f862843c6b804097c124961b5567ded4f1sewardj      return False;
8374e14bb9f862843c6b804097c124961b5567ded4f1sewardj   }
8375e14bb9f862843c6b804097c124961b5567ded4f1sewardj
8376e14bb9f862843c6b804097c124961b5567ded4f1sewardj   putFReg( frD_addr, mkexpr(frD) );
8377b183b8571b4ec98866ce2b3653a9d066cf5f16f4sewardj
8378b183b8571b4ec98866ce2b3653a9d066cf5f16f4sewardj   if (set_FPRF) {
8379b183b8571b4ec98866ce2b3653a9d066cf5f16f4sewardj      // XXX XXX XXX FIXME
8380b183b8571b4ec98866ce2b3653a9d066cf5f16f4sewardj      // set FPRF from frD
8381b183b8571b4ec98866ce2b3653a9d066cf5f16f4sewardj   }
8382b183b8571b4ec98866ce2b3653a9d066cf5f16f4sewardj
8383b183b8571b4ec98866ce2b3653a9d066cf5f16f4sewardj   if (flag_rC && clear_CR1) {
8384b183b8571b4ec98866ce2b3653a9d066cf5f16f4sewardj      putCR321( 1, mkU8(0) );
8385b183b8571b4ec98866ce2b3653a9d066cf5f16f4sewardj      putCR0( 1, mkU8(0) );
8386b183b8571b4ec98866ce2b3653a9d066cf5f16f4sewardj   }
8387b183b8571b4ec98866ce2b3653a9d066cf5f16f4sewardj
8388e14bb9f862843c6b804097c124961b5567ded4f1sewardj   return True;
8389e14bb9f862843c6b804097c124961b5567ded4f1sewardj}
8390e14bb9f862843c6b804097c124961b5567ded4f1sewardj
839166d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj/*
839266d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj * fe_flag is set to 1 if any of the following conditions occurs:
8393e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj *  - The floating-point operand in register FRB is a Zero, a
8394e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj *    NaN, an Infinity, or a negative value.
8395e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj *  - e_b is less than or equal to: -970 for double precision; -103 for single precision
8396e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj *  Otherwise fe_flag is set to 0.
8397e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj *
8398e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj * fg_flag is set to 1 if either of the following conditions occurs.
8399e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj *   - The floating-point operand in register FRB is a Zero, an
8400e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj *     Infinity, or a denormalized value.
8401e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj *  Otherwise fg_flag is set to 0.
8402e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj *
8403e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj */
8404e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardjstatic void do_fp_tsqrt(IRTemp frB_Int, Bool sp, IRTemp * fe_flag_tmp, IRTemp * fg_flag_tmp)
8405e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj{
8406e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj   // The following temps are for holding intermediate results
8407e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj   IRTemp e_b = newTemp(Ity_I32);
8408e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj   IRExpr * fe_flag,  * fg_flag;
8409e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj   IRTemp frB_exp_shR = newTemp(Ity_I32);
8410e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj   UInt bias = sp? 127 : 1023;
8411e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj   IRExpr * frbNaN, * frbDenorm, * frBNeg;
8412e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj   IRExpr * eb_LTE;
8413e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj   IRTemp  frbZero_tmp = newTemp(Ity_I1);
8414e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj   IRTemp  frbInf_tmp = newTemp(Ity_I1);
8415e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj   *fe_flag_tmp = newTemp(Ity_I32);
8416e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj   *fg_flag_tmp = newTemp(Ity_I32);
8417e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj   assign( frB_exp_shR, fp_exp_part( frB_Int, sp ) );
8418e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj   assign(e_b, binop( Iop_Sub32, mkexpr(frB_exp_shR), mkU32( bias ) ));
8419e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj
8420e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj   //////////////////  fe_flag tests BEGIN //////////////////////
8421e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj   /* We first do all tests that may result in setting fe_flag to '1'.
8422e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj    * (NOTE: These tests are similar to those used for ftdiv.  See do_fp_tdiv()
8423e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj    * for details.)
8424e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj    */
8425e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj   frbNaN = sp ? is_NaN_32(frB_Int) : is_NaN(frB_Int);
8426e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj   assign( frbInf_tmp, is_Inf(frB_Int, sp) );
8427e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj   assign( frbZero_tmp, is_Zero(frB_Int, sp ) );
8428e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj   {
8429e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj      // Test_value = -970 for double precision
8430e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj      UInt test_value = sp ? 0xffffff99 : 0xfffffc36;
8431e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj      eb_LTE = binop( Iop_CmpLE32S, mkexpr( e_b ), mkU32( test_value ) );
8432e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj   }
8433e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj   frBNeg = binop( Iop_CmpEQ32,
8434e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj                   binop( Iop_Shr32,
8435e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj                          sp ? mkexpr( frB_Int ) : unop( Iop_64HIto32, mkexpr( frB_Int ) ),
8436e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj                          mkU8( 31 ) ),
8437e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj                   mkU32( 1 ) );
8438e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj   //////////////////  fe_flag tests END //////////////////////
8439e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj
8440e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj   //////////////////  fg_flag tests BEGIN //////////////////////
8441e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj   /*
8442e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj    * The following tests were already performed above in the fe_flag
8443e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj    * tests.  So these conditions will result in both fe_ and fg_ flags
8444e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj    * being set.
8445e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj    *   - Test if FRB is Zero
8446e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj    *   - Test if FRB is an Infinity
8447e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj    */
8448e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj
8449e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj   /*
8450e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj    * Test if FRB holds a denormalized value.  A denormalized value is one where
8451e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj    * the exp is 0 and the fraction is non-zero.
8452e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj    */
8453e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj   if (sp) {
8454e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj      IRTemp frac_part = newTemp(Ity_I32);
8455e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj      assign( frac_part, binop( Iop_And32, mkexpr(frB_Int), mkU32(0x007fffff)) );
8456e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj      frbDenorm
8457e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj               = mkAND1( binop( Iop_CmpEQ32, mkexpr( frB_exp_shR ), mkU32( 0 ) ),
8458e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj                         binop( Iop_CmpNE32, mkexpr( frac_part ), mkU32( 0 ) ) );
8459e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj   } else {
8460e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj      IRExpr * hi32, * low32, * fraction_is_nonzero;
8461e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj      IRTemp frac_part = newTemp(Ity_I64);
8462e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj
8463e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj      assign( frac_part, FP_FRAC_PART(frB_Int) );
8464e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj      hi32 = unop( Iop_64HIto32, mkexpr( frac_part ) );
8465e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj      low32 = unop( Iop_64to32, mkexpr( frac_part ) );
8466e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj      fraction_is_nonzero = binop( Iop_CmpNE32, binop( Iop_Or32, low32, hi32 ),
8467e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj                                                mkU32( 0 ) );
8468e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj      frbDenorm
8469e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj               = mkAND1( binop( Iop_CmpEQ32, mkexpr( frB_exp_shR ), mkU32( 0 ) ),
8470e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj                         fraction_is_nonzero );
8471e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj   }
8472e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj   //////////////////  fg_flag tests END //////////////////////
8473e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj
8474e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj   /////////////////////////
8475e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj   fe_flag = mkOR1( mkexpr( frbZero_tmp ),
8476e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj                    mkOR1( frbNaN,
8477e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj                           mkOR1( mkexpr( frbInf_tmp ),
8478e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj                                  mkOR1( frBNeg, eb_LTE ) ) ) );
8479e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj
8480e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj   fe_flag = unop(Iop_1Uto32, fe_flag);
8481e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj
8482e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj   fg_flag = mkOR1( mkexpr( frbZero_tmp ),
8483e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj                    mkOR1( mkexpr( frbInf_tmp ), frbDenorm ) );
8484e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj   fg_flag = unop(Iop_1Uto32, fg_flag);
8485e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj   assign (*fg_flag_tmp, fg_flag);
8486e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj   assign (*fe_flag_tmp, fe_flag);
8487e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj}
8488e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj/*
8489e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj * fe_flag is set to 1 if any of the following conditions occurs:
849066d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj *  - The double-precision floating-point operand in register FRA is a NaN or an
849166d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj *    Infinity.
849266d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj *  - The double-precision floating-point operand in register FRB is a Zero, a
849366d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj *    NaN, or an Infinity.
849466d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj *  - e_b is less than or equal to -1022.
849566d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj *  - e_b is greater than or equal to 1021.
849666d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj *  - The double-precision floating-point operand in register FRA is not a zero
849766d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj *    and the difference, e_a - e_b, is greater than or equal to 1023.
849866d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj *  - The double-precision floating-point operand in register FRA is not a zero
849966d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj *    and the difference, e_a - e_b, is less than or equal to -1021.
850066d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj *  - The double-precision floating-point operand in register FRA is not a zero
850166d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj *    and e_a is less than or equal to -970
850266d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj *  Otherwise fe_flag is set to 0.
850366d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj *
850466d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj * fg_flag is set to 1 if either of the following conditions occurs.
850566d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj *   - The double-precision floating-point operand in register FRA is an Infinity.
850666d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj *   - The double-precision floating-point operand in register FRB is a Zero, an
850766d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj *     Infinity, or a denormalized value.
850866d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj *  Otherwise fg_flag is set to 0.
850966d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj *
851066d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj */
8511e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardjstatic void _do_fp_tdiv(IRTemp frA_int, IRTemp frB_int, Bool sp, IRTemp * fe_flag_tmp, IRTemp * fg_flag_tmp)
851266d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj{
851366d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj   // The following temps are for holding intermediate results
851466d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj   IRTemp e_a = newTemp(Ity_I32);
851566d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj   IRTemp e_b = newTemp(Ity_I32);
851666d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj   IRTemp frA_exp_shR = newTemp(Ity_I32);
851766d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj   IRTemp frB_exp_shR = newTemp(Ity_I32);
851866d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj
8519e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj   UInt bias = sp? 127 : 1023;
8520e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj   *fe_flag_tmp = newTemp(Ity_I32);
8521e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj   *fg_flag_tmp = newTemp(Ity_I32);
852266d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj
852366d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj   /* The following variables hold boolean results from tests
852466d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj    * that are OR'ed together for setting the fe_ and fg_ flags.
852566d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj    * For some cases, the booleans are used more than once, so
852666d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj    * I make those IRTemp's instead of IRExpr's.
852766d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj    */
852866d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj   IRExpr * fraNaN, * frbNaN, * frbDenorm;
852966d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj   IRExpr * eb_LTE, * eb_GTE, * ea_eb_GTE, * ea_eb_LTE, * ea_LTE;
853066d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj   IRTemp  fraInf_tmp = newTemp(Ity_I1);
853166d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj   IRTemp  frbZero_tmp = newTemp(Ity_I1);
853266d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj   IRTemp  frbInf_tmp = newTemp(Ity_I1);
853366d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj   IRTemp  fraNotZero_tmp = newTemp(Ity_I1);
853466d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj
853566d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj/* The following are the flags that are set by OR'ing the results of
85364aa412af1d8166cc11f39a6e721df49431d23618sewardj * all the tests done for tdiv.  These flags are the input to the specified CR.
853766d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj */
8538e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj   IRExpr * fe_flag, * fg_flag;
853966d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj
854066d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj   // Create temps that will be used throughout the following tests.
8541e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj   assign( frA_exp_shR, fp_exp_part( frA_int, sp ) );
8542e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj   assign( frB_exp_shR, fp_exp_part( frB_int, sp ) );
854366d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj   /* Let e_[a|b] be the unbiased exponent: i.e. exp - 1023. */
854466d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj   assign(e_a, binop( Iop_Sub32, mkexpr(frA_exp_shR), mkU32( bias ) ));
854566d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj   assign(e_b, binop( Iop_Sub32, mkexpr(frB_exp_shR), mkU32( bias ) ));
854666d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj
854766d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj
854866d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj   //////////////////  fe_flag tests BEGIN //////////////////////
854966d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj   /* We first do all tests that may result in setting fe_flag to '1'. */
855066d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj
855166d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj   /*
855266d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj    * Test if the double-precision floating-point operand in register FRA is
855366d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj    * a NaN:
855466d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj    */
8555e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj   fraNaN = sp ? is_NaN_32(frA_int) : is_NaN(frA_int);
855666d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj   /*
855766d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj    * Test if the double-precision floating-point operand in register FRA is
855866d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj    * an Infinity.
855966d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj    */
8560e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj   assign(fraInf_tmp, is_Inf(frA_int, sp));
856166d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj
856266d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj   /*
856366d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj    * Test if the double-precision floating-point operand in register FRB is
856466d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj    * a NaN:
856566d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj    */
8566e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj   frbNaN = sp ? is_NaN_32(frB_int) : is_NaN(frB_int);
856766d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj   /*
856866d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj    * Test if the double-precision floating-point operand in register FRB is
856966d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj    * an Infinity.
857066d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj    */
8571e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj   assign( frbInf_tmp, is_Inf(frB_int, sp) );
857266d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj   /*
857366d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj    * Test if the double-precision floating-point operand in register FRB is
857466d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj    * a Zero.
857566d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj    */
8576e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj   assign( frbZero_tmp, is_Zero(frB_int, sp) );
857766d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj
857866d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj   /*
8579e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj    * Test if e_b <= -1022 for double precision;
8580e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj    * or e_b <= -126 for single precision
858166d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj    */
858266d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj   {
8583e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj      UInt test_value = sp ? 0xffffff82 : 0xfffffc02;
858466d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj      eb_LTE = binop(Iop_CmpLE32S, mkexpr(e_b), mkU32(test_value));
858566d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj   }
858666d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj
858766d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj   /*
8588e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj    * Test if e_b >= 1021 (i.e., 1021 < e_b) for double precision;
8589e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj    * or e_b >= -125 (125 < e_b) for single precision
859066d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj    */
859166d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj   {
8592e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj      Int test_value = sp ? 125 : 1021;
859366d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj      eb_GTE = binop(Iop_CmpLT32S, mkU32(test_value), mkexpr(e_b));
859466d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj   }
8595e14bb9f862843c6b804097c124961b5567ded4f1sewardj
859666d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj   /*
8597e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj    * Test if FRA != Zero and (e_a - e_b) >= bias
859866d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj    */
8599e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj   assign( fraNotZero_tmp, unop( Iop_Not1, is_Zero( frA_int, sp ) ) );
860066d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj   ea_eb_GTE = mkAND1( mkexpr( fraNotZero_tmp ),
860166d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj                       binop( Iop_CmpLT32S, mkU32( bias ),
860266d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj                              binop( Iop_Sub32, mkexpr( e_a ),
860366d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj                                     mkexpr( e_b ) ) ) );
860466d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj
860566d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj   /*
8606e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj    * Test if FRA != Zero and (e_a - e_b) <= [-1021 (double precision) or -125 (single precision)]
860766d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj    */
860866d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj   {
8609e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj      UInt test_value = sp ? 0xffffff83 : 0xfffffc03;
861066d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj
861166d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj      ea_eb_LTE = mkAND1( mkexpr( fraNotZero_tmp ),
861266d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj                          binop( Iop_CmpLE32S,
861366d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj                                 binop( Iop_Sub32,
861466d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj                                        mkexpr( e_a ),
861566d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj                                        mkexpr( e_b ) ),
861666d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj                                        mkU32( test_value ) ) );
861766d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj   }
861866d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj
861966d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj   /*
8620e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj    * Test if FRA != Zero and e_a <= [-970 (double precision) or -103 (single precision)]
862166d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj    */
862266d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj   {
862366d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj      UInt test_value = 0xfffffc36;  //Int test_value = -970;
862466d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj
862566d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj      ea_LTE = mkAND1( mkexpr( fraNotZero_tmp ), binop( Iop_CmpLE32S,
862666d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj                                                        mkexpr( e_a ),
862766d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj                                                        mkU32( test_value ) ) );
862866d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj   }
862966d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj   //////////////////  fe_flag tests END //////////////////////
863066d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj
863166d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj   //////////////////  fg_flag tests BEGIN //////////////////////
863266d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj   /*
863366d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj    * The following tests were already performed above in the fe_flag
863466d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj    * tests.  So these conditions will result in both fe_ and fg_ flags
863566d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj    * being set.
863666d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj    *   - Test if FRA is an Infinity
863766d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj    *   - Test if FRB ix Zero
863866d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj    *   - Test if FRB is an Infinity
863966d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj    */
864066d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj
864166d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj   /*
864266d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj    * Test if FRB holds a denormalized value.  A denormalized value is one where
864366d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj    * the exp is 0 and the fraction is non-zero.
864466d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj    */
864566d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj   {
8646e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj      IRExpr * fraction_is_nonzero;
864766d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj
8648e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj      if (sp) {
8649e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj         fraction_is_nonzero = binop( Iop_CmpNE32, FP_FRAC_PART32(frB_int),
8650e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj                                      mkU32( 0 ) );
8651e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj      } else {
8652e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj         IRExpr * hi32, * low32;
8653e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj         IRTemp frac_part = newTemp(Ity_I64);
8654e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj         assign( frac_part, FP_FRAC_PART(frB_int) );
8655e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj
8656e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj         hi32 = unop( Iop_64HIto32, mkexpr( frac_part ) );
8657e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj         low32 = unop( Iop_64to32, mkexpr( frac_part ) );
8658e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj         fraction_is_nonzero = binop( Iop_CmpNE32, binop( Iop_Or32, low32, hi32 ),
8659e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj                                      mkU32( 0 ) );
8660e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj      }
866166d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj      frbDenorm = mkAND1( binop( Iop_CmpEQ32, mkexpr( frB_exp_shR ),
8662e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj                                 mkU32( 0x0 ) ), fraction_is_nonzero );
866366d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj
866466d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj   }
866566d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj   //////////////////  fg_flag tests END //////////////////////
866666d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj
866766d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj   fe_flag
866866d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj   = mkOR1(
866966d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj            fraNaN,
867066d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj            mkOR1(
867166d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj                   mkexpr( fraInf_tmp ),
867266d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj                   mkOR1(
867366d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj                          mkexpr( frbZero_tmp ),
867466d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj                          mkOR1(
867566d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj                                 frbNaN,
867666d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj                                 mkOR1(
867766d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj                                        mkexpr( frbInf_tmp ),
867866d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj                                        mkOR1( eb_LTE,
867966d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj                                               mkOR1( eb_GTE,
868066d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj                                                      mkOR1( ea_eb_GTE,
868166d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj                                                             mkOR1( ea_eb_LTE,
868266d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj                                                                    ea_LTE ) ) ) ) ) ) ) ) );
868366d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj
868466d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj   fe_flag = unop(Iop_1Uto32, fe_flag);
868566d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj
868666d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj   fg_flag = mkOR1( mkexpr( fraInf_tmp ), mkOR1( mkexpr( frbZero_tmp ),
868766d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj                                                 mkOR1( mkexpr( frbInf_tmp ),
868866d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj                                                        frbDenorm ) ) );
868966d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj   fg_flag = unop(Iop_1Uto32, fg_flag);
8690e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj   assign(*fe_flag_tmp, fe_flag);
8691e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj   assign(*fg_flag_tmp, fg_flag);
8692e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj}
869366d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj
8694e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj/* See description for _do_fp_tdiv() above. */
8695e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardjstatic IRExpr * do_fp_tdiv(IRTemp frA_int, IRTemp frB_int)
8696e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj{
8697e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj   IRTemp  fe_flag, fg_flag;
8698e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj   /////////////////////////
8699e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj   /* The CR field consists of fl_flag || fg_flag || fe_flag || 0b0
8700e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj    * where fl_flag == 1 on ppc64.
8701e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj    */
8702e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj   IRExpr * fl_flag = unop(Iop_Not32, mkU32(0xFFFFFE));
8703e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj   fe_flag = fg_flag = IRTemp_INVALID;
8704e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj   _do_fp_tdiv(frA_int, frB_int, False/*not single precision*/, &fe_flag, &fg_flag);
87054aa412af1d8166cc11f39a6e721df49431d23618sewardj   return binop( Iop_Or32,
87064aa412af1d8166cc11f39a6e721df49431d23618sewardj                 binop( Iop_Or32,
87074aa412af1d8166cc11f39a6e721df49431d23618sewardj                        binop( Iop_Shl32, fl_flag, mkU8( 3 ) ),
8708e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj                        binop( Iop_Shl32, mkexpr(fg_flag), mkU8( 2 ) ) ),
8709e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj                 binop( Iop_Shl32, mkexpr(fe_flag), mkU8( 1 ) ) );
87104aa412af1d8166cc11f39a6e721df49431d23618sewardj}
87114aa412af1d8166cc11f39a6e721df49431d23618sewardj
8712e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardjstatic Bool dis_fp_tests ( UInt theInstr )
87134aa412af1d8166cc11f39a6e721df49431d23618sewardj{
87144aa412af1d8166cc11f39a6e721df49431d23618sewardj   UChar opc1     = ifieldOPC(theInstr);
87154aa412af1d8166cc11f39a6e721df49431d23618sewardj   UChar crfD     = toUChar( IFIELD( theInstr, 23, 3 ) );
87164aa412af1d8166cc11f39a6e721df49431d23618sewardj   UChar frB_addr = ifieldRegB(theInstr);
87174aa412af1d8166cc11f39a6e721df49431d23618sewardj   UChar b0       = ifieldBIT0(theInstr);
8718e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj   UInt  opc2     = ifieldOPClo10(theInstr);
87194aa412af1d8166cc11f39a6e721df49431d23618sewardj   IRTemp frB_I64     = newTemp(Ity_I64);
87204aa412af1d8166cc11f39a6e721df49431d23618sewardj
8721e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj   if (opc1 != 0x3F || b0 != 0 ){
8722e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj      vex_printf("dis_fp_tests(ppc)(ftdiv)\n");
87234aa412af1d8166cc11f39a6e721df49431d23618sewardj      return False;
87244aa412af1d8166cc11f39a6e721df49431d23618sewardj   }
87254aa412af1d8166cc11f39a6e721df49431d23618sewardj   assign( frB_I64, unop( Iop_ReinterpF64asI64, getFReg( frB_addr ) ) );
87264aa412af1d8166cc11f39a6e721df49431d23618sewardj
8727e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj   switch (opc2) {
8728e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj      case 0x080: // ftdiv
8729e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj      {
8730e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj         UChar frA_addr = ifieldRegA(theInstr);
8731e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj         IRTemp frA_I64     = newTemp(Ity_I64);
8732e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj         UChar b21to22  = toUChar( IFIELD( theInstr, 21, 2 ) );
8733e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj         if (b21to22 != 0 ) {
8734e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj            vex_printf("dis_fp_tests(ppc)(ftdiv)\n");
8735e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj            return False;
8736e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj         }
8737e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj
8738e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj         assign( frA_I64, unop( Iop_ReinterpF64asI64, getFReg( frA_addr ) ) );
8739e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj         putGST_field( PPC_GST_CR, do_fp_tdiv(frA_I64, frB_I64), crfD );
874066d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj
8741e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj         DIP("ftdiv crf%d,fr%u,fr%u\n", crfD, frA_addr, frB_addr);
8742e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj         break;
8743e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj      }
8744e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj      case 0x0A0: // ftsqrt
8745e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj      {
8746e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj         IRTemp flags = newTemp(Ity_I32);
8747e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj         IRTemp  fe_flag, fg_flag;
8748e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj         fe_flag = fg_flag = IRTemp_INVALID;
8749e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj         UChar b18to22  = toUChar( IFIELD( theInstr, 18, 5 ) );
8750e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj         if ( b18to22 != 0) {
8751e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj            vex_printf("dis_fp_tests(ppc)(ftsqrt)\n");
8752e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj            return False;
8753e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj         }
8754e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj         DIP("ftsqrt crf%d,fr%u\n", crfD, frB_addr);
8755e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj         do_fp_tsqrt(frB_I64, False /* not single precision*/, &fe_flag, &fg_flag);
8756e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj         /* The CR field consists of fl_flag || fg_flag || fe_flag || 0b0
8757e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj          * where fl_flag == 1 on ppc64.
8758e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj          */
8759e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj         assign( flags,
8760e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj                 binop( Iop_Or32,
8761e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj                        binop( Iop_Or32, mkU32( 8 ), // fl_flag
8762e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj                               binop( Iop_Shl32, mkexpr(fg_flag), mkU8( 2 ) ) ),
8763e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj                        binop( Iop_Shl32, mkexpr(fe_flag), mkU8( 1 ) ) ) );
8764e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj         putGST_field( PPC_GST_CR, mkexpr(flags), crfD );
8765e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj         break;
8766e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj      }
8767e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj
8768e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj      default:
8769e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj         vex_printf("dis_fp_tests(ppc)(opc2)\n");
8770e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj         return False;
8771e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj
8772e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj   }
877366d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj   return True;
877466d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj}
8775e14bb9f862843c6b804097c124961b5567ded4f1sewardj
8776e14bb9f862843c6b804097c124961b5567ded4f1sewardj/*
8777e14bb9f862843c6b804097c124961b5567ded4f1sewardj  Floating Point Compare Instructions
8778e14bb9f862843c6b804097c124961b5567ded4f1sewardj*/
8779e14bb9f862843c6b804097c124961b5567ded4f1sewardjstatic Bool dis_fp_cmp ( UInt theInstr )
8780e14bb9f862843c6b804097c124961b5567ded4f1sewardj{
8781e14bb9f862843c6b804097c124961b5567ded4f1sewardj   /* X-Form */
878276de5cf615380b23b4b5bcced6541233cd4a93a0cerion   UChar opc1     = ifieldOPC(theInstr);
878376de5cf615380b23b4b5bcced6541233cd4a93a0cerion   UChar crfD     = toUChar( IFIELD( theInstr, 23, 3 ) );
878476de5cf615380b23b4b5bcced6541233cd4a93a0cerion   UChar b21to22  = toUChar( IFIELD( theInstr, 21, 2 ) );
878576de5cf615380b23b4b5bcced6541233cd4a93a0cerion   UChar frA_addr = ifieldRegA(theInstr);
878676de5cf615380b23b4b5bcced6541233cd4a93a0cerion   UChar frB_addr = ifieldRegB(theInstr);
878776de5cf615380b23b4b5bcced6541233cd4a93a0cerion   UInt  opc2     = ifieldOPClo10(theInstr);
878876de5cf615380b23b4b5bcced6541233cd4a93a0cerion   UChar b0       = ifieldBIT0(theInstr);
8789e14bb9f862843c6b804097c124961b5567ded4f1sewardj
8790e14bb9f862843c6b804097c124961b5567ded4f1sewardj   IRTemp ccIR    = newTemp(Ity_I32);
8791e14bb9f862843c6b804097c124961b5567ded4f1sewardj   IRTemp ccPPC32 = newTemp(Ity_I32);
8792e14bb9f862843c6b804097c124961b5567ded4f1sewardj
8793e14bb9f862843c6b804097c124961b5567ded4f1sewardj   IRTemp frA     = newTemp(Ity_F64);
8794e14bb9f862843c6b804097c124961b5567ded4f1sewardj   IRTemp frB     = newTemp(Ity_F64);
8795e14bb9f862843c6b804097c124961b5567ded4f1sewardj
8796e14bb9f862843c6b804097c124961b5567ded4f1sewardj   if (opc1 != 0x3F || b21to22 != 0 || b0 != 0) {
87975b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion      vex_printf("dis_fp_cmp(ppc)(instr)\n");
8798e14bb9f862843c6b804097c124961b5567ded4f1sewardj      return False;
8799e14bb9f862843c6b804097c124961b5567ded4f1sewardj   }
8800e14bb9f862843c6b804097c124961b5567ded4f1sewardj
8801e14bb9f862843c6b804097c124961b5567ded4f1sewardj   assign( frA, getFReg(frA_addr));
8802e14bb9f862843c6b804097c124961b5567ded4f1sewardj   assign( frB, getFReg(frB_addr));
8803e14bb9f862843c6b804097c124961b5567ded4f1sewardj
8804e14bb9f862843c6b804097c124961b5567ded4f1sewardj   assign( ccIR, binop(Iop_CmpF64, mkexpr(frA), mkexpr(frB)) );
8805e14bb9f862843c6b804097c124961b5567ded4f1sewardj
8806e14bb9f862843c6b804097c124961b5567ded4f1sewardj   /* Map compare result from IR to PPC32 */
8807e14bb9f862843c6b804097c124961b5567ded4f1sewardj   /*
8808e14bb9f862843c6b804097c124961b5567ded4f1sewardj     FP cmp result | PPC | IR
8809e14bb9f862843c6b804097c124961b5567ded4f1sewardj     --------------------------
8810e14bb9f862843c6b804097c124961b5567ded4f1sewardj     UN            | 0x1 | 0x45
8811e14bb9f862843c6b804097c124961b5567ded4f1sewardj     EQ            | 0x2 | 0x40
8812e14bb9f862843c6b804097c124961b5567ded4f1sewardj     GT            | 0x4 | 0x00
8813e14bb9f862843c6b804097c124961b5567ded4f1sewardj     LT            | 0x8 | 0x01
8814e14bb9f862843c6b804097c124961b5567ded4f1sewardj   */
8815e14bb9f862843c6b804097c124961b5567ded4f1sewardj
8816b183b8571b4ec98866ce2b3653a9d066cf5f16f4sewardj   // ccPPC32 = Shl(1, (~(ccIR>>5) & 2)
8817b183b8571b4ec98866ce2b3653a9d066cf5f16f4sewardj   //                    | ((ccIR ^ (ccIR>>6)) & 1)
8818e14bb9f862843c6b804097c124961b5567ded4f1sewardj   assign(
8819e14bb9f862843c6b804097c124961b5567ded4f1sewardj      ccPPC32,
8820b183b8571b4ec98866ce2b3653a9d066cf5f16f4sewardj      binop(
8821b183b8571b4ec98866ce2b3653a9d066cf5f16f4sewardj         Iop_Shl32,
8822b183b8571b4ec98866ce2b3653a9d066cf5f16f4sewardj         mkU32(1),
8823b183b8571b4ec98866ce2b3653a9d066cf5f16f4sewardj         unop(
8824b183b8571b4ec98866ce2b3653a9d066cf5f16f4sewardj            Iop_32to8,
8825b183b8571b4ec98866ce2b3653a9d066cf5f16f4sewardj            binop(
8826b183b8571b4ec98866ce2b3653a9d066cf5f16f4sewardj               Iop_Or32,
8827b183b8571b4ec98866ce2b3653a9d066cf5f16f4sewardj               binop(
8828b183b8571b4ec98866ce2b3653a9d066cf5f16f4sewardj                  Iop_And32,
8829b183b8571b4ec98866ce2b3653a9d066cf5f16f4sewardj                  unop(
8830b183b8571b4ec98866ce2b3653a9d066cf5f16f4sewardj                     Iop_Not32,
8831b183b8571b4ec98866ce2b3653a9d066cf5f16f4sewardj                     binop(Iop_Shr32, mkexpr(ccIR), mkU8(5))
8832b183b8571b4ec98866ce2b3653a9d066cf5f16f4sewardj                  ),
8833b183b8571b4ec98866ce2b3653a9d066cf5f16f4sewardj                  mkU32(2)
8834b183b8571b4ec98866ce2b3653a9d066cf5f16f4sewardj               ),
8835b183b8571b4ec98866ce2b3653a9d066cf5f16f4sewardj               binop(
8836b183b8571b4ec98866ce2b3653a9d066cf5f16f4sewardj                  Iop_And32,
8837b183b8571b4ec98866ce2b3653a9d066cf5f16f4sewardj                  binop(
8838b183b8571b4ec98866ce2b3653a9d066cf5f16f4sewardj                     Iop_Xor32,
8839b183b8571b4ec98866ce2b3653a9d066cf5f16f4sewardj                     mkexpr(ccIR),
8840b183b8571b4ec98866ce2b3653a9d066cf5f16f4sewardj                     binop(Iop_Shr32, mkexpr(ccIR), mkU8(6))
8841b183b8571b4ec98866ce2b3653a9d066cf5f16f4sewardj                  ),
8842b183b8571b4ec98866ce2b3653a9d066cf5f16f4sewardj                  mkU32(1)
8843b183b8571b4ec98866ce2b3653a9d066cf5f16f4sewardj               )
8844b183b8571b4ec98866ce2b3653a9d066cf5f16f4sewardj            )
8845b183b8571b4ec98866ce2b3653a9d066cf5f16f4sewardj         )
8846b183b8571b4ec98866ce2b3653a9d066cf5f16f4sewardj      )
8847e14bb9f862843c6b804097c124961b5567ded4f1sewardj   );
8848e14bb9f862843c6b804097c124961b5567ded4f1sewardj
8849d953ebb9b04cbad6891676df597bf0c542b1ec89cerion   putGST_field( PPC_GST_CR, mkexpr(ccPPC32), crfD );
8850e14bb9f862843c6b804097c124961b5567ded4f1sewardj
8851edf7fc572e2decb93e9143961e8739c8fe18899dcerion   /* CAB: TODO?: Support writing cc to FPSCR->FPCC ?
8852d953ebb9b04cbad6891676df597bf0c542b1ec89cerion      putGST_field( PPC_GST_FPSCR, mkexpr(ccPPC32), 4 );
8853edf7fc572e2decb93e9143961e8739c8fe18899dcerion   */
8854b183b8571b4ec98866ce2b3653a9d066cf5f16f4sewardj   // XXX XXX XXX FIXME
8855b183b8571b4ec98866ce2b3653a9d066cf5f16f4sewardj   // Also write the result into FPRF (it's not entirely clear how)
8856e14bb9f862843c6b804097c124961b5567ded4f1sewardj
8857edf7fc572e2decb93e9143961e8739c8fe18899dcerion   /* Note: Differences between fcmpu and fcmpo are only in exception
8858edf7fc572e2decb93e9143961e8739c8fe18899dcerion      flag settings, which aren't supported anyway. */
8859e14bb9f862843c6b804097c124961b5567ded4f1sewardj   switch (opc2) {
8860d953ebb9b04cbad6891676df597bf0c542b1ec89cerion   case 0x000: // fcmpu (Floating Compare Unordered, PPC32 p403)
8861d953ebb9b04cbad6891676df597bf0c542b1ec89cerion      DIP("fcmpu crf%d,fr%u,fr%u\n", crfD, frA_addr, frB_addr);
8862d953ebb9b04cbad6891676df597bf0c542b1ec89cerion      break;
8863d953ebb9b04cbad6891676df597bf0c542b1ec89cerion   case 0x020: // fcmpo (Floating Compare Ordered, PPC32 p402)
8864d953ebb9b04cbad6891676df597bf0c542b1ec89cerion      DIP("fcmpo crf%d,fr%u,fr%u\n", crfD, frA_addr, frB_addr);
8865d953ebb9b04cbad6891676df597bf0c542b1ec89cerion      break;
8866d953ebb9b04cbad6891676df597bf0c542b1ec89cerion   default:
88675b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion      vex_printf("dis_fp_cmp(ppc)(opc2)\n");
8868d953ebb9b04cbad6891676df597bf0c542b1ec89cerion      return False;
8869e14bb9f862843c6b804097c124961b5567ded4f1sewardj   }
8870e14bb9f862843c6b804097c124961b5567ded4f1sewardj   return True;
8871e14bb9f862843c6b804097c124961b5567ded4f1sewardj}
8872e14bb9f862843c6b804097c124961b5567ded4f1sewardj
8873e14bb9f862843c6b804097c124961b5567ded4f1sewardj
8874e14bb9f862843c6b804097c124961b5567ded4f1sewardj
8875e14bb9f862843c6b804097c124961b5567ded4f1sewardj/*
8876e14bb9f862843c6b804097c124961b5567ded4f1sewardj  Floating Point Rounding/Conversion Instructions
8877e14bb9f862843c6b804097c124961b5567ded4f1sewardj*/
8878e14bb9f862843c6b804097c124961b5567ded4f1sewardjstatic Bool dis_fp_round ( UInt theInstr )
8879e14bb9f862843c6b804097c124961b5567ded4f1sewardj{
8880e14bb9f862843c6b804097c124961b5567ded4f1sewardj   /* X-Form */
888176de5cf615380b23b4b5bcced6541233cd4a93a0cerion   UChar opc1     = ifieldOPC(theInstr);
888276de5cf615380b23b4b5bcced6541233cd4a93a0cerion   UChar b16to20  = ifieldRegA(theInstr);
88837e84630580f89c1022dde97007bffbf6aef81814sewardj   UChar frD_addr = ifieldRegDS(theInstr);
888476de5cf615380b23b4b5bcced6541233cd4a93a0cerion   UChar frB_addr = ifieldRegB(theInstr);
888576de5cf615380b23b4b5bcced6541233cd4a93a0cerion   UInt  opc2     = ifieldOPClo10(theInstr);
888676de5cf615380b23b4b5bcced6541233cd4a93a0cerion   UChar flag_rC  = ifieldBIT0(theInstr);
8887e14bb9f862843c6b804097c124961b5567ded4f1sewardj
8888b183b8571b4ec98866ce2b3653a9d066cf5f16f4sewardj   IRTemp  frD     = newTemp(Ity_F64);
8889b183b8571b4ec98866ce2b3653a9d066cf5f16f4sewardj   IRTemp  frB     = newTemp(Ity_F64);
8890b183b8571b4ec98866ce2b3653a9d066cf5f16f4sewardj   IRTemp  r_tmp32 = newTemp(Ity_I32);
8891b183b8571b4ec98866ce2b3653a9d066cf5f16f4sewardj   IRTemp  r_tmp64 = newTemp(Ity_I64);
8892b183b8571b4ec98866ce2b3653a9d066cf5f16f4sewardj   IRExpr* rm      = get_IR_roundingmode();
8893b183b8571b4ec98866ce2b3653a9d066cf5f16f4sewardj
8894b183b8571b4ec98866ce2b3653a9d066cf5f16f4sewardj   /* By default, we will examine the results of the operation and set
8895b183b8571b4ec98866ce2b3653a9d066cf5f16f4sewardj      fpscr[FPRF] accordingly. */
8896b183b8571b4ec98866ce2b3653a9d066cf5f16f4sewardj   Bool set_FPRF = True;
8897b183b8571b4ec98866ce2b3653a9d066cf5f16f4sewardj
8898b183b8571b4ec98866ce2b3653a9d066cf5f16f4sewardj   /* By default, if flag_RC is set, we will clear cr1 after the
8899b183b8571b4ec98866ce2b3653a9d066cf5f16f4sewardj      operation.  In reality we should set cr1 to indicate the
8900b183b8571b4ec98866ce2b3653a9d066cf5f16f4sewardj      exception status of the operation, but since we're not
8901b183b8571b4ec98866ce2b3653a9d066cf5f16f4sewardj      simulating exceptions, the exception status will appear to be
8902b183b8571b4ec98866ce2b3653a9d066cf5f16f4sewardj      zero.  Hence cr1 should be cleared if this is a . form insn. */
8903b183b8571b4ec98866ce2b3653a9d066cf5f16f4sewardj   Bool clear_CR1 = True;
890466d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj   if ((!(opc1 == 0x3F || opc1 == 0x3B)) || b16to20 != 0) {
89055b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion      vex_printf("dis_fp_round(ppc)(instr)\n");
8906e14bb9f862843c6b804097c124961b5567ded4f1sewardj      return False;
8907e14bb9f862843c6b804097c124961b5567ded4f1sewardj   }
8908e14bb9f862843c6b804097c124961b5567ded4f1sewardj
8909e14bb9f862843c6b804097c124961b5567ded4f1sewardj   assign( frB, getFReg(frB_addr));
891066d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj   if (opc1 == 0x3B) {
891166d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj      /* The fcfid[u]s instructions (from ISA 2.06) are a bit odd because
891266d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj       * they're very similar to the other instructions handled here, but have
891366d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj       * a different primary opcode.
891466d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj       */
891566d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj      switch (opc2) {
891666d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj         case 0x34E: // fcfids (Float convert from signed DWord to single precision)
891766d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj            DIP("fcfids%s fr%u,fr%u\n", flag_rC ? ".":"", frD_addr, frB_addr);
891866d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj            assign( r_tmp64, unop( Iop_ReinterpF64asI64, mkexpr(frB)) );
891966d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj            assign( frD, binop( Iop_RoundF64toF32, rm, binop( Iop_I64StoF64, rm,
892066d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj                                                              mkexpr( r_tmp64 ) ) ) );
892166d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj            goto putFR;
892266d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj
892366d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj         case 0x3Ce: // fcfidus (Float convert from unsigned DWord to single precision)
892466d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj            DIP("fcfidus%s fr%u,fr%u\n", flag_rC ? ".":"", frD_addr, frB_addr);
892566d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj            assign( r_tmp64, unop( Iop_ReinterpF64asI64, mkexpr(frB)) );
892695d6f3a3957232f97e6c680dd49de38cdeb9a1ffsewardj            assign( frD, unop( Iop_F32toF64, binop( Iop_I64UtoF32, rm, mkexpr( r_tmp64 ) ) ) );
892766d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj            goto putFR;
892866d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj      }
892966d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj   }
893066d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj
8931e14bb9f862843c6b804097c124961b5567ded4f1sewardj
8932e14bb9f862843c6b804097c124961b5567ded4f1sewardj   switch (opc2) {
8933f0de28cf1a762b0d6f74c93d3532c89a230673bbcerion   case 0x00C: // frsp (Float Round to Single, PPC32 p423)
89345b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion      DIP("frsp%s fr%u,fr%u\n", flag_rC ? ".":"", frD_addr, frB_addr);
8935b183b8571b4ec98866ce2b3653a9d066cf5f16f4sewardj      assign( frD, binop( Iop_RoundF64toF32, rm, mkexpr(frB) ));
8936d953ebb9b04cbad6891676df597bf0c542b1ec89cerion      break;
8937d953ebb9b04cbad6891676df597bf0c542b1ec89cerion
8938f0de28cf1a762b0d6f74c93d3532c89a230673bbcerion   case 0x00E: // fctiw (Float Conv to Int, PPC32 p404)
89395b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion      DIP("fctiw%s fr%u,fr%u\n", flag_rC ? ".":"", frD_addr, frB_addr);
89405b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion      assign( r_tmp32,
89416c299f3acab617581ea504e45fbb6cab24c2b29fsewardj              binop(Iop_F64toI32S, rm, mkexpr(frB)) );
8942d953ebb9b04cbad6891676df597bf0c542b1ec89cerion      assign( frD, unop( Iop_ReinterpI64asF64,
894307b07a966a2fdbcf621251a0c1a8ab84807fb120cerion                         unop( Iop_32Uto64, mkexpr(r_tmp32))));
8944b183b8571b4ec98866ce2b3653a9d066cf5f16f4sewardj      /* FPRF is undefined after fctiw.  Leave unchanged. */
8945b183b8571b4ec98866ce2b3653a9d066cf5f16f4sewardj      set_FPRF = False;
8946d953ebb9b04cbad6891676df597bf0c542b1ec89cerion      break;
8947d953ebb9b04cbad6891676df597bf0c542b1ec89cerion
8948f0de28cf1a762b0d6f74c93d3532c89a230673bbcerion   case 0x00F: // fctiwz (Float Conv to Int, Round to Zero, PPC32 p405)
89495b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion      DIP("fctiwz%s fr%u,fr%u\n", flag_rC ? ".":"", frD_addr, frB_addr);
8950b183b8571b4ec98866ce2b3653a9d066cf5f16f4sewardj      assign( r_tmp32,
89516c299f3acab617581ea504e45fbb6cab24c2b29fsewardj              binop(Iop_F64toI32S, mkU32(Irrm_ZERO), mkexpr(frB) ));
8952d953ebb9b04cbad6891676df597bf0c542b1ec89cerion      assign( frD, unop( Iop_ReinterpI64asF64,
895307b07a966a2fdbcf621251a0c1a8ab84807fb120cerion                         unop( Iop_32Uto64, mkexpr(r_tmp32))));
8954b183b8571b4ec98866ce2b3653a9d066cf5f16f4sewardj      /* FPRF is undefined after fctiwz.  Leave unchanged. */
8955b183b8571b4ec98866ce2b3653a9d066cf5f16f4sewardj      set_FPRF = False;
8956d953ebb9b04cbad6891676df597bf0c542b1ec89cerion      break;
8957f0de28cf1a762b0d6f74c93d3532c89a230673bbcerion
89584aa412af1d8166cc11f39a6e721df49431d23618sewardj   case 0x08F: case 0x08E: // fctiwu[z]
89594aa412af1d8166cc11f39a6e721df49431d23618sewardj      DIP("fctiwu%s%s fr%u,fr%u\n", opc2 == 0x08F ? "z" : "",
89604aa412af1d8166cc11f39a6e721df49431d23618sewardj               flag_rC ? ".":"", frD_addr, frB_addr);
89614aa412af1d8166cc11f39a6e721df49431d23618sewardj      assign( r_tmp32,
89624aa412af1d8166cc11f39a6e721df49431d23618sewardj              binop( Iop_F64toI32U,
89634aa412af1d8166cc11f39a6e721df49431d23618sewardj                     opc2 == 0x08F ? mkU32( Irrm_ZERO ) : rm,
89644aa412af1d8166cc11f39a6e721df49431d23618sewardj                     mkexpr( frB ) ) );
89654aa412af1d8166cc11f39a6e721df49431d23618sewardj      assign( frD, unop( Iop_ReinterpI64asF64,
89664aa412af1d8166cc11f39a6e721df49431d23618sewardj                         unop( Iop_32Uto64, mkexpr(r_tmp32))));
89674aa412af1d8166cc11f39a6e721df49431d23618sewardj      /* FPRF is undefined after fctiwz.  Leave unchanged. */
89684aa412af1d8166cc11f39a6e721df49431d23618sewardj      set_FPRF = False;
89694aa412af1d8166cc11f39a6e721df49431d23618sewardj      break;
89704aa412af1d8166cc11f39a6e721df49431d23618sewardj
89714aa412af1d8166cc11f39a6e721df49431d23618sewardj
89725b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion   case 0x32E: // fctid (Float Conv to Int DWord, PPC64 p437)
89735b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion      DIP("fctid%s fr%u,fr%u\n", flag_rC ? ".":"", frD_addr, frB_addr);
89745b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion      assign( r_tmp64,
89756c299f3acab617581ea504e45fbb6cab24c2b29fsewardj              binop(Iop_F64toI64S, rm, mkexpr(frB)) );
897607b07a966a2fdbcf621251a0c1a8ab84807fb120cerion      assign( frD, unop( Iop_ReinterpI64asF64, mkexpr(r_tmp64)) );
8977b183b8571b4ec98866ce2b3653a9d066cf5f16f4sewardj      /* FPRF is undefined after fctid.  Leave unchanged. */
8978b183b8571b4ec98866ce2b3653a9d066cf5f16f4sewardj      set_FPRF = False;
897907b07a966a2fdbcf621251a0c1a8ab84807fb120cerion      break;
8980f0de28cf1a762b0d6f74c93d3532c89a230673bbcerion
89815b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion   case 0x32F: // fctidz (Float Conv to Int DWord, Round to Zero, PPC64 p437)
89825b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion      DIP("fctidz%s fr%u,fr%u\n", flag_rC ? ".":"", frD_addr, frB_addr);
8983b183b8571b4ec98866ce2b3653a9d066cf5f16f4sewardj      assign( r_tmp64,
89846c299f3acab617581ea504e45fbb6cab24c2b29fsewardj              binop(Iop_F64toI64S, mkU32(Irrm_ZERO), mkexpr(frB)) );
898507b07a966a2fdbcf621251a0c1a8ab84807fb120cerion      assign( frD, unop( Iop_ReinterpI64asF64, mkexpr(r_tmp64)) );
8986b183b8571b4ec98866ce2b3653a9d066cf5f16f4sewardj      /* FPRF is undefined after fctidz.  Leave unchanged. */
8987b183b8571b4ec98866ce2b3653a9d066cf5f16f4sewardj      set_FPRF = False;
898807b07a966a2fdbcf621251a0c1a8ab84807fb120cerion      break;
8989f0de28cf1a762b0d6f74c93d3532c89a230673bbcerion
89904aa412af1d8166cc11f39a6e721df49431d23618sewardj   case 0x3AE: case 0x3AF: // fctidu[z] (Float Conv to Int DWord Unsigned [Round to Zero])
89914aa412af1d8166cc11f39a6e721df49431d23618sewardj   {
89924aa412af1d8166cc11f39a6e721df49431d23618sewardj      DIP("fctidu%s%s fr%u,fr%u\n", opc2 == 0x3AE ? "" : "z",
89934aa412af1d8166cc11f39a6e721df49431d23618sewardj               flag_rC ? ".":"", frD_addr, frB_addr);
89944aa412af1d8166cc11f39a6e721df49431d23618sewardj      assign( r_tmp64,
89954aa412af1d8166cc11f39a6e721df49431d23618sewardj              binop(Iop_F64toI64U, opc2 == 0x3AE ? rm : mkU32(Irrm_ZERO), mkexpr(frB)) );
89964aa412af1d8166cc11f39a6e721df49431d23618sewardj      assign( frD, unop( Iop_ReinterpI64asF64, mkexpr(r_tmp64)) );
89974aa412af1d8166cc11f39a6e721df49431d23618sewardj      /* FPRF is undefined after fctidz.  Leave unchanged. */
89984aa412af1d8166cc11f39a6e721df49431d23618sewardj      set_FPRF = False;
89994aa412af1d8166cc11f39a6e721df49431d23618sewardj      break;
90004aa412af1d8166cc11f39a6e721df49431d23618sewardj   }
90015b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion   case 0x34E: // fcfid (Float Conv from Int DWord, PPC64 p434)
90025b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion      DIP("fcfid%s fr%u,fr%u\n", flag_rC ? ".":"", frD_addr, frB_addr);
900307b07a966a2fdbcf621251a0c1a8ab84807fb120cerion      assign( r_tmp64, unop( Iop_ReinterpF64asI64, mkexpr(frB)) );
9004b183b8571b4ec98866ce2b3653a9d066cf5f16f4sewardj      assign( frD,
90056c299f3acab617581ea504e45fbb6cab24c2b29fsewardj              binop(Iop_I64StoF64, rm, mkexpr(r_tmp64)) );
900607b07a966a2fdbcf621251a0c1a8ab84807fb120cerion      break;
9007f0de28cf1a762b0d6f74c93d3532c89a230673bbcerion
900866d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj   case 0x3CE: // fcfidu (Float convert from unsigned DWord)
900966d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj      DIP("fcfidu%s fr%u,fr%u\n", flag_rC ? ".":"", frD_addr, frB_addr);
901066d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj      assign( r_tmp64, unop( Iop_ReinterpF64asI64, mkexpr(frB)) );
901166d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj      assign( frD, binop( Iop_I64UtoF64, rm, mkexpr( r_tmp64 ) ) );
901266d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj      break;
901366d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj
90147e84630580f89c1022dde97007bffbf6aef81814sewardj   case 0x188: case 0x1A8: case 0x1C8: case 0x1E8: // frin, friz, frip, frim
90157e84630580f89c1022dde97007bffbf6aef81814sewardj      switch(opc2) {
90167e84630580f89c1022dde97007bffbf6aef81814sewardj      case 0x188: // frin (Floating Round to Integer Nearest)
90177e84630580f89c1022dde97007bffbf6aef81814sewardj         DIP("frin%s fr%u,fr%u\n", flag_rC ? ".":"", frD_addr, frB_addr);
90187e84630580f89c1022dde97007bffbf6aef81814sewardj         assign( r_tmp64,
90197e84630580f89c1022dde97007bffbf6aef81814sewardj                 binop(Iop_F64toI64S, mkU32(Irrm_NEAREST), mkexpr(frB)) );
90207e84630580f89c1022dde97007bffbf6aef81814sewardj         break;
90217e84630580f89c1022dde97007bffbf6aef81814sewardj      case 0x1A8: // friz (Floating Round to Integer Toward Zero)
90227e84630580f89c1022dde97007bffbf6aef81814sewardj         DIP("friz%s fr%u,fr%u\n", flag_rC ? ".":"", frD_addr, frB_addr);
90237e84630580f89c1022dde97007bffbf6aef81814sewardj         assign( r_tmp64,
90247e84630580f89c1022dde97007bffbf6aef81814sewardj                 binop(Iop_F64toI64S, mkU32(Irrm_ZERO), mkexpr(frB)) );
90257e84630580f89c1022dde97007bffbf6aef81814sewardj         break;
90267e84630580f89c1022dde97007bffbf6aef81814sewardj      case 0x1C8: // frip (Floating Round to Integer Plus)
90277e84630580f89c1022dde97007bffbf6aef81814sewardj         DIP("frip%s fr%u,fr%u\n", flag_rC ? ".":"", frD_addr, frB_addr);
90287e84630580f89c1022dde97007bffbf6aef81814sewardj         assign( r_tmp64,
90297e84630580f89c1022dde97007bffbf6aef81814sewardj                 binop(Iop_F64toI64S, mkU32(Irrm_PosINF), mkexpr(frB)) );
90307e84630580f89c1022dde97007bffbf6aef81814sewardj         break;
90317e84630580f89c1022dde97007bffbf6aef81814sewardj      case 0x1E8: // frim (Floating Round to Integer Minus)
90327e84630580f89c1022dde97007bffbf6aef81814sewardj         DIP("frim%s fr%u,fr%u\n", flag_rC ? ".":"", frD_addr, frB_addr);
90337e84630580f89c1022dde97007bffbf6aef81814sewardj         assign( r_tmp64,
90347e84630580f89c1022dde97007bffbf6aef81814sewardj                 binop(Iop_F64toI64S, mkU32(Irrm_NegINF), mkexpr(frB)) );
90357e84630580f89c1022dde97007bffbf6aef81814sewardj         break;
90367e84630580f89c1022dde97007bffbf6aef81814sewardj      }
90377e84630580f89c1022dde97007bffbf6aef81814sewardj
90387e84630580f89c1022dde97007bffbf6aef81814sewardj      /* don't use the rounded integer if frB is outside -9e18..9e18 */
90397e84630580f89c1022dde97007bffbf6aef81814sewardj      /* F64 has only log10(2**52) significant digits anyway */
90407e84630580f89c1022dde97007bffbf6aef81814sewardj      /* need to preserve sign of zero */
90417e84630580f89c1022dde97007bffbf6aef81814sewardj      /*   frD = (fabs(frB) > 9e18) ? frB :
90427e84630580f89c1022dde97007bffbf6aef81814sewardj               (sign(frB)) ? -fabs((double)r_tmp64) : (double)r_tmp64  */
904399dd03e04a6914d90d5fee727d61d76905334becflorian      assign(frD, IRExpr_ITE(
9044009230b9758291b594e60d7c0243a73d53e81854sewardj                     binop(Iop_CmpNE8,
9045009230b9758291b594e60d7c0243a73d53e81854sewardj                           unop(Iop_32to8,
9046009230b9758291b594e60d7c0243a73d53e81854sewardj                                binop(Iop_CmpF64,
9047009230b9758291b594e60d7c0243a73d53e81854sewardj                                      IRExpr_Const(IRConst_F64(9e18)),
9048009230b9758291b594e60d7c0243a73d53e81854sewardj                                      unop(Iop_AbsF64, mkexpr(frB)))),
9049009230b9758291b594e60d7c0243a73d53e81854sewardj                           mkU8(0)),
905099dd03e04a6914d90d5fee727d61d76905334becflorian                     mkexpr(frB),
905199dd03e04a6914d90d5fee727d61d76905334becflorian                     IRExpr_ITE(
9052009230b9758291b594e60d7c0243a73d53e81854sewardj                        binop(Iop_CmpNE32,
9053009230b9758291b594e60d7c0243a73d53e81854sewardj                              binop(Iop_Shr32,
9054009230b9758291b594e60d7c0243a73d53e81854sewardj                                    unop(Iop_64HIto32,
9055009230b9758291b594e60d7c0243a73d53e81854sewardj                                         unop(Iop_ReinterpF64asI64,
9056009230b9758291b594e60d7c0243a73d53e81854sewardj                                              mkexpr(frB))),
9057009230b9758291b594e60d7c0243a73d53e81854sewardj                                    mkU8(31)),
9058009230b9758291b594e60d7c0243a73d53e81854sewardj                              mkU32(0)),
9059009230b9758291b594e60d7c0243a73d53e81854sewardj                        unop(Iop_NegF64,
9060009230b9758291b594e60d7c0243a73d53e81854sewardj                             unop( Iop_AbsF64,
9061009230b9758291b594e60d7c0243a73d53e81854sewardj                                   binop(Iop_I64StoF64, mkU32(0),
906299dd03e04a6914d90d5fee727d61d76905334becflorian                                         mkexpr(r_tmp64)) )),
906399dd03e04a6914d90d5fee727d61d76905334becflorian                        binop(Iop_I64StoF64, mkU32(0), mkexpr(r_tmp64) )
906499dd03e04a6914d90d5fee727d61d76905334becflorian                     )
9065009230b9758291b594e60d7c0243a73d53e81854sewardj      ));
90667e84630580f89c1022dde97007bffbf6aef81814sewardj      break;
90677e84630580f89c1022dde97007bffbf6aef81814sewardj
9068d953ebb9b04cbad6891676df597bf0c542b1ec89cerion   default:
90695b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion      vex_printf("dis_fp_round(ppc)(opc2)\n");
9070d953ebb9b04cbad6891676df597bf0c542b1ec89cerion      return False;
9071e14bb9f862843c6b804097c124961b5567ded4f1sewardj   }
907266d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardjputFR:
9073e14bb9f862843c6b804097c124961b5567ded4f1sewardj   putFReg( frD_addr, mkexpr(frD) );
9074b183b8571b4ec98866ce2b3653a9d066cf5f16f4sewardj
9075b183b8571b4ec98866ce2b3653a9d066cf5f16f4sewardj   if (set_FPRF) {
9076b183b8571b4ec98866ce2b3653a9d066cf5f16f4sewardj      // XXX XXX XXX FIXME
9077b183b8571b4ec98866ce2b3653a9d066cf5f16f4sewardj      // set FPRF from frD
9078b183b8571b4ec98866ce2b3653a9d066cf5f16f4sewardj   }
9079b183b8571b4ec98866ce2b3653a9d066cf5f16f4sewardj
9080b183b8571b4ec98866ce2b3653a9d066cf5f16f4sewardj   if (flag_rC && clear_CR1) {
9081b183b8571b4ec98866ce2b3653a9d066cf5f16f4sewardj      putCR321( 1, mkU8(0) );
9082b183b8571b4ec98866ce2b3653a9d066cf5f16f4sewardj      putCR0( 1, mkU8(0) );
9083b183b8571b4ec98866ce2b3653a9d066cf5f16f4sewardj   }
9084b183b8571b4ec98866ce2b3653a9d066cf5f16f4sewardj
9085e14bb9f862843c6b804097c124961b5567ded4f1sewardj   return True;
9086e14bb9f862843c6b804097c124961b5567ded4f1sewardj}
9087e14bb9f862843c6b804097c124961b5567ded4f1sewardj
90887e84630580f89c1022dde97007bffbf6aef81814sewardj/*
90897e84630580f89c1022dde97007bffbf6aef81814sewardj  Floating Point Pair Instructions
90907e84630580f89c1022dde97007bffbf6aef81814sewardj*/
90917e84630580f89c1022dde97007bffbf6aef81814sewardjstatic Bool dis_fp_pair ( UInt theInstr )
90927e84630580f89c1022dde97007bffbf6aef81814sewardj{
90937e84630580f89c1022dde97007bffbf6aef81814sewardj   /* X-Form/DS-Form */
90947e84630580f89c1022dde97007bffbf6aef81814sewardj   UChar  opc1         = ifieldOPC(theInstr);
90957e84630580f89c1022dde97007bffbf6aef81814sewardj   UChar  frT_hi_addr  = ifieldRegDS(theInstr);
90967e84630580f89c1022dde97007bffbf6aef81814sewardj   UChar  frT_lo_addr  = frT_hi_addr + 1;
90977e84630580f89c1022dde97007bffbf6aef81814sewardj   UChar  rA_addr      = ifieldRegA(theInstr);
90987e84630580f89c1022dde97007bffbf6aef81814sewardj   UChar  rB_addr      = ifieldRegB(theInstr);
90997e84630580f89c1022dde97007bffbf6aef81814sewardj   UInt  uimm16        = ifieldUIMM16(theInstr);
91007e84630580f89c1022dde97007bffbf6aef81814sewardj   Int    simm16       = extend_s_16to32(uimm16);
91017e84630580f89c1022dde97007bffbf6aef81814sewardj   UInt   opc2         = ifieldOPClo10(theInstr);
91027e84630580f89c1022dde97007bffbf6aef81814sewardj   IRType ty           = mode64 ? Ity_I64 : Ity_I32;
91037e84630580f89c1022dde97007bffbf6aef81814sewardj   IRTemp EA_hi        = newTemp(ty);
91047e84630580f89c1022dde97007bffbf6aef81814sewardj   IRTemp EA_lo        = newTemp(ty);
91057e84630580f89c1022dde97007bffbf6aef81814sewardj   IRTemp frT_hi       = newTemp(Ity_F64);
91067e84630580f89c1022dde97007bffbf6aef81814sewardj   IRTemp frT_lo       = newTemp(Ity_F64);
91077e84630580f89c1022dde97007bffbf6aef81814sewardj   UChar b0            = ifieldBIT0(theInstr);
91087e84630580f89c1022dde97007bffbf6aef81814sewardj   Bool is_load        = 0;
91097e84630580f89c1022dde97007bffbf6aef81814sewardj
91107e84630580f89c1022dde97007bffbf6aef81814sewardj   if ((frT_hi_addr %2) != 0) {
91117e84630580f89c1022dde97007bffbf6aef81814sewardj      vex_printf("dis_fp_pair(ppc) : odd frT register\n");
91127e84630580f89c1022dde97007bffbf6aef81814sewardj      return False;
91137e84630580f89c1022dde97007bffbf6aef81814sewardj   }
91147e84630580f89c1022dde97007bffbf6aef81814sewardj
91157e84630580f89c1022dde97007bffbf6aef81814sewardj   switch (opc1) {
91167e84630580f89c1022dde97007bffbf6aef81814sewardj   case 0x1F: // register offset
91177e84630580f89c1022dde97007bffbf6aef81814sewardj      switch(opc2) {
91187e84630580f89c1022dde97007bffbf6aef81814sewardj      case 0x317:     // lfdpx (FP Load Double Pair X-form, ISA 2.05  p125)
91197e84630580f89c1022dde97007bffbf6aef81814sewardj         DIP("ldpx fr%u,r%u,r%u\n", frT_hi_addr, rA_addr, rB_addr);
91207e84630580f89c1022dde97007bffbf6aef81814sewardj         is_load = 1;
91217e84630580f89c1022dde97007bffbf6aef81814sewardj         break;
91227e84630580f89c1022dde97007bffbf6aef81814sewardj      case 0x397:     // stfdpx (FP STORE Double Pair X-form, ISA 2.05  p125)
91237e84630580f89c1022dde97007bffbf6aef81814sewardj         DIP("stdpx fr%u,r%u,r%u\n", frT_hi_addr, rA_addr, rB_addr);
91247e84630580f89c1022dde97007bffbf6aef81814sewardj         break;
91257e84630580f89c1022dde97007bffbf6aef81814sewardj      default:
91267e84630580f89c1022dde97007bffbf6aef81814sewardj         vex_printf("dis_fp_pair(ppc) : X-form wrong opc2\n");
91277e84630580f89c1022dde97007bffbf6aef81814sewardj         return False;
91287e84630580f89c1022dde97007bffbf6aef81814sewardj      }
91297e84630580f89c1022dde97007bffbf6aef81814sewardj
91307e84630580f89c1022dde97007bffbf6aef81814sewardj      if (b0 != 0) {
91317e84630580f89c1022dde97007bffbf6aef81814sewardj         vex_printf("dis_fp_pair(ppc)(0x1F,b0)\n");
91327e84630580f89c1022dde97007bffbf6aef81814sewardj         return False;
91337e84630580f89c1022dde97007bffbf6aef81814sewardj      }
91347e84630580f89c1022dde97007bffbf6aef81814sewardj      assign( EA_hi, ea_rAor0_idxd( rA_addr, rB_addr ) );
91357e84630580f89c1022dde97007bffbf6aef81814sewardj      break;
91367e84630580f89c1022dde97007bffbf6aef81814sewardj   case 0x39: // lfdp (FP Load Double Pair DS-form, ISA 2.05  p125)
91377e84630580f89c1022dde97007bffbf6aef81814sewardj      DIP("lfdp fr%u,%d(r%u)\n", frT_hi_addr, simm16, rA_addr);
91387e84630580f89c1022dde97007bffbf6aef81814sewardj      assign( EA_hi, ea_rAor0_simm( rA_addr, simm16  ) );
91397e84630580f89c1022dde97007bffbf6aef81814sewardj      is_load = 1;
91407e84630580f89c1022dde97007bffbf6aef81814sewardj      break;
91417e84630580f89c1022dde97007bffbf6aef81814sewardj   case 0x3d: // stfdp (FP Store Double Pair DS-form, ISA 2.05  p125)
91427e84630580f89c1022dde97007bffbf6aef81814sewardj      DIP("stfdp fr%u,%d(r%u)\n", frT_hi_addr, simm16, rA_addr);
91437e84630580f89c1022dde97007bffbf6aef81814sewardj      assign( EA_hi, ea_rAor0_simm( rA_addr, simm16  ) );
91447e84630580f89c1022dde97007bffbf6aef81814sewardj      break;
91457e84630580f89c1022dde97007bffbf6aef81814sewardj   default:   // immediate offset
91467e84630580f89c1022dde97007bffbf6aef81814sewardj      vex_printf("dis_fp_pair(ppc)(instr)\n");
91477e84630580f89c1022dde97007bffbf6aef81814sewardj      return False;
91487e84630580f89c1022dde97007bffbf6aef81814sewardj   }
91497e84630580f89c1022dde97007bffbf6aef81814sewardj
91507e84630580f89c1022dde97007bffbf6aef81814sewardj   if (mode64)
91517e84630580f89c1022dde97007bffbf6aef81814sewardj      assign( EA_lo, binop(Iop_Add64, mkexpr(EA_hi), mkU64(8)) );
91527e84630580f89c1022dde97007bffbf6aef81814sewardj   else
91537e84630580f89c1022dde97007bffbf6aef81814sewardj      assign( EA_lo, binop(Iop_Add32, mkexpr(EA_hi), mkU32(8)) );
91547e84630580f89c1022dde97007bffbf6aef81814sewardj
91557e84630580f89c1022dde97007bffbf6aef81814sewardj   assign( frT_hi, getFReg(frT_hi_addr) );
91567e84630580f89c1022dde97007bffbf6aef81814sewardj   assign( frT_lo, getFReg(frT_lo_addr) );
91577e84630580f89c1022dde97007bffbf6aef81814sewardj
91587e84630580f89c1022dde97007bffbf6aef81814sewardj   if (is_load) {
91591f5fe1fc3a37ca729925e8eec25aa1025b4a6cdbcarll      putFReg( frT_hi_addr, load(Ity_F64, mkexpr(EA_hi)) );
91601f5fe1fc3a37ca729925e8eec25aa1025b4a6cdbcarll      putFReg( frT_lo_addr, load(Ity_F64, mkexpr(EA_lo)) );
91617e84630580f89c1022dde97007bffbf6aef81814sewardj   } else {
91621f5fe1fc3a37ca729925e8eec25aa1025b4a6cdbcarll      store( mkexpr(EA_hi), mkexpr(frT_hi) );
91631f5fe1fc3a37ca729925e8eec25aa1025b4a6cdbcarll      store( mkexpr(EA_lo), mkexpr(frT_lo) );
91647e84630580f89c1022dde97007bffbf6aef81814sewardj   }
91657e84630580f89c1022dde97007bffbf6aef81814sewardj
91667e84630580f89c1022dde97007bffbf6aef81814sewardj   return True;
91677e84630580f89c1022dde97007bffbf6aef81814sewardj}
9168e14bb9f862843c6b804097c124961b5567ded4f1sewardj
9169e14bb9f862843c6b804097c124961b5567ded4f1sewardj
9170e14bb9f862843c6b804097c124961b5567ded4f1sewardj/*
917178850ae9874a90ea625fcee1fd4c359375b7b538carll  Floating Point Merge Instructions
917278850ae9874a90ea625fcee1fd4c359375b7b538carll*/
917378850ae9874a90ea625fcee1fd4c359375b7b538carllstatic Bool dis_fp_merge ( UInt theInstr )
917478850ae9874a90ea625fcee1fd4c359375b7b538carll{
917578850ae9874a90ea625fcee1fd4c359375b7b538carll   /* X-Form */
917678850ae9874a90ea625fcee1fd4c359375b7b538carll   UInt  opc2     = ifieldOPClo10(theInstr);
917778850ae9874a90ea625fcee1fd4c359375b7b538carll   UChar frD_addr = ifieldRegDS(theInstr);
917878850ae9874a90ea625fcee1fd4c359375b7b538carll   UChar frA_addr = ifieldRegA(theInstr);
917978850ae9874a90ea625fcee1fd4c359375b7b538carll   UChar frB_addr = ifieldRegB(theInstr);
918078850ae9874a90ea625fcee1fd4c359375b7b538carll
918178850ae9874a90ea625fcee1fd4c359375b7b538carll   IRTemp frD = newTemp(Ity_F64);
918278850ae9874a90ea625fcee1fd4c359375b7b538carll   IRTemp frA = newTemp(Ity_F64);
918378850ae9874a90ea625fcee1fd4c359375b7b538carll   IRTemp frB = newTemp(Ity_F64);
918478850ae9874a90ea625fcee1fd4c359375b7b538carll
918578850ae9874a90ea625fcee1fd4c359375b7b538carll   assign( frA, getFReg(frA_addr));
918678850ae9874a90ea625fcee1fd4c359375b7b538carll   assign( frB, getFReg(frB_addr));
918778850ae9874a90ea625fcee1fd4c359375b7b538carll
918878850ae9874a90ea625fcee1fd4c359375b7b538carll   switch (opc2) {
918978850ae9874a90ea625fcee1fd4c359375b7b538carll   case 0x3c6: // fmrgew floating merge even word
919078850ae9874a90ea625fcee1fd4c359375b7b538carll      DIP("fmrgew fr%u,fr%u,fr%u\n", frD_addr, frA_addr, frB_addr);
919178850ae9874a90ea625fcee1fd4c359375b7b538carll
919278850ae9874a90ea625fcee1fd4c359375b7b538carll      assign( frD, unop( Iop_ReinterpI64asF64,
919378850ae9874a90ea625fcee1fd4c359375b7b538carll                         binop( Iop_32HLto64,
919478850ae9874a90ea625fcee1fd4c359375b7b538carll                                unop( Iop_64HIto32,
919578850ae9874a90ea625fcee1fd4c359375b7b538carll                                      unop( Iop_ReinterpF64asI64,
919678850ae9874a90ea625fcee1fd4c359375b7b538carll                                            mkexpr(frA) ) ),
919778850ae9874a90ea625fcee1fd4c359375b7b538carll                                unop( Iop_64HIto32,
919878850ae9874a90ea625fcee1fd4c359375b7b538carll                                      unop( Iop_ReinterpF64asI64,
919978850ae9874a90ea625fcee1fd4c359375b7b538carll                                            mkexpr(frB) ) ) ) ) );
920078850ae9874a90ea625fcee1fd4c359375b7b538carll   break;
920178850ae9874a90ea625fcee1fd4c359375b7b538carll
920278850ae9874a90ea625fcee1fd4c359375b7b538carll   case 0x346: // fmrgow floating merge odd word
920378850ae9874a90ea625fcee1fd4c359375b7b538carll      DIP("fmrgow fr%u,fr%u,fr%u\n", frD_addr, frA_addr, frB_addr);
920478850ae9874a90ea625fcee1fd4c359375b7b538carll
920578850ae9874a90ea625fcee1fd4c359375b7b538carll      assign( frD, unop( Iop_ReinterpI64asF64,
920678850ae9874a90ea625fcee1fd4c359375b7b538carll                         binop( Iop_32HLto64,
920778850ae9874a90ea625fcee1fd4c359375b7b538carll                                unop( Iop_64to32,
920878850ae9874a90ea625fcee1fd4c359375b7b538carll                                      unop( Iop_ReinterpF64asI64,
920978850ae9874a90ea625fcee1fd4c359375b7b538carll                                            mkexpr(frA) ) ),
921078850ae9874a90ea625fcee1fd4c359375b7b538carll                                unop( Iop_64to32,
921178850ae9874a90ea625fcee1fd4c359375b7b538carll                                      unop( Iop_ReinterpF64asI64,
921278850ae9874a90ea625fcee1fd4c359375b7b538carll                                            mkexpr(frB) ) ) ) ) );
921378850ae9874a90ea625fcee1fd4c359375b7b538carll   break;
921478850ae9874a90ea625fcee1fd4c359375b7b538carll
921578850ae9874a90ea625fcee1fd4c359375b7b538carll   default:
921678850ae9874a90ea625fcee1fd4c359375b7b538carll      vex_printf("dis_fp_merge(ppc)(opc2)\n");
921778850ae9874a90ea625fcee1fd4c359375b7b538carll      return False;
921878850ae9874a90ea625fcee1fd4c359375b7b538carll   }
921978850ae9874a90ea625fcee1fd4c359375b7b538carll
922078850ae9874a90ea625fcee1fd4c359375b7b538carll   putFReg( frD_addr, mkexpr(frD) );
922178850ae9874a90ea625fcee1fd4c359375b7b538carll   return True;
922278850ae9874a90ea625fcee1fd4c359375b7b538carll}
922378850ae9874a90ea625fcee1fd4c359375b7b538carll
922478850ae9874a90ea625fcee1fd4c359375b7b538carll/*
9225e14bb9f862843c6b804097c124961b5567ded4f1sewardj  Floating Point Move Instructions
9226e14bb9f862843c6b804097c124961b5567ded4f1sewardj*/
9227e14bb9f862843c6b804097c124961b5567ded4f1sewardjstatic Bool dis_fp_move ( UInt theInstr )
9228e14bb9f862843c6b804097c124961b5567ded4f1sewardj{
9229e14bb9f862843c6b804097c124961b5567ded4f1sewardj   /* X-Form */
923076de5cf615380b23b4b5bcced6541233cd4a93a0cerion   UChar opc1     = ifieldOPC(theInstr);
923176de5cf615380b23b4b5bcced6541233cd4a93a0cerion   UChar frD_addr = ifieldRegDS(theInstr);
92327e84630580f89c1022dde97007bffbf6aef81814sewardj   UChar frA_addr = ifieldRegA(theInstr);
923376de5cf615380b23b4b5bcced6541233cd4a93a0cerion   UChar frB_addr = ifieldRegB(theInstr);
923476de5cf615380b23b4b5bcced6541233cd4a93a0cerion   UInt  opc2     = ifieldOPClo10(theInstr);
923576de5cf615380b23b4b5bcced6541233cd4a93a0cerion   UChar flag_rC  = ifieldBIT0(theInstr);
9236e14bb9f862843c6b804097c124961b5567ded4f1sewardj
9237e14bb9f862843c6b804097c124961b5567ded4f1sewardj   IRTemp frD = newTemp(Ity_F64);
9238e14bb9f862843c6b804097c124961b5567ded4f1sewardj   IRTemp frB = newTemp(Ity_F64);
92397e84630580f89c1022dde97007bffbf6aef81814sewardj   IRTemp itmpB = newTemp(Ity_F64);
92407e84630580f89c1022dde97007bffbf6aef81814sewardj   IRTemp frA;
92417e84630580f89c1022dde97007bffbf6aef81814sewardj   IRTemp signA;
92427e84630580f89c1022dde97007bffbf6aef81814sewardj   IRTemp hiD;
9243e14bb9f862843c6b804097c124961b5567ded4f1sewardj
92447e84630580f89c1022dde97007bffbf6aef81814sewardj   if (opc1 != 0x3F || (frA_addr != 0 && opc2 != 0x008)) {
92455b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion      vex_printf("dis_fp_move(ppc)(instr)\n");
9246e14bb9f862843c6b804097c124961b5567ded4f1sewardj      return False;
9247e14bb9f862843c6b804097c124961b5567ded4f1sewardj   }
9248e14bb9f862843c6b804097c124961b5567ded4f1sewardj
9249e14bb9f862843c6b804097c124961b5567ded4f1sewardj   assign( frB, getFReg(frB_addr));
9250e14bb9f862843c6b804097c124961b5567ded4f1sewardj
9251e14bb9f862843c6b804097c124961b5567ded4f1sewardj   switch (opc2) {
92527e84630580f89c1022dde97007bffbf6aef81814sewardj   case 0x008: // fcpsgn (Floating Copy Sign, ISA_V2.05 p126)
92537e84630580f89c1022dde97007bffbf6aef81814sewardj      DIP("fcpsgn%s fr%u,fr%u,fr%u\n", flag_rC ? ".":"", frD_addr, frA_addr,
92547e84630580f89c1022dde97007bffbf6aef81814sewardj          frB_addr);
92557e84630580f89c1022dde97007bffbf6aef81814sewardj      signA = newTemp(Ity_I32);
92567e84630580f89c1022dde97007bffbf6aef81814sewardj      hiD = newTemp(Ity_I32);
92577e84630580f89c1022dde97007bffbf6aef81814sewardj      itmpB = newTemp(Ity_I64);
92587e84630580f89c1022dde97007bffbf6aef81814sewardj      frA = newTemp(Ity_F64);
92597e84630580f89c1022dde97007bffbf6aef81814sewardj      assign( frA, getFReg(frA_addr) );
92607e84630580f89c1022dde97007bffbf6aef81814sewardj
92617e84630580f89c1022dde97007bffbf6aef81814sewardj      /* get A's sign bit */
92627e84630580f89c1022dde97007bffbf6aef81814sewardj      assign(signA, binop(Iop_And32,
92637e84630580f89c1022dde97007bffbf6aef81814sewardj                          unop(Iop_64HIto32, unop(Iop_ReinterpF64asI64,
92647e84630580f89c1022dde97007bffbf6aef81814sewardj                                                  mkexpr(frA))),
92657e84630580f89c1022dde97007bffbf6aef81814sewardj                          mkU32(0x80000000)) );
92667e84630580f89c1022dde97007bffbf6aef81814sewardj
92677e84630580f89c1022dde97007bffbf6aef81814sewardj      assign( itmpB, unop(Iop_ReinterpF64asI64, mkexpr(frB)) );
92687e84630580f89c1022dde97007bffbf6aef81814sewardj
92697e84630580f89c1022dde97007bffbf6aef81814sewardj      /* mask off B's sign bit and or in A's sign bit */
92707e84630580f89c1022dde97007bffbf6aef81814sewardj      assign(hiD, binop(Iop_Or32,
92717e84630580f89c1022dde97007bffbf6aef81814sewardj                        binop(Iop_And32,
92727e84630580f89c1022dde97007bffbf6aef81814sewardj                              unop(Iop_64HIto32,
92737e84630580f89c1022dde97007bffbf6aef81814sewardj                                   mkexpr(itmpB)),  /* frB's high 32 bits */
92747e84630580f89c1022dde97007bffbf6aef81814sewardj                              mkU32(0x7fffffff)),
92757e84630580f89c1022dde97007bffbf6aef81814sewardj                        mkexpr(signA)) );
92767e84630580f89c1022dde97007bffbf6aef81814sewardj
92777e84630580f89c1022dde97007bffbf6aef81814sewardj      /* combine hiD/loB into frD */
92787e84630580f89c1022dde97007bffbf6aef81814sewardj      assign( frD, unop(Iop_ReinterpI64asF64,
92797e84630580f89c1022dde97007bffbf6aef81814sewardj                        binop(Iop_32HLto64,
92807e84630580f89c1022dde97007bffbf6aef81814sewardj                              mkexpr(hiD),
92817e84630580f89c1022dde97007bffbf6aef81814sewardj                              unop(Iop_64to32,
92827e84630580f89c1022dde97007bffbf6aef81814sewardj                                   mkexpr(itmpB)))) );   /* frB's low 32 bits */
92837e84630580f89c1022dde97007bffbf6aef81814sewardj      break;
92847e84630580f89c1022dde97007bffbf6aef81814sewardj
9285d953ebb9b04cbad6891676df597bf0c542b1ec89cerion   case 0x028: // fneg (Floating Negate, PPC32 p416)
92865b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion      DIP("fneg%s fr%u,fr%u\n", flag_rC ? ".":"", frD_addr, frB_addr);
9287d953ebb9b04cbad6891676df597bf0c542b1ec89cerion      assign( frD, unop( Iop_NegF64, mkexpr(frB) ));
9288d953ebb9b04cbad6891676df597bf0c542b1ec89cerion      break;
9289d953ebb9b04cbad6891676df597bf0c542b1ec89cerion
9290d953ebb9b04cbad6891676df597bf0c542b1ec89cerion   case 0x048: // fmr (Floating Move Register, PPC32 p410)
92915b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion      DIP("fmr%s fr%u,fr%u\n", flag_rC ? ".":"", frD_addr, frB_addr);
9292d953ebb9b04cbad6891676df597bf0c542b1ec89cerion      assign( frD, mkexpr(frB) );
9293d953ebb9b04cbad6891676df597bf0c542b1ec89cerion      break;
9294d953ebb9b04cbad6891676df597bf0c542b1ec89cerion
9295d953ebb9b04cbad6891676df597bf0c542b1ec89cerion   case 0x088: // fnabs (Floating Negative Absolute Value, PPC32 p415)
92965b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion      DIP("fnabs%s fr%u,fr%u\n", flag_rC ? ".":"", frD_addr, frB_addr);
9297d953ebb9b04cbad6891676df597bf0c542b1ec89cerion      assign( frD, unop( Iop_NegF64, unop( Iop_AbsF64, mkexpr(frB) )));
9298d953ebb9b04cbad6891676df597bf0c542b1ec89cerion      break;
9299d953ebb9b04cbad6891676df597bf0c542b1ec89cerion
9300d953ebb9b04cbad6891676df597bf0c542b1ec89cerion   case 0x108: // fabs (Floating Absolute Value, PPC32 p399)
93015b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion      DIP("fabs%s fr%u,fr%u\n", flag_rC ? ".":"", frD_addr, frB_addr);
9302d953ebb9b04cbad6891676df597bf0c542b1ec89cerion      assign( frD, unop( Iop_AbsF64, mkexpr(frB) ));
9303d953ebb9b04cbad6891676df597bf0c542b1ec89cerion      break;
9304d953ebb9b04cbad6891676df597bf0c542b1ec89cerion
9305d953ebb9b04cbad6891676df597bf0c542b1ec89cerion   default:
93065b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion      vex_printf("dis_fp_move(ppc)(opc2)\n");
9307d953ebb9b04cbad6891676df597bf0c542b1ec89cerion      return False;
9308e14bb9f862843c6b804097c124961b5567ded4f1sewardj   }
9309e14bb9f862843c6b804097c124961b5567ded4f1sewardj
9310e14bb9f862843c6b804097c124961b5567ded4f1sewardj   putFReg( frD_addr, mkexpr(frD) );
9311b183b8571b4ec98866ce2b3653a9d066cf5f16f4sewardj
9312b183b8571b4ec98866ce2b3653a9d066cf5f16f4sewardj   /* None of these change FPRF.  cr1 is set in the usual way though,
9313b183b8571b4ec98866ce2b3653a9d066cf5f16f4sewardj      if flag_rC is set. */
9314b183b8571b4ec98866ce2b3653a9d066cf5f16f4sewardj
9315b183b8571b4ec98866ce2b3653a9d066cf5f16f4sewardj   if (flag_rC) {
9316b183b8571b4ec98866ce2b3653a9d066cf5f16f4sewardj      putCR321( 1, mkU8(0) );
9317b183b8571b4ec98866ce2b3653a9d066cf5f16f4sewardj      putCR0( 1, mkU8(0) );
9318b183b8571b4ec98866ce2b3653a9d066cf5f16f4sewardj   }
9319b183b8571b4ec98866ce2b3653a9d066cf5f16f4sewardj
9320e14bb9f862843c6b804097c124961b5567ded4f1sewardj   return True;
9321e14bb9f862843c6b804097c124961b5567ded4f1sewardj}
9322e14bb9f862843c6b804097c124961b5567ded4f1sewardj
9323e14bb9f862843c6b804097c124961b5567ded4f1sewardj
9324e14bb9f862843c6b804097c124961b5567ded4f1sewardj
9325e14bb9f862843c6b804097c124961b5567ded4f1sewardj/*
9326e14bb9f862843c6b804097c124961b5567ded4f1sewardj  Floating Point Status/Control Register Instructions
9327e14bb9f862843c6b804097c124961b5567ded4f1sewardj*/
9328c6bbd470e9bd9898b84959227a406d3972d95f3bsewardjstatic Bool dis_fp_scr ( UInt theInstr, Bool GX_level )
9329e14bb9f862843c6b804097c124961b5567ded4f1sewardj{
933076de5cf615380b23b4b5bcced6541233cd4a93a0cerion   /* Many forms - see each switch case */
933176de5cf615380b23b4b5bcced6541233cd4a93a0cerion   UChar opc1    = ifieldOPC(theInstr);
933276de5cf615380b23b4b5bcced6541233cd4a93a0cerion   UInt  opc2    = ifieldOPClo10(theInstr);
933376de5cf615380b23b4b5bcced6541233cd4a93a0cerion   UChar flag_rC = ifieldBIT0(theInstr);
9334e14bb9f862843c6b804097c124961b5567ded4f1sewardj
9335e14bb9f862843c6b804097c124961b5567ded4f1sewardj   if (opc1 != 0x3F) {
93365b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion      vex_printf("dis_fp_scr(ppc)(instr)\n");
9337e14bb9f862843c6b804097c124961b5567ded4f1sewardj      return False;
9338e14bb9f862843c6b804097c124961b5567ded4f1sewardj   }
9339e14bb9f862843c6b804097c124961b5567ded4f1sewardj
9340e14bb9f862843c6b804097c124961b5567ded4f1sewardj   switch (opc2) {
93413ea49ee14d8c061bc0e7c3e90a22849de1c59d73cerion   case 0x026: { // mtfsb1 (Move to FPSCR Bit 1, PPC32 p479)
93423ea49ee14d8c061bc0e7c3e90a22849de1c59d73cerion      // Bit crbD of the FPSCR is set.
93433ea49ee14d8c061bc0e7c3e90a22849de1c59d73cerion      UChar crbD    = ifieldRegDS(theInstr);
93443ea49ee14d8c061bc0e7c3e90a22849de1c59d73cerion      UInt  b11to20 = IFIELD(theInstr, 11, 10);
93453ea49ee14d8c061bc0e7c3e90a22849de1c59d73cerion
93463ea49ee14d8c061bc0e7c3e90a22849de1c59d73cerion      if (b11to20 != 0) {
93473ea49ee14d8c061bc0e7c3e90a22849de1c59d73cerion         vex_printf("dis_fp_scr(ppc)(instr,mtfsb1)\n");
93483ea49ee14d8c061bc0e7c3e90a22849de1c59d73cerion         return False;
93493ea49ee14d8c061bc0e7c3e90a22849de1c59d73cerion      }
93503ea49ee14d8c061bc0e7c3e90a22849de1c59d73cerion      DIP("mtfsb1%s crb%d \n", flag_rC ? ".":"", crbD);
9351c6bbd470e9bd9898b84959227a406d3972d95f3bsewardj      putGST_masked( PPC_GST_FPSCR, mkU64( 1 <<( 31 - crbD ) ),
9352c6bbd470e9bd9898b84959227a406d3972d95f3bsewardj		     1ULL << ( 31 - crbD ) );
93533ea49ee14d8c061bc0e7c3e90a22849de1c59d73cerion      break;
93543ea49ee14d8c061bc0e7c3e90a22849de1c59d73cerion   }
93553ea49ee14d8c061bc0e7c3e90a22849de1c59d73cerion
9356496b88f208ea5cca7b03d41209fba7f4e1ae9c9bsewardj   case 0x040: { // mcrfs (Move to Condition Register from FPSCR, PPC32 p465)
9357496b88f208ea5cca7b03d41209fba7f4e1ae9c9bsewardj      UChar   crfD    = toUChar( IFIELD( theInstr, 23, 3 ) );
9358496b88f208ea5cca7b03d41209fba7f4e1ae9c9bsewardj      UChar   b21to22 = toUChar( IFIELD( theInstr, 21, 2 ) );
9359496b88f208ea5cca7b03d41209fba7f4e1ae9c9bsewardj      UChar   crfS    = toUChar( IFIELD( theInstr, 18, 3 ) );
9360496b88f208ea5cca7b03d41209fba7f4e1ae9c9bsewardj      UChar   b11to17 = toUChar( IFIELD( theInstr, 11, 7 ) );
9361496b88f208ea5cca7b03d41209fba7f4e1ae9c9bsewardj      IRTemp  tmp     = newTemp(Ity_I32);
9362496b88f208ea5cca7b03d41209fba7f4e1ae9c9bsewardj      IRExpr* fpscr_all;
9363496b88f208ea5cca7b03d41209fba7f4e1ae9c9bsewardj      if (b21to22 != 0 || b11to17 != 0 || flag_rC != 0) {
9364496b88f208ea5cca7b03d41209fba7f4e1ae9c9bsewardj         vex_printf("dis_fp_scr(ppc)(instr,mcrfs)\n");
9365496b88f208ea5cca7b03d41209fba7f4e1ae9c9bsewardj         return False;
9366496b88f208ea5cca7b03d41209fba7f4e1ae9c9bsewardj      }
9367496b88f208ea5cca7b03d41209fba7f4e1ae9c9bsewardj      DIP("mcrfs crf%d,crf%d\n", crfD, crfS);
9368496b88f208ea5cca7b03d41209fba7f4e1ae9c9bsewardj      vassert(crfD < 8);
9369496b88f208ea5cca7b03d41209fba7f4e1ae9c9bsewardj      vassert(crfS < 8);
9370496b88f208ea5cca7b03d41209fba7f4e1ae9c9bsewardj      fpscr_all = getGST_masked( PPC_GST_FPSCR, MASK_FPSCR_RN );
9371496b88f208ea5cca7b03d41209fba7f4e1ae9c9bsewardj      assign( tmp, binop(Iop_And32,
9372496b88f208ea5cca7b03d41209fba7f4e1ae9c9bsewardj                         binop(Iop_Shr32,fpscr_all,mkU8(4 * (7-crfS))),
9373496b88f208ea5cca7b03d41209fba7f4e1ae9c9bsewardj                        mkU32(0xF)) );
9374496b88f208ea5cca7b03d41209fba7f4e1ae9c9bsewardj      putGST_field( PPC_GST_CR, mkexpr(tmp), crfD );
9375496b88f208ea5cca7b03d41209fba7f4e1ae9c9bsewardj      break;
9376496b88f208ea5cca7b03d41209fba7f4e1ae9c9bsewardj   }
93770e2cc67b30d1bb4d0515a1e09d944143becb3881sewardj
93780e2cc67b30d1bb4d0515a1e09d944143becb3881sewardj   case 0x046: { // mtfsb0 (Move to FPSCR Bit 0, PPC32 p478)
93790e2cc67b30d1bb4d0515a1e09d944143becb3881sewardj      // Bit crbD of the FPSCR is cleared.
938076de5cf615380b23b4b5bcced6541233cd4a93a0cerion      UChar crbD    = ifieldRegDS(theInstr);
938176de5cf615380b23b4b5bcced6541233cd4a93a0cerion      UInt  b11to20 = IFIELD(theInstr, 11, 10);
93820e2cc67b30d1bb4d0515a1e09d944143becb3881sewardj
93830e2cc67b30d1bb4d0515a1e09d944143becb3881sewardj      if (b11to20 != 0) {
93845b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion         vex_printf("dis_fp_scr(ppc)(instr,mtfsb0)\n");
93850e2cc67b30d1bb4d0515a1e09d944143becb3881sewardj         return False;
93860e2cc67b30d1bb4d0515a1e09d944143becb3881sewardj      }
93875b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion      DIP("mtfsb0%s crb%d\n", flag_rC ? ".":"", crbD);
9388c6bbd470e9bd9898b84959227a406d3972d95f3bsewardj      putGST_masked( PPC_GST_FPSCR, mkU64( 0 ), 1ULL << ( 31 - crbD ) );
93890e2cc67b30d1bb4d0515a1e09d944143becb3881sewardj      break;
93900e2cc67b30d1bb4d0515a1e09d944143becb3881sewardj   }
93910e2cc67b30d1bb4d0515a1e09d944143becb3881sewardj
93920e2cc67b30d1bb4d0515a1e09d944143becb3881sewardj   case 0x086: { // mtfsfi (Move to FPSCR Field Immediate, PPC32 p481)
9393c6bbd470e9bd9898b84959227a406d3972d95f3bsewardj      UInt crfD     = IFIELD( theInstr, 23, 3 );
939476de5cf615380b23b4b5bcced6541233cd4a93a0cerion      UChar b16to22 = toUChar( IFIELD( theInstr, 16, 7 ) );
939576de5cf615380b23b4b5bcced6541233cd4a93a0cerion      UChar IMM     = toUChar( IFIELD( theInstr, 12, 4 ) );
939676de5cf615380b23b4b5bcced6541233cd4a93a0cerion      UChar b11     = toUChar( IFIELD( theInstr, 11, 1 ) );
9397c6bbd470e9bd9898b84959227a406d3972d95f3bsewardj      UChar Wbit;
93980e2cc67b30d1bb4d0515a1e09d944143becb3881sewardj
93990e2cc67b30d1bb4d0515a1e09d944143becb3881sewardj      if (b16to22 != 0 || b11 != 0) {
94005b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion         vex_printf("dis_fp_scr(ppc)(instr,mtfsfi)\n");
94010e2cc67b30d1bb4d0515a1e09d944143becb3881sewardj         return False;
94020e2cc67b30d1bb4d0515a1e09d944143becb3881sewardj      }
94035b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion      DIP("mtfsfi%s crf%d,%d\n", flag_rC ? ".":"", crfD, IMM);
9404c6bbd470e9bd9898b84959227a406d3972d95f3bsewardj      if (GX_level) {
9405c6bbd470e9bd9898b84959227a406d3972d95f3bsewardj         /* This implies that Decimal Floating Point is supported, and the
9406c6bbd470e9bd9898b84959227a406d3972d95f3bsewardj          * FPSCR must be managed as a 64-bit register.
9407c6bbd470e9bd9898b84959227a406d3972d95f3bsewardj          */
9408c6bbd470e9bd9898b84959227a406d3972d95f3bsewardj         Wbit = toUChar( IFIELD(theInstr, 16, 1) );
9409c6bbd470e9bd9898b84959227a406d3972d95f3bsewardj      } else {
9410c6bbd470e9bd9898b84959227a406d3972d95f3bsewardj         Wbit = 0;
9411c6bbd470e9bd9898b84959227a406d3972d95f3bsewardj      }
9412c6bbd470e9bd9898b84959227a406d3972d95f3bsewardj      crfD = crfD + (8 * (1 - Wbit) );
9413c6bbd470e9bd9898b84959227a406d3972d95f3bsewardj      putGST_field( PPC_GST_FPSCR, mkU32( IMM ), crfD );
94140e2cc67b30d1bb4d0515a1e09d944143becb3881sewardj      break;
94150e2cc67b30d1bb4d0515a1e09d944143becb3881sewardj   }
9416e14bb9f862843c6b804097c124961b5567ded4f1sewardj
9417e14bb9f862843c6b804097c124961b5567ded4f1sewardj   case 0x247: { // mffs (Move from FPSCR, PPC32 p468)
9418496b88f208ea5cca7b03d41209fba7f4e1ae9c9bsewardj      UChar   frD_addr  = ifieldRegDS(theInstr);
9419496b88f208ea5cca7b03d41209fba7f4e1ae9c9bsewardj      UInt    b11to20   = IFIELD(theInstr, 11, 10);
9420c6bbd470e9bd9898b84959227a406d3972d95f3bsewardj      IRExpr* fpscr_lower = getGST_masked( PPC_GST_FPSCR, MASK_FPSCR_RN );
9421c6bbd470e9bd9898b84959227a406d3972d95f3bsewardj      IRExpr* fpscr_upper = getGST_masked_upper( PPC_GST_FPSCR,
9422c6bbd470e9bd9898b84959227a406d3972d95f3bsewardj                                                 MASK_FPSCR_DRN );
9423e14bb9f862843c6b804097c124961b5567ded4f1sewardj
9424e14bb9f862843c6b804097c124961b5567ded4f1sewardj      if (b11to20 != 0) {
94255b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion         vex_printf("dis_fp_scr(ppc)(instr,mffs)\n");
9426e14bb9f862843c6b804097c124961b5567ded4f1sewardj         return False;
9427e14bb9f862843c6b804097c124961b5567ded4f1sewardj      }
94285b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion      DIP("mffs%s fr%u\n", flag_rC ? ".":"", frD_addr);
94295b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion      putFReg( frD_addr,
94305b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion          unop( Iop_ReinterpI64asF64,
9431c6bbd470e9bd9898b84959227a406d3972d95f3bsewardj                binop( Iop_32HLto64, fpscr_upper, fpscr_lower ) ) );
9432e14bb9f862843c6b804097c124961b5567ded4f1sewardj      break;
9433e14bb9f862843c6b804097c124961b5567ded4f1sewardj   }
9434e14bb9f862843c6b804097c124961b5567ded4f1sewardj
9435e14bb9f862843c6b804097c124961b5567ded4f1sewardj   case 0x2C7: { // mtfsf (Move to FPSCR Fields, PPC32 p480)
943676de5cf615380b23b4b5bcced6541233cd4a93a0cerion      UChar b25      = toUChar( IFIELD(theInstr, 25, 1) );
943776de5cf615380b23b4b5bcced6541233cd4a93a0cerion      UChar FM       = toUChar( IFIELD(theInstr, 17, 8) );
943876de5cf615380b23b4b5bcced6541233cd4a93a0cerion      UChar frB_addr = ifieldRegB(theInstr);
943976de5cf615380b23b4b5bcced6541233cd4a93a0cerion      IRTemp frB   = newTemp(Ity_F64);
9440c6bbd470e9bd9898b84959227a406d3972d95f3bsewardj      IRTemp rB_64 = newTemp( Ity_I64 );
9441c6bbd470e9bd9898b84959227a406d3972d95f3bsewardj      Int i;
9442c6bbd470e9bd9898b84959227a406d3972d95f3bsewardj      ULong mask;
9443c6bbd470e9bd9898b84959227a406d3972d95f3bsewardj      UChar Wbit;
9444c6bbd470e9bd9898b84959227a406d3972d95f3bsewardj#define BFP_MASK_SEED 0x3000000000000000ULL
9445c6bbd470e9bd9898b84959227a406d3972d95f3bsewardj#define DFP_MASK_SEED 0x7000000000000000ULL
9446c6bbd470e9bd9898b84959227a406d3972d95f3bsewardj
9447c6bbd470e9bd9898b84959227a406d3972d95f3bsewardj      if (GX_level) {
9448c6bbd470e9bd9898b84959227a406d3972d95f3bsewardj         /* This implies that Decimal Floating Point is supported, and the
9449c6bbd470e9bd9898b84959227a406d3972d95f3bsewardj          * FPSCR must be managed as a 64-bit register.
9450c6bbd470e9bd9898b84959227a406d3972d95f3bsewardj          */
9451c6bbd470e9bd9898b84959227a406d3972d95f3bsewardj         Wbit = toUChar( IFIELD(theInstr, 16, 1) );
9452c6bbd470e9bd9898b84959227a406d3972d95f3bsewardj      } else {
9453c6bbd470e9bd9898b84959227a406d3972d95f3bsewardj         Wbit = 0;
9454c6bbd470e9bd9898b84959227a406d3972d95f3bsewardj      }
9455e14bb9f862843c6b804097c124961b5567ded4f1sewardj
94567e84630580f89c1022dde97007bffbf6aef81814sewardj      if (b25 == 1) {
94577e84630580f89c1022dde97007bffbf6aef81814sewardj         /* new 64 bit move variant for power 6.  If L field (bit 25) is
94587e84630580f89c1022dde97007bffbf6aef81814sewardj          * a one do a full 64 bit move.  Note, the FPSCR is not really
94597e84630580f89c1022dde97007bffbf6aef81814sewardj          * properly modeled.  This instruciton only changes the value of
94607e84630580f89c1022dde97007bffbf6aef81814sewardj          * the rounding mode.  The HW exception bits do not get set in
94617e84630580f89c1022dde97007bffbf6aef81814sewardj          * the simulator.  1/12/09
94627e84630580f89c1022dde97007bffbf6aef81814sewardj          */
94637e84630580f89c1022dde97007bffbf6aef81814sewardj         DIP("mtfsf%s %d,fr%u (L=1)\n", flag_rC ? ".":"", FM, frB_addr);
94647e84630580f89c1022dde97007bffbf6aef81814sewardj         mask = 0xFF;
94657e84630580f89c1022dde97007bffbf6aef81814sewardj
94667e84630580f89c1022dde97007bffbf6aef81814sewardj      } else {
94677e84630580f89c1022dde97007bffbf6aef81814sewardj         DIP("mtfsf%s %d,fr%u\n", flag_rC ? ".":"", FM, frB_addr);
94687e84630580f89c1022dde97007bffbf6aef81814sewardj         // Build 32bit mask from FM:
94697e84630580f89c1022dde97007bffbf6aef81814sewardj         mask = 0;
94707e84630580f89c1022dde97007bffbf6aef81814sewardj         for (i=0; i<8; i++) {
94717e84630580f89c1022dde97007bffbf6aef81814sewardj            if ((FM & (1<<(7-i))) == 1) {
9472c6bbd470e9bd9898b84959227a406d3972d95f3bsewardj               /* FPSCR field k is set to the contents of the corresponding
9473c6bbd470e9bd9898b84959227a406d3972d95f3bsewardj                * field of register FRB, where k = i+8x(1-W).  In the Power
9474c6bbd470e9bd9898b84959227a406d3972d95f3bsewardj                * ISA, register field numbering is from left to right, so field
9475c6bbd470e9bd9898b84959227a406d3972d95f3bsewardj                * 15 is the least significant field in a 64-bit register.  To
9476c6bbd470e9bd9898b84959227a406d3972d95f3bsewardj                * generate the mask, we set all the appropriate rounding mode
9477c6bbd470e9bd9898b84959227a406d3972d95f3bsewardj                * bits in the highest order nibble (field 0) and shift right
9478c6bbd470e9bd9898b84959227a406d3972d95f3bsewardj                * 'k x nibble length'.
9479c6bbd470e9bd9898b84959227a406d3972d95f3bsewardj                */
9480c6bbd470e9bd9898b84959227a406d3972d95f3bsewardj               if (Wbit)
9481c6bbd470e9bd9898b84959227a406d3972d95f3bsewardj                  mask |= DFP_MASK_SEED >> ( 4 * ( i + 8 * ( 1 - Wbit ) ) );
9482c6bbd470e9bd9898b84959227a406d3972d95f3bsewardj               else
9483c6bbd470e9bd9898b84959227a406d3972d95f3bsewardj                  mask |= BFP_MASK_SEED >> ( 4 * ( i + 8 * ( 1 - Wbit ) ) );
94847e84630580f89c1022dde97007bffbf6aef81814sewardj            }
94857e84630580f89c1022dde97007bffbf6aef81814sewardj         }
94867e84630580f89c1022dde97007bffbf6aef81814sewardj      }
9487e14bb9f862843c6b804097c124961b5567ded4f1sewardj      assign( frB, getFReg(frB_addr));
9488c6bbd470e9bd9898b84959227a406d3972d95f3bsewardj      assign( rB_64, unop( Iop_ReinterpF64asI64, mkexpr( frB ) ) );
9489c6bbd470e9bd9898b84959227a406d3972d95f3bsewardj      putGST_masked( PPC_GST_FPSCR, mkexpr( rB_64 ), mask );
9490e14bb9f862843c6b804097c124961b5567ded4f1sewardj      break;
9491e14bb9f862843c6b804097c124961b5567ded4f1sewardj   }
9492e14bb9f862843c6b804097c124961b5567ded4f1sewardj
9493e14bb9f862843c6b804097c124961b5567ded4f1sewardj   default:
94945b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion      vex_printf("dis_fp_scr(ppc)(opc2)\n");
9495e14bb9f862843c6b804097c124961b5567ded4f1sewardj      return False;
9496e14bb9f862843c6b804097c124961b5567ded4f1sewardj   }
9497e14bb9f862843c6b804097c124961b5567ded4f1sewardj   return True;
9498e14bb9f862843c6b804097c124961b5567ded4f1sewardj}
9499e14bb9f862843c6b804097c124961b5567ded4f1sewardj
9500c6bbd470e9bd9898b84959227a406d3972d95f3bsewardj/*------------------------------------------------------------*/
95015eff1c502e995d1f9668cc9def72d5db59f21b13sewardj/*--- Decimal Floating Point (DFP)  Helper functions       ---*/
95025eff1c502e995d1f9668cc9def72d5db59f21b13sewardj/*------------------------------------------------------------*/
95035eff1c502e995d1f9668cc9def72d5db59f21b13sewardj#define DFP_LONG  1
95045eff1c502e995d1f9668cc9def72d5db59f21b13sewardj#define DFP_EXTND 2
95054c96e61dd85c172b999d6afc88ce6640aeba9962sewardj#define DFP_LONG_BIAS   398
95065eff1c502e995d1f9668cc9def72d5db59f21b13sewardj#define DFP_LONG_ENCODED_FIELD_MASK  0x1F00
95074c96e61dd85c172b999d6afc88ce6640aeba9962sewardj#define DFP_EXTND_BIAS  6176
95085eff1c502e995d1f9668cc9def72d5db59f21b13sewardj#define DFP_EXTND_ENCODED_FIELD_MASK 0x1F000
95095eff1c502e995d1f9668cc9def72d5db59f21b13sewardj#define DFP_LONG_EXP_MSK   0XFF
95105eff1c502e995d1f9668cc9def72d5db59f21b13sewardj#define DFP_EXTND_EXP_MSK  0XFFF
95115eff1c502e995d1f9668cc9def72d5db59f21b13sewardj
95125eff1c502e995d1f9668cc9def72d5db59f21b13sewardj#define DFP_G_FIELD_LONG_MASK     0x7FFC0000  // upper 32-bits only
95135eff1c502e995d1f9668cc9def72d5db59f21b13sewardj#define DFP_LONG_GFIELD_RT_SHIFT  (63 - 13 - 32) // adj for upper 32-bits
95145eff1c502e995d1f9668cc9def72d5db59f21b13sewardj#define DFP_G_FIELD_EXTND_MASK    0x7FFFC000  // upper 32-bits only
95155eff1c502e995d1f9668cc9def72d5db59f21b13sewardj#define DFP_EXTND_GFIELD_RT_SHIFT (63 - 17 - 32) //adj for upper 32 bits
95165eff1c502e995d1f9668cc9def72d5db59f21b13sewardj#define DFP_T_FIELD_LONG_MASK     0x3FFFF  // mask for upper 32-bits
95175eff1c502e995d1f9668cc9def72d5db59f21b13sewardj#define DFP_T_FIELD_EXTND_MASK    0x03FFFF // mask for upper 32-bits
95185eff1c502e995d1f9668cc9def72d5db59f21b13sewardj#define DFP_LONG_EXP_MAX          369      // biased max
95195eff1c502e995d1f9668cc9def72d5db59f21b13sewardj#define DFP_LONG_EXP_MIN          0        // biased min
95205eff1c502e995d1f9668cc9def72d5db59f21b13sewardj#define DFP_EXTND_EXP_MAX         6111     // biased max
95215eff1c502e995d1f9668cc9def72d5db59f21b13sewardj#define DFP_EXTND_EXP_MIN         0        // biased min
95224c96e61dd85c172b999d6afc88ce6640aeba9962sewardj#define DFP_LONG_MAX_SIG_DIGITS   16
95234c96e61dd85c172b999d6afc88ce6640aeba9962sewardj#define DFP_EXTND_MAX_SIG_DIGITS  34
95244c96e61dd85c172b999d6afc88ce6640aeba9962sewardj#define MAX_DIGITS_IN_STRING      8
95254c96e61dd85c172b999d6afc88ce6640aeba9962sewardj
95265eff1c502e995d1f9668cc9def72d5db59f21b13sewardj
95275eff1c502e995d1f9668cc9def72d5db59f21b13sewardj#define  AND(x, y) binop( Iop_And32, x, y )
95285eff1c502e995d1f9668cc9def72d5db59f21b13sewardj#define AND4(w, x, y, z) AND( AND( w, x ), AND( y, z ) )
95294c96e61dd85c172b999d6afc88ce6640aeba9962sewardj#define   OR(x, y) binop( Iop_Or32,  x, y )
95305eff1c502e995d1f9668cc9def72d5db59f21b13sewardj#define  OR3(x, y, z)    OR( x, OR( y, z ) )
95315eff1c502e995d1f9668cc9def72d5db59f21b13sewardj#define  OR4(w, x, y, z) OR( OR( w, x ), OR( y, z ) )
95324c96e61dd85c172b999d6afc88ce6640aeba9962sewardj#define  NOT(x) unop( Iop_1Uto32, unop( Iop_Not1, unop( Iop_32to1,  mkexpr( x ) ) ) )
95334c96e61dd85c172b999d6afc88ce6640aeba9962sewardj
95345eff1c502e995d1f9668cc9def72d5db59f21b13sewardj#define  SHL(value, by) binop( Iop_Shl32, value, mkU8( by ) )
95354c96e61dd85c172b999d6afc88ce6640aeba9962sewardj#define  SHR(value, by) binop( Iop_Shr32, value, mkU8( by ) )
95364c96e61dd85c172b999d6afc88ce6640aeba9962sewardj
9537cb06d5e50876ee734e09a5fa0d5f300014e13852sewardj#define BITS5(_b4,_b3,_b2,_b1,_b0) \
9538cb06d5e50876ee734e09a5fa0d5f300014e13852sewardj   (((_b4) << 4) | ((_b3) << 3) | ((_b2) << 2) | \
9539cb06d5e50876ee734e09a5fa0d5f300014e13852sewardj    ((_b1) << 1) | ((_b0) << 0))
95405eff1c502e995d1f9668cc9def72d5db59f21b13sewardj
95414c96e61dd85c172b999d6afc88ce6640aeba9962sewardjstatic IRExpr * Gfield_encoding( IRExpr * lmexp, IRExpr * lmd32 )
95425eff1c502e995d1f9668cc9def72d5db59f21b13sewardj{
95434c96e61dd85c172b999d6afc88ce6640aeba9962sewardj   IRTemp lmd_07_mask   = newTemp( Ity_I32 );
95444c96e61dd85c172b999d6afc88ce6640aeba9962sewardj   IRTemp lmd_8_mask    = newTemp( Ity_I32 );
95454c96e61dd85c172b999d6afc88ce6640aeba9962sewardj   IRTemp lmd_9_mask    = newTemp( Ity_I32 );
95464c96e61dd85c172b999d6afc88ce6640aeba9962sewardj   IRTemp lmexp_00_mask = newTemp( Ity_I32 );
95474c96e61dd85c172b999d6afc88ce6640aeba9962sewardj   IRTemp lmexp_01_mask = newTemp( Ity_I32 );
95484c96e61dd85c172b999d6afc88ce6640aeba9962sewardj   IRTemp lmexp_10_mask = newTemp( Ity_I32 );
95494c96e61dd85c172b999d6afc88ce6640aeba9962sewardj   IRTemp lmd_07_val    = newTemp( Ity_I32 );
95504c96e61dd85c172b999d6afc88ce6640aeba9962sewardj   IRTemp lmd_8_val     = newTemp( Ity_I32 );
95514c96e61dd85c172b999d6afc88ce6640aeba9962sewardj   IRTemp lmd_9_val     = newTemp( Ity_I32 );
95524c96e61dd85c172b999d6afc88ce6640aeba9962sewardj
95534c96e61dd85c172b999d6afc88ce6640aeba9962sewardj   /* The encodig is as follows:
95544c96e61dd85c172b999d6afc88ce6640aeba9962sewardj    * lmd - left most digit
95554c96e61dd85c172b999d6afc88ce6640aeba9962sewardj    * lme - left most 2-bits of the exponent
95564c96e61dd85c172b999d6afc88ce6640aeba9962sewardj    *
95574c96e61dd85c172b999d6afc88ce6640aeba9962sewardj    *    lmd
95584c96e61dd85c172b999d6afc88ce6640aeba9962sewardj    *   0 - 7    (lmexp << 3) | lmd
95594c96e61dd85c172b999d6afc88ce6640aeba9962sewardj    *     8      0b11000 (24 decimal) if lme=0b00;
95604c96e61dd85c172b999d6afc88ce6640aeba9962sewardj    *            0b11010 (26 decimal) if lme=0b01;
95614c96e61dd85c172b999d6afc88ce6640aeba9962sewardj    *            0b11100 (28 decimal) if lme=0b10;
95624c96e61dd85c172b999d6afc88ce6640aeba9962sewardj    *     9      0b11001 (25 decimal) if lme=0b00;
95634c96e61dd85c172b999d6afc88ce6640aeba9962sewardj    *            0b11011 (27 decimal) if lme=0b01;
95644c96e61dd85c172b999d6afc88ce6640aeba9962sewardj    *            0b11101 (29 decimal) if lme=0b10;
95654c96e61dd85c172b999d6afc88ce6640aeba9962sewardj    */
95664c96e61dd85c172b999d6afc88ce6640aeba9962sewardj
95674c96e61dd85c172b999d6afc88ce6640aeba9962sewardj   /* Generate the masks for each condition */
95684c96e61dd85c172b999d6afc88ce6640aeba9962sewardj   assign( lmd_07_mask,
95694c96e61dd85c172b999d6afc88ce6640aeba9962sewardj           unop( Iop_1Sto32, binop( Iop_CmpLE32U, lmd32, mkU32( 7 ) ) ) );
95704c96e61dd85c172b999d6afc88ce6640aeba9962sewardj   assign( lmd_8_mask,
95714c96e61dd85c172b999d6afc88ce6640aeba9962sewardj           unop( Iop_1Sto32, binop( Iop_CmpEQ32, lmd32, mkU32( 8 ) ) ) );
95724c96e61dd85c172b999d6afc88ce6640aeba9962sewardj   assign( lmd_9_mask,
95734c96e61dd85c172b999d6afc88ce6640aeba9962sewardj           unop( Iop_1Sto32, binop( Iop_CmpEQ32, lmd32, mkU32( 9 ) ) ) );
95744c96e61dd85c172b999d6afc88ce6640aeba9962sewardj   assign( lmexp_00_mask,
95754c96e61dd85c172b999d6afc88ce6640aeba9962sewardj           unop( Iop_1Sto32, binop( Iop_CmpEQ32, lmexp, mkU32( 0 ) ) ) );
95764c96e61dd85c172b999d6afc88ce6640aeba9962sewardj   assign( lmexp_01_mask,
95774c96e61dd85c172b999d6afc88ce6640aeba9962sewardj           unop( Iop_1Sto32, binop( Iop_CmpEQ32, lmexp, mkU32( 1 ) ) ) );
95784c96e61dd85c172b999d6afc88ce6640aeba9962sewardj   assign( lmexp_10_mask,
95794c96e61dd85c172b999d6afc88ce6640aeba9962sewardj           unop( Iop_1Sto32, binop( Iop_CmpEQ32, lmexp, mkU32( 2 ) ) ) );
95805eff1c502e995d1f9668cc9def72d5db59f21b13sewardj
95814c96e61dd85c172b999d6afc88ce6640aeba9962sewardj   /* Generate the values for each LMD condition, assuming the condition
95824c96e61dd85c172b999d6afc88ce6640aeba9962sewardj    * is TRUE.
95834c96e61dd85c172b999d6afc88ce6640aeba9962sewardj    */
95844c96e61dd85c172b999d6afc88ce6640aeba9962sewardj   assign( lmd_07_val,
95854c96e61dd85c172b999d6afc88ce6640aeba9962sewardj           binop( Iop_Or32, binop( Iop_Shl32, lmexp, mkU8( 3 ) ), lmd32 ) );
95864c96e61dd85c172b999d6afc88ce6640aeba9962sewardj   assign( lmd_8_val,
95874c96e61dd85c172b999d6afc88ce6640aeba9962sewardj           binop( Iop_Or32,
95884c96e61dd85c172b999d6afc88ce6640aeba9962sewardj                  binop( Iop_Or32,
95894c96e61dd85c172b999d6afc88ce6640aeba9962sewardj                         binop( Iop_And32,
95904c96e61dd85c172b999d6afc88ce6640aeba9962sewardj                                mkexpr( lmexp_00_mask ),
95914c96e61dd85c172b999d6afc88ce6640aeba9962sewardj                                mkU32( 24 ) ),
95924c96e61dd85c172b999d6afc88ce6640aeba9962sewardj                         binop( Iop_And32,
95934c96e61dd85c172b999d6afc88ce6640aeba9962sewardj                                mkexpr( lmexp_01_mask ),
95944c96e61dd85c172b999d6afc88ce6640aeba9962sewardj                                mkU32( 26 ) ) ),
95954c96e61dd85c172b999d6afc88ce6640aeba9962sewardj                  binop( Iop_And32, mkexpr( lmexp_10_mask ), mkU32( 28 ) ) ) );
95964c96e61dd85c172b999d6afc88ce6640aeba9962sewardj   assign( lmd_9_val,
95974c96e61dd85c172b999d6afc88ce6640aeba9962sewardj           binop( Iop_Or32,
95984c96e61dd85c172b999d6afc88ce6640aeba9962sewardj                  binop( Iop_Or32,
95994c96e61dd85c172b999d6afc88ce6640aeba9962sewardj                         binop( Iop_And32,
96004c96e61dd85c172b999d6afc88ce6640aeba9962sewardj                                mkexpr( lmexp_00_mask ),
96014c96e61dd85c172b999d6afc88ce6640aeba9962sewardj                                mkU32( 25 ) ),
96024c96e61dd85c172b999d6afc88ce6640aeba9962sewardj                         binop( Iop_And32,
96034c96e61dd85c172b999d6afc88ce6640aeba9962sewardj                                mkexpr( lmexp_01_mask ),
96044c96e61dd85c172b999d6afc88ce6640aeba9962sewardj                                mkU32( 27 ) ) ),
96054c96e61dd85c172b999d6afc88ce6640aeba9962sewardj                  binop( Iop_And32, mkexpr( lmexp_10_mask ), mkU32( 29 ) ) ) );
96064c96e61dd85c172b999d6afc88ce6640aeba9962sewardj
96074c96e61dd85c172b999d6afc88ce6640aeba9962sewardj   /* generate the result from the possible LMD values */
96084c96e61dd85c172b999d6afc88ce6640aeba9962sewardj   return binop( Iop_Or32,
96094c96e61dd85c172b999d6afc88ce6640aeba9962sewardj                 binop( Iop_Or32,
96104c96e61dd85c172b999d6afc88ce6640aeba9962sewardj                        binop( Iop_And32,
96114c96e61dd85c172b999d6afc88ce6640aeba9962sewardj                               mkexpr( lmd_07_mask ),
96124c96e61dd85c172b999d6afc88ce6640aeba9962sewardj                               mkexpr( lmd_07_val ) ),
96134c96e61dd85c172b999d6afc88ce6640aeba9962sewardj                        binop( Iop_And32,
96144c96e61dd85c172b999d6afc88ce6640aeba9962sewardj                               mkexpr( lmd_8_mask ),
96154c96e61dd85c172b999d6afc88ce6640aeba9962sewardj                               mkexpr( lmd_8_val ) ) ),
96164c96e61dd85c172b999d6afc88ce6640aeba9962sewardj                 binop( Iop_And32, mkexpr( lmd_9_mask ), mkexpr( lmd_9_val ) ) );
96174c96e61dd85c172b999d6afc88ce6640aeba9962sewardj}
96184c96e61dd85c172b999d6afc88ce6640aeba9962sewardj
96194c96e61dd85c172b999d6afc88ce6640aeba9962sewardjstatic void Get_lmd( IRTemp * lmd, IRExpr * gfield_0_4 )
96204c96e61dd85c172b999d6afc88ce6640aeba9962sewardj{
96215eff1c502e995d1f9668cc9def72d5db59f21b13sewardj   /* Extract the exponent and the left most digit of the mantissa
96225eff1c502e995d1f9668cc9def72d5db59f21b13sewardj    * from the G field bits [0:4].
96235eff1c502e995d1f9668cc9def72d5db59f21b13sewardj    */
96245eff1c502e995d1f9668cc9def72d5db59f21b13sewardj   IRTemp lmd_07_mask   = newTemp( Ity_I32 );
96255eff1c502e995d1f9668cc9def72d5db59f21b13sewardj   IRTemp lmd_8_00_mask = newTemp( Ity_I32 );
96265eff1c502e995d1f9668cc9def72d5db59f21b13sewardj   IRTemp lmd_8_01_mask = newTemp( Ity_I32 );
96275eff1c502e995d1f9668cc9def72d5db59f21b13sewardj   IRTemp lmd_8_10_mask = newTemp( Ity_I32 );
96285eff1c502e995d1f9668cc9def72d5db59f21b13sewardj   IRTemp lmd_9_00_mask = newTemp( Ity_I32 );
96295eff1c502e995d1f9668cc9def72d5db59f21b13sewardj   IRTemp lmd_9_01_mask = newTemp( Ity_I32 );
96305eff1c502e995d1f9668cc9def72d5db59f21b13sewardj   IRTemp lmd_9_10_mask = newTemp( Ity_I32 );
96315eff1c502e995d1f9668cc9def72d5db59f21b13sewardj
96325eff1c502e995d1f9668cc9def72d5db59f21b13sewardj   IRTemp lmd_07_val = newTemp( Ity_I32 );
96335eff1c502e995d1f9668cc9def72d5db59f21b13sewardj   IRTemp lmd_8_val  = newTemp( Ity_I32 );
96345eff1c502e995d1f9668cc9def72d5db59f21b13sewardj   IRTemp lmd_9_val  = newTemp( Ity_I32 );
96355eff1c502e995d1f9668cc9def72d5db59f21b13sewardj
96365eff1c502e995d1f9668cc9def72d5db59f21b13sewardj   /* The left most digit (LMD) encoding is as follows:
96375eff1c502e995d1f9668cc9def72d5db59f21b13sewardj    *    lmd
96385eff1c502e995d1f9668cc9def72d5db59f21b13sewardj    *   0 - 7    (lmexp << 3) | lmd
96395eff1c502e995d1f9668cc9def72d5db59f21b13sewardj    *     8      0b11000 (24 decimal) if lme=0b00;
96405eff1c502e995d1f9668cc9def72d5db59f21b13sewardj    *            0b11010 (26 decimal) if lme=0b01;
96415eff1c502e995d1f9668cc9def72d5db59f21b13sewardj    *            0b11100 (28 decimal) if lme=0b10
96425eff1c502e995d1f9668cc9def72d5db59f21b13sewardj    *     9      0b11001 (25 decimal) if lme=0b00;
96435eff1c502e995d1f9668cc9def72d5db59f21b13sewardj    *            0b11011 (27 decimal) if lme=0b01;
96445eff1c502e995d1f9668cc9def72d5db59f21b13sewardj    *            0b11101 (29 decimal) if lme=0b10;
96455eff1c502e995d1f9668cc9def72d5db59f21b13sewardj    */
96465eff1c502e995d1f9668cc9def72d5db59f21b13sewardj
96475eff1c502e995d1f9668cc9def72d5db59f21b13sewardj   /* Generate the masks for each condition of LMD and exponent bits */
9648cb06d5e50876ee734e09a5fa0d5f300014e13852sewardj   assign( lmd_07_mask,
9649cb06d5e50876ee734e09a5fa0d5f300014e13852sewardj           unop( Iop_1Sto32, binop( Iop_CmpLE32U,
9650cb06d5e50876ee734e09a5fa0d5f300014e13852sewardj                                    gfield_0_4,
9651cb06d5e50876ee734e09a5fa0d5f300014e13852sewardj                                    mkU32( BITS5(1,0,1,1,1) ) ) ) );
9652cb06d5e50876ee734e09a5fa0d5f300014e13852sewardj   assign( lmd_8_00_mask,
9653cb06d5e50876ee734e09a5fa0d5f300014e13852sewardj           unop( Iop_1Sto32, binop( Iop_CmpEQ32,
9654cb06d5e50876ee734e09a5fa0d5f300014e13852sewardj                                    gfield_0_4,
9655cb06d5e50876ee734e09a5fa0d5f300014e13852sewardj                                    mkU32( BITS5(1,1,0,0,0) ) ) ) );
9656cb06d5e50876ee734e09a5fa0d5f300014e13852sewardj   assign( lmd_8_01_mask,
9657cb06d5e50876ee734e09a5fa0d5f300014e13852sewardj           unop( Iop_1Sto32, binop( Iop_CmpEQ32,
9658cb06d5e50876ee734e09a5fa0d5f300014e13852sewardj                                    gfield_0_4,
9659cb06d5e50876ee734e09a5fa0d5f300014e13852sewardj                                    mkU32( BITS5(1,1,0,1,0) ) ) ) );
9660cb06d5e50876ee734e09a5fa0d5f300014e13852sewardj   assign( lmd_8_10_mask,
9661cb06d5e50876ee734e09a5fa0d5f300014e13852sewardj           unop( Iop_1Sto32, binop( Iop_CmpEQ32,
9662cb06d5e50876ee734e09a5fa0d5f300014e13852sewardj                                    gfield_0_4,
9663cb06d5e50876ee734e09a5fa0d5f300014e13852sewardj                                    mkU32( BITS5(1,1,1,0,0) ) ) ) );
9664cb06d5e50876ee734e09a5fa0d5f300014e13852sewardj   assign( lmd_9_00_mask,
9665cb06d5e50876ee734e09a5fa0d5f300014e13852sewardj           unop( Iop_1Sto32, binop( Iop_CmpEQ32,
9666cb06d5e50876ee734e09a5fa0d5f300014e13852sewardj                                    gfield_0_4,
9667cb06d5e50876ee734e09a5fa0d5f300014e13852sewardj                                    mkU32( BITS5(1,1,0,0,1) ) ) ) );
9668cb06d5e50876ee734e09a5fa0d5f300014e13852sewardj   assign( lmd_9_01_mask,
9669cb06d5e50876ee734e09a5fa0d5f300014e13852sewardj           unop( Iop_1Sto32, binop( Iop_CmpEQ32,
9670cb06d5e50876ee734e09a5fa0d5f300014e13852sewardj                                    gfield_0_4,
9671cb06d5e50876ee734e09a5fa0d5f300014e13852sewardj                                    mkU32( BITS5(1,1,0,1,1) ) ) ) );
9672cb06d5e50876ee734e09a5fa0d5f300014e13852sewardj   assign( lmd_9_10_mask,
9673cb06d5e50876ee734e09a5fa0d5f300014e13852sewardj           unop( Iop_1Sto32, binop( Iop_CmpEQ32,
9674cb06d5e50876ee734e09a5fa0d5f300014e13852sewardj                                    gfield_0_4,
9675cb06d5e50876ee734e09a5fa0d5f300014e13852sewardj                                    mkU32( BITS5(1,1,1,0,1) ) ) ) );
96765eff1c502e995d1f9668cc9def72d5db59f21b13sewardj
96775eff1c502e995d1f9668cc9def72d5db59f21b13sewardj   /* Generate the values for each LMD condition, assuming the condition
96785eff1c502e995d1f9668cc9def72d5db59f21b13sewardj    * is TRUE.
96795eff1c502e995d1f9668cc9def72d5db59f21b13sewardj    */
96805eff1c502e995d1f9668cc9def72d5db59f21b13sewardj   assign( lmd_07_val, binop( Iop_And32, gfield_0_4, mkU32( 0x7 ) ) );
96815eff1c502e995d1f9668cc9def72d5db59f21b13sewardj   assign( lmd_8_val, mkU32( 0x8 ) );
96825eff1c502e995d1f9668cc9def72d5db59f21b13sewardj   assign( lmd_9_val, mkU32( 0x9 ) );
96835eff1c502e995d1f9668cc9def72d5db59f21b13sewardj
96845eff1c502e995d1f9668cc9def72d5db59f21b13sewardj   assign( *lmd,
96855eff1c502e995d1f9668cc9def72d5db59f21b13sewardj           OR( OR3 ( AND( mkexpr( lmd_07_mask ), mkexpr( lmd_07_val ) ),
96865eff1c502e995d1f9668cc9def72d5db59f21b13sewardj                     AND( mkexpr( lmd_8_00_mask ), mkexpr( lmd_8_val ) ),
96875eff1c502e995d1f9668cc9def72d5db59f21b13sewardj                     AND( mkexpr( lmd_8_01_mask ), mkexpr( lmd_8_val ) )),
96885eff1c502e995d1f9668cc9def72d5db59f21b13sewardj                     OR4( AND( mkexpr( lmd_8_10_mask ), mkexpr( lmd_8_val ) ),
96895eff1c502e995d1f9668cc9def72d5db59f21b13sewardj                          AND( mkexpr( lmd_9_00_mask ), mkexpr( lmd_9_val ) ),
96905eff1c502e995d1f9668cc9def72d5db59f21b13sewardj                          AND( mkexpr( lmd_9_01_mask ), mkexpr( lmd_9_val ) ),
96915eff1c502e995d1f9668cc9def72d5db59f21b13sewardj                          AND( mkexpr( lmd_9_10_mask ), mkexpr( lmd_9_val ) )
96925eff1c502e995d1f9668cc9def72d5db59f21b13sewardj                     ) ) );
96935eff1c502e995d1f9668cc9def72d5db59f21b13sewardj}
96945eff1c502e995d1f9668cc9def72d5db59f21b13sewardj
96954c96e61dd85c172b999d6afc88ce6640aeba9962sewardj#define DIGIT1_SHR 4    // shift digit 1 to bottom 4 bits
96964c96e61dd85c172b999d6afc88ce6640aeba9962sewardj#define DIGIT2_SHR 8    // shift digit 2 to bottom 4 bits
96974c96e61dd85c172b999d6afc88ce6640aeba9962sewardj#define DIGIT3_SHR 12
96984c96e61dd85c172b999d6afc88ce6640aeba9962sewardj#define DIGIT4_SHR 16
96994c96e61dd85c172b999d6afc88ce6640aeba9962sewardj#define DIGIT5_SHR 20
97004c96e61dd85c172b999d6afc88ce6640aeba9962sewardj#define DIGIT6_SHR 24
97014c96e61dd85c172b999d6afc88ce6640aeba9962sewardj#define DIGIT7_SHR 28
97024c96e61dd85c172b999d6afc88ce6640aeba9962sewardj
97034c96e61dd85c172b999d6afc88ce6640aeba9962sewardjstatic IRExpr * bcd_digit_inval( IRExpr * bcd_u, IRExpr * bcd_l )
97044c96e61dd85c172b999d6afc88ce6640aeba9962sewardj{
97054c96e61dd85c172b999d6afc88ce6640aeba9962sewardj   /* 60-bit BCD string stored in two 32-bit values.  Check that each,
97064c96e61dd85c172b999d6afc88ce6640aeba9962sewardj    * digit is a valid BCD number, i.e. less then 9.
97074c96e61dd85c172b999d6afc88ce6640aeba9962sewardj    */
97084c96e61dd85c172b999d6afc88ce6640aeba9962sewardj   IRTemp valid = newTemp( Ity_I32 );
97094c96e61dd85c172b999d6afc88ce6640aeba9962sewardj
97104c96e61dd85c172b999d6afc88ce6640aeba9962sewardj   assign( valid,
97114c96e61dd85c172b999d6afc88ce6640aeba9962sewardj           AND4( AND4 ( unop( Iop_1Sto32,
97124c96e61dd85c172b999d6afc88ce6640aeba9962sewardj                              binop( Iop_CmpLE32U,
97134c96e61dd85c172b999d6afc88ce6640aeba9962sewardj                                     binop( Iop_And32,
97144c96e61dd85c172b999d6afc88ce6640aeba9962sewardj                                            bcd_l,
97154c96e61dd85c172b999d6afc88ce6640aeba9962sewardj                                            mkU32 ( 0xF ) ),
97164c96e61dd85c172b999d6afc88ce6640aeba9962sewardj                                      mkU32( 0x9 ) ) ),
97174c96e61dd85c172b999d6afc88ce6640aeba9962sewardj                        unop( Iop_1Sto32,
97184c96e61dd85c172b999d6afc88ce6640aeba9962sewardj                              binop( Iop_CmpLE32U,
97194c96e61dd85c172b999d6afc88ce6640aeba9962sewardj                                     binop( Iop_And32,
97204c96e61dd85c172b999d6afc88ce6640aeba9962sewardj                                            binop( Iop_Shr32,
97214c96e61dd85c172b999d6afc88ce6640aeba9962sewardj                                                   bcd_l,
97224c96e61dd85c172b999d6afc88ce6640aeba9962sewardj                                                   mkU8 ( DIGIT1_SHR ) ),
97234c96e61dd85c172b999d6afc88ce6640aeba9962sewardj                                             mkU32 ( 0xF ) ),
97244c96e61dd85c172b999d6afc88ce6640aeba9962sewardj                                      mkU32( 0x9 ) ) ),
97254c96e61dd85c172b999d6afc88ce6640aeba9962sewardj                        unop( Iop_1Sto32,
97264c96e61dd85c172b999d6afc88ce6640aeba9962sewardj                              binop( Iop_CmpLE32U,
97274c96e61dd85c172b999d6afc88ce6640aeba9962sewardj                                     binop( Iop_And32,
97284c96e61dd85c172b999d6afc88ce6640aeba9962sewardj                                            binop( Iop_Shr32,
97294c96e61dd85c172b999d6afc88ce6640aeba9962sewardj                                                   bcd_l,
97304c96e61dd85c172b999d6afc88ce6640aeba9962sewardj                                                   mkU8 ( DIGIT2_SHR ) ),
97314c96e61dd85c172b999d6afc88ce6640aeba9962sewardj                                            mkU32 ( 0xF ) ),
97324c96e61dd85c172b999d6afc88ce6640aeba9962sewardj                                      mkU32( 0x9 ) ) ),
97334c96e61dd85c172b999d6afc88ce6640aeba9962sewardj                        unop( Iop_1Sto32,
97344c96e61dd85c172b999d6afc88ce6640aeba9962sewardj                              binop( Iop_CmpLE32U,
97354c96e61dd85c172b999d6afc88ce6640aeba9962sewardj                                     binop( Iop_And32,
97364c96e61dd85c172b999d6afc88ce6640aeba9962sewardj                                            binop( Iop_Shr32,
97374c96e61dd85c172b999d6afc88ce6640aeba9962sewardj                                                   bcd_l,
97384c96e61dd85c172b999d6afc88ce6640aeba9962sewardj                                                   mkU8 ( DIGIT3_SHR ) ),
97394c96e61dd85c172b999d6afc88ce6640aeba9962sewardj                                             mkU32 ( 0xF ) ),
97404c96e61dd85c172b999d6afc88ce6640aeba9962sewardj                                      mkU32( 0x9 ) ) ) ),
97414c96e61dd85c172b999d6afc88ce6640aeba9962sewardj                 AND4 ( unop( Iop_1Sto32,
97424c96e61dd85c172b999d6afc88ce6640aeba9962sewardj                              binop( Iop_CmpLE32U,
97434c96e61dd85c172b999d6afc88ce6640aeba9962sewardj                                     binop( Iop_And32,
97444c96e61dd85c172b999d6afc88ce6640aeba9962sewardj                                            binop( Iop_Shr32,
97454c96e61dd85c172b999d6afc88ce6640aeba9962sewardj                                                   bcd_l,
97464c96e61dd85c172b999d6afc88ce6640aeba9962sewardj                                                   mkU8 ( DIGIT4_SHR ) ),
97474c96e61dd85c172b999d6afc88ce6640aeba9962sewardj                                            mkU32 ( 0xF ) ),
97484c96e61dd85c172b999d6afc88ce6640aeba9962sewardj                                     mkU32( 0x9 ) ) ),
97494c96e61dd85c172b999d6afc88ce6640aeba9962sewardj                        unop( Iop_1Sto32,
97504c96e61dd85c172b999d6afc88ce6640aeba9962sewardj                              binop( Iop_CmpLE32U,
97514c96e61dd85c172b999d6afc88ce6640aeba9962sewardj                                     binop( Iop_And32,
97524c96e61dd85c172b999d6afc88ce6640aeba9962sewardj                                            binop( Iop_Shr32,
97534c96e61dd85c172b999d6afc88ce6640aeba9962sewardj                                                   bcd_l,
97544c96e61dd85c172b999d6afc88ce6640aeba9962sewardj                                                   mkU8 ( DIGIT5_SHR ) ),
97554c96e61dd85c172b999d6afc88ce6640aeba9962sewardj                                            mkU32 ( 0xF ) ),
97564c96e61dd85c172b999d6afc88ce6640aeba9962sewardj                                     mkU32( 0x9 ) ) ),
97574c96e61dd85c172b999d6afc88ce6640aeba9962sewardj                        unop( Iop_1Sto32,
97584c96e61dd85c172b999d6afc88ce6640aeba9962sewardj                              binop( Iop_CmpLE32U,
97594c96e61dd85c172b999d6afc88ce6640aeba9962sewardj                                     binop( Iop_And32,
97604c96e61dd85c172b999d6afc88ce6640aeba9962sewardj                                            binop( Iop_Shr32,
97614c96e61dd85c172b999d6afc88ce6640aeba9962sewardj                                                   bcd_l,
97624c96e61dd85c172b999d6afc88ce6640aeba9962sewardj                                                   mkU8 ( DIGIT6_SHR ) ),
97634c96e61dd85c172b999d6afc88ce6640aeba9962sewardj                                            mkU32 ( 0xF ) ),
97644c96e61dd85c172b999d6afc88ce6640aeba9962sewardj                                     mkU32( 0x9 ) ) ),
97654c96e61dd85c172b999d6afc88ce6640aeba9962sewardj                        unop( Iop_1Sto32,
97664c96e61dd85c172b999d6afc88ce6640aeba9962sewardj                              binop( Iop_CmpLE32U,
97674c96e61dd85c172b999d6afc88ce6640aeba9962sewardj                                     binop( Iop_And32,
97684c96e61dd85c172b999d6afc88ce6640aeba9962sewardj                                            binop( Iop_Shr32,
97694c96e61dd85c172b999d6afc88ce6640aeba9962sewardj                                                   bcd_l,
97704c96e61dd85c172b999d6afc88ce6640aeba9962sewardj                                                   mkU8 ( DIGIT7_SHR ) ),
97714c96e61dd85c172b999d6afc88ce6640aeba9962sewardj                                            mkU32 ( 0xF ) ),
97724c96e61dd85c172b999d6afc88ce6640aeba9962sewardj                                     mkU32( 0x9 ) ) ) ),
97734c96e61dd85c172b999d6afc88ce6640aeba9962sewardj                 AND4( unop( Iop_1Sto32,
97744c96e61dd85c172b999d6afc88ce6640aeba9962sewardj                             binop( Iop_CmpLE32U,
97754c96e61dd85c172b999d6afc88ce6640aeba9962sewardj                                    binop( Iop_And32,
97764c96e61dd85c172b999d6afc88ce6640aeba9962sewardj                                           bcd_u,
97774c96e61dd85c172b999d6afc88ce6640aeba9962sewardj                                           mkU32 ( 0xF ) ),
97784c96e61dd85c172b999d6afc88ce6640aeba9962sewardj                                    mkU32( 0x9 ) ) ),
97794c96e61dd85c172b999d6afc88ce6640aeba9962sewardj                       unop( Iop_1Sto32,
97804c96e61dd85c172b999d6afc88ce6640aeba9962sewardj                             binop( Iop_CmpLE32U,
97814c96e61dd85c172b999d6afc88ce6640aeba9962sewardj                                    binop( Iop_And32,
97824c96e61dd85c172b999d6afc88ce6640aeba9962sewardj                                           binop( Iop_Shr32,
97834c96e61dd85c172b999d6afc88ce6640aeba9962sewardj                                                  bcd_u,
97844c96e61dd85c172b999d6afc88ce6640aeba9962sewardj                                                  mkU8 ( DIGIT1_SHR ) ),
97854c96e61dd85c172b999d6afc88ce6640aeba9962sewardj                                           mkU32 ( 0xF ) ),
97864c96e61dd85c172b999d6afc88ce6640aeba9962sewardj                                    mkU32( 0x9 ) ) ),
97874c96e61dd85c172b999d6afc88ce6640aeba9962sewardj                       unop( Iop_1Sto32,
97884c96e61dd85c172b999d6afc88ce6640aeba9962sewardj                             binop( Iop_CmpLE32U,
97894c96e61dd85c172b999d6afc88ce6640aeba9962sewardj                                    binop( Iop_And32,
97904c96e61dd85c172b999d6afc88ce6640aeba9962sewardj                                           binop( Iop_Shr32,
97914c96e61dd85c172b999d6afc88ce6640aeba9962sewardj                                                  bcd_u,
97924c96e61dd85c172b999d6afc88ce6640aeba9962sewardj                                                  mkU8 ( DIGIT2_SHR ) ),
97934c96e61dd85c172b999d6afc88ce6640aeba9962sewardj                                           mkU32 ( 0xF ) ),
97944c96e61dd85c172b999d6afc88ce6640aeba9962sewardj                                    mkU32( 0x9 ) ) ),
97954c96e61dd85c172b999d6afc88ce6640aeba9962sewardj                       unop( Iop_1Sto32,
97964c96e61dd85c172b999d6afc88ce6640aeba9962sewardj                             binop( Iop_CmpLE32U,
97974c96e61dd85c172b999d6afc88ce6640aeba9962sewardj                                    binop( Iop_And32,
97984c96e61dd85c172b999d6afc88ce6640aeba9962sewardj                                           binop( Iop_Shr32,
97994c96e61dd85c172b999d6afc88ce6640aeba9962sewardj                                                  bcd_u,
98004c96e61dd85c172b999d6afc88ce6640aeba9962sewardj                                                  mkU8 ( DIGIT3_SHR ) ),
98014c96e61dd85c172b999d6afc88ce6640aeba9962sewardj                                           mkU32 ( 0xF ) ),
98024c96e61dd85c172b999d6afc88ce6640aeba9962sewardj                                    mkU32( 0x9 ) ) ) ),
98034c96e61dd85c172b999d6afc88ce6640aeba9962sewardj                 AND4( unop( Iop_1Sto32,
98044c96e61dd85c172b999d6afc88ce6640aeba9962sewardj                             binop( Iop_CmpLE32U,
98054c96e61dd85c172b999d6afc88ce6640aeba9962sewardj                                    binop( Iop_And32,
98064c96e61dd85c172b999d6afc88ce6640aeba9962sewardj                                           binop( Iop_Shr32,
98074c96e61dd85c172b999d6afc88ce6640aeba9962sewardj                                                  bcd_u,
98084c96e61dd85c172b999d6afc88ce6640aeba9962sewardj                                                  mkU8 ( DIGIT4_SHR ) ),
98094c96e61dd85c172b999d6afc88ce6640aeba9962sewardj                                           mkU32 ( 0xF ) ),
98104c96e61dd85c172b999d6afc88ce6640aeba9962sewardj                                    mkU32( 0x9 ) ) ),
98114c96e61dd85c172b999d6afc88ce6640aeba9962sewardj                       unop( Iop_1Sto32,
98124c96e61dd85c172b999d6afc88ce6640aeba9962sewardj                             binop( Iop_CmpLE32U,
98134c96e61dd85c172b999d6afc88ce6640aeba9962sewardj                                    binop( Iop_And32,
98144c96e61dd85c172b999d6afc88ce6640aeba9962sewardj                                           binop( Iop_Shr32,
98154c96e61dd85c172b999d6afc88ce6640aeba9962sewardj                                                  bcd_u,
98164c96e61dd85c172b999d6afc88ce6640aeba9962sewardj                                                  mkU8 ( DIGIT5_SHR ) ),
98174c96e61dd85c172b999d6afc88ce6640aeba9962sewardj                                           mkU32 ( 0xF ) ),
98184c96e61dd85c172b999d6afc88ce6640aeba9962sewardj                                    mkU32( 0x9 ) ) ),
98194c96e61dd85c172b999d6afc88ce6640aeba9962sewardj                       unop( Iop_1Sto32,
98204c96e61dd85c172b999d6afc88ce6640aeba9962sewardj                             binop( Iop_CmpLE32U,
98214c96e61dd85c172b999d6afc88ce6640aeba9962sewardj                                    binop( Iop_And32,
98224c96e61dd85c172b999d6afc88ce6640aeba9962sewardj                                           binop( Iop_Shr32,
98234c96e61dd85c172b999d6afc88ce6640aeba9962sewardj                                                  bcd_u,
98244c96e61dd85c172b999d6afc88ce6640aeba9962sewardj                                                  mkU8 ( DIGIT6_SHR ) ),
98254c96e61dd85c172b999d6afc88ce6640aeba9962sewardj                                           mkU32 ( 0xF ) ),
98264c96e61dd85c172b999d6afc88ce6640aeba9962sewardj                                    mkU32( 0x9 ) ) ),
98274c96e61dd85c172b999d6afc88ce6640aeba9962sewardj                       unop( Iop_1Sto32,
98284c96e61dd85c172b999d6afc88ce6640aeba9962sewardj                             binop( Iop_CmpLE32U,
98294c96e61dd85c172b999d6afc88ce6640aeba9962sewardj                                    binop( Iop_And32,
98304c96e61dd85c172b999d6afc88ce6640aeba9962sewardj                                           binop( Iop_Shr32,
98314c96e61dd85c172b999d6afc88ce6640aeba9962sewardj                                                  bcd_u,
98324c96e61dd85c172b999d6afc88ce6640aeba9962sewardj                                                  mkU8 ( DIGIT7_SHR ) ),
98334c96e61dd85c172b999d6afc88ce6640aeba9962sewardj                                           mkU32 ( 0xF ) ),
98344c96e61dd85c172b999d6afc88ce6640aeba9962sewardj                                    mkU32( 0x9 ) ) ) ) ) );
98354c96e61dd85c172b999d6afc88ce6640aeba9962sewardj
98364c96e61dd85c172b999d6afc88ce6640aeba9962sewardj   return unop( Iop_Not32, mkexpr( valid ) );
98374c96e61dd85c172b999d6afc88ce6640aeba9962sewardj}
98384c96e61dd85c172b999d6afc88ce6640aeba9962sewardj#undef DIGIT1_SHR
98394c96e61dd85c172b999d6afc88ce6640aeba9962sewardj#undef DIGIT2_SHR
98404c96e61dd85c172b999d6afc88ce6640aeba9962sewardj#undef DIGIT3_SHR
98414c96e61dd85c172b999d6afc88ce6640aeba9962sewardj#undef DIGIT4_SHR
98424c96e61dd85c172b999d6afc88ce6640aeba9962sewardj#undef DIGIT5_SHR
98434c96e61dd85c172b999d6afc88ce6640aeba9962sewardj#undef DIGIT6_SHR
98444c96e61dd85c172b999d6afc88ce6640aeba9962sewardj#undef DIGIT7_SHR
98454c96e61dd85c172b999d6afc88ce6640aeba9962sewardj
98464c96e61dd85c172b999d6afc88ce6640aeba9962sewardjstatic IRExpr * Generate_neg_sign_mask( IRExpr * sign )
98474c96e61dd85c172b999d6afc88ce6640aeba9962sewardj{
98484c96e61dd85c172b999d6afc88ce6640aeba9962sewardj   return binop( Iop_Or32,
98494c96e61dd85c172b999d6afc88ce6640aeba9962sewardj                 unop( Iop_1Sto32, binop( Iop_CmpEQ32, sign, mkU32( 0xB ) ) ),
98504c96e61dd85c172b999d6afc88ce6640aeba9962sewardj                 unop( Iop_1Sto32, binop( Iop_CmpEQ32, sign, mkU32( 0xD ) ) )
98514c96e61dd85c172b999d6afc88ce6640aeba9962sewardj               );
98524c96e61dd85c172b999d6afc88ce6640aeba9962sewardj}
98534c96e61dd85c172b999d6afc88ce6640aeba9962sewardj
98544c96e61dd85c172b999d6afc88ce6640aeba9962sewardjstatic IRExpr * Generate_pos_sign_mask( IRExpr * sign )
98554c96e61dd85c172b999d6afc88ce6640aeba9962sewardj{
98564c96e61dd85c172b999d6afc88ce6640aeba9962sewardj   return binop( Iop_Or32,
98574c96e61dd85c172b999d6afc88ce6640aeba9962sewardj                 binop( Iop_Or32,
98584c96e61dd85c172b999d6afc88ce6640aeba9962sewardj                        unop( Iop_1Sto32,
98594c96e61dd85c172b999d6afc88ce6640aeba9962sewardj                              binop( Iop_CmpEQ32, sign, mkU32( 0xA ) ) ),
98604c96e61dd85c172b999d6afc88ce6640aeba9962sewardj                        unop( Iop_1Sto32,
98614c96e61dd85c172b999d6afc88ce6640aeba9962sewardj                              binop( Iop_CmpEQ32, sign, mkU32( 0xC ) ) ) ),
98624c96e61dd85c172b999d6afc88ce6640aeba9962sewardj                 binop( Iop_Or32,
98634c96e61dd85c172b999d6afc88ce6640aeba9962sewardj                        unop( Iop_1Sto32,
98644c96e61dd85c172b999d6afc88ce6640aeba9962sewardj                              binop( Iop_CmpEQ32, sign, mkU32( 0xE ) ) ),
98654c96e61dd85c172b999d6afc88ce6640aeba9962sewardj                        unop( Iop_1Sto32,
98664c96e61dd85c172b999d6afc88ce6640aeba9962sewardj                              binop( Iop_CmpEQ32, sign, mkU32( 0xF ) ) ) ) );
98674c96e61dd85c172b999d6afc88ce6640aeba9962sewardj}
98684c96e61dd85c172b999d6afc88ce6640aeba9962sewardj
98694c96e61dd85c172b999d6afc88ce6640aeba9962sewardjstatic IRExpr * Generate_sign_bit( IRExpr * pos_sign_mask,
98704c96e61dd85c172b999d6afc88ce6640aeba9962sewardj                                   IRExpr * neg_sign_mask )
98714c96e61dd85c172b999d6afc88ce6640aeba9962sewardj{
98724c96e61dd85c172b999d6afc88ce6640aeba9962sewardj   return binop( Iop_Or32,
98734c96e61dd85c172b999d6afc88ce6640aeba9962sewardj                 binop( Iop_And32, neg_sign_mask, mkU32( 0x80000000 ) ),
98744c96e61dd85c172b999d6afc88ce6640aeba9962sewardj                 binop( Iop_And32, pos_sign_mask, mkU32( 0x00000000 ) ) );
98754c96e61dd85c172b999d6afc88ce6640aeba9962sewardj}
98764c96e61dd85c172b999d6afc88ce6640aeba9962sewardj
98774c96e61dd85c172b999d6afc88ce6640aeba9962sewardjstatic IRExpr * Generate_inv_mask( IRExpr * invalid_bcd_mask,
98784c96e61dd85c172b999d6afc88ce6640aeba9962sewardj                                   IRExpr * pos_sign_mask,
98794c96e61dd85c172b999d6afc88ce6640aeba9962sewardj                                   IRExpr * neg_sign_mask )
98804c96e61dd85c172b999d6afc88ce6640aeba9962sewardj/* first argument is all 1's if the BCD string had an invalid digit in it. */
98814c96e61dd85c172b999d6afc88ce6640aeba9962sewardj{
98824c96e61dd85c172b999d6afc88ce6640aeba9962sewardj   return binop( Iop_Or32,
98834c96e61dd85c172b999d6afc88ce6640aeba9962sewardj                 invalid_bcd_mask,
98844c96e61dd85c172b999d6afc88ce6640aeba9962sewardj                 unop( Iop_1Sto32,
98854c96e61dd85c172b999d6afc88ce6640aeba9962sewardj                       binop( Iop_CmpEQ32,
98864c96e61dd85c172b999d6afc88ce6640aeba9962sewardj                              binop( Iop_Or32, pos_sign_mask, neg_sign_mask ),
98874c96e61dd85c172b999d6afc88ce6640aeba9962sewardj                              mkU32( 0x0 ) ) ) );
98884c96e61dd85c172b999d6afc88ce6640aeba9962sewardj}
98894c96e61dd85c172b999d6afc88ce6640aeba9962sewardj
98904c96e61dd85c172b999d6afc88ce6640aeba9962sewardjstatic void Generate_132_bit_bcd_string( IRExpr * frBI64_hi, IRExpr * frBI64_lo,
98914c96e61dd85c172b999d6afc88ce6640aeba9962sewardj                                         IRTemp * top_12_l, IRTemp * mid_60_u,
98924c96e61dd85c172b999d6afc88ce6640aeba9962sewardj                                         IRTemp * mid_60_l, IRTemp * low_60_u,
98934c96e61dd85c172b999d6afc88ce6640aeba9962sewardj                                         IRTemp * low_60_l)
98944c96e61dd85c172b999d6afc88ce6640aeba9962sewardj{
98954c96e61dd85c172b999d6afc88ce6640aeba9962sewardj   IRTemp tmplow60 = newTemp( Ity_I64 );
98964c96e61dd85c172b999d6afc88ce6640aeba9962sewardj   IRTemp tmpmid60 = newTemp( Ity_I64 );
98974c96e61dd85c172b999d6afc88ce6640aeba9962sewardj   IRTemp tmptop12 = newTemp( Ity_I64 );
98984c96e61dd85c172b999d6afc88ce6640aeba9962sewardj   IRTemp low_50   = newTemp( Ity_I64 );
98994c96e61dd85c172b999d6afc88ce6640aeba9962sewardj   IRTemp mid_50   = newTemp( Ity_I64 );
99004c96e61dd85c172b999d6afc88ce6640aeba9962sewardj   IRTemp top_10   = newTemp( Ity_I64 );
99014c96e61dd85c172b999d6afc88ce6640aeba9962sewardj   IRTemp top_12_u = newTemp( Ity_I32 ); // only needed for a dummy arg
99024c96e61dd85c172b999d6afc88ce6640aeba9962sewardj
99034c96e61dd85c172b999d6afc88ce6640aeba9962sewardj   /* Convert the 110-bit densely packed BCD string to a 128-bit BCD string */
99044c96e61dd85c172b999d6afc88ce6640aeba9962sewardj
99054c96e61dd85c172b999d6afc88ce6640aeba9962sewardj   /* low_50[49:0] = ((frBI64_lo[49:32]  << 14) | frBI64_lo[31:0]) */
99064c96e61dd85c172b999d6afc88ce6640aeba9962sewardj   assign( low_50,
99074c96e61dd85c172b999d6afc88ce6640aeba9962sewardj           binop( Iop_32HLto64,
99084c96e61dd85c172b999d6afc88ce6640aeba9962sewardj                  binop( Iop_And32,
99094c96e61dd85c172b999d6afc88ce6640aeba9962sewardj                         unop( Iop_64HIto32, frBI64_lo ),
99104c96e61dd85c172b999d6afc88ce6640aeba9962sewardj                         mkU32( 0x3FFFF ) ),
99114c96e61dd85c172b999d6afc88ce6640aeba9962sewardj                         unop( Iop_64to32, frBI64_lo ) ) );
99124c96e61dd85c172b999d6afc88ce6640aeba9962sewardj
99134c96e61dd85c172b999d6afc88ce6640aeba9962sewardj   /* Convert the 50 bit densely packed BCD string to a 60 bit
99144c96e61dd85c172b999d6afc88ce6640aeba9962sewardj    * BCD string.
99154c96e61dd85c172b999d6afc88ce6640aeba9962sewardj    */
99164c96e61dd85c172b999d6afc88ce6640aeba9962sewardj   assign( tmplow60, unop( Iop_DPBtoBCD, mkexpr( low_50 ) ) );
99174c96e61dd85c172b999d6afc88ce6640aeba9962sewardj   assign( *low_60_u, unop( Iop_64HIto32, mkexpr( tmplow60 ) ) );
99184c96e61dd85c172b999d6afc88ce6640aeba9962sewardj   assign( *low_60_l, unop( Iop_64to32, mkexpr( tmplow60 ) ) );
99194c96e61dd85c172b999d6afc88ce6640aeba9962sewardj
99204c96e61dd85c172b999d6afc88ce6640aeba9962sewardj   /* mid_50[49:0] =  ((frBI64_hi[35:32] << 14) | frBI64_hi[31:18]) |
99214c96e61dd85c172b999d6afc88ce6640aeba9962sewardj    *                 ((frBI64_hi[17:0]  << 14) | frBI64_lo[63:50])
99224c96e61dd85c172b999d6afc88ce6640aeba9962sewardj    */
99234c96e61dd85c172b999d6afc88ce6640aeba9962sewardj   assign( mid_50,
99244c96e61dd85c172b999d6afc88ce6640aeba9962sewardj           binop( Iop_32HLto64,
99254c96e61dd85c172b999d6afc88ce6640aeba9962sewardj                  binop( Iop_Or32,
99264c96e61dd85c172b999d6afc88ce6640aeba9962sewardj                         binop( Iop_Shl32,
99274c96e61dd85c172b999d6afc88ce6640aeba9962sewardj                                binop( Iop_And32,
99284c96e61dd85c172b999d6afc88ce6640aeba9962sewardj                                       unop( Iop_64HIto32, frBI64_hi ),
99294c96e61dd85c172b999d6afc88ce6640aeba9962sewardj                                       mkU32( 0xF ) ),
99304c96e61dd85c172b999d6afc88ce6640aeba9962sewardj                                mkU8( 14 ) ),
99314c96e61dd85c172b999d6afc88ce6640aeba9962sewardj                         binop( Iop_Shr32,
99324c96e61dd85c172b999d6afc88ce6640aeba9962sewardj                                unop( Iop_64to32, frBI64_hi ),
99334c96e61dd85c172b999d6afc88ce6640aeba9962sewardj                                mkU8( 18 ) ) ),
99344c96e61dd85c172b999d6afc88ce6640aeba9962sewardj                  binop( Iop_Or32,
99354c96e61dd85c172b999d6afc88ce6640aeba9962sewardj                         binop( Iop_Shl32,
99364c96e61dd85c172b999d6afc88ce6640aeba9962sewardj                                unop( Iop_64to32, frBI64_hi ),
99374c96e61dd85c172b999d6afc88ce6640aeba9962sewardj                                mkU8( 14 ) ),
99384c96e61dd85c172b999d6afc88ce6640aeba9962sewardj                         binop( Iop_Shr32,
99394c96e61dd85c172b999d6afc88ce6640aeba9962sewardj                                unop( Iop_64HIto32, frBI64_lo ),
99404c96e61dd85c172b999d6afc88ce6640aeba9962sewardj                                mkU8( 18 ) ) ) ) );
99414c96e61dd85c172b999d6afc88ce6640aeba9962sewardj
99424c96e61dd85c172b999d6afc88ce6640aeba9962sewardj   /* Convert the 50 bit densely packed BCD string to a 60 bit
99434c96e61dd85c172b999d6afc88ce6640aeba9962sewardj    * BCD string.
99444c96e61dd85c172b999d6afc88ce6640aeba9962sewardj    */
99454c96e61dd85c172b999d6afc88ce6640aeba9962sewardj   assign( tmpmid60, unop( Iop_DPBtoBCD, mkexpr( mid_50 ) ) );
99464c96e61dd85c172b999d6afc88ce6640aeba9962sewardj   assign( *mid_60_u, unop( Iop_64HIto32, mkexpr( tmpmid60 ) ) );
99474c96e61dd85c172b999d6afc88ce6640aeba9962sewardj   assign( *mid_60_l, unop( Iop_64to32, mkexpr( tmpmid60 ) ) );
99484c96e61dd85c172b999d6afc88ce6640aeba9962sewardj
99494c96e61dd85c172b999d6afc88ce6640aeba9962sewardj   /* top_10[49:0] = frBI64_hi[45:36]) |  */
99504c96e61dd85c172b999d6afc88ce6640aeba9962sewardj   assign( top_10,
99514c96e61dd85c172b999d6afc88ce6640aeba9962sewardj           binop( Iop_32HLto64,
99524c96e61dd85c172b999d6afc88ce6640aeba9962sewardj                  mkU32( 0 ),
99534c96e61dd85c172b999d6afc88ce6640aeba9962sewardj                  binop( Iop_And32,
99544c96e61dd85c172b999d6afc88ce6640aeba9962sewardj                         binop( Iop_Shr32,
99554c96e61dd85c172b999d6afc88ce6640aeba9962sewardj                                unop( Iop_64HIto32, frBI64_hi ),
99564c96e61dd85c172b999d6afc88ce6640aeba9962sewardj                                mkU8( 4 ) ),
99574c96e61dd85c172b999d6afc88ce6640aeba9962sewardj                         mkU32( 0x3FF ) ) ) );
99584c96e61dd85c172b999d6afc88ce6640aeba9962sewardj
99594c96e61dd85c172b999d6afc88ce6640aeba9962sewardj   /* Convert the 10 bit densely packed BCD string to a 12 bit
99604c96e61dd85c172b999d6afc88ce6640aeba9962sewardj    * BCD string.
99614c96e61dd85c172b999d6afc88ce6640aeba9962sewardj    */
99624c96e61dd85c172b999d6afc88ce6640aeba9962sewardj   assign( tmptop12, unop( Iop_DPBtoBCD, mkexpr( top_10 ) ) );
99634c96e61dd85c172b999d6afc88ce6640aeba9962sewardj   assign( top_12_u, unop( Iop_64HIto32, mkexpr( tmptop12 ) ) );
99644c96e61dd85c172b999d6afc88ce6640aeba9962sewardj   assign( *top_12_l, unop( Iop_64to32, mkexpr( tmptop12 ) ) );
99654c96e61dd85c172b999d6afc88ce6640aeba9962sewardj}
99664c96e61dd85c172b999d6afc88ce6640aeba9962sewardj
99674c96e61dd85c172b999d6afc88ce6640aeba9962sewardjstatic void Count_zeros( int start, IRExpr * init_cnt, IRExpr * init_flag,
99684c96e61dd85c172b999d6afc88ce6640aeba9962sewardj                         IRTemp * final_cnt, IRTemp * final_flag,
99694c96e61dd85c172b999d6afc88ce6640aeba9962sewardj                         IRExpr * string )
99704c96e61dd85c172b999d6afc88ce6640aeba9962sewardj{
99714c96e61dd85c172b999d6afc88ce6640aeba9962sewardj   IRTemp cnt[MAX_DIGITS_IN_STRING + 1];IRTemp flag[MAX_DIGITS_IN_STRING+1];
99724c96e61dd85c172b999d6afc88ce6640aeba9962sewardj   int digits = MAX_DIGITS_IN_STRING;
99734c96e61dd85c172b999d6afc88ce6640aeba9962sewardj   int i;
99744c96e61dd85c172b999d6afc88ce6640aeba9962sewardj
99754c96e61dd85c172b999d6afc88ce6640aeba9962sewardj   cnt[start-1] = newTemp( Ity_I8 );
99764c96e61dd85c172b999d6afc88ce6640aeba9962sewardj   flag[start-1] = newTemp( Ity_I8 );
99774c96e61dd85c172b999d6afc88ce6640aeba9962sewardj   assign( cnt[start-1], init_cnt);
99784c96e61dd85c172b999d6afc88ce6640aeba9962sewardj   assign( flag[start-1], init_flag);
99794c96e61dd85c172b999d6afc88ce6640aeba9962sewardj
99804c96e61dd85c172b999d6afc88ce6640aeba9962sewardj   for ( i = start; i <= digits; i++) {
99814c96e61dd85c172b999d6afc88ce6640aeba9962sewardj      cnt[i] = newTemp( Ity_I8 );
99824c96e61dd85c172b999d6afc88ce6640aeba9962sewardj      flag[i] = newTemp( Ity_I8 );
99834c96e61dd85c172b999d6afc88ce6640aeba9962sewardj      assign( cnt[i],
99844c96e61dd85c172b999d6afc88ce6640aeba9962sewardj              binop( Iop_Add8,
99854c96e61dd85c172b999d6afc88ce6640aeba9962sewardj                     mkexpr( cnt[i-1] ),
99864c96e61dd85c172b999d6afc88ce6640aeba9962sewardj                     binop(Iop_And8,
99874c96e61dd85c172b999d6afc88ce6640aeba9962sewardj                           unop( Iop_1Uto8,
99884c96e61dd85c172b999d6afc88ce6640aeba9962sewardj                                 binop(Iop_CmpEQ32,
99894c96e61dd85c172b999d6afc88ce6640aeba9962sewardj                                       binop(Iop_And32,
99904c96e61dd85c172b999d6afc88ce6640aeba9962sewardj                                             string,
99914c96e61dd85c172b999d6afc88ce6640aeba9962sewardj                                             mkU32( 0xF <<
99924c96e61dd85c172b999d6afc88ce6640aeba9962sewardj                                                    ( ( digits - i ) * 4) ) ),
99934c96e61dd85c172b999d6afc88ce6640aeba9962sewardj                                       mkU32( 0 ) ) ),
99944c96e61dd85c172b999d6afc88ce6640aeba9962sewardj                           binop( Iop_Xor8, /* complement flag */
99954c96e61dd85c172b999d6afc88ce6640aeba9962sewardj                                  mkexpr( flag[i - 1] ),
99964c96e61dd85c172b999d6afc88ce6640aeba9962sewardj                                  mkU8( 0xFF ) ) ) ) );
99974c96e61dd85c172b999d6afc88ce6640aeba9962sewardj
99984c96e61dd85c172b999d6afc88ce6640aeba9962sewardj      /* set flag to 1 if digit was not a zero */
99994c96e61dd85c172b999d6afc88ce6640aeba9962sewardj      assign( flag[i],
100004c96e61dd85c172b999d6afc88ce6640aeba9962sewardj              binop(Iop_Or8,
100014c96e61dd85c172b999d6afc88ce6640aeba9962sewardj                    unop( Iop_1Sto8,
100024c96e61dd85c172b999d6afc88ce6640aeba9962sewardj                          binop(Iop_CmpNE32,
100034c96e61dd85c172b999d6afc88ce6640aeba9962sewardj                                binop(Iop_And32,
100044c96e61dd85c172b999d6afc88ce6640aeba9962sewardj                                      string,
100054c96e61dd85c172b999d6afc88ce6640aeba9962sewardj                                      mkU32( 0xF <<
100064c96e61dd85c172b999d6afc88ce6640aeba9962sewardj                                             ( (digits - i) * 4) ) ),
100074c96e61dd85c172b999d6afc88ce6640aeba9962sewardj                                mkU32( 0 ) ) ),
100084c96e61dd85c172b999d6afc88ce6640aeba9962sewardj                    mkexpr( flag[i - 1] ) ) );
100094c96e61dd85c172b999d6afc88ce6640aeba9962sewardj   }
100104c96e61dd85c172b999d6afc88ce6640aeba9962sewardj
100114c96e61dd85c172b999d6afc88ce6640aeba9962sewardj   *final_cnt = cnt[digits];
100124c96e61dd85c172b999d6afc88ce6640aeba9962sewardj   *final_flag = flag[digits];
100134c96e61dd85c172b999d6afc88ce6640aeba9962sewardj}
100144c96e61dd85c172b999d6afc88ce6640aeba9962sewardj
100154c96e61dd85c172b999d6afc88ce6640aeba9962sewardjstatic IRExpr * Count_leading_zeros_60( IRExpr * lmd, IRExpr * upper_28,
100164c96e61dd85c172b999d6afc88ce6640aeba9962sewardj                                        IRExpr * low_32 )
100174c96e61dd85c172b999d6afc88ce6640aeba9962sewardj{
100184c96e61dd85c172b999d6afc88ce6640aeba9962sewardj   IRTemp num_lmd    = newTemp( Ity_I8 );
100194c96e61dd85c172b999d6afc88ce6640aeba9962sewardj   IRTemp num_upper  = newTemp( Ity_I8 );
100204c96e61dd85c172b999d6afc88ce6640aeba9962sewardj   IRTemp num_low    = newTemp( Ity_I8 );
100214c96e61dd85c172b999d6afc88ce6640aeba9962sewardj   IRTemp lmd_flag   = newTemp( Ity_I8 );
100224c96e61dd85c172b999d6afc88ce6640aeba9962sewardj   IRTemp upper_flag = newTemp( Ity_I8 );
100234c96e61dd85c172b999d6afc88ce6640aeba9962sewardj   IRTemp low_flag   = newTemp( Ity_I8 );
100244c96e61dd85c172b999d6afc88ce6640aeba9962sewardj
100254c96e61dd85c172b999d6afc88ce6640aeba9962sewardj   assign( num_lmd, unop( Iop_1Uto8, binop( Iop_CmpEQ32, lmd, mkU32( 0 ) ) ) );
100264c96e61dd85c172b999d6afc88ce6640aeba9962sewardj   assign( lmd_flag, unop( Iop_Not8, mkexpr( num_lmd ) ) );
100274c96e61dd85c172b999d6afc88ce6640aeba9962sewardj
100284c96e61dd85c172b999d6afc88ce6640aeba9962sewardj   Count_zeros( 2,
100294c96e61dd85c172b999d6afc88ce6640aeba9962sewardj                mkexpr( num_lmd ),
100304c96e61dd85c172b999d6afc88ce6640aeba9962sewardj                mkexpr( lmd_flag ),
100314c96e61dd85c172b999d6afc88ce6640aeba9962sewardj                &num_upper,
100324c96e61dd85c172b999d6afc88ce6640aeba9962sewardj                &upper_flag,
100334c96e61dd85c172b999d6afc88ce6640aeba9962sewardj                upper_28 );
100344c96e61dd85c172b999d6afc88ce6640aeba9962sewardj
100354c96e61dd85c172b999d6afc88ce6640aeba9962sewardj   Count_zeros( 1,
100364c96e61dd85c172b999d6afc88ce6640aeba9962sewardj                mkexpr( num_upper ),
100374c96e61dd85c172b999d6afc88ce6640aeba9962sewardj                mkexpr( upper_flag ),
100384c96e61dd85c172b999d6afc88ce6640aeba9962sewardj                &num_low,
100394c96e61dd85c172b999d6afc88ce6640aeba9962sewardj                &low_flag,
100404c96e61dd85c172b999d6afc88ce6640aeba9962sewardj                low_32 );
100414c96e61dd85c172b999d6afc88ce6640aeba9962sewardj
100424c96e61dd85c172b999d6afc88ce6640aeba9962sewardj   return mkexpr( num_low );
100434c96e61dd85c172b999d6afc88ce6640aeba9962sewardj}
100444c96e61dd85c172b999d6afc88ce6640aeba9962sewardj
100454c96e61dd85c172b999d6afc88ce6640aeba9962sewardjstatic IRExpr * Count_leading_zeros_128( IRExpr * lmd, IRExpr * top_12_l,
100464c96e61dd85c172b999d6afc88ce6640aeba9962sewardj                                         IRExpr * mid_60_u, IRExpr * mid_60_l,
100474c96e61dd85c172b999d6afc88ce6640aeba9962sewardj                                         IRExpr * low_60_u, IRExpr * low_60_l)
100484c96e61dd85c172b999d6afc88ce6640aeba9962sewardj{
100494c96e61dd85c172b999d6afc88ce6640aeba9962sewardj   IRTemp num_lmd   = newTemp( Ity_I8 );
100504c96e61dd85c172b999d6afc88ce6640aeba9962sewardj   IRTemp num_top   = newTemp( Ity_I8 );
100514c96e61dd85c172b999d6afc88ce6640aeba9962sewardj   IRTemp num_mid_u = newTemp( Ity_I8 );
100524c96e61dd85c172b999d6afc88ce6640aeba9962sewardj   IRTemp num_mid_l = newTemp( Ity_I8 );
100534c96e61dd85c172b999d6afc88ce6640aeba9962sewardj   IRTemp num_low_u = newTemp( Ity_I8 );
100544c96e61dd85c172b999d6afc88ce6640aeba9962sewardj   IRTemp num_low_l = newTemp( Ity_I8 );
100554c96e61dd85c172b999d6afc88ce6640aeba9962sewardj
100564c96e61dd85c172b999d6afc88ce6640aeba9962sewardj   IRTemp lmd_flag   = newTemp( Ity_I8 );
100574c96e61dd85c172b999d6afc88ce6640aeba9962sewardj   IRTemp top_flag   = newTemp( Ity_I8 );
100584c96e61dd85c172b999d6afc88ce6640aeba9962sewardj   IRTemp mid_u_flag = newTemp( Ity_I8 );
100594c96e61dd85c172b999d6afc88ce6640aeba9962sewardj   IRTemp mid_l_flag = newTemp( Ity_I8 );
100604c96e61dd85c172b999d6afc88ce6640aeba9962sewardj   IRTemp low_u_flag = newTemp( Ity_I8 );
100614c96e61dd85c172b999d6afc88ce6640aeba9962sewardj   IRTemp low_l_flag = newTemp( Ity_I8 );
100624c96e61dd85c172b999d6afc88ce6640aeba9962sewardj
100634c96e61dd85c172b999d6afc88ce6640aeba9962sewardj   /* Check the LMD, digit 16, to see if it is zero. */
100644c96e61dd85c172b999d6afc88ce6640aeba9962sewardj   assign( num_lmd, unop( Iop_1Uto8, binop( Iop_CmpEQ32, lmd, mkU32( 0 ) ) ) );
100654c96e61dd85c172b999d6afc88ce6640aeba9962sewardj
100664c96e61dd85c172b999d6afc88ce6640aeba9962sewardj   assign( lmd_flag, unop( Iop_Not8, mkexpr( num_lmd ) ) );
100674c96e61dd85c172b999d6afc88ce6640aeba9962sewardj
100684c96e61dd85c172b999d6afc88ce6640aeba9962sewardj   Count_zeros( 6,
100694c96e61dd85c172b999d6afc88ce6640aeba9962sewardj                mkexpr( num_lmd ),
100704c96e61dd85c172b999d6afc88ce6640aeba9962sewardj                mkexpr( lmd_flag ),
100714c96e61dd85c172b999d6afc88ce6640aeba9962sewardj                &num_top,
100724c96e61dd85c172b999d6afc88ce6640aeba9962sewardj                &top_flag,
100734c96e61dd85c172b999d6afc88ce6640aeba9962sewardj                top_12_l );
100744c96e61dd85c172b999d6afc88ce6640aeba9962sewardj
100754c96e61dd85c172b999d6afc88ce6640aeba9962sewardj   Count_zeros( 1,
100764c96e61dd85c172b999d6afc88ce6640aeba9962sewardj                mkexpr( num_top ),
100774c96e61dd85c172b999d6afc88ce6640aeba9962sewardj                mkexpr( top_flag ),
100784c96e61dd85c172b999d6afc88ce6640aeba9962sewardj                &num_mid_u,
100794c96e61dd85c172b999d6afc88ce6640aeba9962sewardj                &mid_u_flag,
100804c96e61dd85c172b999d6afc88ce6640aeba9962sewardj                binop( Iop_Or32,
100814c96e61dd85c172b999d6afc88ce6640aeba9962sewardj                       binop( Iop_Shl32, mid_60_u, mkU8( 2 ) ),
100824c96e61dd85c172b999d6afc88ce6640aeba9962sewardj                       binop( Iop_Shr32, mid_60_l, mkU8( 30 ) ) ) );
100834c96e61dd85c172b999d6afc88ce6640aeba9962sewardj
100844c96e61dd85c172b999d6afc88ce6640aeba9962sewardj   Count_zeros( 2,
100854c96e61dd85c172b999d6afc88ce6640aeba9962sewardj                mkexpr( num_mid_u ),
100864c96e61dd85c172b999d6afc88ce6640aeba9962sewardj                mkexpr( mid_u_flag ),
100874c96e61dd85c172b999d6afc88ce6640aeba9962sewardj                &num_mid_l,
100884c96e61dd85c172b999d6afc88ce6640aeba9962sewardj                &mid_l_flag,
100894c96e61dd85c172b999d6afc88ce6640aeba9962sewardj                mid_60_l );
100904c96e61dd85c172b999d6afc88ce6640aeba9962sewardj
100914c96e61dd85c172b999d6afc88ce6640aeba9962sewardj   Count_zeros( 1,
100924c96e61dd85c172b999d6afc88ce6640aeba9962sewardj                mkexpr( num_mid_l ),
100934c96e61dd85c172b999d6afc88ce6640aeba9962sewardj                mkexpr( mid_l_flag ),
100944c96e61dd85c172b999d6afc88ce6640aeba9962sewardj                &num_low_u,
100954c96e61dd85c172b999d6afc88ce6640aeba9962sewardj                &low_u_flag,
100964c96e61dd85c172b999d6afc88ce6640aeba9962sewardj                binop( Iop_Or32,
100974c96e61dd85c172b999d6afc88ce6640aeba9962sewardj                       binop( Iop_Shl32, low_60_u, mkU8( 2 ) ),
100984c96e61dd85c172b999d6afc88ce6640aeba9962sewardj                       binop( Iop_Shr32, low_60_l, mkU8( 30 ) ) ) );
100994c96e61dd85c172b999d6afc88ce6640aeba9962sewardj
101004c96e61dd85c172b999d6afc88ce6640aeba9962sewardj   Count_zeros( 2,
101014c96e61dd85c172b999d6afc88ce6640aeba9962sewardj                mkexpr( num_low_u ),
101024c96e61dd85c172b999d6afc88ce6640aeba9962sewardj                mkexpr( low_u_flag ),
101034c96e61dd85c172b999d6afc88ce6640aeba9962sewardj                &num_low_l,
101044c96e61dd85c172b999d6afc88ce6640aeba9962sewardj                &low_l_flag,
101054c96e61dd85c172b999d6afc88ce6640aeba9962sewardj                low_60_l );
101064c96e61dd85c172b999d6afc88ce6640aeba9962sewardj
101074c96e61dd85c172b999d6afc88ce6640aeba9962sewardj   return mkexpr( num_low_l );
101084c96e61dd85c172b999d6afc88ce6640aeba9962sewardj}
101094c96e61dd85c172b999d6afc88ce6640aeba9962sewardj
101104c96e61dd85c172b999d6afc88ce6640aeba9962sewardjstatic IRExpr * Check_unordered(IRExpr * val)
101114c96e61dd85c172b999d6afc88ce6640aeba9962sewardj{
101124c96e61dd85c172b999d6afc88ce6640aeba9962sewardj   IRTemp gfield0to5 = newTemp( Ity_I32 );
101134c96e61dd85c172b999d6afc88ce6640aeba9962sewardj
101144c96e61dd85c172b999d6afc88ce6640aeba9962sewardj   /* Extract G[0:4] */
101154c96e61dd85c172b999d6afc88ce6640aeba9962sewardj   assign( gfield0to5,
101164c96e61dd85c172b999d6afc88ce6640aeba9962sewardj           binop( Iop_And32,
101174c96e61dd85c172b999d6afc88ce6640aeba9962sewardj                  binop( Iop_Shr32, unop( Iop_64HIto32, val ), mkU8( 26 ) ),
101184c96e61dd85c172b999d6afc88ce6640aeba9962sewardj                  mkU32( 0x1F ) ) );
101194c96e61dd85c172b999d6afc88ce6640aeba9962sewardj
101204c96e61dd85c172b999d6afc88ce6640aeba9962sewardj   /* Check for unordered, return all 1'x if true */
101214c96e61dd85c172b999d6afc88ce6640aeba9962sewardj   return binop( Iop_Or32, /* QNaN check */
101224c96e61dd85c172b999d6afc88ce6640aeba9962sewardj                 unop( Iop_1Sto32,
101234c96e61dd85c172b999d6afc88ce6640aeba9962sewardj                       binop( Iop_CmpEQ32,
101244c96e61dd85c172b999d6afc88ce6640aeba9962sewardj                              mkexpr( gfield0to5 ),
101254c96e61dd85c172b999d6afc88ce6640aeba9962sewardj                              mkU32( 0x1E ) ) ),
101264c96e61dd85c172b999d6afc88ce6640aeba9962sewardj                              unop( Iop_1Sto32, /* SNaN check */
101274c96e61dd85c172b999d6afc88ce6640aeba9962sewardj                                    binop( Iop_CmpEQ32,
101284c96e61dd85c172b999d6afc88ce6640aeba9962sewardj                                           mkexpr( gfield0to5 ),
101294c96e61dd85c172b999d6afc88ce6640aeba9962sewardj                                           mkU32( 0x1F ) ) ) );
101304c96e61dd85c172b999d6afc88ce6640aeba9962sewardj}
101314c96e61dd85c172b999d6afc88ce6640aeba9962sewardj
101325eff1c502e995d1f9668cc9def72d5db59f21b13sewardj#undef AND
101335eff1c502e995d1f9668cc9def72d5db59f21b13sewardj#undef AND4
101344c96e61dd85c172b999d6afc88ce6640aeba9962sewardj#undef OR
101355eff1c502e995d1f9668cc9def72d5db59f21b13sewardj#undef OR3
101365eff1c502e995d1f9668cc9def72d5db59f21b13sewardj#undef OR4
101374c96e61dd85c172b999d6afc88ce6640aeba9962sewardj#undef NOT
101384c96e61dd85c172b999d6afc88ce6640aeba9962sewardj#undef SHR
101395eff1c502e995d1f9668cc9def72d5db59f21b13sewardj#undef SHL
10140cb06d5e50876ee734e09a5fa0d5f300014e13852sewardj#undef BITS5
101415eff1c502e995d1f9668cc9def72d5db59f21b13sewardj
101425eff1c502e995d1f9668cc9def72d5db59f21b13sewardj/*------------------------------------------------------------*/
10143c6bbd470e9bd9898b84959227a406d3972d95f3bsewardj/*--- Decimal Floating Point (DFP) instruction translation ---*/
10144c6bbd470e9bd9898b84959227a406d3972d95f3bsewardj/*------------------------------------------------------------*/
101455eff1c502e995d1f9668cc9def72d5db59f21b13sewardj
10146c6bbd470e9bd9898b84959227a406d3972d95f3bsewardj/* DFP Arithmetic instructions */
10147c6bbd470e9bd9898b84959227a406d3972d95f3bsewardjstatic Bool dis_dfp_arith(UInt theInstr)
10148c6bbd470e9bd9898b84959227a406d3972d95f3bsewardj{
10149c6bbd470e9bd9898b84959227a406d3972d95f3bsewardj   UInt opc2 = ifieldOPClo10( theInstr );
10150c6bbd470e9bd9898b84959227a406d3972d95f3bsewardj   UChar frS_addr = ifieldRegDS( theInstr );
10151c6bbd470e9bd9898b84959227a406d3972d95f3bsewardj   UChar frA_addr = ifieldRegA( theInstr );
10152c6bbd470e9bd9898b84959227a406d3972d95f3bsewardj   UChar frB_addr = ifieldRegB( theInstr );
10153c6bbd470e9bd9898b84959227a406d3972d95f3bsewardj   UChar flag_rC = ifieldBIT0( theInstr );
10154c6bbd470e9bd9898b84959227a406d3972d95f3bsewardj
10155c6bbd470e9bd9898b84959227a406d3972d95f3bsewardj   IRTemp frA = newTemp( Ity_D64 );
10156c6bbd470e9bd9898b84959227a406d3972d95f3bsewardj   IRTemp frB = newTemp( Ity_D64 );
10157c6bbd470e9bd9898b84959227a406d3972d95f3bsewardj   IRTemp frS = newTemp( Ity_D64 );
10158c6bbd470e9bd9898b84959227a406d3972d95f3bsewardj   IRExpr* round = get_IR_roundingmode_DFP();
10159c6bbd470e9bd9898b84959227a406d3972d95f3bsewardj
10160c6bbd470e9bd9898b84959227a406d3972d95f3bsewardj   /* By default, if flag_RC is set, we will clear cr1 after the
10161c6bbd470e9bd9898b84959227a406d3972d95f3bsewardj    * operation.  In reality we should set cr1 to indicate the
10162c6bbd470e9bd9898b84959227a406d3972d95f3bsewardj    * exception status of the operation, but since we're not
10163c6bbd470e9bd9898b84959227a406d3972d95f3bsewardj    * simulating exceptions, the exception status will appear to be
10164c6bbd470e9bd9898b84959227a406d3972d95f3bsewardj    * zero.  Hence cr1 should be cleared if this is a . form insn.
10165c6bbd470e9bd9898b84959227a406d3972d95f3bsewardj    */
10166c6bbd470e9bd9898b84959227a406d3972d95f3bsewardj   Bool clear_CR1 = True;
10167c6bbd470e9bd9898b84959227a406d3972d95f3bsewardj
10168c6bbd470e9bd9898b84959227a406d3972d95f3bsewardj   assign( frA, getDReg( frA_addr ) );
10169c6bbd470e9bd9898b84959227a406d3972d95f3bsewardj   assign( frB, getDReg( frB_addr ) );
10170e14bb9f862843c6b804097c124961b5567ded4f1sewardj
10171c6bbd470e9bd9898b84959227a406d3972d95f3bsewardj   switch (opc2) {
10172c6bbd470e9bd9898b84959227a406d3972d95f3bsewardj   case 0x2: // dadd
10173c6bbd470e9bd9898b84959227a406d3972d95f3bsewardj      DIP( "dadd%s fr%u,fr%u,fr%u\n",
10174c6bbd470e9bd9898b84959227a406d3972d95f3bsewardj           flag_rC ? ".":"", frS_addr, frA_addr, frB_addr );
10175c6bbd470e9bd9898b84959227a406d3972d95f3bsewardj      assign( frS, triop( Iop_AddD64, round, mkexpr( frA ), mkexpr( frB ) ) );
10176c6bbd470e9bd9898b84959227a406d3972d95f3bsewardj      break;
10177c6bbd470e9bd9898b84959227a406d3972d95f3bsewardj   case 0x202: // dsub
10178c6bbd470e9bd9898b84959227a406d3972d95f3bsewardj      DIP( "dsub%s fr%u,fr%u,fr%u\n",
10179c6bbd470e9bd9898b84959227a406d3972d95f3bsewardj           flag_rC ? ".":"", frS_addr, frA_addr, frB_addr );
10180c6bbd470e9bd9898b84959227a406d3972d95f3bsewardj      assign( frS, triop( Iop_SubD64, round, mkexpr( frA ), mkexpr( frB ) ) );
10181c6bbd470e9bd9898b84959227a406d3972d95f3bsewardj      break;
10182c6bbd470e9bd9898b84959227a406d3972d95f3bsewardj   case 0x22: // dmul
10183c6bbd470e9bd9898b84959227a406d3972d95f3bsewardj      DIP( "dmul%s fr%u,fr%u,fr%u\n",
10184c6bbd470e9bd9898b84959227a406d3972d95f3bsewardj           flag_rC ? ".":"", frS_addr, frA_addr, frB_addr );
10185c6bbd470e9bd9898b84959227a406d3972d95f3bsewardj      assign( frS, triop( Iop_MulD64, round, mkexpr( frA ), mkexpr( frB ) ) );
10186c6bbd470e9bd9898b84959227a406d3972d95f3bsewardj      break;
10187c6bbd470e9bd9898b84959227a406d3972d95f3bsewardj   case 0x222: // ddiv
10188c6bbd470e9bd9898b84959227a406d3972d95f3bsewardj      DIP( "ddiv%s fr%u,fr%u,fr%u\n",
10189c6bbd470e9bd9898b84959227a406d3972d95f3bsewardj           flag_rC ? ".":"", frS_addr, frA_addr, frB_addr );
10190c6bbd470e9bd9898b84959227a406d3972d95f3bsewardj      assign( frS, triop( Iop_DivD64, round, mkexpr( frA ), mkexpr( frB ) ) );
10191c6bbd470e9bd9898b84959227a406d3972d95f3bsewardj      break;
10192c6bbd470e9bd9898b84959227a406d3972d95f3bsewardj   }
10193c6bbd470e9bd9898b84959227a406d3972d95f3bsewardj
10194c6bbd470e9bd9898b84959227a406d3972d95f3bsewardj   putDReg( frS_addr, mkexpr( frS ) );
10195c6bbd470e9bd9898b84959227a406d3972d95f3bsewardj
10196c6bbd470e9bd9898b84959227a406d3972d95f3bsewardj   if (flag_rC && clear_CR1) {
10197c6bbd470e9bd9898b84959227a406d3972d95f3bsewardj      putCR321( 1, mkU8( 0 ) );
10198c6bbd470e9bd9898b84959227a406d3972d95f3bsewardj      putCR0( 1, mkU8( 0 ) );
10199c6bbd470e9bd9898b84959227a406d3972d95f3bsewardj   }
10200c6bbd470e9bd9898b84959227a406d3972d95f3bsewardj
10201c6bbd470e9bd9898b84959227a406d3972d95f3bsewardj   return True;
10202c6bbd470e9bd9898b84959227a406d3972d95f3bsewardj}
10203c6bbd470e9bd9898b84959227a406d3972d95f3bsewardj
10204c6bbd470e9bd9898b84959227a406d3972d95f3bsewardj/* Quad DFP Arithmetic instructions */
10205c6bbd470e9bd9898b84959227a406d3972d95f3bsewardjstatic Bool dis_dfp_arithq(UInt theInstr)
10206c6bbd470e9bd9898b84959227a406d3972d95f3bsewardj{
10207c6bbd470e9bd9898b84959227a406d3972d95f3bsewardj   UInt opc2 = ifieldOPClo10( theInstr );
10208c6bbd470e9bd9898b84959227a406d3972d95f3bsewardj   UChar frS_addr = ifieldRegDS( theInstr );
10209c6bbd470e9bd9898b84959227a406d3972d95f3bsewardj   UChar frA_addr = ifieldRegA( theInstr );
10210c6bbd470e9bd9898b84959227a406d3972d95f3bsewardj   UChar frB_addr = ifieldRegB( theInstr );
10211c6bbd470e9bd9898b84959227a406d3972d95f3bsewardj   UChar flag_rC = ifieldBIT0( theInstr );
10212c6bbd470e9bd9898b84959227a406d3972d95f3bsewardj
10213c6bbd470e9bd9898b84959227a406d3972d95f3bsewardj   IRTemp frA = newTemp( Ity_D128 );
10214c6bbd470e9bd9898b84959227a406d3972d95f3bsewardj   IRTemp frB = newTemp( Ity_D128 );
10215c6bbd470e9bd9898b84959227a406d3972d95f3bsewardj   IRTemp frS = newTemp( Ity_D128 );
10216c6bbd470e9bd9898b84959227a406d3972d95f3bsewardj   IRExpr* round = get_IR_roundingmode_DFP();
10217c6bbd470e9bd9898b84959227a406d3972d95f3bsewardj
10218c6bbd470e9bd9898b84959227a406d3972d95f3bsewardj   /* By default, if flag_RC is set, we will clear cr1 after the
10219c6bbd470e9bd9898b84959227a406d3972d95f3bsewardj    * operation.  In reality we should set cr1 to indicate the
10220c6bbd470e9bd9898b84959227a406d3972d95f3bsewardj    * exception status of the operation, but since we're not
10221c6bbd470e9bd9898b84959227a406d3972d95f3bsewardj    * simulating exceptions, the exception status will appear to be
10222c6bbd470e9bd9898b84959227a406d3972d95f3bsewardj    * zero.  Hence cr1 should be cleared if this is a . form insn.
10223c6bbd470e9bd9898b84959227a406d3972d95f3bsewardj    */
10224c6bbd470e9bd9898b84959227a406d3972d95f3bsewardj   Bool clear_CR1 = True;
10225c6bbd470e9bd9898b84959227a406d3972d95f3bsewardj
10226c6bbd470e9bd9898b84959227a406d3972d95f3bsewardj   assign( frA, getDReg_pair( frA_addr ) );
10227c6bbd470e9bd9898b84959227a406d3972d95f3bsewardj   assign( frB, getDReg_pair( frB_addr ) );
10228c6bbd470e9bd9898b84959227a406d3972d95f3bsewardj
10229c6bbd470e9bd9898b84959227a406d3972d95f3bsewardj   switch (opc2) {
10230c6bbd470e9bd9898b84959227a406d3972d95f3bsewardj   case 0x2: // daddq
10231c6bbd470e9bd9898b84959227a406d3972d95f3bsewardj      DIP( "daddq%s fr%u,fr%u,fr%u\n",
10232c6bbd470e9bd9898b84959227a406d3972d95f3bsewardj           flag_rC ? ".":"", frS_addr, frA_addr, frB_addr );
10233c6bbd470e9bd9898b84959227a406d3972d95f3bsewardj      assign( frS, triop( Iop_AddD128, round, mkexpr( frA ), mkexpr( frB ) ) );
10234c6bbd470e9bd9898b84959227a406d3972d95f3bsewardj      break;
10235c6bbd470e9bd9898b84959227a406d3972d95f3bsewardj   case 0x202: // dsubq
10236c6bbd470e9bd9898b84959227a406d3972d95f3bsewardj      DIP( "dsubq%s fr%u,fr%u,fr%u\n",
10237c6bbd470e9bd9898b84959227a406d3972d95f3bsewardj           flag_rC ? ".":"", frS_addr, frA_addr, frB_addr );
10238c6bbd470e9bd9898b84959227a406d3972d95f3bsewardj      assign( frS, triop( Iop_SubD128, round, mkexpr( frA ), mkexpr( frB ) ) );
10239c6bbd470e9bd9898b84959227a406d3972d95f3bsewardj      break;
10240c6bbd470e9bd9898b84959227a406d3972d95f3bsewardj   case 0x22: // dmulq
10241c6bbd470e9bd9898b84959227a406d3972d95f3bsewardj      DIP( "dmulq%s fr%u,fr%u,fr%u\n",
10242c6bbd470e9bd9898b84959227a406d3972d95f3bsewardj           flag_rC ? ".":"", frS_addr, frA_addr, frB_addr );
10243c6bbd470e9bd9898b84959227a406d3972d95f3bsewardj      assign( frS, triop( Iop_MulD128, round, mkexpr( frA ), mkexpr( frB ) ) );
10244c6bbd470e9bd9898b84959227a406d3972d95f3bsewardj      break;
10245c6bbd470e9bd9898b84959227a406d3972d95f3bsewardj   case 0x222: // ddivq
10246c6bbd470e9bd9898b84959227a406d3972d95f3bsewardj      DIP( "ddivq%s fr%u,fr%u,fr%u\n",
10247c6bbd470e9bd9898b84959227a406d3972d95f3bsewardj           flag_rC ? ".":"", frS_addr, frA_addr, frB_addr );
10248c6bbd470e9bd9898b84959227a406d3972d95f3bsewardj      assign( frS, triop( Iop_DivD128, round, mkexpr( frA ), mkexpr( frB ) ) );
10249c6bbd470e9bd9898b84959227a406d3972d95f3bsewardj      break;
10250c6bbd470e9bd9898b84959227a406d3972d95f3bsewardj   }
10251c6bbd470e9bd9898b84959227a406d3972d95f3bsewardj
10252c6bbd470e9bd9898b84959227a406d3972d95f3bsewardj   putDReg_pair( frS_addr, mkexpr( frS ) );
10253c6bbd470e9bd9898b84959227a406d3972d95f3bsewardj
10254c6bbd470e9bd9898b84959227a406d3972d95f3bsewardj   if (flag_rC && clear_CR1) {
10255c6bbd470e9bd9898b84959227a406d3972d95f3bsewardj      putCR321( 1, mkU8( 0 ) );
10256c6bbd470e9bd9898b84959227a406d3972d95f3bsewardj      putCR0( 1, mkU8( 0 ) );
10257c6bbd470e9bd9898b84959227a406d3972d95f3bsewardj   }
10258c6bbd470e9bd9898b84959227a406d3972d95f3bsewardj
10259c6bbd470e9bd9898b84959227a406d3972d95f3bsewardj   return True;
10260c6bbd470e9bd9898b84959227a406d3972d95f3bsewardj}
10261e14bb9f862843c6b804097c124961b5567ded4f1sewardj
1026226217b09205cc1801b842ba5ba8f0d83aabca1b4sewardj/* DFP 64-bit logical shift instructions  */
1026326217b09205cc1801b842ba5ba8f0d83aabca1b4sewardjstatic Bool dis_dfp_shift(UInt theInstr) {
1026426217b09205cc1801b842ba5ba8f0d83aabca1b4sewardj   UInt opc2       = ifieldOPClo9( theInstr );
1026526217b09205cc1801b842ba5ba8f0d83aabca1b4sewardj   UChar frS_addr  = ifieldRegDS( theInstr );
1026626217b09205cc1801b842ba5ba8f0d83aabca1b4sewardj   UChar frA_addr  = ifieldRegA( theInstr );
1026726217b09205cc1801b842ba5ba8f0d83aabca1b4sewardj   UChar shift_val = IFIELD(theInstr, 10, 6);
1026826217b09205cc1801b842ba5ba8f0d83aabca1b4sewardj   UChar flag_rC   = ifieldBIT0( theInstr );
1026926217b09205cc1801b842ba5ba8f0d83aabca1b4sewardj
1027026217b09205cc1801b842ba5ba8f0d83aabca1b4sewardj   IRTemp frA = newTemp( Ity_D64 );
1027126217b09205cc1801b842ba5ba8f0d83aabca1b4sewardj   IRTemp frS = newTemp( Ity_D64 );
1027226217b09205cc1801b842ba5ba8f0d83aabca1b4sewardj   Bool clear_CR1 = True;
1027326217b09205cc1801b842ba5ba8f0d83aabca1b4sewardj
1027426217b09205cc1801b842ba5ba8f0d83aabca1b4sewardj   assign( frA, getDReg( frA_addr ) );
1027526217b09205cc1801b842ba5ba8f0d83aabca1b4sewardj
1027626217b09205cc1801b842ba5ba8f0d83aabca1b4sewardj   switch (opc2) {
1027726217b09205cc1801b842ba5ba8f0d83aabca1b4sewardj   case 0x42: // dscli
1027826217b09205cc1801b842ba5ba8f0d83aabca1b4sewardj      DIP( "dscli%s fr%u,fr%u,%u\n",
1027926217b09205cc1801b842ba5ba8f0d83aabca1b4sewardj           flag_rC ? ".":"", frS_addr, frA_addr, shift_val );
1028026217b09205cc1801b842ba5ba8f0d83aabca1b4sewardj      assign( frS, binop( Iop_ShlD64, mkexpr( frA ), mkU8( shift_val ) ) );
1028126217b09205cc1801b842ba5ba8f0d83aabca1b4sewardj      break;
1028226217b09205cc1801b842ba5ba8f0d83aabca1b4sewardj   case 0x62: // dscri
1028326217b09205cc1801b842ba5ba8f0d83aabca1b4sewardj      DIP( "dscri%s fr%u,fr%u,%u\n",
1028426217b09205cc1801b842ba5ba8f0d83aabca1b4sewardj           flag_rC ? ".":"", frS_addr, frA_addr, shift_val );
1028526217b09205cc1801b842ba5ba8f0d83aabca1b4sewardj      assign( frS, binop( Iop_ShrD64, mkexpr( frA ), mkU8( shift_val ) ) );
1028626217b09205cc1801b842ba5ba8f0d83aabca1b4sewardj      break;
1028726217b09205cc1801b842ba5ba8f0d83aabca1b4sewardj   }
1028826217b09205cc1801b842ba5ba8f0d83aabca1b4sewardj
1028926217b09205cc1801b842ba5ba8f0d83aabca1b4sewardj   putDReg( frS_addr, mkexpr( frS ) );
1029026217b09205cc1801b842ba5ba8f0d83aabca1b4sewardj
1029126217b09205cc1801b842ba5ba8f0d83aabca1b4sewardj   if (flag_rC && clear_CR1) {
1029226217b09205cc1801b842ba5ba8f0d83aabca1b4sewardj      putCR321( 1, mkU8( 0 ) );
1029326217b09205cc1801b842ba5ba8f0d83aabca1b4sewardj      putCR0( 1, mkU8( 0 ) );
1029426217b09205cc1801b842ba5ba8f0d83aabca1b4sewardj   }
1029526217b09205cc1801b842ba5ba8f0d83aabca1b4sewardj
1029626217b09205cc1801b842ba5ba8f0d83aabca1b4sewardj   return True;
1029726217b09205cc1801b842ba5ba8f0d83aabca1b4sewardj}
1029826217b09205cc1801b842ba5ba8f0d83aabca1b4sewardj
1029926217b09205cc1801b842ba5ba8f0d83aabca1b4sewardj/* Quad DFP  logical shift instructions  */
1030026217b09205cc1801b842ba5ba8f0d83aabca1b4sewardjstatic Bool dis_dfp_shiftq(UInt theInstr) {
1030126217b09205cc1801b842ba5ba8f0d83aabca1b4sewardj   UInt opc2       = ifieldOPClo9( theInstr );
1030226217b09205cc1801b842ba5ba8f0d83aabca1b4sewardj   UChar frS_addr  = ifieldRegDS( theInstr );
1030326217b09205cc1801b842ba5ba8f0d83aabca1b4sewardj   UChar frA_addr  = ifieldRegA( theInstr );
1030426217b09205cc1801b842ba5ba8f0d83aabca1b4sewardj   UChar shift_val = IFIELD(theInstr, 10, 6);
1030526217b09205cc1801b842ba5ba8f0d83aabca1b4sewardj   UChar flag_rC   = ifieldBIT0( theInstr );
1030626217b09205cc1801b842ba5ba8f0d83aabca1b4sewardj
1030726217b09205cc1801b842ba5ba8f0d83aabca1b4sewardj   IRTemp frA = newTemp( Ity_D128 );
1030826217b09205cc1801b842ba5ba8f0d83aabca1b4sewardj   IRTemp frS = newTemp( Ity_D128 );
1030926217b09205cc1801b842ba5ba8f0d83aabca1b4sewardj   Bool clear_CR1 = True;
1031026217b09205cc1801b842ba5ba8f0d83aabca1b4sewardj
1031126217b09205cc1801b842ba5ba8f0d83aabca1b4sewardj   assign( frA, getDReg_pair( frA_addr ) );
1031226217b09205cc1801b842ba5ba8f0d83aabca1b4sewardj
1031326217b09205cc1801b842ba5ba8f0d83aabca1b4sewardj   switch (opc2) {
1031426217b09205cc1801b842ba5ba8f0d83aabca1b4sewardj   case 0x42: // dscliq
1031526217b09205cc1801b842ba5ba8f0d83aabca1b4sewardj      DIP( "dscliq%s fr%u,fr%u,%u\n",
1031626217b09205cc1801b842ba5ba8f0d83aabca1b4sewardj           flag_rC ? ".":"", frS_addr, frA_addr, shift_val );
1031726217b09205cc1801b842ba5ba8f0d83aabca1b4sewardj      assign( frS, binop( Iop_ShlD128, mkexpr( frA ), mkU8( shift_val ) ) );
1031826217b09205cc1801b842ba5ba8f0d83aabca1b4sewardj      break;
1031926217b09205cc1801b842ba5ba8f0d83aabca1b4sewardj   case 0x62: // dscriq
1032026217b09205cc1801b842ba5ba8f0d83aabca1b4sewardj      DIP( "dscriq%s fr%u,fr%u,%u\n",
1032126217b09205cc1801b842ba5ba8f0d83aabca1b4sewardj           flag_rC ? ".":"", frS_addr, frA_addr, shift_val );
1032226217b09205cc1801b842ba5ba8f0d83aabca1b4sewardj      assign( frS, binop( Iop_ShrD128, mkexpr( frA ), mkU8( shift_val ) ) );
1032326217b09205cc1801b842ba5ba8f0d83aabca1b4sewardj      break;
1032426217b09205cc1801b842ba5ba8f0d83aabca1b4sewardj   }
1032526217b09205cc1801b842ba5ba8f0d83aabca1b4sewardj
1032626217b09205cc1801b842ba5ba8f0d83aabca1b4sewardj   putDReg_pair( frS_addr, mkexpr( frS ) );
1032726217b09205cc1801b842ba5ba8f0d83aabca1b4sewardj
1032826217b09205cc1801b842ba5ba8f0d83aabca1b4sewardj   if (flag_rC && clear_CR1) {
1032926217b09205cc1801b842ba5ba8f0d83aabca1b4sewardj      putCR321( 1, mkU8( 0 ) );
1033026217b09205cc1801b842ba5ba8f0d83aabca1b4sewardj      putCR0( 1, mkU8( 0 ) );
1033126217b09205cc1801b842ba5ba8f0d83aabca1b4sewardj   }
1033226217b09205cc1801b842ba5ba8f0d83aabca1b4sewardj
1033326217b09205cc1801b842ba5ba8f0d83aabca1b4sewardj   return True;
1033426217b09205cc1801b842ba5ba8f0d83aabca1b4sewardj}
1033526217b09205cc1801b842ba5ba8f0d83aabca1b4sewardj
1033626217b09205cc1801b842ba5ba8f0d83aabca1b4sewardj/* DFP 64-bit format conversion instructions */
1033726217b09205cc1801b842ba5ba8f0d83aabca1b4sewardjstatic Bool dis_dfp_fmt_conv(UInt theInstr) {
1033826217b09205cc1801b842ba5ba8f0d83aabca1b4sewardj   UInt opc2      = ifieldOPClo10( theInstr );
1033926217b09205cc1801b842ba5ba8f0d83aabca1b4sewardj   UChar frS_addr = ifieldRegDS( theInstr );
1034026217b09205cc1801b842ba5ba8f0d83aabca1b4sewardj   UChar frB_addr = ifieldRegB( theInstr );
1034126217b09205cc1801b842ba5ba8f0d83aabca1b4sewardj   IRExpr* round  = get_IR_roundingmode_DFP();
1034226217b09205cc1801b842ba5ba8f0d83aabca1b4sewardj   UChar flag_rC  = ifieldBIT0( theInstr );
1034326217b09205cc1801b842ba5ba8f0d83aabca1b4sewardj   IRTemp frB;
1034426217b09205cc1801b842ba5ba8f0d83aabca1b4sewardj   IRTemp frS;
1034526217b09205cc1801b842ba5ba8f0d83aabca1b4sewardj   Bool clear_CR1 = True;
1034626217b09205cc1801b842ba5ba8f0d83aabca1b4sewardj
1034726217b09205cc1801b842ba5ba8f0d83aabca1b4sewardj   switch (opc2) {
1034826217b09205cc1801b842ba5ba8f0d83aabca1b4sewardj   case 0x102: //dctdp
1034926217b09205cc1801b842ba5ba8f0d83aabca1b4sewardj      DIP( "dctdp%s fr%u,fr%u\n",
1035026217b09205cc1801b842ba5ba8f0d83aabca1b4sewardj           flag_rC ? ".":"", frS_addr, frB_addr );
1035126217b09205cc1801b842ba5ba8f0d83aabca1b4sewardj
10352f704eb2bab3d06d983c850b0bcf243e178060f75carll      frB = newTemp( Ity_D32 );
1035326217b09205cc1801b842ba5ba8f0d83aabca1b4sewardj      frS = newTemp( Ity_D64 );
10354f704eb2bab3d06d983c850b0bcf243e178060f75carll      assign( frB, getDReg32( frB_addr ) );
1035526217b09205cc1801b842ba5ba8f0d83aabca1b4sewardj      assign( frS, unop( Iop_D32toD64, mkexpr( frB ) ) );
1035626217b09205cc1801b842ba5ba8f0d83aabca1b4sewardj      putDReg( frS_addr, mkexpr( frS ) );
1035726217b09205cc1801b842ba5ba8f0d83aabca1b4sewardj      break;
1035826217b09205cc1801b842ba5ba8f0d83aabca1b4sewardj   case 0x302: // drsp
1035926217b09205cc1801b842ba5ba8f0d83aabca1b4sewardj      DIP( "drsp%s fr%u,fr%u\n",
1036026217b09205cc1801b842ba5ba8f0d83aabca1b4sewardj           flag_rC ? ".":"", frS_addr, frB_addr );
1036126217b09205cc1801b842ba5ba8f0d83aabca1b4sewardj      frB = newTemp( Ity_D64 );
10362f704eb2bab3d06d983c850b0bcf243e178060f75carll      frS = newTemp( Ity_D32 );
1036326217b09205cc1801b842ba5ba8f0d83aabca1b4sewardj      assign( frB, getDReg( frB_addr ) );
1036426217b09205cc1801b842ba5ba8f0d83aabca1b4sewardj      assign( frS, binop( Iop_D64toD32, round, mkexpr( frB ) ) );
10365f704eb2bab3d06d983c850b0bcf243e178060f75carll      putDReg32( frS_addr, mkexpr( frS ) );
1036626217b09205cc1801b842ba5ba8f0d83aabca1b4sewardj      break;
1036726217b09205cc1801b842ba5ba8f0d83aabca1b4sewardj   case 0x122: // dctfix
10368cea07ccbe9aa9b5fd8e9b318471c6c74aa147acbcarll      {
10369cea07ccbe9aa9b5fd8e9b318471c6c74aa147acbcarll         IRTemp tmp = newTemp( Ity_I64 );
10370cea07ccbe9aa9b5fd8e9b318471c6c74aa147acbcarll
10371cea07ccbe9aa9b5fd8e9b318471c6c74aa147acbcarll         DIP( "dctfix%s fr%u,fr%u\n",
10372cea07ccbe9aa9b5fd8e9b318471c6c74aa147acbcarll              flag_rC ? ".":"", frS_addr, frB_addr );
10373cea07ccbe9aa9b5fd8e9b318471c6c74aa147acbcarll         frB = newTemp( Ity_D64 );
10374cea07ccbe9aa9b5fd8e9b318471c6c74aa147acbcarll         frS = newTemp( Ity_D64 );
10375cea07ccbe9aa9b5fd8e9b318471c6c74aa147acbcarll         assign( frB, getDReg( frB_addr ) );
10376cea07ccbe9aa9b5fd8e9b318471c6c74aa147acbcarll         assign( tmp, binop( Iop_D64toI64S, round, mkexpr( frB ) ) );
10377cea07ccbe9aa9b5fd8e9b318471c6c74aa147acbcarll         assign( frS, unop( Iop_ReinterpI64asD64, mkexpr( tmp ) ) );
10378cea07ccbe9aa9b5fd8e9b318471c6c74aa147acbcarll         putDReg( frS_addr, mkexpr( frS ) );
10379cea07ccbe9aa9b5fd8e9b318471c6c74aa147acbcarll      }
1038026217b09205cc1801b842ba5ba8f0d83aabca1b4sewardj      break;
1038126217b09205cc1801b842ba5ba8f0d83aabca1b4sewardj   case 0x322: // dcffix
1038226217b09205cc1801b842ba5ba8f0d83aabca1b4sewardj      DIP( "dcffix%s fr%u,fr%u\n",
1038326217b09205cc1801b842ba5ba8f0d83aabca1b4sewardj           flag_rC ? ".":"", frS_addr, frB_addr );
1038426217b09205cc1801b842ba5ba8f0d83aabca1b4sewardj      frB = newTemp( Ity_D64 );
1038526217b09205cc1801b842ba5ba8f0d83aabca1b4sewardj      frS = newTemp( Ity_D64 );
1038626217b09205cc1801b842ba5ba8f0d83aabca1b4sewardj      assign( frB, getDReg( frB_addr ) );
10387cea07ccbe9aa9b5fd8e9b318471c6c74aa147acbcarll      assign( frS, binop( Iop_I64StoD64,
10388cea07ccbe9aa9b5fd8e9b318471c6c74aa147acbcarll                          round,
10389cea07ccbe9aa9b5fd8e9b318471c6c74aa147acbcarll                          unop( Iop_ReinterpD64asI64, mkexpr( frB ) ) ) );
1039026217b09205cc1801b842ba5ba8f0d83aabca1b4sewardj      putDReg( frS_addr, mkexpr( frS ) );
1039126217b09205cc1801b842ba5ba8f0d83aabca1b4sewardj      break;
1039226217b09205cc1801b842ba5ba8f0d83aabca1b4sewardj   }
1039326217b09205cc1801b842ba5ba8f0d83aabca1b4sewardj
1039426217b09205cc1801b842ba5ba8f0d83aabca1b4sewardj   if (flag_rC && clear_CR1) {
1039526217b09205cc1801b842ba5ba8f0d83aabca1b4sewardj      putCR321( 1, mkU8( 0 ) );
1039626217b09205cc1801b842ba5ba8f0d83aabca1b4sewardj      putCR0( 1, mkU8( 0 ) );
1039726217b09205cc1801b842ba5ba8f0d83aabca1b4sewardj   }
1039826217b09205cc1801b842ba5ba8f0d83aabca1b4sewardj
1039926217b09205cc1801b842ba5ba8f0d83aabca1b4sewardj   return True;
1040026217b09205cc1801b842ba5ba8f0d83aabca1b4sewardj}
1040126217b09205cc1801b842ba5ba8f0d83aabca1b4sewardj
1040226217b09205cc1801b842ba5ba8f0d83aabca1b4sewardj/* Quad DFP format conversion instructions */
1040326217b09205cc1801b842ba5ba8f0d83aabca1b4sewardjstatic Bool dis_dfp_fmt_convq(UInt theInstr) {
1040426217b09205cc1801b842ba5ba8f0d83aabca1b4sewardj   UInt opc2      = ifieldOPClo10( theInstr );
1040526217b09205cc1801b842ba5ba8f0d83aabca1b4sewardj   UChar frS_addr = ifieldRegDS( theInstr );
1040626217b09205cc1801b842ba5ba8f0d83aabca1b4sewardj   UChar frB_addr = ifieldRegB( theInstr );
1040726217b09205cc1801b842ba5ba8f0d83aabca1b4sewardj   IRExpr* round  = get_IR_roundingmode_DFP();
1040826217b09205cc1801b842ba5ba8f0d83aabca1b4sewardj   IRTemp frB64   = newTemp( Ity_D64 );
1040926217b09205cc1801b842ba5ba8f0d83aabca1b4sewardj   IRTemp frB128  = newTemp( Ity_D128 );
1041026217b09205cc1801b842ba5ba8f0d83aabca1b4sewardj   IRTemp frS64   = newTemp( Ity_D64 );
1041126217b09205cc1801b842ba5ba8f0d83aabca1b4sewardj   IRTemp frS128  = newTemp( Ity_D128 );
1041226217b09205cc1801b842ba5ba8f0d83aabca1b4sewardj   UChar flag_rC  = ifieldBIT0( theInstr );
1041326217b09205cc1801b842ba5ba8f0d83aabca1b4sewardj   Bool clear_CR1 = True;
1041426217b09205cc1801b842ba5ba8f0d83aabca1b4sewardj
1041526217b09205cc1801b842ba5ba8f0d83aabca1b4sewardj   switch (opc2) {
1041626217b09205cc1801b842ba5ba8f0d83aabca1b4sewardj   case 0x102: // dctqpq
1041726217b09205cc1801b842ba5ba8f0d83aabca1b4sewardj      DIP( "dctqpq%s fr%u,fr%u\n",
1041826217b09205cc1801b842ba5ba8f0d83aabca1b4sewardj           flag_rC ? ".":"", frS_addr, frB_addr );
1041926217b09205cc1801b842ba5ba8f0d83aabca1b4sewardj      assign( frB64, getDReg( frB_addr ) );
1042026217b09205cc1801b842ba5ba8f0d83aabca1b4sewardj      assign( frS128, unop( Iop_D64toD128, mkexpr( frB64 ) ) );
1042126217b09205cc1801b842ba5ba8f0d83aabca1b4sewardj      putDReg_pair( frS_addr, mkexpr( frS128 ) );
1042226217b09205cc1801b842ba5ba8f0d83aabca1b4sewardj      break;
1042326217b09205cc1801b842ba5ba8f0d83aabca1b4sewardj   case 0x122: // dctfixq
10424cea07ccbe9aa9b5fd8e9b318471c6c74aa147acbcarll      {
10425cea07ccbe9aa9b5fd8e9b318471c6c74aa147acbcarll         IRTemp tmp = newTemp( Ity_I64 );
10426cea07ccbe9aa9b5fd8e9b318471c6c74aa147acbcarll
10427cea07ccbe9aa9b5fd8e9b318471c6c74aa147acbcarll         DIP( "dctfixq%s fr%u,fr%u\n",
10428cea07ccbe9aa9b5fd8e9b318471c6c74aa147acbcarll              flag_rC ? ".":"", frS_addr, frB_addr );
10429cea07ccbe9aa9b5fd8e9b318471c6c74aa147acbcarll         assign( frB128, getDReg_pair( frB_addr ) );
10430cea07ccbe9aa9b5fd8e9b318471c6c74aa147acbcarll         assign( tmp, binop( Iop_D128toI64S, round, mkexpr( frB128 ) ) );
10431cea07ccbe9aa9b5fd8e9b318471c6c74aa147acbcarll         assign( frS64, unop( Iop_ReinterpI64asD64, mkexpr( tmp ) ) );
10432cea07ccbe9aa9b5fd8e9b318471c6c74aa147acbcarll         putDReg( frS_addr, mkexpr( frS64 ) );
10433cea07ccbe9aa9b5fd8e9b318471c6c74aa147acbcarll      }
1043426217b09205cc1801b842ba5ba8f0d83aabca1b4sewardj      break;
1043526217b09205cc1801b842ba5ba8f0d83aabca1b4sewardj   case 0x302: //drdpq
1043626217b09205cc1801b842ba5ba8f0d83aabca1b4sewardj      DIP( "drdpq%s fr%u,fr%u\n",
1043726217b09205cc1801b842ba5ba8f0d83aabca1b4sewardj           flag_rC ? ".":"", frS_addr, frB_addr );
1043826217b09205cc1801b842ba5ba8f0d83aabca1b4sewardj      assign( frB128, getDReg_pair( frB_addr ) );
1043926217b09205cc1801b842ba5ba8f0d83aabca1b4sewardj      assign( frS64, binop( Iop_D128toD64, round, mkexpr( frB128 ) ) );
1044026217b09205cc1801b842ba5ba8f0d83aabca1b4sewardj      putDReg( frS_addr, mkexpr( frS64 ) );
1044126217b09205cc1801b842ba5ba8f0d83aabca1b4sewardj      break;
1044226217b09205cc1801b842ba5ba8f0d83aabca1b4sewardj   case 0x322: // dcffixq
10443cea07ccbe9aa9b5fd8e9b318471c6c74aa147acbcarll     {
1044426217b09205cc1801b842ba5ba8f0d83aabca1b4sewardj      /* Have to introduce an IOP for this instruction so it will work
1044526217b09205cc1801b842ba5ba8f0d83aabca1b4sewardj       * on POWER 6 because emulating the instruction requires a POWER 7
1044626217b09205cc1801b842ba5ba8f0d83aabca1b4sewardj       * DFP instruction in the emulation code.
1044726217b09205cc1801b842ba5ba8f0d83aabca1b4sewardj       */
1044826217b09205cc1801b842ba5ba8f0d83aabca1b4sewardj      DIP( "dcffixq%s fr%u,fr%u\n",
1044926217b09205cc1801b842ba5ba8f0d83aabca1b4sewardj           flag_rC ? ".":"", frS_addr, frB_addr );
1045026217b09205cc1801b842ba5ba8f0d83aabca1b4sewardj      assign( frB64, getDReg( frB_addr ) );
10451cea07ccbe9aa9b5fd8e9b318471c6c74aa147acbcarll      assign( frS128, unop( Iop_I64StoD128,
10452cea07ccbe9aa9b5fd8e9b318471c6c74aa147acbcarll                            unop( Iop_ReinterpD64asI64,
10453cea07ccbe9aa9b5fd8e9b318471c6c74aa147acbcarll                                  mkexpr( frB64 ) ) ) );
1045426217b09205cc1801b842ba5ba8f0d83aabca1b4sewardj      putDReg_pair( frS_addr, mkexpr( frS128 ) );
1045526217b09205cc1801b842ba5ba8f0d83aabca1b4sewardj      break;
10456cea07ccbe9aa9b5fd8e9b318471c6c74aa147acbcarll     }
1045726217b09205cc1801b842ba5ba8f0d83aabca1b4sewardj   }
1045826217b09205cc1801b842ba5ba8f0d83aabca1b4sewardj
1045926217b09205cc1801b842ba5ba8f0d83aabca1b4sewardj   if (flag_rC && clear_CR1) {
1046026217b09205cc1801b842ba5ba8f0d83aabca1b4sewardj      putCR321( 1, mkU8( 0 ) );
1046126217b09205cc1801b842ba5ba8f0d83aabca1b4sewardj      putCR0( 1, mkU8( 0 ) );
1046226217b09205cc1801b842ba5ba8f0d83aabca1b4sewardj   }
1046326217b09205cc1801b842ba5ba8f0d83aabca1b4sewardj
1046426217b09205cc1801b842ba5ba8f0d83aabca1b4sewardj   return True;
1046526217b09205cc1801b842ba5ba8f0d83aabca1b4sewardj}
1046626217b09205cc1801b842ba5ba8f0d83aabca1b4sewardj
10467cdc376dcb5a4560b0a35d4abcb2146c499756f0dsewardjstatic Bool dis_dfp_round( UInt theInstr ) {
10468cdc376dcb5a4560b0a35d4abcb2146c499756f0dsewardj   UChar frS_addr = ifieldRegDS(theInstr);
10469cdc376dcb5a4560b0a35d4abcb2146c499756f0dsewardj   UChar R        = IFIELD(theInstr, 16, 1);
10470cdc376dcb5a4560b0a35d4abcb2146c499756f0dsewardj   UChar RMC      = IFIELD(theInstr, 9, 2);
10471cdc376dcb5a4560b0a35d4abcb2146c499756f0dsewardj   UChar frB_addr = ifieldRegB( theInstr );
10472cdc376dcb5a4560b0a35d4abcb2146c499756f0dsewardj   UChar flag_rC  = ifieldBIT0( theInstr );
10473cdc376dcb5a4560b0a35d4abcb2146c499756f0dsewardj   IRTemp frB     = newTemp( Ity_D64 );
10474cdc376dcb5a4560b0a35d4abcb2146c499756f0dsewardj   IRTemp frS     = newTemp( Ity_D64 );
10475cdc376dcb5a4560b0a35d4abcb2146c499756f0dsewardj   UInt opc2      = ifieldOPClo8( theInstr );
10476cdc376dcb5a4560b0a35d4abcb2146c499756f0dsewardj   Bool clear_CR1 = True;
10477cdc376dcb5a4560b0a35d4abcb2146c499756f0dsewardj
10478cdc376dcb5a4560b0a35d4abcb2146c499756f0dsewardj   switch (opc2) {
10479cdc376dcb5a4560b0a35d4abcb2146c499756f0dsewardj   /* drintn, is the same as drintx.  The only difference is this
10480cdc376dcb5a4560b0a35d4abcb2146c499756f0dsewardj    * instruction does not generate an exception for an inexact operation.
10481cdc376dcb5a4560b0a35d4abcb2146c499756f0dsewardj    * Currently not supporting inexact exceptions.
10482cdc376dcb5a4560b0a35d4abcb2146c499756f0dsewardj    */
10483cdc376dcb5a4560b0a35d4abcb2146c499756f0dsewardj   case 0x63: // drintx
10484cdc376dcb5a4560b0a35d4abcb2146c499756f0dsewardj   case 0xE3: // drintn
10485cdc376dcb5a4560b0a35d4abcb2146c499756f0dsewardj      DIP( "drintx/drintn%s fr%u,fr%u\n",
10486cdc376dcb5a4560b0a35d4abcb2146c499756f0dsewardj           flag_rC ? ".":"", frS_addr, frB_addr );
10487cdc376dcb5a4560b0a35d4abcb2146c499756f0dsewardj
10488cea07ccbe9aa9b5fd8e9b318471c6c74aa147acbcarll      /* NOTE, this instruction takes a DFP value and rounds to the
10489cea07ccbe9aa9b5fd8e9b318471c6c74aa147acbcarll       * neares floating point integer value, i.e. fractional part
10490cea07ccbe9aa9b5fd8e9b318471c6c74aa147acbcarll       * is zero.  The result is a floating point number.
10491cea07ccbe9aa9b5fd8e9b318471c6c74aa147acbcarll       */
10492cdc376dcb5a4560b0a35d4abcb2146c499756f0dsewardj      /* pass the value of R and RMC in the same field */
10493cdc376dcb5a4560b0a35d4abcb2146c499756f0dsewardj      assign( frB, getDReg( frB_addr ) );
10494cdc376dcb5a4560b0a35d4abcb2146c499756f0dsewardj      assign( frS, binop( Iop_RoundD64toInt,
10495cdc376dcb5a4560b0a35d4abcb2146c499756f0dsewardj                          mkU32( ( R << 3 ) | RMC ),
10496cdc376dcb5a4560b0a35d4abcb2146c499756f0dsewardj                          mkexpr( frB ) ) );
10497cdc376dcb5a4560b0a35d4abcb2146c499756f0dsewardj      putDReg( frS_addr, mkexpr( frS ) );
10498cdc376dcb5a4560b0a35d4abcb2146c499756f0dsewardj      break;
10499cdc376dcb5a4560b0a35d4abcb2146c499756f0dsewardj   default:
10500cdc376dcb5a4560b0a35d4abcb2146c499756f0dsewardj      vex_printf("dis_dfp_round(ppc)(opc2)\n");
10501cdc376dcb5a4560b0a35d4abcb2146c499756f0dsewardj      return False;
10502cdc376dcb5a4560b0a35d4abcb2146c499756f0dsewardj   }
10503cdc376dcb5a4560b0a35d4abcb2146c499756f0dsewardj
10504cdc376dcb5a4560b0a35d4abcb2146c499756f0dsewardj   if (flag_rC && clear_CR1) {
10505cdc376dcb5a4560b0a35d4abcb2146c499756f0dsewardj      putCR321( 1, mkU8( 0 ) );
10506cdc376dcb5a4560b0a35d4abcb2146c499756f0dsewardj      putCR0( 1, mkU8( 0 ) );
10507cdc376dcb5a4560b0a35d4abcb2146c499756f0dsewardj   }
10508cdc376dcb5a4560b0a35d4abcb2146c499756f0dsewardj
10509cdc376dcb5a4560b0a35d4abcb2146c499756f0dsewardj   return True;
10510cdc376dcb5a4560b0a35d4abcb2146c499756f0dsewardj}
10511cdc376dcb5a4560b0a35d4abcb2146c499756f0dsewardj
10512cdc376dcb5a4560b0a35d4abcb2146c499756f0dsewardjstatic Bool dis_dfp_roundq(UInt theInstr) {
10513cdc376dcb5a4560b0a35d4abcb2146c499756f0dsewardj   UChar frS_addr = ifieldRegDS( theInstr );
10514cdc376dcb5a4560b0a35d4abcb2146c499756f0dsewardj   UChar frB_addr = ifieldRegB( theInstr );
10515cdc376dcb5a4560b0a35d4abcb2146c499756f0dsewardj   UChar R = IFIELD(theInstr, 16, 1);
10516cdc376dcb5a4560b0a35d4abcb2146c499756f0dsewardj   UChar RMC = IFIELD(theInstr, 9, 2);
10517cdc376dcb5a4560b0a35d4abcb2146c499756f0dsewardj   UChar flag_rC = ifieldBIT0( theInstr );
10518cdc376dcb5a4560b0a35d4abcb2146c499756f0dsewardj   IRTemp frB = newTemp( Ity_D128 );
10519cdc376dcb5a4560b0a35d4abcb2146c499756f0dsewardj   IRTemp frS = newTemp( Ity_D128 );
10520cdc376dcb5a4560b0a35d4abcb2146c499756f0dsewardj   Bool clear_CR1 = True;
10521cdc376dcb5a4560b0a35d4abcb2146c499756f0dsewardj   UInt opc2 = ifieldOPClo8( theInstr );
10522cdc376dcb5a4560b0a35d4abcb2146c499756f0dsewardj
10523cdc376dcb5a4560b0a35d4abcb2146c499756f0dsewardj   switch (opc2) {
10524cdc376dcb5a4560b0a35d4abcb2146c499756f0dsewardj   /* drintnq, is the same as drintxq.  The only difference is this
10525cdc376dcb5a4560b0a35d4abcb2146c499756f0dsewardj    * instruction does not generate an exception for an inexact operation.
10526cdc376dcb5a4560b0a35d4abcb2146c499756f0dsewardj    * Currently not supporting inexact exceptions.
10527cdc376dcb5a4560b0a35d4abcb2146c499756f0dsewardj    */
10528cdc376dcb5a4560b0a35d4abcb2146c499756f0dsewardj   case 0x63: // drintxq
10529cdc376dcb5a4560b0a35d4abcb2146c499756f0dsewardj   case 0xE3: // drintnq
10530cdc376dcb5a4560b0a35d4abcb2146c499756f0dsewardj      DIP( "drintxq/drintnq%s fr%u,fr%u\n",
10531cdc376dcb5a4560b0a35d4abcb2146c499756f0dsewardj           flag_rC ? ".":"", frS_addr, frB_addr );
10532cdc376dcb5a4560b0a35d4abcb2146c499756f0dsewardj
10533cdc376dcb5a4560b0a35d4abcb2146c499756f0dsewardj      /* pass the value of R and RMC in the same field */
10534cdc376dcb5a4560b0a35d4abcb2146c499756f0dsewardj      assign( frB, getDReg_pair( frB_addr ) );
10535cdc376dcb5a4560b0a35d4abcb2146c499756f0dsewardj      assign( frS, binop( Iop_RoundD128toInt,
10536cdc376dcb5a4560b0a35d4abcb2146c499756f0dsewardj                          mkU32( ( R << 3 ) | RMC ),
10537cdc376dcb5a4560b0a35d4abcb2146c499756f0dsewardj                          mkexpr( frB ) ) );
10538cdc376dcb5a4560b0a35d4abcb2146c499756f0dsewardj      putDReg_pair( frS_addr, mkexpr( frS ) );
10539cdc376dcb5a4560b0a35d4abcb2146c499756f0dsewardj      break;
10540cdc376dcb5a4560b0a35d4abcb2146c499756f0dsewardj   default:
10541cdc376dcb5a4560b0a35d4abcb2146c499756f0dsewardj      vex_printf("dis_dfp_roundq(ppc)(opc2)\n");
10542cdc376dcb5a4560b0a35d4abcb2146c499756f0dsewardj      return False;
10543cdc376dcb5a4560b0a35d4abcb2146c499756f0dsewardj   }
10544cdc376dcb5a4560b0a35d4abcb2146c499756f0dsewardj
10545cdc376dcb5a4560b0a35d4abcb2146c499756f0dsewardj   if (flag_rC && clear_CR1) {
10546cdc376dcb5a4560b0a35d4abcb2146c499756f0dsewardj      putCR321( 1, mkU8( 0 ) );
10547cdc376dcb5a4560b0a35d4abcb2146c499756f0dsewardj      putCR0( 1, mkU8( 0 ) );
10548cdc376dcb5a4560b0a35d4abcb2146c499756f0dsewardj   }
10549cdc376dcb5a4560b0a35d4abcb2146c499756f0dsewardj
10550cdc376dcb5a4560b0a35d4abcb2146c499756f0dsewardj   return True;
10551cdc376dcb5a4560b0a35d4abcb2146c499756f0dsewardj}
10552cdc376dcb5a4560b0a35d4abcb2146c499756f0dsewardj
10553cdc376dcb5a4560b0a35d4abcb2146c499756f0dsewardjstatic Bool dis_dfp_quantize_sig_rrnd(UInt theInstr) {
10554cdc376dcb5a4560b0a35d4abcb2146c499756f0dsewardj   UInt opc2 = ifieldOPClo8( theInstr );
10555cdc376dcb5a4560b0a35d4abcb2146c499756f0dsewardj   UChar frS_addr = ifieldRegDS( theInstr );
10556cdc376dcb5a4560b0a35d4abcb2146c499756f0dsewardj   UChar frA_addr = ifieldRegA( theInstr );
10557cdc376dcb5a4560b0a35d4abcb2146c499756f0dsewardj   UChar frB_addr = ifieldRegB( theInstr );
10558cdc376dcb5a4560b0a35d4abcb2146c499756f0dsewardj   UChar flag_rC = ifieldBIT0( theInstr );
10559cdc376dcb5a4560b0a35d4abcb2146c499756f0dsewardj   UInt TE_value = IFIELD(theInstr, 16, 4);
10560cdc376dcb5a4560b0a35d4abcb2146c499756f0dsewardj   UInt TE_sign  = IFIELD(theInstr, 20, 1);
10561cdc376dcb5a4560b0a35d4abcb2146c499756f0dsewardj   UInt RMC = IFIELD(theInstr, 9, 2);
10562cdc376dcb5a4560b0a35d4abcb2146c499756f0dsewardj   IRTemp frA = newTemp( Ity_D64 );
10563cdc376dcb5a4560b0a35d4abcb2146c499756f0dsewardj   IRTemp frB = newTemp( Ity_D64 );
10564cdc376dcb5a4560b0a35d4abcb2146c499756f0dsewardj   IRTemp frS = newTemp( Ity_D64 );
10565cdc376dcb5a4560b0a35d4abcb2146c499756f0dsewardj   Bool clear_CR1 = True;
10566cdc376dcb5a4560b0a35d4abcb2146c499756f0dsewardj
10567cdc376dcb5a4560b0a35d4abcb2146c499756f0dsewardj   assign( frB, getDReg( frB_addr ) );
10568cdc376dcb5a4560b0a35d4abcb2146c499756f0dsewardj
10569cdc376dcb5a4560b0a35d4abcb2146c499756f0dsewardj   switch (opc2) {
10570cdc376dcb5a4560b0a35d4abcb2146c499756f0dsewardj   case 0x43: // dquai
10571cdc376dcb5a4560b0a35d4abcb2146c499756f0dsewardj      DIP( "dquai%s fr%u,fr%u,fr%u\n",
10572cdc376dcb5a4560b0a35d4abcb2146c499756f0dsewardj           flag_rC ? ".":"", frS_addr, frA_addr, frB_addr );
10573cea07ccbe9aa9b5fd8e9b318471c6c74aa147acbcarll      IRTemp TE_I64 = newTemp( Ity_I64 );
10574cdc376dcb5a4560b0a35d4abcb2146c499756f0dsewardj
10575cdc376dcb5a4560b0a35d4abcb2146c499756f0dsewardj      /* Generate a reference DFP value frA with the desired exponent
10576cdc376dcb5a4560b0a35d4abcb2146c499756f0dsewardj       * given by TE using significand from frB.  Need to add the bias
10577cdc376dcb5a4560b0a35d4abcb2146c499756f0dsewardj       * 398 to TE.  TE is stored as a 2's complement number.
10578cdc376dcb5a4560b0a35d4abcb2146c499756f0dsewardj       */
10579cdc376dcb5a4560b0a35d4abcb2146c499756f0dsewardj      if (TE_sign == 1) {
10580cdc376dcb5a4560b0a35d4abcb2146c499756f0dsewardj         /* Take 2's complement of the 5-bit value and subtract from bias.
10581cdc376dcb5a4560b0a35d4abcb2146c499756f0dsewardj          *  Bias is adjusted for the +1 required when taking 2's complement.
10582cdc376dcb5a4560b0a35d4abcb2146c499756f0dsewardj          */
10583cea07ccbe9aa9b5fd8e9b318471c6c74aa147acbcarll         assign( TE_I64,
10584cea07ccbe9aa9b5fd8e9b318471c6c74aa147acbcarll                 unop( Iop_32Uto64,
10585cea07ccbe9aa9b5fd8e9b318471c6c74aa147acbcarll                       binop( Iop_Sub32, mkU32( 397 ),
10586cea07ccbe9aa9b5fd8e9b318471c6c74aa147acbcarll                              binop( Iop_And32, mkU32( 0xF ),
10587cea07ccbe9aa9b5fd8e9b318471c6c74aa147acbcarll                                     unop( Iop_Not32, mkU32( TE_value ) )
10588cea07ccbe9aa9b5fd8e9b318471c6c74aa147acbcarll                                     ) ) ) );
10589cdc376dcb5a4560b0a35d4abcb2146c499756f0dsewardj
10590cdc376dcb5a4560b0a35d4abcb2146c499756f0dsewardj      } else {
10591cea07ccbe9aa9b5fd8e9b318471c6c74aa147acbcarll          assign( TE_I64,
10592cea07ccbe9aa9b5fd8e9b318471c6c74aa147acbcarll                  unop( Iop_32Uto64,
10593cea07ccbe9aa9b5fd8e9b318471c6c74aa147acbcarll                        binop( Iop_Add32, mkU32( 398 ), mkU32( TE_value ) )
10594cea07ccbe9aa9b5fd8e9b318471c6c74aa147acbcarll                        ) );
10595cdc376dcb5a4560b0a35d4abcb2146c499756f0dsewardj      }
10596cdc376dcb5a4560b0a35d4abcb2146c499756f0dsewardj
10597cea07ccbe9aa9b5fd8e9b318471c6c74aa147acbcarll      assign( frA, binop( Iop_InsertExpD64, mkexpr( TE_I64 ),
10598cdc376dcb5a4560b0a35d4abcb2146c499756f0dsewardj                          unop( Iop_ReinterpI64asD64, mkU64( 1 ) ) ) );
10599cdc376dcb5a4560b0a35d4abcb2146c499756f0dsewardj
10600cdc376dcb5a4560b0a35d4abcb2146c499756f0dsewardj      assign( frS, triop( Iop_QuantizeD64,
10601cdc376dcb5a4560b0a35d4abcb2146c499756f0dsewardj                          mkU32( RMC ),
10602cdc376dcb5a4560b0a35d4abcb2146c499756f0dsewardj                          mkexpr( frA ),
10603cdc376dcb5a4560b0a35d4abcb2146c499756f0dsewardj                          mkexpr( frB ) ) );
10604cdc376dcb5a4560b0a35d4abcb2146c499756f0dsewardj      break;
10605cdc376dcb5a4560b0a35d4abcb2146c499756f0dsewardj
10606cdc376dcb5a4560b0a35d4abcb2146c499756f0dsewardj   case 0x3: // dqua
10607cdc376dcb5a4560b0a35d4abcb2146c499756f0dsewardj      DIP( "dqua%s fr%u,fr%u,fr%u\n",
10608cdc376dcb5a4560b0a35d4abcb2146c499756f0dsewardj           flag_rC ? ".":"", frS_addr, frA_addr, frB_addr );
10609cdc376dcb5a4560b0a35d4abcb2146c499756f0dsewardj      assign( frA, getDReg( frA_addr ) );
10610cdc376dcb5a4560b0a35d4abcb2146c499756f0dsewardj      assign( frS, triop( Iop_QuantizeD64,
10611cdc376dcb5a4560b0a35d4abcb2146c499756f0dsewardj                          mkU32( RMC ),
10612cdc376dcb5a4560b0a35d4abcb2146c499756f0dsewardj                          mkexpr( frA ),
10613cdc376dcb5a4560b0a35d4abcb2146c499756f0dsewardj                          mkexpr( frB ) ) );
10614cdc376dcb5a4560b0a35d4abcb2146c499756f0dsewardj      break;
10615cdc376dcb5a4560b0a35d4abcb2146c499756f0dsewardj   case 0x23: // drrnd
10616cea07ccbe9aa9b5fd8e9b318471c6c74aa147acbcarll      {
10617cea07ccbe9aa9b5fd8e9b318471c6c74aa147acbcarll         IRTemp tmp = newTemp( Ity_I8 );
10618cea07ccbe9aa9b5fd8e9b318471c6c74aa147acbcarll
10619cea07ccbe9aa9b5fd8e9b318471c6c74aa147acbcarll         DIP( "drrnd%s fr%u,fr%u,fr%u\n",
10620cea07ccbe9aa9b5fd8e9b318471c6c74aa147acbcarll              flag_rC ? ".":"", frS_addr, frA_addr, frB_addr );
10621cea07ccbe9aa9b5fd8e9b318471c6c74aa147acbcarll         assign( frA, getDReg( frA_addr ) );
10622cea07ccbe9aa9b5fd8e9b318471c6c74aa147acbcarll         /* Iop_64to8 not supported in 32 bit mode, do it in two steps. */
10623cea07ccbe9aa9b5fd8e9b318471c6c74aa147acbcarll         assign( tmp, unop( Iop_32to8,
10624cea07ccbe9aa9b5fd8e9b318471c6c74aa147acbcarll                            unop( Iop_64to32,
10625cea07ccbe9aa9b5fd8e9b318471c6c74aa147acbcarll                                  unop( Iop_ReinterpD64asI64,
10626cea07ccbe9aa9b5fd8e9b318471c6c74aa147acbcarll                                        mkexpr( frA ) ) ) ) );
10627cea07ccbe9aa9b5fd8e9b318471c6c74aa147acbcarll         assign( frS, triop( Iop_SignificanceRoundD64,
10628cea07ccbe9aa9b5fd8e9b318471c6c74aa147acbcarll                             mkU32( RMC ),
10629cea07ccbe9aa9b5fd8e9b318471c6c74aa147acbcarll                             mkexpr( tmp ),
10630cea07ccbe9aa9b5fd8e9b318471c6c74aa147acbcarll                             mkexpr( frB ) ) );
10631cea07ccbe9aa9b5fd8e9b318471c6c74aa147acbcarll      }
10632cdc376dcb5a4560b0a35d4abcb2146c499756f0dsewardj      break;
10633cdc376dcb5a4560b0a35d4abcb2146c499756f0dsewardj   default:
10634cdc376dcb5a4560b0a35d4abcb2146c499756f0dsewardj      vex_printf("dis_dfp_quantize_sig_rrnd(ppc)(opc2)\n");
10635cdc376dcb5a4560b0a35d4abcb2146c499756f0dsewardj      return False;
10636cdc376dcb5a4560b0a35d4abcb2146c499756f0dsewardj   }
10637cdc376dcb5a4560b0a35d4abcb2146c499756f0dsewardj   putDReg( frS_addr, mkexpr( frS ) );
10638cdc376dcb5a4560b0a35d4abcb2146c499756f0dsewardj
10639cdc376dcb5a4560b0a35d4abcb2146c499756f0dsewardj   if (flag_rC && clear_CR1) {
10640cdc376dcb5a4560b0a35d4abcb2146c499756f0dsewardj      putCR321( 1, mkU8( 0 ) );
10641cdc376dcb5a4560b0a35d4abcb2146c499756f0dsewardj      putCR0( 1, mkU8( 0 ) );
10642cdc376dcb5a4560b0a35d4abcb2146c499756f0dsewardj   }
10643cdc376dcb5a4560b0a35d4abcb2146c499756f0dsewardj
10644cdc376dcb5a4560b0a35d4abcb2146c499756f0dsewardj   return True;
10645cdc376dcb5a4560b0a35d4abcb2146c499756f0dsewardj}
10646cdc376dcb5a4560b0a35d4abcb2146c499756f0dsewardj
10647cdc376dcb5a4560b0a35d4abcb2146c499756f0dsewardjstatic Bool dis_dfp_quantize_sig_rrndq(UInt theInstr) {
10648cdc376dcb5a4560b0a35d4abcb2146c499756f0dsewardj   UInt opc2 = ifieldOPClo8( theInstr );
10649cdc376dcb5a4560b0a35d4abcb2146c499756f0dsewardj   UChar frS_addr = ifieldRegDS( theInstr );
10650cdc376dcb5a4560b0a35d4abcb2146c499756f0dsewardj   UChar frA_addr = ifieldRegA( theInstr );
10651cdc376dcb5a4560b0a35d4abcb2146c499756f0dsewardj   UChar frB_addr = ifieldRegB( theInstr );
10652cdc376dcb5a4560b0a35d4abcb2146c499756f0dsewardj   UChar flag_rC = ifieldBIT0( theInstr );
10653cdc376dcb5a4560b0a35d4abcb2146c499756f0dsewardj   UInt TE_value = IFIELD(theInstr, 16, 4);
10654cdc376dcb5a4560b0a35d4abcb2146c499756f0dsewardj   UInt TE_sign  = IFIELD(theInstr, 20, 1);
10655cdc376dcb5a4560b0a35d4abcb2146c499756f0dsewardj   UInt RMC = IFIELD(theInstr, 9, 2);
10656cdc376dcb5a4560b0a35d4abcb2146c499756f0dsewardj   IRTemp frA = newTemp( Ity_D128 );
10657cdc376dcb5a4560b0a35d4abcb2146c499756f0dsewardj   IRTemp frB = newTemp( Ity_D128 );
10658cdc376dcb5a4560b0a35d4abcb2146c499756f0dsewardj   IRTemp frS = newTemp( Ity_D128 );
10659cdc376dcb5a4560b0a35d4abcb2146c499756f0dsewardj   Bool clear_CR1 = True;
10660cdc376dcb5a4560b0a35d4abcb2146c499756f0dsewardj
10661cdc376dcb5a4560b0a35d4abcb2146c499756f0dsewardj   assign( frB, getDReg_pair( frB_addr ) );
10662cdc376dcb5a4560b0a35d4abcb2146c499756f0dsewardj
10663cdc376dcb5a4560b0a35d4abcb2146c499756f0dsewardj   switch (opc2) {
10664cdc376dcb5a4560b0a35d4abcb2146c499756f0dsewardj   case 0x43: // dquaiq
10665cdc376dcb5a4560b0a35d4abcb2146c499756f0dsewardj      DIP( "dquaiq%s fr%u,fr%u,fr%u\n",
10666cdc376dcb5a4560b0a35d4abcb2146c499756f0dsewardj           flag_rC ? ".":"", frS_addr, frA_addr, frB_addr );
10667cea07ccbe9aa9b5fd8e9b318471c6c74aa147acbcarll      IRTemp TE_I64 = newTemp( Ity_I64 );
10668cdc376dcb5a4560b0a35d4abcb2146c499756f0dsewardj
10669cdc376dcb5a4560b0a35d4abcb2146c499756f0dsewardj      /* Generate a reference DFP value frA with the desired exponent
10670cdc376dcb5a4560b0a35d4abcb2146c499756f0dsewardj       * given by TE using significand of 1.  Need to add the bias
10671cdc376dcb5a4560b0a35d4abcb2146c499756f0dsewardj       * 6176 to TE.
10672cdc376dcb5a4560b0a35d4abcb2146c499756f0dsewardj       */
10673cdc376dcb5a4560b0a35d4abcb2146c499756f0dsewardj      if (TE_sign == 1) {
10674cdc376dcb5a4560b0a35d4abcb2146c499756f0dsewardj         /* Take 2's complement of the 5-bit value and subtract from bias.
10675cdc376dcb5a4560b0a35d4abcb2146c499756f0dsewardj          *  Bias adjusted for the +1 required when taking 2's complement.
10676cdc376dcb5a4560b0a35d4abcb2146c499756f0dsewardj          */
10677cea07ccbe9aa9b5fd8e9b318471c6c74aa147acbcarll         assign( TE_I64,
10678cea07ccbe9aa9b5fd8e9b318471c6c74aa147acbcarll                 unop( Iop_32Uto64,
10679cea07ccbe9aa9b5fd8e9b318471c6c74aa147acbcarll                       binop( Iop_Sub32, mkU32( 6175 ),
10680cea07ccbe9aa9b5fd8e9b318471c6c74aa147acbcarll                              binop( Iop_And32, mkU32( 0xF ),
10681cea07ccbe9aa9b5fd8e9b318471c6c74aa147acbcarll                                     unop( Iop_Not32, mkU32( TE_value ) )
10682cea07ccbe9aa9b5fd8e9b318471c6c74aa147acbcarll                                     ) ) ) );
10683cdc376dcb5a4560b0a35d4abcb2146c499756f0dsewardj
10684cdc376dcb5a4560b0a35d4abcb2146c499756f0dsewardj      } else {
10685cea07ccbe9aa9b5fd8e9b318471c6c74aa147acbcarll         assign( TE_I64,
10686cea07ccbe9aa9b5fd8e9b318471c6c74aa147acbcarll                 unop( Iop_32Uto64,
10687cea07ccbe9aa9b5fd8e9b318471c6c74aa147acbcarll                       binop( Iop_Add32,
10688cea07ccbe9aa9b5fd8e9b318471c6c74aa147acbcarll                             mkU32( 6176 ),
10689cea07ccbe9aa9b5fd8e9b318471c6c74aa147acbcarll                             mkU32( TE_value ) ) ) );
10690cdc376dcb5a4560b0a35d4abcb2146c499756f0dsewardj      }
10691cdc376dcb5a4560b0a35d4abcb2146c499756f0dsewardj
10692cdc376dcb5a4560b0a35d4abcb2146c499756f0dsewardj      assign( frA,
10693cea07ccbe9aa9b5fd8e9b318471c6c74aa147acbcarll              binop( Iop_InsertExpD128, mkexpr( TE_I64 ),
10694cea07ccbe9aa9b5fd8e9b318471c6c74aa147acbcarll                     unop( Iop_D64toD128,
10695cdc376dcb5a4560b0a35d4abcb2146c499756f0dsewardj                           unop( Iop_ReinterpI64asD64, mkU64( 1 ) ) ) ) );
10696cdc376dcb5a4560b0a35d4abcb2146c499756f0dsewardj      assign( frS, triop( Iop_QuantizeD128,
10697cdc376dcb5a4560b0a35d4abcb2146c499756f0dsewardj                          mkU32( RMC ),
10698cdc376dcb5a4560b0a35d4abcb2146c499756f0dsewardj                          mkexpr( frA ),
10699cdc376dcb5a4560b0a35d4abcb2146c499756f0dsewardj                          mkexpr( frB ) ) );
10700cdc376dcb5a4560b0a35d4abcb2146c499756f0dsewardj      break;
10701cdc376dcb5a4560b0a35d4abcb2146c499756f0dsewardj   case 0x3: // dquaq
10702cdc376dcb5a4560b0a35d4abcb2146c499756f0dsewardj      DIP( "dquaiq%s fr%u,fr%u,fr%u\n",
10703cdc376dcb5a4560b0a35d4abcb2146c499756f0dsewardj           flag_rC ? ".":"", frS_addr, frA_addr, frB_addr );
10704cdc376dcb5a4560b0a35d4abcb2146c499756f0dsewardj      assign( frA, getDReg_pair( frA_addr ) );
10705cdc376dcb5a4560b0a35d4abcb2146c499756f0dsewardj      assign( frS, triop( Iop_QuantizeD128,
10706cdc376dcb5a4560b0a35d4abcb2146c499756f0dsewardj                          mkU32( RMC ),
10707cdc376dcb5a4560b0a35d4abcb2146c499756f0dsewardj                          mkexpr( frA ),
10708cdc376dcb5a4560b0a35d4abcb2146c499756f0dsewardj                          mkexpr( frB ) ) );
10709cdc376dcb5a4560b0a35d4abcb2146c499756f0dsewardj      break;
10710cdc376dcb5a4560b0a35d4abcb2146c499756f0dsewardj   case 0x23: // drrndq
10711cea07ccbe9aa9b5fd8e9b318471c6c74aa147acbcarll      {
10712cea07ccbe9aa9b5fd8e9b318471c6c74aa147acbcarll         IRTemp tmp = newTemp( Ity_I8 );
10713cea07ccbe9aa9b5fd8e9b318471c6c74aa147acbcarll
10714cea07ccbe9aa9b5fd8e9b318471c6c74aa147acbcarll         DIP( "drrndq%s fr%u,fr%u,fr%u\n",
10715cea07ccbe9aa9b5fd8e9b318471c6c74aa147acbcarll              flag_rC ? ".":"", frS_addr, frA_addr, frB_addr );
10716cea07ccbe9aa9b5fd8e9b318471c6c74aa147acbcarll         assign( frA, getDReg_pair( frA_addr ) );
10717cea07ccbe9aa9b5fd8e9b318471c6c74aa147acbcarll         assign( tmp, unop( Iop_32to8,
10718cea07ccbe9aa9b5fd8e9b318471c6c74aa147acbcarll                            unop( Iop_64to32,
10719cea07ccbe9aa9b5fd8e9b318471c6c74aa147acbcarll                                  unop( Iop_ReinterpD64asI64,
10720cea07ccbe9aa9b5fd8e9b318471c6c74aa147acbcarll                                        unop( Iop_D128HItoD64,
10721cea07ccbe9aa9b5fd8e9b318471c6c74aa147acbcarll                                              mkexpr( frA ) ) ) ) ) );
10722cea07ccbe9aa9b5fd8e9b318471c6c74aa147acbcarll         assign( frS, triop( Iop_SignificanceRoundD128,
10723cea07ccbe9aa9b5fd8e9b318471c6c74aa147acbcarll                             mkU32( RMC ),
10724cea07ccbe9aa9b5fd8e9b318471c6c74aa147acbcarll                             mkexpr( tmp ),
10725cea07ccbe9aa9b5fd8e9b318471c6c74aa147acbcarll                             mkexpr( frB ) ) );
10726cea07ccbe9aa9b5fd8e9b318471c6c74aa147acbcarll      }
10727cdc376dcb5a4560b0a35d4abcb2146c499756f0dsewardj      break;
10728cdc376dcb5a4560b0a35d4abcb2146c499756f0dsewardj   default:
10729cdc376dcb5a4560b0a35d4abcb2146c499756f0dsewardj      vex_printf("dis_dfp_quantize_sig_rrndq(ppc)(opc2)\n");
10730cdc376dcb5a4560b0a35d4abcb2146c499756f0dsewardj      return False;
10731cdc376dcb5a4560b0a35d4abcb2146c499756f0dsewardj   }
10732cdc376dcb5a4560b0a35d4abcb2146c499756f0dsewardj   putDReg_pair( frS_addr, mkexpr( frS ) );
10733cdc376dcb5a4560b0a35d4abcb2146c499756f0dsewardj
10734cdc376dcb5a4560b0a35d4abcb2146c499756f0dsewardj   if (flag_rC && clear_CR1) {
10735cdc376dcb5a4560b0a35d4abcb2146c499756f0dsewardj      putCR321( 1, mkU8( 0 ) );
10736cdc376dcb5a4560b0a35d4abcb2146c499756f0dsewardj      putCR0( 1, mkU8( 0 ) );
10737cdc376dcb5a4560b0a35d4abcb2146c499756f0dsewardj   }
10738cdc376dcb5a4560b0a35d4abcb2146c499756f0dsewardj
10739cdc376dcb5a4560b0a35d4abcb2146c499756f0dsewardj   return True;
10740cdc376dcb5a4560b0a35d4abcb2146c499756f0dsewardj}
10741cdc376dcb5a4560b0a35d4abcb2146c499756f0dsewardj
10742cdc376dcb5a4560b0a35d4abcb2146c499756f0dsewardjstatic Bool dis_dfp_extract_insert(UInt theInstr) {
10743cdc376dcb5a4560b0a35d4abcb2146c499756f0dsewardj   UInt opc2 = ifieldOPClo10( theInstr );
10744cdc376dcb5a4560b0a35d4abcb2146c499756f0dsewardj   UChar frS_addr = ifieldRegDS( theInstr );
10745cdc376dcb5a4560b0a35d4abcb2146c499756f0dsewardj   UChar frA_addr = ifieldRegA( theInstr );
10746cdc376dcb5a4560b0a35d4abcb2146c499756f0dsewardj   UChar frB_addr = ifieldRegB( theInstr );
10747cdc376dcb5a4560b0a35d4abcb2146c499756f0dsewardj   UChar flag_rC = ifieldBIT0( theInstr );
10748cdc376dcb5a4560b0a35d4abcb2146c499756f0dsewardj   Bool clear_CR1 = True;
10749cdc376dcb5a4560b0a35d4abcb2146c499756f0dsewardj
10750cdc376dcb5a4560b0a35d4abcb2146c499756f0dsewardj   IRTemp frA = newTemp( Ity_D64 );
10751cdc376dcb5a4560b0a35d4abcb2146c499756f0dsewardj   IRTemp frB = newTemp( Ity_D64 );
10752cdc376dcb5a4560b0a35d4abcb2146c499756f0dsewardj   IRTemp frS = newTemp( Ity_D64 );
10753cea07ccbe9aa9b5fd8e9b318471c6c74aa147acbcarll   IRTemp tmp = newTemp( Ity_I64 );
10754cdc376dcb5a4560b0a35d4abcb2146c499756f0dsewardj
10755cdc376dcb5a4560b0a35d4abcb2146c499756f0dsewardj   assign( frA, getDReg( frA_addr ) );
10756cdc376dcb5a4560b0a35d4abcb2146c499756f0dsewardj   assign( frB, getDReg( frB_addr ) );
10757cdc376dcb5a4560b0a35d4abcb2146c499756f0dsewardj
10758cdc376dcb5a4560b0a35d4abcb2146c499756f0dsewardj   switch (opc2) {
10759cdc376dcb5a4560b0a35d4abcb2146c499756f0dsewardj   case 0x162: // dxex
10760cdc376dcb5a4560b0a35d4abcb2146c499756f0dsewardj      DIP( "dxex%s fr%u,fr%u,fr%u\n",
10761cdc376dcb5a4560b0a35d4abcb2146c499756f0dsewardj           flag_rC ? ".":"", frS_addr, frA_addr, frB_addr );
10762cea07ccbe9aa9b5fd8e9b318471c6c74aa147acbcarll      assign( tmp, unop( Iop_ExtractExpD64, mkexpr( frB ) ) );
10763cea07ccbe9aa9b5fd8e9b318471c6c74aa147acbcarll      assign( frS, unop( Iop_ReinterpI64asD64, mkexpr( tmp ) ) );
10764cdc376dcb5a4560b0a35d4abcb2146c499756f0dsewardj      break;
10765cdc376dcb5a4560b0a35d4abcb2146c499756f0dsewardj   case 0x362: // diex
10766cdc376dcb5a4560b0a35d4abcb2146c499756f0dsewardj      DIP( "diex%s fr%u,fr%u,fr%u\n",
10767cdc376dcb5a4560b0a35d4abcb2146c499756f0dsewardj           flag_rC ? ".":"", frS_addr, frA_addr, frB_addr );
10768cea07ccbe9aa9b5fd8e9b318471c6c74aa147acbcarll      assign( frS, binop( Iop_InsertExpD64,
10769cea07ccbe9aa9b5fd8e9b318471c6c74aa147acbcarll                          unop( Iop_ReinterpD64asI64,
10770cea07ccbe9aa9b5fd8e9b318471c6c74aa147acbcarll                                mkexpr( frA ) ),
10771cea07ccbe9aa9b5fd8e9b318471c6c74aa147acbcarll                          mkexpr( frB ) ) );
10772cdc376dcb5a4560b0a35d4abcb2146c499756f0dsewardj      break;
10773cdc376dcb5a4560b0a35d4abcb2146c499756f0dsewardj   default:
10774cdc376dcb5a4560b0a35d4abcb2146c499756f0dsewardj      vex_printf("dis_dfp_extract_insert(ppc)(opc2)\n");
10775cdc376dcb5a4560b0a35d4abcb2146c499756f0dsewardj      return False;
10776cdc376dcb5a4560b0a35d4abcb2146c499756f0dsewardj   }
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_extract_insertq(UInt theInstr) {
10789cdc376dcb5a4560b0a35d4abcb2146c499756f0dsewardj   UInt opc2 = ifieldOPClo10( 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
10795cdc376dcb5a4560b0a35d4abcb2146c499756f0dsewardj   IRTemp frA   = newTemp( Ity_D64 );
10796cdc376dcb5a4560b0a35d4abcb2146c499756f0dsewardj   IRTemp frB   = newTemp( Ity_D128 );
10797cdc376dcb5a4560b0a35d4abcb2146c499756f0dsewardj   IRTemp frS64 = newTemp( Ity_D64 );
10798cdc376dcb5a4560b0a35d4abcb2146c499756f0dsewardj   IRTemp frS   = newTemp( Ity_D128 );
10799cea07ccbe9aa9b5fd8e9b318471c6c74aa147acbcarll   IRTemp tmp   = newTemp( Ity_I64 );
10800cdc376dcb5a4560b0a35d4abcb2146c499756f0dsewardj   Bool clear_CR1 = True;
10801cdc376dcb5a4560b0a35d4abcb2146c499756f0dsewardj
10802cdc376dcb5a4560b0a35d4abcb2146c499756f0dsewardj   assign( frB, getDReg_pair( frB_addr ) );
10803cdc376dcb5a4560b0a35d4abcb2146c499756f0dsewardj
10804cdc376dcb5a4560b0a35d4abcb2146c499756f0dsewardj   switch (opc2) {
10805cdc376dcb5a4560b0a35d4abcb2146c499756f0dsewardj   case 0x162:  // dxexq
10806cdc376dcb5a4560b0a35d4abcb2146c499756f0dsewardj      DIP( "dxexq%s fr%u,fr%u\n",
10807cdc376dcb5a4560b0a35d4abcb2146c499756f0dsewardj           flag_rC ? ".":"", frS_addr,  frB_addr );
10808cdc376dcb5a4560b0a35d4abcb2146c499756f0dsewardj      /* Instruction actually returns a 64-bit result.  So as to be
10809cdc376dcb5a4560b0a35d4abcb2146c499756f0dsewardj       * consistent and not have to add a new struct, the emulation returns
10810cdc376dcb5a4560b0a35d4abcb2146c499756f0dsewardj       * the 64-bit result in the upper and lower register.
10811cdc376dcb5a4560b0a35d4abcb2146c499756f0dsewardj       */
10812cea07ccbe9aa9b5fd8e9b318471c6c74aa147acbcarll      assign( tmp, unop( Iop_ExtractExpD128, mkexpr( frB ) ) );
10813cea07ccbe9aa9b5fd8e9b318471c6c74aa147acbcarll      assign( frS64, unop( Iop_ReinterpI64asD64, mkexpr( tmp ) ) );
10814cdc376dcb5a4560b0a35d4abcb2146c499756f0dsewardj      putDReg( frS_addr, mkexpr( frS64 ) );
10815cdc376dcb5a4560b0a35d4abcb2146c499756f0dsewardj      break;
10816cdc376dcb5a4560b0a35d4abcb2146c499756f0dsewardj   case 0x362:  // diexq
10817cdc376dcb5a4560b0a35d4abcb2146c499756f0dsewardj      DIP( "diexq%s fr%u,fr%u,fr%u\n",
10818cdc376dcb5a4560b0a35d4abcb2146c499756f0dsewardj           flag_rC ? ".":"", frS_addr, frA_addr, frB_addr );
10819cdc376dcb5a4560b0a35d4abcb2146c499756f0dsewardj      assign( frA, getDReg( frA_addr ) );
10820cea07ccbe9aa9b5fd8e9b318471c6c74aa147acbcarll      assign( frS, binop( Iop_InsertExpD128,
10821cea07ccbe9aa9b5fd8e9b318471c6c74aa147acbcarll                          unop( Iop_ReinterpD64asI64, mkexpr( frA ) ),
10822cea07ccbe9aa9b5fd8e9b318471c6c74aa147acbcarll                          mkexpr( frB ) ) );
10823cdc376dcb5a4560b0a35d4abcb2146c499756f0dsewardj      putDReg_pair( frS_addr, mkexpr( frS ) );
10824cdc376dcb5a4560b0a35d4abcb2146c499756f0dsewardj      break;
10825cdc376dcb5a4560b0a35d4abcb2146c499756f0dsewardj   default:
10826cdc376dcb5a4560b0a35d4abcb2146c499756f0dsewardj      vex_printf("dis_dfp_extract_insertq(ppc)(opc2)\n");
10827cdc376dcb5a4560b0a35d4abcb2146c499756f0dsewardj      return False;
10828cdc376dcb5a4560b0a35d4abcb2146c499756f0dsewardj   }
10829cdc376dcb5a4560b0a35d4abcb2146c499756f0dsewardj
10830cdc376dcb5a4560b0a35d4abcb2146c499756f0dsewardj   if (flag_rC && clear_CR1) {
10831cdc376dcb5a4560b0a35d4abcb2146c499756f0dsewardj      putCR321( 1, mkU8( 0 ) );
10832cdc376dcb5a4560b0a35d4abcb2146c499756f0dsewardj      putCR0( 1, mkU8( 0 ) );
10833cdc376dcb5a4560b0a35d4abcb2146c499756f0dsewardj   }
10834cdc376dcb5a4560b0a35d4abcb2146c499756f0dsewardj
10835cdc376dcb5a4560b0a35d4abcb2146c499756f0dsewardj   return True;
10836cdc376dcb5a4560b0a35d4abcb2146c499756f0dsewardj}
10837cdc376dcb5a4560b0a35d4abcb2146c499756f0dsewardj
10838cdc376dcb5a4560b0a35d4abcb2146c499756f0dsewardj/* DFP 64-bit comparison instructions */
10839cdc376dcb5a4560b0a35d4abcb2146c499756f0dsewardjstatic Bool dis_dfp_compare(UInt theInstr) {
10840cdc376dcb5a4560b0a35d4abcb2146c499756f0dsewardj   /* X-Form */
10841cdc376dcb5a4560b0a35d4abcb2146c499756f0dsewardj   UChar crfD = toUChar( IFIELD( theInstr, 23, 3 ) ); // AKA BF
10842cdc376dcb5a4560b0a35d4abcb2146c499756f0dsewardj   UChar frA_addr = ifieldRegA( theInstr );
10843cdc376dcb5a4560b0a35d4abcb2146c499756f0dsewardj   UChar frB_addr = ifieldRegB( theInstr );
10844cdc376dcb5a4560b0a35d4abcb2146c499756f0dsewardj   UInt opc1 = ifieldOPC( theInstr );
10845cdc376dcb5a4560b0a35d4abcb2146c499756f0dsewardj   IRTemp frA;
10846cdc376dcb5a4560b0a35d4abcb2146c499756f0dsewardj   IRTemp frB;
10847cdc376dcb5a4560b0a35d4abcb2146c499756f0dsewardj
10848cdc376dcb5a4560b0a35d4abcb2146c499756f0dsewardj   IRTemp ccIR = newTemp( Ity_I32 );
10849cdc376dcb5a4560b0a35d4abcb2146c499756f0dsewardj   IRTemp ccPPC32 = newTemp( Ity_I32 );
10850cdc376dcb5a4560b0a35d4abcb2146c499756f0dsewardj
10851cdc376dcb5a4560b0a35d4abcb2146c499756f0dsewardj
10852cdc376dcb5a4560b0a35d4abcb2146c499756f0dsewardj   /* Note: Differences between dcmpu and dcmpo are only in exception
10853cdc376dcb5a4560b0a35d4abcb2146c499756f0dsewardj    flag settings, which aren't supported anyway. */
10854cdc376dcb5a4560b0a35d4abcb2146c499756f0dsewardj   switch (opc1) {
10855cdc376dcb5a4560b0a35d4abcb2146c499756f0dsewardj   case 0x3B: /* dcmpo and dcmpu, DFP 64-bit */
10856cdc376dcb5a4560b0a35d4abcb2146c499756f0dsewardj      DIP( "dcmpo %u,fr%u,fr%u\n", crfD, frA_addr, frB_addr );
10857cdc376dcb5a4560b0a35d4abcb2146c499756f0dsewardj      frA = newTemp( Ity_D64 );
10858cdc376dcb5a4560b0a35d4abcb2146c499756f0dsewardj      frB = newTemp( Ity_D64 );
10859cdc376dcb5a4560b0a35d4abcb2146c499756f0dsewardj
10860cdc376dcb5a4560b0a35d4abcb2146c499756f0dsewardj      assign( frA, getDReg( frA_addr ) );
10861cdc376dcb5a4560b0a35d4abcb2146c499756f0dsewardj      assign( frB, getDReg( frB_addr ) );
10862cdc376dcb5a4560b0a35d4abcb2146c499756f0dsewardj
10863cdc376dcb5a4560b0a35d4abcb2146c499756f0dsewardj      assign( ccIR, binop( Iop_CmpD64, mkexpr( frA ), mkexpr( frB ) ) );
10864cdc376dcb5a4560b0a35d4abcb2146c499756f0dsewardj      break;
10865cdc376dcb5a4560b0a35d4abcb2146c499756f0dsewardj   case 0x3F: /* dcmpoq and dcmpuq,DFP 128-bit */
10866cdc376dcb5a4560b0a35d4abcb2146c499756f0dsewardj      DIP( "dcmpoq %u,fr%u,fr%u\n", crfD, frA_addr, frB_addr );
10867cdc376dcb5a4560b0a35d4abcb2146c499756f0dsewardj      frA = newTemp( Ity_D128 );
10868cdc376dcb5a4560b0a35d4abcb2146c499756f0dsewardj      frB = newTemp( Ity_D128 );
10869cdc376dcb5a4560b0a35d4abcb2146c499756f0dsewardj
10870cdc376dcb5a4560b0a35d4abcb2146c499756f0dsewardj      assign( frA, getDReg_pair( frA_addr ) );
10871cdc376dcb5a4560b0a35d4abcb2146c499756f0dsewardj      assign( frB, getDReg_pair( frB_addr ) );
10872cdc376dcb5a4560b0a35d4abcb2146c499756f0dsewardj      assign( ccIR, binop( Iop_CmpD128, mkexpr( frA ), mkexpr( frB ) ) );
10873cdc376dcb5a4560b0a35d4abcb2146c499756f0dsewardj      break;
10874cdc376dcb5a4560b0a35d4abcb2146c499756f0dsewardj   default:
10875cdc376dcb5a4560b0a35d4abcb2146c499756f0dsewardj      vex_printf("dis_dfp_compare(ppc)(opc2)\n");
10876cdc376dcb5a4560b0a35d4abcb2146c499756f0dsewardj      return False;
10877cdc376dcb5a4560b0a35d4abcb2146c499756f0dsewardj   }
10878cdc376dcb5a4560b0a35d4abcb2146c499756f0dsewardj
10879cdc376dcb5a4560b0a35d4abcb2146c499756f0dsewardj   /* Map compare result from IR to PPC32 */
10880cdc376dcb5a4560b0a35d4abcb2146c499756f0dsewardj   /*
10881cdc376dcb5a4560b0a35d4abcb2146c499756f0dsewardj    FP cmp result | PPC | IR
10882cdc376dcb5a4560b0a35d4abcb2146c499756f0dsewardj    --------------------------
10883cdc376dcb5a4560b0a35d4abcb2146c499756f0dsewardj    UN            | 0x1 | 0x45
10884cdc376dcb5a4560b0a35d4abcb2146c499756f0dsewardj    EQ            | 0x2 | 0x40
10885cdc376dcb5a4560b0a35d4abcb2146c499756f0dsewardj    GT            | 0x4 | 0x00
10886cdc376dcb5a4560b0a35d4abcb2146c499756f0dsewardj    LT            | 0x8 | 0x01
10887cdc376dcb5a4560b0a35d4abcb2146c499756f0dsewardj    */
10888cdc376dcb5a4560b0a35d4abcb2146c499756f0dsewardj
10889cdc376dcb5a4560b0a35d4abcb2146c499756f0dsewardj   assign( ccPPC32,
10890cdc376dcb5a4560b0a35d4abcb2146c499756f0dsewardj           binop( Iop_Shl32,
10891cdc376dcb5a4560b0a35d4abcb2146c499756f0dsewardj                  mkU32( 1 ),
10892cdc376dcb5a4560b0a35d4abcb2146c499756f0dsewardj                  unop( Iop_32to8,
10893cdc376dcb5a4560b0a35d4abcb2146c499756f0dsewardj                        binop( Iop_Or32,
10894cdc376dcb5a4560b0a35d4abcb2146c499756f0dsewardj                               binop( Iop_And32,
10895cdc376dcb5a4560b0a35d4abcb2146c499756f0dsewardj                                      unop( Iop_Not32,
10896cdc376dcb5a4560b0a35d4abcb2146c499756f0dsewardj                                            binop( Iop_Shr32,
10897cdc376dcb5a4560b0a35d4abcb2146c499756f0dsewardj                                                   mkexpr( ccIR ),
10898cdc376dcb5a4560b0a35d4abcb2146c499756f0dsewardj                                                   mkU8( 5 ) ) ),
10899cdc376dcb5a4560b0a35d4abcb2146c499756f0dsewardj                                      mkU32( 2 ) ),
10900cdc376dcb5a4560b0a35d4abcb2146c499756f0dsewardj                               binop( Iop_And32,
10901cdc376dcb5a4560b0a35d4abcb2146c499756f0dsewardj                                      binop( Iop_Xor32,
10902cdc376dcb5a4560b0a35d4abcb2146c499756f0dsewardj                                             mkexpr( ccIR ),
10903cdc376dcb5a4560b0a35d4abcb2146c499756f0dsewardj                                             binop( Iop_Shr32,
10904cdc376dcb5a4560b0a35d4abcb2146c499756f0dsewardj                                                    mkexpr( ccIR ),
10905cdc376dcb5a4560b0a35d4abcb2146c499756f0dsewardj                                                    mkU8( 6 ) ) ),
10906cdc376dcb5a4560b0a35d4abcb2146c499756f0dsewardj                                      mkU32( 1 ) ) ) ) ) );
10907cdc376dcb5a4560b0a35d4abcb2146c499756f0dsewardj
10908cdc376dcb5a4560b0a35d4abcb2146c499756f0dsewardj   putGST_field( PPC_GST_CR, mkexpr( ccPPC32 ), crfD );
10909cdc376dcb5a4560b0a35d4abcb2146c499756f0dsewardj   return True;
10910cdc376dcb5a4560b0a35d4abcb2146c499756f0dsewardj}
10911cdc376dcb5a4560b0a35d4abcb2146c499756f0dsewardj
109125eff1c502e995d1f9668cc9def72d5db59f21b13sewardj/* Test class/group/exponent/significance instructions. */
109135eff1c502e995d1f9668cc9def72d5db59f21b13sewardjstatic Bool dis_dfp_exponent_test ( UInt theInstr )
109145eff1c502e995d1f9668cc9def72d5db59f21b13sewardj{
109155eff1c502e995d1f9668cc9def72d5db59f21b13sewardj   UChar frA_addr   = ifieldRegA( theInstr );
109165eff1c502e995d1f9668cc9def72d5db59f21b13sewardj   UChar frB_addr   = ifieldRegB( theInstr );
109175eff1c502e995d1f9668cc9def72d5db59f21b13sewardj   UChar crfD       = toUChar( IFIELD( theInstr, 23, 3 ) );
109185eff1c502e995d1f9668cc9def72d5db59f21b13sewardj   IRTemp frA       = newTemp( Ity_D64 );
109195eff1c502e995d1f9668cc9def72d5db59f21b13sewardj   IRTemp frB       = newTemp( Ity_D64 );
109205eff1c502e995d1f9668cc9def72d5db59f21b13sewardj   IRTemp frA128    = newTemp( Ity_D128 );
109215eff1c502e995d1f9668cc9def72d5db59f21b13sewardj   IRTemp frB128    = newTemp( Ity_D128 );
109225eff1c502e995d1f9668cc9def72d5db59f21b13sewardj   UInt opc1        = ifieldOPC( theInstr );
109235eff1c502e995d1f9668cc9def72d5db59f21b13sewardj   IRTemp gfield_A  = newTemp( Ity_I32 );
109245eff1c502e995d1f9668cc9def72d5db59f21b13sewardj   IRTemp gfield_B  = newTemp( Ity_I32 );
109255eff1c502e995d1f9668cc9def72d5db59f21b13sewardj   IRTemp gfield_mask   = newTemp( Ity_I32 );
109265eff1c502e995d1f9668cc9def72d5db59f21b13sewardj   IRTemp exponent_A    = newTemp( Ity_I32 );
109275eff1c502e995d1f9668cc9def72d5db59f21b13sewardj   IRTemp exponent_B    = newTemp( Ity_I32 );
109285eff1c502e995d1f9668cc9def72d5db59f21b13sewardj   IRTemp A_NaN_true    = newTemp( Ity_I32 );
109295eff1c502e995d1f9668cc9def72d5db59f21b13sewardj   IRTemp B_NaN_true    = newTemp( Ity_I32 );
109305eff1c502e995d1f9668cc9def72d5db59f21b13sewardj   IRTemp A_inf_true    = newTemp( Ity_I32 );
109315eff1c502e995d1f9668cc9def72d5db59f21b13sewardj   IRTemp B_inf_true    = newTemp( Ity_I32 );
109325eff1c502e995d1f9668cc9def72d5db59f21b13sewardj   IRTemp A_equals_B    = newTemp( Ity_I32 );
109335eff1c502e995d1f9668cc9def72d5db59f21b13sewardj   IRTemp finite_number = newTemp( Ity_I32 );
109345eff1c502e995d1f9668cc9def72d5db59f21b13sewardj   IRTemp cc0 = newTemp( Ity_I32 );
109355eff1c502e995d1f9668cc9def72d5db59f21b13sewardj   IRTemp cc1 = newTemp( Ity_I32 );
109365eff1c502e995d1f9668cc9def72d5db59f21b13sewardj   IRTemp cc2 = newTemp( Ity_I32 );
109375eff1c502e995d1f9668cc9def72d5db59f21b13sewardj   IRTemp cc3 = newTemp( Ity_I32 );
109385eff1c502e995d1f9668cc9def72d5db59f21b13sewardj
109395eff1c502e995d1f9668cc9def72d5db59f21b13sewardj   /* The dtstex and dtstexg instructions only differ in the size of the
109405eff1c502e995d1f9668cc9def72d5db59f21b13sewardj    * exponent field.  The following switch statement takes care of the size
109415eff1c502e995d1f9668cc9def72d5db59f21b13sewardj    * specific setup.  Once the value of the exponents, the G-field shift
109425eff1c502e995d1f9668cc9def72d5db59f21b13sewardj    * and mask is setup the remaining code is identical.
109435eff1c502e995d1f9668cc9def72d5db59f21b13sewardj    */
109445eff1c502e995d1f9668cc9def72d5db59f21b13sewardj   switch (opc1) {
109455eff1c502e995d1f9668cc9def72d5db59f21b13sewardj   case 0x3b: // dtstex       Extended instruction setup
109465eff1c502e995d1f9668cc9def72d5db59f21b13sewardj      DIP("dtstex %u,r%u,r%d\n", crfD, frA_addr, frB_addr);
109475eff1c502e995d1f9668cc9def72d5db59f21b13sewardj      assign( frA, getDReg( frA_addr ) );
109485eff1c502e995d1f9668cc9def72d5db59f21b13sewardj      assign( frB, getDReg( frB_addr ) );
109495eff1c502e995d1f9668cc9def72d5db59f21b13sewardj      assign( gfield_mask, mkU32( DFP_G_FIELD_LONG_MASK ) );
10950cea07ccbe9aa9b5fd8e9b318471c6c74aa147acbcarll      assign(exponent_A, unop( Iop_64to32,
10951cea07ccbe9aa9b5fd8e9b318471c6c74aa147acbcarll                               unop( Iop_ExtractExpD64,
10952cea07ccbe9aa9b5fd8e9b318471c6c74aa147acbcarll                                     mkexpr( frA ) ) ) );
10953cea07ccbe9aa9b5fd8e9b318471c6c74aa147acbcarll      assign(exponent_B, unop( Iop_64to32,
10954cea07ccbe9aa9b5fd8e9b318471c6c74aa147acbcarll                               unop( Iop_ExtractExpD64,
10955cea07ccbe9aa9b5fd8e9b318471c6c74aa147acbcarll                                     mkexpr( frB ) ) ) );
109565eff1c502e995d1f9668cc9def72d5db59f21b13sewardj      break;
109575eff1c502e995d1f9668cc9def72d5db59f21b13sewardj
109585eff1c502e995d1f9668cc9def72d5db59f21b13sewardj   case 0x3F: //  dtstexq      Quad instruction setup
109595eff1c502e995d1f9668cc9def72d5db59f21b13sewardj      DIP("dtstexq %u,r%u,r%d\n", crfD, frA_addr, frB_addr);
109605eff1c502e995d1f9668cc9def72d5db59f21b13sewardj      assign( frA128, getDReg_pair( frA_addr ) );
109615eff1c502e995d1f9668cc9def72d5db59f21b13sewardj      assign( frB128, getDReg_pair( frB_addr ) );
109625eff1c502e995d1f9668cc9def72d5db59f21b13sewardj      assign( frA, unop( Iop_D128HItoD64, mkexpr( frA128 ) ) );
109635eff1c502e995d1f9668cc9def72d5db59f21b13sewardj      assign( frB, unop( Iop_D128HItoD64, mkexpr( frB128 ) ) );
109645eff1c502e995d1f9668cc9def72d5db59f21b13sewardj      assign( gfield_mask, mkU32( DFP_G_FIELD_EXTND_MASK ) );
10965cea07ccbe9aa9b5fd8e9b318471c6c74aa147acbcarll      assign( exponent_A, unop( Iop_64to32,
10966cea07ccbe9aa9b5fd8e9b318471c6c74aa147acbcarll                                unop( Iop_ExtractExpD128,
10967cea07ccbe9aa9b5fd8e9b318471c6c74aa147acbcarll                                      mkexpr( frA128 ) ) ) );
10968cea07ccbe9aa9b5fd8e9b318471c6c74aa147acbcarll      assign( exponent_B, unop( Iop_64to32,
10969cea07ccbe9aa9b5fd8e9b318471c6c74aa147acbcarll                                unop( Iop_ExtractExpD128,
10970cea07ccbe9aa9b5fd8e9b318471c6c74aa147acbcarll                                      mkexpr( frB128 ) ) ) );
109715eff1c502e995d1f9668cc9def72d5db59f21b13sewardj      break;
109725eff1c502e995d1f9668cc9def72d5db59f21b13sewardj   default:
109735eff1c502e995d1f9668cc9def72d5db59f21b13sewardj      vex_printf("dis_dfp_exponent_test(ppc)(opc2)\n");
109745eff1c502e995d1f9668cc9def72d5db59f21b13sewardj      return False;
109755eff1c502e995d1f9668cc9def72d5db59f21b13sewardj   }
109765eff1c502e995d1f9668cc9def72d5db59f21b13sewardj
109775eff1c502e995d1f9668cc9def72d5db59f21b13sewardj   /* Extract the Gfield */
109785eff1c502e995d1f9668cc9def72d5db59f21b13sewardj   assign( gfield_A, binop( Iop_And32,
109795eff1c502e995d1f9668cc9def72d5db59f21b13sewardj                            mkexpr( gfield_mask ),
109805eff1c502e995d1f9668cc9def72d5db59f21b13sewardj                            unop( Iop_64HIto32,
109815eff1c502e995d1f9668cc9def72d5db59f21b13sewardj                                  unop( Iop_ReinterpD64asI64,
109825eff1c502e995d1f9668cc9def72d5db59f21b13sewardj                                        mkexpr(frA) ) ) ) );
109835eff1c502e995d1f9668cc9def72d5db59f21b13sewardj
109845eff1c502e995d1f9668cc9def72d5db59f21b13sewardj   assign( gfield_B, binop( Iop_And32,
109855eff1c502e995d1f9668cc9def72d5db59f21b13sewardj                            mkexpr( gfield_mask ),
109865eff1c502e995d1f9668cc9def72d5db59f21b13sewardj                            unop( Iop_64HIto32,
109875eff1c502e995d1f9668cc9def72d5db59f21b13sewardj                                  unop( Iop_ReinterpD64asI64,
109885eff1c502e995d1f9668cc9def72d5db59f21b13sewardj                                        mkexpr(frB) ) ) ) );
109895eff1c502e995d1f9668cc9def72d5db59f21b13sewardj
109905eff1c502e995d1f9668cc9def72d5db59f21b13sewardj   /* check for NAN */
109915eff1c502e995d1f9668cc9def72d5db59f21b13sewardj   assign( A_NaN_true, binop(Iop_Or32,
109925eff1c502e995d1f9668cc9def72d5db59f21b13sewardj                             unop( Iop_1Sto32,
109935eff1c502e995d1f9668cc9def72d5db59f21b13sewardj                                   binop( Iop_CmpEQ32,
109945eff1c502e995d1f9668cc9def72d5db59f21b13sewardj                                          mkexpr( gfield_A ),
109955eff1c502e995d1f9668cc9def72d5db59f21b13sewardj                                          mkU32( 0x7C000000 ) ) ),
109965eff1c502e995d1f9668cc9def72d5db59f21b13sewardj                             unop( Iop_1Sto32,
109975eff1c502e995d1f9668cc9def72d5db59f21b13sewardj                                   binop( Iop_CmpEQ32,
109985eff1c502e995d1f9668cc9def72d5db59f21b13sewardj                                          mkexpr( gfield_A ),
109995eff1c502e995d1f9668cc9def72d5db59f21b13sewardj                                          mkU32( 0x7E000000 ) )
110005eff1c502e995d1f9668cc9def72d5db59f21b13sewardj                                   ) ) );
110015eff1c502e995d1f9668cc9def72d5db59f21b13sewardj   assign( B_NaN_true, binop(Iop_Or32,
110025eff1c502e995d1f9668cc9def72d5db59f21b13sewardj                             unop( Iop_1Sto32,
110035eff1c502e995d1f9668cc9def72d5db59f21b13sewardj                                   binop( Iop_CmpEQ32,
110045eff1c502e995d1f9668cc9def72d5db59f21b13sewardj                                          mkexpr( gfield_B ),
110055eff1c502e995d1f9668cc9def72d5db59f21b13sewardj                                          mkU32( 0x7C000000 ) ) ),
110065eff1c502e995d1f9668cc9def72d5db59f21b13sewardj                             unop( Iop_1Sto32,
110075eff1c502e995d1f9668cc9def72d5db59f21b13sewardj                                   binop( Iop_CmpEQ32,
110085eff1c502e995d1f9668cc9def72d5db59f21b13sewardj                                          mkexpr( gfield_B ),
110095eff1c502e995d1f9668cc9def72d5db59f21b13sewardj                                          mkU32( 0x7E000000 ) )
110105eff1c502e995d1f9668cc9def72d5db59f21b13sewardj                             ) ) );
110115eff1c502e995d1f9668cc9def72d5db59f21b13sewardj
110125eff1c502e995d1f9668cc9def72d5db59f21b13sewardj   /* check for infinity */
110135eff1c502e995d1f9668cc9def72d5db59f21b13sewardj   assign( A_inf_true,
110145eff1c502e995d1f9668cc9def72d5db59f21b13sewardj           unop( Iop_1Sto32,
110155eff1c502e995d1f9668cc9def72d5db59f21b13sewardj                 binop( Iop_CmpEQ32,
110165eff1c502e995d1f9668cc9def72d5db59f21b13sewardj                        mkexpr( gfield_A ),
110175eff1c502e995d1f9668cc9def72d5db59f21b13sewardj                        mkU32( 0x78000000 ) ) ) );
110185eff1c502e995d1f9668cc9def72d5db59f21b13sewardj
110195eff1c502e995d1f9668cc9def72d5db59f21b13sewardj   assign( B_inf_true,
110205eff1c502e995d1f9668cc9def72d5db59f21b13sewardj           unop( Iop_1Sto32,
110215eff1c502e995d1f9668cc9def72d5db59f21b13sewardj                 binop( Iop_CmpEQ32,
110225eff1c502e995d1f9668cc9def72d5db59f21b13sewardj                        mkexpr( gfield_B ),
110235eff1c502e995d1f9668cc9def72d5db59f21b13sewardj                        mkU32( 0x78000000 ) ) ) );
110245eff1c502e995d1f9668cc9def72d5db59f21b13sewardj
110255eff1c502e995d1f9668cc9def72d5db59f21b13sewardj   assign( finite_number,
110265eff1c502e995d1f9668cc9def72d5db59f21b13sewardj           unop( Iop_Not32,
110275eff1c502e995d1f9668cc9def72d5db59f21b13sewardj                 binop( Iop_Or32,
110285eff1c502e995d1f9668cc9def72d5db59f21b13sewardj                        binop( Iop_Or32,
110295eff1c502e995d1f9668cc9def72d5db59f21b13sewardj                               mkexpr( A_NaN_true ),
110305eff1c502e995d1f9668cc9def72d5db59f21b13sewardj                               mkexpr( B_NaN_true ) ),
110315eff1c502e995d1f9668cc9def72d5db59f21b13sewardj                        binop( Iop_Or32,
110325eff1c502e995d1f9668cc9def72d5db59f21b13sewardj                               mkexpr( A_inf_true ),
110335eff1c502e995d1f9668cc9def72d5db59f21b13sewardj                               mkexpr( B_inf_true ) ) ) ) );
110345eff1c502e995d1f9668cc9def72d5db59f21b13sewardj
110355eff1c502e995d1f9668cc9def72d5db59f21b13sewardj   /* Calculate the condition code bits
110365eff1c502e995d1f9668cc9def72d5db59f21b13sewardj    * If QNaN,SNaN, +infinity, -infinity then cc0, cc1 and cc2 are zero
110375eff1c502e995d1f9668cc9def72d5db59f21b13sewardj    * regardless of the value of the comparisons and cc3 is 1.  Otherwise,
110385eff1c502e995d1f9668cc9def72d5db59f21b13sewardj    * cc0, cc1 and cc0 reflect the results of the comparisons.
110395eff1c502e995d1f9668cc9def72d5db59f21b13sewardj    */
110405eff1c502e995d1f9668cc9def72d5db59f21b13sewardj   assign( A_equals_B,
110415eff1c502e995d1f9668cc9def72d5db59f21b13sewardj           binop( Iop_Or32,
110425eff1c502e995d1f9668cc9def72d5db59f21b13sewardj                  unop( Iop_1Uto32,
110435eff1c502e995d1f9668cc9def72d5db59f21b13sewardj                  binop( Iop_CmpEQ32,
110445eff1c502e995d1f9668cc9def72d5db59f21b13sewardj                         mkexpr( exponent_A ),
110455eff1c502e995d1f9668cc9def72d5db59f21b13sewardj                         mkexpr( exponent_B ) ) ),
110465eff1c502e995d1f9668cc9def72d5db59f21b13sewardj                  binop( Iop_Or32,
110475eff1c502e995d1f9668cc9def72d5db59f21b13sewardj                         binop( Iop_And32,
110485eff1c502e995d1f9668cc9def72d5db59f21b13sewardj                                mkexpr( A_inf_true ),
110495eff1c502e995d1f9668cc9def72d5db59f21b13sewardj                                mkexpr( B_inf_true ) ),
110505eff1c502e995d1f9668cc9def72d5db59f21b13sewardj                         binop( Iop_And32,
110515eff1c502e995d1f9668cc9def72d5db59f21b13sewardj                                mkexpr( A_NaN_true ),
110525eff1c502e995d1f9668cc9def72d5db59f21b13sewardj                                mkexpr( B_NaN_true ) ) ) ) );
110535eff1c502e995d1f9668cc9def72d5db59f21b13sewardj
110545eff1c502e995d1f9668cc9def72d5db59f21b13sewardj   assign( cc0, binop( Iop_And32,
110555eff1c502e995d1f9668cc9def72d5db59f21b13sewardj                       mkexpr( finite_number ),
110565eff1c502e995d1f9668cc9def72d5db59f21b13sewardj                       binop( Iop_Shl32,
110575eff1c502e995d1f9668cc9def72d5db59f21b13sewardj                              unop( Iop_1Uto32,
110585eff1c502e995d1f9668cc9def72d5db59f21b13sewardj                                    binop( Iop_CmpLT32U,
110595eff1c502e995d1f9668cc9def72d5db59f21b13sewardj                                           mkexpr( exponent_A ),
110605eff1c502e995d1f9668cc9def72d5db59f21b13sewardj                                           mkexpr( exponent_B ) ) ),
110615eff1c502e995d1f9668cc9def72d5db59f21b13sewardj                                           mkU8( 3 ) ) ) );
110625eff1c502e995d1f9668cc9def72d5db59f21b13sewardj
110635eff1c502e995d1f9668cc9def72d5db59f21b13sewardj   assign( cc1, binop( Iop_And32,
110645eff1c502e995d1f9668cc9def72d5db59f21b13sewardj                       mkexpr( finite_number ),
110655eff1c502e995d1f9668cc9def72d5db59f21b13sewardj                       binop( Iop_Shl32,
110665eff1c502e995d1f9668cc9def72d5db59f21b13sewardj                              unop( Iop_1Uto32,
110675eff1c502e995d1f9668cc9def72d5db59f21b13sewardj                                    binop( Iop_CmpLT32U,
110685eff1c502e995d1f9668cc9def72d5db59f21b13sewardj                                           mkexpr( exponent_B ),
110695eff1c502e995d1f9668cc9def72d5db59f21b13sewardj                                           mkexpr( exponent_A ) ) ),
110705eff1c502e995d1f9668cc9def72d5db59f21b13sewardj                                           mkU8( 2 ) ) ) );
110715eff1c502e995d1f9668cc9def72d5db59f21b13sewardj
110725eff1c502e995d1f9668cc9def72d5db59f21b13sewardj   assign( cc2, binop( Iop_Shl32,
110735eff1c502e995d1f9668cc9def72d5db59f21b13sewardj                       binop( Iop_And32,
110745eff1c502e995d1f9668cc9def72d5db59f21b13sewardj                              mkexpr( A_equals_B ),
110755eff1c502e995d1f9668cc9def72d5db59f21b13sewardj                              mkU32( 1 ) ),
110765eff1c502e995d1f9668cc9def72d5db59f21b13sewardj                              mkU8( 1 ) ) );
110775eff1c502e995d1f9668cc9def72d5db59f21b13sewardj
110785eff1c502e995d1f9668cc9def72d5db59f21b13sewardj   assign( cc3, binop( Iop_And32,
110795eff1c502e995d1f9668cc9def72d5db59f21b13sewardj                       unop( Iop_Not32, mkexpr( A_equals_B ) ),
110805eff1c502e995d1f9668cc9def72d5db59f21b13sewardj                       binop( Iop_And32,
110815eff1c502e995d1f9668cc9def72d5db59f21b13sewardj                              mkU32( 0x1 ),
110825eff1c502e995d1f9668cc9def72d5db59f21b13sewardj                              binop( Iop_Or32,
110835eff1c502e995d1f9668cc9def72d5db59f21b13sewardj                                     binop( Iop_Or32,
110845eff1c502e995d1f9668cc9def72d5db59f21b13sewardj                                            mkexpr ( A_inf_true ),
110855eff1c502e995d1f9668cc9def72d5db59f21b13sewardj                                            mkexpr ( B_inf_true ) ),
110865eff1c502e995d1f9668cc9def72d5db59f21b13sewardj                                            binop( Iop_Or32,
110875eff1c502e995d1f9668cc9def72d5db59f21b13sewardj                                                   mkexpr ( A_NaN_true ),
110885eff1c502e995d1f9668cc9def72d5db59f21b13sewardj                                                   mkexpr ( B_NaN_true ) ) )
110895eff1c502e995d1f9668cc9def72d5db59f21b13sewardj                              ) ) );
110905eff1c502e995d1f9668cc9def72d5db59f21b13sewardj
110915eff1c502e995d1f9668cc9def72d5db59f21b13sewardj   /* store the condition code */
110925eff1c502e995d1f9668cc9def72d5db59f21b13sewardj   putGST_field( PPC_GST_CR,
110935eff1c502e995d1f9668cc9def72d5db59f21b13sewardj                 binop( Iop_Or32,
110945eff1c502e995d1f9668cc9def72d5db59f21b13sewardj                        mkexpr( cc0 ),
110955eff1c502e995d1f9668cc9def72d5db59f21b13sewardj                        binop( Iop_Or32,
110965eff1c502e995d1f9668cc9def72d5db59f21b13sewardj                               mkexpr( cc1 ),
110975eff1c502e995d1f9668cc9def72d5db59f21b13sewardj                               binop( Iop_Or32,
110985eff1c502e995d1f9668cc9def72d5db59f21b13sewardj                                      mkexpr( cc2 ),
110995eff1c502e995d1f9668cc9def72d5db59f21b13sewardj                                      mkexpr( cc3 ) ) ) ),
111005eff1c502e995d1f9668cc9def72d5db59f21b13sewardj                 crfD );
111015eff1c502e995d1f9668cc9def72d5db59f21b13sewardj   return True;
111025eff1c502e995d1f9668cc9def72d5db59f21b13sewardj}
111035eff1c502e995d1f9668cc9def72d5db59f21b13sewardj
111045eff1c502e995d1f9668cc9def72d5db59f21b13sewardj/* Test class/group/exponent/significance instructions. */
111055eff1c502e995d1f9668cc9def72d5db59f21b13sewardjstatic Bool dis_dfp_class_test ( UInt theInstr )
111065eff1c502e995d1f9668cc9def72d5db59f21b13sewardj{
111075eff1c502e995d1f9668cc9def72d5db59f21b13sewardj   UChar frA_addr   = ifieldRegA( theInstr );
111085eff1c502e995d1f9668cc9def72d5db59f21b13sewardj   IRTemp frA       = newTemp( Ity_D64 );
111095eff1c502e995d1f9668cc9def72d5db59f21b13sewardj   IRTemp abs_frA   = newTemp( Ity_D64 );
111105eff1c502e995d1f9668cc9def72d5db59f21b13sewardj   IRTemp frAI64_hi = newTemp( Ity_I64 );
111115eff1c502e995d1f9668cc9def72d5db59f21b13sewardj   IRTemp frAI64_lo = newTemp( Ity_I64 );
111125eff1c502e995d1f9668cc9def72d5db59f21b13sewardj   UInt opc1        = ifieldOPC( theInstr );
111135eff1c502e995d1f9668cc9def72d5db59f21b13sewardj   UInt opc2        = ifieldOPClo9( theInstr );
111145eff1c502e995d1f9668cc9def72d5db59f21b13sewardj   UChar crfD       = toUChar( IFIELD( theInstr, 23, 3 ) );  // AKA BF
111155eff1c502e995d1f9668cc9def72d5db59f21b13sewardj   UInt DCM         = IFIELD( theInstr, 10, 6 );
111165eff1c502e995d1f9668cc9def72d5db59f21b13sewardj   IRTemp DCM_calc  = newTemp( Ity_I32 );
111175eff1c502e995d1f9668cc9def72d5db59f21b13sewardj   UInt max_exp     = 0;
111185eff1c502e995d1f9668cc9def72d5db59f21b13sewardj   UInt min_exp     = 0;
111195eff1c502e995d1f9668cc9def72d5db59f21b13sewardj   IRTemp min_subnormalD64  = newTemp( Ity_D64 );
111205eff1c502e995d1f9668cc9def72d5db59f21b13sewardj   IRTemp min_subnormalD128 = newTemp( Ity_D128 );
111215eff1c502e995d1f9668cc9def72d5db59f21b13sewardj   IRTemp significand64  = newTemp( Ity_D64 );
111225eff1c502e995d1f9668cc9def72d5db59f21b13sewardj   IRTemp significand128 = newTemp( Ity_D128 );
11123cea07ccbe9aa9b5fd8e9b318471c6c74aa147acbcarll   IRTemp exp_min_normal = newTemp( Ity_I64 );
111245eff1c502e995d1f9668cc9def72d5db59f21b13sewardj   IRTemp exponent       = newTemp( Ity_I32 );
111255eff1c502e995d1f9668cc9def72d5db59f21b13sewardj
111265eff1c502e995d1f9668cc9def72d5db59f21b13sewardj   IRTemp infinity_true  = newTemp( Ity_I32 );
111275eff1c502e995d1f9668cc9def72d5db59f21b13sewardj   IRTemp SNaN_true      = newTemp( Ity_I32 );
111285eff1c502e995d1f9668cc9def72d5db59f21b13sewardj   IRTemp QNaN_true      = newTemp( Ity_I32 );
111295eff1c502e995d1f9668cc9def72d5db59f21b13sewardj   IRTemp subnormal_true = newTemp( Ity_I32 );
111305eff1c502e995d1f9668cc9def72d5db59f21b13sewardj   IRTemp normal_true    = newTemp( Ity_I32 );
111315eff1c502e995d1f9668cc9def72d5db59f21b13sewardj   IRTemp extreme_true   = newTemp( Ity_I32 );
111325eff1c502e995d1f9668cc9def72d5db59f21b13sewardj   IRTemp lmd            = newTemp( Ity_I32 );
111335eff1c502e995d1f9668cc9def72d5db59f21b13sewardj   IRTemp lmd_zero_true  = newTemp( Ity_I32 );
111345eff1c502e995d1f9668cc9def72d5db59f21b13sewardj   IRTemp zero_true      = newTemp( Ity_I32 );
111355eff1c502e995d1f9668cc9def72d5db59f21b13sewardj   IRTemp sign           = newTemp( Ity_I32 );
111365eff1c502e995d1f9668cc9def72d5db59f21b13sewardj   IRTemp field          = newTemp( Ity_I32 );
111375eff1c502e995d1f9668cc9def72d5db59f21b13sewardj   IRTemp ccIR_zero      = newTemp( Ity_I32 );
111385eff1c502e995d1f9668cc9def72d5db59f21b13sewardj   IRTemp ccIR_subnormal = newTemp( Ity_I32 );
111395eff1c502e995d1f9668cc9def72d5db59f21b13sewardj
111405eff1c502e995d1f9668cc9def72d5db59f21b13sewardj   /* UInt size     = DFP_LONG;  JRS:unused */
111415eff1c502e995d1f9668cc9def72d5db59f21b13sewardj   IRTemp gfield = newTemp( Ity_I32 );
111425eff1c502e995d1f9668cc9def72d5db59f21b13sewardj   IRTemp gfield_0_4_shift  = newTemp( Ity_I8 );
111435eff1c502e995d1f9668cc9def72d5db59f21b13sewardj   IRTemp gfield_mask       = newTemp( Ity_I32 );
111445eff1c502e995d1f9668cc9def72d5db59f21b13sewardj   IRTemp dcm0 = newTemp( Ity_I32 );
111455eff1c502e995d1f9668cc9def72d5db59f21b13sewardj   IRTemp dcm1 = newTemp( Ity_I32 );
111465eff1c502e995d1f9668cc9def72d5db59f21b13sewardj   IRTemp dcm2 = newTemp( Ity_I32 );
111475eff1c502e995d1f9668cc9def72d5db59f21b13sewardj   IRTemp dcm3 = newTemp( Ity_I32 );
111485eff1c502e995d1f9668cc9def72d5db59f21b13sewardj   IRTemp dcm4 = newTemp( Ity_I32 );
111495eff1c502e995d1f9668cc9def72d5db59f21b13sewardj   IRTemp dcm5 = newTemp( Ity_I32 );
111505eff1c502e995d1f9668cc9def72d5db59f21b13sewardj
111515eff1c502e995d1f9668cc9def72d5db59f21b13sewardj   /* The only difference between the dtstdc and dtstdcq instructions is
111525eff1c502e995d1f9668cc9def72d5db59f21b13sewardj    * size of the T and G fields.  The calculation of the 4 bit field
111535eff1c502e995d1f9668cc9def72d5db59f21b13sewardj    * is the same.  Setup the parameters and values that are DFP size
111545eff1c502e995d1f9668cc9def72d5db59f21b13sewardj    * specific.  The rest of the code is independent of the DFP size.
111555eff1c502e995d1f9668cc9def72d5db59f21b13sewardj    *
111565eff1c502e995d1f9668cc9def72d5db59f21b13sewardj    * The Io_CmpD64 is used below.  The instruction sets the ccIR values.
111575eff1c502e995d1f9668cc9def72d5db59f21b13sewardj    * The interpretation of the ccIR values is as follows:
111585eff1c502e995d1f9668cc9def72d5db59f21b13sewardj    *
111595eff1c502e995d1f9668cc9def72d5db59f21b13sewardj    *    DFP cmp result | IR
111605eff1c502e995d1f9668cc9def72d5db59f21b13sewardj    * --------------------------
111615eff1c502e995d1f9668cc9def72d5db59f21b13sewardj    *	 UN             | 0x45
111625eff1c502e995d1f9668cc9def72d5db59f21b13sewardj    *	 EQ             | 0x40
111635eff1c502e995d1f9668cc9def72d5db59f21b13sewardj    *	 GT             | 0x00
111645eff1c502e995d1f9668cc9def72d5db59f21b13sewardj    *	 LT             | 0x01
111655eff1c502e995d1f9668cc9def72d5db59f21b13sewardj    */
111665eff1c502e995d1f9668cc9def72d5db59f21b13sewardj
111675eff1c502e995d1f9668cc9def72d5db59f21b13sewardj   assign( frA, getDReg( frA_addr ) );
111685eff1c502e995d1f9668cc9def72d5db59f21b13sewardj   assign( frAI64_hi, unop( Iop_ReinterpD64asI64, mkexpr( frA ) ) );
111695eff1c502e995d1f9668cc9def72d5db59f21b13sewardj
111705eff1c502e995d1f9668cc9def72d5db59f21b13sewardj   assign( abs_frA, unop( Iop_ReinterpI64asD64,
111715eff1c502e995d1f9668cc9def72d5db59f21b13sewardj                          binop( Iop_And64,
111725eff1c502e995d1f9668cc9def72d5db59f21b13sewardj                                 unop( Iop_ReinterpD64asI64,
111735eff1c502e995d1f9668cc9def72d5db59f21b13sewardj                                       mkexpr( frA ) ),
111745eff1c502e995d1f9668cc9def72d5db59f21b13sewardj                                 mkU64( 0x7FFFFFFFFFFFFFFFULL ) ) ) );
111755eff1c502e995d1f9668cc9def72d5db59f21b13sewardj   assign( gfield_0_4_shift, mkU8( 31 - 5 ) );  // G-field[0:4]
111765eff1c502e995d1f9668cc9def72d5db59f21b13sewardj   switch (opc1) {
111775eff1c502e995d1f9668cc9def72d5db59f21b13sewardj   case 0x3b: // dtstdc, dtstdg
111785eff1c502e995d1f9668cc9def72d5db59f21b13sewardj      DIP("dtstd%s %u,r%u,%d\n", opc2 == 0xc2 ? "c" : "g",
111795eff1c502e995d1f9668cc9def72d5db59f21b13sewardj               crfD, frA_addr, DCM);
111805eff1c502e995d1f9668cc9def72d5db59f21b13sewardj      /* setup the parameters for the long format of the two instructions */
111815eff1c502e995d1f9668cc9def72d5db59f21b13sewardj      assign( frAI64_lo, mkU64( 0 ) );
111825eff1c502e995d1f9668cc9def72d5db59f21b13sewardj      assign( gfield_mask, mkU32( DFP_G_FIELD_LONG_MASK ) );
111835eff1c502e995d1f9668cc9def72d5db59f21b13sewardj      max_exp = DFP_LONG_EXP_MAX;
111845eff1c502e995d1f9668cc9def72d5db59f21b13sewardj      min_exp = DFP_LONG_EXP_MIN;
111855eff1c502e995d1f9668cc9def72d5db59f21b13sewardj
11186cea07ccbe9aa9b5fd8e9b318471c6c74aa147acbcarll      assign( exponent, unop( Iop_64to32,
11187cea07ccbe9aa9b5fd8e9b318471c6c74aa147acbcarll                              unop( Iop_ExtractExpD64,
11188cea07ccbe9aa9b5fd8e9b318471c6c74aa147acbcarll                                    mkexpr( frA ) ) ) );
111895eff1c502e995d1f9668cc9def72d5db59f21b13sewardj      assign( significand64,
111905eff1c502e995d1f9668cc9def72d5db59f21b13sewardj              unop( Iop_ReinterpI64asD64,
111915eff1c502e995d1f9668cc9def72d5db59f21b13sewardj                    mkU64( 0x2234000000000001ULL ) ) );  // dfp 1.0
11192cea07ccbe9aa9b5fd8e9b318471c6c74aa147acbcarll      assign( exp_min_normal,mkU64( 398 - 383 ) );
111935eff1c502e995d1f9668cc9def72d5db59f21b13sewardj      assign( min_subnormalD64,
111945eff1c502e995d1f9668cc9def72d5db59f21b13sewardj              binop( Iop_InsertExpD64,
111955eff1c502e995d1f9668cc9def72d5db59f21b13sewardj                     mkexpr( exp_min_normal ),
111965eff1c502e995d1f9668cc9def72d5db59f21b13sewardj                     mkexpr( significand64 ) ) );
111975eff1c502e995d1f9668cc9def72d5db59f21b13sewardj
111985eff1c502e995d1f9668cc9def72d5db59f21b13sewardj      assign( ccIR_subnormal,
111995eff1c502e995d1f9668cc9def72d5db59f21b13sewardj              binop( Iop_CmpD64,
112005eff1c502e995d1f9668cc9def72d5db59f21b13sewardj                     mkexpr( abs_frA ),
112015eff1c502e995d1f9668cc9def72d5db59f21b13sewardj                     mkexpr( min_subnormalD64 ) ) );
112025eff1c502e995d1f9668cc9def72d5db59f21b13sewardj
112035eff1c502e995d1f9668cc9def72d5db59f21b13sewardj      /* compare absolute value of frA with zero */
112045eff1c502e995d1f9668cc9def72d5db59f21b13sewardj      assign( ccIR_zero,
112055eff1c502e995d1f9668cc9def72d5db59f21b13sewardj              binop( Iop_CmpD64,
112065eff1c502e995d1f9668cc9def72d5db59f21b13sewardj                     mkexpr( abs_frA ),
112075eff1c502e995d1f9668cc9def72d5db59f21b13sewardj                     unop( Iop_ReinterpI64asD64,
112085eff1c502e995d1f9668cc9def72d5db59f21b13sewardj                           mkU64( 0x2238000000000000ULL ) ) ) );
112095eff1c502e995d1f9668cc9def72d5db59f21b13sewardj
112105eff1c502e995d1f9668cc9def72d5db59f21b13sewardj      /* size = DFP_LONG; JRS: unused */
112115eff1c502e995d1f9668cc9def72d5db59f21b13sewardj      break;
112125eff1c502e995d1f9668cc9def72d5db59f21b13sewardj
112135eff1c502e995d1f9668cc9def72d5db59f21b13sewardj   case 0x3F:   // dtstdcq, dtstdgq
112145eff1c502e995d1f9668cc9def72d5db59f21b13sewardj      DIP("dtstd%sq %u,r%u,%d\n", opc2 == 0xc2 ? "c" : "g",
112155eff1c502e995d1f9668cc9def72d5db59f21b13sewardj               crfD, frA_addr, DCM);
112165eff1c502e995d1f9668cc9def72d5db59f21b13sewardj      /* setup the parameters for the extended format of the
112175eff1c502e995d1f9668cc9def72d5db59f21b13sewardj       * two instructions
112185eff1c502e995d1f9668cc9def72d5db59f21b13sewardj       */
112195eff1c502e995d1f9668cc9def72d5db59f21b13sewardj      assign( frAI64_lo, unop( Iop_ReinterpD64asI64,
112205eff1c502e995d1f9668cc9def72d5db59f21b13sewardj                               getDReg( frA_addr+1 ) ) );
112215eff1c502e995d1f9668cc9def72d5db59f21b13sewardj
112225eff1c502e995d1f9668cc9def72d5db59f21b13sewardj      assign( gfield_mask, mkU32( DFP_G_FIELD_EXTND_MASK ) );
112235eff1c502e995d1f9668cc9def72d5db59f21b13sewardj      max_exp = DFP_EXTND_EXP_MAX;
112245eff1c502e995d1f9668cc9def72d5db59f21b13sewardj      min_exp = DFP_EXTND_EXP_MIN;
112255eff1c502e995d1f9668cc9def72d5db59f21b13sewardj      assign( exponent, unop( Iop_64to32,
11226cea07ccbe9aa9b5fd8e9b318471c6c74aa147acbcarll                              unop( Iop_ExtractExpD128,
11227cea07ccbe9aa9b5fd8e9b318471c6c74aa147acbcarll                                    getDReg_pair( frA_addr) ) ) );
112285eff1c502e995d1f9668cc9def72d5db59f21b13sewardj
112295eff1c502e995d1f9668cc9def72d5db59f21b13sewardj      /* create quand exponent for minimum normal number */
11230cea07ccbe9aa9b5fd8e9b318471c6c74aa147acbcarll      assign( exp_min_normal, mkU64( 6176 - 6143 ) );
112315eff1c502e995d1f9668cc9def72d5db59f21b13sewardj      assign( significand128,
112325eff1c502e995d1f9668cc9def72d5db59f21b13sewardj              unop( Iop_D64toD128,
112335eff1c502e995d1f9668cc9def72d5db59f21b13sewardj                    unop( Iop_ReinterpI64asD64,
112345eff1c502e995d1f9668cc9def72d5db59f21b13sewardj                          mkU64( 0x2234000000000001ULL ) ) ) );  // dfp 1.0
112355eff1c502e995d1f9668cc9def72d5db59f21b13sewardj
112365eff1c502e995d1f9668cc9def72d5db59f21b13sewardj      assign( min_subnormalD128,
112375eff1c502e995d1f9668cc9def72d5db59f21b13sewardj              binop( Iop_InsertExpD128,
112385eff1c502e995d1f9668cc9def72d5db59f21b13sewardj                     mkexpr( exp_min_normal ),
112395eff1c502e995d1f9668cc9def72d5db59f21b13sewardj                     mkexpr( significand128 ) ) );
112405eff1c502e995d1f9668cc9def72d5db59f21b13sewardj
112415eff1c502e995d1f9668cc9def72d5db59f21b13sewardj      assign( ccIR_subnormal,
112425eff1c502e995d1f9668cc9def72d5db59f21b13sewardj              binop( Iop_CmpD128,
112435eff1c502e995d1f9668cc9def72d5db59f21b13sewardj                     binop( Iop_D64HLtoD128,
112445eff1c502e995d1f9668cc9def72d5db59f21b13sewardj                            unop( Iop_ReinterpI64asD64,
112455eff1c502e995d1f9668cc9def72d5db59f21b13sewardj                                  binop( Iop_And64,
112465eff1c502e995d1f9668cc9def72d5db59f21b13sewardj                                         unop( Iop_ReinterpD64asI64,
112475eff1c502e995d1f9668cc9def72d5db59f21b13sewardj                                               mkexpr( frA ) ),
112485eff1c502e995d1f9668cc9def72d5db59f21b13sewardj                                         mkU64( 0x7FFFFFFFFFFFFFFFULL ) ) ),
112495eff1c502e995d1f9668cc9def72d5db59f21b13sewardj                            getDReg( frA_addr+1 ) ),
112505eff1c502e995d1f9668cc9def72d5db59f21b13sewardj                     mkexpr( min_subnormalD128 ) ) );
112515eff1c502e995d1f9668cc9def72d5db59f21b13sewardj      assign( ccIR_zero,
112525eff1c502e995d1f9668cc9def72d5db59f21b13sewardj              binop( Iop_CmpD128,
112535eff1c502e995d1f9668cc9def72d5db59f21b13sewardj                     binop( Iop_D64HLtoD128,
112545eff1c502e995d1f9668cc9def72d5db59f21b13sewardj                            mkexpr( abs_frA ),
112555eff1c502e995d1f9668cc9def72d5db59f21b13sewardj                            getDReg( frA_addr+1 ) ),
112565eff1c502e995d1f9668cc9def72d5db59f21b13sewardj                     unop( Iop_D64toD128,
112575eff1c502e995d1f9668cc9def72d5db59f21b13sewardj                           unop( Iop_ReinterpI64asD64,
112585eff1c502e995d1f9668cc9def72d5db59f21b13sewardj                                 mkU64( 0x0ULL ) ) ) ) );
112595eff1c502e995d1f9668cc9def72d5db59f21b13sewardj
112605eff1c502e995d1f9668cc9def72d5db59f21b13sewardj      /* size = DFP_EXTND; JRS:unused */
112615eff1c502e995d1f9668cc9def72d5db59f21b13sewardj      break;
112625eff1c502e995d1f9668cc9def72d5db59f21b13sewardj   default:
112635eff1c502e995d1f9668cc9def72d5db59f21b13sewardj      vex_printf("dis_dfp_class_test(ppc)(opc2)\n");
112645eff1c502e995d1f9668cc9def72d5db59f21b13sewardj      return False;
112655eff1c502e995d1f9668cc9def72d5db59f21b13sewardj   }
112665eff1c502e995d1f9668cc9def72d5db59f21b13sewardj
112675eff1c502e995d1f9668cc9def72d5db59f21b13sewardj   /* The G-field is in the upper 32-bits.  The I64 logical operations
112685eff1c502e995d1f9668cc9def72d5db59f21b13sewardj    * do not seem to be supported in 32-bit mode so keep things as 32-bit
112695eff1c502e995d1f9668cc9def72d5db59f21b13sewardj    * operations.
112705eff1c502e995d1f9668cc9def72d5db59f21b13sewardj    */
112715eff1c502e995d1f9668cc9def72d5db59f21b13sewardj   assign( gfield, binop( Iop_And32,
112725eff1c502e995d1f9668cc9def72d5db59f21b13sewardj                          mkexpr( gfield_mask ),
112735eff1c502e995d1f9668cc9def72d5db59f21b13sewardj                          unop( Iop_64HIto32,
112745eff1c502e995d1f9668cc9def72d5db59f21b13sewardj                                mkexpr(frAI64_hi) ) ) );
112755eff1c502e995d1f9668cc9def72d5db59f21b13sewardj
112765eff1c502e995d1f9668cc9def72d5db59f21b13sewardj   /* There is a lot of code that is the same to do the class and group
112775eff1c502e995d1f9668cc9def72d5db59f21b13sewardj    * instructions.  Later there is an if statement to handle the specific
112785eff1c502e995d1f9668cc9def72d5db59f21b13sewardj    * instruction.
112795eff1c502e995d1f9668cc9def72d5db59f21b13sewardj    *
112805eff1c502e995d1f9668cc9def72d5db59f21b13sewardj    * Will be using I32 values, compares, shifts and logical operations for
112815eff1c502e995d1f9668cc9def72d5db59f21b13sewardj    * this code as the 64-bit compare, shifts, logical operations are not
112825eff1c502e995d1f9668cc9def72d5db59f21b13sewardj    * supported in 32-bit mode.
112835eff1c502e995d1f9668cc9def72d5db59f21b13sewardj    */
112845eff1c502e995d1f9668cc9def72d5db59f21b13sewardj
112855eff1c502e995d1f9668cc9def72d5db59f21b13sewardj   /* Check the bits for Infinity, QNaN or Signaling NaN */
112865eff1c502e995d1f9668cc9def72d5db59f21b13sewardj   assign( infinity_true,
112875eff1c502e995d1f9668cc9def72d5db59f21b13sewardj           unop( Iop_1Sto32,
112885eff1c502e995d1f9668cc9def72d5db59f21b13sewardj                 binop( Iop_CmpEQ32,
112895eff1c502e995d1f9668cc9def72d5db59f21b13sewardj                        binop( Iop_And32,
112905eff1c502e995d1f9668cc9def72d5db59f21b13sewardj                               mkU32( 0x7C000000 ),
112915eff1c502e995d1f9668cc9def72d5db59f21b13sewardj                               mkexpr( gfield ) ),
112925eff1c502e995d1f9668cc9def72d5db59f21b13sewardj                        mkU32( 0x78000000 ) ) ) );
112935eff1c502e995d1f9668cc9def72d5db59f21b13sewardj
112945eff1c502e995d1f9668cc9def72d5db59f21b13sewardj   assign( SNaN_true,
112955eff1c502e995d1f9668cc9def72d5db59f21b13sewardj           unop( Iop_1Sto32,
112965eff1c502e995d1f9668cc9def72d5db59f21b13sewardj                 binop( Iop_CmpEQ32,
112975eff1c502e995d1f9668cc9def72d5db59f21b13sewardj                        binop( Iop_And32,
112985eff1c502e995d1f9668cc9def72d5db59f21b13sewardj                               mkU32( 0x7E000000 ),
112995eff1c502e995d1f9668cc9def72d5db59f21b13sewardj                               mkexpr( gfield ) ),
113005eff1c502e995d1f9668cc9def72d5db59f21b13sewardj                        mkU32( 0x7E000000 ) ) ) );
113015eff1c502e995d1f9668cc9def72d5db59f21b13sewardj
113025eff1c502e995d1f9668cc9def72d5db59f21b13sewardj   assign( QNaN_true,
113035eff1c502e995d1f9668cc9def72d5db59f21b13sewardj           binop( Iop_And32,
113045eff1c502e995d1f9668cc9def72d5db59f21b13sewardj                  unop( Iop_1Sto32,
113055eff1c502e995d1f9668cc9def72d5db59f21b13sewardj                       binop( Iop_CmpEQ32,
113065eff1c502e995d1f9668cc9def72d5db59f21b13sewardj                              binop( Iop_And32,
113075eff1c502e995d1f9668cc9def72d5db59f21b13sewardj                                     mkU32( 0x7E000000 ),
113085eff1c502e995d1f9668cc9def72d5db59f21b13sewardj                                     mkexpr( gfield ) ),
113095eff1c502e995d1f9668cc9def72d5db59f21b13sewardj                              mkU32( 0x7C000000 ) ) ),
113105eff1c502e995d1f9668cc9def72d5db59f21b13sewardj                  unop( Iop_Not32,
113115eff1c502e995d1f9668cc9def72d5db59f21b13sewardj                        mkexpr( SNaN_true ) ) ) );
113125eff1c502e995d1f9668cc9def72d5db59f21b13sewardj
113135eff1c502e995d1f9668cc9def72d5db59f21b13sewardj   assign( zero_true,
113145eff1c502e995d1f9668cc9def72d5db59f21b13sewardj           binop( Iop_And32,
113155eff1c502e995d1f9668cc9def72d5db59f21b13sewardj                  unop(Iop_1Sto32,
113165eff1c502e995d1f9668cc9def72d5db59f21b13sewardj                       binop( Iop_CmpEQ32,
113175eff1c502e995d1f9668cc9def72d5db59f21b13sewardj                              mkexpr( ccIR_zero ),
113185eff1c502e995d1f9668cc9def72d5db59f21b13sewardj                              mkU32( 0x40 ) ) ),  // ccIR code for Equal
113195eff1c502e995d1f9668cc9def72d5db59f21b13sewardj                  unop( Iop_Not32,
113205eff1c502e995d1f9668cc9def72d5db59f21b13sewardj                        binop( Iop_Or32,
113215eff1c502e995d1f9668cc9def72d5db59f21b13sewardj                               mkexpr( infinity_true ),
113225eff1c502e995d1f9668cc9def72d5db59f21b13sewardj                               binop( Iop_Or32,
113235eff1c502e995d1f9668cc9def72d5db59f21b13sewardj                                      mkexpr( QNaN_true ),
113245eff1c502e995d1f9668cc9def72d5db59f21b13sewardj                                      mkexpr( SNaN_true ) ) ) ) ) );
113255eff1c502e995d1f9668cc9def72d5db59f21b13sewardj
113265eff1c502e995d1f9668cc9def72d5db59f21b13sewardj   /* Do compare of frA the minimum normal value.  Comparison is size
113275eff1c502e995d1f9668cc9def72d5db59f21b13sewardj    * depenent and was done above to get the ccIR value.
113285eff1c502e995d1f9668cc9def72d5db59f21b13sewardj    */
113295eff1c502e995d1f9668cc9def72d5db59f21b13sewardj   assign( subnormal_true,
113305eff1c502e995d1f9668cc9def72d5db59f21b13sewardj           binop( Iop_And32,
113315eff1c502e995d1f9668cc9def72d5db59f21b13sewardj                  binop( Iop_Or32,
113325eff1c502e995d1f9668cc9def72d5db59f21b13sewardj                         unop( Iop_1Sto32,
113335eff1c502e995d1f9668cc9def72d5db59f21b13sewardj                               binop( Iop_CmpEQ32,
113345eff1c502e995d1f9668cc9def72d5db59f21b13sewardj                                      mkexpr( ccIR_subnormal ),
113355eff1c502e995d1f9668cc9def72d5db59f21b13sewardj                                      mkU32( 0x40 ) ) ), // ccIR code for Equal
113365eff1c502e995d1f9668cc9def72d5db59f21b13sewardj                         unop( Iop_1Sto32,
113375eff1c502e995d1f9668cc9def72d5db59f21b13sewardj                               binop( Iop_CmpEQ32,
113385eff1c502e995d1f9668cc9def72d5db59f21b13sewardj                                      mkexpr( ccIR_subnormal ),
113395eff1c502e995d1f9668cc9def72d5db59f21b13sewardj                                      mkU32( 0x1 ) ) ) ), // ccIR code for LT
113405eff1c502e995d1f9668cc9def72d5db59f21b13sewardj           unop( Iop_Not32,
113415eff1c502e995d1f9668cc9def72d5db59f21b13sewardj                 binop( Iop_Or32,
113425eff1c502e995d1f9668cc9def72d5db59f21b13sewardj                        binop( Iop_Or32,
113435eff1c502e995d1f9668cc9def72d5db59f21b13sewardj                               mkexpr( infinity_true ),
113445eff1c502e995d1f9668cc9def72d5db59f21b13sewardj                               mkexpr( zero_true) ),
113455eff1c502e995d1f9668cc9def72d5db59f21b13sewardj                        binop( Iop_Or32,
113465eff1c502e995d1f9668cc9def72d5db59f21b13sewardj                               mkexpr( QNaN_true ),
113475eff1c502e995d1f9668cc9def72d5db59f21b13sewardj                               mkexpr( SNaN_true ) ) ) ) ) );
113485eff1c502e995d1f9668cc9def72d5db59f21b13sewardj
113495eff1c502e995d1f9668cc9def72d5db59f21b13sewardj   /* Normal number is not subnormal, infinity, NaN or Zero */
113505eff1c502e995d1f9668cc9def72d5db59f21b13sewardj   assign( normal_true,
113515eff1c502e995d1f9668cc9def72d5db59f21b13sewardj           unop( Iop_Not32,
113525eff1c502e995d1f9668cc9def72d5db59f21b13sewardj                 binop( Iop_Or32,
113535eff1c502e995d1f9668cc9def72d5db59f21b13sewardj                        binop( Iop_Or32,
113545eff1c502e995d1f9668cc9def72d5db59f21b13sewardj                               mkexpr( infinity_true ),
113555eff1c502e995d1f9668cc9def72d5db59f21b13sewardj                               mkexpr( zero_true ) ),
113565eff1c502e995d1f9668cc9def72d5db59f21b13sewardj                        binop( Iop_Or32,
113575eff1c502e995d1f9668cc9def72d5db59f21b13sewardj                               mkexpr( subnormal_true ),
113585eff1c502e995d1f9668cc9def72d5db59f21b13sewardj                               binop( Iop_Or32,
113595eff1c502e995d1f9668cc9def72d5db59f21b13sewardj                                      mkexpr( QNaN_true ),
113605eff1c502e995d1f9668cc9def72d5db59f21b13sewardj                                      mkexpr( SNaN_true ) ) ) ) ) );
113615eff1c502e995d1f9668cc9def72d5db59f21b13sewardj
113625eff1c502e995d1f9668cc9def72d5db59f21b13sewardj   /* Calculate the DCM bit field based on the tests for the specific
113635eff1c502e995d1f9668cc9def72d5db59f21b13sewardj    * instruction
113645eff1c502e995d1f9668cc9def72d5db59f21b13sewardj    */
113655eff1c502e995d1f9668cc9def72d5db59f21b13sewardj   if (opc2 == 0xC2) {    // dtstdc, dtstdcq
113665eff1c502e995d1f9668cc9def72d5db59f21b13sewardj      /* DCM[0:5] Bit   Data Class definition
113675eff1c502e995d1f9668cc9def72d5db59f21b13sewardj       *   0   Zero
113685eff1c502e995d1f9668cc9def72d5db59f21b13sewardj       *   1   Subnormal
113695eff1c502e995d1f9668cc9def72d5db59f21b13sewardj       *   2   Normal
113705eff1c502e995d1f9668cc9def72d5db59f21b13sewardj       *   3   Infinity
113715eff1c502e995d1f9668cc9def72d5db59f21b13sewardj       *   4   Quiet NaN
113725eff1c502e995d1f9668cc9def72d5db59f21b13sewardj       *   5   Signaling NaN
113735eff1c502e995d1f9668cc9def72d5db59f21b13sewardj       */
113745eff1c502e995d1f9668cc9def72d5db59f21b13sewardj
113755eff1c502e995d1f9668cc9def72d5db59f21b13sewardj      assign( dcm0, binop( Iop_Shl32,
113765eff1c502e995d1f9668cc9def72d5db59f21b13sewardj                           mkexpr( zero_true ),
113775eff1c502e995d1f9668cc9def72d5db59f21b13sewardj                           mkU8( 5 ) ) );
113785eff1c502e995d1f9668cc9def72d5db59f21b13sewardj      assign( dcm1, binop( Iop_Shl32,
113795eff1c502e995d1f9668cc9def72d5db59f21b13sewardj                           binop( Iop_And32,
113805eff1c502e995d1f9668cc9def72d5db59f21b13sewardj                                  mkexpr( subnormal_true ),
113815eff1c502e995d1f9668cc9def72d5db59f21b13sewardj                                  mkU32( 1 ) ),
113825eff1c502e995d1f9668cc9def72d5db59f21b13sewardj                           mkU8( 4 ) ) );
113835eff1c502e995d1f9668cc9def72d5db59f21b13sewardj      assign( dcm2, binop( Iop_Shl32,
113845eff1c502e995d1f9668cc9def72d5db59f21b13sewardj                           binop( Iop_And32,
113855eff1c502e995d1f9668cc9def72d5db59f21b13sewardj                                  mkexpr( normal_true ),
113865eff1c502e995d1f9668cc9def72d5db59f21b13sewardj                                  mkU32( 1 ) ),
113875eff1c502e995d1f9668cc9def72d5db59f21b13sewardj                           mkU8( 3 ) ) );
113885eff1c502e995d1f9668cc9def72d5db59f21b13sewardj      assign( dcm3, binop( Iop_Shl32,
113895eff1c502e995d1f9668cc9def72d5db59f21b13sewardj                           binop( Iop_And32,
113905eff1c502e995d1f9668cc9def72d5db59f21b13sewardj                                  mkexpr( infinity_true),
113915eff1c502e995d1f9668cc9def72d5db59f21b13sewardj                                  mkU32( 1 ) ),
113925eff1c502e995d1f9668cc9def72d5db59f21b13sewardj                           mkU8( 2 ) ) );
113935eff1c502e995d1f9668cc9def72d5db59f21b13sewardj      assign( dcm4, binop( Iop_Shl32,
113945eff1c502e995d1f9668cc9def72d5db59f21b13sewardj                           binop( Iop_And32,
113955eff1c502e995d1f9668cc9def72d5db59f21b13sewardj                                  mkexpr( QNaN_true ),
113965eff1c502e995d1f9668cc9def72d5db59f21b13sewardj                                  mkU32( 1 ) ),
113975eff1c502e995d1f9668cc9def72d5db59f21b13sewardj                           mkU8( 1 ) ) );
113985eff1c502e995d1f9668cc9def72d5db59f21b13sewardj      assign( dcm5, binop( Iop_And32, mkexpr( SNaN_true), mkU32( 1 ) ) );
113995eff1c502e995d1f9668cc9def72d5db59f21b13sewardj
114005eff1c502e995d1f9668cc9def72d5db59f21b13sewardj   } else if (opc2 == 0xE2) {   // dtstdg, dtstdgq
114015eff1c502e995d1f9668cc9def72d5db59f21b13sewardj      /* check if the exponent is extreme */
114025eff1c502e995d1f9668cc9def72d5db59f21b13sewardj      assign( extreme_true, binop( Iop_Or32,
114035eff1c502e995d1f9668cc9def72d5db59f21b13sewardj                                   unop( Iop_1Sto32,
114045eff1c502e995d1f9668cc9def72d5db59f21b13sewardj                                         binop( Iop_CmpEQ32,
114055eff1c502e995d1f9668cc9def72d5db59f21b13sewardj                                                mkexpr( exponent ),
114065eff1c502e995d1f9668cc9def72d5db59f21b13sewardj                                                mkU32( max_exp ) ) ),
114075eff1c502e995d1f9668cc9def72d5db59f21b13sewardj                                   unop( Iop_1Sto32,
114085eff1c502e995d1f9668cc9def72d5db59f21b13sewardj                                         binop( Iop_CmpEQ32,
114095eff1c502e995d1f9668cc9def72d5db59f21b13sewardj                                                mkexpr( exponent ),
114105eff1c502e995d1f9668cc9def72d5db59f21b13sewardj                                                mkU32( min_exp ) ) ) ) );
114115eff1c502e995d1f9668cc9def72d5db59f21b13sewardj
114125eff1c502e995d1f9668cc9def72d5db59f21b13sewardj      /* Check if LMD is zero */
114135eff1c502e995d1f9668cc9def72d5db59f21b13sewardj      Get_lmd( &lmd, binop( Iop_Shr32,
114145eff1c502e995d1f9668cc9def72d5db59f21b13sewardj                            mkexpr( gfield ), mkU8( 31 - 5 ) ) );
114155eff1c502e995d1f9668cc9def72d5db59f21b13sewardj
114165eff1c502e995d1f9668cc9def72d5db59f21b13sewardj      assign( lmd_zero_true, unop( Iop_1Sto32,
114175eff1c502e995d1f9668cc9def72d5db59f21b13sewardj                                   binop( Iop_CmpEQ32,
114185eff1c502e995d1f9668cc9def72d5db59f21b13sewardj                                          mkexpr( lmd ),
114195eff1c502e995d1f9668cc9def72d5db59f21b13sewardj                                          mkU32( 0 ) ) ) );
114205eff1c502e995d1f9668cc9def72d5db59f21b13sewardj
114215eff1c502e995d1f9668cc9def72d5db59f21b13sewardj      /* DCM[0:5] Bit   Data Class definition
114225eff1c502e995d1f9668cc9def72d5db59f21b13sewardj       *  0   Zero with non-extreme exponent
114235eff1c502e995d1f9668cc9def72d5db59f21b13sewardj       *  1   Zero with extreme exponent
114245eff1c502e995d1f9668cc9def72d5db59f21b13sewardj       *  2   Subnormal or (Normal with extreme exponent)
114255eff1c502e995d1f9668cc9def72d5db59f21b13sewardj       *  3   Normal with non-extreme exponent and
114265eff1c502e995d1f9668cc9def72d5db59f21b13sewardj       *      leftmost zero digit in significand
114275eff1c502e995d1f9668cc9def72d5db59f21b13sewardj       *  4   Normal with non-extreme exponent and
114285eff1c502e995d1f9668cc9def72d5db59f21b13sewardj       *      leftmost nonzero digit in significand
114295eff1c502e995d1f9668cc9def72d5db59f21b13sewardj       *  5   Special symbol (Infinity, QNaN, or SNaN)
114305eff1c502e995d1f9668cc9def72d5db59f21b13sewardj       */
114315eff1c502e995d1f9668cc9def72d5db59f21b13sewardj      assign( dcm0, binop( Iop_Shl32,
114325eff1c502e995d1f9668cc9def72d5db59f21b13sewardj                           binop( Iop_And32,
114335eff1c502e995d1f9668cc9def72d5db59f21b13sewardj                                  binop( Iop_And32,
114345eff1c502e995d1f9668cc9def72d5db59f21b13sewardj                                         unop( Iop_Not32,
114355eff1c502e995d1f9668cc9def72d5db59f21b13sewardj                                               mkexpr( extreme_true ) ),
114365eff1c502e995d1f9668cc9def72d5db59f21b13sewardj                                         mkexpr( zero_true ) ),
114375eff1c502e995d1f9668cc9def72d5db59f21b13sewardj                                  mkU32( 0x1 ) ),
114385eff1c502e995d1f9668cc9def72d5db59f21b13sewardj                           mkU8( 5 ) ) );
114395eff1c502e995d1f9668cc9def72d5db59f21b13sewardj
114405eff1c502e995d1f9668cc9def72d5db59f21b13sewardj      assign( dcm1, binop( Iop_Shl32,
114415eff1c502e995d1f9668cc9def72d5db59f21b13sewardj                           binop( Iop_And32,
114425eff1c502e995d1f9668cc9def72d5db59f21b13sewardj                                  binop( Iop_And32,
114435eff1c502e995d1f9668cc9def72d5db59f21b13sewardj                                         mkexpr( extreme_true ),
114445eff1c502e995d1f9668cc9def72d5db59f21b13sewardj                                         mkexpr( zero_true ) ),
114455eff1c502e995d1f9668cc9def72d5db59f21b13sewardj                                  mkU32( 0x1 ) ),
114465eff1c502e995d1f9668cc9def72d5db59f21b13sewardj                           mkU8( 4 ) ) );
114475eff1c502e995d1f9668cc9def72d5db59f21b13sewardj
114485eff1c502e995d1f9668cc9def72d5db59f21b13sewardj      assign( dcm2, binop( Iop_Shl32,
114495eff1c502e995d1f9668cc9def72d5db59f21b13sewardj                           binop( Iop_And32,
114505eff1c502e995d1f9668cc9def72d5db59f21b13sewardj                                  binop( Iop_Or32,
114515eff1c502e995d1f9668cc9def72d5db59f21b13sewardj                                         binop( Iop_And32,
114525eff1c502e995d1f9668cc9def72d5db59f21b13sewardj                                                mkexpr( extreme_true ),
114535eff1c502e995d1f9668cc9def72d5db59f21b13sewardj                                                mkexpr( normal_true ) ),
114545eff1c502e995d1f9668cc9def72d5db59f21b13sewardj                                         mkexpr( subnormal_true ) ),
114555eff1c502e995d1f9668cc9def72d5db59f21b13sewardj                                  mkU32( 0x1 ) ),
114565eff1c502e995d1f9668cc9def72d5db59f21b13sewardj                           mkU8( 3 ) ) );
114575eff1c502e995d1f9668cc9def72d5db59f21b13sewardj
114585eff1c502e995d1f9668cc9def72d5db59f21b13sewardj      assign( dcm3, binop( Iop_Shl32,
114595eff1c502e995d1f9668cc9def72d5db59f21b13sewardj                           binop( Iop_And32,
114605eff1c502e995d1f9668cc9def72d5db59f21b13sewardj                                  binop( Iop_And32,
114615eff1c502e995d1f9668cc9def72d5db59f21b13sewardj                                         binop( Iop_And32,
114625eff1c502e995d1f9668cc9def72d5db59f21b13sewardj                                                unop( Iop_Not32,
114635eff1c502e995d1f9668cc9def72d5db59f21b13sewardj                                                      mkexpr( extreme_true ) ),
114645eff1c502e995d1f9668cc9def72d5db59f21b13sewardj                                                      mkexpr( normal_true ) ),
114655eff1c502e995d1f9668cc9def72d5db59f21b13sewardj                                         unop( Iop_1Sto32,
114665eff1c502e995d1f9668cc9def72d5db59f21b13sewardj                                               binop( Iop_CmpEQ32,
114675eff1c502e995d1f9668cc9def72d5db59f21b13sewardj                                                      mkexpr( lmd ),
114685eff1c502e995d1f9668cc9def72d5db59f21b13sewardj                                                      mkU32( 0 ) ) ) ),
114695eff1c502e995d1f9668cc9def72d5db59f21b13sewardj                                  mkU32( 0x1 ) ),
114705eff1c502e995d1f9668cc9def72d5db59f21b13sewardj                           mkU8( 2 ) ) );
114715eff1c502e995d1f9668cc9def72d5db59f21b13sewardj
114725eff1c502e995d1f9668cc9def72d5db59f21b13sewardj      assign( dcm4, binop( Iop_Shl32,
114735eff1c502e995d1f9668cc9def72d5db59f21b13sewardj                           binop( Iop_And32,
114745eff1c502e995d1f9668cc9def72d5db59f21b13sewardj                                  binop( Iop_And32,
114755eff1c502e995d1f9668cc9def72d5db59f21b13sewardj                                         binop( Iop_And32,
114765eff1c502e995d1f9668cc9def72d5db59f21b13sewardj                                                unop( Iop_Not32,
114775eff1c502e995d1f9668cc9def72d5db59f21b13sewardj                                                      mkexpr( extreme_true ) ),
114785eff1c502e995d1f9668cc9def72d5db59f21b13sewardj                                                mkexpr( normal_true ) ),
114795eff1c502e995d1f9668cc9def72d5db59f21b13sewardj                                          unop( Iop_1Sto32,
114805eff1c502e995d1f9668cc9def72d5db59f21b13sewardj                                                binop( Iop_CmpNE32,
114815eff1c502e995d1f9668cc9def72d5db59f21b13sewardj                                                       mkexpr( lmd ),
114824c96e61dd85c172b999d6afc88ce6640aeba9962sewardj                                                       mkU32( 0 ) ) ) ),
114835eff1c502e995d1f9668cc9def72d5db59f21b13sewardj                                  mkU32( 0x1 ) ),
114845eff1c502e995d1f9668cc9def72d5db59f21b13sewardj                           mkU8( 1 ) ) );
114855eff1c502e995d1f9668cc9def72d5db59f21b13sewardj
114865eff1c502e995d1f9668cc9def72d5db59f21b13sewardj      assign( dcm5, binop( Iop_And32,
114875eff1c502e995d1f9668cc9def72d5db59f21b13sewardj                           binop( Iop_Or32,
114885eff1c502e995d1f9668cc9def72d5db59f21b13sewardj                                  mkexpr( SNaN_true),
114895eff1c502e995d1f9668cc9def72d5db59f21b13sewardj                                  binop( Iop_Or32,
114905eff1c502e995d1f9668cc9def72d5db59f21b13sewardj                                         mkexpr( QNaN_true),
114915eff1c502e995d1f9668cc9def72d5db59f21b13sewardj                                         mkexpr( infinity_true) ) ),
114925eff1c502e995d1f9668cc9def72d5db59f21b13sewardj                           mkU32( 0x1 ) ) );
114935eff1c502e995d1f9668cc9def72d5db59f21b13sewardj   }
114945eff1c502e995d1f9668cc9def72d5db59f21b13sewardj
114955eff1c502e995d1f9668cc9def72d5db59f21b13sewardj   /* create DCM field */
114965eff1c502e995d1f9668cc9def72d5db59f21b13sewardj   assign( DCM_calc,
114975eff1c502e995d1f9668cc9def72d5db59f21b13sewardj           binop( Iop_Or32,
114985eff1c502e995d1f9668cc9def72d5db59f21b13sewardj                  mkexpr( dcm0 ),
114995eff1c502e995d1f9668cc9def72d5db59f21b13sewardj                  binop( Iop_Or32,
115005eff1c502e995d1f9668cc9def72d5db59f21b13sewardj                         mkexpr( dcm1 ),
115015eff1c502e995d1f9668cc9def72d5db59f21b13sewardj                         binop( Iop_Or32,
115025eff1c502e995d1f9668cc9def72d5db59f21b13sewardj                                mkexpr( dcm2 ),
115035eff1c502e995d1f9668cc9def72d5db59f21b13sewardj                                binop( Iop_Or32,
115045eff1c502e995d1f9668cc9def72d5db59f21b13sewardj                                       mkexpr( dcm3 ),
115055eff1c502e995d1f9668cc9def72d5db59f21b13sewardj                                       binop( Iop_Or32,
115065eff1c502e995d1f9668cc9def72d5db59f21b13sewardj                                              mkexpr( dcm4 ),
115075eff1c502e995d1f9668cc9def72d5db59f21b13sewardj                                              mkexpr( dcm5 ) ) ) ) ) ) );
115085eff1c502e995d1f9668cc9def72d5db59f21b13sewardj
115095eff1c502e995d1f9668cc9def72d5db59f21b13sewardj   /* Get the sign of the DFP number, ignore sign for QNaN */
115105eff1c502e995d1f9668cc9def72d5db59f21b13sewardj   assign( sign,
115115eff1c502e995d1f9668cc9def72d5db59f21b13sewardj           unop( Iop_1Uto32,
115125eff1c502e995d1f9668cc9def72d5db59f21b13sewardj                 binop( Iop_CmpEQ32,
115135eff1c502e995d1f9668cc9def72d5db59f21b13sewardj                        binop( Iop_Shr32,
115145eff1c502e995d1f9668cc9def72d5db59f21b13sewardj                               unop( Iop_64HIto32, mkexpr( frAI64_hi ) ),
115155eff1c502e995d1f9668cc9def72d5db59f21b13sewardj                               mkU8( 63 - 32 ) ),
115165eff1c502e995d1f9668cc9def72d5db59f21b13sewardj                        mkU32( 1 ) ) ) );
115175eff1c502e995d1f9668cc9def72d5db59f21b13sewardj
115185eff1c502e995d1f9668cc9def72d5db59f21b13sewardj   /* This instruction generates a four bit field to be stored in the
115195eff1c502e995d1f9668cc9def72d5db59f21b13sewardj    * condition code register.  The condition code register consists of 7
115205eff1c502e995d1f9668cc9def72d5db59f21b13sewardj    * fields.  The field to be written to is specified by the BF (AKA crfD)
115215eff1c502e995d1f9668cc9def72d5db59f21b13sewardj    * field.
115225eff1c502e995d1f9668cc9def72d5db59f21b13sewardj    *
115235eff1c502e995d1f9668cc9def72d5db59f21b13sewardj    * The field layout is as follows:
115245eff1c502e995d1f9668cc9def72d5db59f21b13sewardj    *
115255eff1c502e995d1f9668cc9def72d5db59f21b13sewardj    *      Field          Meaning
115265eff1c502e995d1f9668cc9def72d5db59f21b13sewardj    *      0000           Operand positive with no match
115275eff1c502e995d1f9668cc9def72d5db59f21b13sewardj    *      0100           Operand positive with at least one match
115285eff1c502e995d1f9668cc9def72d5db59f21b13sewardj    *      0001           Operand negative with no match
115295eff1c502e995d1f9668cc9def72d5db59f21b13sewardj    *      0101           Operand negative with at least one match
115305eff1c502e995d1f9668cc9def72d5db59f21b13sewardj    */
115315eff1c502e995d1f9668cc9def72d5db59f21b13sewardj   assign( field, binop( Iop_Or32,
115325eff1c502e995d1f9668cc9def72d5db59f21b13sewardj                         binop( Iop_Shl32,
115335eff1c502e995d1f9668cc9def72d5db59f21b13sewardj                                mkexpr( sign ),
115345eff1c502e995d1f9668cc9def72d5db59f21b13sewardj                                mkU8( 3 ) ),
115355eff1c502e995d1f9668cc9def72d5db59f21b13sewardj                                binop( Iop_Shl32,
115365eff1c502e995d1f9668cc9def72d5db59f21b13sewardj                                       unop( Iop_1Uto32,
115375eff1c502e995d1f9668cc9def72d5db59f21b13sewardj                                             binop( Iop_CmpNE32,
115385eff1c502e995d1f9668cc9def72d5db59f21b13sewardj                                                    binop( Iop_And32,
115395eff1c502e995d1f9668cc9def72d5db59f21b13sewardj                                                           mkU32( DCM ),
115405eff1c502e995d1f9668cc9def72d5db59f21b13sewardj                                                           mkexpr( DCM_calc ) ),
115415eff1c502e995d1f9668cc9def72d5db59f21b13sewardj                                                     mkU32( 0 ) ) ),
115425eff1c502e995d1f9668cc9def72d5db59f21b13sewardj                                       mkU8( 1 ) ) ) );
115435eff1c502e995d1f9668cc9def72d5db59f21b13sewardj
115445eff1c502e995d1f9668cc9def72d5db59f21b13sewardj   putGST_field( PPC_GST_CR, mkexpr( field ), crfD );
115455eff1c502e995d1f9668cc9def72d5db59f21b13sewardj   return True;
115465eff1c502e995d1f9668cc9def72d5db59f21b13sewardj}
115475eff1c502e995d1f9668cc9def72d5db59f21b13sewardj
115484c96e61dd85c172b999d6afc88ce6640aeba9962sewardjstatic Bool dis_dfp_bcd(UInt theInstr) {
115494c96e61dd85c172b999d6afc88ce6640aeba9962sewardj   UInt opc2        = ifieldOPClo10( theInstr );
115504c96e61dd85c172b999d6afc88ce6640aeba9962sewardj   ULong sp         = IFIELD(theInstr, 19, 2);
115514c96e61dd85c172b999d6afc88ce6640aeba9962sewardj   ULong s          = IFIELD(theInstr, 20, 1);
115524c96e61dd85c172b999d6afc88ce6640aeba9962sewardj   UChar frT_addr   = ifieldRegDS( theInstr );
115534c96e61dd85c172b999d6afc88ce6640aeba9962sewardj   UChar frB_addr   = ifieldRegB( theInstr );
115544c96e61dd85c172b999d6afc88ce6640aeba9962sewardj   IRTemp frB       = newTemp( Ity_D64 );
115554c96e61dd85c172b999d6afc88ce6640aeba9962sewardj   IRTemp frBI64    = newTemp( Ity_I64 );
115564c96e61dd85c172b999d6afc88ce6640aeba9962sewardj   IRTemp result    = newTemp( Ity_I64 );
115574c96e61dd85c172b999d6afc88ce6640aeba9962sewardj   IRTemp resultD64 = newTemp( Ity_D64 );
115584c96e61dd85c172b999d6afc88ce6640aeba9962sewardj   IRTemp bcd64     = newTemp( Ity_I64 );
115594c96e61dd85c172b999d6afc88ce6640aeba9962sewardj   IRTemp bcd_u     = newTemp( Ity_I32 );
115604c96e61dd85c172b999d6afc88ce6640aeba9962sewardj   IRTemp bcd_l     = newTemp( Ity_I32 );
115614c96e61dd85c172b999d6afc88ce6640aeba9962sewardj   IRTemp dbcd_u    = newTemp( Ity_I32 );
115624c96e61dd85c172b999d6afc88ce6640aeba9962sewardj   IRTemp dbcd_l    = newTemp( Ity_I32 );
115634c96e61dd85c172b999d6afc88ce6640aeba9962sewardj   IRTemp lmd       = newTemp( Ity_I32 );
115644c96e61dd85c172b999d6afc88ce6640aeba9962sewardj
115654c96e61dd85c172b999d6afc88ce6640aeba9962sewardj   assign( frB, getDReg( frB_addr ) );
115664c96e61dd85c172b999d6afc88ce6640aeba9962sewardj   assign( frBI64, unop( Iop_ReinterpD64asI64, mkexpr( frB ) ) );
115674c96e61dd85c172b999d6afc88ce6640aeba9962sewardj
115684c96e61dd85c172b999d6afc88ce6640aeba9962sewardj   switch ( opc2 ) {
115694c96e61dd85c172b999d6afc88ce6640aeba9962sewardj   case 0x142: // ddedpd   DFP Decode DPD to BCD
115704c96e61dd85c172b999d6afc88ce6640aeba9962sewardj      DIP( "ddedpd %llu,r%u,r%u\n", sp, frT_addr, frB_addr );
115714c96e61dd85c172b999d6afc88ce6640aeba9962sewardj
115724c96e61dd85c172b999d6afc88ce6640aeba9962sewardj         assign( bcd64, unop( Iop_DPBtoBCD, mkexpr( frBI64 ) ) );
115734c96e61dd85c172b999d6afc88ce6640aeba9962sewardj         assign( bcd_u, unop( Iop_64HIto32, mkexpr( bcd64 ) ) );
115744c96e61dd85c172b999d6afc88ce6640aeba9962sewardj         assign( bcd_l, unop( Iop_64to32, mkexpr( bcd64 ) ) );
115754c96e61dd85c172b999d6afc88ce6640aeba9962sewardj
115764c96e61dd85c172b999d6afc88ce6640aeba9962sewardj      if ( ( sp == 0 ) || ( sp == 1 ) ) {
115774c96e61dd85c172b999d6afc88ce6640aeba9962sewardj         /* Unsigned BCD string */
115784c96e61dd85c172b999d6afc88ce6640aeba9962sewardj         Get_lmd( &lmd,
115794c96e61dd85c172b999d6afc88ce6640aeba9962sewardj                  binop( Iop_Shr32,
115804c96e61dd85c172b999d6afc88ce6640aeba9962sewardj                         unop( Iop_64HIto32, mkexpr( frBI64 ) ),
115814c96e61dd85c172b999d6afc88ce6640aeba9962sewardj                         mkU8( 31 - 5 ) ) ); // G-field[0:4]
115824c96e61dd85c172b999d6afc88ce6640aeba9962sewardj
115834c96e61dd85c172b999d6afc88ce6640aeba9962sewardj         assign( result,
115844c96e61dd85c172b999d6afc88ce6640aeba9962sewardj                 binop( Iop_32HLto64,
115854c96e61dd85c172b999d6afc88ce6640aeba9962sewardj                        binop( Iop_Or32,
115864c96e61dd85c172b999d6afc88ce6640aeba9962sewardj                               binop( Iop_Shl32, mkexpr( lmd ), mkU8( 28 ) ),
115874c96e61dd85c172b999d6afc88ce6640aeba9962sewardj                               mkexpr( bcd_u ) ),
115884c96e61dd85c172b999d6afc88ce6640aeba9962sewardj                        mkexpr( bcd_l ) ) );
115894c96e61dd85c172b999d6afc88ce6640aeba9962sewardj
115904c96e61dd85c172b999d6afc88ce6640aeba9962sewardj      } else {
115914c96e61dd85c172b999d6afc88ce6640aeba9962sewardj         /* Signed BCD string, the cases for sp 2 and 3 only differ in how
115924c96e61dd85c172b999d6afc88ce6640aeba9962sewardj          * the positive and negative values are encoded in the least
115934c96e61dd85c172b999d6afc88ce6640aeba9962sewardj          * significant bits.
115944c96e61dd85c172b999d6afc88ce6640aeba9962sewardj          */
115954c96e61dd85c172b999d6afc88ce6640aeba9962sewardj         IRTemp sign = newTemp( Ity_I32 );
115964c96e61dd85c172b999d6afc88ce6640aeba9962sewardj
115974c96e61dd85c172b999d6afc88ce6640aeba9962sewardj         if (sp == 2) {
115984c96e61dd85c172b999d6afc88ce6640aeba9962sewardj            /* Positive sign = 0xC, negative sign = 0xD */
115994c96e61dd85c172b999d6afc88ce6640aeba9962sewardj
116004c96e61dd85c172b999d6afc88ce6640aeba9962sewardj            assign( sign,
116014c96e61dd85c172b999d6afc88ce6640aeba9962sewardj                    binop( Iop_Or32,
116024c96e61dd85c172b999d6afc88ce6640aeba9962sewardj                           binop( Iop_Shr32,
116034c96e61dd85c172b999d6afc88ce6640aeba9962sewardj                                  unop( Iop_64HIto32, mkexpr( frBI64 ) ),
116044c96e61dd85c172b999d6afc88ce6640aeba9962sewardj                                  mkU8( 31 ) ),
116054c96e61dd85c172b999d6afc88ce6640aeba9962sewardj                           mkU32( 0xC ) ) );
116064c96e61dd85c172b999d6afc88ce6640aeba9962sewardj
116074c96e61dd85c172b999d6afc88ce6640aeba9962sewardj         } else if ( sp == 3 ) {
116084c96e61dd85c172b999d6afc88ce6640aeba9962sewardj            /* Positive sign = 0xF, negative sign = 0xD */
116094c96e61dd85c172b999d6afc88ce6640aeba9962sewardj            IRTemp tmp32 = newTemp( Ity_I32 );
116104c96e61dd85c172b999d6afc88ce6640aeba9962sewardj
116114c96e61dd85c172b999d6afc88ce6640aeba9962sewardj            /* Complement sign bit then OR into bit position 1 */
116124c96e61dd85c172b999d6afc88ce6640aeba9962sewardj            assign( tmp32,
116134c96e61dd85c172b999d6afc88ce6640aeba9962sewardj                    binop( Iop_Xor32,
116144c96e61dd85c172b999d6afc88ce6640aeba9962sewardj                           binop( Iop_Shr32,
116154c96e61dd85c172b999d6afc88ce6640aeba9962sewardj                                  unop( Iop_64HIto32, mkexpr( frBI64 ) ),
116164c96e61dd85c172b999d6afc88ce6640aeba9962sewardj                                  mkU8( 30 ) ),
116174c96e61dd85c172b999d6afc88ce6640aeba9962sewardj                           mkU32( 0x2 ) ) );
116184c96e61dd85c172b999d6afc88ce6640aeba9962sewardj
116194c96e61dd85c172b999d6afc88ce6640aeba9962sewardj            assign( sign, binop( Iop_Or32, mkexpr( tmp32 ), mkU32( 0xD ) ) );
116204c96e61dd85c172b999d6afc88ce6640aeba9962sewardj
116214c96e61dd85c172b999d6afc88ce6640aeba9962sewardj         } else {
116224c96e61dd85c172b999d6afc88ce6640aeba9962sewardj            vpanic( "The impossible happened: dis_dfp_bcd(ppc), undefined SP field" );
116234c96e61dd85c172b999d6afc88ce6640aeba9962sewardj         }
116244c96e61dd85c172b999d6afc88ce6640aeba9962sewardj
116254c96e61dd85c172b999d6afc88ce6640aeba9962sewardj         /* Put sign in bottom 4 bits, move most significant 4-bits from
116264c96e61dd85c172b999d6afc88ce6640aeba9962sewardj          * bcd_l to bcd_u.
116274c96e61dd85c172b999d6afc88ce6640aeba9962sewardj          */
116284c96e61dd85c172b999d6afc88ce6640aeba9962sewardj         assign( result,
116294c96e61dd85c172b999d6afc88ce6640aeba9962sewardj                 binop( Iop_32HLto64,
116304c96e61dd85c172b999d6afc88ce6640aeba9962sewardj                        binop( Iop_Or32,
116314c96e61dd85c172b999d6afc88ce6640aeba9962sewardj                               binop( Iop_Shr32,
116324c96e61dd85c172b999d6afc88ce6640aeba9962sewardj                                      mkexpr( bcd_l ),
116334c96e61dd85c172b999d6afc88ce6640aeba9962sewardj                                      mkU8( 28 ) ),
116344c96e61dd85c172b999d6afc88ce6640aeba9962sewardj                               binop( Iop_Shl32,
116354c96e61dd85c172b999d6afc88ce6640aeba9962sewardj                                      mkexpr( bcd_u ),
116364c96e61dd85c172b999d6afc88ce6640aeba9962sewardj                                      mkU8( 4 ) ) ),
116374c96e61dd85c172b999d6afc88ce6640aeba9962sewardj                        binop( Iop_Or32,
116384c96e61dd85c172b999d6afc88ce6640aeba9962sewardj                                      mkexpr( sign ),
116394c96e61dd85c172b999d6afc88ce6640aeba9962sewardj                               binop( Iop_Shl32,
116404c96e61dd85c172b999d6afc88ce6640aeba9962sewardj                                      mkexpr( bcd_l ),
116414c96e61dd85c172b999d6afc88ce6640aeba9962sewardj                                      mkU8( 4 ) ) ) ) );
116424c96e61dd85c172b999d6afc88ce6640aeba9962sewardj      }
116434c96e61dd85c172b999d6afc88ce6640aeba9962sewardj
116444c96e61dd85c172b999d6afc88ce6640aeba9962sewardj      putDReg( frT_addr, unop( Iop_ReinterpI64asD64, mkexpr( result ) ) );
116454c96e61dd85c172b999d6afc88ce6640aeba9962sewardj      break;
116464c96e61dd85c172b999d6afc88ce6640aeba9962sewardj
116474c96e61dd85c172b999d6afc88ce6640aeba9962sewardj   case 0x342: // denbcd   DFP Encode BCD to DPD
116484c96e61dd85c172b999d6afc88ce6640aeba9962sewardj   {
116494c96e61dd85c172b999d6afc88ce6640aeba9962sewardj      IRTemp valid_mask   = newTemp( Ity_I32 );
116504c96e61dd85c172b999d6afc88ce6640aeba9962sewardj      IRTemp invalid_mask = newTemp( Ity_I32 );
116514c96e61dd85c172b999d6afc88ce6640aeba9962sewardj      IRTemp without_lmd  = newTemp( Ity_I64 );
116524c96e61dd85c172b999d6afc88ce6640aeba9962sewardj      IRTemp tmp64        = newTemp( Ity_I64 );
116534c96e61dd85c172b999d6afc88ce6640aeba9962sewardj      IRTemp dbcd64       = newTemp( Ity_I64 );
116544c96e61dd85c172b999d6afc88ce6640aeba9962sewardj      IRTemp left_exp     = newTemp( Ity_I32 );
116554c96e61dd85c172b999d6afc88ce6640aeba9962sewardj      IRTemp g0_4         = newTemp( Ity_I32 );
116564c96e61dd85c172b999d6afc88ce6640aeba9962sewardj
116574c96e61dd85c172b999d6afc88ce6640aeba9962sewardj      DIP( "denbcd %llu,r%u,r%u\n", s, frT_addr, frB_addr );
116584c96e61dd85c172b999d6afc88ce6640aeba9962sewardj
116594c96e61dd85c172b999d6afc88ce6640aeba9962sewardj      if ( s == 0 ) {
116604c96e61dd85c172b999d6afc88ce6640aeba9962sewardj         /* Unsigned BCD string */
116614c96e61dd85c172b999d6afc88ce6640aeba9962sewardj         assign( dbcd64, unop( Iop_BCDtoDPB, mkexpr(frBI64 ) ) );
116624c96e61dd85c172b999d6afc88ce6640aeba9962sewardj         assign( dbcd_u, unop( Iop_64HIto32, mkexpr( dbcd64 ) ) );
116634c96e61dd85c172b999d6afc88ce6640aeba9962sewardj         assign( dbcd_l, unop( Iop_64to32, mkexpr( dbcd64 ) ) );
116644c96e61dd85c172b999d6afc88ce6640aeba9962sewardj
116654c96e61dd85c172b999d6afc88ce6640aeba9962sewardj         assign( lmd,
116664c96e61dd85c172b999d6afc88ce6640aeba9962sewardj                 binop( Iop_Shr32,
116674c96e61dd85c172b999d6afc88ce6640aeba9962sewardj                        binop( Iop_And32,
116684c96e61dd85c172b999d6afc88ce6640aeba9962sewardj                               unop( Iop_64HIto32, mkexpr( frBI64 ) ),
116694c96e61dd85c172b999d6afc88ce6640aeba9962sewardj                               mkU32( 0xF0000000 ) ),
116704c96e61dd85c172b999d6afc88ce6640aeba9962sewardj                        mkU8( 28 ) ) );
116714c96e61dd85c172b999d6afc88ce6640aeba9962sewardj
116724c96e61dd85c172b999d6afc88ce6640aeba9962sewardj         assign( invalid_mask,
116734c96e61dd85c172b999d6afc88ce6640aeba9962sewardj                 bcd_digit_inval( unop( Iop_64HIto32, mkexpr( frBI64 ) ),
116744c96e61dd85c172b999d6afc88ce6640aeba9962sewardj                                  unop( Iop_64to32, mkexpr( frBI64 ) ) ) );
116754c96e61dd85c172b999d6afc88ce6640aeba9962sewardj         assign( valid_mask, unop( Iop_Not32, mkexpr( invalid_mask ) ) );
116764c96e61dd85c172b999d6afc88ce6640aeba9962sewardj
116774c96e61dd85c172b999d6afc88ce6640aeba9962sewardj         assign( without_lmd,
116784c96e61dd85c172b999d6afc88ce6640aeba9962sewardj                 unop( Iop_ReinterpD64asI64,
116794c96e61dd85c172b999d6afc88ce6640aeba9962sewardj                       binop( Iop_InsertExpD64,
11680cea07ccbe9aa9b5fd8e9b318471c6c74aa147acbcarll                              mkU64( DFP_LONG_BIAS ),
116814c96e61dd85c172b999d6afc88ce6640aeba9962sewardj                              unop( Iop_ReinterpI64asD64,
116824c96e61dd85c172b999d6afc88ce6640aeba9962sewardj                                    binop( Iop_32HLto64,
116834c96e61dd85c172b999d6afc88ce6640aeba9962sewardj                                           mkexpr( dbcd_u ),
116844c96e61dd85c172b999d6afc88ce6640aeba9962sewardj                                           mkexpr( dbcd_l ) ) ) ) ) );
116854c96e61dd85c172b999d6afc88ce6640aeba9962sewardj         assign( left_exp,
116864c96e61dd85c172b999d6afc88ce6640aeba9962sewardj                 binop( Iop_Shr32,
116874c96e61dd85c172b999d6afc88ce6640aeba9962sewardj                        binop( Iop_And32,
116884c96e61dd85c172b999d6afc88ce6640aeba9962sewardj                               unop( Iop_64HIto32, mkexpr( without_lmd ) ),
116894c96e61dd85c172b999d6afc88ce6640aeba9962sewardj                               mkU32( 0x60000000 ) ),
116904c96e61dd85c172b999d6afc88ce6640aeba9962sewardj                        mkU8( 29 ) ) );
116914c96e61dd85c172b999d6afc88ce6640aeba9962sewardj
116924c96e61dd85c172b999d6afc88ce6640aeba9962sewardj         assign( g0_4,
116934c96e61dd85c172b999d6afc88ce6640aeba9962sewardj                 binop( Iop_Shl32,
116944c96e61dd85c172b999d6afc88ce6640aeba9962sewardj                        Gfield_encoding( mkexpr( left_exp ), mkexpr( lmd ) ),
116954c96e61dd85c172b999d6afc88ce6640aeba9962sewardj                        mkU8( 26 ) ) );
116964c96e61dd85c172b999d6afc88ce6640aeba9962sewardj
116974c96e61dd85c172b999d6afc88ce6640aeba9962sewardj         assign( tmp64,
116984c96e61dd85c172b999d6afc88ce6640aeba9962sewardj                 binop( Iop_32HLto64,
116994c96e61dd85c172b999d6afc88ce6640aeba9962sewardj                        binop( Iop_Or32,
117004c96e61dd85c172b999d6afc88ce6640aeba9962sewardj                               binop( Iop_And32,
117014c96e61dd85c172b999d6afc88ce6640aeba9962sewardj                                      unop( Iop_64HIto32,
117024c96e61dd85c172b999d6afc88ce6640aeba9962sewardj                                            mkexpr( without_lmd ) ),
117034c96e61dd85c172b999d6afc88ce6640aeba9962sewardj                                      mkU32( 0x83FFFFFF ) ),
117044c96e61dd85c172b999d6afc88ce6640aeba9962sewardj                               mkexpr( g0_4 ) ),
117054c96e61dd85c172b999d6afc88ce6640aeba9962sewardj                        unop( Iop_64to32, mkexpr( without_lmd ) ) ) );
117064c96e61dd85c172b999d6afc88ce6640aeba9962sewardj
117074c96e61dd85c172b999d6afc88ce6640aeba9962sewardj      } else if ( s == 1 ) {
117084c96e61dd85c172b999d6afc88ce6640aeba9962sewardj         IRTemp sign = newTemp( Ity_I32 );
117094c96e61dd85c172b999d6afc88ce6640aeba9962sewardj         IRTemp sign_bit = newTemp( Ity_I32 );
117104c96e61dd85c172b999d6afc88ce6640aeba9962sewardj         IRTemp pos_sign_mask = newTemp( Ity_I32 );
117114c96e61dd85c172b999d6afc88ce6640aeba9962sewardj         IRTemp neg_sign_mask = newTemp( Ity_I32 );
117124c96e61dd85c172b999d6afc88ce6640aeba9962sewardj         IRTemp tmp = newTemp( Ity_I64 );
117134c96e61dd85c172b999d6afc88ce6640aeba9962sewardj
117144c96e61dd85c172b999d6afc88ce6640aeba9962sewardj         /* Signed BCD string, least significant 4 bits are sign bits
117154c96e61dd85c172b999d6afc88ce6640aeba9962sewardj          * positive sign = 0xC, negative sign = 0xD
117164c96e61dd85c172b999d6afc88ce6640aeba9962sewardj          */
117174c96e61dd85c172b999d6afc88ce6640aeba9962sewardj         assign( tmp, unop( Iop_BCDtoDPB,
117184c96e61dd85c172b999d6afc88ce6640aeba9962sewardj                            binop( Iop_32HLto64,
117194c96e61dd85c172b999d6afc88ce6640aeba9962sewardj                                   binop( Iop_Shr32,
117204c96e61dd85c172b999d6afc88ce6640aeba9962sewardj                                          unop( Iop_64HIto32,
117214c96e61dd85c172b999d6afc88ce6640aeba9962sewardj                                                mkexpr( frBI64 ) ),
117224c96e61dd85c172b999d6afc88ce6640aeba9962sewardj                                                mkU8( 4 ) ),
117234c96e61dd85c172b999d6afc88ce6640aeba9962sewardj                                   binop( Iop_Or32,
117244c96e61dd85c172b999d6afc88ce6640aeba9962sewardj                                          binop( Iop_Shr32,
117254c96e61dd85c172b999d6afc88ce6640aeba9962sewardj                                                 unop( Iop_64to32,
117264c96e61dd85c172b999d6afc88ce6640aeba9962sewardj                                                       mkexpr( frBI64 ) ),
117274c96e61dd85c172b999d6afc88ce6640aeba9962sewardj                                                  mkU8( 4 ) ),
117284c96e61dd85c172b999d6afc88ce6640aeba9962sewardj                                          binop( Iop_Shl32,
117294c96e61dd85c172b999d6afc88ce6640aeba9962sewardj                                                 unop( Iop_64HIto32,
117304c96e61dd85c172b999d6afc88ce6640aeba9962sewardj                                                       mkexpr( frBI64 ) ),
117314c96e61dd85c172b999d6afc88ce6640aeba9962sewardj                                                       mkU8( 28 ) ) ) ) ) );
117324c96e61dd85c172b999d6afc88ce6640aeba9962sewardj
117334c96e61dd85c172b999d6afc88ce6640aeba9962sewardj         assign( dbcd_u, unop( Iop_64HIto32, mkexpr( tmp ) ) );
117344c96e61dd85c172b999d6afc88ce6640aeba9962sewardj         assign( dbcd_l, unop( Iop_64to32, mkexpr( tmp ) ) );
117354c96e61dd85c172b999d6afc88ce6640aeba9962sewardj
117364c96e61dd85c172b999d6afc88ce6640aeba9962sewardj         /* Get the sign of the BCD string. */
117374c96e61dd85c172b999d6afc88ce6640aeba9962sewardj         assign( sign,
117384c96e61dd85c172b999d6afc88ce6640aeba9962sewardj                 binop( Iop_And32,
117394c96e61dd85c172b999d6afc88ce6640aeba9962sewardj                        unop( Iop_64to32, mkexpr( frBI64 ) ),
117404c96e61dd85c172b999d6afc88ce6640aeba9962sewardj                        mkU32( 0xF ) ) );
117414c96e61dd85c172b999d6afc88ce6640aeba9962sewardj
117424c96e61dd85c172b999d6afc88ce6640aeba9962sewardj         assign( neg_sign_mask, Generate_neg_sign_mask( mkexpr( sign ) ) );
117434c96e61dd85c172b999d6afc88ce6640aeba9962sewardj         assign( pos_sign_mask, Generate_pos_sign_mask( mkexpr( sign ) ) );
117444c96e61dd85c172b999d6afc88ce6640aeba9962sewardj         assign( sign_bit,
117454c96e61dd85c172b999d6afc88ce6640aeba9962sewardj                 Generate_sign_bit( mkexpr( pos_sign_mask ),
117464c96e61dd85c172b999d6afc88ce6640aeba9962sewardj                                    mkexpr( neg_sign_mask ) ) );
117474c96e61dd85c172b999d6afc88ce6640aeba9962sewardj
117484c96e61dd85c172b999d6afc88ce6640aeba9962sewardj         /* Check for invalid sign and BCD digit.  Don't check the bottom
117494c96e61dd85c172b999d6afc88ce6640aeba9962sewardj          * four bits of bcd_l as that is the sign value.
117504c96e61dd85c172b999d6afc88ce6640aeba9962sewardj          */
117514c96e61dd85c172b999d6afc88ce6640aeba9962sewardj         assign( invalid_mask,
117524c96e61dd85c172b999d6afc88ce6640aeba9962sewardj                 Generate_inv_mask(
117534c96e61dd85c172b999d6afc88ce6640aeba9962sewardj                                   bcd_digit_inval( unop( Iop_64HIto32,
117544c96e61dd85c172b999d6afc88ce6640aeba9962sewardj                                                          mkexpr( frBI64 ) ),
117554c96e61dd85c172b999d6afc88ce6640aeba9962sewardj                                                    binop( Iop_Shr32,
117564c96e61dd85c172b999d6afc88ce6640aeba9962sewardj                                                           unop( Iop_64to32,
117574c96e61dd85c172b999d6afc88ce6640aeba9962sewardj                                                                 mkexpr( frBI64 ) ),
117584c96e61dd85c172b999d6afc88ce6640aeba9962sewardj                                                           mkU8( 4 ) ) ),
117594c96e61dd85c172b999d6afc88ce6640aeba9962sewardj                                   mkexpr( pos_sign_mask ),
117604c96e61dd85c172b999d6afc88ce6640aeba9962sewardj                                   mkexpr( neg_sign_mask ) ) );
117614c96e61dd85c172b999d6afc88ce6640aeba9962sewardj
117624c96e61dd85c172b999d6afc88ce6640aeba9962sewardj         assign( valid_mask, unop( Iop_Not32, mkexpr( invalid_mask ) ) );
117634c96e61dd85c172b999d6afc88ce6640aeba9962sewardj
117644c96e61dd85c172b999d6afc88ce6640aeba9962sewardj         /* Generate the result assuming the sign value was valid. */
117654c96e61dd85c172b999d6afc88ce6640aeba9962sewardj         assign( tmp64,
117664c96e61dd85c172b999d6afc88ce6640aeba9962sewardj                 unop( Iop_ReinterpD64asI64,
117674c96e61dd85c172b999d6afc88ce6640aeba9962sewardj                       binop( Iop_InsertExpD64,
11768cea07ccbe9aa9b5fd8e9b318471c6c74aa147acbcarll                              mkU64( DFP_LONG_BIAS ),
117694c96e61dd85c172b999d6afc88ce6640aeba9962sewardj                              unop( Iop_ReinterpI64asD64,
117704c96e61dd85c172b999d6afc88ce6640aeba9962sewardj                                    binop( Iop_32HLto64,
117714c96e61dd85c172b999d6afc88ce6640aeba9962sewardj                                           binop( Iop_Or32,
117724c96e61dd85c172b999d6afc88ce6640aeba9962sewardj                                                  mkexpr( dbcd_u ),
117734c96e61dd85c172b999d6afc88ce6640aeba9962sewardj                                                  mkexpr( sign_bit ) ),
117744c96e61dd85c172b999d6afc88ce6640aeba9962sewardj                                           mkexpr( dbcd_l ) ) ) ) ) );
117754c96e61dd85c172b999d6afc88ce6640aeba9962sewardj      }
117764c96e61dd85c172b999d6afc88ce6640aeba9962sewardj
117774c96e61dd85c172b999d6afc88ce6640aeba9962sewardj      /* Generate the value to store depending on the validity of the
117784c96e61dd85c172b999d6afc88ce6640aeba9962sewardj       * sign value and the validity of the BCD digits.
117794c96e61dd85c172b999d6afc88ce6640aeba9962sewardj       */
117804c96e61dd85c172b999d6afc88ce6640aeba9962sewardj      assign( resultD64,
117814c96e61dd85c172b999d6afc88ce6640aeba9962sewardj              unop( Iop_ReinterpI64asD64,
117824c96e61dd85c172b999d6afc88ce6640aeba9962sewardj                    binop( Iop_32HLto64,
117834c96e61dd85c172b999d6afc88ce6640aeba9962sewardj                           binop( Iop_Or32,
117844c96e61dd85c172b999d6afc88ce6640aeba9962sewardj                                  binop( Iop_And32,
117854c96e61dd85c172b999d6afc88ce6640aeba9962sewardj                                         mkexpr( valid_mask ),
117864c96e61dd85c172b999d6afc88ce6640aeba9962sewardj                                         unop( Iop_64HIto32,
117874c96e61dd85c172b999d6afc88ce6640aeba9962sewardj                                               mkexpr( tmp64 ) ) ),
117884c96e61dd85c172b999d6afc88ce6640aeba9962sewardj                                  binop( Iop_And32,
117894c96e61dd85c172b999d6afc88ce6640aeba9962sewardj                                         mkU32( 0x7C000000 ),
117904c96e61dd85c172b999d6afc88ce6640aeba9962sewardj                                         mkexpr( invalid_mask ) ) ),
117914c96e61dd85c172b999d6afc88ce6640aeba9962sewardj                           binop( Iop_Or32,
117924c96e61dd85c172b999d6afc88ce6640aeba9962sewardj                                  binop( Iop_And32,
117934c96e61dd85c172b999d6afc88ce6640aeba9962sewardj                                         mkexpr( valid_mask ),
117944c96e61dd85c172b999d6afc88ce6640aeba9962sewardj                                         unop( Iop_64to32, mkexpr( tmp64 ) ) ),
117954c96e61dd85c172b999d6afc88ce6640aeba9962sewardj                                  binop( Iop_And32,
117964c96e61dd85c172b999d6afc88ce6640aeba9962sewardj                                         mkU32( 0x0 ),
117974c96e61dd85c172b999d6afc88ce6640aeba9962sewardj                                         mkexpr( invalid_mask ) ) ) ) ) );
117984c96e61dd85c172b999d6afc88ce6640aeba9962sewardj      putDReg( frT_addr, mkexpr( resultD64 ) );
117994c96e61dd85c172b999d6afc88ce6640aeba9962sewardj   }
118004c96e61dd85c172b999d6afc88ce6640aeba9962sewardj   break;
118014c96e61dd85c172b999d6afc88ce6640aeba9962sewardj   default:
118024c96e61dd85c172b999d6afc88ce6640aeba9962sewardj      vpanic( "ERROR: dis_dfp_bcd(ppc), undefined opc2 case " );
118034c96e61dd85c172b999d6afc88ce6640aeba9962sewardj      return False;
118044c96e61dd85c172b999d6afc88ce6640aeba9962sewardj   }
118054c96e61dd85c172b999d6afc88ce6640aeba9962sewardj   return True;
118064c96e61dd85c172b999d6afc88ce6640aeba9962sewardj}
118074c96e61dd85c172b999d6afc88ce6640aeba9962sewardj
118084c96e61dd85c172b999d6afc88ce6640aeba9962sewardjstatic Bool dis_dfp_bcdq( UInt theInstr )
118094c96e61dd85c172b999d6afc88ce6640aeba9962sewardj{
118104c96e61dd85c172b999d6afc88ce6640aeba9962sewardj   UInt opc2        = ifieldOPClo10( theInstr );
118114c96e61dd85c172b999d6afc88ce6640aeba9962sewardj   ULong sp         = IFIELD(theInstr, 19, 2);
118124c96e61dd85c172b999d6afc88ce6640aeba9962sewardj   ULong s          = IFIELD(theInstr, 20, 1);
118134c96e61dd85c172b999d6afc88ce6640aeba9962sewardj   IRTemp frB_hi    = newTemp( Ity_D64 );
118144c96e61dd85c172b999d6afc88ce6640aeba9962sewardj   IRTemp frB_lo    = newTemp( Ity_D64 );
118154c96e61dd85c172b999d6afc88ce6640aeba9962sewardj   IRTemp frBI64_hi = newTemp( Ity_I64 );
118164c96e61dd85c172b999d6afc88ce6640aeba9962sewardj   IRTemp frBI64_lo = newTemp( Ity_I64 );
118174c96e61dd85c172b999d6afc88ce6640aeba9962sewardj   UChar frT_addr   = ifieldRegDS( theInstr );
118184c96e61dd85c172b999d6afc88ce6640aeba9962sewardj   UChar frB_addr   = ifieldRegB( theInstr );
118194c96e61dd85c172b999d6afc88ce6640aeba9962sewardj
118204c96e61dd85c172b999d6afc88ce6640aeba9962sewardj   IRTemp lmd       = newTemp( Ity_I32 );
118214c96e61dd85c172b999d6afc88ce6640aeba9962sewardj   IRTemp result_hi = newTemp( Ity_I64 );
118224c96e61dd85c172b999d6afc88ce6640aeba9962sewardj   IRTemp result_lo = newTemp( Ity_I64 );
118234c96e61dd85c172b999d6afc88ce6640aeba9962sewardj
118244c96e61dd85c172b999d6afc88ce6640aeba9962sewardj   assign( frB_hi, getDReg( frB_addr ) );
118254c96e61dd85c172b999d6afc88ce6640aeba9962sewardj   assign( frB_lo, getDReg( frB_addr + 1 ) );
118264c96e61dd85c172b999d6afc88ce6640aeba9962sewardj   assign( frBI64_hi, unop( Iop_ReinterpD64asI64, mkexpr( frB_hi ) ) );
118274c96e61dd85c172b999d6afc88ce6640aeba9962sewardj   assign( frBI64_lo, unop( Iop_ReinterpD64asI64, mkexpr( frB_lo ) ) );
118284c96e61dd85c172b999d6afc88ce6640aeba9962sewardj
118294c96e61dd85c172b999d6afc88ce6640aeba9962sewardj   switch ( opc2 ) {
118304c96e61dd85c172b999d6afc88ce6640aeba9962sewardj   case 0x142: // ddedpdq   DFP Decode DPD to BCD
118314c96e61dd85c172b999d6afc88ce6640aeba9962sewardj   {
118324c96e61dd85c172b999d6afc88ce6640aeba9962sewardj      IRTemp low_60_u = newTemp( Ity_I32 );
118334c96e61dd85c172b999d6afc88ce6640aeba9962sewardj      IRTemp low_60_l = newTemp( Ity_I32 );
118344c96e61dd85c172b999d6afc88ce6640aeba9962sewardj      IRTemp mid_60_u = newTemp( Ity_I32 );
118354c96e61dd85c172b999d6afc88ce6640aeba9962sewardj      IRTemp mid_60_l = newTemp( Ity_I32 );
118364c96e61dd85c172b999d6afc88ce6640aeba9962sewardj      IRTemp top_12_l = newTemp( Ity_I32 );
118374c96e61dd85c172b999d6afc88ce6640aeba9962sewardj
118384c96e61dd85c172b999d6afc88ce6640aeba9962sewardj      DIP( "ddedpdq %llu,r%u,r%u\n", sp, frT_addr, frB_addr );
118394c96e61dd85c172b999d6afc88ce6640aeba9962sewardj
118404c96e61dd85c172b999d6afc88ce6640aeba9962sewardj      /* Note, instruction only stores the lower 32 BCD digits in
118414c96e61dd85c172b999d6afc88ce6640aeba9962sewardj       * the result
118424c96e61dd85c172b999d6afc88ce6640aeba9962sewardj       */
118434c96e61dd85c172b999d6afc88ce6640aeba9962sewardj      Generate_132_bit_bcd_string( mkexpr( frBI64_hi ),
118444c96e61dd85c172b999d6afc88ce6640aeba9962sewardj                                   mkexpr( frBI64_lo ),
118454c96e61dd85c172b999d6afc88ce6640aeba9962sewardj                                   &top_12_l,
118464c96e61dd85c172b999d6afc88ce6640aeba9962sewardj                                   &mid_60_u,
118474c96e61dd85c172b999d6afc88ce6640aeba9962sewardj                                   &mid_60_l,
118484c96e61dd85c172b999d6afc88ce6640aeba9962sewardj                                   &low_60_u,
118494c96e61dd85c172b999d6afc88ce6640aeba9962sewardj                                   &low_60_l );
118504c96e61dd85c172b999d6afc88ce6640aeba9962sewardj
118514c96e61dd85c172b999d6afc88ce6640aeba9962sewardj      if ( ( sp == 0 ) || ( sp == 1 ) ) {
118524c96e61dd85c172b999d6afc88ce6640aeba9962sewardj         /* Unsigned BCD string */
118534c96e61dd85c172b999d6afc88ce6640aeba9962sewardj         assign( result_hi,
118544c96e61dd85c172b999d6afc88ce6640aeba9962sewardj                 binop( Iop_32HLto64,
118554c96e61dd85c172b999d6afc88ce6640aeba9962sewardj                        binop( Iop_Or32,
118564c96e61dd85c172b999d6afc88ce6640aeba9962sewardj                               binop( Iop_Shl32,
118574c96e61dd85c172b999d6afc88ce6640aeba9962sewardj                                      mkexpr( top_12_l ),
118584c96e61dd85c172b999d6afc88ce6640aeba9962sewardj                                      mkU8( 24 ) ),
118594c96e61dd85c172b999d6afc88ce6640aeba9962sewardj                               binop( Iop_Shr32,
118604c96e61dd85c172b999d6afc88ce6640aeba9962sewardj                                      mkexpr( mid_60_u ),
118614c96e61dd85c172b999d6afc88ce6640aeba9962sewardj                                      mkU8( 4 ) ) ),
118624c96e61dd85c172b999d6afc88ce6640aeba9962sewardj                        binop( Iop_Or32,
118634c96e61dd85c172b999d6afc88ce6640aeba9962sewardj                               binop( Iop_Shl32,
118644c96e61dd85c172b999d6afc88ce6640aeba9962sewardj                                      mkexpr( mid_60_u ),
118654c96e61dd85c172b999d6afc88ce6640aeba9962sewardj                                      mkU8( 28 ) ),
118664c96e61dd85c172b999d6afc88ce6640aeba9962sewardj                               binop( Iop_Shr32,
118674c96e61dd85c172b999d6afc88ce6640aeba9962sewardj                                      mkexpr( mid_60_l ),
118684c96e61dd85c172b999d6afc88ce6640aeba9962sewardj                                      mkU8( 4 ) ) ) ) );
118694c96e61dd85c172b999d6afc88ce6640aeba9962sewardj
118704c96e61dd85c172b999d6afc88ce6640aeba9962sewardj         assign( result_lo,
118714c96e61dd85c172b999d6afc88ce6640aeba9962sewardj                 binop( Iop_32HLto64,
118724c96e61dd85c172b999d6afc88ce6640aeba9962sewardj                        binop( Iop_Or32,
118734c96e61dd85c172b999d6afc88ce6640aeba9962sewardj                               binop( Iop_Shl32,
118744c96e61dd85c172b999d6afc88ce6640aeba9962sewardj                                      mkexpr( mid_60_l ),
118754c96e61dd85c172b999d6afc88ce6640aeba9962sewardj                                      mkU8( 28 ) ),
118764c96e61dd85c172b999d6afc88ce6640aeba9962sewardj                               mkexpr( low_60_u ) ),
118774c96e61dd85c172b999d6afc88ce6640aeba9962sewardj                        mkexpr( low_60_l ) ) );
118784c96e61dd85c172b999d6afc88ce6640aeba9962sewardj
118794c96e61dd85c172b999d6afc88ce6640aeba9962sewardj      } else {
118804c96e61dd85c172b999d6afc88ce6640aeba9962sewardj         /* Signed BCD string, the cases for sp 2 and 3 only differ in how
118814c96e61dd85c172b999d6afc88ce6640aeba9962sewardj          * the positive and negative values are encoded in the least
118824c96e61dd85c172b999d6afc88ce6640aeba9962sewardj          * significant bits.
118834c96e61dd85c172b999d6afc88ce6640aeba9962sewardj          */
118844c96e61dd85c172b999d6afc88ce6640aeba9962sewardj         IRTemp sign = newTemp( Ity_I32 );
118854c96e61dd85c172b999d6afc88ce6640aeba9962sewardj
118864c96e61dd85c172b999d6afc88ce6640aeba9962sewardj         if ( sp == 2 ) {
118874c96e61dd85c172b999d6afc88ce6640aeba9962sewardj            /* Positive sign = 0xC, negative sign = 0xD */
118884c96e61dd85c172b999d6afc88ce6640aeba9962sewardj            assign( sign,
118894c96e61dd85c172b999d6afc88ce6640aeba9962sewardj                    binop( Iop_Or32,
118904c96e61dd85c172b999d6afc88ce6640aeba9962sewardj                           binop( Iop_Shr32,
118914c96e61dd85c172b999d6afc88ce6640aeba9962sewardj                                  unop( Iop_64HIto32, mkexpr( frBI64_hi ) ),
118924c96e61dd85c172b999d6afc88ce6640aeba9962sewardj                                  mkU8( 31 ) ),
118934c96e61dd85c172b999d6afc88ce6640aeba9962sewardj                           mkU32( 0xC ) ) );
118944c96e61dd85c172b999d6afc88ce6640aeba9962sewardj
118954c96e61dd85c172b999d6afc88ce6640aeba9962sewardj         } else if ( sp == 3 ) {
118964c96e61dd85c172b999d6afc88ce6640aeba9962sewardj            IRTemp tmp32 = newTemp( Ity_I32 );
118974c96e61dd85c172b999d6afc88ce6640aeba9962sewardj
118984c96e61dd85c172b999d6afc88ce6640aeba9962sewardj            /* Positive sign = 0xF, negative sign = 0xD.
118994c96e61dd85c172b999d6afc88ce6640aeba9962sewardj             * Need to complement sign bit then OR into bit position 1.
119004c96e61dd85c172b999d6afc88ce6640aeba9962sewardj             */
119014c96e61dd85c172b999d6afc88ce6640aeba9962sewardj            assign( tmp32,
119024c96e61dd85c172b999d6afc88ce6640aeba9962sewardj                    binop( Iop_Xor32,
119034c96e61dd85c172b999d6afc88ce6640aeba9962sewardj                           binop( Iop_Shr32,
119044c96e61dd85c172b999d6afc88ce6640aeba9962sewardj                                  unop( Iop_64HIto32, mkexpr( frBI64_hi ) ),
119054c96e61dd85c172b999d6afc88ce6640aeba9962sewardj                                  mkU8( 30 ) ),
119064c96e61dd85c172b999d6afc88ce6640aeba9962sewardj                           mkU32( 0x2 ) ) );
119074c96e61dd85c172b999d6afc88ce6640aeba9962sewardj
119084c96e61dd85c172b999d6afc88ce6640aeba9962sewardj            assign( sign, binop( Iop_Or32, mkexpr( tmp32 ), mkU32( 0xD ) ) );
119094c96e61dd85c172b999d6afc88ce6640aeba9962sewardj
119104c96e61dd85c172b999d6afc88ce6640aeba9962sewardj         } else {
119114c96e61dd85c172b999d6afc88ce6640aeba9962sewardj            vpanic( "The impossible happened: dis_dfp_bcd(ppc), undefined SP field" );
119124c96e61dd85c172b999d6afc88ce6640aeba9962sewardj         }
119134c96e61dd85c172b999d6afc88ce6640aeba9962sewardj
119144c96e61dd85c172b999d6afc88ce6640aeba9962sewardj         assign( result_hi,
119154c96e61dd85c172b999d6afc88ce6640aeba9962sewardj                 binop( Iop_32HLto64,
119164c96e61dd85c172b999d6afc88ce6640aeba9962sewardj                        binop( Iop_Or32,
119174c96e61dd85c172b999d6afc88ce6640aeba9962sewardj                               binop( Iop_Shl32,
119184c96e61dd85c172b999d6afc88ce6640aeba9962sewardj                                      mkexpr( top_12_l ),
119194c96e61dd85c172b999d6afc88ce6640aeba9962sewardj                                      mkU8( 28 ) ),
119204c96e61dd85c172b999d6afc88ce6640aeba9962sewardj                               mkexpr( mid_60_u ) ),
119214c96e61dd85c172b999d6afc88ce6640aeba9962sewardj                        mkexpr( mid_60_l ) ) );
119224c96e61dd85c172b999d6afc88ce6640aeba9962sewardj
119234c96e61dd85c172b999d6afc88ce6640aeba9962sewardj         assign( result_lo,
119244c96e61dd85c172b999d6afc88ce6640aeba9962sewardj                 binop( Iop_32HLto64,
119254c96e61dd85c172b999d6afc88ce6640aeba9962sewardj                        binop( Iop_Or32,
119264c96e61dd85c172b999d6afc88ce6640aeba9962sewardj                               binop( Iop_Shl32,
119274c96e61dd85c172b999d6afc88ce6640aeba9962sewardj                                      mkexpr( low_60_u ),
119284c96e61dd85c172b999d6afc88ce6640aeba9962sewardj                                      mkU8( 4 ) ),
119294c96e61dd85c172b999d6afc88ce6640aeba9962sewardj                               binop( Iop_Shr32,
119304c96e61dd85c172b999d6afc88ce6640aeba9962sewardj                                      mkexpr( low_60_l ),
119314c96e61dd85c172b999d6afc88ce6640aeba9962sewardj                                      mkU8( 28 ) ) ),
119324c96e61dd85c172b999d6afc88ce6640aeba9962sewardj                        binop( Iop_Or32,
119334c96e61dd85c172b999d6afc88ce6640aeba9962sewardj                               binop( Iop_Shl32,
119344c96e61dd85c172b999d6afc88ce6640aeba9962sewardj                                      mkexpr( low_60_l ),
119354c96e61dd85c172b999d6afc88ce6640aeba9962sewardj                                      mkU8( 4 ) ),
119364c96e61dd85c172b999d6afc88ce6640aeba9962sewardj                               mkexpr( sign ) ) ) );
119374c96e61dd85c172b999d6afc88ce6640aeba9962sewardj      }
119384c96e61dd85c172b999d6afc88ce6640aeba9962sewardj
119394c96e61dd85c172b999d6afc88ce6640aeba9962sewardj      putDReg( frT_addr, unop( Iop_ReinterpI64asD64, mkexpr( result_hi ) ) );
119404c96e61dd85c172b999d6afc88ce6640aeba9962sewardj      putDReg( frT_addr + 1,
119414c96e61dd85c172b999d6afc88ce6640aeba9962sewardj               unop( Iop_ReinterpI64asD64, mkexpr( result_lo ) ) );
119424c96e61dd85c172b999d6afc88ce6640aeba9962sewardj   }
119434c96e61dd85c172b999d6afc88ce6640aeba9962sewardj   break;
119444c96e61dd85c172b999d6afc88ce6640aeba9962sewardj   case 0x342: // denbcdq   DFP Encode BCD to DPD
119454c96e61dd85c172b999d6afc88ce6640aeba9962sewardj   {
119464c96e61dd85c172b999d6afc88ce6640aeba9962sewardj      IRTemp valid_mask      = newTemp( Ity_I32 );
119474c96e61dd85c172b999d6afc88ce6640aeba9962sewardj      IRTemp invalid_mask    = newTemp( Ity_I32 );
119484c96e61dd85c172b999d6afc88ce6640aeba9962sewardj      IRTemp result128       = newTemp( Ity_D128 );
119494c96e61dd85c172b999d6afc88ce6640aeba9962sewardj      IRTemp dfp_significand = newTemp( Ity_D128 );
119504c96e61dd85c172b999d6afc88ce6640aeba9962sewardj      IRTemp tmp_hi          = newTemp( Ity_I64 );
119514c96e61dd85c172b999d6afc88ce6640aeba9962sewardj      IRTemp tmp_lo          = newTemp( Ity_I64 );
119524c96e61dd85c172b999d6afc88ce6640aeba9962sewardj      IRTemp dbcd_top_l      = newTemp( Ity_I32 );
119534c96e61dd85c172b999d6afc88ce6640aeba9962sewardj      IRTemp dbcd_mid_u      = newTemp( Ity_I32 );
119544c96e61dd85c172b999d6afc88ce6640aeba9962sewardj      IRTemp dbcd_mid_l      = newTemp( Ity_I32 );
119554c96e61dd85c172b999d6afc88ce6640aeba9962sewardj      IRTemp dbcd_low_u      = newTemp( Ity_I32 );
119564c96e61dd85c172b999d6afc88ce6640aeba9962sewardj      IRTemp dbcd_low_l      = newTemp( Ity_I32 );
119574c96e61dd85c172b999d6afc88ce6640aeba9962sewardj      IRTemp bcd_top_8       = newTemp( Ity_I64 );
119584c96e61dd85c172b999d6afc88ce6640aeba9962sewardj      IRTemp bcd_mid_60      = newTemp( Ity_I64 );
119594c96e61dd85c172b999d6afc88ce6640aeba9962sewardj      IRTemp bcd_low_60      = newTemp( Ity_I64 );
119604c96e61dd85c172b999d6afc88ce6640aeba9962sewardj      IRTemp sign_bit        = newTemp( Ity_I32 );
119614c96e61dd85c172b999d6afc88ce6640aeba9962sewardj      IRTemp tmptop10        = newTemp( Ity_I64 );
119624c96e61dd85c172b999d6afc88ce6640aeba9962sewardj      IRTemp tmpmid50        = newTemp( Ity_I64 );
119634c96e61dd85c172b999d6afc88ce6640aeba9962sewardj      IRTemp tmplow50        = newTemp( Ity_I64 );
119644c96e61dd85c172b999d6afc88ce6640aeba9962sewardj      IRTemp inval_bcd_digit_mask = newTemp( Ity_I32 );
119654c96e61dd85c172b999d6afc88ce6640aeba9962sewardj
119664c96e61dd85c172b999d6afc88ce6640aeba9962sewardj      DIP( "denbcd %llu,r%u,r%u\n", s, frT_addr, frB_addr );
119674c96e61dd85c172b999d6afc88ce6640aeba9962sewardj
119684c96e61dd85c172b999d6afc88ce6640aeba9962sewardj      if ( s == 0 ) {
119694c96e61dd85c172b999d6afc88ce6640aeba9962sewardj         /* Unsigned BCD string */
119704c96e61dd85c172b999d6afc88ce6640aeba9962sewardj         assign( sign_bit, mkU32( 0 ) ); // set to zero for unsigned string
119714c96e61dd85c172b999d6afc88ce6640aeba9962sewardj
119724c96e61dd85c172b999d6afc88ce6640aeba9962sewardj         assign( bcd_top_8,
119734c96e61dd85c172b999d6afc88ce6640aeba9962sewardj                 binop( Iop_32HLto64,
119744c96e61dd85c172b999d6afc88ce6640aeba9962sewardj                        mkU32( 0 ),
119754c96e61dd85c172b999d6afc88ce6640aeba9962sewardj                        binop( Iop_And32,
119764c96e61dd85c172b999d6afc88ce6640aeba9962sewardj                               binop( Iop_Shr32,
119774c96e61dd85c172b999d6afc88ce6640aeba9962sewardj                                      unop( Iop_64HIto32,
119784c96e61dd85c172b999d6afc88ce6640aeba9962sewardj                                            mkexpr( frBI64_hi ) ),
119794c96e61dd85c172b999d6afc88ce6640aeba9962sewardj                                      mkU8( 24 ) ),
119804c96e61dd85c172b999d6afc88ce6640aeba9962sewardj                               mkU32( 0xFF ) ) ) );
119814c96e61dd85c172b999d6afc88ce6640aeba9962sewardj         assign( bcd_mid_60,
119824c96e61dd85c172b999d6afc88ce6640aeba9962sewardj                 binop( Iop_32HLto64,
119834c96e61dd85c172b999d6afc88ce6640aeba9962sewardj                        binop( Iop_Or32,
119844c96e61dd85c172b999d6afc88ce6640aeba9962sewardj                               binop( Iop_Shr32,
119854c96e61dd85c172b999d6afc88ce6640aeba9962sewardj                                      unop( Iop_64to32,
119864c96e61dd85c172b999d6afc88ce6640aeba9962sewardj                                            mkexpr( frBI64_hi ) ),
119874c96e61dd85c172b999d6afc88ce6640aeba9962sewardj                                      mkU8( 28 ) ),
119884c96e61dd85c172b999d6afc88ce6640aeba9962sewardj                               binop( Iop_Shl32,
119894c96e61dd85c172b999d6afc88ce6640aeba9962sewardj                                      unop( Iop_64HIto32,
119904c96e61dd85c172b999d6afc88ce6640aeba9962sewardj                                            mkexpr( frBI64_hi ) ),
119914c96e61dd85c172b999d6afc88ce6640aeba9962sewardj                                      mkU8( 4 ) ) ),
119924c96e61dd85c172b999d6afc88ce6640aeba9962sewardj                        binop( Iop_Or32,
119934c96e61dd85c172b999d6afc88ce6640aeba9962sewardj                               binop( Iop_Shl32,
119944c96e61dd85c172b999d6afc88ce6640aeba9962sewardj                                      unop( Iop_64to32,
119954c96e61dd85c172b999d6afc88ce6640aeba9962sewardj                                            mkexpr( frBI64_hi ) ),
119964c96e61dd85c172b999d6afc88ce6640aeba9962sewardj                                      mkU8( 4 ) ),
119974c96e61dd85c172b999d6afc88ce6640aeba9962sewardj                               binop( Iop_Shr32,
119984c96e61dd85c172b999d6afc88ce6640aeba9962sewardj                                      unop( Iop_64HIto32,
119994c96e61dd85c172b999d6afc88ce6640aeba9962sewardj                                            mkexpr( frBI64_lo ) ),
120004c96e61dd85c172b999d6afc88ce6640aeba9962sewardj                                      mkU8( 28 ) ) ) ) );
120014c96e61dd85c172b999d6afc88ce6640aeba9962sewardj
120024c96e61dd85c172b999d6afc88ce6640aeba9962sewardj         /* Note, the various helper functions ignores top 4-bits */
120034c96e61dd85c172b999d6afc88ce6640aeba9962sewardj         assign( bcd_low_60, mkexpr( frBI64_lo ) );
120044c96e61dd85c172b999d6afc88ce6640aeba9962sewardj
120054c96e61dd85c172b999d6afc88ce6640aeba9962sewardj         assign( tmptop10, unop( Iop_BCDtoDPB, mkexpr( bcd_top_8 ) ) );
120064c96e61dd85c172b999d6afc88ce6640aeba9962sewardj         assign( dbcd_top_l, unop( Iop_64to32, mkexpr( tmptop10 ) ) );
120074c96e61dd85c172b999d6afc88ce6640aeba9962sewardj
120084c96e61dd85c172b999d6afc88ce6640aeba9962sewardj         assign( tmpmid50, unop( Iop_BCDtoDPB, mkexpr( bcd_mid_60 ) ) );
120094c96e61dd85c172b999d6afc88ce6640aeba9962sewardj         assign( dbcd_mid_u, unop( Iop_64HIto32, mkexpr( tmpmid50 ) ) );
120104c96e61dd85c172b999d6afc88ce6640aeba9962sewardj         assign( dbcd_mid_l, unop( Iop_64to32, mkexpr( tmpmid50 ) ) );
120114c96e61dd85c172b999d6afc88ce6640aeba9962sewardj
120124c96e61dd85c172b999d6afc88ce6640aeba9962sewardj         assign( tmplow50, unop( Iop_BCDtoDPB, mkexpr( bcd_low_60 ) ) );
120134c96e61dd85c172b999d6afc88ce6640aeba9962sewardj         assign( dbcd_low_u, unop( Iop_64HIto32, mkexpr( tmplow50 ) ) );
120144c96e61dd85c172b999d6afc88ce6640aeba9962sewardj         assign( dbcd_low_l, unop( Iop_64to32, mkexpr( tmplow50 ) ) );
120154c96e61dd85c172b999d6afc88ce6640aeba9962sewardj
120164c96e61dd85c172b999d6afc88ce6640aeba9962sewardj         /* The entire BCD string fits in lower 110-bits.  The LMD = 0,
120174c96e61dd85c172b999d6afc88ce6640aeba9962sewardj          * value is not part of the final result. Only the right most
120184c96e61dd85c172b999d6afc88ce6640aeba9962sewardj          * BCD digits are stored.
120194c96e61dd85c172b999d6afc88ce6640aeba9962sewardj          */
120204c96e61dd85c172b999d6afc88ce6640aeba9962sewardj         assign( lmd, mkU32( 0 ) );
120214c96e61dd85c172b999d6afc88ce6640aeba9962sewardj
120224c96e61dd85c172b999d6afc88ce6640aeba9962sewardj         assign( invalid_mask,
120234c96e61dd85c172b999d6afc88ce6640aeba9962sewardj                 binop( Iop_Or32,
120244c96e61dd85c172b999d6afc88ce6640aeba9962sewardj                        bcd_digit_inval( mkU32( 0 ),
120254c96e61dd85c172b999d6afc88ce6640aeba9962sewardj                                         unop( Iop_64to32,
120264c96e61dd85c172b999d6afc88ce6640aeba9962sewardj                                               mkexpr( bcd_top_8 ) ) ),
120274c96e61dd85c172b999d6afc88ce6640aeba9962sewardj                        binop( Iop_Or32,
120284c96e61dd85c172b999d6afc88ce6640aeba9962sewardj                               bcd_digit_inval( unop( Iop_64HIto32,
120294c96e61dd85c172b999d6afc88ce6640aeba9962sewardj                                                      mkexpr( bcd_mid_60 ) ),
120304c96e61dd85c172b999d6afc88ce6640aeba9962sewardj                                                unop( Iop_64to32,
120314c96e61dd85c172b999d6afc88ce6640aeba9962sewardj                                                      mkexpr( bcd_mid_60 ) ) ),
120324c96e61dd85c172b999d6afc88ce6640aeba9962sewardj                               bcd_digit_inval( unop( Iop_64HIto32,
120334c96e61dd85c172b999d6afc88ce6640aeba9962sewardj                                                      mkexpr( bcd_low_60 ) ),
120344c96e61dd85c172b999d6afc88ce6640aeba9962sewardj                                                unop( Iop_64to32,
120354c96e61dd85c172b999d6afc88ce6640aeba9962sewardj                                                      mkexpr( bcd_low_60 ) )
120364c96e61dd85c172b999d6afc88ce6640aeba9962sewardj                                                ) ) ) );
120374c96e61dd85c172b999d6afc88ce6640aeba9962sewardj
120384c96e61dd85c172b999d6afc88ce6640aeba9962sewardj      } else if ( s == 1 ) {
120394c96e61dd85c172b999d6afc88ce6640aeba9962sewardj         IRTemp sign          = newTemp( Ity_I32 );
120404c96e61dd85c172b999d6afc88ce6640aeba9962sewardj         IRTemp zero          = newTemp( Ity_I32 );
120414c96e61dd85c172b999d6afc88ce6640aeba9962sewardj         IRTemp pos_sign_mask = newTemp( Ity_I32 );
120424c96e61dd85c172b999d6afc88ce6640aeba9962sewardj         IRTemp neg_sign_mask = newTemp( Ity_I32 );
120434c96e61dd85c172b999d6afc88ce6640aeba9962sewardj
120444c96e61dd85c172b999d6afc88ce6640aeba9962sewardj         /* The sign of the BCD string is stored in lower 4 bits */
120454c96e61dd85c172b999d6afc88ce6640aeba9962sewardj         assign( sign,
120464c96e61dd85c172b999d6afc88ce6640aeba9962sewardj                 binop( Iop_And32,
120474c96e61dd85c172b999d6afc88ce6640aeba9962sewardj                        unop( Iop_64to32, mkexpr( frBI64_lo ) ),
120484c96e61dd85c172b999d6afc88ce6640aeba9962sewardj                        mkU32( 0xF ) ) );
120494c96e61dd85c172b999d6afc88ce6640aeba9962sewardj         assign( neg_sign_mask, Generate_neg_sign_mask( mkexpr( sign ) ) );
120504c96e61dd85c172b999d6afc88ce6640aeba9962sewardj         assign( pos_sign_mask, Generate_pos_sign_mask( mkexpr( sign ) ) );
120514c96e61dd85c172b999d6afc88ce6640aeba9962sewardj         assign( sign_bit,
120524c96e61dd85c172b999d6afc88ce6640aeba9962sewardj                 Generate_sign_bit( mkexpr( pos_sign_mask ),
120534c96e61dd85c172b999d6afc88ce6640aeba9962sewardj                                    mkexpr( neg_sign_mask ) ) );
120544c96e61dd85c172b999d6afc88ce6640aeba9962sewardj
120554c96e61dd85c172b999d6afc88ce6640aeba9962sewardj         /* Generate the value assuminig the sign and BCD digits are vaild */
120564c96e61dd85c172b999d6afc88ce6640aeba9962sewardj         assign( bcd_top_8,
120574c96e61dd85c172b999d6afc88ce6640aeba9962sewardj                 binop( Iop_32HLto64,
120584c96e61dd85c172b999d6afc88ce6640aeba9962sewardj                        mkU32( 0x0 ),
120594c96e61dd85c172b999d6afc88ce6640aeba9962sewardj                        binop( Iop_Shr32,
120604c96e61dd85c172b999d6afc88ce6640aeba9962sewardj                               unop( Iop_64HIto32, mkexpr( frBI64_hi ) ),
120614c96e61dd85c172b999d6afc88ce6640aeba9962sewardj                               mkU8( 28 ) ) ) );
120624c96e61dd85c172b999d6afc88ce6640aeba9962sewardj
120634c96e61dd85c172b999d6afc88ce6640aeba9962sewardj         /* The various helper routines ignore the upper 4-bits */
120644c96e61dd85c172b999d6afc88ce6640aeba9962sewardj         assign( bcd_mid_60, mkexpr( frBI64_hi ) );
120654c96e61dd85c172b999d6afc88ce6640aeba9962sewardj
120664c96e61dd85c172b999d6afc88ce6640aeba9962sewardj         /* Remove bottom four sign bits */
120674c96e61dd85c172b999d6afc88ce6640aeba9962sewardj         assign( bcd_low_60,
120684c96e61dd85c172b999d6afc88ce6640aeba9962sewardj                 binop( Iop_32HLto64,
120694c96e61dd85c172b999d6afc88ce6640aeba9962sewardj                        binop( Iop_Shr32,
120704c96e61dd85c172b999d6afc88ce6640aeba9962sewardj                               unop( Iop_64HIto32,
120714c96e61dd85c172b999d6afc88ce6640aeba9962sewardj                                     mkexpr( frBI64_lo ) ),
120724c96e61dd85c172b999d6afc88ce6640aeba9962sewardj                               mkU8( 4 ) ),
120734c96e61dd85c172b999d6afc88ce6640aeba9962sewardj                               binop( Iop_Or32,
120744c96e61dd85c172b999d6afc88ce6640aeba9962sewardj                                      binop( Iop_Shl32,
120754c96e61dd85c172b999d6afc88ce6640aeba9962sewardj                                             unop( Iop_64HIto32,
120764c96e61dd85c172b999d6afc88ce6640aeba9962sewardj                                                   mkexpr( frBI64_lo ) ),
120774c96e61dd85c172b999d6afc88ce6640aeba9962sewardj                                             mkU8( 28 ) ),
120784c96e61dd85c172b999d6afc88ce6640aeba9962sewardj                                      binop( Iop_Shr32,
120794c96e61dd85c172b999d6afc88ce6640aeba9962sewardj                                             unop( Iop_64to32,
120804c96e61dd85c172b999d6afc88ce6640aeba9962sewardj                                                   mkexpr( frBI64_lo ) ),
120814c96e61dd85c172b999d6afc88ce6640aeba9962sewardj                                             mkU8( 4 ) ) ) ) );
120824c96e61dd85c172b999d6afc88ce6640aeba9962sewardj         assign( tmptop10, unop( Iop_BCDtoDPB, mkexpr(bcd_top_8 ) ) );
120834c96e61dd85c172b999d6afc88ce6640aeba9962sewardj         assign( dbcd_top_l, unop( Iop_64to32, mkexpr( tmptop10 ) ) );
120844c96e61dd85c172b999d6afc88ce6640aeba9962sewardj
120854c96e61dd85c172b999d6afc88ce6640aeba9962sewardj         assign( tmpmid50, unop( Iop_BCDtoDPB, mkexpr(bcd_mid_60 ) ) );
120864c96e61dd85c172b999d6afc88ce6640aeba9962sewardj         assign( dbcd_mid_u, unop( Iop_64HIto32, mkexpr( tmpmid50 ) ) );
120874c96e61dd85c172b999d6afc88ce6640aeba9962sewardj         assign( dbcd_mid_l, unop( Iop_64to32, mkexpr( tmpmid50 ) ) );
120884c96e61dd85c172b999d6afc88ce6640aeba9962sewardj
120894c96e61dd85c172b999d6afc88ce6640aeba9962sewardj         assign( tmplow50, unop( Iop_BCDtoDPB, mkexpr( bcd_low_60 ) ) );
120904c96e61dd85c172b999d6afc88ce6640aeba9962sewardj         assign( dbcd_low_u, unop( Iop_64HIto32, mkexpr( tmplow50 ) ) );
120914c96e61dd85c172b999d6afc88ce6640aeba9962sewardj         assign( dbcd_low_l, unop( Iop_64to32, mkexpr( tmplow50 ) ) );
120924c96e61dd85c172b999d6afc88ce6640aeba9962sewardj
120934c96e61dd85c172b999d6afc88ce6640aeba9962sewardj         /* The entire BCD string fits in lower 110-bits.  The LMD value
120944c96e61dd85c172b999d6afc88ce6640aeba9962sewardj          * is not stored in the final result for the DFP Long instruction.
120954c96e61dd85c172b999d6afc88ce6640aeba9962sewardj          */
120964c96e61dd85c172b999d6afc88ce6640aeba9962sewardj         assign( lmd, mkU32( 0 ) );
120974c96e61dd85c172b999d6afc88ce6640aeba9962sewardj
120984c96e61dd85c172b999d6afc88ce6640aeba9962sewardj         /* Check for invalid sign and invalid BCD digit.  Don't check the
120994c96e61dd85c172b999d6afc88ce6640aeba9962sewardj          *  bottom four bits of frBI64_lo as that is the sign value.
121004c96e61dd85c172b999d6afc88ce6640aeba9962sewardj          */
121014c96e61dd85c172b999d6afc88ce6640aeba9962sewardj         assign( zero, mkU32( 0 ) );
121024c96e61dd85c172b999d6afc88ce6640aeba9962sewardj         assign( inval_bcd_digit_mask,
121034c96e61dd85c172b999d6afc88ce6640aeba9962sewardj                 binop( Iop_Or32,
121044c96e61dd85c172b999d6afc88ce6640aeba9962sewardj                        bcd_digit_inval( mkexpr( zero ),
121054c96e61dd85c172b999d6afc88ce6640aeba9962sewardj                                         unop( Iop_64to32,
121064c96e61dd85c172b999d6afc88ce6640aeba9962sewardj                                               mkexpr( bcd_top_8 ) ) ),
121074c96e61dd85c172b999d6afc88ce6640aeba9962sewardj                        binop( Iop_Or32,
121084c96e61dd85c172b999d6afc88ce6640aeba9962sewardj                               bcd_digit_inval( unop( Iop_64HIto32,
121094c96e61dd85c172b999d6afc88ce6640aeba9962sewardj                                                     mkexpr( bcd_mid_60 ) ),
121104c96e61dd85c172b999d6afc88ce6640aeba9962sewardj                                               unop( Iop_64to32,
121114c96e61dd85c172b999d6afc88ce6640aeba9962sewardj                                                     mkexpr( bcd_mid_60 ) ) ),
121124c96e61dd85c172b999d6afc88ce6640aeba9962sewardj                               bcd_digit_inval( unop( Iop_64HIto32,
121134c96e61dd85c172b999d6afc88ce6640aeba9962sewardj                                                     mkexpr( frBI64_lo ) ),
121144c96e61dd85c172b999d6afc88ce6640aeba9962sewardj                                               binop( Iop_Shr32,
121154c96e61dd85c172b999d6afc88ce6640aeba9962sewardj                                                      unop( Iop_64to32,
121164c96e61dd85c172b999d6afc88ce6640aeba9962sewardj                                                            mkexpr( frBI64_lo ) ),
121174c96e61dd85c172b999d6afc88ce6640aeba9962sewardj                                                        mkU8( 4 ) ) ) ) ) );
121184c96e61dd85c172b999d6afc88ce6640aeba9962sewardj         assign( invalid_mask,
121194c96e61dd85c172b999d6afc88ce6640aeba9962sewardj                 Generate_inv_mask( mkexpr( inval_bcd_digit_mask ),
121204c96e61dd85c172b999d6afc88ce6640aeba9962sewardj                                    mkexpr( pos_sign_mask ),
121214c96e61dd85c172b999d6afc88ce6640aeba9962sewardj                                    mkexpr( neg_sign_mask ) ) );
121224c96e61dd85c172b999d6afc88ce6640aeba9962sewardj
121234c96e61dd85c172b999d6afc88ce6640aeba9962sewardj      }
121244c96e61dd85c172b999d6afc88ce6640aeba9962sewardj
121254c96e61dd85c172b999d6afc88ce6640aeba9962sewardj      assign( valid_mask, unop( Iop_Not32, mkexpr( invalid_mask ) ) );
121264c96e61dd85c172b999d6afc88ce6640aeba9962sewardj
121274c96e61dd85c172b999d6afc88ce6640aeba9962sewardj      /* Calculate the value of the result assuming sign and BCD digits
121284c96e61dd85c172b999d6afc88ce6640aeba9962sewardj       * are all valid.
121294c96e61dd85c172b999d6afc88ce6640aeba9962sewardj       */
121304c96e61dd85c172b999d6afc88ce6640aeba9962sewardj      assign( dfp_significand,
121314c96e61dd85c172b999d6afc88ce6640aeba9962sewardj              binop( Iop_D64HLtoD128,
121324c96e61dd85c172b999d6afc88ce6640aeba9962sewardj                     unop( Iop_ReinterpI64asD64,
121334c96e61dd85c172b999d6afc88ce6640aeba9962sewardj                           binop( Iop_32HLto64,
121344c96e61dd85c172b999d6afc88ce6640aeba9962sewardj                                  binop( Iop_Or32,
121354c96e61dd85c172b999d6afc88ce6640aeba9962sewardj                                         mkexpr( sign_bit ),
121364c96e61dd85c172b999d6afc88ce6640aeba9962sewardj                                         mkexpr( dbcd_top_l ) ),
121374c96e61dd85c172b999d6afc88ce6640aeba9962sewardj                                  binop( Iop_Or32,
121384c96e61dd85c172b999d6afc88ce6640aeba9962sewardj                                         binop( Iop_Shl32,
121394c96e61dd85c172b999d6afc88ce6640aeba9962sewardj                                                mkexpr( dbcd_mid_u ),
121404c96e61dd85c172b999d6afc88ce6640aeba9962sewardj                                                mkU8( 18 ) ),
121414c96e61dd85c172b999d6afc88ce6640aeba9962sewardj                                         binop( Iop_Shr32,
121424c96e61dd85c172b999d6afc88ce6640aeba9962sewardj                                                mkexpr( dbcd_mid_l ),
121434c96e61dd85c172b999d6afc88ce6640aeba9962sewardj                                                mkU8( 14 ) ) ) ) ),
121444c96e61dd85c172b999d6afc88ce6640aeba9962sewardj                     unop( Iop_ReinterpI64asD64,
121454c96e61dd85c172b999d6afc88ce6640aeba9962sewardj                           binop( Iop_32HLto64,
121464c96e61dd85c172b999d6afc88ce6640aeba9962sewardj                                  binop( Iop_Or32,
121474c96e61dd85c172b999d6afc88ce6640aeba9962sewardj                                         mkexpr( dbcd_low_u ),
121484c96e61dd85c172b999d6afc88ce6640aeba9962sewardj                                         binop( Iop_Shl32,
121494c96e61dd85c172b999d6afc88ce6640aeba9962sewardj                                                mkexpr( dbcd_mid_l ),
121504c96e61dd85c172b999d6afc88ce6640aeba9962sewardj                                                mkU8( 18 ) ) ),
121514c96e61dd85c172b999d6afc88ce6640aeba9962sewardj                                  mkexpr( dbcd_low_l ) ) ) ) );
121524c96e61dd85c172b999d6afc88ce6640aeba9962sewardj
121534c96e61dd85c172b999d6afc88ce6640aeba9962sewardj      /* Break the result back down to 32-bit chunks and replace chunks.
121544c96e61dd85c172b999d6afc88ce6640aeba9962sewardj       * If there was an invalid BCD digit or invalid sign value, replace
121554c96e61dd85c172b999d6afc88ce6640aeba9962sewardj       * the calculated result with the invalid bit string.
121564c96e61dd85c172b999d6afc88ce6640aeba9962sewardj       */
121574c96e61dd85c172b999d6afc88ce6640aeba9962sewardj      assign( result128,
121584c96e61dd85c172b999d6afc88ce6640aeba9962sewardj              binop( Iop_InsertExpD128,
12159cea07ccbe9aa9b5fd8e9b318471c6c74aa147acbcarll                     mkU64( DFP_EXTND_BIAS ),
121604c96e61dd85c172b999d6afc88ce6640aeba9962sewardj                     mkexpr( dfp_significand ) ) );
121614c96e61dd85c172b999d6afc88ce6640aeba9962sewardj
121624c96e61dd85c172b999d6afc88ce6640aeba9962sewardj      assign( tmp_hi,
121634c96e61dd85c172b999d6afc88ce6640aeba9962sewardj              unop( Iop_ReinterpD64asI64,
121644c96e61dd85c172b999d6afc88ce6640aeba9962sewardj                    unop( Iop_D128HItoD64, mkexpr( result128 ) ) ) );
121654c96e61dd85c172b999d6afc88ce6640aeba9962sewardj
121664c96e61dd85c172b999d6afc88ce6640aeba9962sewardj      assign( tmp_lo,
121674c96e61dd85c172b999d6afc88ce6640aeba9962sewardj              unop( Iop_ReinterpD64asI64,
121684c96e61dd85c172b999d6afc88ce6640aeba9962sewardj                    unop( Iop_D128LOtoD64, mkexpr( result128 ) ) ) );
121694c96e61dd85c172b999d6afc88ce6640aeba9962sewardj
121704c96e61dd85c172b999d6afc88ce6640aeba9962sewardj      assign( result_hi,
121714c96e61dd85c172b999d6afc88ce6640aeba9962sewardj              binop( Iop_32HLto64,
121724c96e61dd85c172b999d6afc88ce6640aeba9962sewardj                     binop( Iop_Or32,
121734c96e61dd85c172b999d6afc88ce6640aeba9962sewardj                            binop( Iop_And32,
121744c96e61dd85c172b999d6afc88ce6640aeba9962sewardj                                   mkexpr( valid_mask ),
121754c96e61dd85c172b999d6afc88ce6640aeba9962sewardj                                   unop( Iop_64HIto32, mkexpr( tmp_hi ) ) ),
121764c96e61dd85c172b999d6afc88ce6640aeba9962sewardj                            binop( Iop_And32,
121774c96e61dd85c172b999d6afc88ce6640aeba9962sewardj                                   mkU32( 0x7C000000 ),
121784c96e61dd85c172b999d6afc88ce6640aeba9962sewardj                                   mkexpr( invalid_mask ) ) ),
121794c96e61dd85c172b999d6afc88ce6640aeba9962sewardj                     binop( Iop_Or32,
121804c96e61dd85c172b999d6afc88ce6640aeba9962sewardj                            binop( Iop_And32,
121814c96e61dd85c172b999d6afc88ce6640aeba9962sewardj                                   mkexpr( valid_mask ),
121824c96e61dd85c172b999d6afc88ce6640aeba9962sewardj                                   unop( Iop_64to32, mkexpr( tmp_hi ) ) ),
121834c96e61dd85c172b999d6afc88ce6640aeba9962sewardj                            binop( Iop_And32,
121844c96e61dd85c172b999d6afc88ce6640aeba9962sewardj                                   mkU32( 0x0 ),
121854c96e61dd85c172b999d6afc88ce6640aeba9962sewardj                                   mkexpr( invalid_mask ) ) ) ) );
121864c96e61dd85c172b999d6afc88ce6640aeba9962sewardj
121874c96e61dd85c172b999d6afc88ce6640aeba9962sewardj      assign( result_lo,
121884c96e61dd85c172b999d6afc88ce6640aeba9962sewardj              binop( Iop_32HLto64,
121894c96e61dd85c172b999d6afc88ce6640aeba9962sewardj                     binop( Iop_Or32,
121904c96e61dd85c172b999d6afc88ce6640aeba9962sewardj                            binop( Iop_And32,
121914c96e61dd85c172b999d6afc88ce6640aeba9962sewardj                                   mkexpr( valid_mask ),
121924c96e61dd85c172b999d6afc88ce6640aeba9962sewardj                                   unop( Iop_64HIto32, mkexpr( tmp_lo ) ) ),
121934c96e61dd85c172b999d6afc88ce6640aeba9962sewardj                            binop( Iop_And32,
121944c96e61dd85c172b999d6afc88ce6640aeba9962sewardj                                   mkU32( 0x0 ),
121954c96e61dd85c172b999d6afc88ce6640aeba9962sewardj                                   mkexpr( invalid_mask ) ) ),
121964c96e61dd85c172b999d6afc88ce6640aeba9962sewardj                     binop( Iop_Or32,
121974c96e61dd85c172b999d6afc88ce6640aeba9962sewardj                            binop( Iop_And32,
121984c96e61dd85c172b999d6afc88ce6640aeba9962sewardj                                   mkexpr( valid_mask ),
121994c96e61dd85c172b999d6afc88ce6640aeba9962sewardj                                   unop( Iop_64to32, mkexpr( tmp_lo ) ) ),
122004c96e61dd85c172b999d6afc88ce6640aeba9962sewardj                            binop( Iop_And32,
122014c96e61dd85c172b999d6afc88ce6640aeba9962sewardj                                   mkU32( 0x0 ),
122024c96e61dd85c172b999d6afc88ce6640aeba9962sewardj                                   mkexpr( invalid_mask ) ) ) ) );
122034c96e61dd85c172b999d6afc88ce6640aeba9962sewardj
122044c96e61dd85c172b999d6afc88ce6640aeba9962sewardj      putDReg( frT_addr, unop( Iop_ReinterpI64asD64, mkexpr( result_hi ) ) );
122054c96e61dd85c172b999d6afc88ce6640aeba9962sewardj      putDReg( frT_addr + 1,
122064c96e61dd85c172b999d6afc88ce6640aeba9962sewardj               unop( Iop_ReinterpI64asD64, mkexpr( result_lo ) ) );
122074c96e61dd85c172b999d6afc88ce6640aeba9962sewardj
122084c96e61dd85c172b999d6afc88ce6640aeba9962sewardj   }
122094c96e61dd85c172b999d6afc88ce6640aeba9962sewardj   break;
122104c96e61dd85c172b999d6afc88ce6640aeba9962sewardj   default:
122114c96e61dd85c172b999d6afc88ce6640aeba9962sewardj      vpanic( "ERROR: dis_dfp_bcdq(ppc), undefined opc2 case " );
122124c96e61dd85c172b999d6afc88ce6640aeba9962sewardj      break;
122134c96e61dd85c172b999d6afc88ce6640aeba9962sewardj   }
122144c96e61dd85c172b999d6afc88ce6640aeba9962sewardj   return True;
122154c96e61dd85c172b999d6afc88ce6640aeba9962sewardj}
122164c96e61dd85c172b999d6afc88ce6640aeba9962sewardj
122174c96e61dd85c172b999d6afc88ce6640aeba9962sewardjstatic Bool dis_dfp_significant_digits( UInt theInstr )
122184c96e61dd85c172b999d6afc88ce6640aeba9962sewardj{
122194c96e61dd85c172b999d6afc88ce6640aeba9962sewardj   UChar frA_addr = ifieldRegA( theInstr );
122204c96e61dd85c172b999d6afc88ce6640aeba9962sewardj   UChar frB_addr = ifieldRegB( theInstr );
122214c96e61dd85c172b999d6afc88ce6640aeba9962sewardj   IRTemp frA     = newTemp( Ity_D64 );
122224c96e61dd85c172b999d6afc88ce6640aeba9962sewardj   UInt opc1      = ifieldOPC( theInstr );
122234c96e61dd85c172b999d6afc88ce6640aeba9962sewardj   IRTemp B_sig   = newTemp( Ity_I8 );
122244c96e61dd85c172b999d6afc88ce6640aeba9962sewardj   IRTemp K       = newTemp( Ity_I8 );
122254c96e61dd85c172b999d6afc88ce6640aeba9962sewardj   IRTemp lmd_B   = newTemp( Ity_I32 );
122264c96e61dd85c172b999d6afc88ce6640aeba9962sewardj   IRTemp field   = newTemp( Ity_I32 );
122274c96e61dd85c172b999d6afc88ce6640aeba9962sewardj   UChar crfD     = toUChar( IFIELD( theInstr, 23, 3 ) ); // AKA BF
122284c96e61dd85c172b999d6afc88ce6640aeba9962sewardj   IRTemp Unordered_true     = newTemp( Ity_I32 );
122294c96e61dd85c172b999d6afc88ce6640aeba9962sewardj   IRTemp Eq_true_mask       = newTemp( Ity_I32 );
122304c96e61dd85c172b999d6afc88ce6640aeba9962sewardj   IRTemp Lt_true_mask       = newTemp( Ity_I32 );
122314c96e61dd85c172b999d6afc88ce6640aeba9962sewardj   IRTemp Gt_true_mask       = newTemp( Ity_I32 );
122324c96e61dd85c172b999d6afc88ce6640aeba9962sewardj   IRTemp KisZero_true_mask  = newTemp( Ity_I32 );
122334c96e61dd85c172b999d6afc88ce6640aeba9962sewardj   IRTemp KisZero_false_mask = newTemp( Ity_I32 );
122344c96e61dd85c172b999d6afc88ce6640aeba9962sewardj
122354c96e61dd85c172b999d6afc88ce6640aeba9962sewardj   /* Get the reference singificance stored in frA */
122364c96e61dd85c172b999d6afc88ce6640aeba9962sewardj   assign( frA, getDReg( frA_addr ) );
122374c96e61dd85c172b999d6afc88ce6640aeba9962sewardj
122384c96e61dd85c172b999d6afc88ce6640aeba9962sewardj   /* Convert from 64 bit to 8 bits in two steps.  The Iop_64to8 is not
122394c96e61dd85c172b999d6afc88ce6640aeba9962sewardj    * supported in 32-bit mode.
122404c96e61dd85c172b999d6afc88ce6640aeba9962sewardj    */
122414c96e61dd85c172b999d6afc88ce6640aeba9962sewardj   assign( K, unop( Iop_32to8,
122424c96e61dd85c172b999d6afc88ce6640aeba9962sewardj                    binop( Iop_And32,
122434c96e61dd85c172b999d6afc88ce6640aeba9962sewardj                           unop( Iop_64to32,
122444c96e61dd85c172b999d6afc88ce6640aeba9962sewardj                                 unop( Iop_ReinterpD64asI64,
122454c96e61dd85c172b999d6afc88ce6640aeba9962sewardj                                       mkexpr( frA ) ) ),
122464c96e61dd85c172b999d6afc88ce6640aeba9962sewardj                           mkU32( 0x3F ) ) ) );
122474c96e61dd85c172b999d6afc88ce6640aeba9962sewardj
122484c96e61dd85c172b999d6afc88ce6640aeba9962sewardj   switch ( opc1 ) {
122494c96e61dd85c172b999d6afc88ce6640aeba9962sewardj   case 0x3b: // dtstsf   DFP Test Significance
122504c96e61dd85c172b999d6afc88ce6640aeba9962sewardj   {
122514c96e61dd85c172b999d6afc88ce6640aeba9962sewardj      IRTemp frB     = newTemp( Ity_D64 );
122524c96e61dd85c172b999d6afc88ce6640aeba9962sewardj      IRTemp frBI64  = newTemp( Ity_I64 );
122534c96e61dd85c172b999d6afc88ce6640aeba9962sewardj      IRTemp B_bcd_u = newTemp( Ity_I32 );
122544c96e61dd85c172b999d6afc88ce6640aeba9962sewardj      IRTemp B_bcd_l = newTemp( Ity_I32 );
122554c96e61dd85c172b999d6afc88ce6640aeba9962sewardj      IRTemp tmp64   = newTemp( Ity_I64 );
122564c96e61dd85c172b999d6afc88ce6640aeba9962sewardj
122574c96e61dd85c172b999d6afc88ce6640aeba9962sewardj      DIP( "dtstsf %u,r%u,r%u\n", crfD, frA_addr, frB_addr );
122584c96e61dd85c172b999d6afc88ce6640aeba9962sewardj
122594c96e61dd85c172b999d6afc88ce6640aeba9962sewardj      assign( frB, getDReg( frB_addr ) );
122604c96e61dd85c172b999d6afc88ce6640aeba9962sewardj      assign( frBI64, unop( Iop_ReinterpD64asI64, mkexpr( frB ) ) );
122614c96e61dd85c172b999d6afc88ce6640aeba9962sewardj
122624c96e61dd85c172b999d6afc88ce6640aeba9962sewardj      /* Get the BCD string for the value stored in a series of I32 values.
122634c96e61dd85c172b999d6afc88ce6640aeba9962sewardj       * Count the number of leading zeros.  Subtract the number of leading
122644c96e61dd85c172b999d6afc88ce6640aeba9962sewardj       * zeros from 16 (maximum number of significant digits in DFP
122654c96e61dd85c172b999d6afc88ce6640aeba9962sewardj       * Long).
122664c96e61dd85c172b999d6afc88ce6640aeba9962sewardj       */
122674c96e61dd85c172b999d6afc88ce6640aeba9962sewardj      Get_lmd( &lmd_B,
122684c96e61dd85c172b999d6afc88ce6640aeba9962sewardj               binop( Iop_Shr32,
122694c96e61dd85c172b999d6afc88ce6640aeba9962sewardj                      unop( Iop_64HIto32, mkexpr( frBI64 ) ),
122704c96e61dd85c172b999d6afc88ce6640aeba9962sewardj                      mkU8( 31 - 5 ) ) ); // G-field[0:4]
122714c96e61dd85c172b999d6afc88ce6640aeba9962sewardj
122724c96e61dd85c172b999d6afc88ce6640aeba9962sewardj      assign( tmp64, unop( Iop_DPBtoBCD, mkexpr( frBI64 ) ) );
122734c96e61dd85c172b999d6afc88ce6640aeba9962sewardj      assign( B_bcd_u, unop( Iop_64HIto32, mkexpr( tmp64 ) ) );
122744c96e61dd85c172b999d6afc88ce6640aeba9962sewardj      assign( B_bcd_l, unop( Iop_64to32, mkexpr( tmp64 ) ) );
122754c96e61dd85c172b999d6afc88ce6640aeba9962sewardj
122764c96e61dd85c172b999d6afc88ce6640aeba9962sewardj      assign( B_sig,
122774c96e61dd85c172b999d6afc88ce6640aeba9962sewardj              binop( Iop_Sub8,
122784c96e61dd85c172b999d6afc88ce6640aeba9962sewardj                     mkU8( DFP_LONG_MAX_SIG_DIGITS ),
122794c96e61dd85c172b999d6afc88ce6640aeba9962sewardj                     Count_leading_zeros_60( mkexpr( lmd_B ),
122804c96e61dd85c172b999d6afc88ce6640aeba9962sewardj                                             mkexpr( B_bcd_u ),
122814c96e61dd85c172b999d6afc88ce6640aeba9962sewardj                                             mkexpr( B_bcd_l ) ) ) );
122824c96e61dd85c172b999d6afc88ce6640aeba9962sewardj      assign( Unordered_true, Check_unordered( mkexpr( frBI64 ) ) );
122834c96e61dd85c172b999d6afc88ce6640aeba9962sewardj   }
122844c96e61dd85c172b999d6afc88ce6640aeba9962sewardj   break;
122854c96e61dd85c172b999d6afc88ce6640aeba9962sewardj   case 0x3F: // dtstsfq     DFP Test Significance
122864c96e61dd85c172b999d6afc88ce6640aeba9962sewardj   {
122874c96e61dd85c172b999d6afc88ce6640aeba9962sewardj      IRTemp frB_hi     = newTemp( Ity_D64 );
122884c96e61dd85c172b999d6afc88ce6640aeba9962sewardj      IRTemp frB_lo     = newTemp( Ity_D64 );
122894c96e61dd85c172b999d6afc88ce6640aeba9962sewardj      IRTemp frBI64_hi  = newTemp( Ity_I64 );
122904c96e61dd85c172b999d6afc88ce6640aeba9962sewardj      IRTemp frBI64_lo  = newTemp( Ity_I64 );
122914c96e61dd85c172b999d6afc88ce6640aeba9962sewardj      IRTemp B_low_60_u = newTemp( Ity_I32 );
122924c96e61dd85c172b999d6afc88ce6640aeba9962sewardj      IRTemp B_low_60_l = newTemp( Ity_I32 );
122934c96e61dd85c172b999d6afc88ce6640aeba9962sewardj      IRTemp B_mid_60_u = newTemp( Ity_I32 );
122944c96e61dd85c172b999d6afc88ce6640aeba9962sewardj      IRTemp B_mid_60_l = newTemp( Ity_I32 );
122954c96e61dd85c172b999d6afc88ce6640aeba9962sewardj      IRTemp B_top_12_l = newTemp( Ity_I32 );
122964c96e61dd85c172b999d6afc88ce6640aeba9962sewardj
122974c96e61dd85c172b999d6afc88ce6640aeba9962sewardj      DIP( "dtstsfq %u,r%u,r%u\n", crfD, frA_addr, frB_addr );
122984c96e61dd85c172b999d6afc88ce6640aeba9962sewardj
122994c96e61dd85c172b999d6afc88ce6640aeba9962sewardj      assign( frB_hi, getDReg( frB_addr ) );
123004c96e61dd85c172b999d6afc88ce6640aeba9962sewardj      assign( frB_lo, getDReg( frB_addr + 1 ) );
123014c96e61dd85c172b999d6afc88ce6640aeba9962sewardj
123024c96e61dd85c172b999d6afc88ce6640aeba9962sewardj      assign( frBI64_hi, unop( Iop_ReinterpD64asI64, mkexpr( frB_hi ) ) );
123034c96e61dd85c172b999d6afc88ce6640aeba9962sewardj      assign( frBI64_lo, unop( Iop_ReinterpD64asI64, mkexpr( frB_lo ) ) );
123044c96e61dd85c172b999d6afc88ce6640aeba9962sewardj
123054c96e61dd85c172b999d6afc88ce6640aeba9962sewardj      /* Get the BCD string for the value stored in a series of I32 values.
123064c96e61dd85c172b999d6afc88ce6640aeba9962sewardj       * Count the number of leading zeros.  Subtract the number of leading
123074c96e61dd85c172b999d6afc88ce6640aeba9962sewardj       * zeros from 32 (maximum number of significant digits in DFP
123084c96e61dd85c172b999d6afc88ce6640aeba9962sewardj       * extended).
123094c96e61dd85c172b999d6afc88ce6640aeba9962sewardj       */
123104c96e61dd85c172b999d6afc88ce6640aeba9962sewardj      Get_lmd( &lmd_B,
123114c96e61dd85c172b999d6afc88ce6640aeba9962sewardj               binop( Iop_Shr32,
123124c96e61dd85c172b999d6afc88ce6640aeba9962sewardj                      unop( Iop_64HIto32, mkexpr( frBI64_hi ) ),
123134c96e61dd85c172b999d6afc88ce6640aeba9962sewardj                      mkU8( 31 - 5 ) ) ); // G-field[0:4]
123144c96e61dd85c172b999d6afc88ce6640aeba9962sewardj
123154c96e61dd85c172b999d6afc88ce6640aeba9962sewardj      Generate_132_bit_bcd_string( mkexpr( frBI64_hi ),
123164c96e61dd85c172b999d6afc88ce6640aeba9962sewardj                                   mkexpr( frBI64_lo ),
123174c96e61dd85c172b999d6afc88ce6640aeba9962sewardj                                   &B_top_12_l,
123184c96e61dd85c172b999d6afc88ce6640aeba9962sewardj                                   &B_mid_60_u,
123194c96e61dd85c172b999d6afc88ce6640aeba9962sewardj                                   &B_mid_60_l,
123204c96e61dd85c172b999d6afc88ce6640aeba9962sewardj                                   &B_low_60_u,
123214c96e61dd85c172b999d6afc88ce6640aeba9962sewardj                                   &B_low_60_l );
123224c96e61dd85c172b999d6afc88ce6640aeba9962sewardj
123234c96e61dd85c172b999d6afc88ce6640aeba9962sewardj      assign( B_sig,
123244c96e61dd85c172b999d6afc88ce6640aeba9962sewardj              binop( Iop_Sub8,
123254c96e61dd85c172b999d6afc88ce6640aeba9962sewardj                     mkU8( DFP_EXTND_MAX_SIG_DIGITS ),
123264c96e61dd85c172b999d6afc88ce6640aeba9962sewardj                     Count_leading_zeros_128( mkexpr( lmd_B ),
123274c96e61dd85c172b999d6afc88ce6640aeba9962sewardj                                              mkexpr( B_top_12_l ),
123284c96e61dd85c172b999d6afc88ce6640aeba9962sewardj                                              mkexpr( B_mid_60_u ),
123294c96e61dd85c172b999d6afc88ce6640aeba9962sewardj                                              mkexpr( B_mid_60_l ),
123304c96e61dd85c172b999d6afc88ce6640aeba9962sewardj                                              mkexpr( B_low_60_u ),
123314c96e61dd85c172b999d6afc88ce6640aeba9962sewardj                                              mkexpr( B_low_60_l ) ) ) );
123324c96e61dd85c172b999d6afc88ce6640aeba9962sewardj
123334c96e61dd85c172b999d6afc88ce6640aeba9962sewardj      assign( Unordered_true, Check_unordered( mkexpr( frBI64_hi ) ) );
123344c96e61dd85c172b999d6afc88ce6640aeba9962sewardj   }
123354c96e61dd85c172b999d6afc88ce6640aeba9962sewardj   break;
123364c96e61dd85c172b999d6afc88ce6640aeba9962sewardj   }
123374c96e61dd85c172b999d6afc88ce6640aeba9962sewardj
123384c96e61dd85c172b999d6afc88ce6640aeba9962sewardj   /* Compare (16 - cnt[0]) against K and set the condition code field
123394c96e61dd85c172b999d6afc88ce6640aeba9962sewardj    * accordingly.
123404c96e61dd85c172b999d6afc88ce6640aeba9962sewardj    *
123414c96e61dd85c172b999d6afc88ce6640aeba9962sewardj    * The field layout is as follows:
123424c96e61dd85c172b999d6afc88ce6640aeba9962sewardj    *
123434c96e61dd85c172b999d6afc88ce6640aeba9962sewardj    * bit[3:0]    Description
123444c96e61dd85c172b999d6afc88ce6640aeba9962sewardj    *    3     K != 0 and K < Number of significant digits if FRB
123454c96e61dd85c172b999d6afc88ce6640aeba9962sewardj    *    2     K != 0 and K > Number of significant digits if FRB OR K = 0
123464c96e61dd85c172b999d6afc88ce6640aeba9962sewardj    *    1     K != 0 and K = Number of significant digits if FRB
123474c96e61dd85c172b999d6afc88ce6640aeba9962sewardj    *    0     K ? Number of significant digits if FRB
123484c96e61dd85c172b999d6afc88ce6640aeba9962sewardj    */
123494c96e61dd85c172b999d6afc88ce6640aeba9962sewardj   assign( Eq_true_mask,
123504c96e61dd85c172b999d6afc88ce6640aeba9962sewardj           unop( Iop_1Sto32,
123514c96e61dd85c172b999d6afc88ce6640aeba9962sewardj                 binop( Iop_CmpEQ32,
123524c96e61dd85c172b999d6afc88ce6640aeba9962sewardj                        unop( Iop_8Uto32, mkexpr( K ) ),
123534c96e61dd85c172b999d6afc88ce6640aeba9962sewardj                        unop( Iop_8Uto32, mkexpr( B_sig ) ) ) ) );
123544c96e61dd85c172b999d6afc88ce6640aeba9962sewardj   assign( Lt_true_mask,
123554c96e61dd85c172b999d6afc88ce6640aeba9962sewardj           unop( Iop_1Sto32,
123564c96e61dd85c172b999d6afc88ce6640aeba9962sewardj                 binop( Iop_CmpLT32U,
123574c96e61dd85c172b999d6afc88ce6640aeba9962sewardj                        unop( Iop_8Uto32, mkexpr( K ) ),
123584c96e61dd85c172b999d6afc88ce6640aeba9962sewardj                        unop( Iop_8Uto32, mkexpr( B_sig ) ) ) ) );
123594c96e61dd85c172b999d6afc88ce6640aeba9962sewardj   assign( Gt_true_mask,
123604c96e61dd85c172b999d6afc88ce6640aeba9962sewardj           unop( Iop_1Sto32,
123614c96e61dd85c172b999d6afc88ce6640aeba9962sewardj                 binop( Iop_CmpLT32U,
123624c96e61dd85c172b999d6afc88ce6640aeba9962sewardj                        unop( Iop_8Uto32, mkexpr( B_sig ) ),
123634c96e61dd85c172b999d6afc88ce6640aeba9962sewardj                        unop( Iop_8Uto32, mkexpr( K ) ) ) ) );
123644c96e61dd85c172b999d6afc88ce6640aeba9962sewardj
123654c96e61dd85c172b999d6afc88ce6640aeba9962sewardj   assign( KisZero_true_mask,
123664c96e61dd85c172b999d6afc88ce6640aeba9962sewardj           unop( Iop_1Sto32,
123674c96e61dd85c172b999d6afc88ce6640aeba9962sewardj                 binop( Iop_CmpEQ32,
123684c96e61dd85c172b999d6afc88ce6640aeba9962sewardj                        unop( Iop_8Uto32, mkexpr( K ) ),
123694c96e61dd85c172b999d6afc88ce6640aeba9962sewardj                        mkU32( 0 ) ) ) );
123704c96e61dd85c172b999d6afc88ce6640aeba9962sewardj   assign( KisZero_false_mask,
123714c96e61dd85c172b999d6afc88ce6640aeba9962sewardj           unop( Iop_1Sto32,
123724c96e61dd85c172b999d6afc88ce6640aeba9962sewardj                 binop( Iop_CmpNE32,
123734c96e61dd85c172b999d6afc88ce6640aeba9962sewardj                        unop( Iop_8Uto32, mkexpr( K ) ),
123744c96e61dd85c172b999d6afc88ce6640aeba9962sewardj                        mkU32( 0 ) ) ) );
123754c96e61dd85c172b999d6afc88ce6640aeba9962sewardj
123764c96e61dd85c172b999d6afc88ce6640aeba9962sewardj   assign( field,
123774c96e61dd85c172b999d6afc88ce6640aeba9962sewardj           binop( Iop_Or32,
123784c96e61dd85c172b999d6afc88ce6640aeba9962sewardj                  binop( Iop_And32,
123794c96e61dd85c172b999d6afc88ce6640aeba9962sewardj                         mkexpr( KisZero_false_mask ),
123804c96e61dd85c172b999d6afc88ce6640aeba9962sewardj                         binop( Iop_Or32,
123814c96e61dd85c172b999d6afc88ce6640aeba9962sewardj                                binop( Iop_And32,
123824c96e61dd85c172b999d6afc88ce6640aeba9962sewardj                                       mkexpr( Lt_true_mask ),
123834c96e61dd85c172b999d6afc88ce6640aeba9962sewardj                                       mkU32( 0x8 ) ),
123844c96e61dd85c172b999d6afc88ce6640aeba9962sewardj                                binop( Iop_Or32,
123854c96e61dd85c172b999d6afc88ce6640aeba9962sewardj                                       binop( Iop_And32,
123864c96e61dd85c172b999d6afc88ce6640aeba9962sewardj                                              mkexpr( Gt_true_mask ),
123874c96e61dd85c172b999d6afc88ce6640aeba9962sewardj                                              mkU32( 0x4 ) ),
123884c96e61dd85c172b999d6afc88ce6640aeba9962sewardj                                       binop( Iop_And32,
123894c96e61dd85c172b999d6afc88ce6640aeba9962sewardj                                              mkexpr( Eq_true_mask ),
123904c96e61dd85c172b999d6afc88ce6640aeba9962sewardj                                              mkU32( 0x2 ) ) ) ) ),
123914c96e61dd85c172b999d6afc88ce6640aeba9962sewardj                  binop( Iop_And32,
123924c96e61dd85c172b999d6afc88ce6640aeba9962sewardj                         mkexpr( KisZero_true_mask ),
123934c96e61dd85c172b999d6afc88ce6640aeba9962sewardj                         mkU32( 0x4 ) ) ) );
123944c96e61dd85c172b999d6afc88ce6640aeba9962sewardj
123954c96e61dd85c172b999d6afc88ce6640aeba9962sewardj   putGST_field( PPC_GST_CR,
123964c96e61dd85c172b999d6afc88ce6640aeba9962sewardj                 binop( Iop_Or32,
123974c96e61dd85c172b999d6afc88ce6640aeba9962sewardj                        binop( Iop_And32,
123984c96e61dd85c172b999d6afc88ce6640aeba9962sewardj                               mkexpr( Unordered_true ),
123994c96e61dd85c172b999d6afc88ce6640aeba9962sewardj                               mkU32( 0x1 ) ),
124004c96e61dd85c172b999d6afc88ce6640aeba9962sewardj                        binop( Iop_And32,
124014c96e61dd85c172b999d6afc88ce6640aeba9962sewardj                               unop( Iop_Not32, mkexpr( Unordered_true ) ),
124024c96e61dd85c172b999d6afc88ce6640aeba9962sewardj                               mkexpr( field ) ) ),
124034c96e61dd85c172b999d6afc88ce6640aeba9962sewardj                 crfD );
124044c96e61dd85c172b999d6afc88ce6640aeba9962sewardj
124054c96e61dd85c172b999d6afc88ce6640aeba9962sewardj   return True;
124064c96e61dd85c172b999d6afc88ce6640aeba9962sewardj}
124075eff1c502e995d1f9668cc9def72d5db59f21b13sewardj
1240832aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion/*------------------------------------------------------------*/
1240932aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion/*--- AltiVec Instruction Translation                      ---*/
1241032aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion/*------------------------------------------------------------*/
1241132aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion
1241232aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion/*
1241332aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion  Altivec Cache Control Instructions (Data Streams)
1241432aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion*/
1241532aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerionstatic Bool dis_av_datastream ( UInt theInstr )
1241632aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion{
1241776de5cf615380b23b4b5bcced6541233cd4a93a0cerion   /* X-Form */
1241876de5cf615380b23b4b5bcced6541233cd4a93a0cerion   UChar opc1     = ifieldOPC(theInstr);
1241976de5cf615380b23b4b5bcced6541233cd4a93a0cerion   UChar flag_T   = toUChar( IFIELD( theInstr, 25, 1 ) );
1242076de5cf615380b23b4b5bcced6541233cd4a93a0cerion   UChar flag_A   = flag_T;
1242176de5cf615380b23b4b5bcced6541233cd4a93a0cerion   UChar b23to24  = toUChar( IFIELD( theInstr, 23, 2 ) );
1242276de5cf615380b23b4b5bcced6541233cd4a93a0cerion   UChar STRM     = toUChar( IFIELD( theInstr, 21, 2 ) );
1242376de5cf615380b23b4b5bcced6541233cd4a93a0cerion   UChar rA_addr  = ifieldRegA(theInstr);
1242476de5cf615380b23b4b5bcced6541233cd4a93a0cerion   UChar rB_addr  = ifieldRegB(theInstr);
1242576de5cf615380b23b4b5bcced6541233cd4a93a0cerion   UInt  opc2     = ifieldOPClo10(theInstr);
1242676de5cf615380b23b4b5bcced6541233cd4a93a0cerion   UChar b0       = ifieldBIT0(theInstr);
1242732aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion
1242832aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion   if (opc1 != 0x1F || b23to24 != 0 || b0 != 0) {
124295b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion      vex_printf("dis_av_datastream(ppc)(instr)\n");
1243032aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion      return False;
1243132aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion   }
1243232aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion
1243332aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion   switch (opc2) {
1243432aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion   case 0x156: // dst (Data Stream Touch, AV p115)
124355b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion      DIP("dst%s r%u,r%u,%d\n", flag_T ? "t" : "",
124365b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion                                rA_addr, rB_addr, STRM);
12437923c65b4e7bd32fb022735115d2bbcb8e03f13d2sewardj      break;
1243832aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion
1243932aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion   case 0x176: // dstst (Data Stream Touch for Store, AV p117)
124405b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion      DIP("dstst%s r%u,r%u,%d\n", flag_T ? "t" : "",
124415b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion                                  rA_addr, rB_addr, STRM);
12442923c65b4e7bd32fb022735115d2bbcb8e03f13d2sewardj      break;
1244332aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion
1244432aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion   case 0x336: // dss (Data Stream Stop, AV p114)
1244532aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion      if (rA_addr != 0 || rB_addr != 0) {
124465b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion         vex_printf("dis_av_datastream(ppc)(opc2,dst)\n");
1244732aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion         return False;
1244832aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion      }
1244932aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion      if (flag_A == 0) {
1245032aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion         DIP("dss %d\n", STRM);
1245132aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion      } else {
1245232aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion         DIP("dssall\n");
1245332aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion      }
12454923c65b4e7bd32fb022735115d2bbcb8e03f13d2sewardj      break;
1245532aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion
1245632aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion   default:
124575b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion      vex_printf("dis_av_datastream(ppc)(opc2)\n");
1245832aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion      return False;
1245932aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion   }
1246032aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion   return True;
1246132aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion}
1246232aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion
1246332aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion/*
1246432aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion  AltiVec Processor Control Instructions
1246532aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion*/
1246632aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerionstatic Bool dis_av_procctl ( UInt theInstr )
1246732aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion{
1246876de5cf615380b23b4b5bcced6541233cd4a93a0cerion   /* VX-Form */
1246976de5cf615380b23b4b5bcced6541233cd4a93a0cerion   UChar opc1    = ifieldOPC(theInstr);
1247076de5cf615380b23b4b5bcced6541233cd4a93a0cerion   UChar vD_addr = ifieldRegDS(theInstr);
1247176de5cf615380b23b4b5bcced6541233cd4a93a0cerion   UChar vA_addr = ifieldRegA(theInstr);
1247276de5cf615380b23b4b5bcced6541233cd4a93a0cerion   UChar vB_addr = ifieldRegB(theInstr);
1247376de5cf615380b23b4b5bcced6541233cd4a93a0cerion   UInt  opc2    = IFIELD( theInstr, 0, 11 );
1247432aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion
1247532aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion   if (opc1 != 0x4) {
124765b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion      vex_printf("dis_av_procctl(ppc)(instr)\n");
1247732aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion      return False;
1247832aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion   }
1247932aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion
1248032aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion   switch (opc2) {
1248132aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion   case 0x604: // mfvscr (Move from VSCR, AV p129)
1248232aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion      if (vA_addr != 0 || vB_addr != 0) {
124835b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion         vex_printf("dis_av_procctl(ppc)(opc2,dst)\n");
1248432aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion         return False;
1248532aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion      }
1248632aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion      DIP("mfvscr v%d\n", vD_addr);
12487d953ebb9b04cbad6891676df597bf0c542b1ec89cerion      putVReg( vD_addr, unop(Iop_32UtoV128, getGST( PPC_GST_VSCR )) );
12488225a034683024109da729a4d2f080364b9485007cerion      break;
1248932aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion
12490225a034683024109da729a4d2f080364b9485007cerion   case 0x644: { // mtvscr (Move to VSCR, AV p130)
12491197bd17d3ba8ac5204cd5c9ba5fab571249eb791sewardj      IRTemp vB = newTemp(Ity_V128);
1249232aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion      if (vD_addr != 0 || vA_addr != 0) {
124935b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion         vex_printf("dis_av_procctl(ppc)(opc2,dst)\n");
1249432aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion         return False;
1249532aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion      }
1249632aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion      DIP("mtvscr v%d\n", vB_addr);
12497225a034683024109da729a4d2f080364b9485007cerion      assign( vB, getVReg(vB_addr));
12498d953ebb9b04cbad6891676df597bf0c542b1ec89cerion      putGST( PPC_GST_VSCR, unop(Iop_V128to32, mkexpr(vB)) );
12499225a034683024109da729a4d2f080364b9485007cerion      break;
12500225a034683024109da729a4d2f080364b9485007cerion   }
1250132aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion   default:
125025b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion      vex_printf("dis_av_procctl(ppc)(opc2)\n");
1250332aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion      return False;
1250432aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion   }
1250532aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion   return True;
1250632aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion}
12507a982c0503d8c0c6069ae453bfe70657bd2c134aecerion
12508a982c0503d8c0c6069ae453bfe70657bd2c134aecerion/*
125094aa412af1d8166cc11f39a6e721df49431d23618sewardj * VSX scalar and vector convert instructions
1251066d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj */
1251166d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardjstatic Bool
1251266d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardjdis_vx_conv ( UInt theInstr, UInt opc2 )
1251366d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj{
1251466d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj   /* XX2-Form */
1251566d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj   UChar opc1 = ifieldOPC( theInstr );
1251666d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj   UChar XT = ifieldRegXT( theInstr );
1251766d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj   UChar XB = ifieldRegXB( theInstr );
12518e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj   IRTemp xB, xB2;
12519e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj   IRTemp b3, b2, b1, b0;
12520e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj   xB = xB2 = IRTemp_INVALID;
1252166d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj
1252266d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj   if (opc1 != 0x3C) {
1252366d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj      vex_printf( "dis_vx_conv(ppc)(instr)\n" );
1252466d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj      return False;
1252566d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj   }
1252666d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj
12527e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj   /* Create and assign temps only as needed for the given instruction. */
12528e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj   switch (opc2) {
12529e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj      // scalar double-precision floating point argument
125300c74bb5aa3240f693df0568d578baabf0c376dc4carll      case 0x2B0: case 0x0b0: case 0x290: case 0x212: case 0x216: case 0x090:
12531e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj         xB = newTemp(Ity_F64);
12532e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj         assign( xB,
12533e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj                 unop( Iop_ReinterpI64asF64,
12534e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj                       unop( Iop_V128HIto64, getVSReg( XB ) ) ) );
12535e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj         break;
12536e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj      // vector double-precision floating point arguments
12537e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj      case 0x1b0: case 0x312: case 0x390: case 0x190: case 0x3B0:
12538e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj
12539e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj         xB = newTemp(Ity_F64);
12540e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj         xB2 = newTemp(Ity_F64);
12541e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj         assign( xB,
12542e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj                 unop( Iop_ReinterpI64asF64,
12543e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj                       unop( Iop_V128HIto64, getVSReg( XB ) ) ) );
12544e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj         assign( xB2,
12545e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj                 unop( Iop_ReinterpI64asF64,
12546e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj                       unop( Iop_V128to64, getVSReg( XB ) ) ) );
12547e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj         break;
12548e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj      // vector single precision or [un]signed integer word arguments
12549e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj      case 0x130: case 0x392: case 0x330: case 0x310: case 0x110:
12550e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj      case 0x1f0: case 0x1d0:
12551e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj         b3 = b2 = b1 = b0 = IRTemp_INVALID;
12552e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj         breakV128to4x32(getVSReg(XB), &b3, &b2, &b1, &b0);
12553e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj         break;
12554e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj         // vector [un]signed integer doubleword argument
12555e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj      case 0x3f0: case 0x370: case 0x3d0: case 0x350:
12556e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj         xB = newTemp(Ity_I64);
12557e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj         assign( xB, unop( Iop_V128HIto64, getVSReg( XB ) ) );
12558e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj         xB2 = newTemp(Ity_I64);
12559e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj         assign( xB2, unop( Iop_V128to64, getVSReg( XB ) ) );
12560e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj         break;
12561e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj      // scalar [un]signed integer doubleword argument
125626c758b64a77c254065ab7450576bbd3a0b583595carll      case 0x250: case 0x270: case 0x2D0: case 0x2F0:
12563e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj         xB = newTemp(Ity_I64);
12564e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj         assign( xB, unop( Iop_V128HIto64, getVSReg( XB ) ) );
12565e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj         break;
12566e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj      // scalar single precision argument
12567e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj      case 0x292: // xscvspdp
125686fef87a15cd79526ece8c38798e2d304b805a1f3carll         xB  = newTemp(Ity_I32);
125696fef87a15cd79526ece8c38798e2d304b805a1f3carll
125706fef87a15cd79526ece8c38798e2d304b805a1f3carll         assign( xB, handle_SNaN_to_QNaN_32(unop( Iop_64HIto32,
125716fef87a15cd79526ece8c38798e2d304b805a1f3carll                                                  unop( Iop_V128HIto64,
125726fef87a15cd79526ece8c38798e2d304b805a1f3carll                                                        getVSReg( XB ) ) ) ) );
12573e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj         break;
125740c74bb5aa3240f693df0568d578baabf0c376dc4carll      case 0x296: // xscvspdpn (non signaling version of xscvpdp)
125750c74bb5aa3240f693df0568d578baabf0c376dc4carll         xB = newTemp(Ity_I32);
125760c74bb5aa3240f693df0568d578baabf0c376dc4carll         assign( xB,
125770c74bb5aa3240f693df0568d578baabf0c376dc4carll                 unop( Iop_64HIto32, unop( Iop_V128HIto64, getVSReg( XB ) ) ) );
125780c74bb5aa3240f693df0568d578baabf0c376dc4carll         break;
12579e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj
12580e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj      /* Certain instructions have their complete implementation in the main switch statement
12581e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj       * that follows this one; thus we have a "do nothing" case for those instructions here.
12582e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj       */
12583e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj      case 0x170: case 0x150:
12584e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj         break; // do nothing
12585e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj
12586e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj      default:
12587e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj         vex_printf( "dis_vx_conv(ppc)(opc2)\n" );
12588e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj         return False;
12589e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj   }
12590e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj
1259166d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj
1259266d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj   switch (opc2) {
12593e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj      case 0x2B0:
12594e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj         // xscvdpsxds (VSX Scalar truncate Double-Precision to integer and Convert
12595e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj         //             to Signed Integer Doubleword format with Saturate)
12596e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj         DIP("xscvdpsxds v%u,v%u\n",  (UInt)XT, (UInt)XB);
12597e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj         putVSReg( XT,
1259866d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj                   binop( Iop_64HLtoV128, binop( Iop_F64toI64S,
1259966d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj                                                 mkU32( Irrm_ZERO ),
12600e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj                                                 mkexpr( xB ) ), mkU64( 0 ) ) );
12601e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj         break;
12602e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj      case 0x0b0: // xscvdpsxws (VSX Scalar truncate Double-Precision to integer and
12603e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj                  //             Convert to Signed Integer Word format with Saturate)
12604e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj         DIP("xscvdpsxws v%u,v%u\n",  (UInt)XT, (UInt)XB);
12605e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj         putVSReg( XT,
126064aa412af1d8166cc11f39a6e721df49431d23618sewardj                   binop( Iop_64HLtoV128,
126074aa412af1d8166cc11f39a6e721df49431d23618sewardj                          unop( Iop_32Sto64,
126084aa412af1d8166cc11f39a6e721df49431d23618sewardj                                binop( Iop_F64toI32S,
126094aa412af1d8166cc11f39a6e721df49431d23618sewardj                                       mkU32( Irrm_ZERO ),
12610e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj                                       mkexpr( xB ) ) ),
12611e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj                                       mkU64( 0ULL ) ) );
126124aa412af1d8166cc11f39a6e721df49431d23618sewardj         break;
12613e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj      case 0x290: // xscvdpuxds (VSX Scalar truncate Double-Precision integer and Convert
12614e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj                  //             to Unsigned Integer Doubleword format with Saturate)
12615e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj         DIP("xscvdpuxds v%u,v%u\n",  (UInt)XT, (UInt)XB);
12616e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj         putVSReg( XT,
126174aa412af1d8166cc11f39a6e721df49431d23618sewardj                   binop( Iop_64HLtoV128,
126184aa412af1d8166cc11f39a6e721df49431d23618sewardj                          binop( Iop_F64toI64U,
126194aa412af1d8166cc11f39a6e721df49431d23618sewardj                                 mkU32( Irrm_ZERO ),
12620e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj                                 mkexpr( xB ) ),
12621e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj                                 mkU64( 0ULL ) ) );
12622e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj         break;
126236c758b64a77c254065ab7450576bbd3a0b583595carll      case 0x270:
126246c758b64a77c254065ab7450576bbd3a0b583595carll         // xscvsxdsp (VSX Scalar Convert and round Signed Integer Doubleword
126256c758b64a77c254065ab7450576bbd3a0b583595carll         //             to Single-Precision format)
126266c758b64a77c254065ab7450576bbd3a0b583595carll         DIP("xscvsxdsp v%u,v%u\n",  (UInt)XT, (UInt)XB);
126276c758b64a77c254065ab7450576bbd3a0b583595carll         putVSReg( XT,
126286c758b64a77c254065ab7450576bbd3a0b583595carll                   binop( Iop_64HLtoV128,
126296c758b64a77c254065ab7450576bbd3a0b583595carll                          unop( Iop_ReinterpF64asI64,
126306c758b64a77c254065ab7450576bbd3a0b583595carll                                binop( Iop_RoundF64toF32,
126316c758b64a77c254065ab7450576bbd3a0b583595carll                                       get_IR_roundingmode(),
126326c758b64a77c254065ab7450576bbd3a0b583595carll                                       binop( Iop_I64StoF64,
126336c758b64a77c254065ab7450576bbd3a0b583595carll                                              get_IR_roundingmode(),
126346c758b64a77c254065ab7450576bbd3a0b583595carll                                              mkexpr( xB ) ) ) ),
126356c758b64a77c254065ab7450576bbd3a0b583595carll                          mkU64( 0 ) ) );
126366c758b64a77c254065ab7450576bbd3a0b583595carll         break;
12637e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj      case 0x2F0:
12638e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj         // xscvsxddp (VSX Scalar Convert and round Signed Integer Doubleword to
12639e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj         //            Double-Precision format)
12640e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj         DIP("xscvsxddp v%u,v%u\n",  (UInt)XT, (UInt)XB);
12641e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj         putVSReg( XT,
1264266d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj                   binop( Iop_64HLtoV128, unop( Iop_ReinterpF64asI64,
126434aa412af1d8166cc11f39a6e721df49431d23618sewardj                                                binop( Iop_I64StoF64, get_IR_roundingmode(),
12644e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj                                                       mkexpr( xB ) ) ),
12645e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj                                                       mkU64( 0 ) ) );
12646e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj         break;
126476c758b64a77c254065ab7450576bbd3a0b583595carll      case 0x250:
126486c758b64a77c254065ab7450576bbd3a0b583595carll         // xscvuxdsp (VSX Scalar Convert and round Unsigned Integer
126496c758b64a77c254065ab7450576bbd3a0b583595carll         //            Doubleword to Singel-Precision format)
126506c758b64a77c254065ab7450576bbd3a0b583595carll         DIP("xscvuxdsp v%u,v%u\n",  (UInt)XT, (UInt)XB);
126516c758b64a77c254065ab7450576bbd3a0b583595carll         putVSReg( XT,
126526c758b64a77c254065ab7450576bbd3a0b583595carll                   binop( Iop_64HLtoV128,
126536c758b64a77c254065ab7450576bbd3a0b583595carll                          unop( Iop_ReinterpF64asI64,
126546c758b64a77c254065ab7450576bbd3a0b583595carll                                binop( Iop_RoundF64toF32,
126556c758b64a77c254065ab7450576bbd3a0b583595carll                                       get_IR_roundingmode(),
126566c758b64a77c254065ab7450576bbd3a0b583595carll                                       binop( Iop_I64UtoF64,
126576c758b64a77c254065ab7450576bbd3a0b583595carll                                              get_IR_roundingmode(),
126586c758b64a77c254065ab7450576bbd3a0b583595carll                                              mkexpr( xB ) ) ) ),
126596c758b64a77c254065ab7450576bbd3a0b583595carll                          mkU64( 0 ) ) );
126606c758b64a77c254065ab7450576bbd3a0b583595carll         break;
12661e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj      case 0x2D0:
12662e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj         // xscvuxddp (VSX Scalar Convert and round Unsigned Integer Doubleword to
12663e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj         //            Double-Precision format)
12664e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj         DIP("xscvuxddp v%u,v%u\n",  (UInt)XT, (UInt)XB);
12665e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj         putVSReg( XT,
1266666d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj                   binop( Iop_64HLtoV128, unop( Iop_ReinterpF64asI64,
126674aa412af1d8166cc11f39a6e721df49431d23618sewardj                                                binop( Iop_I64UtoF64, get_IR_roundingmode(),
12668e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj                                                       mkexpr( xB ) ) ),
12669e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj                                                       mkU64( 0 ) ) );
12670e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj         break;
12671e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj      case 0x1b0: // xvcvdpsxws (VSX Vector truncate Double-Precision to integer and Convert
12672e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj                  //             to Signed Integer Word format with Saturate)
12673e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj      {
12674e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj         IRTemp hiResult_32 = newTemp(Ity_I32);
12675e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj         IRTemp loResult_32 = newTemp(Ity_I32);
12676e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj         IRExpr* rmZero = mkU32(Irrm_ZERO);
1267766d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj
12678e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj         DIP("xvcvdpsxws v%u,v%u\n",  (UInt)XT, (UInt)XB);
12679e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj         assign(hiResult_32, binop(Iop_F64toI32S, rmZero, mkexpr(xB)));
12680e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj         assign(loResult_32, binop(Iop_F64toI32S, rmZero, mkexpr(xB2)));
12681e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj         putVSReg( XT,
126824aa412af1d8166cc11f39a6e721df49431d23618sewardj                   binop( Iop_64HLtoV128,
126834aa412af1d8166cc11f39a6e721df49431d23618sewardj                          unop( Iop_32Sto64, mkexpr( hiResult_32 ) ),
126844aa412af1d8166cc11f39a6e721df49431d23618sewardj                          unop( Iop_32Sto64, mkexpr( loResult_32 ) ) ) );
12685e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj         break;
12686e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj      }
12687e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj      case 0x130: case 0x110: // xvcvspsxws, xvcvspuxws
12688e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj         //  (VSX Vector truncate Single-Precision to integer and
12689e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj         //   Convert to [Un]signed Integer Word format with Saturate)
12690e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj      {
12691e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj         IRExpr * b0_result, * b1_result, * b2_result, * b3_result;
12692e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj         IRTemp tempResult = newTemp(Ity_V128);
12693e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj         IRTemp res0 = newTemp(Ity_I32);
12694e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj         IRTemp res1 = newTemp(Ity_I32);
12695e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj         IRTemp res2 = newTemp(Ity_I32);
12696e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj         IRTemp res3 = newTemp(Ity_I32);
12697e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj         IRTemp hi64 = newTemp(Ity_I64);
12698e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj         IRTemp lo64 = newTemp(Ity_I64);
12699e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj         Bool un_signed = (opc2 == 0x110);
12700e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj         IROp op = un_signed ? Iop_QFtoI32Ux4_RZ : Iop_QFtoI32Sx4_RZ;
12701e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj
12702e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj         DIP("xvcvsp%sxws v%u,v%u\n", un_signed ? "u" : "s", (UInt)XT, (UInt)XB);
12703e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj         /* The xvcvsp{s|u}xws instruction is similar to vct{s|u}xs, except if src is a NaN,
12704e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj          * then result is set to 0x80000000.  */
12705e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj         assign(tempResult, unop(op, getVSReg(XB)));
12706e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj         assign( hi64, unop(Iop_V128HIto64, mkexpr(tempResult)) );
12707e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj         assign( lo64, unop(Iop_V128to64,   mkexpr(tempResult)) );
12708e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj         assign( res3, unop(Iop_64HIto32, mkexpr(hi64)) );
12709e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj         assign( res2, unop(Iop_64to32,   mkexpr(hi64)) );
12710e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj         assign( res1, unop(Iop_64HIto32, mkexpr(lo64)) );
12711e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj         assign( res0, unop(Iop_64to32,   mkexpr(lo64)) );
12712e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj
1271399dd03e04a6914d90d5fee727d61d76905334becflorian         b3_result = IRExpr_ITE(is_NaN_32(b3),
1271499dd03e04a6914d90d5fee727d61d76905334becflorian                                // then: result is 0x{8|0}80000000
1271599dd03e04a6914d90d5fee727d61d76905334becflorian                                mkU32(un_signed ? 0x00000000 : 0x80000000),
1271699dd03e04a6914d90d5fee727d61d76905334becflorian                                // else: result is from the Iop_QFtoI32{s|u}x4_RZ
1271799dd03e04a6914d90d5fee727d61d76905334becflorian                                mkexpr(res3));
1271899dd03e04a6914d90d5fee727d61d76905334becflorian         b2_result = IRExpr_ITE(is_NaN_32(b2),
1271999dd03e04a6914d90d5fee727d61d76905334becflorian                                // then: result is 0x{8|0}80000000
1272099dd03e04a6914d90d5fee727d61d76905334becflorian                                mkU32(un_signed ? 0x00000000 : 0x80000000),
1272199dd03e04a6914d90d5fee727d61d76905334becflorian                                // else: result is from the Iop_QFtoI32{s|u}x4_RZ
1272299dd03e04a6914d90d5fee727d61d76905334becflorian                                mkexpr(res2));
1272399dd03e04a6914d90d5fee727d61d76905334becflorian         b1_result = IRExpr_ITE(is_NaN_32(b1),
1272499dd03e04a6914d90d5fee727d61d76905334becflorian                                // then: result is 0x{8|0}80000000
1272599dd03e04a6914d90d5fee727d61d76905334becflorian                                mkU32(un_signed ? 0x00000000 : 0x80000000),
1272699dd03e04a6914d90d5fee727d61d76905334becflorian                                // else: result is from the Iop_QFtoI32{s|u}x4_RZ
1272799dd03e04a6914d90d5fee727d61d76905334becflorian                                mkexpr(res1));
1272899dd03e04a6914d90d5fee727d61d76905334becflorian         b0_result = IRExpr_ITE(is_NaN_32(b0),
1272999dd03e04a6914d90d5fee727d61d76905334becflorian                                // then: result is 0x{8|0}80000000
1273099dd03e04a6914d90d5fee727d61d76905334becflorian                                mkU32(un_signed ? 0x00000000 : 0x80000000),
1273199dd03e04a6914d90d5fee727d61d76905334becflorian                                // else: result is from the Iop_QFtoI32{s|u}x4_RZ
1273299dd03e04a6914d90d5fee727d61d76905334becflorian                                mkexpr(res0));
12733e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj
12734e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj         putVSReg( XT,
127354aa412af1d8166cc11f39a6e721df49431d23618sewardj                   binop( Iop_64HLtoV128,
127364aa412af1d8166cc11f39a6e721df49431d23618sewardj                          binop( Iop_32HLto64, b3_result, b2_result ),
127374aa412af1d8166cc11f39a6e721df49431d23618sewardj                          binop( Iop_32HLto64, b1_result, b0_result ) ) );
12738e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj         break;
12739e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj      }
12740e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj      case 0x212: // xscvdpsp (VSX Scalar round Double-Precision to single-precision and
12741e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj                  //           Convert to Single-Precision format
12742e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj         DIP("xscvdpsp v%u,v%u\n",  (UInt)XT, (UInt)XB);
12743e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj         putVSReg( XT,
12744e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj                   binop( Iop_64HLtoV128,
12745e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj                          binop( Iop_32HLto64,
12746e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj                                 unop( Iop_ReinterpF32asI32,
12747e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj                                       unop( Iop_TruncF64asF32,
12748e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj                                             binop( Iop_RoundF64toF32,
12749e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj                                                    get_IR_roundingmode(),
12750e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj                                                    mkexpr( xB ) ) ) ),
12751e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj                                 mkU32( 0 ) ),
12752e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj                          mkU64( 0ULL ) ) );
12753e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj         break;
127540c74bb5aa3240f693df0568d578baabf0c376dc4carll      case 0x216: /* xscvdpspn (VSX Scalar convert scalar Single-Precision to
127556c758b64a77c254065ab7450576bbd3a0b583595carll                              vector Single-Precision non-signalling */
127560c74bb5aa3240f693df0568d578baabf0c376dc4carll         DIP("xscvdpspn v%u,v%u\n",  (UInt)XT, (UInt)XB);
127570c74bb5aa3240f693df0568d578baabf0c376dc4carll         putVSReg( XT,
127580c74bb5aa3240f693df0568d578baabf0c376dc4carll                   binop( Iop_64HLtoV128,
127590c74bb5aa3240f693df0568d578baabf0c376dc4carll                          binop( Iop_32HLto64,
127600c74bb5aa3240f693df0568d578baabf0c376dc4carll                                 unop( Iop_ReinterpF32asI32,
127610c74bb5aa3240f693df0568d578baabf0c376dc4carll                                       unop( Iop_TruncF64asF32,
127620c74bb5aa3240f693df0568d578baabf0c376dc4carll                                             mkexpr( xB ) ) ),
127636c758b64a77c254065ab7450576bbd3a0b583595carll                                 mkU32( 0 ) ),
127646c758b64a77c254065ab7450576bbd3a0b583595carll                          mkU64( 0ULL ) ) );
127650c74bb5aa3240f693df0568d578baabf0c376dc4carll         break;
12766e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj      case 0x090: // xscvdpuxws (VSX Scalar truncate Double-Precision to integer
12767e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj                  //             and Convert to Unsigned Integer Word format with Saturate)
12768e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj         DIP("xscvdpuxws v%u,v%u\n",  (UInt)XT, (UInt)XB);
12769e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj         putVSReg( XT,
12770e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj                   binop( Iop_64HLtoV128,
12771e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj                          binop( Iop_32HLto64,
12772e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj                                 mkU32( 0 ),
12773e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj                                 binop( Iop_F64toI32U,
12774e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj                                        mkU32( Irrm_ZERO ),
12775e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj                                        mkexpr( xB ) ) ),
12776e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj                          mkU64( 0ULL ) ) );
12777e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj         break;
127786c758b64a77c254065ab7450576bbd3a0b583595carll      case 0x292: // xscvspdp (VSX Scalar Convert Single-Precision to Double-Precision format, signaling)
12779e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj         DIP("xscvspdp v%u,v%u\n",  (UInt)XT, (UInt)XB);
12780e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj         putVSReg( XT,
12781e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj                   binop( Iop_64HLtoV128,
12782e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj                          unop( Iop_ReinterpF64asI64,
12783e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj                                unop( Iop_F32toF64,
12784e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj                                      unop( Iop_ReinterpI32asF32, mkexpr( xB ) ) ) ),
12785e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj                          mkU64( 0ULL ) ) );
12786e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj         break;
127870c74bb5aa3240f693df0568d578baabf0c376dc4carll      case 0x296: // xscvspdpn (VSX Scalar Convert Single-Precision to Double-Precision format Non signaling)
127880c74bb5aa3240f693df0568d578baabf0c376dc4carll         DIP("xscvspdpn v%u,v%u\n",  (UInt)XT, (UInt)XB);
127890c74bb5aa3240f693df0568d578baabf0c376dc4carll         putVSReg( XT,
127900c74bb5aa3240f693df0568d578baabf0c376dc4carll                   binop( Iop_64HLtoV128,
127910c74bb5aa3240f693df0568d578baabf0c376dc4carll                          unop( Iop_ReinterpF64asI64,
127920c74bb5aa3240f693df0568d578baabf0c376dc4carll                                unop( Iop_F32toF64,
127930c74bb5aa3240f693df0568d578baabf0c376dc4carll                                      unop( Iop_ReinterpI32asF32, mkexpr( xB ) ) ) ),
127940c74bb5aa3240f693df0568d578baabf0c376dc4carll                                      mkU64( 0ULL ) ) );
127950c74bb5aa3240f693df0568d578baabf0c376dc4carll         break;
12796e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj      case 0x312: // xvcvdpsp (VSX Vector round Double-Precision to single-precision
12797e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj                  //           and Convert to Single-Precision format)
12798e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj         DIP("xvcvdpsp v%u,v%u\n",  (UInt)XT, (UInt)XB);
12799e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj         putVSReg( XT,
12800e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj                   binop( Iop_64HLtoV128,
12801e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj                          binop( Iop_32HLto64,
12802e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj                                 unop( Iop_ReinterpF32asI32,
12803e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj                                       unop( Iop_TruncF64asF32,
12804e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj                                             binop( Iop_RoundF64toF32,
12805e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj                                                    get_IR_roundingmode(),
12806e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj                                                    mkexpr( xB ) ) ) ),
12807e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj                                 mkU32( 0 ) ),
12808e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj                          binop( Iop_32HLto64,
12809e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj                                 unop( Iop_ReinterpF32asI32,
12810e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj                                       unop( Iop_TruncF64asF32,
12811e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj                                             binop( Iop_RoundF64toF32,
12812e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj                                                    get_IR_roundingmode(),
12813e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj                                                    mkexpr( xB2 ) ) ) ),
12814e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj                                 mkU32( 0 ) ) ) );
12815e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj         break;
12816e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj      case 0x390: // xvcvdpuxds (VSX Vector truncate Double-Precision to integer
12817e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj                  //             and Convert to Unsigned Integer Doubleword format
12818e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj                  //             with Saturate)
12819e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj         DIP("xvcvdpuxds v%u,v%u\n",  (UInt)XT, (UInt)XB);
12820e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj         putVSReg( XT,
12821e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj                   binop( Iop_64HLtoV128,
12822e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj                          binop( Iop_F64toI64U, mkU32( Irrm_ZERO ), mkexpr( xB ) ),
12823e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj                          binop( Iop_F64toI64U, mkU32( Irrm_ZERO ), mkexpr( xB2 ) ) ) );
12824e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj         break;
12825e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj      case 0x190: // xvcvdpuxws (VSX Vector truncate Double-Precision to integer and
12826e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj                  //             Convert to Unsigned Integer Word format with Saturate)
12827e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj         DIP("xvcvdpuxws v%u,v%u\n",  (UInt)XT, (UInt)XB);
12828e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj         putVSReg( XT,
12829e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj                   binop( Iop_64HLtoV128,
12830e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj                          binop( Iop_32HLto64,
12831e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj                                 binop( Iop_F64toI32U,
12832e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj                                        mkU32( Irrm_ZERO ),
12833e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj                                        mkexpr( xB ) ),
12834e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj                                 mkU32( 0 ) ),
12835e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj                          binop( Iop_32HLto64,
12836e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj                                 binop( Iop_F64toI32U,
12837e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj                                        mkU32( Irrm_ZERO ),
12838e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj                                        mkexpr( xB2 ) ),
12839e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj                                 mkU32( 0 ) ) ) );
12840e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj         break;
12841e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj      case 0x392: // xvcvspdp (VSX Vector Convert Single-Precision to Double-Precision format)
12842e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj         DIP("xvcvspdp v%u,v%u\n",  (UInt)XT, (UInt)XB);
12843e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj         putVSReg( XT,
12844e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj                   binop( Iop_64HLtoV128,
12845e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj                          unop( Iop_ReinterpF64asI64,
12846e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj                                unop( Iop_F32toF64,
128476fef87a15cd79526ece8c38798e2d304b805a1f3carll                                      unop( Iop_ReinterpI32asF32,
128486fef87a15cd79526ece8c38798e2d304b805a1f3carll                                            handle_SNaN_to_QNaN_32( mkexpr( b3 ) ) ) ) ),
12849e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj                          unop( Iop_ReinterpF64asI64,
12850e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj                                unop( Iop_F32toF64,
128516fef87a15cd79526ece8c38798e2d304b805a1f3carll                                      unop( Iop_ReinterpI32asF32,
128526fef87a15cd79526ece8c38798e2d304b805a1f3carll                                            handle_SNaN_to_QNaN_32( mkexpr( b1 ) ) ) ) ) ) );
12853e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj         break;
12854e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj      case 0x330: // xvcvspsxds (VSX Vector truncate Single-Precision to integer and
12855e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj                  //           Convert to Signed Integer Doubleword format with Saturate)
12856e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj         DIP("xvcvspsxds v%u,v%u\n",  (UInt)XT, (UInt)XB);
12857e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj         putVSReg( XT,
12858e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj                   binop( Iop_64HLtoV128,
12859e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj                          binop( Iop_F64toI64S,
12860e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj                                 mkU32( Irrm_ZERO ),
12861e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj                                 unop( Iop_F32toF64,
12862e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj                                       unop( Iop_ReinterpI32asF32, mkexpr( b3 ) ) ) ),
12863e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj                          binop( Iop_F64toI64S,
12864e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj                                 mkU32( Irrm_ZERO ),
12865e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj                                 unop( Iop_F32toF64,
12866e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj                                       unop( Iop_ReinterpI32asF32, mkexpr( b1 ) ) ) ) ) );
12867e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj         break;
12868e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj      case 0x310: // xvcvspuxds (VSX Vector truncate Single-Precision to integer and
12869e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj                  //            Convert to Unsigned Integer Doubleword format with Saturate)
12870e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj         DIP("xvcvspuxds v%u,v%u\n",  (UInt)XT, (UInt)XB);
12871e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj         putVSReg( XT,
12872e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj                   binop( Iop_64HLtoV128,
12873e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj                          binop( Iop_F64toI64U,
12874e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj                                 mkU32( Irrm_ZERO ),
12875e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj                                 unop( Iop_F32toF64,
12876e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj                                       unop( Iop_ReinterpI32asF32, mkexpr( b3 ) ) ) ),
12877e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj                          binop( Iop_F64toI64U,
12878e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj                                 mkU32( Irrm_ZERO ),
12879e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj                                 unop( Iop_F32toF64,
12880e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj                                       unop( Iop_ReinterpI32asF32, mkexpr( b1 ) ) ) ) ) );
12881e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj         break;
12882e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj      case 0x3B0: // xvcvdpsxds (VSX Vector truncate Double-Precision to integer and
12883e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj                  //             Convert to Signed Integer Doubleword format with Saturate)
12884e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj         DIP("xvcvdpsxds v%u,v%u\n",  (UInt)XT, (UInt)XB);
12885e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj         putVSReg( XT,
12886e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj                   binop( Iop_64HLtoV128,
12887e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj                          binop( Iop_F64toI64S, mkU32( Irrm_ZERO ), mkexpr( xB ) ),
12888e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj                          binop( Iop_F64toI64S, mkU32( Irrm_ZERO ), mkexpr( xB2 ) ) ) );
12889e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj         break;
12890e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj      case 0x3f0: // xvcvsxddp (VSX Vector Convert and round Signed Integer Doubleword
12891e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj                  //            to Double-Precision format)
12892e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj         DIP("xvcvsxddp v%u,v%u\n",  (UInt)XT, (UInt)XB);
12893e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj         putVSReg( XT,
12894e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj                   binop( Iop_64HLtoV128,
12895e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj                          unop( Iop_ReinterpF64asI64,
12896e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj                                binop( Iop_I64StoF64,
12897e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj                                       get_IR_roundingmode(),
12898e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj                                       mkexpr( xB ) ) ),
12899e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj                          unop( Iop_ReinterpF64asI64,
12900e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj                                binop( Iop_I64StoF64,
12901e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj                                       get_IR_roundingmode(),
12902e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj                                       mkexpr( xB2 ) ) ) ) );
12903e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj         break;
12904e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj      case 0x3d0: // xvcvuxddp (VSX Vector Convert and round Unsigned Integer Doubleword
12905e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj                  //            to Double-Precision format)
12906e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj         DIP("xvcvuxddp v%u,v%u\n",  (UInt)XT, (UInt)XB);
12907e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj         putVSReg( XT,
12908e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj                   binop( Iop_64HLtoV128,
12909e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj                          unop( Iop_ReinterpF64asI64,
12910e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj                                binop( Iop_I64UtoF64,
12911e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj                                       get_IR_roundingmode(),
12912e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj                                       mkexpr( xB ) ) ),
12913e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj                          unop( Iop_ReinterpF64asI64,
12914e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj                                binop( Iop_I64UtoF64,
12915e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj                                       get_IR_roundingmode(),
12916e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj                                       mkexpr( xB2 ) ) ) ) );
12917e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj
12918e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj         break;
12919e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj      case 0x370: // xvcvsxdsp (VSX Vector Convert and round Signed Integer Doubleword
12920e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj                  //            to Single-Precision format)
12921e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj         DIP("xvcvsxddp v%u,v%u\n",  (UInt)XT, (UInt)XB);
12922e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj         putVSReg( XT,
12923e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj                   binop( Iop_64HLtoV128,
12924e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj                          binop( Iop_32HLto64,
12925e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj                                 unop( Iop_ReinterpF32asI32,
12926e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj                                       unop( Iop_TruncF64asF32,
12927e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj                                             binop( Iop_RoundF64toF32,
12928e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj                                                    get_IR_roundingmode(),
12929e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj                                                    binop( Iop_I64StoF64,
12930e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj                                                           get_IR_roundingmode(),
12931e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj                                                           mkexpr( xB ) ) ) ) ),
12932e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj                                 mkU32( 0 ) ),
12933e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj                          binop( Iop_32HLto64,
12934e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj                                 unop( Iop_ReinterpF32asI32,
12935e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj                                       unop( Iop_TruncF64asF32,
12936e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj                                             binop( Iop_RoundF64toF32,
12937e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj                                                    get_IR_roundingmode(),
12938e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj                                                    binop( Iop_I64StoF64,
12939e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj                                                           get_IR_roundingmode(),
12940e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj                                                           mkexpr( xB2 ) ) ) ) ),
12941e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj                                 mkU32( 0 ) ) ) );
12942e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj         break;
12943e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj      case 0x350: // xvcvuxdsp (VSX Vector Convert and round Unsigned Integer Doubleword
12944e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj                  //            to Single-Precision format)
12945e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj         DIP("xvcvuxddp v%u,v%u\n", (UInt)XT, (UInt)XB);
12946e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj         putVSReg( XT,
12947e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj                   binop( Iop_64HLtoV128,
12948e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj                          binop( Iop_32HLto64,
12949e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj                                 unop( Iop_ReinterpF32asI32,
12950e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj                                       unop( Iop_TruncF64asF32,
12951e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj                                             binop( Iop_RoundF64toF32,
12952e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj                                                    get_IR_roundingmode(),
12953e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj                                                    binop( Iop_I64UtoF64,
12954e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj                                                           get_IR_roundingmode(),
12955e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj                                                           mkexpr( xB ) ) ) ) ),
12956e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj                                 mkU32( 0 ) ),
12957e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj                          binop( Iop_32HLto64,
12958e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj                                 unop( Iop_ReinterpF32asI32,
12959e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj                                       unop( Iop_TruncF64asF32,
12960e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj                                             binop( Iop_RoundF64toF32,
12961e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj                                                    get_IR_roundingmode(),
12962e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj                                                    binop( Iop_I64UtoF64,
12963e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj                                                           get_IR_roundingmode(),
12964e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj                                                           mkexpr( xB2 ) ) ) ) ),
12965e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj                                 mkU32( 0 ) ) ) );
12966e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj         break;
12967e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj
12968e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj      case 0x1f0: // xvcvsxwdp (VSX Vector Convert Signed Integer Word to Double-Precision format)
12969e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj         DIP("xvcvsxwdp v%u,v%u\n",  (UInt)XT, (UInt)XB);
12970e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj         putVSReg( XT,
12971e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj                   binop( Iop_64HLtoV128,
12972e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj                          unop( Iop_ReinterpF64asI64,
12973e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj                                binop( Iop_I64StoF64, get_IR_roundingmode(),
12974e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj                                       unop( Iop_32Sto64, mkexpr( b3 ) ) ) ),
12975e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj                          unop( Iop_ReinterpF64asI64,
12976e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj                                binop( Iop_I64StoF64, get_IR_roundingmode(),
12977e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj                                       unop( Iop_32Sto64, mkexpr( b1 ) ) ) ) ) );
12978e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj         break;
12979e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj      case 0x1d0: // xvcvuxwdp (VSX Vector Convert Unsigned Integer Word to Double-Precision format)
12980e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj         DIP("xvcvuxwdp v%u,v%u\n",  (UInt)XT, (UInt)XB);
12981e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj         putVSReg( XT,
12982e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj                   binop( Iop_64HLtoV128,
12983e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj                          unop( Iop_ReinterpF64asI64,
12984e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj                                binop( Iop_I64UtoF64, get_IR_roundingmode(),
12985e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj                                       unop( Iop_32Uto64, mkexpr( b3 ) ) ) ),
12986e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj                          unop( Iop_ReinterpF64asI64,
12987e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj                                binop( Iop_I64UtoF64, get_IR_roundingmode(),
12988e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj                                       unop( Iop_32Uto64, mkexpr( b1 ) ) ) ) ) );
12989e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj         break;
12990e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj      case 0x170: // xvcvsxwsp (VSX Vector Convert Signed Integer Word to Single-Precision format)
12991e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj         DIP("xvcvsxwsp v%u,v%u\n",  (UInt)XT, (UInt)XB);
12992e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj         putVSReg( XT, unop( Iop_I32StoFx4, getVSReg( XB ) ) );
12993e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj         break;
12994e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj      case 0x150: // xvcvuxwsp (VSX Vector Convert Unsigned Integer Word to Single-Precision format)
12995e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj         DIP("xvcvuxwsp v%u,v%u\n",  (UInt)XT, (UInt)XB);
12996e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj         putVSReg( XT, unop( Iop_I32UtoFx4, getVSReg( XB ) ) );
12997e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj         break;
129984aa412af1d8166cc11f39a6e721df49431d23618sewardj
12999e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj      default:
13000e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj         vex_printf( "dis_vx_conv(ppc)(opc2)\n" );
13001e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj         return False;
1300266d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj   }
1300366d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj   return True;
1300466d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj}
1300566d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj
1300666d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj/*
130074aa412af1d8166cc11f39a6e721df49431d23618sewardj * VSX vector Double Precision Floating Point Arithmetic Instructions
130084aa412af1d8166cc11f39a6e721df49431d23618sewardj */
130094aa412af1d8166cc11f39a6e721df49431d23618sewardjstatic Bool
130104aa412af1d8166cc11f39a6e721df49431d23618sewardjdis_vxv_dp_arith ( UInt theInstr, UInt opc2 )
130114aa412af1d8166cc11f39a6e721df49431d23618sewardj{
130124aa412af1d8166cc11f39a6e721df49431d23618sewardj   /* XX3-Form */
130134aa412af1d8166cc11f39a6e721df49431d23618sewardj   UChar opc1 = ifieldOPC( theInstr );
130144aa412af1d8166cc11f39a6e721df49431d23618sewardj   UChar XT = ifieldRegXT( theInstr );
130154aa412af1d8166cc11f39a6e721df49431d23618sewardj   UChar XA = ifieldRegXA( theInstr );
130164aa412af1d8166cc11f39a6e721df49431d23618sewardj   UChar XB = ifieldRegXB( theInstr );
130174aa412af1d8166cc11f39a6e721df49431d23618sewardj   IRExpr* rm = get_IR_roundingmode();
130184aa412af1d8166cc11f39a6e721df49431d23618sewardj   IRTemp frA = newTemp(Ity_F64);
130194aa412af1d8166cc11f39a6e721df49431d23618sewardj   IRTemp frB = newTemp(Ity_F64);
130204aa412af1d8166cc11f39a6e721df49431d23618sewardj   IRTemp frA2 = newTemp(Ity_F64);
130214aa412af1d8166cc11f39a6e721df49431d23618sewardj   IRTemp frB2 = newTemp(Ity_F64);
130224aa412af1d8166cc11f39a6e721df49431d23618sewardj
130234aa412af1d8166cc11f39a6e721df49431d23618sewardj   if (opc1 != 0x3C) {
130244aa412af1d8166cc11f39a6e721df49431d23618sewardj      vex_printf( "dis_vxv_dp_arith(ppc)(instr)\n" );
130254aa412af1d8166cc11f39a6e721df49431d23618sewardj      return False;
130264aa412af1d8166cc11f39a6e721df49431d23618sewardj   }
130274aa412af1d8166cc11f39a6e721df49431d23618sewardj
130284aa412af1d8166cc11f39a6e721df49431d23618sewardj   assign(frA,  unop(Iop_ReinterpI64asF64, unop(Iop_V128HIto64, getVSReg( XA ))));
130294aa412af1d8166cc11f39a6e721df49431d23618sewardj   assign(frB,  unop(Iop_ReinterpI64asF64, unop(Iop_V128HIto64, getVSReg( XB ))));
130304aa412af1d8166cc11f39a6e721df49431d23618sewardj   assign(frA2, unop(Iop_ReinterpI64asF64, unop(Iop_V128to64, getVSReg( XA ))));
130314aa412af1d8166cc11f39a6e721df49431d23618sewardj   assign(frB2, unop(Iop_ReinterpI64asF64, unop(Iop_V128to64, getVSReg( XB ))));
130324aa412af1d8166cc11f39a6e721df49431d23618sewardj
130334aa412af1d8166cc11f39a6e721df49431d23618sewardj   switch (opc2) {
130344aa412af1d8166cc11f39a6e721df49431d23618sewardj      case 0x1E0: // xvdivdp (VSX Vector Divide Double-Precision)
130354aa412af1d8166cc11f39a6e721df49431d23618sewardj      case 0x1C0: // xvmuldp (VSX Vector Multiply Double-Precision)
130364aa412af1d8166cc11f39a6e721df49431d23618sewardj      case 0x180: // xvadddp (VSX Vector Add Double-Precision)
130374aa412af1d8166cc11f39a6e721df49431d23618sewardj      case 0x1A0: // xvsubdp (VSX Vector Subtract Double-Precision)
130384aa412af1d8166cc11f39a6e721df49431d23618sewardj      {
130394aa412af1d8166cc11f39a6e721df49431d23618sewardj         IROp mOp;
1304055085f8680acc89d727e321f3b34cae1a8c4093aflorian         const HChar * oper_name;
130414aa412af1d8166cc11f39a6e721df49431d23618sewardj         switch (opc2) {
130424aa412af1d8166cc11f39a6e721df49431d23618sewardj            case 0x1E0:
130434aa412af1d8166cc11f39a6e721df49431d23618sewardj               mOp = Iop_DivF64;
130444aa412af1d8166cc11f39a6e721df49431d23618sewardj               oper_name = "div";
130454aa412af1d8166cc11f39a6e721df49431d23618sewardj               break;
130464aa412af1d8166cc11f39a6e721df49431d23618sewardj            case 0x1C0:
130474aa412af1d8166cc11f39a6e721df49431d23618sewardj               mOp = Iop_MulF64;
130484aa412af1d8166cc11f39a6e721df49431d23618sewardj               oper_name = "mul";
130494aa412af1d8166cc11f39a6e721df49431d23618sewardj               break;
130504aa412af1d8166cc11f39a6e721df49431d23618sewardj            case 0x180:
130514aa412af1d8166cc11f39a6e721df49431d23618sewardj               mOp = Iop_AddF64;
130524aa412af1d8166cc11f39a6e721df49431d23618sewardj               oper_name = "add";
130534aa412af1d8166cc11f39a6e721df49431d23618sewardj               break;
130544aa412af1d8166cc11f39a6e721df49431d23618sewardj            case 0x1A0:
130554aa412af1d8166cc11f39a6e721df49431d23618sewardj               mOp = Iop_SubF64;
130564aa412af1d8166cc11f39a6e721df49431d23618sewardj               oper_name = "sub";
130574aa412af1d8166cc11f39a6e721df49431d23618sewardj               break;
130584aa412af1d8166cc11f39a6e721df49431d23618sewardj
130594aa412af1d8166cc11f39a6e721df49431d23618sewardj            default:
130604aa412af1d8166cc11f39a6e721df49431d23618sewardj               vpanic("The impossible happened: dis_vxv_dp_arith(ppc)");
130614aa412af1d8166cc11f39a6e721df49431d23618sewardj         }
130624aa412af1d8166cc11f39a6e721df49431d23618sewardj         IRTemp hiResult = newTemp(Ity_I64);
130634aa412af1d8166cc11f39a6e721df49431d23618sewardj         IRTemp loResult = newTemp(Ity_I64);
130644aa412af1d8166cc11f39a6e721df49431d23618sewardj         DIP("xv%sdp v%d,v%d,v%d\n", oper_name, (UInt)XT, (UInt)XA, (UInt)XB);
130654aa412af1d8166cc11f39a6e721df49431d23618sewardj
130664aa412af1d8166cc11f39a6e721df49431d23618sewardj         assign( hiResult,
130674aa412af1d8166cc11f39a6e721df49431d23618sewardj                 unop( Iop_ReinterpF64asI64,
130684aa412af1d8166cc11f39a6e721df49431d23618sewardj                       triop( mOp, rm, mkexpr( frA ), mkexpr( frB ) ) ) );
130694aa412af1d8166cc11f39a6e721df49431d23618sewardj         assign( loResult,
130704aa412af1d8166cc11f39a6e721df49431d23618sewardj                 unop( Iop_ReinterpF64asI64,
130714aa412af1d8166cc11f39a6e721df49431d23618sewardj                       triop( mOp, rm, mkexpr( frA2 ), mkexpr( frB2 ) ) ) );
130724aa412af1d8166cc11f39a6e721df49431d23618sewardj         putVSReg( XT,
130734aa412af1d8166cc11f39a6e721df49431d23618sewardj                   binop( Iop_64HLtoV128, mkexpr( hiResult ), mkexpr( loResult ) ) );
130744aa412af1d8166cc11f39a6e721df49431d23618sewardj         break;
130754aa412af1d8166cc11f39a6e721df49431d23618sewardj      }
13076e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj      case 0x196: // xvsqrtdp
13077e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj      {
13078e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj         IRTemp hiResult = newTemp(Ity_I64);
13079e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj         IRTemp loResult = newTemp(Ity_I64);
13080e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj         DIP("xvsqrtdp v%d,v%d\n", (UInt)XT, (UInt)XB);
130814aa412af1d8166cc11f39a6e721df49431d23618sewardj
13082e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj         assign( hiResult,
13083e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj                 unop( Iop_ReinterpF64asI64,
13084e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj                       binop( Iop_SqrtF64, rm, mkexpr( frB ) ) ) );
13085e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj         assign( loResult,
13086e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj                 unop( Iop_ReinterpF64asI64,
13087e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj                       binop( Iop_SqrtF64, rm, mkexpr( frB2 ) ) ) );
13088e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj         putVSReg( XT,
13089e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj                   binop( Iop_64HLtoV128, mkexpr( hiResult ), mkexpr( loResult ) ) );
13090e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj         break;
13091e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj      }
130924aa412af1d8166cc11f39a6e721df49431d23618sewardj      case 0x184: case 0x1A4: // xvmaddadp, xvmaddmdp (VSX Vector Multiply-Add Double-Precision)
130934aa412af1d8166cc11f39a6e721df49431d23618sewardj      case 0x1C4: case 0x1E4: // xvmsubadp, xvmsubmdp (VSX Vector Multiply-Subtract Double-Precision)
130944aa412af1d8166cc11f39a6e721df49431d23618sewardj      case 0x384: case 0x3A4: // xvnmaddadp, xvnmaddmdp (VSX Vector Negate Multiply-Add Double-Precision)
130954aa412af1d8166cc11f39a6e721df49431d23618sewardj      case 0x3C4: case 0x3E4: // xvnmsubadp, xvnmsubmdp (VSX Vector Negate Multiply-Subtract Double-Precision)
130964aa412af1d8166cc11f39a6e721df49431d23618sewardj      {
130974aa412af1d8166cc11f39a6e721df49431d23618sewardj         /* xvm{add|sub}mdp XT,XA,XB is element-wise equivalent to fm{add|sub} FRT,FRA,FRC,FRB with . . .
130984aa412af1d8166cc11f39a6e721df49431d23618sewardj          *    XT == FRC
130994aa412af1d8166cc11f39a6e721df49431d23618sewardj          *    XA == FRA
131004aa412af1d8166cc11f39a6e721df49431d23618sewardj          *    XB == FRB
131014aa412af1d8166cc11f39a6e721df49431d23618sewardj          *
131024aa412af1d8166cc11f39a6e721df49431d23618sewardj          * and for xvm{add|sub}adp . . .
131034aa412af1d8166cc11f39a6e721df49431d23618sewardj          *    XT == FRB
131044aa412af1d8166cc11f39a6e721df49431d23618sewardj          *    XA == FRA
131054aa412af1d8166cc11f39a6e721df49431d23618sewardj          *    XB == FRC
131064aa412af1d8166cc11f39a6e721df49431d23618sewardj          */
131074aa412af1d8166cc11f39a6e721df49431d23618sewardj         Bool negate;
131084aa412af1d8166cc11f39a6e721df49431d23618sewardj         IROp mOp = Iop_INVALID;
1310955085f8680acc89d727e321f3b34cae1a8c4093aflorian         const HChar * oper_name = NULL;
131104aa412af1d8166cc11f39a6e721df49431d23618sewardj         Bool mdp = False;
131114aa412af1d8166cc11f39a6e721df49431d23618sewardj
131124aa412af1d8166cc11f39a6e721df49431d23618sewardj         switch (opc2) {
131134aa412af1d8166cc11f39a6e721df49431d23618sewardj            case 0x184: case 0x1A4:
131144aa412af1d8166cc11f39a6e721df49431d23618sewardj            case 0x384: case 0x3A4:
131154aa412af1d8166cc11f39a6e721df49431d23618sewardj               mOp = Iop_MAddF64;
131164aa412af1d8166cc11f39a6e721df49431d23618sewardj               oper_name = "add";
131174aa412af1d8166cc11f39a6e721df49431d23618sewardj               mdp = (opc2 & 0x0FF) == 0x0A4;
131184aa412af1d8166cc11f39a6e721df49431d23618sewardj               break;
131194aa412af1d8166cc11f39a6e721df49431d23618sewardj
131204aa412af1d8166cc11f39a6e721df49431d23618sewardj            case 0x1C4: case 0x1E4:
131214aa412af1d8166cc11f39a6e721df49431d23618sewardj            case 0x3C4: case 0x3E4:
131224aa412af1d8166cc11f39a6e721df49431d23618sewardj               mOp = Iop_MSubF64;
131234aa412af1d8166cc11f39a6e721df49431d23618sewardj               oper_name = "sub";
131244aa412af1d8166cc11f39a6e721df49431d23618sewardj               mdp = (opc2 & 0x0FF) == 0x0E4;
131254aa412af1d8166cc11f39a6e721df49431d23618sewardj               break;
131264aa412af1d8166cc11f39a6e721df49431d23618sewardj
131274aa412af1d8166cc11f39a6e721df49431d23618sewardj            default:
131284aa412af1d8166cc11f39a6e721df49431d23618sewardj               vpanic("The impossible happened: dis_vxv_sp_arith(ppc)");
131294aa412af1d8166cc11f39a6e721df49431d23618sewardj         }
131304aa412af1d8166cc11f39a6e721df49431d23618sewardj
131314aa412af1d8166cc11f39a6e721df49431d23618sewardj         switch (opc2) {
131324aa412af1d8166cc11f39a6e721df49431d23618sewardj            case 0x384: case 0x3A4:
131334aa412af1d8166cc11f39a6e721df49431d23618sewardj            case 0x3C4: case 0x3E4:
131344aa412af1d8166cc11f39a6e721df49431d23618sewardj               negate = True;
131354aa412af1d8166cc11f39a6e721df49431d23618sewardj               break;
131364aa412af1d8166cc11f39a6e721df49431d23618sewardj            default:
131374aa412af1d8166cc11f39a6e721df49431d23618sewardj               negate = False;
131384aa412af1d8166cc11f39a6e721df49431d23618sewardj         }
131394aa412af1d8166cc11f39a6e721df49431d23618sewardj         IRTemp hiResult = newTemp(Ity_I64);
131404aa412af1d8166cc11f39a6e721df49431d23618sewardj         IRTemp loResult = newTemp(Ity_I64);
131414aa412af1d8166cc11f39a6e721df49431d23618sewardj         IRTemp frT = newTemp(Ity_F64);
131424aa412af1d8166cc11f39a6e721df49431d23618sewardj         IRTemp frT2 = newTemp(Ity_F64);
131434aa412af1d8166cc11f39a6e721df49431d23618sewardj         DIP("xv%sm%s%s v%d,v%d,v%d\n", negate ? "n" : "", oper_name, mdp ? "mdp" : "adp",
131444aa412af1d8166cc11f39a6e721df49431d23618sewardj             (UInt)XT, (UInt)XA, (UInt)XB);
131454aa412af1d8166cc11f39a6e721df49431d23618sewardj         assign(frT,  unop(Iop_ReinterpI64asF64, unop(Iop_V128HIto64, getVSReg( XT ) ) ) );
131464aa412af1d8166cc11f39a6e721df49431d23618sewardj         assign(frT2, unop(Iop_ReinterpI64asF64, unop(Iop_V128to64, getVSReg( XT ) ) ) );
131474aa412af1d8166cc11f39a6e721df49431d23618sewardj
131484aa412af1d8166cc11f39a6e721df49431d23618sewardj         assign( hiResult,
131494aa412af1d8166cc11f39a6e721df49431d23618sewardj                 unop( Iop_ReinterpF64asI64,
131504aa412af1d8166cc11f39a6e721df49431d23618sewardj                       qop( mOp,
131514aa412af1d8166cc11f39a6e721df49431d23618sewardj                            rm,
131524aa412af1d8166cc11f39a6e721df49431d23618sewardj                            mkexpr( frA ),
131534aa412af1d8166cc11f39a6e721df49431d23618sewardj                            mkexpr( mdp ? frT : frB ),
131544aa412af1d8166cc11f39a6e721df49431d23618sewardj                            mkexpr( mdp ? frB : frT ) ) ) );
131554aa412af1d8166cc11f39a6e721df49431d23618sewardj         assign( loResult,
131564aa412af1d8166cc11f39a6e721df49431d23618sewardj                 unop( Iop_ReinterpF64asI64,
131574aa412af1d8166cc11f39a6e721df49431d23618sewardj                       qop( mOp,
131584aa412af1d8166cc11f39a6e721df49431d23618sewardj                            rm,
131594aa412af1d8166cc11f39a6e721df49431d23618sewardj                            mkexpr( frA2 ),
131604aa412af1d8166cc11f39a6e721df49431d23618sewardj                            mkexpr( mdp ? frT2 : frB2 ),
131614aa412af1d8166cc11f39a6e721df49431d23618sewardj                            mkexpr( mdp ? frB2 : frT2 ) ) ) );
131624aa412af1d8166cc11f39a6e721df49431d23618sewardj         putVSReg( XT,
131634aa412af1d8166cc11f39a6e721df49431d23618sewardj                   binop( Iop_64HLtoV128,
131644aa412af1d8166cc11f39a6e721df49431d23618sewardj                          mkexpr( negate ? getNegatedResult( hiResult )
131654aa412af1d8166cc11f39a6e721df49431d23618sewardj                                         : hiResult ),
131664aa412af1d8166cc11f39a6e721df49431d23618sewardj                          mkexpr( negate ? getNegatedResult( loResult )
131674aa412af1d8166cc11f39a6e721df49431d23618sewardj                                         : loResult ) ) );
131684aa412af1d8166cc11f39a6e721df49431d23618sewardj         break;
131694aa412af1d8166cc11f39a6e721df49431d23618sewardj      }
13170e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj      case 0x1D4: // xvtsqrtdp (VSX Vector Test for software Square Root Double-Precision)
13171e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj      {
13172e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj         IRTemp frBHi_I64 = newTemp(Ity_I64);
13173e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj         IRTemp frBLo_I64 = newTemp(Ity_I64);
13174e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj         IRTemp flagsHi = newTemp(Ity_I32);
13175e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj         IRTemp flagsLo = newTemp(Ity_I32);
13176e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj         UChar crfD     = toUChar( IFIELD( theInstr, 23, 3 ) );
13177e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj         IRTemp  fe_flagHi, fg_flagHi, fe_flagLo, fg_flagLo;
13178e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj         fe_flagHi = fg_flagHi = fe_flagLo = fg_flagLo = IRTemp_INVALID;
13179e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj
13180e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj         DIP("xvtsqrtdp cr%d,v%d\n", (UInt)crfD, (UInt)XB);
13181e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj         assign( frBHi_I64, unop(Iop_V128HIto64, getVSReg( XB )) );
13182e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj         assign( frBLo_I64, unop(Iop_V128to64, getVSReg( XB )) );
13183e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj         do_fp_tsqrt(frBHi_I64, False /*not single precision*/, &fe_flagHi, &fg_flagHi);
13184e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj         do_fp_tsqrt(frBLo_I64, False /*not single precision*/, &fe_flagLo, &fg_flagLo);
13185e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj         /* The CR field consists of fl_flag || fg_flag || fe_flag || 0b0
13186e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj          * where fl_flag == 1 on ppc64.
13187e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj          */
13188e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj         assign( flagsHi,
13189e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj                 binop( Iop_Or32,
13190e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj                        binop( Iop_Or32, mkU32( 8 ), // fl_flag
13191e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj                               binop( Iop_Shl32, mkexpr(fg_flagHi), mkU8( 2 ) ) ),
13192e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj                        binop( Iop_Shl32, mkexpr(fe_flagHi), mkU8( 1 ) ) ) );
13193e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj         assign( flagsLo,
13194e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj                 binop( Iop_Or32,
13195e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj                        binop( Iop_Or32, mkU32( 8 ), // fl_flag
13196e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj                               binop( Iop_Shl32, mkexpr(fg_flagLo), mkU8( 2 ) ) ),
13197e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj                        binop( Iop_Shl32, mkexpr(fe_flagLo), mkU8( 1 ) ) ) );
13198e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj         putGST_field( PPC_GST_CR,
13199e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj                       binop( Iop_Or32, mkexpr( flagsHi ), mkexpr( flagsLo ) ),
13200e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj                       crfD );
13201e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj         break;
13202e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj      }
13203e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj      case 0x1F4: // xvtdivdp (VSX Vector Test for software Divide Double-Precision)
13204e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj      {
13205e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj         IRTemp frBHi_I64 = newTemp(Ity_I64);
13206e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj         IRTemp frBLo_I64 = newTemp(Ity_I64);
13207e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj         IRTemp frAHi_I64 = newTemp(Ity_I64);
13208e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj         IRTemp frALo_I64 = newTemp(Ity_I64);
13209e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj         IRTemp flagsHi = newTemp(Ity_I32);
13210e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj         IRTemp flagsLo = newTemp(Ity_I32);
13211e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj         UChar crfD     = toUChar( IFIELD( theInstr, 23, 3 ) );
13212e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj         IRTemp  fe_flagHi, fg_flagHi, fe_flagLo, fg_flagLo;
13213e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj         fe_flagHi = fg_flagHi = fe_flagLo = fg_flagLo = IRTemp_INVALID;
13214e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj
13215e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj         DIP("xvtdivdp cr%d,v%d,v%d\n", (UInt)crfD, (UInt)XA, (UInt)XB);
13216e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj         assign( frAHi_I64, unop(Iop_V128HIto64, getVSReg( XA )) );
13217e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj         assign( frALo_I64, unop(Iop_V128to64, getVSReg( XA )) );
13218e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj         assign( frBHi_I64, unop(Iop_V128HIto64, getVSReg( XB )) );
13219e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj         assign( frBLo_I64, unop(Iop_V128to64, getVSReg( XB )) );
13220e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj
13221e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj         _do_fp_tdiv(frAHi_I64, frBHi_I64, False/*dp*/, &fe_flagHi, &fg_flagHi);
13222e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj         _do_fp_tdiv(frALo_I64, frBLo_I64, False/*dp*/, &fe_flagLo, &fg_flagLo);
13223e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj         /* The CR field consists of fl_flag || fg_flag || fe_flag || 0b0
13224e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj          * where fl_flag == 1 on ppc64.
13225e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj          */
13226e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj         assign( flagsHi,
13227e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj                 binop( Iop_Or32,
13228e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj                        binop( Iop_Or32, mkU32( 8 ), // fl_flag
13229e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj                               binop( Iop_Shl32, mkexpr(fg_flagHi), mkU8( 2 ) ) ),
13230e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj                        binop( Iop_Shl32, mkexpr(fe_flagHi), mkU8( 1 ) ) ) );
13231e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj         assign( flagsLo,
13232e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj                 binop( Iop_Or32,
13233e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj                        binop( Iop_Or32, mkU32( 8 ), // fl_flag
13234e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj                               binop( Iop_Shl32, mkexpr(fg_flagLo), mkU8( 2 ) ) ),
13235e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj                        binop( Iop_Shl32, mkexpr(fe_flagLo), mkU8( 1 ) ) ) );
13236e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj         putGST_field( PPC_GST_CR,
13237e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj                       binop( Iop_Or32, mkexpr( flagsHi ), mkexpr( flagsLo ) ),
13238e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj                       crfD );
13239e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj         break;
13240e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj      }
132414aa412af1d8166cc11f39a6e721df49431d23618sewardj
132424aa412af1d8166cc11f39a6e721df49431d23618sewardj      default:
132434aa412af1d8166cc11f39a6e721df49431d23618sewardj         vex_printf( "dis_vxv_dp_arith(ppc)(opc2)\n" );
132444aa412af1d8166cc11f39a6e721df49431d23618sewardj         return False;
132454aa412af1d8166cc11f39a6e721df49431d23618sewardj   }
132464aa412af1d8166cc11f39a6e721df49431d23618sewardj   return True;
132474aa412af1d8166cc11f39a6e721df49431d23618sewardj}
132484aa412af1d8166cc11f39a6e721df49431d23618sewardj
132494aa412af1d8166cc11f39a6e721df49431d23618sewardj/*
132504aa412af1d8166cc11f39a6e721df49431d23618sewardj * VSX vector Single Precision Floating Point Arithmetic Instructions
132514aa412af1d8166cc11f39a6e721df49431d23618sewardj */
132524aa412af1d8166cc11f39a6e721df49431d23618sewardjstatic Bool
132534aa412af1d8166cc11f39a6e721df49431d23618sewardjdis_vxv_sp_arith ( UInt theInstr, UInt opc2 )
132544aa412af1d8166cc11f39a6e721df49431d23618sewardj{
132554aa412af1d8166cc11f39a6e721df49431d23618sewardj   /* XX3-Form */
132564aa412af1d8166cc11f39a6e721df49431d23618sewardj   UChar opc1 = ifieldOPC( theInstr );
132574aa412af1d8166cc11f39a6e721df49431d23618sewardj   UChar XT = ifieldRegXT( theInstr );
132584aa412af1d8166cc11f39a6e721df49431d23618sewardj   UChar XA = ifieldRegXA( theInstr );
132594aa412af1d8166cc11f39a6e721df49431d23618sewardj   UChar XB = ifieldRegXB( theInstr );
132604aa412af1d8166cc11f39a6e721df49431d23618sewardj   IRExpr* rm = get_IR_roundingmode();
132614aa412af1d8166cc11f39a6e721df49431d23618sewardj   IRTemp a3, a2, a1, a0;
132624aa412af1d8166cc11f39a6e721df49431d23618sewardj   IRTemp b3, b2, b1, b0;
132634aa412af1d8166cc11f39a6e721df49431d23618sewardj   IRTemp res0 = newTemp(Ity_I32);
132644aa412af1d8166cc11f39a6e721df49431d23618sewardj   IRTemp res1 = newTemp(Ity_I32);
132654aa412af1d8166cc11f39a6e721df49431d23618sewardj   IRTemp res2 = newTemp(Ity_I32);
132664aa412af1d8166cc11f39a6e721df49431d23618sewardj   IRTemp res3 = newTemp(Ity_I32);
132674aa412af1d8166cc11f39a6e721df49431d23618sewardj
132684aa412af1d8166cc11f39a6e721df49431d23618sewardj   a3 = a2 = a1 = a0 = IRTemp_INVALID;
132694aa412af1d8166cc11f39a6e721df49431d23618sewardj   b3 = b2 = b1 = b0 = IRTemp_INVALID;
132704aa412af1d8166cc11f39a6e721df49431d23618sewardj
132714aa412af1d8166cc11f39a6e721df49431d23618sewardj   if (opc1 != 0x3C) {
132724aa412af1d8166cc11f39a6e721df49431d23618sewardj      vex_printf( "dis_vxv_sp_arith(ppc)(instr)\n" );
132734aa412af1d8166cc11f39a6e721df49431d23618sewardj      return False;
132744aa412af1d8166cc11f39a6e721df49431d23618sewardj   }
132754aa412af1d8166cc11f39a6e721df49431d23618sewardj
132764aa412af1d8166cc11f39a6e721df49431d23618sewardj   switch (opc2) {
132774aa412af1d8166cc11f39a6e721df49431d23618sewardj      case 0x100: // xvaddsp (VSX Vector Add Single-Precision)
132784aa412af1d8166cc11f39a6e721df49431d23618sewardj         DIP("xvaddsp v%d,v%d,v%d\n", (UInt)XT, (UInt)XA, (UInt)XB);
1327920a760ec66a13a93147a40d3c3530be21d7fe411sewardj         // WARNING: BOGUS! The backend ignores rm on Iop_Add32Fx4
1328020a760ec66a13a93147a40d3c3530be21d7fe411sewardj         putVSReg( XT, triop(Iop_Add32Fx4, rm,
1328120a760ec66a13a93147a40d3c3530be21d7fe411sewardj                             getVSReg( XA ), getVSReg( XB )) );
132824aa412af1d8166cc11f39a6e721df49431d23618sewardj         break;
132834aa412af1d8166cc11f39a6e721df49431d23618sewardj
132844aa412af1d8166cc11f39a6e721df49431d23618sewardj      case 0x140: // xvmulsp (VSX Vector Multiply Single-Precision)
132854aa412af1d8166cc11f39a6e721df49431d23618sewardj         DIP("xvmulsp v%d,v%d,v%d\n", (UInt)XT, (UInt)XA, (UInt)XB);
1328620a760ec66a13a93147a40d3c3530be21d7fe411sewardj         // WARNING: BOGUS! The backend ignores rm on Iop_Mul32Fx4
1328720a760ec66a13a93147a40d3c3530be21d7fe411sewardj         putVSReg( XT, triop(Iop_Mul32Fx4, rm,
1328820a760ec66a13a93147a40d3c3530be21d7fe411sewardj                             getVSReg( XA ), getVSReg( XB )) );
132894aa412af1d8166cc11f39a6e721df49431d23618sewardj         break;
132904aa412af1d8166cc11f39a6e721df49431d23618sewardj
132914aa412af1d8166cc11f39a6e721df49431d23618sewardj      case 0x120: // xvsubsp (VSX Vector Subtract Single-Precision)
132924aa412af1d8166cc11f39a6e721df49431d23618sewardj         DIP("xvsubsp v%d,v%d,v%d\n", (UInt)XT, (UInt)XA, (UInt)XB);
1329320a760ec66a13a93147a40d3c3530be21d7fe411sewardj         // WARNING: BOGUS! The backend ignores rm on Iop_Sub32Fx4
1329420a760ec66a13a93147a40d3c3530be21d7fe411sewardj         putVSReg( XT, triop(Iop_Sub32Fx4, rm,
1329520a760ec66a13a93147a40d3c3530be21d7fe411sewardj                             getVSReg( XA ), getVSReg( XB )) );
132964aa412af1d8166cc11f39a6e721df49431d23618sewardj         break;
132974aa412af1d8166cc11f39a6e721df49431d23618sewardj
132984aa412af1d8166cc11f39a6e721df49431d23618sewardj      case 0x160: // xvdivsp (VSX Vector Divide Single-Precision)
132994aa412af1d8166cc11f39a6e721df49431d23618sewardj      {
133004aa412af1d8166cc11f39a6e721df49431d23618sewardj         /* Iop_Div32Fx4 is not implemented for ppc64 (in host_ppc_{isel|defs}.c.
133014aa412af1d8166cc11f39a6e721df49431d23618sewardj          * So there are two choices:
133024aa412af1d8166cc11f39a6e721df49431d23618sewardj          *   1. Implement the xvdivsp with a native insn; or
133034aa412af1d8166cc11f39a6e721df49431d23618sewardj          *   2. Extract the 4 single precision floats from each vector
133044aa412af1d8166cc11f39a6e721df49431d23618sewardj          *      register inputs and perform fdivs on each pair
133054aa412af1d8166cc11f39a6e721df49431d23618sewardj          * I will do the latter, due to the general philosophy of
133064aa412af1d8166cc11f39a6e721df49431d23618sewardj          * reusing existing implementations when practical.
133074aa412af1d8166cc11f39a6e721df49431d23618sewardj          */
133084aa412af1d8166cc11f39a6e721df49431d23618sewardj         DIP("xvdivsp v%d,v%d,v%d\n", (UInt)XT, (UInt)XA, (UInt)XB);
133094aa412af1d8166cc11f39a6e721df49431d23618sewardj         breakV128to4xF64( getVSReg( XA ), &a3, &a2, &a1, &a0 );
133104aa412af1d8166cc11f39a6e721df49431d23618sewardj         breakV128to4xF64( getVSReg( XB ), &b3, &b2, &b1, &b0 );
133114aa412af1d8166cc11f39a6e721df49431d23618sewardj
133124aa412af1d8166cc11f39a6e721df49431d23618sewardj         assign( res0,
133134aa412af1d8166cc11f39a6e721df49431d23618sewardj              unop( Iop_ReinterpF32asI32,
133144aa412af1d8166cc11f39a6e721df49431d23618sewardj                    unop( Iop_TruncF64asF32,
133154aa412af1d8166cc11f39a6e721df49431d23618sewardj                          triop( Iop_DivF64r32, rm, mkexpr( a0 ), mkexpr( b0 ) ) ) ) );
133164aa412af1d8166cc11f39a6e721df49431d23618sewardj         assign( res1,
133174aa412af1d8166cc11f39a6e721df49431d23618sewardj                 unop( Iop_ReinterpF32asI32,
133184aa412af1d8166cc11f39a6e721df49431d23618sewardj                       unop( Iop_TruncF64asF32,
133194aa412af1d8166cc11f39a6e721df49431d23618sewardj                             triop( Iop_DivF64r32, rm, mkexpr( a1 ), mkexpr( b1 ) ) ) ) );
133204aa412af1d8166cc11f39a6e721df49431d23618sewardj         assign( res2,
133214aa412af1d8166cc11f39a6e721df49431d23618sewardj                 unop( Iop_ReinterpF32asI32,
133224aa412af1d8166cc11f39a6e721df49431d23618sewardj                       unop( Iop_TruncF64asF32,
133234aa412af1d8166cc11f39a6e721df49431d23618sewardj                             triop( Iop_DivF64r32, rm, mkexpr( a2 ), mkexpr( b2 ) ) ) ) );
133244aa412af1d8166cc11f39a6e721df49431d23618sewardj         assign( res3,
133254aa412af1d8166cc11f39a6e721df49431d23618sewardj                 unop( Iop_ReinterpF32asI32,
133264aa412af1d8166cc11f39a6e721df49431d23618sewardj                       unop( Iop_TruncF64asF32,
133274aa412af1d8166cc11f39a6e721df49431d23618sewardj                             triop( Iop_DivF64r32, rm, mkexpr( a3 ), mkexpr( b3 ) ) ) ) );
133284aa412af1d8166cc11f39a6e721df49431d23618sewardj
133294aa412af1d8166cc11f39a6e721df49431d23618sewardj         putVSReg( XT,
133304aa412af1d8166cc11f39a6e721df49431d23618sewardj                   binop( Iop_64HLtoV128,
133314aa412af1d8166cc11f39a6e721df49431d23618sewardj                          binop( Iop_32HLto64, mkexpr( res3 ), mkexpr( res2 ) ),
133324aa412af1d8166cc11f39a6e721df49431d23618sewardj                          binop( Iop_32HLto64, mkexpr( res1 ), mkexpr( res0 ) ) ) );
133334aa412af1d8166cc11f39a6e721df49431d23618sewardj         break;
133344aa412af1d8166cc11f39a6e721df49431d23618sewardj      }
13335e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj      case 0x116: // xvsqrtsp (VSX Vector Square Root Single-Precision)
13336e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj      {
13337e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj         DIP("xvsqrtsp v%d,v%d\n", (UInt)XT, (UInt)XB);
13338e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj         breakV128to4xF64( getVSReg( XB ), &b3, &b2, &b1, &b0 );
13339e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj         /* Note: The native xvsqrtsp insruction does not always give the same precision
13340e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj          * as what we get with Iop_SqrtF64.  But it doesn't seem worthwhile to implement
13341e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj          * an Iop_SqrtF32 that would give us a lower precision result, albeit more true
13342e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj          * to the actual instruction.
13343e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj          */
13344e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj
13345e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj         assign( res0,
13346e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj                 unop( Iop_ReinterpF32asI32,
13347e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj                       unop( Iop_TruncF64asF32,
13348e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj                             binop(Iop_SqrtF64, rm, mkexpr( b0 ) ) ) ) );
13349e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj         assign( res1,
13350e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj                 unop( Iop_ReinterpF32asI32,
13351e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj                       unop( Iop_TruncF64asF32,
13352e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj                             binop(Iop_SqrtF64, rm, mkexpr( b1 ) ) ) ) );
13353e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj         assign( res2,
13354e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj                 unop( Iop_ReinterpF32asI32,
13355e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj                       unop( Iop_TruncF64asF32,
13356e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj                             binop(Iop_SqrtF64, rm, mkexpr( b2) ) ) ) );
13357e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj         assign( res3,
13358e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj                 unop( Iop_ReinterpF32asI32,
13359e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj                       unop( Iop_TruncF64asF32,
13360e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj                             binop(Iop_SqrtF64, rm, mkexpr( b3 ) ) ) ) );
13361e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj
13362e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj         putVSReg( XT,
13363e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj                   binop( Iop_64HLtoV128,
13364e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj                          binop( Iop_32HLto64, mkexpr( res3 ), mkexpr( res2 ) ),
13365e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj                          binop( Iop_32HLto64, mkexpr( res1 ), mkexpr( res0 ) ) ) );
13366e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj         break;
13367e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj      }
133684aa412af1d8166cc11f39a6e721df49431d23618sewardj
133694aa412af1d8166cc11f39a6e721df49431d23618sewardj      case 0x104: case 0x124: // xvmaddasp, xvmaddmsp (VSX Vector Multiply-Add Single-Precision)
133704aa412af1d8166cc11f39a6e721df49431d23618sewardj      case 0x144: case 0x164: // xvmsubasp, xvmsubmsp (VSX Vector Multiply-Subtract Single-Precision)
133714aa412af1d8166cc11f39a6e721df49431d23618sewardj      case 0x304: case 0x324: // xvnmaddasp, xvnmaddmsp (VSX Vector Negate Multiply-Add Single-Precision)
133724aa412af1d8166cc11f39a6e721df49431d23618sewardj      case 0x344: case 0x364: // xvnmsubasp, xvnmsubmsp (VSX Vector Negate Multiply-Subtract Single-Precision)
133734aa412af1d8166cc11f39a6e721df49431d23618sewardj      {
133744aa412af1d8166cc11f39a6e721df49431d23618sewardj         IRTemp t3, t2, t1, t0;
133754aa412af1d8166cc11f39a6e721df49431d23618sewardj         Bool msp = False;
133764aa412af1d8166cc11f39a6e721df49431d23618sewardj         Bool negate;
1337755085f8680acc89d727e321f3b34cae1a8c4093aflorian         const HChar * oper_name = NULL;
133784aa412af1d8166cc11f39a6e721df49431d23618sewardj         IROp mOp = Iop_INVALID;
133794aa412af1d8166cc11f39a6e721df49431d23618sewardj         switch (opc2) {
133804aa412af1d8166cc11f39a6e721df49431d23618sewardj            case 0x104: case 0x124:
133814aa412af1d8166cc11f39a6e721df49431d23618sewardj            case 0x304: case 0x324:
133824aa412af1d8166cc11f39a6e721df49431d23618sewardj               msp = (opc2 & 0x0FF) == 0x024;
133834aa412af1d8166cc11f39a6e721df49431d23618sewardj               mOp = Iop_MAddF64r32;
133844aa412af1d8166cc11f39a6e721df49431d23618sewardj               oper_name = "madd";
133854aa412af1d8166cc11f39a6e721df49431d23618sewardj               break;
133864aa412af1d8166cc11f39a6e721df49431d23618sewardj
133874aa412af1d8166cc11f39a6e721df49431d23618sewardj            case 0x144: case 0x164:
133884aa412af1d8166cc11f39a6e721df49431d23618sewardj            case 0x344: case 0x364:
133894aa412af1d8166cc11f39a6e721df49431d23618sewardj               msp = (opc2 & 0x0FF) == 0x064;
133904aa412af1d8166cc11f39a6e721df49431d23618sewardj               mOp = Iop_MSubF64r32;
133914aa412af1d8166cc11f39a6e721df49431d23618sewardj               oper_name = "sub";
133924aa412af1d8166cc11f39a6e721df49431d23618sewardj               break;
133934aa412af1d8166cc11f39a6e721df49431d23618sewardj
133944aa412af1d8166cc11f39a6e721df49431d23618sewardj            default:
133954aa412af1d8166cc11f39a6e721df49431d23618sewardj               vpanic("The impossible happened: dis_vxv_sp_arith(ppc)");
133964aa412af1d8166cc11f39a6e721df49431d23618sewardj         }
133974aa412af1d8166cc11f39a6e721df49431d23618sewardj
133984aa412af1d8166cc11f39a6e721df49431d23618sewardj         switch (opc2) {
133994aa412af1d8166cc11f39a6e721df49431d23618sewardj            case 0x304: case 0x324:
134004aa412af1d8166cc11f39a6e721df49431d23618sewardj            case 0x344: case 0x364:
134014aa412af1d8166cc11f39a6e721df49431d23618sewardj               negate = True;
134024aa412af1d8166cc11f39a6e721df49431d23618sewardj               break;
134034aa412af1d8166cc11f39a6e721df49431d23618sewardj
134044aa412af1d8166cc11f39a6e721df49431d23618sewardj            default:
134054aa412af1d8166cc11f39a6e721df49431d23618sewardj               negate = False;
134064aa412af1d8166cc11f39a6e721df49431d23618sewardj         }
134074aa412af1d8166cc11f39a6e721df49431d23618sewardj
134084aa412af1d8166cc11f39a6e721df49431d23618sewardj         DIP("xv%sm%s%s v%d,v%d,v%d\n", negate ? "n" : "", oper_name, msp ? "msp" : "asp",
134094aa412af1d8166cc11f39a6e721df49431d23618sewardj             (UInt)XT, (UInt)XA, (UInt)XB);
134104aa412af1d8166cc11f39a6e721df49431d23618sewardj
134114aa412af1d8166cc11f39a6e721df49431d23618sewardj         t3 = t2 = t1 = t0 = IRTemp_INVALID;
134124aa412af1d8166cc11f39a6e721df49431d23618sewardj         breakV128to4xF64( getVSReg( XA ), &a3, &a2, &a1, &a0 );
134134aa412af1d8166cc11f39a6e721df49431d23618sewardj         breakV128to4xF64( getVSReg( XB ), &b3, &b2, &b1, &b0 );
134144aa412af1d8166cc11f39a6e721df49431d23618sewardj         breakV128to4xF64( getVSReg( XT ), &t3, &t2, &t1, &t0 );
134154aa412af1d8166cc11f39a6e721df49431d23618sewardj
134164aa412af1d8166cc11f39a6e721df49431d23618sewardj         assign( res0,
134174aa412af1d8166cc11f39a6e721df49431d23618sewardj                 unop( Iop_ReinterpF32asI32,
134184aa412af1d8166cc11f39a6e721df49431d23618sewardj                       unop( Iop_TruncF64asF32,
134194aa412af1d8166cc11f39a6e721df49431d23618sewardj                             qop( mOp,
134204aa412af1d8166cc11f39a6e721df49431d23618sewardj                                  rm,
134214aa412af1d8166cc11f39a6e721df49431d23618sewardj                                  mkexpr( a0 ),
134224aa412af1d8166cc11f39a6e721df49431d23618sewardj                                  mkexpr( msp ? t0 : b0 ),
134234aa412af1d8166cc11f39a6e721df49431d23618sewardj                                  mkexpr( msp ? b0 : t0 ) ) ) ) );
134244aa412af1d8166cc11f39a6e721df49431d23618sewardj         assign( res1,
134254aa412af1d8166cc11f39a6e721df49431d23618sewardj                 unop( Iop_ReinterpF32asI32,
134264aa412af1d8166cc11f39a6e721df49431d23618sewardj                       unop( Iop_TruncF64asF32,
134274aa412af1d8166cc11f39a6e721df49431d23618sewardj                             qop( mOp,
134284aa412af1d8166cc11f39a6e721df49431d23618sewardj                                  rm,
134294aa412af1d8166cc11f39a6e721df49431d23618sewardj                                  mkexpr( a1 ),
134304aa412af1d8166cc11f39a6e721df49431d23618sewardj                                  mkexpr( msp ? t1 : b1 ),
134314aa412af1d8166cc11f39a6e721df49431d23618sewardj                                  mkexpr( msp ? b1 : t1 ) ) ) ) );
134324aa412af1d8166cc11f39a6e721df49431d23618sewardj         assign( res2,
134334aa412af1d8166cc11f39a6e721df49431d23618sewardj                 unop( Iop_ReinterpF32asI32,
134344aa412af1d8166cc11f39a6e721df49431d23618sewardj                       unop( Iop_TruncF64asF32,
134354aa412af1d8166cc11f39a6e721df49431d23618sewardj                             qop( mOp,
134364aa412af1d8166cc11f39a6e721df49431d23618sewardj                                  rm,
134374aa412af1d8166cc11f39a6e721df49431d23618sewardj                                  mkexpr( a2 ),
134384aa412af1d8166cc11f39a6e721df49431d23618sewardj                                  mkexpr( msp ? t2 : b2 ),
134394aa412af1d8166cc11f39a6e721df49431d23618sewardj                                  mkexpr( msp ? b2 : t2 ) ) ) ) );
134404aa412af1d8166cc11f39a6e721df49431d23618sewardj         assign( res3,
134414aa412af1d8166cc11f39a6e721df49431d23618sewardj                 unop( Iop_ReinterpF32asI32,
134424aa412af1d8166cc11f39a6e721df49431d23618sewardj                       unop( Iop_TruncF64asF32,
134434aa412af1d8166cc11f39a6e721df49431d23618sewardj                             qop( mOp,
134444aa412af1d8166cc11f39a6e721df49431d23618sewardj                                  rm,
134454aa412af1d8166cc11f39a6e721df49431d23618sewardj                                  mkexpr( a3 ),
134464aa412af1d8166cc11f39a6e721df49431d23618sewardj                                  mkexpr( msp ? t3 : b3 ),
134474aa412af1d8166cc11f39a6e721df49431d23618sewardj                                  mkexpr( msp ? b3 : t3 ) ) ) ) );
134484aa412af1d8166cc11f39a6e721df49431d23618sewardj
134494aa412af1d8166cc11f39a6e721df49431d23618sewardj         putVSReg( XT,
134504aa412af1d8166cc11f39a6e721df49431d23618sewardj                   binop( Iop_64HLtoV128,
134514aa412af1d8166cc11f39a6e721df49431d23618sewardj                          binop( Iop_32HLto64, mkexpr( negate ? getNegatedResult_32( res3 ) : res3 ),
134524aa412af1d8166cc11f39a6e721df49431d23618sewardj                                 mkexpr( negate ? getNegatedResult_32( res2 ) : res2 ) ),
134534aa412af1d8166cc11f39a6e721df49431d23618sewardj                          binop( Iop_32HLto64, mkexpr( negate ? getNegatedResult_32( res1 ) : res1 ),
134544aa412af1d8166cc11f39a6e721df49431d23618sewardj                                 mkexpr( negate ? getNegatedResult_32( res0 ) : res0 ) ) ) );
134554aa412af1d8166cc11f39a6e721df49431d23618sewardj
134564aa412af1d8166cc11f39a6e721df49431d23618sewardj         break;
134574aa412af1d8166cc11f39a6e721df49431d23618sewardj      }
13458e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj      case 0x154: // xvtsqrtsp (VSX Vector Test for software Square Root Single-Precision)
13459e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj      {
13460e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj         IRTemp flags0 = newTemp(Ity_I32);
13461e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj         IRTemp flags1 = newTemp(Ity_I32);
13462e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj         IRTemp flags2 = newTemp(Ity_I32);
13463e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj         IRTemp flags3 = newTemp(Ity_I32);
13464e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj         UChar crfD     = toUChar( IFIELD( theInstr, 23, 3 ) );
13465e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj         IRTemp  fe_flag0, fg_flag0, fe_flag1, fg_flag1;
13466e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj         IRTemp  fe_flag2, fg_flag2, fe_flag3, fg_flag3;
13467e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj         fe_flag0 = fg_flag0 = fe_flag1 = fg_flag1 = IRTemp_INVALID;
13468e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj         fe_flag2 = fg_flag2 = fe_flag3 = fg_flag3 = IRTemp_INVALID;
13469e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj         DIP("xvtsqrtsp cr%d,v%d\n", (UInt)crfD, (UInt)XB);
13470e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj
13471e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj         breakV128to4x32( getVSReg( XB ), &b3, &b2, &b1, &b0 );
13472e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj         do_fp_tsqrt(b0, True /* single precision*/, &fe_flag0, &fg_flag0);
13473e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj         do_fp_tsqrt(b1, True /* single precision*/, &fe_flag1, &fg_flag1);
13474e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj         do_fp_tsqrt(b2, True /* single precision*/, &fe_flag2, &fg_flag2);
13475e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj         do_fp_tsqrt(b3, True /* single precision*/, &fe_flag3, &fg_flag3);
13476e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj
13477e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj         /* The CR field consists of fl_flag || fg_flag || fe_flag || 0b0
13478e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj          * where fl_flag == 1 on ppc64.
13479e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj          */
13480e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj         assign( flags0,
13481e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj                 binop( Iop_Or32,
13482e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj                        binop( Iop_Or32, mkU32( 8 ), // fl_flag
13483e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj                               binop( Iop_Shl32, mkexpr(fg_flag0), mkU8( 2 ) ) ),
13484e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj                        binop( Iop_Shl32, mkexpr(fe_flag0), mkU8( 1 ) ) ) );
13485e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj         assign( flags1,
13486e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj                 binop( Iop_Or32,
13487e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj                        binop( Iop_Or32, mkU32( 8 ), // fl_flag
13488e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj                               binop( Iop_Shl32, mkexpr(fg_flag1), mkU8( 2 ) ) ),
13489e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj                        binop( Iop_Shl32, mkexpr(fe_flag1), mkU8( 1 ) ) ) );
13490e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj         assign( flags2,
13491e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj                 binop( Iop_Or32,
13492e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj                        binop( Iop_Or32, mkU32( 8 ), // fl_flag
13493e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj                               binop( Iop_Shl32, mkexpr(fg_flag2), mkU8( 2 ) ) ),
13494e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj                        binop( Iop_Shl32, mkexpr(fe_flag2), mkU8( 1 ) ) ) );
13495e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj         assign( flags3,
13496e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj                 binop( Iop_Or32,
13497e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj                        binop( Iop_Or32, mkU32( 8 ), // fl_flag
13498e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj                               binop( Iop_Shl32, mkexpr(fg_flag3), mkU8( 2 ) ) ),
13499e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj                        binop( Iop_Shl32, mkexpr(fe_flag3), mkU8( 1 ) ) ) );
13500e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj         putGST_field( PPC_GST_CR,
13501e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj                       binop( Iop_Or32,
13502e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj                              mkexpr( flags0 ),
13503e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj                              binop( Iop_Or32,
13504e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj                                     mkexpr( flags1 ),
13505e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj                                     binop( Iop_Or32,
13506e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj                                            mkexpr( flags2 ),
13507e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj                                            mkexpr( flags3 ) ) ) ),
13508e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj                       crfD );
13509e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj
13510e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj         break;
13511e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj      }
13512e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj      case 0x174: // xvtdivsp (VSX Vector Test for software Divide Single-Precision)
13513e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj      {
13514e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj         IRTemp flags0 = newTemp(Ity_I32);
13515e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj         IRTemp flags1 = newTemp(Ity_I32);
13516e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj         IRTemp flags2 = newTemp(Ity_I32);
13517e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj         IRTemp flags3 = newTemp(Ity_I32);
13518e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj         UChar crfD     = toUChar( IFIELD( theInstr, 23, 3 ) );
13519e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj         IRTemp  fe_flag0, fg_flag0, fe_flag1, fg_flag1;
13520e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj         IRTemp  fe_flag2, fg_flag2, fe_flag3, fg_flag3;
13521e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj         fe_flag0 = fg_flag0 = fe_flag1 = fg_flag1 = IRTemp_INVALID;
13522e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj         fe_flag2 = fg_flag2 = fe_flag3 = fg_flag3 = IRTemp_INVALID;
13523e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj         DIP("xvtdivsp cr%d,v%d,v%d\n", (UInt)crfD, (UInt)XA, (UInt)XB);
13524e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj
13525e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj         breakV128to4x32( getVSReg( XA ), &a3, &a2, &a1, &a0 );
13526e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj         breakV128to4x32( getVSReg( XB ), &b3, &b2, &b1, &b0 );
13527e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj         _do_fp_tdiv(a0, b0, True /* single precision*/, &fe_flag0, &fg_flag0);
13528e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj         _do_fp_tdiv(a1, b1, True /* single precision*/, &fe_flag1, &fg_flag1);
13529e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj         _do_fp_tdiv(a2, b2, True /* single precision*/, &fe_flag2, &fg_flag2);
13530e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj         _do_fp_tdiv(a3, b3, True /* single precision*/, &fe_flag3, &fg_flag3);
13531e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj
13532e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj         /* The CR field consists of fl_flag || fg_flag || fe_flag || 0b0
13533e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj          * where fl_flag == 1 on ppc64.
13534e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj          */
13535e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj         assign( flags0,
13536e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj                 binop( Iop_Or32,
13537e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj                        binop( Iop_Or32, mkU32( 8 ), // fl_flag
13538e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj                               binop( Iop_Shl32, mkexpr(fg_flag0), mkU8( 2 ) ) ),
13539e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj                        binop( Iop_Shl32, mkexpr(fe_flag0), mkU8( 1 ) ) ) );
13540e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj         assign( flags1,
13541e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj                 binop( Iop_Or32,
13542e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj                        binop( Iop_Or32, mkU32( 8 ), // fl_flag
13543e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj                               binop( Iop_Shl32, mkexpr(fg_flag1), mkU8( 2 ) ) ),
13544e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj                        binop( Iop_Shl32, mkexpr(fe_flag1), mkU8( 1 ) ) ) );
13545e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj         assign( flags2,
13546e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj                 binop( Iop_Or32,
13547e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj                        binop( Iop_Or32, mkU32( 8 ), // fl_flag
13548e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj                               binop( Iop_Shl32, mkexpr(fg_flag2), mkU8( 2 ) ) ),
13549e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj                        binop( Iop_Shl32, mkexpr(fe_flag2), mkU8( 1 ) ) ) );
13550e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj         assign( flags3,
13551e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj                 binop( Iop_Or32,
13552e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj                        binop( Iop_Or32, mkU32( 8 ), // fl_flag
13553e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj                               binop( Iop_Shl32, mkexpr(fg_flag3), mkU8( 2 ) ) ),
13554e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj                        binop( Iop_Shl32, mkexpr(fe_flag3), mkU8( 1 ) ) ) );
13555e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj         putGST_field( PPC_GST_CR,
13556e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj                       binop( Iop_Or32,
13557e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj                              mkexpr( flags0 ),
13558e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj                              binop( Iop_Or32,
13559e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj                                     mkexpr( flags1 ),
13560e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj                                     binop( Iop_Or32,
13561e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj                                            mkexpr( flags2 ),
13562e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj                                            mkexpr( flags3 ) ) ) ),
13563e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj                       crfD );
13564e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj
13565e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj         break;
13566e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj      }
135674aa412af1d8166cc11f39a6e721df49431d23618sewardj
135684aa412af1d8166cc11f39a6e721df49431d23618sewardj      default:
135694aa412af1d8166cc11f39a6e721df49431d23618sewardj         vex_printf( "dis_vxv_sp_arith(ppc)(opc2)\n" );
135704aa412af1d8166cc11f39a6e721df49431d23618sewardj         return False;
135714aa412af1d8166cc11f39a6e721df49431d23618sewardj   }
135724aa412af1d8166cc11f39a6e721df49431d23618sewardj   return True;
135734aa412af1d8166cc11f39a6e721df49431d23618sewardj}
135744aa412af1d8166cc11f39a6e721df49431d23618sewardj
135757deaf9552b546b847528cf39b38898fb7742b5f5carll/*
1357660c6bac19ffe055cabab554e7877d73096a8bf17carll * Vector Population Count/bit matrix transpose
135777deaf9552b546b847528cf39b38898fb7742b5f5carll */
135787deaf9552b546b847528cf39b38898fb7742b5f5carllstatic Bool
1357960c6bac19ffe055cabab554e7877d73096a8bf17carlldis_av_count_bitTranspose ( UInt theInstr, UInt opc2 )
135807deaf9552b546b847528cf39b38898fb7742b5f5carll{
135817deaf9552b546b847528cf39b38898fb7742b5f5carll   UChar vRB_addr = ifieldRegB(theInstr);
135827deaf9552b546b847528cf39b38898fb7742b5f5carll   UChar vRT_addr = ifieldRegDS(theInstr);
135837deaf9552b546b847528cf39b38898fb7742b5f5carll   UChar opc1 = ifieldOPC( theInstr );
135847deaf9552b546b847528cf39b38898fb7742b5f5carll   IRTemp vB = newTemp(Ity_V128);
135857deaf9552b546b847528cf39b38898fb7742b5f5carll   assign( vB, getVReg(vRB_addr));
135867deaf9552b546b847528cf39b38898fb7742b5f5carll
135877deaf9552b546b847528cf39b38898fb7742b5f5carll   if (opc1 != 0x4) {
1358860c6bac19ffe055cabab554e7877d73096a8bf17carll      vex_printf( "dis_av_count_bitTranspose(ppc)(instr)\n" );
135897deaf9552b546b847528cf39b38898fb7742b5f5carll      return False;
135907deaf9552b546b847528cf39b38898fb7742b5f5carll   }
135917deaf9552b546b847528cf39b38898fb7742b5f5carll
135927deaf9552b546b847528cf39b38898fb7742b5f5carll   switch (opc2) {
135937deaf9552b546b847528cf39b38898fb7742b5f5carll      case 0x702:    // vclzb
135947deaf9552b546b847528cf39b38898fb7742b5f5carll         DIP("vclzb v%d,v%d\n", vRT_addr, vRB_addr);
13595a8c7b0f2ac208ed08763d0873131962a65669d58sewardj         putVReg( vRT_addr, unop(Iop_Clz8x16, mkexpr( vB ) ) );
135967deaf9552b546b847528cf39b38898fb7742b5f5carll         break;
135977deaf9552b546b847528cf39b38898fb7742b5f5carll
135987deaf9552b546b847528cf39b38898fb7742b5f5carll      case 0x742:    // vclzh
135997deaf9552b546b847528cf39b38898fb7742b5f5carll         DIP("vclzh v%d,v%d\n", vRT_addr, vRB_addr);
13600a8c7b0f2ac208ed08763d0873131962a65669d58sewardj         putVReg( vRT_addr, unop(Iop_Clz16x8, mkexpr( vB ) ) );
136017deaf9552b546b847528cf39b38898fb7742b5f5carll         break;
136027deaf9552b546b847528cf39b38898fb7742b5f5carll
136037deaf9552b546b847528cf39b38898fb7742b5f5carll      case 0x782:    // vclzw
136047deaf9552b546b847528cf39b38898fb7742b5f5carll         DIP("vclzw v%d,v%d\n", vRT_addr, vRB_addr);
13605a8c7b0f2ac208ed08763d0873131962a65669d58sewardj         putVReg( vRT_addr, unop(Iop_Clz32x4, mkexpr( vB ) ) );
136067deaf9552b546b847528cf39b38898fb7742b5f5carll         break;
136077deaf9552b546b847528cf39b38898fb7742b5f5carll
136087deaf9552b546b847528cf39b38898fb7742b5f5carll      case 0x7C2:    // vclzd
136097deaf9552b546b847528cf39b38898fb7742b5f5carll         DIP("vclzd v%d,v%d\n", vRT_addr, vRB_addr);
136107deaf9552b546b847528cf39b38898fb7742b5f5carll         putVReg( vRT_addr, unop(Iop_Clz64x2, mkexpr( vB ) ) );
136117deaf9552b546b847528cf39b38898fb7742b5f5carll         break;
136127deaf9552b546b847528cf39b38898fb7742b5f5carll
136137deaf9552b546b847528cf39b38898fb7742b5f5carll      case 0x703:    // vpopcntb
136147deaf9552b546b847528cf39b38898fb7742b5f5carll      {
136157deaf9552b546b847528cf39b38898fb7742b5f5carll         /* Break vector into 32-bit words and do the population count
136167deaf9552b546b847528cf39b38898fb7742b5f5carll          * on byte in the words
136177deaf9552b546b847528cf39b38898fb7742b5f5carll          */
136187deaf9552b546b847528cf39b38898fb7742b5f5carll         IRType ty = Ity_I32;
136197deaf9552b546b847528cf39b38898fb7742b5f5carll         IRTemp bits0_31, bits32_63, bits64_95, bits96_127;
136207deaf9552b546b847528cf39b38898fb7742b5f5carll         bits0_31 = bits32_63 = bits64_95 = bits96_127 = IRTemp_INVALID;
136217deaf9552b546b847528cf39b38898fb7742b5f5carll         IRTemp cnt_bits0_31, cnt_bits32_63, cnt_bits64_95, cnt_bits96_127;
136227deaf9552b546b847528cf39b38898fb7742b5f5carll         cnt_bits0_31 = cnt_bits32_63 = cnt_bits64_95 = cnt_bits96_127 = IRTemp_INVALID;
136237deaf9552b546b847528cf39b38898fb7742b5f5carll
136247deaf9552b546b847528cf39b38898fb7742b5f5carll         DIP("vpopcntb v%d,v%d\n", vRT_addr, vRB_addr);
136257deaf9552b546b847528cf39b38898fb7742b5f5carll         breakV128to4x32(mkexpr( vB), &bits96_127, &bits64_95, &bits32_63, &bits0_31 );
136267deaf9552b546b847528cf39b38898fb7742b5f5carll         cnt_bits0_31   = gen_POPCOUNT(ty, bits0_31,   BYTE);
136277deaf9552b546b847528cf39b38898fb7742b5f5carll         cnt_bits32_63  = gen_POPCOUNT(ty, bits32_63,  BYTE);
136287deaf9552b546b847528cf39b38898fb7742b5f5carll         cnt_bits64_95  = gen_POPCOUNT(ty, bits64_95,  BYTE);
136297deaf9552b546b847528cf39b38898fb7742b5f5carll         cnt_bits96_127 = gen_POPCOUNT(ty, bits96_127, BYTE);
136307deaf9552b546b847528cf39b38898fb7742b5f5carll
136317deaf9552b546b847528cf39b38898fb7742b5f5carll         putVReg( vRT_addr, mkV128from32(cnt_bits96_127, cnt_bits64_95,
136327deaf9552b546b847528cf39b38898fb7742b5f5carll                                         cnt_bits32_63, cnt_bits0_31) );
136337deaf9552b546b847528cf39b38898fb7742b5f5carll         break;
136347deaf9552b546b847528cf39b38898fb7742b5f5carll      }
136357deaf9552b546b847528cf39b38898fb7742b5f5carll
136367deaf9552b546b847528cf39b38898fb7742b5f5carll      case 0x743:    // vpopcnth
136377deaf9552b546b847528cf39b38898fb7742b5f5carll      {
136387deaf9552b546b847528cf39b38898fb7742b5f5carll         /* Break vector into 32-bit words and do the population count
136397deaf9552b546b847528cf39b38898fb7742b5f5carll          * for each half word
136407deaf9552b546b847528cf39b38898fb7742b5f5carll          */
136417deaf9552b546b847528cf39b38898fb7742b5f5carll         IRType ty = Ity_I32;
136427deaf9552b546b847528cf39b38898fb7742b5f5carll         IRTemp bits0_31, bits32_63, bits64_95, bits96_127;
136437deaf9552b546b847528cf39b38898fb7742b5f5carll         bits0_31 = bits32_63 = bits64_95 = bits96_127 = IRTemp_INVALID;
136447deaf9552b546b847528cf39b38898fb7742b5f5carll         IRTemp cnt_bits0_31, cnt_bits32_63, cnt_bits64_95, cnt_bits96_127;
136457deaf9552b546b847528cf39b38898fb7742b5f5carll         cnt_bits0_31 = cnt_bits32_63 = cnt_bits64_95 = cnt_bits96_127 = IRTemp_INVALID;
136467deaf9552b546b847528cf39b38898fb7742b5f5carll
136477deaf9552b546b847528cf39b38898fb7742b5f5carll         DIP("vpopcnth v%d,v%d\n", vRT_addr, vRB_addr);
136487deaf9552b546b847528cf39b38898fb7742b5f5carll         breakV128to4x32(mkexpr( vB), &bits96_127, &bits64_95, &bits32_63, &bits0_31 );
136497deaf9552b546b847528cf39b38898fb7742b5f5carll
136507deaf9552b546b847528cf39b38898fb7742b5f5carll         cnt_bits0_31   = gen_POPCOUNT(ty, bits0_31,   HWORD);
136517deaf9552b546b847528cf39b38898fb7742b5f5carll         cnt_bits32_63  = gen_POPCOUNT(ty, bits32_63,  HWORD);
136527deaf9552b546b847528cf39b38898fb7742b5f5carll         cnt_bits64_95  = gen_POPCOUNT(ty, bits64_95,  HWORD);
136537deaf9552b546b847528cf39b38898fb7742b5f5carll         cnt_bits96_127 = gen_POPCOUNT(ty, bits96_127, HWORD);
136547deaf9552b546b847528cf39b38898fb7742b5f5carll
136557deaf9552b546b847528cf39b38898fb7742b5f5carll         putVReg( vRT_addr, mkV128from32(cnt_bits96_127, cnt_bits64_95,
136567deaf9552b546b847528cf39b38898fb7742b5f5carll                                         cnt_bits32_63, cnt_bits0_31) );
136577deaf9552b546b847528cf39b38898fb7742b5f5carll         break;
136587deaf9552b546b847528cf39b38898fb7742b5f5carll      }
136597deaf9552b546b847528cf39b38898fb7742b5f5carll
136607deaf9552b546b847528cf39b38898fb7742b5f5carll      case 0x783:    // vpopcntw
136617deaf9552b546b847528cf39b38898fb7742b5f5carll      {
136627deaf9552b546b847528cf39b38898fb7742b5f5carll         /* Break vector into 32-bit words and do the population count
136637deaf9552b546b847528cf39b38898fb7742b5f5carll          * on each word.
136647deaf9552b546b847528cf39b38898fb7742b5f5carll          */
136657deaf9552b546b847528cf39b38898fb7742b5f5carll         IRType ty = Ity_I32;
136667deaf9552b546b847528cf39b38898fb7742b5f5carll         IRTemp bits0_31, bits32_63, bits64_95, bits96_127;
136677deaf9552b546b847528cf39b38898fb7742b5f5carll         bits0_31 = bits32_63 = bits64_95 = bits96_127 = IRTemp_INVALID;
136687deaf9552b546b847528cf39b38898fb7742b5f5carll         IRTemp cnt_bits0_31, cnt_bits32_63, cnt_bits64_95, cnt_bits96_127;
136697deaf9552b546b847528cf39b38898fb7742b5f5carll         cnt_bits0_31 = cnt_bits32_63 = cnt_bits64_95 = cnt_bits96_127 = IRTemp_INVALID;
136707deaf9552b546b847528cf39b38898fb7742b5f5carll
136717deaf9552b546b847528cf39b38898fb7742b5f5carll         DIP("vpopcntw v%d,v%d\n", vRT_addr, vRB_addr);
136727deaf9552b546b847528cf39b38898fb7742b5f5carll         breakV128to4x32(mkexpr( vB), &bits96_127, &bits64_95, &bits32_63, &bits0_31 );
136737deaf9552b546b847528cf39b38898fb7742b5f5carll
136747deaf9552b546b847528cf39b38898fb7742b5f5carll         cnt_bits0_31   = gen_POPCOUNT(ty, bits0_31,   WORD);
136757deaf9552b546b847528cf39b38898fb7742b5f5carll         cnt_bits32_63  = gen_POPCOUNT(ty, bits32_63,  WORD);
136767deaf9552b546b847528cf39b38898fb7742b5f5carll         cnt_bits64_95  = gen_POPCOUNT(ty, bits64_95,  WORD);
136777deaf9552b546b847528cf39b38898fb7742b5f5carll         cnt_bits96_127 = gen_POPCOUNT(ty, bits96_127, WORD);
136787deaf9552b546b847528cf39b38898fb7742b5f5carll
136797deaf9552b546b847528cf39b38898fb7742b5f5carll         putVReg( vRT_addr, mkV128from32(cnt_bits96_127, cnt_bits64_95,
136807deaf9552b546b847528cf39b38898fb7742b5f5carll                                         cnt_bits32_63, cnt_bits0_31) );
136817deaf9552b546b847528cf39b38898fb7742b5f5carll         break;
136827deaf9552b546b847528cf39b38898fb7742b5f5carll      }
136837deaf9552b546b847528cf39b38898fb7742b5f5carll
136847deaf9552b546b847528cf39b38898fb7742b5f5carll      case 0x7C3:    // vpopcntd
136857deaf9552b546b847528cf39b38898fb7742b5f5carll      {
136867deaf9552b546b847528cf39b38898fb7742b5f5carll         if (mode64) {
136877deaf9552b546b847528cf39b38898fb7742b5f5carll            /* Break vector into 64-bit double words and do the population count
136887deaf9552b546b847528cf39b38898fb7742b5f5carll             * on each double word.
136897deaf9552b546b847528cf39b38898fb7742b5f5carll             */
136907deaf9552b546b847528cf39b38898fb7742b5f5carll            IRType ty = Ity_I64;
136917deaf9552b546b847528cf39b38898fb7742b5f5carll            IRTemp bits0_63   = newTemp(Ity_I64);
136927deaf9552b546b847528cf39b38898fb7742b5f5carll            IRTemp bits64_127 = newTemp(Ity_I64);
136937deaf9552b546b847528cf39b38898fb7742b5f5carll            IRTemp cnt_bits0_63   = newTemp(Ity_I64);
136947deaf9552b546b847528cf39b38898fb7742b5f5carll            IRTemp cnt_bits64_127 = newTemp(Ity_I64);
136957deaf9552b546b847528cf39b38898fb7742b5f5carll
136967deaf9552b546b847528cf39b38898fb7742b5f5carll            DIP("vpopcntd v%d,v%d\n", vRT_addr, vRB_addr);
136977deaf9552b546b847528cf39b38898fb7742b5f5carll
136987deaf9552b546b847528cf39b38898fb7742b5f5carll            assign(bits0_63,   unop( Iop_V128to64,   mkexpr( vB ) ) );
136997deaf9552b546b847528cf39b38898fb7742b5f5carll            assign(bits64_127, unop( Iop_V128HIto64, mkexpr( vB ) ) );
137007deaf9552b546b847528cf39b38898fb7742b5f5carll            cnt_bits0_63   = gen_POPCOUNT(ty, bits0_63,   DWORD);
137017deaf9552b546b847528cf39b38898fb7742b5f5carll            cnt_bits64_127 = gen_POPCOUNT(ty, bits64_127, DWORD);
137027deaf9552b546b847528cf39b38898fb7742b5f5carll
137037deaf9552b546b847528cf39b38898fb7742b5f5carll            putVReg( vRT_addr, binop( Iop_64HLtoV128,
137047deaf9552b546b847528cf39b38898fb7742b5f5carll                                      mkexpr( cnt_bits64_127 ),
137057deaf9552b546b847528cf39b38898fb7742b5f5carll                                      mkexpr( cnt_bits0_63 ) ) );
137067deaf9552b546b847528cf39b38898fb7742b5f5carll         } else {
137077deaf9552b546b847528cf39b38898fb7742b5f5carll            /* Break vector into 32-bit words and do the population count
137087deaf9552b546b847528cf39b38898fb7742b5f5carll             * on each doubleword.
137097deaf9552b546b847528cf39b38898fb7742b5f5carll             */
137107deaf9552b546b847528cf39b38898fb7742b5f5carll            IRTemp bits0_31, bits32_63, bits64_95, bits96_127;
137117deaf9552b546b847528cf39b38898fb7742b5f5carll            bits0_31 = bits32_63 = bits64_95 = bits96_127 = IRTemp_INVALID;
137127deaf9552b546b847528cf39b38898fb7742b5f5carll            IRTemp cnt_bits0_63   = newTemp(Ity_I64);
137137deaf9552b546b847528cf39b38898fb7742b5f5carll            IRTemp cnt_bits64_127  = newTemp(Ity_I64);
137147deaf9552b546b847528cf39b38898fb7742b5f5carll
137157deaf9552b546b847528cf39b38898fb7742b5f5carll            DIP("vpopcntd v%d,v%d\n", vRT_addr, vRB_addr);
137167deaf9552b546b847528cf39b38898fb7742b5f5carll            breakV128to4x32(mkexpr( vB), &bits96_127, &bits64_95, &bits32_63, &bits0_31 );
137177deaf9552b546b847528cf39b38898fb7742b5f5carll
137187deaf9552b546b847528cf39b38898fb7742b5f5carll            cnt_bits0_63   = gen_vpopcntd_mode32(bits0_31, bits32_63);
137197deaf9552b546b847528cf39b38898fb7742b5f5carll            cnt_bits64_127 = gen_vpopcntd_mode32(bits64_95, bits96_127);
137207deaf9552b546b847528cf39b38898fb7742b5f5carll
137217deaf9552b546b847528cf39b38898fb7742b5f5carll            putVReg( vRT_addr, binop( Iop_64HLtoV128,
137227deaf9552b546b847528cf39b38898fb7742b5f5carll                                      mkexpr( cnt_bits64_127 ),
137237deaf9552b546b847528cf39b38898fb7742b5f5carll                                      mkexpr( cnt_bits0_63 ) ) );
137247deaf9552b546b847528cf39b38898fb7742b5f5carll         }
137257deaf9552b546b847528cf39b38898fb7742b5f5carll         break;
137267deaf9552b546b847528cf39b38898fb7742b5f5carll      }
137277deaf9552b546b847528cf39b38898fb7742b5f5carll
1372860c6bac19ffe055cabab554e7877d73096a8bf17carll      case 0x50C:  // vgbbd Vector Gather Bits by Bytes by Doubleword
1372960c6bac19ffe055cabab554e7877d73096a8bf17carll         DIP("vgbbd v%d,v%d\n", vRT_addr, vRB_addr);
1373060c6bac19ffe055cabab554e7877d73096a8bf17carll         putVReg( vRT_addr, unop( Iop_PwBitMtxXpose64x2, mkexpr( vB ) ) );
1373160c6bac19ffe055cabab554e7877d73096a8bf17carll         break;
1373260c6bac19ffe055cabab554e7877d73096a8bf17carll
137337deaf9552b546b847528cf39b38898fb7742b5f5carll      default:
1373460c6bac19ffe055cabab554e7877d73096a8bf17carll         vex_printf("dis_av_count_bitTranspose(ppc)(opc2)\n");
137357deaf9552b546b847528cf39b38898fb7742b5f5carll         return False;
137367deaf9552b546b847528cf39b38898fb7742b5f5carll      break;
137377deaf9552b546b847528cf39b38898fb7742b5f5carll   }
137387deaf9552b546b847528cf39b38898fb7742b5f5carll   return True;
137397deaf9552b546b847528cf39b38898fb7742b5f5carll}
137407deaf9552b546b847528cf39b38898fb7742b5f5carll
137414aa412af1d8166cc11f39a6e721df49431d23618sewardjtypedef enum {
137424aa412af1d8166cc11f39a6e721df49431d23618sewardj   PPC_CMP_EQ = 2,
137434aa412af1d8166cc11f39a6e721df49431d23618sewardj   PPC_CMP_GT = 4,
137444aa412af1d8166cc11f39a6e721df49431d23618sewardj   PPC_CMP_GE = 6,
137454aa412af1d8166cc11f39a6e721df49431d23618sewardj   PPC_CMP_LT = 8
137464aa412af1d8166cc11f39a6e721df49431d23618sewardj} ppc_cmp_t;
137474aa412af1d8166cc11f39a6e721df49431d23618sewardj
137484aa412af1d8166cc11f39a6e721df49431d23618sewardj
137494aa412af1d8166cc11f39a6e721df49431d23618sewardj/*
137504aa412af1d8166cc11f39a6e721df49431d23618sewardj  This helper function takes as input the IRExpr returned
137514aa412af1d8166cc11f39a6e721df49431d23618sewardj  from a binop( Iop_CmpF64, fpA, fpB), whose result is returned
137524aa412af1d8166cc11f39a6e721df49431d23618sewardj  in IR form.  This helper function converts it to PPC form.
137534aa412af1d8166cc11f39a6e721df49431d23618sewardj
137544aa412af1d8166cc11f39a6e721df49431d23618sewardj  Map compare result from IR to PPC
137554aa412af1d8166cc11f39a6e721df49431d23618sewardj
137564aa412af1d8166cc11f39a6e721df49431d23618sewardj  FP cmp result | PPC | IR
137574aa412af1d8166cc11f39a6e721df49431d23618sewardj  --------------------------
137584aa412af1d8166cc11f39a6e721df49431d23618sewardj  UN            | 0x1 | 0x45
137594aa412af1d8166cc11f39a6e721df49431d23618sewardj  EQ            | 0x2 | 0x40
137604aa412af1d8166cc11f39a6e721df49431d23618sewardj  GT            | 0x4 | 0x00
137614aa412af1d8166cc11f39a6e721df49431d23618sewardj  LT            | 0x8 | 0x01
137624aa412af1d8166cc11f39a6e721df49431d23618sewardj
137634aa412af1d8166cc11f39a6e721df49431d23618sewardj condcode = Shl(1, (~(ccIR>>5) & 2)
137644aa412af1d8166cc11f39a6e721df49431d23618sewardj                    | ((ccIR ^ (ccIR>>6)) & 1)
137654aa412af1d8166cc11f39a6e721df49431d23618sewardj*/
137664aa412af1d8166cc11f39a6e721df49431d23618sewardjstatic IRTemp
137674aa412af1d8166cc11f39a6e721df49431d23618sewardjget_fp_cmp_CR_val (IRExpr * ccIR_expr)
137684aa412af1d8166cc11f39a6e721df49431d23618sewardj{
137694aa412af1d8166cc11f39a6e721df49431d23618sewardj   IRTemp condcode = newTemp( Ity_I32 );
137704aa412af1d8166cc11f39a6e721df49431d23618sewardj   IRTemp ccIR = newTemp( Ity_I32 );
137714aa412af1d8166cc11f39a6e721df49431d23618sewardj
137724aa412af1d8166cc11f39a6e721df49431d23618sewardj   assign(ccIR, ccIR_expr);
137734aa412af1d8166cc11f39a6e721df49431d23618sewardj   assign( condcode,
137744aa412af1d8166cc11f39a6e721df49431d23618sewardj           binop( Iop_Shl32,
137754aa412af1d8166cc11f39a6e721df49431d23618sewardj                  mkU32( 1 ),
137764aa412af1d8166cc11f39a6e721df49431d23618sewardj                  unop( Iop_32to8,
137774aa412af1d8166cc11f39a6e721df49431d23618sewardj                        binop( Iop_Or32,
137784aa412af1d8166cc11f39a6e721df49431d23618sewardj                               binop( Iop_And32,
137794aa412af1d8166cc11f39a6e721df49431d23618sewardj                                      unop( Iop_Not32,
137804aa412af1d8166cc11f39a6e721df49431d23618sewardj                                            binop( Iop_Shr32,
137814aa412af1d8166cc11f39a6e721df49431d23618sewardj                                                   mkexpr( ccIR ),
137824aa412af1d8166cc11f39a6e721df49431d23618sewardj                                                   mkU8( 5 ) ) ),
137834aa412af1d8166cc11f39a6e721df49431d23618sewardj                                      mkU32( 2 ) ),
137844aa412af1d8166cc11f39a6e721df49431d23618sewardj                               binop( Iop_And32,
137854aa412af1d8166cc11f39a6e721df49431d23618sewardj                                      binop( Iop_Xor32,
137864aa412af1d8166cc11f39a6e721df49431d23618sewardj                                             mkexpr( ccIR ),
137874aa412af1d8166cc11f39a6e721df49431d23618sewardj                                             binop( Iop_Shr32,
137884aa412af1d8166cc11f39a6e721df49431d23618sewardj                                                    mkexpr( ccIR ),
137894aa412af1d8166cc11f39a6e721df49431d23618sewardj                                                    mkU8( 6 ) ) ),
137904aa412af1d8166cc11f39a6e721df49431d23618sewardj                                      mkU32( 1 ) ) ) ) ) );
137914aa412af1d8166cc11f39a6e721df49431d23618sewardj   return condcode;
137924aa412af1d8166cc11f39a6e721df49431d23618sewardj}
137934aa412af1d8166cc11f39a6e721df49431d23618sewardj
137944aa412af1d8166cc11f39a6e721df49431d23618sewardj/*
137954aa412af1d8166cc11f39a6e721df49431d23618sewardj * Helper function for get_max_min_fp for ascertaining the max or min between two doubles
137964aa412af1d8166cc11f39a6e721df49431d23618sewardj * following these special rules:
137974aa412af1d8166cc11f39a6e721df49431d23618sewardj *   - The max/min of a QNaN and any value is that value
137984aa412af1d8166cc11f39a6e721df49431d23618sewardj *     (When two QNaNs are being compared, the frA QNaN is the return value.)
137994aa412af1d8166cc11f39a6e721df49431d23618sewardj *   - The max/min of any value and an SNaN is that SNaN converted to a QNaN
138004aa412af1d8166cc11f39a6e721df49431d23618sewardj *     (When two SNaNs are being compared, the frA SNaN is converted to a QNaN.)
138014aa412af1d8166cc11f39a6e721df49431d23618sewardj */
138024aa412af1d8166cc11f39a6e721df49431d23618sewardjstatic IRExpr * _get_maxmin_fp_NaN(IRTemp frA_I64, IRTemp frB_I64)
138034aa412af1d8166cc11f39a6e721df49431d23618sewardj{
138044aa412af1d8166cc11f39a6e721df49431d23618sewardj   IRTemp frA_isNaN = newTemp(Ity_I1);
138054aa412af1d8166cc11f39a6e721df49431d23618sewardj   IRTemp frB_isNaN = newTemp(Ity_I1);
138064aa412af1d8166cc11f39a6e721df49431d23618sewardj   IRTemp frA_isSNaN = newTemp(Ity_I1);
138074aa412af1d8166cc11f39a6e721df49431d23618sewardj   IRTemp frB_isSNaN = newTemp(Ity_I1);
138084aa412af1d8166cc11f39a6e721df49431d23618sewardj   IRTemp frA_isQNaN = newTemp(Ity_I1);
138094aa412af1d8166cc11f39a6e721df49431d23618sewardj   IRTemp frB_isQNaN = newTemp(Ity_I1);
138104aa412af1d8166cc11f39a6e721df49431d23618sewardj
138114aa412af1d8166cc11f39a6e721df49431d23618sewardj   assign( frA_isNaN, is_NaN( frA_I64 ) );
138124aa412af1d8166cc11f39a6e721df49431d23618sewardj   assign( frB_isNaN, is_NaN( frB_I64 ) );
138134aa412af1d8166cc11f39a6e721df49431d23618sewardj   // If operand is a NAN and bit 12 is '0', then it's an SNaN
138144aa412af1d8166cc11f39a6e721df49431d23618sewardj   assign( frA_isSNaN,
138154aa412af1d8166cc11f39a6e721df49431d23618sewardj           mkAND1( mkexpr(frA_isNaN),
138164aa412af1d8166cc11f39a6e721df49431d23618sewardj                   binop( Iop_CmpEQ32,
138174aa412af1d8166cc11f39a6e721df49431d23618sewardj                          binop( Iop_And32,
138184aa412af1d8166cc11f39a6e721df49431d23618sewardj                                 unop( Iop_64HIto32, mkexpr( frA_I64 ) ),
138194aa412af1d8166cc11f39a6e721df49431d23618sewardj                                 mkU32( 0x00080000 ) ),
138204aa412af1d8166cc11f39a6e721df49431d23618sewardj                          mkU32( 0 ) ) ) );
138214aa412af1d8166cc11f39a6e721df49431d23618sewardj   assign( frB_isSNaN,
138224aa412af1d8166cc11f39a6e721df49431d23618sewardj           mkAND1( mkexpr(frB_isNaN),
138234aa412af1d8166cc11f39a6e721df49431d23618sewardj                   binop( Iop_CmpEQ32,
138244aa412af1d8166cc11f39a6e721df49431d23618sewardj                          binop( Iop_And32,
138254aa412af1d8166cc11f39a6e721df49431d23618sewardj                                 unop( Iop_64HIto32, mkexpr( frB_I64 ) ),
138264aa412af1d8166cc11f39a6e721df49431d23618sewardj                                 mkU32( 0x00080000 ) ),
138274aa412af1d8166cc11f39a6e721df49431d23618sewardj                          mkU32( 0 ) ) ) );
138284aa412af1d8166cc11f39a6e721df49431d23618sewardj   assign( frA_isQNaN,
138294aa412af1d8166cc11f39a6e721df49431d23618sewardj           mkAND1( mkexpr( frA_isNaN ), unop( Iop_Not1, mkexpr( frA_isSNaN ) ) ) );
138304aa412af1d8166cc11f39a6e721df49431d23618sewardj   assign( frB_isQNaN,
138314aa412af1d8166cc11f39a6e721df49431d23618sewardj           mkAND1( mkexpr( frB_isNaN ), unop( Iop_Not1, mkexpr( frB_isSNaN ) ) ) );
138324aa412af1d8166cc11f39a6e721df49431d23618sewardj
138334aa412af1d8166cc11f39a6e721df49431d23618sewardj   /* Based on the rules specified in the function prologue, the algorithm is as follows:
138344aa412af1d8166cc11f39a6e721df49431d23618sewardj    *  <<<<<<<<<>>>>>>>>>>>>>>>>>>
138354aa412af1d8166cc11f39a6e721df49431d23618sewardj    *   if frA is a SNaN
138364aa412af1d8166cc11f39a6e721df49431d23618sewardj    *     result = frA converted to QNaN
138374aa412af1d8166cc11f39a6e721df49431d23618sewardj    *   else if frB is a SNaN
138384aa412af1d8166cc11f39a6e721df49431d23618sewardj    *     result = frB converted to QNaN
138394aa412af1d8166cc11f39a6e721df49431d23618sewardj    *   else if frB is a QNaN
138404aa412af1d8166cc11f39a6e721df49431d23618sewardj    *     result = frA
138414aa412af1d8166cc11f39a6e721df49431d23618sewardj    *   // One of frA or frB was a NaN in order for this function to be called, so
138424aa412af1d8166cc11f39a6e721df49431d23618sewardj    *   // if we get to this point, we KNOW that frA must be a QNaN.
138434aa412af1d8166cc11f39a6e721df49431d23618sewardj    *   else // frA is a QNaN
138444aa412af1d8166cc11f39a6e721df49431d23618sewardj    *     result = frB
138454aa412af1d8166cc11f39a6e721df49431d23618sewardj    *  <<<<<<<<<>>>>>>>>>>>>>>>>>>
138464aa412af1d8166cc11f39a6e721df49431d23618sewardj    */
138474aa412af1d8166cc11f39a6e721df49431d23618sewardj
138484aa412af1d8166cc11f39a6e721df49431d23618sewardj#define SNAN_MASK 0x0008000000000000ULL
138494aa412af1d8166cc11f39a6e721df49431d23618sewardj   return
1385099dd03e04a6914d90d5fee727d61d76905334becflorian   IRExpr_ITE(mkexpr(frA_isSNaN),
1385199dd03e04a6914d90d5fee727d61d76905334becflorian              /* then: result = frA converted to QNaN */
1385299dd03e04a6914d90d5fee727d61d76905334becflorian              binop(Iop_Or64, mkexpr(frA_I64), mkU64(SNAN_MASK)),
1385399dd03e04a6914d90d5fee727d61d76905334becflorian              /* else:  if frB is a SNaN */
1385499dd03e04a6914d90d5fee727d61d76905334becflorian              IRExpr_ITE(mkexpr(frB_isSNaN),
1385599dd03e04a6914d90d5fee727d61d76905334becflorian                         /* then: result = frB converted to QNaN */
1385699dd03e04a6914d90d5fee727d61d76905334becflorian                         binop(Iop_Or64, mkexpr(frB_I64), mkU64(SNAN_MASK)),
1385799dd03e04a6914d90d5fee727d61d76905334becflorian                         /* else:  if frB is a QNaN */
1385899dd03e04a6914d90d5fee727d61d76905334becflorian                         IRExpr_ITE(mkexpr(frB_isQNaN),
1385999dd03e04a6914d90d5fee727d61d76905334becflorian                                    /* then: result = frA */
1386099dd03e04a6914d90d5fee727d61d76905334becflorian                                    mkexpr(frA_I64),
1386199dd03e04a6914d90d5fee727d61d76905334becflorian                                    /* else:  frA is a QNaN, so result = frB */
1386299dd03e04a6914d90d5fee727d61d76905334becflorian                                    mkexpr(frB_I64))));
138634aa412af1d8166cc11f39a6e721df49431d23618sewardj}
138644aa412af1d8166cc11f39a6e721df49431d23618sewardj
138654aa412af1d8166cc11f39a6e721df49431d23618sewardj/*
138664aa412af1d8166cc11f39a6e721df49431d23618sewardj * Helper function for get_max_min_fp.
138674aa412af1d8166cc11f39a6e721df49431d23618sewardj */
138684aa412af1d8166cc11f39a6e721df49431d23618sewardjstatic IRExpr * _get_maxmin_fp_cmp(IRTemp src1, IRTemp src2, Bool isMin)
138694aa412af1d8166cc11f39a6e721df49431d23618sewardj{
138704aa412af1d8166cc11f39a6e721df49431d23618sewardj   IRTemp src1cmpsrc2 = get_fp_cmp_CR_val( binop( Iop_CmpF64,
138714aa412af1d8166cc11f39a6e721df49431d23618sewardj                                                  unop( Iop_ReinterpI64asF64,
138724aa412af1d8166cc11f39a6e721df49431d23618sewardj                                                        mkexpr( src1 ) ),
138734aa412af1d8166cc11f39a6e721df49431d23618sewardj                                                  unop( Iop_ReinterpI64asF64,
138744aa412af1d8166cc11f39a6e721df49431d23618sewardj                                                        mkexpr( src2 ) ) ) );
138754aa412af1d8166cc11f39a6e721df49431d23618sewardj
1387699dd03e04a6914d90d5fee727d61d76905334becflorian   return IRExpr_ITE( binop( Iop_CmpEQ32,
13877009230b9758291b594e60d7c0243a73d53e81854sewardj                               mkexpr( src1cmpsrc2 ),
13878009230b9758291b594e60d7c0243a73d53e81854sewardj                               mkU32( isMin ? PPC_CMP_LT : PPC_CMP_GT ) ),
1387999dd03e04a6914d90d5fee727d61d76905334becflorian                      /* then: use src1 */
1388099dd03e04a6914d90d5fee727d61d76905334becflorian                      mkexpr( src1 ),
1388199dd03e04a6914d90d5fee727d61d76905334becflorian                      /* else: use src2 */
1388299dd03e04a6914d90d5fee727d61d76905334becflorian                      mkexpr( src2 ) );
138834aa412af1d8166cc11f39a6e721df49431d23618sewardj}
138844aa412af1d8166cc11f39a6e721df49431d23618sewardj
138854aa412af1d8166cc11f39a6e721df49431d23618sewardj/*
138864aa412af1d8166cc11f39a6e721df49431d23618sewardj * Helper function for "Maximum/Minimum Double Precision" operations.
138874aa412af1d8166cc11f39a6e721df49431d23618sewardj * Arguments: frA and frb are Ity_I64
138884aa412af1d8166cc11f39a6e721df49431d23618sewardj * Returns Ity_I64 IRExpr that answers the "which is Maxiumum/Minimum" question
138894aa412af1d8166cc11f39a6e721df49431d23618sewardj */
138904aa412af1d8166cc11f39a6e721df49431d23618sewardjstatic IRExpr * get_max_min_fp(IRTemp frA_I64, IRTemp frB_I64, Bool isMin)
138914aa412af1d8166cc11f39a6e721df49431d23618sewardj{
138924aa412af1d8166cc11f39a6e721df49431d23618sewardj   /* There are three special cases where get_fp_cmp_CR_val is not helpful
138934aa412af1d8166cc11f39a6e721df49431d23618sewardj    * for ascertaining the maximum between two doubles:
138944aa412af1d8166cc11f39a6e721df49431d23618sewardj    *   1. The max/min of +0 and -0 is +0.
138954aa412af1d8166cc11f39a6e721df49431d23618sewardj    *   2. The max/min of a QNaN and any value is that value.
138964aa412af1d8166cc11f39a6e721df49431d23618sewardj    *   3. The max/min of any value and an SNaN is that SNaN converted to a QNaN.
138974aa412af1d8166cc11f39a6e721df49431d23618sewardj    * We perform the check for [+/-]0 here in this function and use the
138984aa412af1d8166cc11f39a6e721df49431d23618sewardj    * _get_maxmin_fp_NaN helper for the two NaN cases; otherwise we call _get_maxmin_fp_cmp
138994aa412af1d8166cc11f39a6e721df49431d23618sewardj    * to do the standard comparison function.
139004aa412af1d8166cc11f39a6e721df49431d23618sewardj    */
139014aa412af1d8166cc11f39a6e721df49431d23618sewardj   IRTemp anyNaN = newTemp(Ity_I1);
139024aa412af1d8166cc11f39a6e721df49431d23618sewardj   IRTemp frA_isZero = newTemp(Ity_I1);
139034aa412af1d8166cc11f39a6e721df49431d23618sewardj   IRTemp frB_isZero = newTemp(Ity_I1);
13904e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj   assign(frA_isZero, is_Zero(frA_I64, False /*not single precision*/ ));
13905e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj   assign(frB_isZero, is_Zero(frB_I64, False /*not single precision*/ ));
139064aa412af1d8166cc11f39a6e721df49431d23618sewardj   assign(anyNaN, mkOR1(is_NaN(frA_I64), is_NaN(frB_I64)));
139074aa412af1d8166cc11f39a6e721df49431d23618sewardj#define MINUS_ZERO 0x8000000000000000ULL
139084aa412af1d8166cc11f39a6e721df49431d23618sewardj
1390999dd03e04a6914d90d5fee727d61d76905334becflorian   return IRExpr_ITE( /* If both arguments are zero . . . */
1391099dd03e04a6914d90d5fee727d61d76905334becflorian                     mkAND1( mkexpr( frA_isZero ), mkexpr( frB_isZero ) ),
1391199dd03e04a6914d90d5fee727d61d76905334becflorian                     /* then: if frA is -0 and isMin==True, return -0;
1391299dd03e04a6914d90d5fee727d61d76905334becflorian                      *     else if frA is +0 and isMin==False; return +0;
1391399dd03e04a6914d90d5fee727d61d76905334becflorian                      *     otherwise, simply return frB. */
1391499dd03e04a6914d90d5fee727d61d76905334becflorian                     IRExpr_ITE( binop( Iop_CmpEQ32,
1391599dd03e04a6914d90d5fee727d61d76905334becflorian                                        unop( Iop_64HIto32,
1391699dd03e04a6914d90d5fee727d61d76905334becflorian                                              mkexpr( frA_I64 ) ),
1391799dd03e04a6914d90d5fee727d61d76905334becflorian                                        mkU32( isMin ? 0x80000000 : 0 ) ),
1391899dd03e04a6914d90d5fee727d61d76905334becflorian                                 mkU64( isMin ? MINUS_ZERO : 0ULL ),
1391999dd03e04a6914d90d5fee727d61d76905334becflorian                                 mkexpr( frB_I64 ) ),
1392099dd03e04a6914d90d5fee727d61d76905334becflorian                     /* else: check if either input is a NaN*/
1392199dd03e04a6914d90d5fee727d61d76905334becflorian                     IRExpr_ITE( mkexpr( anyNaN ),
1392299dd03e04a6914d90d5fee727d61d76905334becflorian                                 /* then: use "NaN helper" */
1392399dd03e04a6914d90d5fee727d61d76905334becflorian                                 _get_maxmin_fp_NaN( frA_I64, frB_I64 ),
1392499dd03e04a6914d90d5fee727d61d76905334becflorian                                 /* else: use "comparison helper" */
1392599dd03e04a6914d90d5fee727d61d76905334becflorian                                 _get_maxmin_fp_cmp( frB_I64, frA_I64, isMin ) ));
139264aa412af1d8166cc11f39a6e721df49431d23618sewardj}
13927e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj
139289884af0b3cfe935b8fab54231f394fe4ee2d7ebccarllstatic const HChar * _get_vsx_rdpi_suffix(UInt opc2)
139299884af0b3cfe935b8fab54231f394fe4ee2d7ebccarll{
139309884af0b3cfe935b8fab54231f394fe4ee2d7ebccarll   switch (opc2 & 0x7F) {
139319884af0b3cfe935b8fab54231f394fe4ee2d7ebccarll      case 0x72:
139329884af0b3cfe935b8fab54231f394fe4ee2d7ebccarll         return "m";
139339884af0b3cfe935b8fab54231f394fe4ee2d7ebccarll      case 0x52:
139349884af0b3cfe935b8fab54231f394fe4ee2d7ebccarll         return "p";
139359884af0b3cfe935b8fab54231f394fe4ee2d7ebccarll      case 0x56:
139369884af0b3cfe935b8fab54231f394fe4ee2d7ebccarll         return "c";
139379884af0b3cfe935b8fab54231f394fe4ee2d7ebccarll      case 0x32:
139389884af0b3cfe935b8fab54231f394fe4ee2d7ebccarll         return "z";
139399884af0b3cfe935b8fab54231f394fe4ee2d7ebccarll      case 0x12:
139409884af0b3cfe935b8fab54231f394fe4ee2d7ebccarll         return "";
139419884af0b3cfe935b8fab54231f394fe4ee2d7ebccarll
139429884af0b3cfe935b8fab54231f394fe4ee2d7ebccarll      default: // Impossible to get here
139439884af0b3cfe935b8fab54231f394fe4ee2d7ebccarll         vex_printf("Unrecognized opcode %x\n", opc2);
139449884af0b3cfe935b8fab54231f394fe4ee2d7ebccarll         vpanic("_get_vsx_rdpi_suffix(ppc)(opc2)");
139459884af0b3cfe935b8fab54231f394fe4ee2d7ebccarll   }
139469884af0b3cfe935b8fab54231f394fe4ee2d7ebccarll}
139479884af0b3cfe935b8fab54231f394fe4ee2d7ebccarll
13948e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj/*
13949e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj * Helper function for vector/scalar double precision fp round to integer instructions.
13950e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj */
139519884af0b3cfe935b8fab54231f394fe4ee2d7ebccarllstatic IRExpr * _do_vsx_fp_roundToInt(IRTemp frB_I64, UInt opc2)
13952e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj{
13953e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj
13954e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj   /* The same rules apply for x{s|v}rdpi{m|p|c|z} as for floating point round operations (fri{m|n|p|z}). */
13955e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj   IRTemp frB = newTemp(Ity_F64);
13956e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj   IRTemp frD = newTemp(Ity_F64);
13957e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj   IRTemp intermediateResult = newTemp(Ity_I64);
13958e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj   IRTemp is_SNAN = newTemp(Ity_I1);
13959e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj   IRExpr * hi32;
13960e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj   IRExpr * rxpi_rm;
13961e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj   switch (opc2 & 0x7F) {
13962e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj      case 0x72:
13963e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj         rxpi_rm = mkU32(Irrm_NegINF);
13964e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj         break;
13965e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj      case 0x52:
13966e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj         rxpi_rm = mkU32(Irrm_PosINF);
13967e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj         break;
13968e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj      case 0x56:
13969e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj         rxpi_rm = get_IR_roundingmode();
13970e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj         break;
13971e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj      case 0x32:
13972e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj         rxpi_rm = mkU32(Irrm_ZERO);
13973e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj         break;
13974e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj      case 0x12:
13975e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj         rxpi_rm = mkU32(Irrm_NEAREST);
13976e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj         break;
13977e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj
13978e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj      default: // Impossible to get here
139799884af0b3cfe935b8fab54231f394fe4ee2d7ebccarll         vex_printf("Unrecognized opcode %x\n", opc2);
139809884af0b3cfe935b8fab54231f394fe4ee2d7ebccarll         vpanic("_do_vsx_fp_roundToInt(ppc)(opc2)");
13981e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj   }
13982e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj   assign(frB, unop(Iop_ReinterpI64asF64, mkexpr(frB_I64)));
13983e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj   assign( intermediateResult,
13984e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj           binop( Iop_F64toI64S, rxpi_rm,
13985e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj                  mkexpr( frB ) ) );
13986e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj
13987e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj   /* don't use the rounded integer if frB is outside -9e18..9e18 */
13988e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj   /* F64 has only log10(2**52) significant digits anyway */
13989e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj   /* need to preserve sign of zero */
13990e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj   /*   frD = (fabs(frB) > 9e18) ? frB :
13991e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj            (sign(frB)) ? -fabs((double)intermediateResult) : (double)intermediateResult  */
13992e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj   assign( frD,
1399399dd03e04a6914d90d5fee727d61d76905334becflorian           IRExpr_ITE(
13994009230b9758291b594e60d7c0243a73d53e81854sewardj              binop( Iop_CmpNE8,
13995009230b9758291b594e60d7c0243a73d53e81854sewardj                     unop( Iop_32to8,
13996009230b9758291b594e60d7c0243a73d53e81854sewardj                           binop( Iop_CmpF64,
13997009230b9758291b594e60d7c0243a73d53e81854sewardj                                  IRExpr_Const( IRConst_F64( 9e18 ) ),
13998009230b9758291b594e60d7c0243a73d53e81854sewardj                                  unop( Iop_AbsF64, mkexpr( frB ) ) ) ),
13999009230b9758291b594e60d7c0243a73d53e81854sewardj                     mkU8(0) ),
1400099dd03e04a6914d90d5fee727d61d76905334becflorian              mkexpr( frB ),
1400199dd03e04a6914d90d5fee727d61d76905334becflorian              IRExpr_ITE(
14002009230b9758291b594e60d7c0243a73d53e81854sewardj                 binop( Iop_CmpNE32,
14003009230b9758291b594e60d7c0243a73d53e81854sewardj                        binop( Iop_Shr32,
14004009230b9758291b594e60d7c0243a73d53e81854sewardj                               unop( Iop_64HIto32,
14005009230b9758291b594e60d7c0243a73d53e81854sewardj                                     mkexpr( frB_I64 ) ),
14006009230b9758291b594e60d7c0243a73d53e81854sewardj                               mkU8( 31 ) ),
14007009230b9758291b594e60d7c0243a73d53e81854sewardj                        mkU32(0) ),
14008009230b9758291b594e60d7c0243a73d53e81854sewardj                 unop( Iop_NegF64,
14009009230b9758291b594e60d7c0243a73d53e81854sewardj                       unop( Iop_AbsF64,
14010009230b9758291b594e60d7c0243a73d53e81854sewardj                             binop( Iop_I64StoF64,
14011009230b9758291b594e60d7c0243a73d53e81854sewardj                                    mkU32( 0 ),
1401299dd03e04a6914d90d5fee727d61d76905334becflorian                                    mkexpr( intermediateResult ) ) ) ),
1401399dd03e04a6914d90d5fee727d61d76905334becflorian                 binop( Iop_I64StoF64,
1401499dd03e04a6914d90d5fee727d61d76905334becflorian                        mkU32( 0 ),
1401599dd03e04a6914d90d5fee727d61d76905334becflorian                        mkexpr( intermediateResult ) )
1401699dd03e04a6914d90d5fee727d61d76905334becflorian              )
14017009230b9758291b594e60d7c0243a73d53e81854sewardj           )
14018009230b9758291b594e60d7c0243a73d53e81854sewardj   );
14019e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj
14020e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj   /* See Appendix "Floating-Point Round to Integer Model" in ISA doc.
14021e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj    * If frB is a SNAN, then frD <- frB, with bit 12 set to '1'.
14022e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj    */
14023e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj#define SNAN_MASK 0x0008000000000000ULL
14024e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj   hi32 = unop( Iop_64HIto32, mkexpr(frB_I64) );
14025e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj   assign( is_SNAN,
14026e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj           mkAND1( is_NaN( frB_I64 ),
14027e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj                   binop( Iop_CmpEQ32,
14028e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj                          binop( Iop_And32, hi32, mkU32( 0x00080000 ) ),
14029e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj                          mkU32( 0 ) ) ) );
14030e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj
1403199dd03e04a6914d90d5fee727d61d76905334becflorian   return IRExpr_ITE( mkexpr( is_SNAN ),
14032e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj                        unop( Iop_ReinterpI64asF64,
14033e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj                              binop( Iop_Xor64,
14034e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj                                     mkU64( SNAN_MASK ),
1403599dd03e04a6914d90d5fee727d61d76905334becflorian                                     mkexpr( frB_I64 ) ) ),
1403699dd03e04a6914d90d5fee727d61d76905334becflorian                      mkexpr( frD ));
14037e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj}
14038e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj
140394aa412af1d8166cc11f39a6e721df49431d23618sewardj/*
140404aa412af1d8166cc11f39a6e721df49431d23618sewardj * Miscellaneous VSX vector instructions
140414aa412af1d8166cc11f39a6e721df49431d23618sewardj */
140424aa412af1d8166cc11f39a6e721df49431d23618sewardjstatic Bool
140434aa412af1d8166cc11f39a6e721df49431d23618sewardjdis_vxv_misc ( UInt theInstr, UInt opc2 )
140444aa412af1d8166cc11f39a6e721df49431d23618sewardj{
140454aa412af1d8166cc11f39a6e721df49431d23618sewardj   /* XX3-Form */
140464aa412af1d8166cc11f39a6e721df49431d23618sewardj   UChar opc1 = ifieldOPC( theInstr );
140474aa412af1d8166cc11f39a6e721df49431d23618sewardj   UChar XT = ifieldRegXT( theInstr );
140484aa412af1d8166cc11f39a6e721df49431d23618sewardj   UChar XB = ifieldRegXB( theInstr );
140494aa412af1d8166cc11f39a6e721df49431d23618sewardj
140504aa412af1d8166cc11f39a6e721df49431d23618sewardj   if (opc1 != 0x3C) {
140514aa412af1d8166cc11f39a6e721df49431d23618sewardj      vex_printf( "dis_vxv_misc(ppc)(instr)\n" );
140524aa412af1d8166cc11f39a6e721df49431d23618sewardj      return False;
140534aa412af1d8166cc11f39a6e721df49431d23618sewardj   }
140544aa412af1d8166cc11f39a6e721df49431d23618sewardj
140554aa412af1d8166cc11f39a6e721df49431d23618sewardj   switch (opc2) {
14056e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj      case 0x1B4:  // xvredp (VSX Vector Reciprocal Estimate Double-Precision)
14057e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj      case 0x194:  // xvrsqrtedp (VSX Vector Reciprocal Square Root Estimate
14058e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj                   //             Double-Precision)
14059e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj      {
14060e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj         IRExpr* ieee_one = IRExpr_Const(IRConst_F64i(0x3ff0000000000000ULL));
14061e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj         IRExpr* rm  = get_IR_roundingmode();
14062e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj         IRTemp frB = newTemp(Ity_I64);
14063e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj         IRTemp frB2 = newTemp(Ity_I64);
14064e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj         Bool redp = opc2 == 0x1B4;
14065e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj         IRTemp sqrtHi = newTemp(Ity_F64);
14066e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj         IRTemp sqrtLo = newTemp(Ity_F64);
14067e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj         assign(frB,  unop(Iop_V128HIto64, getVSReg( XB )));
14068e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj         assign(frB2, unop(Iop_V128to64, getVSReg( XB )));
14069e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj
14070e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj         DIP("%s v%d,v%d\n", redp ? "xvredp" : "xvrsqrtedp", (UInt)XT, (UInt)XB);
14071e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj         if (!redp) {
14072e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj            assign( sqrtHi,
14073e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj                    binop( Iop_SqrtF64,
14074e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj                           rm,
14075e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj                           unop( Iop_ReinterpI64asF64, mkexpr( frB ) ) ) );
14076e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj            assign( sqrtLo,
14077e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj                    binop( Iop_SqrtF64,
14078e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj                           rm,
14079e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj                           unop( Iop_ReinterpI64asF64, mkexpr( frB2 ) ) ) );
14080e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj         }
14081e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj         putVSReg( XT,
14082e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj                   binop( Iop_64HLtoV128,
14083e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj                          unop( Iop_ReinterpF64asI64,
14084e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj                                triop( Iop_DivF64,
14085e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj                                       rm,
14086e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj                                       ieee_one,
14087e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj                                       redp ? unop( Iop_ReinterpI64asF64,
14088e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj                                                    mkexpr( frB ) )
14089e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj                                            : mkexpr( sqrtHi ) ) ),
14090e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj                          unop( Iop_ReinterpF64asI64,
14091e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj                                triop( Iop_DivF64,
14092e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj                                       rm,
14093e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj                                       ieee_one,
14094e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj                                       redp ? unop( Iop_ReinterpI64asF64,
14095e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj                                                    mkexpr( frB2 ) )
14096e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj                                            : mkexpr( sqrtLo ) ) ) ) );
14097e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj         break;
14098e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj
14099e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj      }
141004aa412af1d8166cc11f39a6e721df49431d23618sewardj      case 0x134: // xvresp (VSX Vector Reciprocal Estimate Single-Precision)
14101e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj      case 0x114: // xvrsqrtesp (VSX Vector Reciprocal Square Root Estimate Single-Precision)
141024aa412af1d8166cc11f39a6e721df49431d23618sewardj      {
141034aa412af1d8166cc11f39a6e721df49431d23618sewardj         IRTemp b3, b2, b1, b0;
141044aa412af1d8166cc11f39a6e721df49431d23618sewardj         IRTemp res0 = newTemp(Ity_I32);
141054aa412af1d8166cc11f39a6e721df49431d23618sewardj         IRTemp res1 = newTemp(Ity_I32);
141064aa412af1d8166cc11f39a6e721df49431d23618sewardj         IRTemp res2 = newTemp(Ity_I32);
141074aa412af1d8166cc11f39a6e721df49431d23618sewardj         IRTemp res3 = newTemp(Ity_I32);
14108e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj         IRTemp sqrt3 = newTemp(Ity_F64);
14109e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj         IRTemp sqrt2 = newTemp(Ity_F64);
14110e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj         IRTemp sqrt1 = newTemp(Ity_F64);
14111e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj         IRTemp sqrt0 = newTemp(Ity_F64);
141124aa412af1d8166cc11f39a6e721df49431d23618sewardj         IRExpr* rm  = get_IR_roundingmode();
14113e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj         Bool resp = opc2 == 0x134;
14114e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj
141154aa412af1d8166cc11f39a6e721df49431d23618sewardj         IRExpr* ieee_one = IRExpr_Const(IRConst_F64i(0x3ff0000000000000ULL));
141164aa412af1d8166cc11f39a6e721df49431d23618sewardj
141174aa412af1d8166cc11f39a6e721df49431d23618sewardj         b3 = b2 = b1 = b0 = IRTemp_INVALID;
14118e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj         DIP("%s v%d,v%d\n", resp ? "xvresp" : "xvrsqrtesp", (UInt)XT, (UInt)XB);
141194aa412af1d8166cc11f39a6e721df49431d23618sewardj         breakV128to4xF64( getVSReg( XB ), &b3, &b2, &b1, &b0 );
14120e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj
14121e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj         if (!resp) {
14122e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj            assign( sqrt3, binop( Iop_SqrtF64, rm, mkexpr( b3 ) ) );
14123e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj            assign( sqrt2, binop( Iop_SqrtF64, rm, mkexpr( b2 ) ) );
14124e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj            assign( sqrt1, binop( Iop_SqrtF64, rm, mkexpr( b1 ) ) );
14125e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj            assign( sqrt0, binop( Iop_SqrtF64, rm, mkexpr( b0 ) ) );
14126e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj         }
14127e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj
141284aa412af1d8166cc11f39a6e721df49431d23618sewardj         assign( res0,
141294aa412af1d8166cc11f39a6e721df49431d23618sewardj                 unop( Iop_ReinterpF32asI32,
141304aa412af1d8166cc11f39a6e721df49431d23618sewardj                       unop( Iop_TruncF64asF32,
14131e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj                             triop( Iop_DivF64r32,
14132e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj                                    rm,
14133e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj                                    ieee_one,
14134e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj                                    resp ? mkexpr( b0 ) : mkexpr( sqrt0 ) ) ) ) );
141354aa412af1d8166cc11f39a6e721df49431d23618sewardj         assign( res1,
141364aa412af1d8166cc11f39a6e721df49431d23618sewardj                 unop( Iop_ReinterpF32asI32,
141374aa412af1d8166cc11f39a6e721df49431d23618sewardj                       unop( Iop_TruncF64asF32,
14138e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj                             triop( Iop_DivF64r32,
14139e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj                                    rm,
14140e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj                                    ieee_one,
14141e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj                                    resp ? mkexpr( b1 ) : mkexpr( sqrt1 ) ) ) ) );
141424aa412af1d8166cc11f39a6e721df49431d23618sewardj         assign( res2,
141434aa412af1d8166cc11f39a6e721df49431d23618sewardj                 unop( Iop_ReinterpF32asI32,
141444aa412af1d8166cc11f39a6e721df49431d23618sewardj                       unop( Iop_TruncF64asF32,
14145e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj                             triop( Iop_DivF64r32,
14146e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj                                    rm,
14147e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj                                    ieee_one,
14148e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj                                    resp ? mkexpr( b2 ) : mkexpr( sqrt2 ) ) ) ) );
141494aa412af1d8166cc11f39a6e721df49431d23618sewardj         assign( res3,
141504aa412af1d8166cc11f39a6e721df49431d23618sewardj                 unop( Iop_ReinterpF32asI32,
141514aa412af1d8166cc11f39a6e721df49431d23618sewardj                       unop( Iop_TruncF64asF32,
14152e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj                             triop( Iop_DivF64r32,
14153e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj                                    rm,
14154e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj                                    ieee_one,
14155e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj                                    resp ? mkexpr( b3 ) : mkexpr( sqrt3 ) ) ) ) );
141564aa412af1d8166cc11f39a6e721df49431d23618sewardj         putVSReg( XT,
141574aa412af1d8166cc11f39a6e721df49431d23618sewardj                   binop( Iop_64HLtoV128,
141584aa412af1d8166cc11f39a6e721df49431d23618sewardj                          binop( Iop_32HLto64, mkexpr( res3 ), mkexpr( res2 ) ),
141594aa412af1d8166cc11f39a6e721df49431d23618sewardj                          binop( Iop_32HLto64, mkexpr( res1 ), mkexpr( res0 ) ) ) );
141604aa412af1d8166cc11f39a6e721df49431d23618sewardj         break;
141614aa412af1d8166cc11f39a6e721df49431d23618sewardj      }
141624aa412af1d8166cc11f39a6e721df49431d23618sewardj      case 0x300: // xvmaxsp (VSX Vector Maximum Single-Precision)
141634aa412af1d8166cc11f39a6e721df49431d23618sewardj      case 0x320: // xvminsp (VSX Vector Minimum Single-Precision)
141644aa412af1d8166cc11f39a6e721df49431d23618sewardj      {
141654aa412af1d8166cc11f39a6e721df49431d23618sewardj         UChar XA = ifieldRegXA( theInstr );
141664aa412af1d8166cc11f39a6e721df49431d23618sewardj         IRTemp a3, a2, a1, a0;
141674aa412af1d8166cc11f39a6e721df49431d23618sewardj         IRTemp b3, b2, b1, b0;
141684aa412af1d8166cc11f39a6e721df49431d23618sewardj         IRTemp res0 = newTemp( Ity_I32 );
141694aa412af1d8166cc11f39a6e721df49431d23618sewardj         IRTemp res1 = newTemp( Ity_I32 );
141704aa412af1d8166cc11f39a6e721df49431d23618sewardj         IRTemp res2 = newTemp( Ity_I32 );
141714aa412af1d8166cc11f39a6e721df49431d23618sewardj         IRTemp res3 = newTemp( Ity_I32 );
141724aa412af1d8166cc11f39a6e721df49431d23618sewardj         IRTemp a0_I64 = newTemp( Ity_I64 );
141734aa412af1d8166cc11f39a6e721df49431d23618sewardj         IRTemp a1_I64 = newTemp( Ity_I64 );
141744aa412af1d8166cc11f39a6e721df49431d23618sewardj         IRTemp a2_I64 = newTemp( Ity_I64 );
141754aa412af1d8166cc11f39a6e721df49431d23618sewardj         IRTemp a3_I64 = newTemp( Ity_I64 );
141764aa412af1d8166cc11f39a6e721df49431d23618sewardj         IRTemp b0_I64 = newTemp( Ity_I64 );
141774aa412af1d8166cc11f39a6e721df49431d23618sewardj         IRTemp b1_I64 = newTemp( Ity_I64 );
141784aa412af1d8166cc11f39a6e721df49431d23618sewardj         IRTemp b2_I64 = newTemp( Ity_I64 );
141794aa412af1d8166cc11f39a6e721df49431d23618sewardj         IRTemp b3_I64 = newTemp( Ity_I64 );
141804aa412af1d8166cc11f39a6e721df49431d23618sewardj
141814aa412af1d8166cc11f39a6e721df49431d23618sewardj         Bool isMin = opc2 == 0x320 ? True : False;
141824aa412af1d8166cc11f39a6e721df49431d23618sewardj
141834aa412af1d8166cc11f39a6e721df49431d23618sewardj         a3 = a2 = a1 = a0 = IRTemp_INVALID;
141844aa412af1d8166cc11f39a6e721df49431d23618sewardj         b3 = b2 = b1 = b0 = IRTemp_INVALID;
141854aa412af1d8166cc11f39a6e721df49431d23618sewardj         DIP("%s v%d,v%d v%d\n", isMin ? "xvminsp" : "xvmaxsp", (UInt)XT, (UInt)XA, (UInt)XB);
141864aa412af1d8166cc11f39a6e721df49431d23618sewardj         breakV128to4xF64( getVSReg( XA ), &a3, &a2, &a1, &a0 );
141874aa412af1d8166cc11f39a6e721df49431d23618sewardj         breakV128to4xF64( getVSReg( XB ), &b3, &b2, &b1, &b0 );
141884aa412af1d8166cc11f39a6e721df49431d23618sewardj         assign( a0_I64, unop( Iop_ReinterpF64asI64, mkexpr( a0 ) ) );
141894aa412af1d8166cc11f39a6e721df49431d23618sewardj         assign( b0_I64, unop( Iop_ReinterpF64asI64, mkexpr( b0 ) ) );
141904aa412af1d8166cc11f39a6e721df49431d23618sewardj         assign( a1_I64, unop( Iop_ReinterpF64asI64, mkexpr( a1 ) ) );
141914aa412af1d8166cc11f39a6e721df49431d23618sewardj         assign( b1_I64, unop( Iop_ReinterpF64asI64, mkexpr( b1 ) ) );
141924aa412af1d8166cc11f39a6e721df49431d23618sewardj         assign( a2_I64, unop( Iop_ReinterpF64asI64, mkexpr( a2 ) ) );
141934aa412af1d8166cc11f39a6e721df49431d23618sewardj         assign( b2_I64, unop( Iop_ReinterpF64asI64, mkexpr( b2 ) ) );
141944aa412af1d8166cc11f39a6e721df49431d23618sewardj         assign( a3_I64, unop( Iop_ReinterpF64asI64, mkexpr( a3 ) ) );
141954aa412af1d8166cc11f39a6e721df49431d23618sewardj         assign( b3_I64, unop( Iop_ReinterpF64asI64, mkexpr( b3 ) ) );
141964aa412af1d8166cc11f39a6e721df49431d23618sewardj         assign( res0,
141974aa412af1d8166cc11f39a6e721df49431d23618sewardj                 unop( Iop_ReinterpF32asI32,
141984aa412af1d8166cc11f39a6e721df49431d23618sewardj                       unop( Iop_TruncF64asF32,
141994aa412af1d8166cc11f39a6e721df49431d23618sewardj                             unop( Iop_ReinterpI64asF64,
142004aa412af1d8166cc11f39a6e721df49431d23618sewardj                                   get_max_min_fp( a0_I64, b0_I64, isMin ) ) ) ) );
142014aa412af1d8166cc11f39a6e721df49431d23618sewardj         assign( res1,
142024aa412af1d8166cc11f39a6e721df49431d23618sewardj                 unop( Iop_ReinterpF32asI32,
142034aa412af1d8166cc11f39a6e721df49431d23618sewardj                       unop( Iop_TruncF64asF32,
142044aa412af1d8166cc11f39a6e721df49431d23618sewardj                             unop( Iop_ReinterpI64asF64,
142054aa412af1d8166cc11f39a6e721df49431d23618sewardj                                   get_max_min_fp( a1_I64, b1_I64, isMin ) ) ) ) );
142064aa412af1d8166cc11f39a6e721df49431d23618sewardj         assign( res2,
142074aa412af1d8166cc11f39a6e721df49431d23618sewardj                 unop( Iop_ReinterpF32asI32,
142084aa412af1d8166cc11f39a6e721df49431d23618sewardj                       unop( Iop_TruncF64asF32,
142094aa412af1d8166cc11f39a6e721df49431d23618sewardj                             unop( Iop_ReinterpI64asF64,
142104aa412af1d8166cc11f39a6e721df49431d23618sewardj                                   get_max_min_fp( a2_I64, b2_I64, isMin ) ) ) ) );
142114aa412af1d8166cc11f39a6e721df49431d23618sewardj         assign( res3,
142124aa412af1d8166cc11f39a6e721df49431d23618sewardj                 unop( Iop_ReinterpF32asI32,
142134aa412af1d8166cc11f39a6e721df49431d23618sewardj                       unop( Iop_TruncF64asF32,
142144aa412af1d8166cc11f39a6e721df49431d23618sewardj                             unop( Iop_ReinterpI64asF64,
142154aa412af1d8166cc11f39a6e721df49431d23618sewardj                                   get_max_min_fp( a3_I64, b3_I64, isMin ) ) ) ) );
142164aa412af1d8166cc11f39a6e721df49431d23618sewardj         putVSReg( XT,
142174aa412af1d8166cc11f39a6e721df49431d23618sewardj                   binop( Iop_64HLtoV128,
142184aa412af1d8166cc11f39a6e721df49431d23618sewardj                          binop( Iop_32HLto64, mkexpr( res3 ), mkexpr( res2 ) ),
142194aa412af1d8166cc11f39a6e721df49431d23618sewardj                          binop( Iop_32HLto64, mkexpr( res1 ), mkexpr( res0 ) ) ) );
142204aa412af1d8166cc11f39a6e721df49431d23618sewardj         break;
142214aa412af1d8166cc11f39a6e721df49431d23618sewardj      }
142224aa412af1d8166cc11f39a6e721df49431d23618sewardj      case 0x380: // xvmaxdp (VSX Vector Maximum Double-Precision)
142234aa412af1d8166cc11f39a6e721df49431d23618sewardj      case 0x3A0: // xvmindp (VSX Vector Minimum Double-Precision)
142244aa412af1d8166cc11f39a6e721df49431d23618sewardj      {
142254aa412af1d8166cc11f39a6e721df49431d23618sewardj         UChar XA = ifieldRegXA( theInstr );
142264aa412af1d8166cc11f39a6e721df49431d23618sewardj         IRTemp frA = newTemp(Ity_I64);
142274aa412af1d8166cc11f39a6e721df49431d23618sewardj         IRTemp frB = newTemp(Ity_I64);
142284aa412af1d8166cc11f39a6e721df49431d23618sewardj         IRTemp frA2 = newTemp(Ity_I64);
142294aa412af1d8166cc11f39a6e721df49431d23618sewardj         IRTemp frB2 = newTemp(Ity_I64);
142304aa412af1d8166cc11f39a6e721df49431d23618sewardj         Bool isMin = opc2 == 0x3A0 ? True : False;
142314aa412af1d8166cc11f39a6e721df49431d23618sewardj
142324aa412af1d8166cc11f39a6e721df49431d23618sewardj         assign(frA,  unop(Iop_V128HIto64, getVSReg( XA )));
142334aa412af1d8166cc11f39a6e721df49431d23618sewardj         assign(frB,  unop(Iop_V128HIto64, getVSReg( XB )));
142344aa412af1d8166cc11f39a6e721df49431d23618sewardj         assign(frA2, unop(Iop_V128to64, getVSReg( XA )));
142354aa412af1d8166cc11f39a6e721df49431d23618sewardj         assign(frB2, unop(Iop_V128to64, getVSReg( XB )));
142364aa412af1d8166cc11f39a6e721df49431d23618sewardj         DIP("%s v%d,v%d v%d\n", isMin ? "xvmindp" : "xvmaxdp", (UInt)XT, (UInt)XA, (UInt)XB);
142374aa412af1d8166cc11f39a6e721df49431d23618sewardj         putVSReg( XT, binop( Iop_64HLtoV128, get_max_min_fp(frA, frB, isMin), get_max_min_fp(frA2, frB2, isMin) ) );
142384aa412af1d8166cc11f39a6e721df49431d23618sewardj
142394aa412af1d8166cc11f39a6e721df49431d23618sewardj         break;
142404aa412af1d8166cc11f39a6e721df49431d23618sewardj      }
142414aa412af1d8166cc11f39a6e721df49431d23618sewardj      case 0x3c0: // xvcpsgndp (VSX Vector Copy Sign Double-Precision)
142424aa412af1d8166cc11f39a6e721df49431d23618sewardj      {
142434aa412af1d8166cc11f39a6e721df49431d23618sewardj         UChar XA = ifieldRegXA( theInstr );
142444aa412af1d8166cc11f39a6e721df49431d23618sewardj         IRTemp frA = newTemp(Ity_I64);
142454aa412af1d8166cc11f39a6e721df49431d23618sewardj         IRTemp frB = newTemp(Ity_I64);
142464aa412af1d8166cc11f39a6e721df49431d23618sewardj         IRTemp frA2 = newTemp(Ity_I64);
142474aa412af1d8166cc11f39a6e721df49431d23618sewardj         IRTemp frB2 = newTemp(Ity_I64);
142484aa412af1d8166cc11f39a6e721df49431d23618sewardj         assign(frA,  unop(Iop_V128HIto64, getVSReg( XA )));
142494aa412af1d8166cc11f39a6e721df49431d23618sewardj         assign(frB,  unop(Iop_V128HIto64, getVSReg( XB )));
142504aa412af1d8166cc11f39a6e721df49431d23618sewardj         assign(frA2, unop(Iop_V128to64, getVSReg( XA )));
142514aa412af1d8166cc11f39a6e721df49431d23618sewardj         assign(frB2, unop(Iop_V128to64, getVSReg( XB )));
142524aa412af1d8166cc11f39a6e721df49431d23618sewardj
142534aa412af1d8166cc11f39a6e721df49431d23618sewardj         DIP("xvcpsgndp v%d,v%d,v%d\n", (UInt)XT, (UInt)XA, (UInt)XB);
142544aa412af1d8166cc11f39a6e721df49431d23618sewardj         putVSReg( XT,
142554aa412af1d8166cc11f39a6e721df49431d23618sewardj                   binop( Iop_64HLtoV128,
142564aa412af1d8166cc11f39a6e721df49431d23618sewardj                          binop( Iop_Or64,
142574aa412af1d8166cc11f39a6e721df49431d23618sewardj                                 binop( Iop_And64,
142584aa412af1d8166cc11f39a6e721df49431d23618sewardj                                        mkexpr( frA ),
142594aa412af1d8166cc11f39a6e721df49431d23618sewardj                                        mkU64( SIGN_BIT ) ),
142604aa412af1d8166cc11f39a6e721df49431d23618sewardj                                 binop( Iop_And64,
142614aa412af1d8166cc11f39a6e721df49431d23618sewardj                                        mkexpr( frB ),
142624aa412af1d8166cc11f39a6e721df49431d23618sewardj                                        mkU64( SIGN_MASK ) ) ),
142634aa412af1d8166cc11f39a6e721df49431d23618sewardj                          binop( Iop_Or64,
142644aa412af1d8166cc11f39a6e721df49431d23618sewardj                                 binop( Iop_And64,
142654aa412af1d8166cc11f39a6e721df49431d23618sewardj                                        mkexpr( frA2 ),
142664aa412af1d8166cc11f39a6e721df49431d23618sewardj                                        mkU64( SIGN_BIT ) ),
142674aa412af1d8166cc11f39a6e721df49431d23618sewardj                                 binop( Iop_And64,
142684aa412af1d8166cc11f39a6e721df49431d23618sewardj                                        mkexpr( frB2 ),
142694aa412af1d8166cc11f39a6e721df49431d23618sewardj                                        mkU64( SIGN_MASK ) ) ) ) );
142704aa412af1d8166cc11f39a6e721df49431d23618sewardj         break;
142714aa412af1d8166cc11f39a6e721df49431d23618sewardj      }
142724aa412af1d8166cc11f39a6e721df49431d23618sewardj      case 0x340: // xvcpsgnsp
142734aa412af1d8166cc11f39a6e721df49431d23618sewardj      {
142744aa412af1d8166cc11f39a6e721df49431d23618sewardj         UChar XA = ifieldRegXA( theInstr );
142754aa412af1d8166cc11f39a6e721df49431d23618sewardj         IRTemp a3_I64, a2_I64, a1_I64, a0_I64;
142764aa412af1d8166cc11f39a6e721df49431d23618sewardj         IRTemp b3_I64, b2_I64, b1_I64, b0_I64;
142774aa412af1d8166cc11f39a6e721df49431d23618sewardj         IRTemp resHi = newTemp(Ity_I64);
142784aa412af1d8166cc11f39a6e721df49431d23618sewardj         IRTemp resLo = newTemp(Ity_I64);
142794aa412af1d8166cc11f39a6e721df49431d23618sewardj
142804aa412af1d8166cc11f39a6e721df49431d23618sewardj         a3_I64 = a2_I64 = a1_I64 = a0_I64 = IRTemp_INVALID;
142814aa412af1d8166cc11f39a6e721df49431d23618sewardj         b3_I64 = b2_I64 = b1_I64 = b0_I64 = IRTemp_INVALID;
142824aa412af1d8166cc11f39a6e721df49431d23618sewardj         DIP("xvcpsgnsp v%d,v%d v%d\n",(UInt)XT, (UInt)XA, (UInt)XB);
142834aa412af1d8166cc11f39a6e721df49431d23618sewardj         breakV128to4x64U( getVSReg( XA ), &a3_I64, &a2_I64, &a1_I64, &a0_I64 );
142844aa412af1d8166cc11f39a6e721df49431d23618sewardj         breakV128to4x64U( getVSReg( XB ), &b3_I64, &b2_I64, &b1_I64, &b0_I64 );
142854aa412af1d8166cc11f39a6e721df49431d23618sewardj
142864aa412af1d8166cc11f39a6e721df49431d23618sewardj         assign( resHi,
142874aa412af1d8166cc11f39a6e721df49431d23618sewardj                 binop( Iop_32HLto64,
142884aa412af1d8166cc11f39a6e721df49431d23618sewardj                        binop( Iop_Or32,
142894aa412af1d8166cc11f39a6e721df49431d23618sewardj                               binop( Iop_And32,
142904aa412af1d8166cc11f39a6e721df49431d23618sewardj                                      unop(Iop_64to32, mkexpr( a3_I64 ) ),
142914aa412af1d8166cc11f39a6e721df49431d23618sewardj                                      mkU32( SIGN_BIT32 ) ),
142924aa412af1d8166cc11f39a6e721df49431d23618sewardj                               binop( Iop_And32,
142934aa412af1d8166cc11f39a6e721df49431d23618sewardj                                      unop(Iop_64to32, mkexpr( b3_I64 ) ),
142944aa412af1d8166cc11f39a6e721df49431d23618sewardj                                      mkU32( SIGN_MASK32) ) ),
142954aa412af1d8166cc11f39a6e721df49431d23618sewardj
142964aa412af1d8166cc11f39a6e721df49431d23618sewardj                        binop( Iop_Or32,
142974aa412af1d8166cc11f39a6e721df49431d23618sewardj                               binop( Iop_And32,
142984aa412af1d8166cc11f39a6e721df49431d23618sewardj                                      unop(Iop_64to32, mkexpr( a2_I64 ) ),
142994aa412af1d8166cc11f39a6e721df49431d23618sewardj                                      mkU32( SIGN_BIT32 ) ),
143004aa412af1d8166cc11f39a6e721df49431d23618sewardj                               binop( Iop_And32,
143014aa412af1d8166cc11f39a6e721df49431d23618sewardj                                      unop(Iop_64to32, mkexpr( b2_I64 ) ),
143024aa412af1d8166cc11f39a6e721df49431d23618sewardj                                      mkU32( SIGN_MASK32 ) ) ) ) );
143034aa412af1d8166cc11f39a6e721df49431d23618sewardj         assign( resLo,
143044aa412af1d8166cc11f39a6e721df49431d23618sewardj                 binop( Iop_32HLto64,
143054aa412af1d8166cc11f39a6e721df49431d23618sewardj                        binop( Iop_Or32,
143064aa412af1d8166cc11f39a6e721df49431d23618sewardj                               binop( Iop_And32,
143074aa412af1d8166cc11f39a6e721df49431d23618sewardj                                      unop(Iop_64to32, mkexpr( a1_I64 ) ),
143084aa412af1d8166cc11f39a6e721df49431d23618sewardj                                      mkU32( SIGN_BIT32 ) ),
143094aa412af1d8166cc11f39a6e721df49431d23618sewardj                               binop( Iop_And32,
143104aa412af1d8166cc11f39a6e721df49431d23618sewardj                                      unop(Iop_64to32, mkexpr( b1_I64 ) ),
143114aa412af1d8166cc11f39a6e721df49431d23618sewardj                                      mkU32( SIGN_MASK32 ) ) ),
143124aa412af1d8166cc11f39a6e721df49431d23618sewardj
143134aa412af1d8166cc11f39a6e721df49431d23618sewardj                        binop( Iop_Or32,
143144aa412af1d8166cc11f39a6e721df49431d23618sewardj                               binop( Iop_And32,
143154aa412af1d8166cc11f39a6e721df49431d23618sewardj                                      unop(Iop_64to32, mkexpr( a0_I64 ) ),
143164aa412af1d8166cc11f39a6e721df49431d23618sewardj                                      mkU32( SIGN_BIT32 ) ),
143174aa412af1d8166cc11f39a6e721df49431d23618sewardj                               binop( Iop_And32,
143184aa412af1d8166cc11f39a6e721df49431d23618sewardj                                      unop(Iop_64to32, mkexpr( b0_I64 ) ),
143194aa412af1d8166cc11f39a6e721df49431d23618sewardj                                      mkU32( SIGN_MASK32 ) ) ) ) );
143204aa412af1d8166cc11f39a6e721df49431d23618sewardj         putVSReg( XT, binop( Iop_64HLtoV128, mkexpr( resHi ), mkexpr( resLo ) ) );
143214aa412af1d8166cc11f39a6e721df49431d23618sewardj         break;
143224aa412af1d8166cc11f39a6e721df49431d23618sewardj      }
14323e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj      case 0x3B2: // xvabsdp (VSX Vector Absolute Value Double-Precision)
14324e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj      case 0x3D2: // xvnabsdp VSX Vector Negative Absolute Value Double-Precision)
14325e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj      {
14326e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj         IRTemp frB = newTemp(Ity_F64);
14327e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj         IRTemp frB2 = newTemp(Ity_F64);
14328e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj         IRTemp abs_resultHi = newTemp(Ity_F64);
14329e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj         IRTemp abs_resultLo = newTemp(Ity_F64);
14330e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj         Bool make_negative = (opc2 == 0x3D2) ? True : False;
14331e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj         assign(frB,  unop(Iop_ReinterpI64asF64, unop(Iop_V128HIto64, getVSReg( XB ))));
14332e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj         assign(frB2, unop(Iop_ReinterpI64asF64, unop(Iop_V128to64, getVSReg(XB))));
14333e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj
14334e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj         DIP("xv%sabsdp v%d,v%d\n", make_negative ? "n" : "", (UInt)XT, (UInt)XB);
14335e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj         if (make_negative) {
14336e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj            assign(abs_resultHi, unop( Iop_NegF64, unop( Iop_AbsF64, mkexpr( frB ) ) ) );
14337e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj            assign(abs_resultLo, unop( Iop_NegF64, unop( Iop_AbsF64, mkexpr( frB2 ) ) ) );
14338e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj
14339e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj         } else {
14340e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj            assign(abs_resultHi, unop( Iop_AbsF64, mkexpr( frB ) ) );
14341e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj            assign(abs_resultLo, unop( Iop_AbsF64, mkexpr( frB2 ) ) );
14342e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj         }
14343e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj         putVSReg( XT, binop( Iop_64HLtoV128,
14344e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj                              unop( Iop_ReinterpF64asI64, mkexpr( abs_resultHi ) ),
14345e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj                              unop( Iop_ReinterpF64asI64, mkexpr( abs_resultLo ) ) ) );
14346e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj         break;
14347e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj      }
14348e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj      case 0x332: // xvabssp (VSX Vector Absolute Value Single-Precision)
14349e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj      case 0x352: // xvnabssp (VSX Vector Negative Absolute Value Single-Precision)
14350e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj      {
14351e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj         /*
14352e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj          * The Iop_AbsF32 IRop is not implemented for ppc64 since, up until introduction
14353e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj          * of xvabssp, there has not been an abs(sp) type of instruction.  But since emulation
14354e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj          * of this function is so easy using shifts, I choose to emulate this instruction that
14355e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj          * way versus a native instruction method of implementation.
14356e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj          */
14357e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj         Bool make_negative = (opc2 == 0x352) ? True : False;
14358e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj         IRTemp shiftVector = newTemp(Ity_V128);
14359e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj         IRTemp absVal_vector = newTemp(Ity_V128);
14360e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj         assign( shiftVector,
14361e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj                 binop( Iop_64HLtoV128,
14362e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj                        binop( Iop_32HLto64, mkU32( 1 ), mkU32( 1 ) ),
14363e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj                        binop( Iop_32HLto64, mkU32( 1 ), mkU32( 1 ) ) ) );
14364e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj         assign( absVal_vector,
14365e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj                   binop( Iop_Shr32x4,
14366e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj                          binop( Iop_Shl32x4,
14367e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj                                 getVSReg( XB ),
14368e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj                                 mkexpr( shiftVector ) ),
14369e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj                          mkexpr( shiftVector ) ) );
14370e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj         if (make_negative) {
14371e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj            IRTemp signBit_vector = newTemp(Ity_V128);
14372e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj            assign( signBit_vector,
14373e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj                    binop( Iop_64HLtoV128,
14374e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj                           binop( Iop_32HLto64,
14375e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj                                  mkU32( 0x80000000 ),
14376e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj                                  mkU32( 0x80000000 ) ),
14377e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj                           binop( Iop_32HLto64,
14378e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj                                  mkU32( 0x80000000 ),
14379e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj                                  mkU32( 0x80000000 ) ) ) );
14380e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj            putVSReg( XT,
14381e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj                      binop( Iop_OrV128,
14382e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj                             mkexpr( absVal_vector ),
14383e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj                             mkexpr( signBit_vector ) ) );
14384e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj         } else {
14385e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj            putVSReg( XT, mkexpr( absVal_vector ) );
14386e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj         }
14387e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj         break;
14388e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj      }
14389e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj      case 0x3F2: // xvnegdp (VSX Vector Negate Double-Precision)
14390e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj      {
14391e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj         IRTemp frB = newTemp(Ity_F64);
14392e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj         IRTemp frB2 = newTemp(Ity_F64);
14393e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj         assign(frB,  unop(Iop_ReinterpI64asF64, unop(Iop_V128HIto64, getVSReg( XB ))));
14394e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj         assign(frB2, unop(Iop_ReinterpI64asF64, unop(Iop_V128to64, getVSReg(XB))));
14395e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj         DIP("xvnegdp v%d,v%d\n",  (UInt)XT, (UInt)XB);
14396e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj         putVSReg( XT,
14397e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj                   binop( Iop_64HLtoV128,
14398e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj                          unop( Iop_ReinterpF64asI64,
14399e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj                                unop( Iop_NegF64, mkexpr( frB ) ) ),
14400e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj                          unop( Iop_ReinterpF64asI64,
14401e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj                                unop( Iop_NegF64, mkexpr( frB2 ) ) ) ) );
14402e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj         break;
14403e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj      }
14404e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj      case 0x192: // xvrdpi  (VSX Vector Round to Double-Precision Integer using round toward Nearest Away)
14405e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj      case 0x1D6: // xvrdpic (VSX Vector Round to Double-Precision Integer using Current rounding mode)
14406e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj      case 0x1F2: // xvrdpim (VSX Vector Round to Double-Precision Integer using round toward -Infinity)
14407e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj      case 0x1D2: // xvrdpip (VSX Vector Round to Double-Precision Integer using round toward +Infinity)
14408e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj      case 0x1B2: // xvrdpiz (VSX Vector Round to Double-Precision Integer using round toward Zero)
14409e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj      {
14410e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj         IRTemp frBHi_I64 = newTemp(Ity_I64);
14411e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj         IRTemp frBLo_I64 = newTemp(Ity_I64);
14412e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj         IRExpr * frD_fp_roundHi = NULL;
14413e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj         IRExpr * frD_fp_roundLo = NULL;
14414e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj
14415e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj         assign( frBHi_I64, unop( Iop_V128HIto64, getVSReg( XB ) ) );
144169884af0b3cfe935b8fab54231f394fe4ee2d7ebccarll         frD_fp_roundHi = _do_vsx_fp_roundToInt(frBHi_I64, opc2);
14417e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj         assign( frBLo_I64, unop( Iop_V128to64, getVSReg( XB ) ) );
144189884af0b3cfe935b8fab54231f394fe4ee2d7ebccarll         frD_fp_roundLo = _do_vsx_fp_roundToInt(frBLo_I64, opc2);
14419e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj
144209884af0b3cfe935b8fab54231f394fe4ee2d7ebccarll         DIP("xvrdpi%s v%d,v%d\n", _get_vsx_rdpi_suffix(opc2), (UInt)XT, (UInt)XB);
14421e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj         putVSReg( XT,
14422e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj                   binop( Iop_64HLtoV128,
14423e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj                          unop( Iop_ReinterpF64asI64, frD_fp_roundHi ),
14424e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj                          unop( Iop_ReinterpF64asI64, frD_fp_roundLo ) ) );
14425e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj         break;
14426e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj      }
14427e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj      case 0x112: // xvrspi  (VSX Vector Round to Single-Precision Integer using round toward Nearest Away)
14428e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj      case 0x156: // xvrspic (VSX Vector Round to SinglePrecision Integer using Current rounding mode)
14429e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj      case 0x172: // xvrspim (VSX Vector Round to SinglePrecision Integer using round toward -Infinity)
14430e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj      case 0x152: // xvrspip (VSX Vector Round to SinglePrecision Integer using round toward +Infinity)
14431e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj      case 0x132: // xvrspiz (VSX Vector Round to SinglePrecision Integer using round toward Zero)
14432e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj      {
1443355085f8680acc89d727e321f3b34cae1a8c4093aflorian         const HChar * insn_suffix = NULL;
14434e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj         IROp op;
14435e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj         if (opc2 != 0x156) {
14436e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj            // Use pre-defined IRop's for vrfi{m|n|p|z}
14437e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj            switch (opc2) {
14438e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj               case 0x112:
14439e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj                  insn_suffix = "";
14440e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj                  op = Iop_RoundF32x4_RN;
14441e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj                  break;
14442e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj               case 0x172:
14443e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj                  insn_suffix = "m";
14444e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj                  op = Iop_RoundF32x4_RM;
14445e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj                  break;
14446e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj               case 0x152:
14447e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj                  insn_suffix = "p";
14448e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj                  op = Iop_RoundF32x4_RP;
14449e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj                  break;
14450e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj               case 0x132:
14451e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj                  insn_suffix = "z";
14452e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj                  op = Iop_RoundF32x4_RZ;
14453e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj                  break;
14454e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj
14455e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj               default:
144569884af0b3cfe935b8fab54231f394fe4ee2d7ebccarll                  vex_printf("Unrecognized opcode %x\n", opc2);
144579884af0b3cfe935b8fab54231f394fe4ee2d7ebccarll                  vpanic("dis_vxv_misc(ppc)(vrspi<x>)(opc2)\n");
14458e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj            }
14459e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj            DIP("xvrspi%s v%d,v%d\n", insn_suffix, (UInt)XT, (UInt)XB);
14460e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj            putVSReg( XT, unop( op, getVSReg(XB) ) );
14461e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj         } else {
14462e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj            // Handle xvrspic.  Unfortunately there is no corresponding "vfric" instruction.
14463e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj            IRExpr * frD_fp_roundb3, * frD_fp_roundb2, * frD_fp_roundb1, * frD_fp_roundb0;
14464e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj            IRTemp b3_F64, b2_F64, b1_F64, b0_F64;
14465e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj            IRTemp b3_I64 = newTemp(Ity_I64);
14466e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj            IRTemp b2_I64 = newTemp(Ity_I64);
14467e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj            IRTemp b1_I64 = newTemp(Ity_I64);
14468e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj            IRTemp b0_I64 = newTemp(Ity_I64);
14469e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj
14470e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj            b3_F64 = b2_F64 = b1_F64 = b0_F64 = IRTemp_INVALID;
14471e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj            frD_fp_roundb3 = frD_fp_roundb2 = frD_fp_roundb1 = frD_fp_roundb0 = NULL;
14472e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj            breakV128to4xF64( getVSReg(XB), &b3_F64, &b2_F64, &b1_F64, &b0_F64);
14473e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj            assign(b3_I64, unop(Iop_ReinterpF64asI64, mkexpr(b3_F64)));
14474e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj            assign(b2_I64, unop(Iop_ReinterpF64asI64, mkexpr(b2_F64)));
14475e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj            assign(b1_I64, unop(Iop_ReinterpF64asI64, mkexpr(b1_F64)));
14476e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj            assign(b0_I64, unop(Iop_ReinterpF64asI64, mkexpr(b0_F64)));
14477e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj            frD_fp_roundb3 = unop(Iop_TruncF64asF32,
144789884af0b3cfe935b8fab54231f394fe4ee2d7ebccarll                                  _do_vsx_fp_roundToInt(b3_I64, opc2));
14479e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj            frD_fp_roundb2 = unop(Iop_TruncF64asF32,
144809884af0b3cfe935b8fab54231f394fe4ee2d7ebccarll                                  _do_vsx_fp_roundToInt(b2_I64, opc2));
14481e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj            frD_fp_roundb1 = unop(Iop_TruncF64asF32,
144829884af0b3cfe935b8fab54231f394fe4ee2d7ebccarll                                  _do_vsx_fp_roundToInt(b1_I64, opc2));
14483e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj            frD_fp_roundb0 = unop(Iop_TruncF64asF32,
144849884af0b3cfe935b8fab54231f394fe4ee2d7ebccarll                                  _do_vsx_fp_roundToInt(b0_I64, opc2));
14485e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj            DIP("xvrspic v%d,v%d\n", (UInt)XT, (UInt)XB);
14486e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj            putVSReg( XT,
14487e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj                      binop( Iop_64HLtoV128,
14488e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj                             binop( Iop_32HLto64,
14489e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj                                    unop( Iop_ReinterpF32asI32, frD_fp_roundb3 ),
14490e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj                                    unop( Iop_ReinterpF32asI32, frD_fp_roundb2 ) ),
14491e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj                             binop( Iop_32HLto64,
14492e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj                                    unop( Iop_ReinterpF32asI32, frD_fp_roundb1 ),
14493e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj                                    unop( Iop_ReinterpF32asI32, frD_fp_roundb0 ) ) ) );
14494e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj         }
14495e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj         break;
14496e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj      }
144974aa412af1d8166cc11f39a6e721df49431d23618sewardj
144984aa412af1d8166cc11f39a6e721df49431d23618sewardj      default:
144994aa412af1d8166cc11f39a6e721df49431d23618sewardj         vex_printf( "dis_vxv_misc(ppc)(opc2)\n" );
145004aa412af1d8166cc11f39a6e721df49431d23618sewardj         return False;
145014aa412af1d8166cc11f39a6e721df49431d23618sewardj   }
145024aa412af1d8166cc11f39a6e721df49431d23618sewardj   return True;
145034aa412af1d8166cc11f39a6e721df49431d23618sewardj}
145044aa412af1d8166cc11f39a6e721df49431d23618sewardj
145054aa412af1d8166cc11f39a6e721df49431d23618sewardj
145064aa412af1d8166cc11f39a6e721df49431d23618sewardj/*
1450766d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj * VSX Scalar Floating Point Arithmetic Instructions
1450866d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj */
1450966d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardjstatic Bool
145104aa412af1d8166cc11f39a6e721df49431d23618sewardjdis_vxs_arith ( UInt theInstr, UInt opc2 )
1451166d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj{
1451266d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj   /* XX3-Form */
1451366d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj   UChar opc1 = ifieldOPC( theInstr );
1451466d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj   UChar XT = ifieldRegXT( theInstr );
1451566d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj   UChar XA = ifieldRegXA( theInstr );
1451666d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj   UChar XB = ifieldRegXB( theInstr );
1451766d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj   IRExpr* rm = get_IR_roundingmode();
1451866d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj   IRTemp frA = newTemp(Ity_F64);
1451966d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj   IRTemp frB = newTemp(Ity_F64);
1452066d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj
1452166d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj   if (opc1 != 0x3C) {
145224aa412af1d8166cc11f39a6e721df49431d23618sewardj      vex_printf( "dis_vxs_arith(ppc)(instr)\n" );
1452366d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj      return False;
1452466d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj   }
1452566d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj
1452666d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj   assign(frA, unop(Iop_ReinterpI64asF64, unop(Iop_V128HIto64, getVSReg( XA ))));
1452766d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj   assign(frB, unop(Iop_ReinterpI64asF64, unop(Iop_V128HIto64, getVSReg( XB ))));
1452866d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj
1452966d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj   /* For all the VSX sclar arithmetic instructions, the contents of doubleword element 1
1453066d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj    * of VSX[XT] are undefined after the operation; therefore, we can simply set
1453166d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj    * element to zero where it makes sense to do so.
1453266d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj    */
1453366d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj   switch (opc2) {
145346c758b64a77c254065ab7450576bbd3a0b583595carll      case 0x000: // xsaddsp  (VSX Scalar Add Single-Precision)
145356c758b64a77c254065ab7450576bbd3a0b583595carll         DIP("xsaddsp v%d,v%d,v%d\n", (UInt)XT, (UInt)XA, (UInt)XB);
145366c758b64a77c254065ab7450576bbd3a0b583595carll         putVSReg( XT, binop( Iop_64HLtoV128,
145376c758b64a77c254065ab7450576bbd3a0b583595carll                              unop( Iop_ReinterpF64asI64,
145386c758b64a77c254065ab7450576bbd3a0b583595carll                                    binop( Iop_RoundF64toF32, rm,
145396c758b64a77c254065ab7450576bbd3a0b583595carll                                           triop( Iop_AddF64, rm,
145406c758b64a77c254065ab7450576bbd3a0b583595carll                                                  mkexpr( frA ),
145416c758b64a77c254065ab7450576bbd3a0b583595carll                                                  mkexpr( frB ) ) ) ),
145426c758b64a77c254065ab7450576bbd3a0b583595carll                              mkU64( 0 ) ) );
145436c758b64a77c254065ab7450576bbd3a0b583595carll         break;
145446c758b64a77c254065ab7450576bbd3a0b583595carll      case 0x020: // xssubsp  (VSX Scalar Subtract Single-Precision)
145456c758b64a77c254065ab7450576bbd3a0b583595carll         DIP("xssubsp v%d,v%d,v%d\n", (UInt)XT, (UInt)XA, (UInt)XB);
145466c758b64a77c254065ab7450576bbd3a0b583595carll         putVSReg( XT, binop( Iop_64HLtoV128,
145476c758b64a77c254065ab7450576bbd3a0b583595carll                              unop( Iop_ReinterpF64asI64,
145486c758b64a77c254065ab7450576bbd3a0b583595carll                                    binop( Iop_RoundF64toF32, rm,
145496c758b64a77c254065ab7450576bbd3a0b583595carll                                           triop( Iop_SubF64, rm,
145506c758b64a77c254065ab7450576bbd3a0b583595carll                                                  mkexpr( frA ),
145516c758b64a77c254065ab7450576bbd3a0b583595carll                                                  mkexpr( frB ) ) ) ),
145526c758b64a77c254065ab7450576bbd3a0b583595carll                              mkU64( 0 ) ) );
145536c758b64a77c254065ab7450576bbd3a0b583595carll         break;
1455466d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj      case 0x080: // xsadddp (VSX scalar add double-precision)
1455566d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj         DIP("xsadddp v%d,v%d,v%d\n", (UInt)XT, (UInt)XA, (UInt)XB);
1455666d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj         putVSReg( XT, binop( Iop_64HLtoV128, unop( Iop_ReinterpF64asI64,
1455766d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj                                                    triop( Iop_AddF64, rm,
1455866d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj                                                           mkexpr( frA ),
1455966d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj                                                           mkexpr( frB ) ) ),
1456066d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj                              mkU64( 0 ) ) );
1456166d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj         break;
145626c758b64a77c254065ab7450576bbd3a0b583595carll      case 0x060: // xsdivsp (VSX scalar divide single-precision)
145636c758b64a77c254065ab7450576bbd3a0b583595carll         DIP("xsdivsp v%d,v%d,v%d\n", (UInt)XT, (UInt)XA, (UInt)XB);
145646c758b64a77c254065ab7450576bbd3a0b583595carll         putVSReg( XT, binop( Iop_64HLtoV128,
145656c758b64a77c254065ab7450576bbd3a0b583595carll                              unop( Iop_ReinterpF64asI64,
145666c758b64a77c254065ab7450576bbd3a0b583595carll                                    binop( Iop_RoundF64toF32, rm,
145676c758b64a77c254065ab7450576bbd3a0b583595carll                                           triop( Iop_DivF64, rm,
145686c758b64a77c254065ab7450576bbd3a0b583595carll                                                  mkexpr( frA ),
145696c758b64a77c254065ab7450576bbd3a0b583595carll                                                  mkexpr( frB ) ) ) ),
145706c758b64a77c254065ab7450576bbd3a0b583595carll                               mkU64( 0 ) ) );
145716c758b64a77c254065ab7450576bbd3a0b583595carll         break;
1457266d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj      case 0x0E0: // xsdivdp (VSX scalar divide double-precision)
1457366d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj         DIP("xsdivdp v%d,v%d,v%d\n", (UInt)XT, (UInt)XA, (UInt)XB);
1457466d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj         putVSReg( XT, binop( Iop_64HLtoV128, unop( Iop_ReinterpF64asI64,
1457566d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj                                                    triop( Iop_DivF64, rm,
1457666d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj                                                           mkexpr( frA ),
1457766d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj                                                           mkexpr( frB ) ) ),
1457866d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj                              mkU64( 0 ) ) );
1457966d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj         break;
145806c758b64a77c254065ab7450576bbd3a0b583595carll      case 0x004: case 0x024: /* xsmaddasp, xsmaddmsp (VSX scalar multiply-add
145816c758b64a77c254065ab7450576bbd3a0b583595carll                               * single-precision)
145826c758b64a77c254065ab7450576bbd3a0b583595carll                               */
145836c758b64a77c254065ab7450576bbd3a0b583595carll      {
145846c758b64a77c254065ab7450576bbd3a0b583595carll         IRTemp frT = newTemp(Ity_F64);
145856c758b64a77c254065ab7450576bbd3a0b583595carll         Bool mdp = opc2 == 0x024;
145866c758b64a77c254065ab7450576bbd3a0b583595carll         DIP("xsmadd%ssp v%d,v%d,v%d\n", mdp ? "m" : "a", (UInt)XT, (UInt)XA, (UInt)XB);
145876c758b64a77c254065ab7450576bbd3a0b583595carll         assign( frT, unop( Iop_ReinterpI64asF64, unop( Iop_V128HIto64,
145886c758b64a77c254065ab7450576bbd3a0b583595carll                                                        getVSReg( XT ) ) ) );
145896c758b64a77c254065ab7450576bbd3a0b583595carll         putVSReg( XT,
145906c758b64a77c254065ab7450576bbd3a0b583595carll                   binop( Iop_64HLtoV128,
145916c758b64a77c254065ab7450576bbd3a0b583595carll                          unop( Iop_ReinterpF64asI64,
145926c758b64a77c254065ab7450576bbd3a0b583595carll                                binop( Iop_RoundF64toF32, rm,
145936c758b64a77c254065ab7450576bbd3a0b583595carll                                       qop( Iop_MAddF64, rm,
145946c758b64a77c254065ab7450576bbd3a0b583595carll                                            mkexpr( frA ),
145956c758b64a77c254065ab7450576bbd3a0b583595carll                                            mkexpr( mdp ? frT : frB ),
145966c758b64a77c254065ab7450576bbd3a0b583595carll                                            mkexpr( mdp ? frB : frT ) ) ) ),
145976c758b64a77c254065ab7450576bbd3a0b583595carll                          mkU64( 0 ) ) );
145986c758b64a77c254065ab7450576bbd3a0b583595carll         break;
145996c758b64a77c254065ab7450576bbd3a0b583595carll      }
1460066d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj      case 0x084: case 0x0A4: // xsmaddadp, xsmaddmdp (VSX scalar multiply-add double-precision)
1460166d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj      {
1460266d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj         IRTemp frT = newTemp(Ity_F64);
1460366d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj         Bool mdp = opc2 == 0x0A4;
1460466d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj         DIP("xsmadd%sdp v%d,v%d,v%d\n", mdp ? "m" : "a", (UInt)XT, (UInt)XA, (UInt)XB);
1460566d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj         assign( frT, unop( Iop_ReinterpI64asF64, unop( Iop_V128HIto64,
1460666d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj                                                        getVSReg( XT ) ) ) );
1460766d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj         putVSReg( XT, binop( Iop_64HLtoV128, unop( Iop_ReinterpF64asI64,
1460866d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj                                                    qop( Iop_MAddF64, rm,
1460966d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj                                                         mkexpr( frA ),
1461066d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj                                                         mkexpr( mdp ? frT : frB ),
1461166d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj                                                         mkexpr( mdp ? frB : frT ) ) ),
1461266d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj                              mkU64( 0 ) ) );
1461366d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj         break;
1461466d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj      }
146156c758b64a77c254065ab7450576bbd3a0b583595carll      case 0x044: case 0x064: /* xsmsubasp, xsmsubmsp (VSX scalar
146166c758b64a77c254065ab7450576bbd3a0b583595carll                               * multiply-subtract single-precision)
146176c758b64a77c254065ab7450576bbd3a0b583595carll			       */
146186c758b64a77c254065ab7450576bbd3a0b583595carll      {
146196c758b64a77c254065ab7450576bbd3a0b583595carll         IRTemp frT = newTemp(Ity_F64);
146206c758b64a77c254065ab7450576bbd3a0b583595carll         Bool mdp = opc2 == 0x064;
146216c758b64a77c254065ab7450576bbd3a0b583595carll         DIP("xsmsub%ssp v%d,v%d,v%d\n", mdp ? "m" : "a", (UInt)XT, (UInt)XA, (UInt)XB);
146226c758b64a77c254065ab7450576bbd3a0b583595carll         assign( frT, unop( Iop_ReinterpI64asF64, unop( Iop_V128HIto64,
146236c758b64a77c254065ab7450576bbd3a0b583595carll                                                        getVSReg( XT ) ) ) );
146246c758b64a77c254065ab7450576bbd3a0b583595carll         putVSReg( XT,
146256c758b64a77c254065ab7450576bbd3a0b583595carll                   binop( Iop_64HLtoV128,
146266c758b64a77c254065ab7450576bbd3a0b583595carll                          unop( Iop_ReinterpF64asI64,
146276c758b64a77c254065ab7450576bbd3a0b583595carll                                binop( Iop_RoundF64toF32, rm,
146286c758b64a77c254065ab7450576bbd3a0b583595carll                                       qop( Iop_MSubF64, rm,
146296c758b64a77c254065ab7450576bbd3a0b583595carll                                            mkexpr( frA ),
146306c758b64a77c254065ab7450576bbd3a0b583595carll                                            mkexpr( mdp ? frT : frB ),
146316c758b64a77c254065ab7450576bbd3a0b583595carll                                            mkexpr( mdp ? frB : frT ) ) ) ),
146326c758b64a77c254065ab7450576bbd3a0b583595carll                          mkU64( 0 ) ) );
146336c758b64a77c254065ab7450576bbd3a0b583595carll         break;
146346c758b64a77c254065ab7450576bbd3a0b583595carll      }
1463566d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj      case 0x0C4: case 0x0E4: // xsmsubadp, xsmsubmdp (VSX scalar multiply-subtract double-precision)
1463666d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj      {
1463766d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj         IRTemp frT = newTemp(Ity_F64);
1463866d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj         Bool mdp = opc2 == 0x0E4;
1463966d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj         DIP("xsmsub%sdp v%d,v%d,v%d\n", mdp ? "m" : "a", (UInt)XT, (UInt)XA, (UInt)XB);
1464066d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj         assign( frT, unop( Iop_ReinterpI64asF64, unop( Iop_V128HIto64,
1464166d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj                                                        getVSReg( XT ) ) ) );
1464266d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj         putVSReg( XT, binop( Iop_64HLtoV128, unop( Iop_ReinterpF64asI64,
1464366d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj                                                    qop( Iop_MSubF64, rm,
1464466d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj                                                         mkexpr( frA ),
1464566d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj                                                         mkexpr( mdp ? frT : frB ),
1464666d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj                                                         mkexpr( mdp ? frB : frT ) ) ),
1464766d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj                              mkU64( 0 ) ) );
1464866d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj         break;
1464966d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj      }
1465066d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj      case 0x284: case 0x2A4: // xsnmaddadp, xsnmaddmdp (VSX scalar multiply-add double-precision)
1465166d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj      {
1465266d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj         /* TODO: mpj -- Naturally, I expected to be able to leverage the implementation
1465366d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj          * of fnmadd and use pretty much the same code. However, that code has a bug in the
1465466d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj          * way it blindly negates the signbit, even if the floating point result is a NaN.
1465566d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj          * So, the TODO is to fix fnmadd (which I'll do in a different patch).
146562bcdd653612c726da0b7203b579b8f6114703be4sewardj          * FIXED 7/1/2012: carll fnmadd and fnmsubs fixed to not negate sign
146572bcdd653612c726da0b7203b579b8f6114703be4sewardj          * bit for NaN result.
1465866d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj          */
1465966d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj         Bool mdp = opc2 == 0x2A4;
1466066d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj         IRTemp frT = newTemp(Ity_F64);
1466166d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj         IRTemp maddResult = newTemp(Ity_I64);
1466266d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj
1466366d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj         DIP("xsnmadd%sdp v%d,v%d,v%d\n", mdp ? "m" : "a", (UInt)XT, (UInt)XA, (UInt)XB);
1466466d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj         assign( frT, unop( Iop_ReinterpI64asF64, unop( Iop_V128HIto64,
1466566d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj                                                        getVSReg( XT ) ) ) );
1466666d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj         assign( maddResult, unop( Iop_ReinterpF64asI64, qop( Iop_MAddF64, rm,
1466766d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj                                                              mkexpr( frA ),
1466866d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj                                                              mkexpr( mdp ? frT : frB ),
1466966d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj                                                              mkexpr( mdp ? frB : frT ) ) ) );
146704aa412af1d8166cc11f39a6e721df49431d23618sewardj
146714aa412af1d8166cc11f39a6e721df49431d23618sewardj         putVSReg( XT, binop( Iop_64HLtoV128, mkexpr( getNegatedResult(maddResult) ),
1467266d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj                              mkU64( 0 ) ) );
1467366d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj         break;
1467466d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj      }
146756c758b64a77c254065ab7450576bbd3a0b583595carll      case 0x204: case 0x224: /* xsnmaddasp, xsnmaddmsp (VSX scalar
146766c758b64a77c254065ab7450576bbd3a0b583595carll                               * multiply-add single-precision)
146776c758b64a77c254065ab7450576bbd3a0b583595carll                               */
146786c758b64a77c254065ab7450576bbd3a0b583595carll      {
146796c758b64a77c254065ab7450576bbd3a0b583595carll         Bool mdp = opc2 == 0x224;
146806c758b64a77c254065ab7450576bbd3a0b583595carll         IRTemp frT = newTemp(Ity_F64);
146816c758b64a77c254065ab7450576bbd3a0b583595carll         IRTemp maddResult = newTemp(Ity_I64);
146826c758b64a77c254065ab7450576bbd3a0b583595carll
146836c758b64a77c254065ab7450576bbd3a0b583595carll         DIP("xsnmadd%ssp v%d,v%d,v%d\n", mdp ? "m" : "a", (UInt)XT, (UInt)XA, (UInt)XB);
146846c758b64a77c254065ab7450576bbd3a0b583595carll         assign( frT, unop( Iop_ReinterpI64asF64, unop( Iop_V128HIto64,
146856c758b64a77c254065ab7450576bbd3a0b583595carll                                                        getVSReg( XT ) ) ) );
146866c758b64a77c254065ab7450576bbd3a0b583595carll         assign( maddResult,
146876c758b64a77c254065ab7450576bbd3a0b583595carll                 unop( Iop_ReinterpF64asI64,
146886c758b64a77c254065ab7450576bbd3a0b583595carll                       binop( Iop_RoundF64toF32, rm,
146896c758b64a77c254065ab7450576bbd3a0b583595carll                              qop( Iop_MAddF64, rm,
146906c758b64a77c254065ab7450576bbd3a0b583595carll                                   mkexpr( frA ),
146916c758b64a77c254065ab7450576bbd3a0b583595carll                                   mkexpr( mdp ? frT : frB ),
146926c758b64a77c254065ab7450576bbd3a0b583595carll                                   mkexpr( mdp ? frB : frT ) ) ) ) );
146936c758b64a77c254065ab7450576bbd3a0b583595carll
146946c758b64a77c254065ab7450576bbd3a0b583595carll         putVSReg( XT, binop( Iop_64HLtoV128,
146956c758b64a77c254065ab7450576bbd3a0b583595carll                              mkexpr( getNegatedResult(maddResult) ),
146966c758b64a77c254065ab7450576bbd3a0b583595carll                              mkU64( 0 ) ) );
146976c758b64a77c254065ab7450576bbd3a0b583595carll         break;
146986c758b64a77c254065ab7450576bbd3a0b583595carll      }
146996c758b64a77c254065ab7450576bbd3a0b583595carll      case 0x244: case 0x264: /* xsnmsubasp, xsnmsubmsp (VSX Scalar Negative
147006c758b64a77c254065ab7450576bbd3a0b583595carll                               * Multiply-Subtract Single-Precision)
147016c758b64a77c254065ab7450576bbd3a0b583595carll                               */
147026c758b64a77c254065ab7450576bbd3a0b583595carll      {
147036c758b64a77c254065ab7450576bbd3a0b583595carll         IRTemp frT = newTemp(Ity_F64);
147046c758b64a77c254065ab7450576bbd3a0b583595carll         Bool mdp = opc2 == 0x264;
147056c758b64a77c254065ab7450576bbd3a0b583595carll         IRTemp msubResult = newTemp(Ity_I64);
147066c758b64a77c254065ab7450576bbd3a0b583595carll
147076c758b64a77c254065ab7450576bbd3a0b583595carll         DIP("xsnmsub%ssp v%d,v%d,v%d\n", mdp ? "m" : "a", (UInt)XT, (UInt)XA, (UInt)XB);
147086c758b64a77c254065ab7450576bbd3a0b583595carll         assign( frT, unop( Iop_ReinterpI64asF64, unop( Iop_V128HIto64,
147096c758b64a77c254065ab7450576bbd3a0b583595carll                                                        getVSReg( XT ) ) ) );
147106c758b64a77c254065ab7450576bbd3a0b583595carll         assign( msubResult,
147116c758b64a77c254065ab7450576bbd3a0b583595carll                 unop( Iop_ReinterpF64asI64,
147126c758b64a77c254065ab7450576bbd3a0b583595carll                       binop( Iop_RoundF64toF32, rm,
147136c758b64a77c254065ab7450576bbd3a0b583595carll                              qop( Iop_MSubF64, rm,
147146c758b64a77c254065ab7450576bbd3a0b583595carll                                   mkexpr( frA ),
147156c758b64a77c254065ab7450576bbd3a0b583595carll                                   mkexpr( mdp ? frT : frB ),
147166c758b64a77c254065ab7450576bbd3a0b583595carll                                   mkexpr( mdp ? frB : frT ) ) ) ) );
147176c758b64a77c254065ab7450576bbd3a0b583595carll
147186c758b64a77c254065ab7450576bbd3a0b583595carll         putVSReg( XT, binop( Iop_64HLtoV128,
147196c758b64a77c254065ab7450576bbd3a0b583595carll                              mkexpr( getNegatedResult(msubResult) ),
147206c758b64a77c254065ab7450576bbd3a0b583595carll                              mkU64( 0 ) ) );
147216c758b64a77c254065ab7450576bbd3a0b583595carll
147226c758b64a77c254065ab7450576bbd3a0b583595carll         break;
147236c758b64a77c254065ab7450576bbd3a0b583595carll      }
147246c758b64a77c254065ab7450576bbd3a0b583595carll
147254aa412af1d8166cc11f39a6e721df49431d23618sewardj      case 0x2C4: case 0x2E4: // xsnmsubadp, xsnmsubmdp (VSX Scalar Negative Multiply-Subtract Double-Precision)
147264aa412af1d8166cc11f39a6e721df49431d23618sewardj      {
147274aa412af1d8166cc11f39a6e721df49431d23618sewardj         IRTemp frT = newTemp(Ity_F64);
147284aa412af1d8166cc11f39a6e721df49431d23618sewardj         Bool mdp = opc2 == 0x2E4;
147294aa412af1d8166cc11f39a6e721df49431d23618sewardj         IRTemp msubResult = newTemp(Ity_I64);
147304aa412af1d8166cc11f39a6e721df49431d23618sewardj
147314aa412af1d8166cc11f39a6e721df49431d23618sewardj         DIP("xsnmsub%sdp v%d,v%d,v%d\n", mdp ? "m" : "a", (UInt)XT, (UInt)XA, (UInt)XB);
147324aa412af1d8166cc11f39a6e721df49431d23618sewardj         assign( frT, unop( Iop_ReinterpI64asF64, unop( Iop_V128HIto64,
147334aa412af1d8166cc11f39a6e721df49431d23618sewardj                                                        getVSReg( XT ) ) ) );
147344aa412af1d8166cc11f39a6e721df49431d23618sewardj         assign(msubResult, unop( Iop_ReinterpF64asI64,
147354aa412af1d8166cc11f39a6e721df49431d23618sewardj                                      qop( Iop_MSubF64,
147364aa412af1d8166cc11f39a6e721df49431d23618sewardj                                           rm,
147374aa412af1d8166cc11f39a6e721df49431d23618sewardj                                           mkexpr( frA ),
147384aa412af1d8166cc11f39a6e721df49431d23618sewardj                                           mkexpr( mdp ? frT : frB ),
147394aa412af1d8166cc11f39a6e721df49431d23618sewardj                                           mkexpr( mdp ? frB : frT ) ) ));
147404aa412af1d8166cc11f39a6e721df49431d23618sewardj
147414aa412af1d8166cc11f39a6e721df49431d23618sewardj         putVSReg( XT, binop( Iop_64HLtoV128, mkexpr( getNegatedResult(msubResult) ), mkU64( 0 ) ) );
147424aa412af1d8166cc11f39a6e721df49431d23618sewardj
147434aa412af1d8166cc11f39a6e721df49431d23618sewardj         break;
147444aa412af1d8166cc11f39a6e721df49431d23618sewardj      }
147454aa412af1d8166cc11f39a6e721df49431d23618sewardj
147466c758b64a77c254065ab7450576bbd3a0b583595carll      case 0x040: // xsmulsp (VSX Scalar Multiply Single-Precision)
147476c758b64a77c254065ab7450576bbd3a0b583595carll         DIP("xsmulsp v%d,v%d,v%d\n", (UInt)XT, (UInt)XA, (UInt)XB);
147486c758b64a77c254065ab7450576bbd3a0b583595carll         putVSReg( XT, binop( Iop_64HLtoV128,
147496c758b64a77c254065ab7450576bbd3a0b583595carll                              unop( Iop_ReinterpF64asI64,
147506c758b64a77c254065ab7450576bbd3a0b583595carll                                    binop( Iop_RoundF64toF32, rm,
147516c758b64a77c254065ab7450576bbd3a0b583595carll                                           triop( Iop_MulF64, rm,
147526c758b64a77c254065ab7450576bbd3a0b583595carll                                                   mkexpr( frA ),
147536c758b64a77c254065ab7450576bbd3a0b583595carll                                                   mkexpr( frB ) ) ) ),
147546c758b64a77c254065ab7450576bbd3a0b583595carll                              mkU64( 0 ) ) );
147556c758b64a77c254065ab7450576bbd3a0b583595carll         break;
147566c758b64a77c254065ab7450576bbd3a0b583595carll
1475766d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj      case 0x0C0: // xsmuldp (VSX Scalar Multiply Double-Precision)
1475866d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj         DIP("xsmuldp v%d,v%d,v%d\n", (UInt)XT, (UInt)XA, (UInt)XB);
1475966d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj         putVSReg( XT, binop( Iop_64HLtoV128, unop( Iop_ReinterpF64asI64,
1476066d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj                                                    triop( Iop_MulF64, rm,
1476166d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj                                                           mkexpr( frA ),
1476266d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj                                                           mkexpr( frB ) ) ),
1476366d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj                              mkU64( 0 ) ) );
1476466d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj         break;
1476566d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj      case 0x0A0: // xssubdp (VSX Scalar Subtract Double-Precision)
1476666d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj         DIP("xssubdp v%d,v%d,v%d\n", (UInt)XT, (UInt)XA, (UInt)XB);
1476766d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj         putVSReg( XT, binop( Iop_64HLtoV128, unop( Iop_ReinterpF64asI64,
1476866d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj                                                    triop( Iop_SubF64, rm,
1476966d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj                                                           mkexpr( frA ),
1477066d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj                                                           mkexpr( frB ) ) ),
1477166d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj                              mkU64( 0 ) ) );
1477266d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj         break;
1477366d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj
147746c758b64a77c254065ab7450576bbd3a0b583595carll      case 0x016: // xssqrtsp (VSX Scalar Square Root Single-Precision)
147756c758b64a77c254065ab7450576bbd3a0b583595carll         DIP("xssqrtsp v%d,v%d\n", (UInt)XT, (UInt)XB);
147766c758b64a77c254065ab7450576bbd3a0b583595carll         putVSReg( XT,
147776c758b64a77c254065ab7450576bbd3a0b583595carll                   binop( Iop_64HLtoV128,
147786c758b64a77c254065ab7450576bbd3a0b583595carll                          unop( Iop_ReinterpF64asI64,
147796c758b64a77c254065ab7450576bbd3a0b583595carll                                binop( Iop_RoundF64toF32, rm,
147806c758b64a77c254065ab7450576bbd3a0b583595carll                                       binop( Iop_SqrtF64, rm,
147816c758b64a77c254065ab7450576bbd3a0b583595carll                                              mkexpr( frB ) ) ) ),
147826c758b64a77c254065ab7450576bbd3a0b583595carll                          mkU64( 0 ) ) );
147836c758b64a77c254065ab7450576bbd3a0b583595carll         break;
147846c758b64a77c254065ab7450576bbd3a0b583595carll
147854aa412af1d8166cc11f39a6e721df49431d23618sewardj      case 0x096: // xssqrtdp (VSX Scalar Square Root Double-Precision)
147864aa412af1d8166cc11f39a6e721df49431d23618sewardj         DIP("xssqrtdp v%d,v%d\n", (UInt)XT, (UInt)XB);
147874aa412af1d8166cc11f39a6e721df49431d23618sewardj         putVSReg( XT,  binop( Iop_64HLtoV128, unop( Iop_ReinterpF64asI64,
147884aa412af1d8166cc11f39a6e721df49431d23618sewardj                                                     binop( Iop_SqrtF64, rm,
147894aa412af1d8166cc11f39a6e721df49431d23618sewardj                                                            mkexpr( frB ) ) ),
147904aa412af1d8166cc11f39a6e721df49431d23618sewardj                               mkU64( 0 ) ) );
147914aa412af1d8166cc11f39a6e721df49431d23618sewardj         break;
147924aa412af1d8166cc11f39a6e721df49431d23618sewardj
147934aa412af1d8166cc11f39a6e721df49431d23618sewardj      case 0x0F4: // xstdivdp (VSX Scalar Test for software Divide Double-Precision)
147944aa412af1d8166cc11f39a6e721df49431d23618sewardj      {
147954aa412af1d8166cc11f39a6e721df49431d23618sewardj         UChar crfD     = toUChar( IFIELD( theInstr, 23, 3 ) );
147964aa412af1d8166cc11f39a6e721df49431d23618sewardj         IRTemp frA_I64 = newTemp(Ity_I64);
147974aa412af1d8166cc11f39a6e721df49431d23618sewardj         IRTemp frB_I64 = newTemp(Ity_I64);
147984aa412af1d8166cc11f39a6e721df49431d23618sewardj         DIP("xstdivdp crf%d,v%d,v%d\n", crfD, (UInt)XA, (UInt)XB);
147994aa412af1d8166cc11f39a6e721df49431d23618sewardj         assign( frA_I64, unop( Iop_ReinterpF64asI64, mkexpr( frA ) ) );
148004aa412af1d8166cc11f39a6e721df49431d23618sewardj         assign( frB_I64, unop( Iop_ReinterpF64asI64, mkexpr( frB ) ) );
148014aa412af1d8166cc11f39a6e721df49431d23618sewardj         putGST_field( PPC_GST_CR, do_fp_tdiv(frA_I64, frB_I64), crfD );
148024aa412af1d8166cc11f39a6e721df49431d23618sewardj         break;
148034aa412af1d8166cc11f39a6e721df49431d23618sewardj      }
14804e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj      case 0x0D4: // xstsqrtdp (VSX Vector Test for software Square Root Double-Precision)
14805e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj      {
14806e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj         IRTemp frB_I64 = newTemp(Ity_I64);
14807e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj         UChar crfD     = toUChar( IFIELD( theInstr, 23, 3 ) );
14808e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj         IRTemp flags = newTemp(Ity_I32);
14809e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj         IRTemp  fe_flag, fg_flag;
14810e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj         fe_flag = fg_flag = IRTemp_INVALID;
14811e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj         DIP("xstsqrtdp v%d,v%d\n", (UInt)XT, (UInt)XB);
14812e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj         assign( frB_I64, unop(Iop_V128HIto64, getVSReg( XB )) );
14813e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj         do_fp_tsqrt(frB_I64, False /*not single precision*/, &fe_flag, &fg_flag);
14814e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj         /* The CR field consists of fl_flag || fg_flag || fe_flag || 0b0
14815e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj          * where fl_flag == 1 on ppc64.
14816e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj          */
14817e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj         assign( flags,
14818e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj                 binop( Iop_Or32,
14819e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj                        binop( Iop_Or32, mkU32( 8 ), // fl_flag
14820e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj                               binop( Iop_Shl32, mkexpr(fg_flag), mkU8( 2 ) ) ),
14821e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj                        binop( Iop_Shl32, mkexpr(fe_flag), mkU8( 1 ) ) ) );
14822e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj         putGST_field( PPC_GST_CR, mkexpr(flags), crfD );
14823e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj         break;
14824e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj      }
148254aa412af1d8166cc11f39a6e721df49431d23618sewardj
1482666d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj      default:
148274aa412af1d8166cc11f39a6e721df49431d23618sewardj         vex_printf( "dis_vxs_arith(ppc)(opc2)\n" );
1482866d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj         return False;
1482966d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj   }
148304aa412af1d8166cc11f39a6e721df49431d23618sewardj
1483166d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj   return True;
1483266d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj}
1483366d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj
148344aa412af1d8166cc11f39a6e721df49431d23618sewardj
1483566d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj/*
1483666d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj * VSX Floating Point Compare Instructions
1483766d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj */
1483866d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardjstatic Bool
1483966d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardjdis_vx_cmp( UInt theInstr, UInt opc2 )
1484066d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj{
1484166d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj   /* XX3-Form and XX2-Form */
1484266d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj   UChar opc1 = ifieldOPC( theInstr );
1484366d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj   UChar crfD     = toUChar( IFIELD( theInstr, 23, 3 ) );
148444aa412af1d8166cc11f39a6e721df49431d23618sewardj   IRTemp ccPPC32;
1484566d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj   UChar XA       = ifieldRegXA ( theInstr );
1484666d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj   UChar XB       = ifieldRegXB ( theInstr );
1484766d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj   IRTemp frA     = newTemp(Ity_F64);
1484866d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj   IRTemp frB     = newTemp(Ity_F64);
1484966d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj
1485066d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj   if (opc1 != 0x3C) {
1485166d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj      vex_printf( "dis_vx_cmp(ppc)(instr)\n" );
1485266d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj      return False;
1485366d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj   }
1485466d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj
1485566d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj   assign(frA, unop(Iop_ReinterpI64asF64, unop(Iop_V128HIto64, getVSReg( XA ))));
1485666d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj   assign(frB, unop(Iop_ReinterpI64asF64, unop(Iop_V128HIto64, getVSReg( XB ))));
1485766d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj   switch (opc2) {
1485866d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj      case 0x08C: case 0x0AC: // xscmpudp, xscmpodp
1485966d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj         /* Note: Differences between xscmpudp and xscmpodp are only in
1486066d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj          * exception flag settings, which aren't supported anyway. */
1486166d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj         DIP("xscmp%sdp crf%d,fr%u,fr%u\n", opc2 == 0x08c ? "u" : "o",
1486266d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj                                           crfD, (UInt)XA, (UInt)XB);
148634aa412af1d8166cc11f39a6e721df49431d23618sewardj         ccPPC32 = get_fp_cmp_CR_val( binop(Iop_CmpF64, mkexpr(frA), mkexpr(frB)));
148644aa412af1d8166cc11f39a6e721df49431d23618sewardj         putGST_field( PPC_GST_CR, mkexpr(ccPPC32), crfD );
148654aa412af1d8166cc11f39a6e721df49431d23618sewardj         break;
1486666d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj
148674aa412af1d8166cc11f39a6e721df49431d23618sewardj      default:
148684aa412af1d8166cc11f39a6e721df49431d23618sewardj         vex_printf( "dis_vx_cmp(ppc)(opc2)\n" );
148694aa412af1d8166cc11f39a6e721df49431d23618sewardj         return False;
148704aa412af1d8166cc11f39a6e721df49431d23618sewardj   }
148714aa412af1d8166cc11f39a6e721df49431d23618sewardj   return True;
148724aa412af1d8166cc11f39a6e721df49431d23618sewardj}
1487366d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj
148744aa412af1d8166cc11f39a6e721df49431d23618sewardjstatic void
148754aa412af1d8166cc11f39a6e721df49431d23618sewardjdo_vvec_fp_cmp ( IRTemp vA, IRTemp vB, UChar XT, UChar flag_rC,
148764aa412af1d8166cc11f39a6e721df49431d23618sewardj                 ppc_cmp_t cmp_type )
148774aa412af1d8166cc11f39a6e721df49431d23618sewardj{
148784aa412af1d8166cc11f39a6e721df49431d23618sewardj   IRTemp frA_hi     = newTemp(Ity_F64);
148794aa412af1d8166cc11f39a6e721df49431d23618sewardj   IRTemp frB_hi     = newTemp(Ity_F64);
148804aa412af1d8166cc11f39a6e721df49431d23618sewardj   IRTemp frA_lo     = newTemp(Ity_F64);
148814aa412af1d8166cc11f39a6e721df49431d23618sewardj   IRTemp frB_lo     = newTemp(Ity_F64);
148824aa412af1d8166cc11f39a6e721df49431d23618sewardj   IRTemp ccPPC32    = newTemp(Ity_I32);
148834aa412af1d8166cc11f39a6e721df49431d23618sewardj   IRTemp ccIR_hi;
148844aa412af1d8166cc11f39a6e721df49431d23618sewardj   IRTemp ccIR_lo;
148854aa412af1d8166cc11f39a6e721df49431d23618sewardj
148864aa412af1d8166cc11f39a6e721df49431d23618sewardj   IRTemp hiResult = newTemp(Ity_I64);
148874aa412af1d8166cc11f39a6e721df49431d23618sewardj   IRTemp loResult = newTemp(Ity_I64);
148884aa412af1d8166cc11f39a6e721df49431d23618sewardj   IRTemp hiEQlo = newTemp(Ity_I1);
148894aa412af1d8166cc11f39a6e721df49431d23618sewardj   IRTemp all_elem_true = newTemp(Ity_I32);
148904aa412af1d8166cc11f39a6e721df49431d23618sewardj   IRTemp all_elem_false = newTemp(Ity_I32);
148914aa412af1d8166cc11f39a6e721df49431d23618sewardj
148924aa412af1d8166cc11f39a6e721df49431d23618sewardj   assign(frA_hi, unop(Iop_ReinterpI64asF64, unop(Iop_V128HIto64, mkexpr( vA ))));
148934aa412af1d8166cc11f39a6e721df49431d23618sewardj   assign(frB_hi, unop(Iop_ReinterpI64asF64, unop(Iop_V128HIto64, mkexpr( vB ))));
148944aa412af1d8166cc11f39a6e721df49431d23618sewardj   assign(frA_lo, unop(Iop_ReinterpI64asF64, unop(Iop_V128to64, mkexpr( vA ))));
148954aa412af1d8166cc11f39a6e721df49431d23618sewardj   assign(frB_lo, unop(Iop_ReinterpI64asF64, unop(Iop_V128to64, mkexpr( vB ))));
148964aa412af1d8166cc11f39a6e721df49431d23618sewardj
148974aa412af1d8166cc11f39a6e721df49431d23618sewardj   ccIR_hi = get_fp_cmp_CR_val( binop( Iop_CmpF64,
148984aa412af1d8166cc11f39a6e721df49431d23618sewardj                                       mkexpr( frA_hi ),
148994aa412af1d8166cc11f39a6e721df49431d23618sewardj                                       mkexpr( frB_hi ) ) );
149004aa412af1d8166cc11f39a6e721df49431d23618sewardj   ccIR_lo = get_fp_cmp_CR_val( binop( Iop_CmpF64,
149014aa412af1d8166cc11f39a6e721df49431d23618sewardj                                       mkexpr( frA_lo ),
149024aa412af1d8166cc11f39a6e721df49431d23618sewardj                                       mkexpr( frB_lo ) ) );
149034aa412af1d8166cc11f39a6e721df49431d23618sewardj
149044aa412af1d8166cc11f39a6e721df49431d23618sewardj   if (cmp_type != PPC_CMP_GE) {
149054aa412af1d8166cc11f39a6e721df49431d23618sewardj      assign( hiResult,
149064aa412af1d8166cc11f39a6e721df49431d23618sewardj              unop( Iop_1Sto64,
149074aa412af1d8166cc11f39a6e721df49431d23618sewardj                    binop( Iop_CmpEQ32, mkexpr( ccIR_hi ), mkU32( cmp_type ) ) ) );
149084aa412af1d8166cc11f39a6e721df49431d23618sewardj      assign( loResult,
149094aa412af1d8166cc11f39a6e721df49431d23618sewardj              unop( Iop_1Sto64,
149104aa412af1d8166cc11f39a6e721df49431d23618sewardj                    binop( Iop_CmpEQ32, mkexpr( ccIR_lo ), mkU32( cmp_type ) ) ) );
149114aa412af1d8166cc11f39a6e721df49431d23618sewardj   } else {
149124aa412af1d8166cc11f39a6e721df49431d23618sewardj      // For PPC_CMP_GE, one element compare may return "4" (for "greater than") and
149134aa412af1d8166cc11f39a6e721df49431d23618sewardj      // the other element compare may return "2" (for "equal to").
149144aa412af1d8166cc11f39a6e721df49431d23618sewardj      IRTemp lo_GE = newTemp(Ity_I1);
149154aa412af1d8166cc11f39a6e721df49431d23618sewardj      IRTemp hi_GE = newTemp(Ity_I1);
149164aa412af1d8166cc11f39a6e721df49431d23618sewardj
149174aa412af1d8166cc11f39a6e721df49431d23618sewardj      assign(hi_GE, mkOR1( binop( Iop_CmpEQ32, mkexpr( ccIR_hi ), mkU32( 2 ) ),
149184aa412af1d8166cc11f39a6e721df49431d23618sewardj                           binop( Iop_CmpEQ32, mkexpr( ccIR_hi ), mkU32( 4 ) ) ) );
149194aa412af1d8166cc11f39a6e721df49431d23618sewardj      assign( hiResult,unop( Iop_1Sto64, mkexpr( hi_GE ) ) );
149204aa412af1d8166cc11f39a6e721df49431d23618sewardj
149214aa412af1d8166cc11f39a6e721df49431d23618sewardj      assign(lo_GE, mkOR1( binop( Iop_CmpEQ32, mkexpr( ccIR_lo ), mkU32( 2 ) ),
149224aa412af1d8166cc11f39a6e721df49431d23618sewardj                           binop( Iop_CmpEQ32, mkexpr( ccIR_lo ), mkU32( 4 ) ) ) );
149234aa412af1d8166cc11f39a6e721df49431d23618sewardj      assign( loResult, unop( Iop_1Sto64, mkexpr( lo_GE ) ) );
149244aa412af1d8166cc11f39a6e721df49431d23618sewardj   }
149254aa412af1d8166cc11f39a6e721df49431d23618sewardj
149264aa412af1d8166cc11f39a6e721df49431d23618sewardj   // The [hi/lo]Result will be all 1's or all 0's.  We just look at the lower word.
149274aa412af1d8166cc11f39a6e721df49431d23618sewardj   assign( hiEQlo,
149284aa412af1d8166cc11f39a6e721df49431d23618sewardj           binop( Iop_CmpEQ32,
149294aa412af1d8166cc11f39a6e721df49431d23618sewardj                  unop( Iop_64to32, mkexpr( hiResult ) ),
149304aa412af1d8166cc11f39a6e721df49431d23618sewardj                  unop( Iop_64to32, mkexpr( loResult ) ) ) );
149314aa412af1d8166cc11f39a6e721df49431d23618sewardj   putVSReg( XT,
149324aa412af1d8166cc11f39a6e721df49431d23618sewardj             binop( Iop_64HLtoV128, mkexpr( hiResult ), mkexpr( loResult ) ) );
149334aa412af1d8166cc11f39a6e721df49431d23618sewardj
149344aa412af1d8166cc11f39a6e721df49431d23618sewardj   assign( all_elem_true,
149354aa412af1d8166cc11f39a6e721df49431d23618sewardj           unop( Iop_1Uto32,
149364aa412af1d8166cc11f39a6e721df49431d23618sewardj                 mkAND1( mkexpr( hiEQlo ),
149374aa412af1d8166cc11f39a6e721df49431d23618sewardj                         binop( Iop_CmpEQ32,
149384aa412af1d8166cc11f39a6e721df49431d23618sewardj                                mkU32( 0xffffffff ),
149394aa412af1d8166cc11f39a6e721df49431d23618sewardj                                unop( Iop_64to32,
149404aa412af1d8166cc11f39a6e721df49431d23618sewardj                                mkexpr( hiResult ) ) ) ) ) );
149414aa412af1d8166cc11f39a6e721df49431d23618sewardj
149424aa412af1d8166cc11f39a6e721df49431d23618sewardj   assign( all_elem_false,
149434aa412af1d8166cc11f39a6e721df49431d23618sewardj           unop( Iop_1Uto32,
149444aa412af1d8166cc11f39a6e721df49431d23618sewardj                 mkAND1( mkexpr( hiEQlo ),
149454aa412af1d8166cc11f39a6e721df49431d23618sewardj                         binop( Iop_CmpEQ32,
149464aa412af1d8166cc11f39a6e721df49431d23618sewardj                                mkU32( 0 ),
149474aa412af1d8166cc11f39a6e721df49431d23618sewardj                                unop( Iop_64to32,
149484aa412af1d8166cc11f39a6e721df49431d23618sewardj                                mkexpr( hiResult ) ) ) ) ) );
149494aa412af1d8166cc11f39a6e721df49431d23618sewardj   assign( ccPPC32,
149504aa412af1d8166cc11f39a6e721df49431d23618sewardj           binop( Iop_Or32,
149514aa412af1d8166cc11f39a6e721df49431d23618sewardj                  binop( Iop_Shl32, mkexpr( all_elem_false ), mkU8( 1 ) ),
149524aa412af1d8166cc11f39a6e721df49431d23618sewardj                  binop( Iop_Shl32, mkexpr( all_elem_true ), mkU8( 3 ) ) ) );
1495366d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj
149544aa412af1d8166cc11f39a6e721df49431d23618sewardj   if (flag_rC) {
149554aa412af1d8166cc11f39a6e721df49431d23618sewardj      putGST_field( PPC_GST_CR, mkexpr(ccPPC32), 6 );
149564aa412af1d8166cc11f39a6e721df49431d23618sewardj   }
149574aa412af1d8166cc11f39a6e721df49431d23618sewardj}
149584aa412af1d8166cc11f39a6e721df49431d23618sewardj
149594aa412af1d8166cc11f39a6e721df49431d23618sewardj/*
149604aa412af1d8166cc11f39a6e721df49431d23618sewardj * VSX Vector Compare Instructions
149614aa412af1d8166cc11f39a6e721df49431d23618sewardj */
149624aa412af1d8166cc11f39a6e721df49431d23618sewardjstatic Bool
149634aa412af1d8166cc11f39a6e721df49431d23618sewardjdis_vvec_cmp( UInt theInstr, UInt opc2 )
149644aa412af1d8166cc11f39a6e721df49431d23618sewardj{
149654aa412af1d8166cc11f39a6e721df49431d23618sewardj   /* XX3-Form */
149664aa412af1d8166cc11f39a6e721df49431d23618sewardj   UChar opc1 = ifieldOPC( theInstr );
149674aa412af1d8166cc11f39a6e721df49431d23618sewardj   UChar XT = ifieldRegXT ( theInstr );
149684aa412af1d8166cc11f39a6e721df49431d23618sewardj   UChar XA = ifieldRegXA ( theInstr );
149694aa412af1d8166cc11f39a6e721df49431d23618sewardj   UChar XB = ifieldRegXB ( theInstr );
149704aa412af1d8166cc11f39a6e721df49431d23618sewardj   UChar flag_rC  = ifieldBIT10(theInstr);
149714aa412af1d8166cc11f39a6e721df49431d23618sewardj   IRTemp vA = newTemp( Ity_V128 );
149724aa412af1d8166cc11f39a6e721df49431d23618sewardj   IRTemp vB = newTemp( Ity_V128 );
149734aa412af1d8166cc11f39a6e721df49431d23618sewardj
149744aa412af1d8166cc11f39a6e721df49431d23618sewardj   if (opc1 != 0x3C) {
149754aa412af1d8166cc11f39a6e721df49431d23618sewardj      vex_printf( "dis_vvec_cmp(ppc)(instr)\n" );
149764aa412af1d8166cc11f39a6e721df49431d23618sewardj      return False;
149774aa412af1d8166cc11f39a6e721df49431d23618sewardj   }
149784aa412af1d8166cc11f39a6e721df49431d23618sewardj
149794aa412af1d8166cc11f39a6e721df49431d23618sewardj   assign( vA, getVSReg( XA ) );
149804aa412af1d8166cc11f39a6e721df49431d23618sewardj   assign( vB, getVSReg( XB ) );
149814aa412af1d8166cc11f39a6e721df49431d23618sewardj
149824aa412af1d8166cc11f39a6e721df49431d23618sewardj   switch (opc2) {
149834aa412af1d8166cc11f39a6e721df49431d23618sewardj      case 0x18C: case 0x38C:  // xvcmpeqdp[.] (VSX Vector Compare Equal To Double-Precision [ & Record ])
149844aa412af1d8166cc11f39a6e721df49431d23618sewardj      {
149854aa412af1d8166cc11f39a6e721df49431d23618sewardj         DIP("xvcmpeqdp%s crf%d,fr%u,fr%u\n", (flag_rC ? ".":""),
149864aa412af1d8166cc11f39a6e721df49431d23618sewardj             (UInt)XT, (UInt)XA, (UInt)XB);
149874aa412af1d8166cc11f39a6e721df49431d23618sewardj         do_vvec_fp_cmp(vA, vB, XT, flag_rC, PPC_CMP_EQ);
149884aa412af1d8166cc11f39a6e721df49431d23618sewardj         break;
149894aa412af1d8166cc11f39a6e721df49431d23618sewardj      }
149904aa412af1d8166cc11f39a6e721df49431d23618sewardj
149914aa412af1d8166cc11f39a6e721df49431d23618sewardj      case 0x1CC: case 0x3CC: // xvcmpgedp[.] (VSX Vector Compare Greater Than or Equal To Double-Precision [ & Record ])
149924aa412af1d8166cc11f39a6e721df49431d23618sewardj      {
149934aa412af1d8166cc11f39a6e721df49431d23618sewardj         DIP("xvcmpgedp%s crf%d,fr%u,fr%u\n", (flag_rC ? ".":""),
149944aa412af1d8166cc11f39a6e721df49431d23618sewardj             (UInt)XT, (UInt)XA, (UInt)XB);
149954aa412af1d8166cc11f39a6e721df49431d23618sewardj         do_vvec_fp_cmp(vA, vB, XT, flag_rC, PPC_CMP_GE);
149964aa412af1d8166cc11f39a6e721df49431d23618sewardj         break;
149974aa412af1d8166cc11f39a6e721df49431d23618sewardj      }
149984aa412af1d8166cc11f39a6e721df49431d23618sewardj
149994aa412af1d8166cc11f39a6e721df49431d23618sewardj      case 0x1AC: case 0x3AC: // xvcmpgtdp[.] (VSX Vector Compare Greater Than Double-Precision [ & Record ])
150004aa412af1d8166cc11f39a6e721df49431d23618sewardj      {
150014aa412af1d8166cc11f39a6e721df49431d23618sewardj         DIP("xvcmpgtdp%s crf%d,fr%u,fr%u\n", (flag_rC ? ".":""),
150024aa412af1d8166cc11f39a6e721df49431d23618sewardj             (UInt)XT, (UInt)XA, (UInt)XB);
150034aa412af1d8166cc11f39a6e721df49431d23618sewardj         do_vvec_fp_cmp(vA, vB, XT, flag_rC, PPC_CMP_GT);
150044aa412af1d8166cc11f39a6e721df49431d23618sewardj         break;
150054aa412af1d8166cc11f39a6e721df49431d23618sewardj      }
150064aa412af1d8166cc11f39a6e721df49431d23618sewardj
150074aa412af1d8166cc11f39a6e721df49431d23618sewardj      case 0x10C: case 0x30C: // xvcmpeqsp[.] (VSX Vector Compare Equal To Single-Precision [ & Record ])
150084aa412af1d8166cc11f39a6e721df49431d23618sewardj      {
150094aa412af1d8166cc11f39a6e721df49431d23618sewardj         IRTemp vD = newTemp(Ity_V128);
150104aa412af1d8166cc11f39a6e721df49431d23618sewardj
150114aa412af1d8166cc11f39a6e721df49431d23618sewardj         DIP("xvcmpeqsp%s crf%d,fr%u,fr%u\n", (flag_rC ? ".":""),
150124aa412af1d8166cc11f39a6e721df49431d23618sewardj             (UInt)XT, (UInt)XA, (UInt)XB);
150134aa412af1d8166cc11f39a6e721df49431d23618sewardj         assign( vD, binop(Iop_CmpEQ32Fx4, mkexpr(vA), mkexpr(vB)) );
150144aa412af1d8166cc11f39a6e721df49431d23618sewardj         putVSReg( XT, mkexpr(vD) );
150154aa412af1d8166cc11f39a6e721df49431d23618sewardj         if (flag_rC) {
150164aa412af1d8166cc11f39a6e721df49431d23618sewardj            set_AV_CR6( mkexpr(vD), True );
150174aa412af1d8166cc11f39a6e721df49431d23618sewardj         }
150184aa412af1d8166cc11f39a6e721df49431d23618sewardj         break;
150194aa412af1d8166cc11f39a6e721df49431d23618sewardj      }
150204aa412af1d8166cc11f39a6e721df49431d23618sewardj
150214aa412af1d8166cc11f39a6e721df49431d23618sewardj      case 0x14C: case 0x34C: // xvcmpgesp[.] (VSX Vector Compare Greater Than or Equal To Single-Precision [ & Record ])
150224aa412af1d8166cc11f39a6e721df49431d23618sewardj      {
150234aa412af1d8166cc11f39a6e721df49431d23618sewardj         IRTemp vD = newTemp(Ity_V128);
150244aa412af1d8166cc11f39a6e721df49431d23618sewardj
150254aa412af1d8166cc11f39a6e721df49431d23618sewardj         DIP("xvcmpgesp%s crf%d,fr%u,fr%u\n", (flag_rC ? ".":""),
150264aa412af1d8166cc11f39a6e721df49431d23618sewardj             (UInt)XT, (UInt)XA, (UInt)XB);
150274aa412af1d8166cc11f39a6e721df49431d23618sewardj         assign( vD, binop(Iop_CmpGE32Fx4, mkexpr(vA), mkexpr(vB)) );
150284aa412af1d8166cc11f39a6e721df49431d23618sewardj         putVSReg( XT, mkexpr(vD) );
150294aa412af1d8166cc11f39a6e721df49431d23618sewardj         if (flag_rC) {
150304aa412af1d8166cc11f39a6e721df49431d23618sewardj            set_AV_CR6( mkexpr(vD), True );
150314aa412af1d8166cc11f39a6e721df49431d23618sewardj         }
150324aa412af1d8166cc11f39a6e721df49431d23618sewardj         break;
150334aa412af1d8166cc11f39a6e721df49431d23618sewardj      }
1503466d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj
150354aa412af1d8166cc11f39a6e721df49431d23618sewardj      case 0x12C: case 0x32C: //xvcmpgtsp[.] (VSX Vector Compare Greater Than Single-Precision [ & Record ])
150364aa412af1d8166cc11f39a6e721df49431d23618sewardj      {
150374aa412af1d8166cc11f39a6e721df49431d23618sewardj         IRTemp vD = newTemp(Ity_V128);
150384aa412af1d8166cc11f39a6e721df49431d23618sewardj
150394aa412af1d8166cc11f39a6e721df49431d23618sewardj         DIP("xvcmpgtsp%s crf%d,fr%u,fr%u\n", (flag_rC ? ".":""),
150404aa412af1d8166cc11f39a6e721df49431d23618sewardj             (UInt)XT, (UInt)XA, (UInt)XB);
150414aa412af1d8166cc11f39a6e721df49431d23618sewardj         assign( vD, binop(Iop_CmpGT32Fx4, mkexpr(vA), mkexpr(vB)) );
150424aa412af1d8166cc11f39a6e721df49431d23618sewardj         putVSReg( XT, mkexpr(vD) );
150434aa412af1d8166cc11f39a6e721df49431d23618sewardj         if (flag_rC) {
150444aa412af1d8166cc11f39a6e721df49431d23618sewardj            set_AV_CR6( mkexpr(vD), True );
150454aa412af1d8166cc11f39a6e721df49431d23618sewardj         }
1504666d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj         break;
150474aa412af1d8166cc11f39a6e721df49431d23618sewardj      }
150484aa412af1d8166cc11f39a6e721df49431d23618sewardj
1504966d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj      default:
150504aa412af1d8166cc11f39a6e721df49431d23618sewardj         vex_printf( "dis_vvec_cmp(ppc)(opc2)\n" );
1505166d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj         return False;
1505266d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj   }
1505366d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj   return True;
1505466d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj}
1505566d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj/*
150564aa412af1d8166cc11f39a6e721df49431d23618sewardj * Miscellaneous VSX Scalar Instructions
1505766d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj */
1505866d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardjstatic Bool
150594aa412af1d8166cc11f39a6e721df49431d23618sewardjdis_vxs_misc( UInt theInstr, UInt opc2 )
1506066d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj{
150611f5fe1fc3a37ca729925e8eec25aa1025b4a6cdbcarll#define VG_PPC_SIGN_MASK 0x7fffffffffffffffULL
1506266d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj   /* XX3-Form and XX2-Form */
1506366d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj   UChar opc1 = ifieldOPC( theInstr );
1506466d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj   UChar XT = ifieldRegXT ( theInstr );
1506566d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj   UChar XA = ifieldRegXA ( theInstr );
1506666d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj   UChar XB = ifieldRegXB ( theInstr );
1506766d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj   IRTemp vA = newTemp( Ity_V128 );
1506866d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj   IRTemp vB = newTemp( Ity_V128 );
1506966d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj
1507066d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj   if (opc1 != 0x3C) {
150714aa412af1d8166cc11f39a6e721df49431d23618sewardj      vex_printf( "dis_vxs_misc(ppc)(instr)\n" );
1507266d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj      return False;
1507366d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj   }
1507466d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj
1507566d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj   assign( vA, getVSReg( XA ) );
1507666d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj   assign( vB, getVSReg( XB ) );
1507766d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj
1507866d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj   /* For all the VSX move instructions, the contents of doubleword element 1
1507966d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj    * of VSX[XT] are undefined after the operation; therefore, we can simply
1508066d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj    * move the entire array element where it makes sense to do so.
1508166d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj    */
1508266d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj
1508366d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj   switch (opc2) {
1508466d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj      case 0x2B2: // xsabsdp (VSX scalar absolute value double-precision
1508566d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj      {
1508666d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj         /* Move abs val of dw 0 of VSX[XB] to dw 0 of VSX[XT]. */
1508766d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj         IRTemp absVal = newTemp(Ity_V128);
150881f5fe1fc3a37ca729925e8eec25aa1025b4a6cdbcarll         if (host_endness == VexEndnessLE) {
150891f5fe1fc3a37ca729925e8eec25aa1025b4a6cdbcarll            IRTemp hi64 = newTemp(Ity_I64);
150901f5fe1fc3a37ca729925e8eec25aa1025b4a6cdbcarll            IRTemp lo64 = newTemp(Ity_I64);
150911f5fe1fc3a37ca729925e8eec25aa1025b4a6cdbcarll            assign( hi64, unop( Iop_V128HIto64, mkexpr(vB) ) );
150921f5fe1fc3a37ca729925e8eec25aa1025b4a6cdbcarll            assign( lo64, unop( Iop_V128to64, mkexpr(vB) ) );
150931f5fe1fc3a37ca729925e8eec25aa1025b4a6cdbcarll            assign( absVal, binop( Iop_64HLtoV128,
150941f5fe1fc3a37ca729925e8eec25aa1025b4a6cdbcarll                                   binop( Iop_And64, mkexpr(hi64),
150951f5fe1fc3a37ca729925e8eec25aa1025b4a6cdbcarll                                          mkU64(VG_PPC_SIGN_MASK) ),
150961f5fe1fc3a37ca729925e8eec25aa1025b4a6cdbcarll                                   mkexpr(lo64) ) );
150971f5fe1fc3a37ca729925e8eec25aa1025b4a6cdbcarll         } else {
150981f5fe1fc3a37ca729925e8eec25aa1025b4a6cdbcarll            assign(absVal, binop(Iop_ShrV128,
150991f5fe1fc3a37ca729925e8eec25aa1025b4a6cdbcarll                                 binop(Iop_ShlV128, mkexpr(vB),
151001f5fe1fc3a37ca729925e8eec25aa1025b4a6cdbcarll                                       mkU8(1)), mkU8(1)));
151011f5fe1fc3a37ca729925e8eec25aa1025b4a6cdbcarll         }
1510266d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj         DIP("xsabsdp v%d,v%d\n", (UInt)XT, (UInt)XB);
1510366d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj         putVSReg(XT, mkexpr(absVal));
1510466d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj         break;
1510566d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj      }
1510666d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj      case 0x2C0: // xscpsgndp
1510766d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj      {
1510866d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj         /* Scalar copy sign double-precision */
151091f5fe1fc3a37ca729925e8eec25aa1025b4a6cdbcarll         IRTemp vecA_signed = newTemp(Ity_I64);
151101f5fe1fc3a37ca729925e8eec25aa1025b4a6cdbcarll         IRTemp vecB_unsigned = newTemp(Ity_I64);
1511166d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj         IRTemp vec_result = newTemp(Ity_V128);
1511266d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj         DIP("xscpsgndp v%d,v%d v%d\n", (UInt)XT, (UInt)XA, (UInt)XB);
151131f5fe1fc3a37ca729925e8eec25aa1025b4a6cdbcarll         assign( vecA_signed, binop( Iop_And64,
151141f5fe1fc3a37ca729925e8eec25aa1025b4a6cdbcarll                                     unop( Iop_V128HIto64,
151151f5fe1fc3a37ca729925e8eec25aa1025b4a6cdbcarll                                           mkexpr(vA)),
151161f5fe1fc3a37ca729925e8eec25aa1025b4a6cdbcarll                                           mkU64(~VG_PPC_SIGN_MASK) ) );
151171f5fe1fc3a37ca729925e8eec25aa1025b4a6cdbcarll         assign( vecB_unsigned, binop( Iop_And64,
151181f5fe1fc3a37ca729925e8eec25aa1025b4a6cdbcarll                                       unop( Iop_V128HIto64,
151191f5fe1fc3a37ca729925e8eec25aa1025b4a6cdbcarll                                             mkexpr(vB) ),
151201f5fe1fc3a37ca729925e8eec25aa1025b4a6cdbcarll                                             mkU64(VG_PPC_SIGN_MASK) ) );
151211f5fe1fc3a37ca729925e8eec25aa1025b4a6cdbcarll         assign( vec_result, binop( Iop_64HLtoV128,
151221f5fe1fc3a37ca729925e8eec25aa1025b4a6cdbcarll                                    binop( Iop_Or64,
151231f5fe1fc3a37ca729925e8eec25aa1025b4a6cdbcarll                                           mkexpr(vecA_signed),
151241f5fe1fc3a37ca729925e8eec25aa1025b4a6cdbcarll                                           mkexpr(vecB_unsigned) ),
151251f5fe1fc3a37ca729925e8eec25aa1025b4a6cdbcarll                                    mkU64(0x0ULL)));
1512666d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj         putVSReg(XT, mkexpr(vec_result));
1512766d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj         break;
1512866d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj      }
1512966d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj      case 0x2D2: // xsnabsdp
1513066d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj      {
1513166d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj         /* Scalar negative absolute value double-precision */
151321f5fe1fc3a37ca729925e8eec25aa1025b4a6cdbcarll         IRTemp BHi_signed = newTemp(Ity_I64);
1513366d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj         DIP("xsnabsdp v%d,v%d\n", (UInt)XT, (UInt)XB);
151341f5fe1fc3a37ca729925e8eec25aa1025b4a6cdbcarll         assign( BHi_signed, binop( Iop_Or64,
151351f5fe1fc3a37ca729925e8eec25aa1025b4a6cdbcarll                                    unop( Iop_V128HIto64,
151361f5fe1fc3a37ca729925e8eec25aa1025b4a6cdbcarll                                          mkexpr(vB) ),
151371f5fe1fc3a37ca729925e8eec25aa1025b4a6cdbcarll                                          mkU64(~VG_PPC_SIGN_MASK) ) );
151381f5fe1fc3a37ca729925e8eec25aa1025b4a6cdbcarll         putVSReg(XT, binop( Iop_64HLtoV128,
151391f5fe1fc3a37ca729925e8eec25aa1025b4a6cdbcarll                             mkexpr(BHi_signed), mkU64(0x0ULL) ) );
1514066d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj         break;
1514166d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj      }
1514266d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj      case 0x2F2: // xsnegdp
1514366d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj      {
1514466d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj         /* Scalar negate double-precision */
151451f5fe1fc3a37ca729925e8eec25aa1025b4a6cdbcarll         IRTemp BHi_signed = newTemp(Ity_I64);
151461f5fe1fc3a37ca729925e8eec25aa1025b4a6cdbcarll         IRTemp BHi_unsigned = newTemp(Ity_I64);
151471f5fe1fc3a37ca729925e8eec25aa1025b4a6cdbcarll         IRTemp BHi_negated = newTemp(Ity_I64);
151481f5fe1fc3a37ca729925e8eec25aa1025b4a6cdbcarll         IRTemp BHi_negated_signbit = newTemp(Ity_I1);
151491f5fe1fc3a37ca729925e8eec25aa1025b4a6cdbcarll         IRTemp vec_result = newTemp(Ity_V128);
1515066d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj         DIP("xsnabsdp v%d,v%d\n", (UInt)XT, (UInt)XB);
151511f5fe1fc3a37ca729925e8eec25aa1025b4a6cdbcarll         assign( BHi_signed, unop( Iop_V128HIto64, mkexpr(vB) ) );
151521f5fe1fc3a37ca729925e8eec25aa1025b4a6cdbcarll         assign( BHi_unsigned, binop( Iop_And64, mkexpr(BHi_signed),
151531f5fe1fc3a37ca729925e8eec25aa1025b4a6cdbcarll                                      mkU64(VG_PPC_SIGN_MASK) ) );
151541f5fe1fc3a37ca729925e8eec25aa1025b4a6cdbcarll         assign( BHi_negated_signbit,
151551f5fe1fc3a37ca729925e8eec25aa1025b4a6cdbcarll                 unop( Iop_Not1,
151561f5fe1fc3a37ca729925e8eec25aa1025b4a6cdbcarll                       unop( Iop_32to1,
151571f5fe1fc3a37ca729925e8eec25aa1025b4a6cdbcarll                             binop( Iop_Shr32,
151581f5fe1fc3a37ca729925e8eec25aa1025b4a6cdbcarll                                    unop( Iop_64HIto32,
151591f5fe1fc3a37ca729925e8eec25aa1025b4a6cdbcarll                                          binop( Iop_And64,
151601f5fe1fc3a37ca729925e8eec25aa1025b4a6cdbcarll                                                 mkexpr(BHi_signed),
151611f5fe1fc3a37ca729925e8eec25aa1025b4a6cdbcarll                                                 mkU64(~VG_PPC_SIGN_MASK) )
151621f5fe1fc3a37ca729925e8eec25aa1025b4a6cdbcarll                                          ),
151631f5fe1fc3a37ca729925e8eec25aa1025b4a6cdbcarll                                    mkU8(31) ) ) ) );
151641f5fe1fc3a37ca729925e8eec25aa1025b4a6cdbcarll         assign( BHi_negated,
151651f5fe1fc3a37ca729925e8eec25aa1025b4a6cdbcarll                 binop( Iop_Or64,
151661f5fe1fc3a37ca729925e8eec25aa1025b4a6cdbcarll                        binop( Iop_32HLto64,
151671f5fe1fc3a37ca729925e8eec25aa1025b4a6cdbcarll                               binop( Iop_Shl32,
151681f5fe1fc3a37ca729925e8eec25aa1025b4a6cdbcarll                                      unop( Iop_1Uto32,
151691f5fe1fc3a37ca729925e8eec25aa1025b4a6cdbcarll                                            mkexpr(BHi_negated_signbit) ),
151701f5fe1fc3a37ca729925e8eec25aa1025b4a6cdbcarll                                      mkU8(31) ),
151711f5fe1fc3a37ca729925e8eec25aa1025b4a6cdbcarll                               mkU32(0) ),
151721f5fe1fc3a37ca729925e8eec25aa1025b4a6cdbcarll                        mkexpr(BHi_unsigned) ) );
151731f5fe1fc3a37ca729925e8eec25aa1025b4a6cdbcarll         assign( vec_result, binop( Iop_64HLtoV128, mkexpr(BHi_negated),
151741f5fe1fc3a37ca729925e8eec25aa1025b4a6cdbcarll                                    mkU64(0x0ULL)));
151751f5fe1fc3a37ca729925e8eec25aa1025b4a6cdbcarll         putVSReg( XT, mkexpr(vec_result));
1517666d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj         break;
1517766d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj      }
151784aa412af1d8166cc11f39a6e721df49431d23618sewardj      case 0x280: // xsmaxdp (VSX Scalar Maximum Double-Precision)
151794aa412af1d8166cc11f39a6e721df49431d23618sewardj      case 0x2A0: // xsmindp (VSX Scalar Minimum Double-Precision)
151804aa412af1d8166cc11f39a6e721df49431d23618sewardj      {
151814aa412af1d8166cc11f39a6e721df49431d23618sewardj         IRTemp frA     = newTemp(Ity_I64);
151824aa412af1d8166cc11f39a6e721df49431d23618sewardj         IRTemp frB     = newTemp(Ity_I64);
151834aa412af1d8166cc11f39a6e721df49431d23618sewardj         Bool isMin = opc2 == 0x2A0 ? True : False;
151844aa412af1d8166cc11f39a6e721df49431d23618sewardj         DIP("%s v%d,v%d v%d\n", isMin ? "xsmaxdp" : "xsmindp", (UInt)XT, (UInt)XA, (UInt)XB);
151854aa412af1d8166cc11f39a6e721df49431d23618sewardj
151864aa412af1d8166cc11f39a6e721df49431d23618sewardj         assign(frA, unop(Iop_V128HIto64, mkexpr( vA )));
151874aa412af1d8166cc11f39a6e721df49431d23618sewardj         assign(frB, unop(Iop_V128HIto64, mkexpr( vB )));
151884aa412af1d8166cc11f39a6e721df49431d23618sewardj         putVSReg( XT, binop( Iop_64HLtoV128, get_max_min_fp(frA, frB, isMin), mkU64( 0 ) ) );
151894aa412af1d8166cc11f39a6e721df49431d23618sewardj
151904aa412af1d8166cc11f39a6e721df49431d23618sewardj         break;
151914aa412af1d8166cc11f39a6e721df49431d23618sewardj      }
151924aa412af1d8166cc11f39a6e721df49431d23618sewardj      case 0x0F2: // xsrdpim (VSX Scalar Round to Double-Precision Integer using round toward -Infinity)
15193e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj      case 0x0D2: // xsrdpip (VSX Scalar Round to Double-Precision Integer using round toward +Infinity)
15194e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj      case 0x0D6: // xsrdpic (VSX Scalar Round to Double-Precision Integer using Current rounding mode)
15195e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj      case 0x0B2: // xsrdpiz (VSX Scalar Round to Double-Precision Integer using round toward Zero)
15196e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj      case 0x092: // xsrdpi  (VSX Scalar Round to Double-Precision Integer using round toward Nearest Away)
151974aa412af1d8166cc11f39a6e721df49431d23618sewardj      {
151984aa412af1d8166cc11f39a6e721df49431d23618sewardj         IRTemp frB_I64 = newTemp(Ity_I64);
15199e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj         IRExpr * frD_fp_round = NULL;
15200e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj
152014aa412af1d8166cc11f39a6e721df49431d23618sewardj         assign(frB_I64, unop(Iop_V128HIto64, mkexpr( vB )));
152029884af0b3cfe935b8fab54231f394fe4ee2d7ebccarll         frD_fp_round = _do_vsx_fp_roundToInt(frB_I64, opc2);
152034aa412af1d8166cc11f39a6e721df49431d23618sewardj
152049884af0b3cfe935b8fab54231f394fe4ee2d7ebccarll         DIP("xsrdpi%s v%d,v%d\n", _get_vsx_rdpi_suffix(opc2), (UInt)XT, (UInt)XB);
152054aa412af1d8166cc11f39a6e721df49431d23618sewardj         putVSReg( XT,
152064aa412af1d8166cc11f39a6e721df49431d23618sewardj                   binop( Iop_64HLtoV128,
15207e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj                          unop( Iop_ReinterpF64asI64, frD_fp_round),
152084aa412af1d8166cc11f39a6e721df49431d23618sewardj                          mkU64( 0 ) ) );
15209e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj         break;
15210e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj      }
152116c758b64a77c254065ab7450576bbd3a0b583595carll      case 0x034: // xsresp (VSX Scalar Reciprocal Estimate single-Precision)
152126c758b64a77c254065ab7450576bbd3a0b583595carll      case 0x014: /* xsrsqrtesp (VSX Scalar Reciprocal Square Root Estimate
152136c758b64a77c254065ab7450576bbd3a0b583595carll                   * single-Precision)
152146c758b64a77c254065ab7450576bbd3a0b583595carll                   */
152156c758b64a77c254065ab7450576bbd3a0b583595carll      {
152166c758b64a77c254065ab7450576bbd3a0b583595carll         IRTemp frB = newTemp(Ity_F64);
152176c758b64a77c254065ab7450576bbd3a0b583595carll         IRTemp sqrt = newTemp(Ity_F64);
152186c758b64a77c254065ab7450576bbd3a0b583595carll         IRExpr* ieee_one = IRExpr_Const(IRConst_F64i(0x3ff0000000000000ULL));
152196c758b64a77c254065ab7450576bbd3a0b583595carll         IRExpr* rm  = get_IR_roundingmode();
152206c758b64a77c254065ab7450576bbd3a0b583595carll         Bool redp = opc2 == 0x034;
152216c758b64a77c254065ab7450576bbd3a0b583595carll         DIP("%s v%d,v%d\n", redp ? "xsresp" : "xsrsqrtesp", (UInt)XT,
152226c758b64a77c254065ab7450576bbd3a0b583595carll             (UInt)XB);
152236c758b64a77c254065ab7450576bbd3a0b583595carll
152246c758b64a77c254065ab7450576bbd3a0b583595carll         assign( frB,
152256c758b64a77c254065ab7450576bbd3a0b583595carll                 unop( Iop_ReinterpI64asF64,
152266c758b64a77c254065ab7450576bbd3a0b583595carll                       unop( Iop_V128HIto64, mkexpr( vB ) ) ) );
152276c758b64a77c254065ab7450576bbd3a0b583595carll
152286c758b64a77c254065ab7450576bbd3a0b583595carll         if (!redp)
152296c758b64a77c254065ab7450576bbd3a0b583595carll            assign( sqrt,
152306c758b64a77c254065ab7450576bbd3a0b583595carll                    binop( Iop_SqrtF64,
152316c758b64a77c254065ab7450576bbd3a0b583595carll                           rm,
152326c758b64a77c254065ab7450576bbd3a0b583595carll                           mkexpr(frB) ) );
152336c758b64a77c254065ab7450576bbd3a0b583595carll         putVSReg( XT,
152346c758b64a77c254065ab7450576bbd3a0b583595carll                      binop( Iop_64HLtoV128,
152356c758b64a77c254065ab7450576bbd3a0b583595carll                             unop( Iop_ReinterpF64asI64,
152366c758b64a77c254065ab7450576bbd3a0b583595carll                                   binop( Iop_RoundF64toF32, rm,
152376c758b64a77c254065ab7450576bbd3a0b583595carll                                          triop( Iop_DivF64,
152386c758b64a77c254065ab7450576bbd3a0b583595carll                                                 rm,
152396c758b64a77c254065ab7450576bbd3a0b583595carll                                                 ieee_one,
152406c758b64a77c254065ab7450576bbd3a0b583595carll                                                 redp ? mkexpr( frB ) :
152416c758b64a77c254065ab7450576bbd3a0b583595carll                                                        mkexpr( sqrt ) ) ) ),
152426c758b64a77c254065ab7450576bbd3a0b583595carll                             mkU64( 0 ) ) );
152436c758b64a77c254065ab7450576bbd3a0b583595carll         break;
152446c758b64a77c254065ab7450576bbd3a0b583595carll      }
152456c758b64a77c254065ab7450576bbd3a0b583595carll
15246e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj      case 0x0B4: // xsredp (VSX Scalar Reciprocal Estimate Double-Precision)
15247e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj      case 0x094: // xsrsqrtedp (VSX Scalar Reciprocal Square Root Estimate Double-Precision)
152484aa412af1d8166cc11f39a6e721df49431d23618sewardj
15249e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj      {
15250e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj         IRTemp frB = newTemp(Ity_F64);
15251e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj         IRTemp sqrt = newTemp(Ity_F64);
15252e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj         IRExpr* ieee_one = IRExpr_Const(IRConst_F64i(0x3ff0000000000000ULL));
15253e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj         IRExpr* rm  = get_IR_roundingmode();
15254e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj         Bool redp = opc2 == 0x0B4;
15255e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj         DIP("%s v%d,v%d\n", redp ? "xsredp" : "xsrsqrtedp", (UInt)XT, (UInt)XB);
15256e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj         assign( frB,
15257e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj                 unop( Iop_ReinterpI64asF64,
15258e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj                       unop( Iop_V128HIto64, mkexpr( vB ) ) ) );
15259e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj
15260e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj         if (!redp)
15261e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj            assign( sqrt,
15262e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj                    binop( Iop_SqrtF64,
15263e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj                           rm,
15264e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj                           mkexpr(frB) ) );
15265e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj         putVSReg( XT,
15266e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj                      binop( Iop_64HLtoV128,
15267e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj                             unop( Iop_ReinterpF64asI64,
15268e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj                                   triop( Iop_DivF64,
15269e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj                                          rm,
15270e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj                                          ieee_one,
15271e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj                                          redp ? mkexpr( frB ) : mkexpr( sqrt ) ) ),
15272e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj                             mkU64( 0 ) ) );
152734aa412af1d8166cc11f39a6e721df49431d23618sewardj         break;
152744aa412af1d8166cc11f39a6e721df49431d23618sewardj      }
1527566d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj
152766c758b64a77c254065ab7450576bbd3a0b583595carll      case 0x232: // xsrsp (VSX Scalar Round to Single-Precision)
152776c758b64a77c254065ab7450576bbd3a0b583595carll      {
152786c758b64a77c254065ab7450576bbd3a0b583595carll         IRTemp frB = newTemp(Ity_F64);
152796c758b64a77c254065ab7450576bbd3a0b583595carll         IRExpr* rm  = get_IR_roundingmode();
152806c758b64a77c254065ab7450576bbd3a0b583595carll         DIP("xsrsp v%d, v%d\n", (UInt)XT, (UInt)XB);
152816c758b64a77c254065ab7450576bbd3a0b583595carll         assign( frB,
152826c758b64a77c254065ab7450576bbd3a0b583595carll                 unop( Iop_ReinterpI64asF64,
152836c758b64a77c254065ab7450576bbd3a0b583595carll                       unop( Iop_V128HIto64, mkexpr( vB ) ) ) );
152846c758b64a77c254065ab7450576bbd3a0b583595carll
152856c758b64a77c254065ab7450576bbd3a0b583595carll         putVSReg( XT, binop( Iop_64HLtoV128,
152866c758b64a77c254065ab7450576bbd3a0b583595carll                              unop( Iop_ReinterpF64asI64,
152876c758b64a77c254065ab7450576bbd3a0b583595carll                                    binop( Iop_RoundF64toF32,
152886c758b64a77c254065ab7450576bbd3a0b583595carll                                           rm,
152896c758b64a77c254065ab7450576bbd3a0b583595carll                                           mkexpr( frB ) ) ),
152906c758b64a77c254065ab7450576bbd3a0b583595carll                              mkU64( 0 ) ) );
152916c758b64a77c254065ab7450576bbd3a0b583595carll         break;
152926c758b64a77c254065ab7450576bbd3a0b583595carll      }
152936c758b64a77c254065ab7450576bbd3a0b583595carll
1529466d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj      default:
152954aa412af1d8166cc11f39a6e721df49431d23618sewardj         vex_printf( "dis_vxs_misc(ppc)(opc2)\n" );
1529666d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj         return False;
1529766d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj   }
1529866d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj   return True;
1529966d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj}
1530066d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj
1530166d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj/*
1530266d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj * VSX Logical Instructions
1530366d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj */
1530466d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardjstatic Bool
1530566d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardjdis_vx_logic ( UInt theInstr, UInt opc2 )
1530666d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj{
1530766d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj   /* XX3-Form */
1530866d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj   UChar opc1 = ifieldOPC( theInstr );
1530966d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj   UChar XT = ifieldRegXT ( theInstr );
1531066d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj   UChar XA = ifieldRegXA ( theInstr );
1531166d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj   UChar XB = ifieldRegXB ( theInstr );
1531266d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj   IRTemp vA = newTemp( Ity_V128 );
1531366d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj   IRTemp vB = newTemp( Ity_V128 );
1531466d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj
1531566d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj   if (opc1 != 0x3C) {
1531666d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj      vex_printf( "dis_vx_logic(ppc)(instr)\n" );
1531766d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj      return False;
1531866d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj   }
1531966d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj
1532066d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj   assign( vA, getVSReg( XA ) );
1532166d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj   assign( vB, getVSReg( XB ) );
1532266d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj
1532366d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj   switch (opc2) {
1532466d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj      case 0x268: // xxlxor
1532566d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj         DIP("xxlxor v%d,v%d,v%d\n", (UInt)XT, (UInt)XA, (UInt)XB);
1532666d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj         putVSReg( XT, binop( Iop_XorV128, mkexpr( vA ), mkexpr( vB ) ) );
1532766d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj         break;
1532866d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj      case 0x248: // xxlor
1532966d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj         DIP("xxlor v%d,v%d,v%d\n", (UInt)XT, (UInt)XA, (UInt)XB);
1533066d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj         putVSReg( XT, binop( Iop_OrV128, mkexpr( vA ), mkexpr( vB ) ) );
1533166d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj         break;
1533266d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj      case 0x288: // xxlnor
1533366d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj         DIP("xxlnor v%d,v%d,v%d\n", (UInt)XT, (UInt)XA, (UInt)XB);
1533466d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj         putVSReg( XT, unop( Iop_NotV128, binop( Iop_OrV128, mkexpr( vA ),
1533566d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj                                                 mkexpr( vB ) ) ) );
1533666d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj         break;
1533766d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj      case 0x208: // xxland
1533866d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj         DIP("xxland v%d,v%d,v%d\n", (UInt)XT, (UInt)XA, (UInt)XB);
1533966d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj         putVSReg( XT, binop( Iop_AndV128, mkexpr( vA ), mkexpr( vB ) ) );
1534066d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj         break;
1534166d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj      case 0x228: //xxlandc
1534266d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj         DIP("xxlandc v%d,v%d,v%d\n", (UInt)XT, (UInt)XA, (UInt)XB);
1534366d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj         putVSReg( XT, binop( Iop_AndV128, mkexpr( vA ), unop( Iop_NotV128,
1534466d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj                                                               mkexpr( vB ) ) ) );
1534566d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj         break;
153466c758b64a77c254065ab7450576bbd3a0b583595carll      case 0x2A8: // xxlorc (VSX Logical OR with complement)
153476c758b64a77c254065ab7450576bbd3a0b583595carll         DIP("xxlorc v%d,v%d,v%d\n", (UInt)XT, (UInt)XA, (UInt)XB);
153486c758b64a77c254065ab7450576bbd3a0b583595carll         putVSReg( XT, binop( Iop_OrV128,
153496c758b64a77c254065ab7450576bbd3a0b583595carll                              mkexpr( vA ),
153506c758b64a77c254065ab7450576bbd3a0b583595carll                              unop( Iop_NotV128, mkexpr( vB ) ) ) );
153516c758b64a77c254065ab7450576bbd3a0b583595carll         break;
153526c758b64a77c254065ab7450576bbd3a0b583595carll      case 0x2C8: // xxlnand (VSX Logical NAND)
153536c758b64a77c254065ab7450576bbd3a0b583595carll         DIP("xxlnand v%d,v%d,v%d\n", (UInt)XT, (UInt)XA, (UInt)XB);
153546c758b64a77c254065ab7450576bbd3a0b583595carll         putVSReg( XT, unop( Iop_NotV128,
153556c758b64a77c254065ab7450576bbd3a0b583595carll                             binop( Iop_AndV128, mkexpr( vA ),
153566c758b64a77c254065ab7450576bbd3a0b583595carll                                    mkexpr( vB ) ) ) );
153576c758b64a77c254065ab7450576bbd3a0b583595carll         break;
153586c758b64a77c254065ab7450576bbd3a0b583595carll      case 0x2E8: // xxleqv (VSX Logical Equivalence)
153596c758b64a77c254065ab7450576bbd3a0b583595carll         DIP("xxleqv v%d,v%d,v%d\n", (UInt)XT, (UInt)XA, (UInt)XB);
153606c758b64a77c254065ab7450576bbd3a0b583595carll         putVSReg( XT, unop( Iop_NotV128,
153616c758b64a77c254065ab7450576bbd3a0b583595carll                             binop( Iop_XorV128,
153626c758b64a77c254065ab7450576bbd3a0b583595carll                             mkexpr( vA ), mkexpr( vB ) ) ) );
153636c758b64a77c254065ab7450576bbd3a0b583595carll         break;
1536466d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj      default:
1536566d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj         vex_printf( "dis_vx_logic(ppc)(opc2)\n" );
1536666d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj         return False;
1536766d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj   }
1536866d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj   return True;
1536966d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj}
1537066d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj
1537166d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj/*
1537266d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj * VSX Load Instructions
1537366d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj * NOTE: VSX supports word-aligned storage access.
1537466d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj */
1537566d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardjstatic Bool
1537666d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardjdis_vx_load ( UInt theInstr )
1537766d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj{
1537866d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj   /* XX1-Form */
1537966d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj   UChar opc1 = ifieldOPC( theInstr );
1538066d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj   UChar XT = ifieldRegXT ( theInstr );
1538166d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj   UChar rA_addr = ifieldRegA( theInstr );
1538266d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj   UChar rB_addr = ifieldRegB( theInstr );
1538366d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj   UInt opc2 = ifieldOPClo10( theInstr );
1538466d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj
1538566d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj   IRType ty = mode64 ? Ity_I64 : Ity_I32;
1538666d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj   IRTemp EA = newTemp( ty );
1538766d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj
1538866d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj   if (opc1 != 0x1F) {
1538966d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj      vex_printf( "dis_vx_load(ppc)(instr)\n" );
1539066d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj      return False;
1539166d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj   }
1539266d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj
1539366d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj   assign( EA, ea_rAor0_idxd( rA_addr, rB_addr ) );
1539466d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj
1539566d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj   switch (opc2) {
153966c758b64a77c254065ab7450576bbd3a0b583595carll   case 0x00C: // lxsiwzx (Load VSX Scalar as Integer Word and Zero Indexed)
153976c758b64a77c254065ab7450576bbd3a0b583595carll   {
153986c758b64a77c254065ab7450576bbd3a0b583595carll      IRExpr * exp;
153996c758b64a77c254065ab7450576bbd3a0b583595carll      DIP("lxsiwzx %d,r%u,r%u\n", (UInt)XT, rA_addr, rB_addr);
15400256df5959b423b38443329b15e4b1ff74240da1ecarll
15401256df5959b423b38443329b15e4b1ff74240da1ecarll      if (host_endness == VexEndnessLE)
15402256df5959b423b38443329b15e4b1ff74240da1ecarll         exp = unop( Iop_64to32, load( Ity_I64, mkexpr( EA ) ) );
15403256df5959b423b38443329b15e4b1ff74240da1ecarll      else
15404256df5959b423b38443329b15e4b1ff74240da1ecarll         exp = unop( Iop_64HIto32, load( Ity_I64, mkexpr( EA ) ) );
15405256df5959b423b38443329b15e4b1ff74240da1ecarll
154066c758b64a77c254065ab7450576bbd3a0b583595carll      putVSReg( XT, binop( Iop_64HLtoV128,
154076c758b64a77c254065ab7450576bbd3a0b583595carll                           unop( Iop_32Uto64, exp),
154086c758b64a77c254065ab7450576bbd3a0b583595carll                           mkU64(0) ) );
154096c758b64a77c254065ab7450576bbd3a0b583595carll      break;
154106c758b64a77c254065ab7450576bbd3a0b583595carll   }
154116c758b64a77c254065ab7450576bbd3a0b583595carll   case 0x04C: // lxsiwax (Load VSX Scalar as Integer Word Algebraic Indexed)
154126c758b64a77c254065ab7450576bbd3a0b583595carll   {
154136c758b64a77c254065ab7450576bbd3a0b583595carll      IRExpr * exp;
154146c758b64a77c254065ab7450576bbd3a0b583595carll      DIP("lxsiwax %d,r%u,r%u\n", (UInt)XT, rA_addr, rB_addr);
15415256df5959b423b38443329b15e4b1ff74240da1ecarll
15416256df5959b423b38443329b15e4b1ff74240da1ecarll      if (host_endness == VexEndnessLE)
15417256df5959b423b38443329b15e4b1ff74240da1ecarll         exp = unop( Iop_64to32, load( Ity_I64, mkexpr( EA ) ) );
15418256df5959b423b38443329b15e4b1ff74240da1ecarll      else
15419256df5959b423b38443329b15e4b1ff74240da1ecarll         exp = unop( Iop_64HIto32, load( Ity_I64, mkexpr( EA ) ) );
15420256df5959b423b38443329b15e4b1ff74240da1ecarll
154216c758b64a77c254065ab7450576bbd3a0b583595carll      putVSReg( XT, binop( Iop_64HLtoV128,
154226c758b64a77c254065ab7450576bbd3a0b583595carll                           unop( Iop_32Sto64, exp),
154236c758b64a77c254065ab7450576bbd3a0b583595carll                           mkU64(0) ) );
154246c758b64a77c254065ab7450576bbd3a0b583595carll      break;
154256c758b64a77c254065ab7450576bbd3a0b583595carll   }
154266c758b64a77c254065ab7450576bbd3a0b583595carll   case 0x20C: // lxsspx (Load VSX Scalar Single-Precision Indexed)
154276c758b64a77c254065ab7450576bbd3a0b583595carll   {
154286c758b64a77c254065ab7450576bbd3a0b583595carll      IRExpr * exp;
154296c758b64a77c254065ab7450576bbd3a0b583595carll      DIP("lxsspx %d,r%u,r%u\n", (UInt)XT, rA_addr, rB_addr);
154306c758b64a77c254065ab7450576bbd3a0b583595carll      /* Take 32-bit floating point value in the upper half of the fetched
154316c758b64a77c254065ab7450576bbd3a0b583595carll       * 64-bit value, convert to 64-bit floating point value and load into
154326c758b64a77c254065ab7450576bbd3a0b583595carll       * top word of V128.
154336c758b64a77c254065ab7450576bbd3a0b583595carll       */
154346c758b64a77c254065ab7450576bbd3a0b583595carll      exp = unop( Iop_ReinterpF64asI64,
154356c758b64a77c254065ab7450576bbd3a0b583595carll                  unop( Iop_F32toF64,
154366c758b64a77c254065ab7450576bbd3a0b583595carll                        unop( Iop_ReinterpI32asF32,
154371f5fe1fc3a37ca729925e8eec25aa1025b4a6cdbcarll                              load( Ity_I32, mkexpr( EA ) ) ) ) );
154386c758b64a77c254065ab7450576bbd3a0b583595carll
154396c758b64a77c254065ab7450576bbd3a0b583595carll      putVSReg( XT, binop( Iop_64HLtoV128, exp, mkU64( 0 ) ) );
154406c758b64a77c254065ab7450576bbd3a0b583595carll      break;
154416c758b64a77c254065ab7450576bbd3a0b583595carll   }
1544266d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj   case 0x24C: // lxsdx
1544366d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj   {
1544466d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj      IRExpr * exp;
1544566d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj      DIP("lxsdx %d,r%u,r%u\n", (UInt)XT, rA_addr, rB_addr);
154461f5fe1fc3a37ca729925e8eec25aa1025b4a6cdbcarll      exp = load( Ity_I64, mkexpr( EA ) );
1544766d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj      // We need to pass an expression of type Ity_V128 with putVSReg, but the load
1544866d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj      // we just performed is only a DW.  But since the contents of VSR[XT] element 1
1544966d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj      // are undefined after this operation, we can just do a splat op.
1545066d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj      putVSReg( XT, binop( Iop_64HLtoV128, exp, exp ) );
1545166d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj      break;
1545266d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj   }
1545366d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj   case 0x34C: // lxvd2x
1545466d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj   {
1545566d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj      IROp addOp = ty == Ity_I64 ? Iop_Add64 : Iop_Add32;
1545666d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj      IRExpr * high, *low;
1545766d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj      ULong ea_off = 8;
1545866d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj      IRExpr* high_addr;
1545966d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj      DIP("lxvd2x %d,r%u,r%u\n", (UInt)XT, rA_addr, rB_addr);
154601f5fe1fc3a37ca729925e8eec25aa1025b4a6cdbcarll      high = load( Ity_I64, mkexpr( EA ) );
1546166d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj      high_addr = binop( addOp, mkexpr( EA ), ty == Ity_I64 ? mkU64( ea_off )
1546266d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj            : mkU32( ea_off ) );
154631f5fe1fc3a37ca729925e8eec25aa1025b4a6cdbcarll      low = load( Ity_I64, high_addr );
1546466d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj      putVSReg( XT, binop( Iop_64HLtoV128, high, low ) );
1546566d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj      break;
1546666d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj   }
1546766d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj   case 0x14C: // lxvdsx
1546866d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj   {
1546966d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj      IRTemp data = newTemp(Ity_I64);
1547066d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj      DIP("lxvdsx %d,r%u,r%u\n", (UInt)XT, rA_addr, rB_addr);
154711f5fe1fc3a37ca729925e8eec25aa1025b4a6cdbcarll      assign( data, load( Ity_I64, mkexpr( EA ) ) );
1547266d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj      putVSReg( XT, binop( Iop_64HLtoV128, mkexpr( data ), mkexpr( data ) ) );
1547366d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj      break;
1547466d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj   }
1547566d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj   case 0x30C:
1547666d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj   {
154774e303f232d62781940a56d48649118f4d801abc1carll      IRExpr *t0;
1547866d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj
1547966d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj      DIP("lxvw4x %d,r%u,r%u\n", (UInt)XT, rA_addr, rB_addr);
154804e303f232d62781940a56d48649118f4d801abc1carll
1548185175a7453c4cc4a7d29a247766b627d5cb933decarll      /* The load will result in the data being in BE order. */
1548285175a7453c4cc4a7d29a247766b627d5cb933decarll      if (host_endness == VexEndnessLE) {
1548385175a7453c4cc4a7d29a247766b627d5cb933decarll         IRExpr *t0_BE;
1548485175a7453c4cc4a7d29a247766b627d5cb933decarll         IRTemp perm_LE = newTemp(Ity_V128);
1548585175a7453c4cc4a7d29a247766b627d5cb933decarll
1548685175a7453c4cc4a7d29a247766b627d5cb933decarll         t0_BE = load( Ity_V128, mkexpr( EA ) );
1548785175a7453c4cc4a7d29a247766b627d5cb933decarll
1548885175a7453c4cc4a7d29a247766b627d5cb933decarll         /*  Permute the data to LE format */
154894047e01fdfc71ddfa1912bd29de45f20fcb77355carll         assign( perm_LE, binop( Iop_64HLtoV128, mkU64(0x0c0d0e0f08090a0bULL),
154904047e01fdfc71ddfa1912bd29de45f20fcb77355carll                                 mkU64(0x0405060700010203ULL)));
1549185175a7453c4cc4a7d29a247766b627d5cb933decarll
1549285175a7453c4cc4a7d29a247766b627d5cb933decarll         t0 = binop( Iop_Perm8x16, t0_BE, mkexpr(perm_LE) );
1549385175a7453c4cc4a7d29a247766b627d5cb933decarll      } else {
1549485175a7453c4cc4a7d29a247766b627d5cb933decarll         t0 = load( Ity_V128, mkexpr( EA ) );
1549585175a7453c4cc4a7d29a247766b627d5cb933decarll      }
1549685175a7453c4cc4a7d29a247766b627d5cb933decarll
154974e303f232d62781940a56d48649118f4d801abc1carll      putVSReg( XT, t0 );
1549866d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj      break;
1549966d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj   }
1550066d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj   default:
1550166d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj      vex_printf( "dis_vx_load(ppc)(opc2)\n" );
1550266d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj      return False;
1550366d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj   }
1550466d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj   return True;
1550566d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj}
1550666d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj
1550766d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj/*
1550866d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj * VSX Store Instructions
1550966d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj * NOTE: VSX supports word-aligned storage access.
1551066d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj */
1551166d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardjstatic Bool
1551266d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardjdis_vx_store ( UInt theInstr )
1551366d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj{
1551466d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj   /* XX1-Form */
1551566d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj   UChar opc1 = ifieldOPC( theInstr );
1551666d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj   UChar XS = ifieldRegXS( theInstr );
1551766d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj   UChar rA_addr = ifieldRegA( theInstr );
1551866d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj   UChar rB_addr = ifieldRegB( theInstr );
1551966d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj   IRTemp vS = newTemp( Ity_V128 );
1552066d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj   UInt opc2 = ifieldOPClo10( theInstr );
1552166d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj
1552266d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj   IRType ty = mode64 ? Ity_I64 : Ity_I32;
1552366d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj   IRTemp EA = newTemp( ty );
1552466d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj
1552566d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj   if (opc1 != 0x1F) {
1552666d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj      vex_printf( "dis_vx_store(ppc)(instr)\n" );
1552766d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj      return False;
1552866d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj   }
1552966d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj
1553066d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj   assign( EA, ea_rAor0_idxd( rA_addr, rB_addr ) );
1553166d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj   assign( vS, getVSReg( XS ) );
1553266d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj
1553366d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj   switch (opc2) {
155346c758b64a77c254065ab7450576bbd3a0b583595carll   case 0x08C:
155356c758b64a77c254065ab7450576bbd3a0b583595carll   {
155366c758b64a77c254065ab7450576bbd3a0b583595carll     /* Need the next to the most significant 32-bit word from
155376c758b64a77c254065ab7450576bbd3a0b583595carll      * the 128-bit vector.
155386c758b64a77c254065ab7450576bbd3a0b583595carll      */
155396c758b64a77c254065ab7450576bbd3a0b583595carll      IRExpr * high64, * low32;
155406c758b64a77c254065ab7450576bbd3a0b583595carll      DIP("stxsiwx %d,r%u,r%u\n", (UInt)XS, rA_addr, rB_addr);
155416c758b64a77c254065ab7450576bbd3a0b583595carll      high64 = unop( Iop_V128HIto64, mkexpr( vS ) );
155426c758b64a77c254065ab7450576bbd3a0b583595carll      low32  = unop( Iop_64to32, high64 );
155431f5fe1fc3a37ca729925e8eec25aa1025b4a6cdbcarll      store( mkexpr( EA ), low32 );
155446c758b64a77c254065ab7450576bbd3a0b583595carll      break;
155456c758b64a77c254065ab7450576bbd3a0b583595carll   }
155466c758b64a77c254065ab7450576bbd3a0b583595carll   case 0x28C:
155476c758b64a77c254065ab7450576bbd3a0b583595carll   {
155486c758b64a77c254065ab7450576bbd3a0b583595carll      IRTemp high64 = newTemp(Ity_F64);
155496c758b64a77c254065ab7450576bbd3a0b583595carll      IRTemp val32  = newTemp(Ity_I32);
155506c758b64a77c254065ab7450576bbd3a0b583595carll      DIP("stxsspx %d,r%u,r%u\n", (UInt)XS, rA_addr, rB_addr);
155516c758b64a77c254065ab7450576bbd3a0b583595carll      assign(high64, unop( Iop_ReinterpI64asF64,
155526c758b64a77c254065ab7450576bbd3a0b583595carll                           unop( Iop_V128HIto64, mkexpr( vS ) ) ) );
155536c758b64a77c254065ab7450576bbd3a0b583595carll      assign(val32, unop( Iop_ReinterpF32asI32,
155546c758b64a77c254065ab7450576bbd3a0b583595carll                          unop( Iop_TruncF64asF32,
155556c758b64a77c254065ab7450576bbd3a0b583595carll                                mkexpr(high64) ) ) );
155561f5fe1fc3a37ca729925e8eec25aa1025b4a6cdbcarll      store( mkexpr( EA ), mkexpr( val32 ) );
155576c758b64a77c254065ab7450576bbd3a0b583595carll      break;
155586c758b64a77c254065ab7450576bbd3a0b583595carll   }
1555966d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj   case 0x2CC:
1556066d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj   {
1556166d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj      IRExpr * high64;
1556266d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj      DIP("stxsdx %d,r%u,r%u\n", (UInt)XS, rA_addr, rB_addr);
1556366d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj      high64 = unop( Iop_V128HIto64, mkexpr( vS ) );
155641f5fe1fc3a37ca729925e8eec25aa1025b4a6cdbcarll      store( mkexpr( EA ), high64 );
1556566d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj      break;
1556666d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj   }
1556766d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj   case 0x3CC:
1556866d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj   {
1556966d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj      IRExpr * high64, *low64;
1557066d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj      DIP("stxvd2x %d,r%u,r%u\n", (UInt)XS, rA_addr, rB_addr);
1557166d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj      high64 = unop( Iop_V128HIto64, mkexpr( vS ) );
1557266d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj      low64 = unop( Iop_V128to64, mkexpr( vS ) );
155731f5fe1fc3a37ca729925e8eec25aa1025b4a6cdbcarll      store( mkexpr( EA ), high64 );
155741f5fe1fc3a37ca729925e8eec25aa1025b4a6cdbcarll      store( binop( mkSzOp( ty, Iop_Add8 ), mkexpr( EA ),
155751f5fe1fc3a37ca729925e8eec25aa1025b4a6cdbcarll                    ty == Ity_I64 ? mkU64( 8 ) : mkU32( 8 ) ), low64 );
1557666d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj      break;
1557766d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj   }
1557866d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj   case 0x38C:
1557966d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj   {
1558066d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj      UInt ea_off = 0;
1558166d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj      IRExpr* irx_addr;
1558266d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj      IRTemp hi64 = newTemp( Ity_I64 );
1558366d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj      IRTemp lo64 = newTemp( Ity_I64 );
1558466d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj
1558566d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj      DIP("stxvw4x %d,r%u,r%u\n", (UInt)XS, rA_addr, rB_addr);
1558666d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj
1558766d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj      // This instruction supports word-aligned stores, so EA may not be
1558866d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj      // quad-word aligned.  Therefore, do 4 individual word-size stores.
1558966d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj      assign( hi64, unop( Iop_V128HIto64, mkexpr( vS ) ) );
1559066d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj      assign( lo64, unop( Iop_V128to64, mkexpr( vS ) ) );
155911f5fe1fc3a37ca729925e8eec25aa1025b4a6cdbcarll      store( mkexpr( EA ), unop( Iop_64HIto32, mkexpr( hi64 ) ) );
1559266d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj      ea_off += 4;
1559366d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj      irx_addr = binop( mkSzOp( ty, Iop_Add8 ), mkexpr( EA ),
1559466d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj                        ty == Ity_I64 ? mkU64( ea_off ) : mkU32( ea_off ) );
155951f5fe1fc3a37ca729925e8eec25aa1025b4a6cdbcarll      store( irx_addr, unop( Iop_64to32, mkexpr( hi64 ) ) );
1559666d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj      ea_off += 4;
1559766d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj      irx_addr = binop( mkSzOp( ty, Iop_Add8 ), mkexpr( EA ),
1559866d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj                        ty == Ity_I64 ? mkU64( ea_off ) : mkU32( ea_off ) );
155991f5fe1fc3a37ca729925e8eec25aa1025b4a6cdbcarll      store( irx_addr, unop( Iop_64HIto32, mkexpr( lo64 ) ) );
1560066d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj      ea_off += 4;
1560166d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj      irx_addr = binop( mkSzOp( ty, Iop_Add8 ), mkexpr( EA ),
1560266d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj                        ty == Ity_I64 ? mkU64( ea_off ) : mkU32( ea_off ) );
156031f5fe1fc3a37ca729925e8eec25aa1025b4a6cdbcarll      store( irx_addr, unop( Iop_64to32, mkexpr( lo64 ) ) );
1560466d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj
1560566d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj      break;
1560666d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj   }
1560766d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj   default:
1560866d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj      vex_printf( "dis_vx_store(ppc)(opc2)\n" );
1560966d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj      return False;
1561066d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj   }
1561166d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj   return True;
1561266d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj}
1561366d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj
1561466d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj/*
156154aa412af1d8166cc11f39a6e721df49431d23618sewardj * VSX permute and other miscealleous instructions
1561666d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj */
1561766d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardjstatic Bool
156184aa412af1d8166cc11f39a6e721df49431d23618sewardjdis_vx_permute_misc( UInt theInstr, UInt opc2 )
1561966d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj{
1562066d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj   /* XX3-Form */
1562166d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj   UChar opc1 = ifieldOPC( theInstr );
1562266d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj   UChar XT = ifieldRegXT ( theInstr );
1562366d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj   UChar XA = ifieldRegXA ( theInstr );
1562466d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj   UChar XB = ifieldRegXB ( theInstr );
1562566d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj   IRTemp vT = newTemp( Ity_V128 );
1562666d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj   IRTemp vA = newTemp( Ity_V128 );
1562766d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj   IRTemp vB = newTemp( Ity_V128 );
1562866d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj
1562966d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj   if (opc1 != 0x3C) {
156304aa412af1d8166cc11f39a6e721df49431d23618sewardj      vex_printf( "dis_vx_permute_misc(ppc)(instr)\n" );
1563166d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj      return False;
1563266d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj   }
1563366d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj
1563466d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj   assign( vA, getVSReg( XA ) );
1563566d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj   assign( vB, getVSReg( XB ) );
1563666d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj
1563766d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj   switch (opc2) {
1563866d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj      case 0x8: // xxsldwi (VSX Shift Left Double by Word Immediate)
1563966d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj      {
1564066d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj         UChar SHW = ifieldSHW ( theInstr );
1564166d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj         IRTemp result = newTemp(Ity_V128);
1564266d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj         if ( SHW != 0 ) {
1564366d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj             IRTemp hi = newTemp(Ity_V128);
1564466d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj             IRTemp lo = newTemp(Ity_V128);
1564566d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj             assign( hi, binop(Iop_ShlV128, mkexpr(vA), mkU8(SHW*32)) );
1564666d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj             assign( lo, binop(Iop_ShrV128, mkexpr(vB), mkU8(128-SHW*32)) );
1564766d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj             assign ( result, binop(Iop_OrV128, mkexpr(hi), mkexpr(lo)) );
1564866d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj         } else
1564966d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj             assign ( result, mkexpr(vA) );
1565066d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj         DIP("xxsldwi v%d,v%d,v%d,%d\n", (UInt)XT, (UInt)XA, (UInt)XB, (UInt)SHW);
1565166d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj         putVSReg( XT, mkexpr(result) );
1565266d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj         break;
1565366d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj      }
1565466d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj      case 0x28: // xpermdi (VSX Permute Doubleword Immediate)
1565566d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj      {
1565666d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj         UChar DM = ifieldDM ( theInstr );
1565766d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj         IRTemp hi = newTemp(Ity_I64);
1565866d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj         IRTemp lo = newTemp(Ity_I64);
1565966d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj
1566066d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj         if (DM & 0x2)
1566166d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj           assign( hi, unop(Iop_V128to64, mkexpr(vA)) );
1566266d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj         else
1566366d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj           assign( hi, unop(Iop_V128HIto64, mkexpr(vA)) );
1566466d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj
1566566d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj         if (DM & 0x1)
1566666d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj           assign( lo, unop(Iop_V128to64, mkexpr(vB)) );
1566766d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj         else
1566866d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj           assign( lo, unop(Iop_V128HIto64, mkexpr(vB)) );
1566966d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj
1567066d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj         assign( vT, binop(Iop_64HLtoV128, mkexpr(hi), mkexpr(lo)) );
1567166d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj
1567266d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj         DIP("xxpermdi v%d,v%d,v%d,0x%x\n", (UInt)XT, (UInt)XA, (UInt)XB, (UInt)DM);
1567366d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj         putVSReg( XT, mkexpr( vT ) );
1567466d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj         break;
1567566d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj      }
1567666d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj      case 0x48: // xxmrghw (VSX Merge High Word)
1567766d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj      case 0xc8: // xxmrglw (VSX Merge Low Word)
1567866d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj      {
1567955085f8680acc89d727e321f3b34cae1a8c4093aflorian         const HChar type = (opc2 == 0x48) ? 'h' : 'l';
1568066d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj         IROp word_op = (opc2 == 0x48) ? Iop_V128HIto64 : Iop_V128to64;
1568166d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj         IRTemp a64 = newTemp(Ity_I64);
1568266d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj         IRTemp ahi32 = newTemp(Ity_I32);
1568366d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj         IRTemp alo32 = newTemp(Ity_I32);
1568466d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj         IRTemp b64 = newTemp(Ity_I64);
1568566d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj         IRTemp bhi32 = newTemp(Ity_I32);
1568666d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj         IRTemp blo32 = newTemp(Ity_I32);
1568766d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj
1568866d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj         assign( a64, unop(word_op, mkexpr(vA)) );
1568966d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj         assign( ahi32, unop(Iop_64HIto32, mkexpr(a64)) );
1569066d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj         assign( alo32, unop(Iop_64to32, mkexpr(a64)) );
1569166d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj
1569266d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj         assign( b64, unop(word_op, mkexpr(vB)) );
1569366d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj         assign( bhi32, unop(Iop_64HIto32, mkexpr(b64)) );
1569466d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj         assign( blo32, unop(Iop_64to32, mkexpr(b64)) );
1569566d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj
1569666d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj         assign( vT, binop(Iop_64HLtoV128,
1569766d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj                           binop(Iop_32HLto64, mkexpr(ahi32), mkexpr(bhi32)),
1569866d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj                           binop(Iop_32HLto64, mkexpr(alo32), mkexpr(blo32))) );
1569966d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj
1570066d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj         DIP("xxmrg%cw v%d,v%d,v%d\n", type, (UInt)XT, (UInt)XA, (UInt)XB);
1570166d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj         putVSReg( XT, mkexpr( vT ) );
1570266d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj         break;
1570366d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj      }
157044aa412af1d8166cc11f39a6e721df49431d23618sewardj      case 0x018: // xxsel (VSX Select)
157054aa412af1d8166cc11f39a6e721df49431d23618sewardj      {
157064aa412af1d8166cc11f39a6e721df49431d23618sewardj         UChar XC = ifieldRegXC(theInstr);
157074aa412af1d8166cc11f39a6e721df49431d23618sewardj         IRTemp vC = newTemp( Ity_V128 );
157084aa412af1d8166cc11f39a6e721df49431d23618sewardj         assign( vC, getVSReg( XC ) );
157094aa412af1d8166cc11f39a6e721df49431d23618sewardj         DIP("xxsel v%d,v%d,v%d,v%d\n", (UInt)XT, (UInt)XA, (UInt)XB, (UInt)XC);
157104aa412af1d8166cc11f39a6e721df49431d23618sewardj         /* vD = (vA & ~vC) | (vB & vC) */
157114aa412af1d8166cc11f39a6e721df49431d23618sewardj         putVSReg( XT, binop(Iop_OrV128,
157124aa412af1d8166cc11f39a6e721df49431d23618sewardj            binop(Iop_AndV128, mkexpr(vA), unop(Iop_NotV128, mkexpr(vC))),
157134aa412af1d8166cc11f39a6e721df49431d23618sewardj            binop(Iop_AndV128, mkexpr(vB), mkexpr(vC))) );
157144aa412af1d8166cc11f39a6e721df49431d23618sewardj         break;
157154aa412af1d8166cc11f39a6e721df49431d23618sewardj      }
157164aa412af1d8166cc11f39a6e721df49431d23618sewardj      case 0x148: // xxspltw (VSX Splat Word)
157174aa412af1d8166cc11f39a6e721df49431d23618sewardj      {
157184aa412af1d8166cc11f39a6e721df49431d23618sewardj         UChar UIM   = ifieldRegA(theInstr) & 3;
157194aa412af1d8166cc11f39a6e721df49431d23618sewardj         UChar sh_uim = (3 - (UIM)) * 32;
157204aa412af1d8166cc11f39a6e721df49431d23618sewardj         DIP("xxspltw v%d,v%d,%d\n", (UInt)XT, (UInt)XB, UIM);
157214aa412af1d8166cc11f39a6e721df49431d23618sewardj         putVSReg( XT,
157224aa412af1d8166cc11f39a6e721df49431d23618sewardj                   unop( Iop_Dup32x4,
157234aa412af1d8166cc11f39a6e721df49431d23618sewardj                         unop( Iop_V128to32,
157244aa412af1d8166cc11f39a6e721df49431d23618sewardj                               binop( Iop_ShrV128, mkexpr( vB ), mkU8( sh_uim ) ) ) ) );
157254aa412af1d8166cc11f39a6e721df49431d23618sewardj         break;
157264aa412af1d8166cc11f39a6e721df49431d23618sewardj      }
1572766d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj
1572866d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj      default:
157294aa412af1d8166cc11f39a6e721df49431d23618sewardj         vex_printf( "dis_vx_permute_misc(ppc)(opc2)\n" );
1573066d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj         return False;
1573166d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj   }
1573266d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj   return True;
1573366d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj}
1573466d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj
1573566d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj/*
15736b51f0f4f33256638ed953156a2635aa739b232f1sewardj  AltiVec Load Instructions
15737a982c0503d8c0c6069ae453bfe70657bd2c134aecerion*/
15738cacba8e675988fbf21b08feea1f317a9c896c053florianstatic Bool dis_av_load ( const VexAbiInfo* vbi, UInt theInstr )
15739a982c0503d8c0c6069ae453bfe70657bd2c134aecerion{
1574076de5cf615380b23b4b5bcced6541233cd4a93a0cerion   /* X-Form */
1574176de5cf615380b23b4b5bcced6541233cd4a93a0cerion   UChar opc1     = ifieldOPC(theInstr);
1574276de5cf615380b23b4b5bcced6541233cd4a93a0cerion   UChar vD_addr  = ifieldRegDS(theInstr);
1574376de5cf615380b23b4b5bcced6541233cd4a93a0cerion   UChar rA_addr  = ifieldRegA(theInstr);
1574476de5cf615380b23b4b5bcced6541233cd4a93a0cerion   UChar rB_addr  = ifieldRegB(theInstr);
1574576de5cf615380b23b4b5bcced6541233cd4a93a0cerion   UInt  opc2     = ifieldOPClo10(theInstr);
1574676de5cf615380b23b4b5bcced6541233cd4a93a0cerion   UChar b0       = ifieldBIT0(theInstr);
15747b51f0f4f33256638ed953156a2635aa739b232f1sewardj
15748fb197c49c89d04987ef801657b2bedc4050e1539cerion   IRType ty         = mode64 ? Ity_I64 : Ity_I32;
15749fb197c49c89d04987ef801657b2bedc4050e1539cerion   IRTemp EA         = newTemp(ty);
15750fb197c49c89d04987ef801657b2bedc4050e1539cerion   IRTemp EA_align16 = newTemp(ty);
157512831b00c4950d6c2b061def05fd67528fe132ececerion
15752b51f0f4f33256638ed953156a2635aa739b232f1sewardj   if (opc1 != 0x1F || b0 != 0) {
157535b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion      vex_printf("dis_av_load(ppc)(instr)\n");
15754a982c0503d8c0c6069ae453bfe70657bd2c134aecerion      return False;
15755a982c0503d8c0c6069ae453bfe70657bd2c134aecerion   }
15756a982c0503d8c0c6069ae453bfe70657bd2c134aecerion
15757fb197c49c89d04987ef801657b2bedc4050e1539cerion   assign( EA, ea_rAor0_idxd(rA_addr, rB_addr) );
15758fb197c49c89d04987ef801657b2bedc4050e1539cerion   assign( EA_align16, addr_align( mkexpr(EA), 16 ) );
15759b51f0f4f33256638ed953156a2635aa739b232f1sewardj
15760a982c0503d8c0c6069ae453bfe70657bd2c134aecerion   switch (opc2) {
15761a982c0503d8c0c6069ae453bfe70657bd2c134aecerion
157626f6c6a0d6a601af3137f861f5fc9d76365c48e96cerion   case 0x006: { // lvsl (Load Vector for Shift Left, AV p123)
15763fb197c49c89d04987ef801657b2bedc4050e1539cerion      IRDirty* d;
15764d14709407df9363767aa888b03f95f08df169dcesewardj      UInt vD_off = vectorGuestRegOffset(vD_addr);
157651f5fe1fc3a37ca729925e8eec25aa1025b4a6cdbcarll      IRExpr** args_be = mkIRExprVec_5(
157669041956f39c57e265122ed0a71061dea1e554edcflorian                         IRExpr_BBPTR(),
157671f5fe1fc3a37ca729925e8eec25aa1025b4a6cdbcarll                         mkU32(vD_off),
15768e9d8a26b690c2561ac54ab0cd6ad83ecbadcbe76sewardj                         binop(Iop_And32, mkNarrowTo32(ty, mkexpr(EA)),
15769fb197c49c89d04987ef801657b2bedc4050e1539cerion                                          mkU32(0xF)),
157701f5fe1fc3a37ca729925e8eec25aa1025b4a6cdbcarll                         mkU32(0)/*left*/,
157711f5fe1fc3a37ca729925e8eec25aa1025b4a6cdbcarll                         mkU32(1)/*Big Endian*/);
157721f5fe1fc3a37ca729925e8eec25aa1025b4a6cdbcarll      IRExpr** args_le = mkIRExprVec_5(
157731f5fe1fc3a37ca729925e8eec25aa1025b4a6cdbcarll                         IRExpr_BBPTR(),
157741f5fe1fc3a37ca729925e8eec25aa1025b4a6cdbcarll                         mkU32(vD_off),
157751f5fe1fc3a37ca729925e8eec25aa1025b4a6cdbcarll                         binop(Iop_And32, mkNarrowTo32(ty, mkexpr(EA)),
157761f5fe1fc3a37ca729925e8eec25aa1025b4a6cdbcarll                                          mkU32(0xF)),
157771f5fe1fc3a37ca729925e8eec25aa1025b4a6cdbcarll                         mkU32(0)/*left*/,
157781f5fe1fc3a37ca729925e8eec25aa1025b4a6cdbcarll                         mkU32(0)/*Little Endian*/);
157795b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion      if (!mode64) {
157804c4f5ef69f89a19844a22a34b7a0cb717f83f033cerion         d = unsafeIRDirty_0_N (
157814c4f5ef69f89a19844a22a34b7a0cb717f83f033cerion                        0/*regparms*/,
157824c4f5ef69f89a19844a22a34b7a0cb717f83f033cerion                        "ppc32g_dirtyhelper_LVS",
15783dd40fdf58cc8a6fe9466c4f00bdfc9fe9bf00449sewardj                        fnptr_to_fnentry(vbi, &ppc32g_dirtyhelper_LVS),
157841f5fe1fc3a37ca729925e8eec25aa1025b4a6cdbcarll                        args_be );
157855b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion      } else {
157861f5fe1fc3a37ca729925e8eec25aa1025b4a6cdbcarll         if (host_endness == VexEndnessBE)
157871f5fe1fc3a37ca729925e8eec25aa1025b4a6cdbcarll            d = unsafeIRDirty_0_N (
157881f5fe1fc3a37ca729925e8eec25aa1025b4a6cdbcarll                           0/*regparms*/,
157891f5fe1fc3a37ca729925e8eec25aa1025b4a6cdbcarll                           "ppc64g_dirtyhelper_LVS",
157901f5fe1fc3a37ca729925e8eec25aa1025b4a6cdbcarll                           fnptr_to_fnentry(vbi, &ppc64g_dirtyhelper_LVS),
157911f5fe1fc3a37ca729925e8eec25aa1025b4a6cdbcarll                           args_be );
157921f5fe1fc3a37ca729925e8eec25aa1025b4a6cdbcarll         else
157931f5fe1fc3a37ca729925e8eec25aa1025b4a6cdbcarll            d = unsafeIRDirty_0_N (
157941f5fe1fc3a37ca729925e8eec25aa1025b4a6cdbcarll                           0/*regparms*/,
157951f5fe1fc3a37ca729925e8eec25aa1025b4a6cdbcarll                           "ppc64g_dirtyhelper_LVS",
157961f5fe1fc3a37ca729925e8eec25aa1025b4a6cdbcarll                           &ppc64g_dirtyhelper_LVS,
157971f5fe1fc3a37ca729925e8eec25aa1025b4a6cdbcarll                           args_le );
157985b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion      }
15799d953ebb9b04cbad6891676df597bf0c542b1ec89cerion      DIP("lvsl v%d,r%u,r%u\n", vD_addr, rA_addr, rB_addr);
158006f6c6a0d6a601af3137f861f5fc9d76365c48e96cerion      /* declare guest state effects */
158016f6c6a0d6a601af3137f861f5fc9d76365c48e96cerion      d->nFxState = 1;
15802c9069f2908814843e9a4da00da9c8905440195a6sewardj      vex_bzero(&d->fxState, sizeof(d->fxState));
158036f6c6a0d6a601af3137f861f5fc9d76365c48e96cerion      d->fxState[0].fx     = Ifx_Write;
15804d14709407df9363767aa888b03f95f08df169dcesewardj      d->fxState[0].offset = vD_off;
158056f6c6a0d6a601af3137f861f5fc9d76365c48e96cerion      d->fxState[0].size   = sizeof(U128);
158066f6c6a0d6a601af3137f861f5fc9d76365c48e96cerion
158076f6c6a0d6a601af3137f861f5fc9d76365c48e96cerion      /* execute the dirty call, side-effecting guest state */
158086f6c6a0d6a601af3137f861f5fc9d76365c48e96cerion      stmt( IRStmt_Dirty(d) );
158096f6c6a0d6a601af3137f861f5fc9d76365c48e96cerion      break;
158106f6c6a0d6a601af3137f861f5fc9d76365c48e96cerion   }
158116f6c6a0d6a601af3137f861f5fc9d76365c48e96cerion   case 0x026: { // lvsr (Load Vector for Shift Right, AV p125)
15812fb197c49c89d04987ef801657b2bedc4050e1539cerion      IRDirty* d;
15813d14709407df9363767aa888b03f95f08df169dcesewardj      UInt vD_off = vectorGuestRegOffset(vD_addr);
158141f5fe1fc3a37ca729925e8eec25aa1025b4a6cdbcarll      IRExpr** args_be = mkIRExprVec_5(
158151f5fe1fc3a37ca729925e8eec25aa1025b4a6cdbcarll                             IRExpr_BBPTR(),
158161f5fe1fc3a37ca729925e8eec25aa1025b4a6cdbcarll                             mkU32(vD_off),
158171f5fe1fc3a37ca729925e8eec25aa1025b4a6cdbcarll                             binop(Iop_And32, mkNarrowTo32(ty, mkexpr(EA)),
158181f5fe1fc3a37ca729925e8eec25aa1025b4a6cdbcarll                                              mkU32(0xF)),
158191f5fe1fc3a37ca729925e8eec25aa1025b4a6cdbcarll                             mkU32(1)/*right*/,
158201f5fe1fc3a37ca729925e8eec25aa1025b4a6cdbcarll                             mkU32(1)/*Big Endian*/);
158211f5fe1fc3a37ca729925e8eec25aa1025b4a6cdbcarll      IRExpr** args_le = mkIRExprVec_5(
158221f5fe1fc3a37ca729925e8eec25aa1025b4a6cdbcarll                             IRExpr_BBPTR(),
158231f5fe1fc3a37ca729925e8eec25aa1025b4a6cdbcarll                             mkU32(vD_off),
158241f5fe1fc3a37ca729925e8eec25aa1025b4a6cdbcarll                             binop(Iop_And32, mkNarrowTo32(ty, mkexpr(EA)),
158251f5fe1fc3a37ca729925e8eec25aa1025b4a6cdbcarll                                              mkU32(0xF)),
158261f5fe1fc3a37ca729925e8eec25aa1025b4a6cdbcarll                             mkU32(1)/*right*/,
158271f5fe1fc3a37ca729925e8eec25aa1025b4a6cdbcarll                             mkU32(0)/*Little Endian*/);
158281f5fe1fc3a37ca729925e8eec25aa1025b4a6cdbcarll
158295b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion      if (!mode64) {
158304c4f5ef69f89a19844a22a34b7a0cb717f83f033cerion         d = unsafeIRDirty_0_N (
158311f5fe1fc3a37ca729925e8eec25aa1025b4a6cdbcarll                        0/*regparms*/,
158324c4f5ef69f89a19844a22a34b7a0cb717f83f033cerion                        "ppc32g_dirtyhelper_LVS",
15833dd40fdf58cc8a6fe9466c4f00bdfc9fe9bf00449sewardj                        fnptr_to_fnentry(vbi, &ppc32g_dirtyhelper_LVS),
158341f5fe1fc3a37ca729925e8eec25aa1025b4a6cdbcarll                        args_be );
158355b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion      } else {
158361f5fe1fc3a37ca729925e8eec25aa1025b4a6cdbcarll         if (host_endness == VexEndnessBE)
158371f5fe1fc3a37ca729925e8eec25aa1025b4a6cdbcarll            d = unsafeIRDirty_0_N (
158381f5fe1fc3a37ca729925e8eec25aa1025b4a6cdbcarll                           0/*regparms*/,
158391f5fe1fc3a37ca729925e8eec25aa1025b4a6cdbcarll                           "ppc64g_dirtyhelper_LVS",
158401f5fe1fc3a37ca729925e8eec25aa1025b4a6cdbcarll                           fnptr_to_fnentry(vbi, &ppc64g_dirtyhelper_LVS),
158411f5fe1fc3a37ca729925e8eec25aa1025b4a6cdbcarll                           args_be );
158421f5fe1fc3a37ca729925e8eec25aa1025b4a6cdbcarll         else
158431f5fe1fc3a37ca729925e8eec25aa1025b4a6cdbcarll            d = unsafeIRDirty_0_N (
158441f5fe1fc3a37ca729925e8eec25aa1025b4a6cdbcarll                           0/*regparms*/,
158451f5fe1fc3a37ca729925e8eec25aa1025b4a6cdbcarll                           "ppc64g_dirtyhelper_LVS",
158461f5fe1fc3a37ca729925e8eec25aa1025b4a6cdbcarll                           &ppc64g_dirtyhelper_LVS,
158471f5fe1fc3a37ca729925e8eec25aa1025b4a6cdbcarll                           args_le );
158485b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion      }
15849d953ebb9b04cbad6891676df597bf0c542b1ec89cerion      DIP("lvsr v%d,r%u,r%u\n", vD_addr, rA_addr, rB_addr);
158506f6c6a0d6a601af3137f861f5fc9d76365c48e96cerion      /* declare guest state effects */
158516f6c6a0d6a601af3137f861f5fc9d76365c48e96cerion      d->nFxState = 1;
15852c9069f2908814843e9a4da00da9c8905440195a6sewardj      vex_bzero(&d->fxState, sizeof(d->fxState));
158536f6c6a0d6a601af3137f861f5fc9d76365c48e96cerion      d->fxState[0].fx     = Ifx_Write;
15854d14709407df9363767aa888b03f95f08df169dcesewardj      d->fxState[0].offset = vD_off;
158556f6c6a0d6a601af3137f861f5fc9d76365c48e96cerion      d->fxState[0].size   = sizeof(U128);
158566f6c6a0d6a601af3137f861f5fc9d76365c48e96cerion
158576f6c6a0d6a601af3137f861f5fc9d76365c48e96cerion      /* execute the dirty call, side-effecting guest state */
158586f6c6a0d6a601af3137f861f5fc9d76365c48e96cerion      stmt( IRStmt_Dirty(d) );
158596f6c6a0d6a601af3137f861f5fc9d76365c48e96cerion      break;
158606f6c6a0d6a601af3137f861f5fc9d76365c48e96cerion   }
1586132aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion   case 0x007: // lvebx (Load Vector Element Byte Indexed, AV p119)
15862d953ebb9b04cbad6891676df597bf0c542b1ec89cerion      DIP("lvebx v%d,r%u,r%u\n", vD_addr, rA_addr, rB_addr);
1586361c92742ac68a38d61602eaac047ae79f07ff06ecerion      /* loads addressed byte into vector[EA[0:3]
1586461c92742ac68a38d61602eaac047ae79f07ff06ecerion         since all other destination bytes are undefined,
1586561c92742ac68a38d61602eaac047ae79f07ff06ecerion         can simply load entire vector from 16-aligned EA */
158661f5fe1fc3a37ca729925e8eec25aa1025b4a6cdbcarll      putVReg( vD_addr, load(Ity_V128, mkexpr(EA_align16)) );
1586761c92742ac68a38d61602eaac047ae79f07ff06ecerion      break;
1586832aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion
1586932aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion   case 0x027: // lvehx (Load Vector Element Half Word Indexed, AV p121)
15870d953ebb9b04cbad6891676df597bf0c542b1ec89cerion      DIP("lvehx v%d,r%u,r%u\n", vD_addr, rA_addr, rB_addr);
1587161c92742ac68a38d61602eaac047ae79f07ff06ecerion      /* see note for lvebx */
158721f5fe1fc3a37ca729925e8eec25aa1025b4a6cdbcarll      putVReg( vD_addr, load(Ity_V128, mkexpr(EA_align16)) );
1587361c92742ac68a38d61602eaac047ae79f07ff06ecerion      break;
1587432aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion
1587532aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion   case 0x047: // lvewx (Load Vector Element Word Indexed, AV p122)
15876d953ebb9b04cbad6891676df597bf0c542b1ec89cerion      DIP("lvewx v%d,r%u,r%u\n", vD_addr, rA_addr, rB_addr);
1587761c92742ac68a38d61602eaac047ae79f07ff06ecerion      /* see note for lvebx */
158781f5fe1fc3a37ca729925e8eec25aa1025b4a6cdbcarll      putVReg( vD_addr, load(Ity_V128, mkexpr(EA_align16)) );
1587961c92742ac68a38d61602eaac047ae79f07ff06ecerion      break;
15880a982c0503d8c0c6069ae453bfe70657bd2c134aecerion
15881b51f0f4f33256638ed953156a2635aa739b232f1sewardj   case 0x067: // lvx (Load Vector Indexed, AV p127)
15882d953ebb9b04cbad6891676df597bf0c542b1ec89cerion      DIP("lvx v%d,r%u,r%u\n", vD_addr, rA_addr, rB_addr);
158831f5fe1fc3a37ca729925e8eec25aa1025b4a6cdbcarll      putVReg( vD_addr, load(Ity_V128, mkexpr(EA_align16)) );
15884b51f0f4f33256638ed953156a2635aa739b232f1sewardj      break;
15885a982c0503d8c0c6069ae453bfe70657bd2c134aecerion
1588632aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion   case 0x167: // lvxl (Load Vector Indexed LRU, AV p128)
15887d953ebb9b04cbad6891676df597bf0c542b1ec89cerion      DIP("lvxl v%d,r%u,r%u\n", vD_addr, rA_addr, rB_addr);
158881f5fe1fc3a37ca729925e8eec25aa1025b4a6cdbcarll      putVReg( vD_addr, load(Ity_V128, mkexpr(EA_align16)) );
15889d2fd864dcbe236580d4f2c9417b6fd98ff6e55d7sewardj      break;
15890a982c0503d8c0c6069ae453bfe70657bd2c134aecerion
15891a982c0503d8c0c6069ae453bfe70657bd2c134aecerion   default:
158925b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion      vex_printf("dis_av_load(ppc)(opc2)\n");
15893a982c0503d8c0c6069ae453bfe70657bd2c134aecerion      return False;
15894a982c0503d8c0c6069ae453bfe70657bd2c134aecerion   }
15895a982c0503d8c0c6069ae453bfe70657bd2c134aecerion   return True;
15896a982c0503d8c0c6069ae453bfe70657bd2c134aecerion}
15897a982c0503d8c0c6069ae453bfe70657bd2c134aecerion
15898a982c0503d8c0c6069ae453bfe70657bd2c134aecerion/*
15899b51f0f4f33256638ed953156a2635aa739b232f1sewardj  AltiVec Store Instructions
15900a982c0503d8c0c6069ae453bfe70657bd2c134aecerion*/
15901b51f0f4f33256638ed953156a2635aa739b232f1sewardjstatic Bool dis_av_store ( UInt theInstr )
15902a982c0503d8c0c6069ae453bfe70657bd2c134aecerion{
1590376de5cf615380b23b4b5bcced6541233cd4a93a0cerion   /* X-Form */
1590476de5cf615380b23b4b5bcced6541233cd4a93a0cerion   UChar opc1     = ifieldOPC(theInstr);
1590576de5cf615380b23b4b5bcced6541233cd4a93a0cerion   UChar vS_addr  = ifieldRegDS(theInstr);
1590676de5cf615380b23b4b5bcced6541233cd4a93a0cerion   UChar rA_addr  = ifieldRegA(theInstr);
1590776de5cf615380b23b4b5bcced6541233cd4a93a0cerion   UChar rB_addr  = ifieldRegB(theInstr);
1590876de5cf615380b23b4b5bcced6541233cd4a93a0cerion   UInt  opc2     = ifieldOPClo10(theInstr);
1590976de5cf615380b23b4b5bcced6541233cd4a93a0cerion   UChar b0       = ifieldBIT0(theInstr);
15910a982c0503d8c0c6069ae453bfe70657bd2c134aecerion
159112831b00c4950d6c2b061def05fd67528fe132ececerion   IRType ty           = mode64 ? Ity_I64 : Ity_I32;
159122831b00c4950d6c2b061def05fd67528fe132ececerion   IRTemp EA           = newTemp(ty);
15913dba87e2eb883914b8c1bc3ef05a1147dd4f930eacerion   IRTemp addr_aligned = newTemp(ty);
159142831b00c4950d6c2b061def05fd67528fe132ececerion   IRTemp vS           = newTemp(Ity_V128);
159152831b00c4950d6c2b061def05fd67528fe132ececerion   IRTemp eb           = newTemp(Ity_I8);
159162831b00c4950d6c2b061def05fd67528fe132ececerion   IRTemp idx          = newTemp(Ity_I8);
15917a982c0503d8c0c6069ae453bfe70657bd2c134aecerion
15918b51f0f4f33256638ed953156a2635aa739b232f1sewardj   if (opc1 != 0x1F || b0 != 0) {
159195b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion      vex_printf("dis_av_store(ppc)(instr)\n");
15920a982c0503d8c0c6069ae453bfe70657bd2c134aecerion      return False;
15921a982c0503d8c0c6069ae453bfe70657bd2c134aecerion   }
15922a982c0503d8c0c6069ae453bfe70657bd2c134aecerion
15923d953ebb9b04cbad6891676df597bf0c542b1ec89cerion   assign( vS, getVReg(vS_addr));
159242831b00c4950d6c2b061def05fd67528fe132ececerion   assign( EA, ea_rAor0_idxd(rA_addr, rB_addr) );
15925d953ebb9b04cbad6891676df597bf0c542b1ec89cerion
15926a982c0503d8c0c6069ae453bfe70657bd2c134aecerion   switch (opc2) {
1592761c92742ac68a38d61602eaac047ae79f07ff06ecerion   case 0x087: { // stvebx (Store Vector Byte Indexed, AV p131)
15928d953ebb9b04cbad6891676df597bf0c542b1ec89cerion      DIP("stvebx v%d,r%u,r%u\n", vS_addr, rA_addr, rB_addr);
1592961c92742ac68a38d61602eaac047ae79f07ff06ecerion      assign( eb, binop(Iop_And8, mkU8(0xF),
159302831b00c4950d6c2b061def05fd67528fe132ececerion                        unop(Iop_32to8,
15931e9d8a26b690c2561ac54ab0cd6ad83ecbadcbe76sewardj                             mkNarrowTo32(ty, mkexpr(EA)) )) );
159321f5fe1fc3a37ca729925e8eec25aa1025b4a6cdbcarll     if (host_endness == VexEndnessLE) {
159331f5fe1fc3a37ca729925e8eec25aa1025b4a6cdbcarll         assign( idx, binop(Iop_Shl8, mkexpr(eb), mkU8(3)) );
159341f5fe1fc3a37ca729925e8eec25aa1025b4a6cdbcarll      } else {
159351f5fe1fc3a37ca729925e8eec25aa1025b4a6cdbcarll         assign( idx, binop(Iop_Shl8,
159361f5fe1fc3a37ca729925e8eec25aa1025b4a6cdbcarll                            binop(Iop_Sub8, mkU8(15), mkexpr(eb)),
159371f5fe1fc3a37ca729925e8eec25aa1025b4a6cdbcarll                            mkU8(3)) );
159381f5fe1fc3a37ca729925e8eec25aa1025b4a6cdbcarll      }
159391f5fe1fc3a37ca729925e8eec25aa1025b4a6cdbcarll      store( mkexpr(EA),
159401f5fe1fc3a37ca729925e8eec25aa1025b4a6cdbcarll             unop( Iop_32to8, unop(Iop_V128to32,
159411f5fe1fc3a37ca729925e8eec25aa1025b4a6cdbcarll                   binop(Iop_ShrV128, mkexpr(vS), mkexpr(idx)))) );
1594261c92742ac68a38d61602eaac047ae79f07ff06ecerion      break;
1594361c92742ac68a38d61602eaac047ae79f07ff06ecerion   }
1594461c92742ac68a38d61602eaac047ae79f07ff06ecerion   case 0x0A7: { // stvehx (Store Vector Half Word Indexed, AV p132)
15945d953ebb9b04cbad6891676df597bf0c542b1ec89cerion      DIP("stvehx v%d,r%u,r%u\n", vS_addr, rA_addr, rB_addr);
15946dba87e2eb883914b8c1bc3ef05a1147dd4f930eacerion      assign( addr_aligned, addr_align(mkexpr(EA), 2) );
1594761c92742ac68a38d61602eaac047ae79f07ff06ecerion      assign( eb, binop(Iop_And8, mkU8(0xF),
15948e9d8a26b690c2561ac54ab0cd6ad83ecbadcbe76sewardj                        mkNarrowTo8(ty, mkexpr(addr_aligned) )) );
159491f5fe1fc3a37ca729925e8eec25aa1025b4a6cdbcarll      if (host_endness == VexEndnessLE) {
159501f5fe1fc3a37ca729925e8eec25aa1025b4a6cdbcarll          assign( idx, binop(Iop_Shl8, mkexpr(eb), mkU8(3)) );
159511f5fe1fc3a37ca729925e8eec25aa1025b4a6cdbcarll      } else {
159521f5fe1fc3a37ca729925e8eec25aa1025b4a6cdbcarll         assign( idx, binop(Iop_Shl8,
159531f5fe1fc3a37ca729925e8eec25aa1025b4a6cdbcarll                            binop(Iop_Sub8, mkU8(14), mkexpr(eb)),
159541f5fe1fc3a37ca729925e8eec25aa1025b4a6cdbcarll                            mkU8(3)) );
159551f5fe1fc3a37ca729925e8eec25aa1025b4a6cdbcarll      }
159561f5fe1fc3a37ca729925e8eec25aa1025b4a6cdbcarll      store( mkexpr(addr_aligned),
159571f5fe1fc3a37ca729925e8eec25aa1025b4a6cdbcarll             unop( Iop_32to16, unop(Iop_V128to32,
159581f5fe1fc3a37ca729925e8eec25aa1025b4a6cdbcarll                   binop(Iop_ShrV128, mkexpr(vS), mkexpr(idx)))) );
1595961c92742ac68a38d61602eaac047ae79f07ff06ecerion      break;
1596061c92742ac68a38d61602eaac047ae79f07ff06ecerion   }
1596161c92742ac68a38d61602eaac047ae79f07ff06ecerion   case 0x0C7: { // stvewx (Store Vector Word Indexed, AV p133)
15962d953ebb9b04cbad6891676df597bf0c542b1ec89cerion      DIP("stvewx v%d,r%u,r%u\n", vS_addr, rA_addr, rB_addr);
15963dba87e2eb883914b8c1bc3ef05a1147dd4f930eacerion      assign( addr_aligned, addr_align(mkexpr(EA), 4) );
1596461c92742ac68a38d61602eaac047ae79f07ff06ecerion      assign( eb, binop(Iop_And8, mkU8(0xF),
15965e9d8a26b690c2561ac54ab0cd6ad83ecbadcbe76sewardj                        mkNarrowTo8(ty, mkexpr(addr_aligned) )) );
159661f5fe1fc3a37ca729925e8eec25aa1025b4a6cdbcarll      if (host_endness == VexEndnessLE) {
159671f5fe1fc3a37ca729925e8eec25aa1025b4a6cdbcarll         assign( idx, binop(Iop_Shl8, mkexpr(eb), mkU8(3)) );
159681f5fe1fc3a37ca729925e8eec25aa1025b4a6cdbcarll      } else {
159691f5fe1fc3a37ca729925e8eec25aa1025b4a6cdbcarll         assign( idx, binop(Iop_Shl8,
159701f5fe1fc3a37ca729925e8eec25aa1025b4a6cdbcarll                            binop(Iop_Sub8, mkU8(12), mkexpr(eb)),
159711f5fe1fc3a37ca729925e8eec25aa1025b4a6cdbcarll                            mkU8(3)) );
159721f5fe1fc3a37ca729925e8eec25aa1025b4a6cdbcarll      }
159731f5fe1fc3a37ca729925e8eec25aa1025b4a6cdbcarll      store( mkexpr( addr_aligned),
159741f5fe1fc3a37ca729925e8eec25aa1025b4a6cdbcarll             unop( Iop_V128to32,
159751f5fe1fc3a37ca729925e8eec25aa1025b4a6cdbcarll                   binop(Iop_ShrV128, mkexpr(vS), mkexpr(idx))) );
1597661c92742ac68a38d61602eaac047ae79f07ff06ecerion      break;
1597761c92742ac68a38d61602eaac047ae79f07ff06ecerion   }
1597832aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion
15979b51f0f4f33256638ed953156a2635aa739b232f1sewardj   case 0x0E7: // stvx (Store Vector Indexed, AV p134)
15980d953ebb9b04cbad6891676df597bf0c542b1ec89cerion      DIP("stvx v%d,r%u,r%u\n", vS_addr, rA_addr, rB_addr);
159811f5fe1fc3a37ca729925e8eec25aa1025b4a6cdbcarll      store( addr_align( mkexpr(EA), 16 ), mkexpr(vS) );
15982b51f0f4f33256638ed953156a2635aa739b232f1sewardj      break;
15983a982c0503d8c0c6069ae453bfe70657bd2c134aecerion
1598432aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion   case 0x1E7: // stvxl (Store Vector Indexed LRU, AV p135)
15985d953ebb9b04cbad6891676df597bf0c542b1ec89cerion      DIP("stvxl v%d,r%u,r%u\n", vS_addr, rA_addr, rB_addr);
159861f5fe1fc3a37ca729925e8eec25aa1025b4a6cdbcarll      store( addr_align( mkexpr(EA), 16 ), mkexpr(vS) );
15987d2fd864dcbe236580d4f2c9417b6fd98ff6e55d7sewardj      break;
15988a982c0503d8c0c6069ae453bfe70657bd2c134aecerion
15989a982c0503d8c0c6069ae453bfe70657bd2c134aecerion   default:
159905b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion      vex_printf("dis_av_store(ppc)(opc2)\n");
15991a982c0503d8c0c6069ae453bfe70657bd2c134aecerion      return False;
15992a982c0503d8c0c6069ae453bfe70657bd2c134aecerion   }
15993a982c0503d8c0c6069ae453bfe70657bd2c134aecerion   return True;
15994a982c0503d8c0c6069ae453bfe70657bd2c134aecerion}
15995a982c0503d8c0c6069ae453bfe70657bd2c134aecerion
1599632aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion/*
1599732aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion  AltiVec Arithmetic Instructions
1599832aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion*/
1599932aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerionstatic Bool dis_av_arith ( UInt theInstr )
1600032aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion{
1600176de5cf615380b23b4b5bcced6541233cd4a93a0cerion   /* VX-Form */
1600276de5cf615380b23b4b5bcced6541233cd4a93a0cerion   UChar opc1     = ifieldOPC(theInstr);
1600376de5cf615380b23b4b5bcced6541233cd4a93a0cerion   UChar vD_addr  = ifieldRegDS(theInstr);
1600476de5cf615380b23b4b5bcced6541233cd4a93a0cerion   UChar vA_addr  = ifieldRegA(theInstr);
1600576de5cf615380b23b4b5bcced6541233cd4a93a0cerion   UChar vB_addr  = ifieldRegB(theInstr);
1600676de5cf615380b23b4b5bcced6541233cd4a93a0cerion   UInt  opc2     = IFIELD( theInstr, 0, 11 );
1600732aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion
16008d3e52410a03147c36dbf977a37e77a4de246f7c9cerion   IRTemp vA = newTemp(Ity_V128);
16009d3e52410a03147c36dbf977a37e77a4de246f7c9cerion   IRTemp vB = newTemp(Ity_V128);
160104a49b0393204185f87664ea58f2b7a2ae1d37338cerion   IRTemp z3 = newTemp(Ity_I64);
160114a49b0393204185f87664ea58f2b7a2ae1d37338cerion   IRTemp z2 = newTemp(Ity_I64);
160124a49b0393204185f87664ea58f2b7a2ae1d37338cerion   IRTemp z1 = newTemp(Ity_I64);
160134a49b0393204185f87664ea58f2b7a2ae1d37338cerion   IRTemp z0 = newTemp(Ity_I64);
160144a49b0393204185f87664ea58f2b7a2ae1d37338cerion   IRTemp aEvn, aOdd;
160154a49b0393204185f87664ea58f2b7a2ae1d37338cerion   IRTemp a15, a14, a13, a12, a11, a10, a9, a8;
160164a49b0393204185f87664ea58f2b7a2ae1d37338cerion   IRTemp a7, a6, a5, a4, a3, a2, a1, a0;
160174a49b0393204185f87664ea58f2b7a2ae1d37338cerion   IRTemp b3, b2, b1, b0;
160184a49b0393204185f87664ea58f2b7a2ae1d37338cerion
160194a49b0393204185f87664ea58f2b7a2ae1d37338cerion   aEvn = aOdd = IRTemp_INVALID;
160204a49b0393204185f87664ea58f2b7a2ae1d37338cerion   a15 = a14 = a13 = a12 = a11 = a10 = a9 = a8 = IRTemp_INVALID;
160214a49b0393204185f87664ea58f2b7a2ae1d37338cerion   a7 = a6 = a5 = a4 = a3 = a2 = a1 = a0 = IRTemp_INVALID;
160224a49b0393204185f87664ea58f2b7a2ae1d37338cerion   b3 = b2 = b1 = b0 = IRTemp_INVALID;
160234a49b0393204185f87664ea58f2b7a2ae1d37338cerion
16024d3e52410a03147c36dbf977a37e77a4de246f7c9cerion   assign( vA, getVReg(vA_addr));
16025d3e52410a03147c36dbf977a37e77a4de246f7c9cerion   assign( vB, getVReg(vB_addr));
16026d3e52410a03147c36dbf977a37e77a4de246f7c9cerion
1602732aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion   if (opc1 != 0x4) {
160285b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion      vex_printf("dis_av_arith(ppc)(opc1 != 0x4)\n");
1602932aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion      return False;
1603032aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion   }
1603132aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion
1603232aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion   switch (opc2) {
1603332aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion   /* Add */
16034d3e52410a03147c36dbf977a37e77a4de246f7c9cerion   case 0x180: { // vaddcuw (Add Carryout Unsigned Word, AV p136)
1603532aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion      DIP("vaddcuw v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
1603636991efdccc3af11ee9691dfa5297872dfb88312cerion      /* unsigned_ov(x+y) = (y >u not(x)) */
16037d3e52410a03147c36dbf977a37e77a4de246f7c9cerion      putVReg( vD_addr, binop(Iop_ShrN32x4,
1603836991efdccc3af11ee9691dfa5297872dfb88312cerion                              binop(Iop_CmpGT32Ux4, mkexpr(vB),
1603936991efdccc3af11ee9691dfa5297872dfb88312cerion                                    unop(Iop_NotV128, mkexpr(vA))),
16040d3e52410a03147c36dbf977a37e77a4de246f7c9cerion                              mkU8(31)) );
16041d3e52410a03147c36dbf977a37e77a4de246f7c9cerion      break;
16042d3e52410a03147c36dbf977a37e77a4de246f7c9cerion   }
1604332aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion   case 0x000: // vaddubm (Add Unsigned Byte Modulo, AV p141)
1604432aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion      DIP("vaddubm v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
1604536991efdccc3af11ee9691dfa5297872dfb88312cerion      putVReg( vD_addr, binop(Iop_Add8x16, mkexpr(vA), mkexpr(vB)) );
1604636991efdccc3af11ee9691dfa5297872dfb88312cerion      break;
1604736991efdccc3af11ee9691dfa5297872dfb88312cerion
1604832aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion   case 0x040: // vadduhm (Add Unsigned Half Word Modulo, AV p143)
1604932aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion      DIP("vadduhm v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
1605036991efdccc3af11ee9691dfa5297872dfb88312cerion      putVReg( vD_addr, binop(Iop_Add16x8, mkexpr(vA), mkexpr(vB)) );
1605136991efdccc3af11ee9691dfa5297872dfb88312cerion      break;
1605236991efdccc3af11ee9691dfa5297872dfb88312cerion
1605332aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion   case 0x080: // vadduwm (Add Unsigned Word Modulo, AV p145)
1605432aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion      DIP("vadduwm v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
1605536991efdccc3af11ee9691dfa5297872dfb88312cerion      putVReg( vD_addr, binop(Iop_Add32x4, mkexpr(vA), mkexpr(vB)) );
1605636991efdccc3af11ee9691dfa5297872dfb88312cerion      break;
1605736991efdccc3af11ee9691dfa5297872dfb88312cerion
160580c74bb5aa3240f693df0568d578baabf0c376dc4carll   case 0x0C0: // vaddudm (Add Unsigned Double Word Modulo)
160590c74bb5aa3240f693df0568d578baabf0c376dc4carll      DIP("vaddudm v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
160600c74bb5aa3240f693df0568d578baabf0c376dc4carll      putVReg( vD_addr, binop(Iop_Add64x2, mkexpr(vA), mkexpr(vB)) );
160610c74bb5aa3240f693df0568d578baabf0c376dc4carll      break;
160620c74bb5aa3240f693df0568d578baabf0c376dc4carll
1606332aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion   case 0x200: // vaddubs (Add Unsigned Byte Saturate, AV p142)
1606432aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion      DIP("vaddubs v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
1606536991efdccc3af11ee9691dfa5297872dfb88312cerion      putVReg( vD_addr, binop(Iop_QAdd8Ux16, mkexpr(vA), mkexpr(vB)) );
1606636991efdccc3af11ee9691dfa5297872dfb88312cerion      // TODO: set VSCR[SAT], perhaps via new primop: Iop_SatOfQAdd8Ux16
1606736991efdccc3af11ee9691dfa5297872dfb88312cerion      break;
1606836991efdccc3af11ee9691dfa5297872dfb88312cerion
1606932aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion   case 0x240: // vadduhs (Add Unsigned Half Word Saturate, AV p144)
1607032aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion      DIP("vadduhs v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
1607136991efdccc3af11ee9691dfa5297872dfb88312cerion      putVReg( vD_addr, binop(Iop_QAdd16Ux8, mkexpr(vA), mkexpr(vB)) );
1607236991efdccc3af11ee9691dfa5297872dfb88312cerion      // TODO: set VSCR[SAT]
1607336991efdccc3af11ee9691dfa5297872dfb88312cerion      break;
1607436991efdccc3af11ee9691dfa5297872dfb88312cerion
1607532aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion   case 0x280: // vadduws (Add Unsigned Word Saturate, AV p146)
1607632aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion      DIP("vadduws v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
1607736991efdccc3af11ee9691dfa5297872dfb88312cerion      putVReg( vD_addr, binop(Iop_QAdd32Ux4, mkexpr(vA), mkexpr(vB)) );
1607836991efdccc3af11ee9691dfa5297872dfb88312cerion      // TODO: set VSCR[SAT]
1607936991efdccc3af11ee9691dfa5297872dfb88312cerion      break;
1608036991efdccc3af11ee9691dfa5297872dfb88312cerion
1608132aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion   case 0x300: // vaddsbs (Add Signed Byte Saturate, AV p138)
1608232aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion      DIP("vaddsbs v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
1608336991efdccc3af11ee9691dfa5297872dfb88312cerion      putVReg( vD_addr, binop(Iop_QAdd8Sx16, mkexpr(vA), mkexpr(vB)) );
1608436991efdccc3af11ee9691dfa5297872dfb88312cerion      // TODO: set VSCR[SAT]
1608536991efdccc3af11ee9691dfa5297872dfb88312cerion      break;
1608636991efdccc3af11ee9691dfa5297872dfb88312cerion
1608732aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion   case 0x340: // vaddshs (Add Signed Half Word Saturate, AV p139)
1608832aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion      DIP("vaddshs v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
1608936991efdccc3af11ee9691dfa5297872dfb88312cerion      putVReg( vD_addr, binop(Iop_QAdd16Sx8, mkexpr(vA), mkexpr(vB)) );
1609036991efdccc3af11ee9691dfa5297872dfb88312cerion      // TODO: set VSCR[SAT]
1609136991efdccc3af11ee9691dfa5297872dfb88312cerion      break;
1609236991efdccc3af11ee9691dfa5297872dfb88312cerion
1609332aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion   case 0x380: // vaddsws (Add Signed Word Saturate, AV p140)
1609432aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion      DIP("vaddsws v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
1609536991efdccc3af11ee9691dfa5297872dfb88312cerion      putVReg( vD_addr, binop(Iop_QAdd32Sx4, mkexpr(vA), mkexpr(vB)) );
1609636991efdccc3af11ee9691dfa5297872dfb88312cerion      // TODO: set VSCR[SAT]
1609736991efdccc3af11ee9691dfa5297872dfb88312cerion      break;
1609836991efdccc3af11ee9691dfa5297872dfb88312cerion
1609936991efdccc3af11ee9691dfa5297872dfb88312cerion
1610032aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion   /* Subtract */
1610136991efdccc3af11ee9691dfa5297872dfb88312cerion   case 0x580: { // vsubcuw (Subtract Carryout Unsigned Word, AV p260)
1610232aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion      DIP("vsubcuw v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
1610336991efdccc3af11ee9691dfa5297872dfb88312cerion      /* unsigned_ov(x-y) = (y >u x) */
1610436991efdccc3af11ee9691dfa5297872dfb88312cerion      putVReg( vD_addr, binop(Iop_ShrN32x4,
1610536991efdccc3af11ee9691dfa5297872dfb88312cerion                              unop(Iop_NotV128,
1610636991efdccc3af11ee9691dfa5297872dfb88312cerion                                   binop(Iop_CmpGT32Ux4, mkexpr(vB),
1610736991efdccc3af11ee9691dfa5297872dfb88312cerion                                         mkexpr(vA))),
1610836991efdccc3af11ee9691dfa5297872dfb88312cerion                              mkU8(31)) );
1610936991efdccc3af11ee9691dfa5297872dfb88312cerion      break;
1611036991efdccc3af11ee9691dfa5297872dfb88312cerion   }
1611132aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion   case 0x400: // vsububm (Subtract Unsigned Byte Modulo, AV p265)
1611232aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion      DIP("vsububm v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
1611336991efdccc3af11ee9691dfa5297872dfb88312cerion      putVReg( vD_addr, binop(Iop_Sub8x16, mkexpr(vA), mkexpr(vB)) );
1611436991efdccc3af11ee9691dfa5297872dfb88312cerion      break;
1611536991efdccc3af11ee9691dfa5297872dfb88312cerion
1611632aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion   case 0x440: // vsubuhm (Subtract Unsigned Half Word Modulo, AV p267)
1611732aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion      DIP("vsubuhm v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
1611836991efdccc3af11ee9691dfa5297872dfb88312cerion      putVReg( vD_addr, binop(Iop_Sub16x8, mkexpr(vA), mkexpr(vB)) );
1611936991efdccc3af11ee9691dfa5297872dfb88312cerion      break;
1612036991efdccc3af11ee9691dfa5297872dfb88312cerion
1612132aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion   case 0x480: // vsubuwm (Subtract Unsigned Word Modulo, AV p269)
1612232aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion      DIP("vsubuwm v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
1612336991efdccc3af11ee9691dfa5297872dfb88312cerion      putVReg( vD_addr, binop(Iop_Sub32x4, mkexpr(vA), mkexpr(vB)) );
1612436991efdccc3af11ee9691dfa5297872dfb88312cerion      break;
1612536991efdccc3af11ee9691dfa5297872dfb88312cerion
1612648ae46b56cef87c90638b25d6b2462c475033da8carll   case 0x4C0: // vsubudm (Subtract Unsigned Double Word Modulo)
1612748ae46b56cef87c90638b25d6b2462c475033da8carll      DIP("vsubudm v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
1612848ae46b56cef87c90638b25d6b2462c475033da8carll      putVReg( vD_addr, binop(Iop_Sub64x2, mkexpr(vA), mkexpr(vB)) );
1612948ae46b56cef87c90638b25d6b2462c475033da8carll      break;
1613048ae46b56cef87c90638b25d6b2462c475033da8carll
1613132aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion   case 0x600: // vsububs (Subtract Unsigned Byte Saturate, AV p266)
1613232aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion      DIP("vsububs v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
1613336991efdccc3af11ee9691dfa5297872dfb88312cerion      putVReg( vD_addr, binop(Iop_QSub8Ux16, mkexpr(vA), mkexpr(vB)) );
1613436991efdccc3af11ee9691dfa5297872dfb88312cerion      // TODO: set VSCR[SAT]
1613536991efdccc3af11ee9691dfa5297872dfb88312cerion      break;
1613636991efdccc3af11ee9691dfa5297872dfb88312cerion
161375b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion   case 0x640: // vsubuhs (Subtract Unsigned HWord Saturate, AV p268)
1613832aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion      DIP("vsubuhs v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
1613936991efdccc3af11ee9691dfa5297872dfb88312cerion      putVReg( vD_addr, binop(Iop_QSub16Ux8, mkexpr(vA), mkexpr(vB)) );
1614036991efdccc3af11ee9691dfa5297872dfb88312cerion      // TODO: set VSCR[SAT]
1614136991efdccc3af11ee9691dfa5297872dfb88312cerion      break;
1614236991efdccc3af11ee9691dfa5297872dfb88312cerion
1614332aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion   case 0x680: // vsubuws (Subtract Unsigned Word Saturate, AV p270)
1614432aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion      DIP("vsubuws v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
1614536991efdccc3af11ee9691dfa5297872dfb88312cerion      putVReg( vD_addr, binop(Iop_QSub32Ux4, mkexpr(vA), mkexpr(vB)) );
1614636991efdccc3af11ee9691dfa5297872dfb88312cerion      // TODO: set VSCR[SAT]
1614736991efdccc3af11ee9691dfa5297872dfb88312cerion      break;
1614836991efdccc3af11ee9691dfa5297872dfb88312cerion
1614932aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion   case 0x700: // vsubsbs (Subtract Signed Byte Saturate, AV p262)
1615032aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion      DIP("vsubsbs v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
1615136991efdccc3af11ee9691dfa5297872dfb88312cerion      putVReg( vD_addr, binop(Iop_QSub8Sx16, mkexpr(vA), mkexpr(vB)) );
1615236991efdccc3af11ee9691dfa5297872dfb88312cerion      // TODO: set VSCR[SAT]
1615336991efdccc3af11ee9691dfa5297872dfb88312cerion      break;
1615436991efdccc3af11ee9691dfa5297872dfb88312cerion
1615532aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion   case 0x740: // vsubshs (Subtract Signed Half Word Saturate, AV p263)
1615632aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion      DIP("vsubshs v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
1615736991efdccc3af11ee9691dfa5297872dfb88312cerion      putVReg( vD_addr, binop(Iop_QSub16Sx8, mkexpr(vA), mkexpr(vB)) );
1615836991efdccc3af11ee9691dfa5297872dfb88312cerion      // TODO: set VSCR[SAT]
1615936991efdccc3af11ee9691dfa5297872dfb88312cerion      break;
1616036991efdccc3af11ee9691dfa5297872dfb88312cerion
1616132aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion   case 0x780: // vsubsws (Subtract Signed Word Saturate, AV p264)
1616232aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion      DIP("vsubsws v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
1616336991efdccc3af11ee9691dfa5297872dfb88312cerion      putVReg( vD_addr, binop(Iop_QSub32Sx4, mkexpr(vA), mkexpr(vB)) );
1616436991efdccc3af11ee9691dfa5297872dfb88312cerion      // TODO: set VSCR[SAT]
1616536991efdccc3af11ee9691dfa5297872dfb88312cerion      break;
1616632aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion
1616732aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion
1616832aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion   /* Maximum */
1616932aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion   case 0x002: // vmaxub (Maximum Unsigned Byte, AV p182)
1617032aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion      DIP("vmaxub v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
1617136991efdccc3af11ee9691dfa5297872dfb88312cerion      putVReg( vD_addr, binop(Iop_Max8Ux16, mkexpr(vA), mkexpr(vB)) );
1617236991efdccc3af11ee9691dfa5297872dfb88312cerion      break;
1617332aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion
1617432aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion   case 0x042: // vmaxuh (Maximum Unsigned Half Word, AV p183)
1617532aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion      DIP("vmaxuh v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
1617636991efdccc3af11ee9691dfa5297872dfb88312cerion      putVReg( vD_addr, binop(Iop_Max16Ux8, mkexpr(vA), mkexpr(vB)) );
1617736991efdccc3af11ee9691dfa5297872dfb88312cerion      break;
1617832aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion
1617932aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion   case 0x082: // vmaxuw (Maximum Unsigned Word, AV p184)
1618032aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion      DIP("vmaxuw v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
1618136991efdccc3af11ee9691dfa5297872dfb88312cerion      putVReg( vD_addr, binop(Iop_Max32Ux4, mkexpr(vA), mkexpr(vB)) );
1618236991efdccc3af11ee9691dfa5297872dfb88312cerion      break;
1618332aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion
1618448ae46b56cef87c90638b25d6b2462c475033da8carll   case 0x0C2: // vmaxud (Maximum Unsigned Double word)
1618548ae46b56cef87c90638b25d6b2462c475033da8carll      DIP("vmaxud v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
1618648ae46b56cef87c90638b25d6b2462c475033da8carll      putVReg( vD_addr, binop(Iop_Max64Ux2, mkexpr(vA), mkexpr(vB)) );
1618748ae46b56cef87c90638b25d6b2462c475033da8carll      break;
1618848ae46b56cef87c90638b25d6b2462c475033da8carll
1618932aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion   case 0x102: // vmaxsb (Maximum Signed Byte, AV p179)
1619032aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion      DIP("vmaxsb v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
1619136991efdccc3af11ee9691dfa5297872dfb88312cerion      putVReg( vD_addr, binop(Iop_Max8Sx16, mkexpr(vA), mkexpr(vB)) );
1619236991efdccc3af11ee9691dfa5297872dfb88312cerion      break;
1619332aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion
1619432aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion   case 0x142: // vmaxsh (Maximum Signed Half Word, AV p180)
1619532aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion      DIP("vmaxsh v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
1619636991efdccc3af11ee9691dfa5297872dfb88312cerion      putVReg( vD_addr, binop(Iop_Max16Sx8, mkexpr(vA), mkexpr(vB)) );
1619736991efdccc3af11ee9691dfa5297872dfb88312cerion      break;
1619832aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion
1619932aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion   case 0x182: // vmaxsw (Maximum Signed Word, AV p181)
1620032aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion      DIP("vmaxsw v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
1620136991efdccc3af11ee9691dfa5297872dfb88312cerion      putVReg( vD_addr, binop(Iop_Max32Sx4, mkexpr(vA), mkexpr(vB)) );
1620236991efdccc3af11ee9691dfa5297872dfb88312cerion      break;
1620332aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion
1620448ae46b56cef87c90638b25d6b2462c475033da8carll   case 0x1C2: // vmaxsd (Maximum Signed Double word)
1620548ae46b56cef87c90638b25d6b2462c475033da8carll      DIP("vmaxsd v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
1620648ae46b56cef87c90638b25d6b2462c475033da8carll      putVReg( vD_addr, binop(Iop_Max64Sx2, mkexpr(vA), mkexpr(vB)) );
1620748ae46b56cef87c90638b25d6b2462c475033da8carll      break;
1620832aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion
1620932aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion   /* Minimum */
1621032aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion   case 0x202: // vminub (Minimum Unsigned Byte, AV p191)
1621132aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion      DIP("vminub v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
1621236991efdccc3af11ee9691dfa5297872dfb88312cerion      putVReg( vD_addr, binop(Iop_Min8Ux16, mkexpr(vA), mkexpr(vB)) );
1621336991efdccc3af11ee9691dfa5297872dfb88312cerion      break;
1621432aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion
1621532aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion   case 0x242: // vminuh (Minimum Unsigned Half Word, AV p192)
1621632aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion      DIP("vminuh v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
1621736991efdccc3af11ee9691dfa5297872dfb88312cerion      putVReg( vD_addr, binop(Iop_Min16Ux8, mkexpr(vA), mkexpr(vB)) );
1621836991efdccc3af11ee9691dfa5297872dfb88312cerion      break;
1621932aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion
1622032aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion   case 0x282: // vminuw (Minimum Unsigned Word, AV p193)
1622132aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion      DIP("vminuw v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
1622236991efdccc3af11ee9691dfa5297872dfb88312cerion      putVReg( vD_addr, binop(Iop_Min32Ux4, mkexpr(vA), mkexpr(vB)) );
1622336991efdccc3af11ee9691dfa5297872dfb88312cerion      break;
1622432aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion
1622548ae46b56cef87c90638b25d6b2462c475033da8carll   case 0x2C2: // vminud (Minimum Unsigned Double Word)
1622648ae46b56cef87c90638b25d6b2462c475033da8carll      DIP("vminud v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
1622748ae46b56cef87c90638b25d6b2462c475033da8carll      putVReg( vD_addr, binop(Iop_Min64Ux2, mkexpr(vA), mkexpr(vB)) );
1622848ae46b56cef87c90638b25d6b2462c475033da8carll      break;
1622948ae46b56cef87c90638b25d6b2462c475033da8carll
1623032aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion   case 0x302: // vminsb (Minimum Signed Byte, AV p188)
1623132aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion      DIP("vminsb v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
1623236991efdccc3af11ee9691dfa5297872dfb88312cerion      putVReg( vD_addr, binop(Iop_Min8Sx16, mkexpr(vA), mkexpr(vB)) );
1623336991efdccc3af11ee9691dfa5297872dfb88312cerion      break;
1623432aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion
1623532aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion   case 0x342: // vminsh (Minimum Signed Half Word, AV p189)
1623632aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion      DIP("vminsh v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
1623736991efdccc3af11ee9691dfa5297872dfb88312cerion      putVReg( vD_addr, binop(Iop_Min16Sx8, mkexpr(vA), mkexpr(vB)) );
1623836991efdccc3af11ee9691dfa5297872dfb88312cerion      break;
1623932aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion
1624032aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion   case 0x382: // vminsw (Minimum Signed Word, AV p190)
1624132aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion      DIP("vminsw v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
1624236991efdccc3af11ee9691dfa5297872dfb88312cerion      putVReg( vD_addr, binop(Iop_Min32Sx4, mkexpr(vA), mkexpr(vB)) );
1624336991efdccc3af11ee9691dfa5297872dfb88312cerion      break;
1624436991efdccc3af11ee9691dfa5297872dfb88312cerion
1624548ae46b56cef87c90638b25d6b2462c475033da8carll   case 0x3C2: // vminsd (Minimum Signed Double Word)
1624648ae46b56cef87c90638b25d6b2462c475033da8carll      DIP("vminsd v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
1624748ae46b56cef87c90638b25d6b2462c475033da8carll      putVReg( vD_addr, binop(Iop_Min64Sx2, mkexpr(vA), mkexpr(vB)) );
1624848ae46b56cef87c90638b25d6b2462c475033da8carll      break;
1624948ae46b56cef87c90638b25d6b2462c475033da8carll
1625032aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion
1625132aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion   /* Average */
1625232aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion   case 0x402: // vavgub (Average Unsigned Byte, AV p152)
1625332aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion      DIP("vavgub v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
1625436991efdccc3af11ee9691dfa5297872dfb88312cerion      putVReg( vD_addr, binop(Iop_Avg8Ux16, mkexpr(vA), mkexpr(vB)) );
1625536991efdccc3af11ee9691dfa5297872dfb88312cerion      break;
1625632aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion
1625732aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion   case 0x442: // vavguh (Average Unsigned Half Word, AV p153)
1625832aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion      DIP("vavguh v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
1625936991efdccc3af11ee9691dfa5297872dfb88312cerion      putVReg( vD_addr, binop(Iop_Avg16Ux8, mkexpr(vA), mkexpr(vB)) );
1626036991efdccc3af11ee9691dfa5297872dfb88312cerion      break;
1626132aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion
1626232aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion   case 0x482: // vavguw (Average Unsigned Word, AV p154)
1626332aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion      DIP("vavguw v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
1626436991efdccc3af11ee9691dfa5297872dfb88312cerion      putVReg( vD_addr, binop(Iop_Avg32Ux4, mkexpr(vA), mkexpr(vB)) );
1626536991efdccc3af11ee9691dfa5297872dfb88312cerion      break;
1626632aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion
1626732aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion   case 0x502: // vavgsb (Average Signed Byte, AV p149)
1626832aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion      DIP("vavgsb v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
1626936991efdccc3af11ee9691dfa5297872dfb88312cerion      putVReg( vD_addr, binop(Iop_Avg8Sx16, mkexpr(vA), mkexpr(vB)) );
1627036991efdccc3af11ee9691dfa5297872dfb88312cerion      break;
1627132aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion
1627232aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion   case 0x542: // vavgsh (Average Signed Half Word, AV p150)
1627332aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion      DIP("vavgsh v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
1627436991efdccc3af11ee9691dfa5297872dfb88312cerion      putVReg( vD_addr, binop(Iop_Avg16Sx8, mkexpr(vA), mkexpr(vB)) );
1627536991efdccc3af11ee9691dfa5297872dfb88312cerion      break;
1627632aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion
1627732aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion   case 0x582: // vavgsw (Average Signed Word, AV p151)
1627832aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion      DIP("vavgsw v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
1627936991efdccc3af11ee9691dfa5297872dfb88312cerion      putVReg( vD_addr, binop(Iop_Avg32Sx4, mkexpr(vA), mkexpr(vB)) );
1628036991efdccc3af11ee9691dfa5297872dfb88312cerion      break;
1628132aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion
1628232aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion
1628332aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion   /* Multiply */
1628432aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion   case 0x008: // vmuloub (Multiply Odd Unsigned Byte, AV p213)
1628532aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion      DIP("vmuloub v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
162865b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion      putVReg( vD_addr,
162875b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion               binop(Iop_MullEven8Ux16, mkexpr(vA), mkexpr(vB)));
1628836991efdccc3af11ee9691dfa5297872dfb88312cerion      break;
1628932aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion
1629032aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion   case 0x048: // vmulouh (Multiply Odd Unsigned Half Word, AV p214)
1629132aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion      DIP("vmulouh v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
162925b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion      putVReg( vD_addr,
162935b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion               binop(Iop_MullEven16Ux8, mkexpr(vA), mkexpr(vB)));
1629436991efdccc3af11ee9691dfa5297872dfb88312cerion      break;
1629532aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion
1629648ae46b56cef87c90638b25d6b2462c475033da8carll   case 0x088: // vmulouw (Multiply Odd Unsigned Word)
1629748ae46b56cef87c90638b25d6b2462c475033da8carll      DIP("vmulouw v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
1629848ae46b56cef87c90638b25d6b2462c475033da8carll      putVReg( vD_addr, binop( Iop_MullEven32Ux4, mkexpr(vA), mkexpr(vB) ) );
1629948ae46b56cef87c90638b25d6b2462c475033da8carll      break;
1630048ae46b56cef87c90638b25d6b2462c475033da8carll
1630148ae46b56cef87c90638b25d6b2462c475033da8carll   case 0x089: // vmuluwm (Multiply Unsigned Word Modulo)
1630248ae46b56cef87c90638b25d6b2462c475033da8carll      DIP("vmuluwm v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
1630348ae46b56cef87c90638b25d6b2462c475033da8carll      putVReg( vD_addr, binop( Iop_Mul32x4, mkexpr(vA), mkexpr(vB) ) );
1630448ae46b56cef87c90638b25d6b2462c475033da8carll      break;
1630548ae46b56cef87c90638b25d6b2462c475033da8carll
1630632aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion   case 0x108: // vmulosb (Multiply Odd Signed Byte, AV p211)
1630732aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion      DIP("vmulosb v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
163085b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion      putVReg( vD_addr,
163095b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion               binop(Iop_MullEven8Sx16, mkexpr(vA), mkexpr(vB)));
1631036991efdccc3af11ee9691dfa5297872dfb88312cerion      break;
1631132aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion
1631232aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion   case 0x148: // vmulosh (Multiply Odd Signed Half Word, AV p212)
1631332aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion      DIP("vmulosh v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
163145b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion      putVReg( vD_addr,
163155b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion               binop(Iop_MullEven16Sx8, mkexpr(vA), mkexpr(vB)));
1631636991efdccc3af11ee9691dfa5297872dfb88312cerion      break;
1631732aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion
1631848ae46b56cef87c90638b25d6b2462c475033da8carll   case 0x188: // vmulosw (Multiply Odd Signed Word)
1631948ae46b56cef87c90638b25d6b2462c475033da8carll      DIP("vmulosw v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
1632048ae46b56cef87c90638b25d6b2462c475033da8carll      putVReg( vD_addr, binop( Iop_MullEven32Sx4, mkexpr(vA), mkexpr(vB) ) );
1632148ae46b56cef87c90638b25d6b2462c475033da8carll      break;
1632248ae46b56cef87c90638b25d6b2462c475033da8carll
1632332aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion   case 0x208: // vmuleub (Multiply Even Unsigned Byte, AV p209)
1632432aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion      DIP("vmuleub v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
1632524d06f124e3325e8edcc1c495d15736d5adcda96cerion      putVReg( vD_addr, MK_Iop_MullOdd8Ux16( mkexpr(vA), mkexpr(vB) ));
1632636991efdccc3af11ee9691dfa5297872dfb88312cerion      break;
1632732aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion
1632832aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion   case 0x248: // vmuleuh (Multiply Even Unsigned Half Word, AV p210)
1632932aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion      DIP("vmuleuh v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
1633024d06f124e3325e8edcc1c495d15736d5adcda96cerion      putVReg( vD_addr, MK_Iop_MullOdd16Ux8( mkexpr(vA), mkexpr(vB) ));
1633136991efdccc3af11ee9691dfa5297872dfb88312cerion      break;
1633232aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion
1633348ae46b56cef87c90638b25d6b2462c475033da8carll   case 0x288: // vmuleuw (Multiply Even Unsigned Word)
1633448ae46b56cef87c90638b25d6b2462c475033da8carll      DIP("vmuleuw v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
1633548ae46b56cef87c90638b25d6b2462c475033da8carll      putVReg( vD_addr, MK_Iop_MullOdd32Ux4( mkexpr(vA), mkexpr(vB) ) );
1633648ae46b56cef87c90638b25d6b2462c475033da8carll      break;
1633748ae46b56cef87c90638b25d6b2462c475033da8carll
1633832aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion   case 0x308: // vmulesb (Multiply Even Signed Byte, AV p207)
1633932aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion      DIP("vmulesb v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
1634024d06f124e3325e8edcc1c495d15736d5adcda96cerion      putVReg( vD_addr, MK_Iop_MullOdd8Sx16( mkexpr(vA), mkexpr(vB) ));
1634136991efdccc3af11ee9691dfa5297872dfb88312cerion      break;
1634232aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion
1634332aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion   case 0x348: // vmulesh (Multiply Even Signed Half Word, AV p208)
1634432aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion      DIP("vmulesh v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
1634524d06f124e3325e8edcc1c495d15736d5adcda96cerion      putVReg( vD_addr, MK_Iop_MullOdd16Sx8( mkexpr(vA), mkexpr(vB) ));
1634636991efdccc3af11ee9691dfa5297872dfb88312cerion      break;
1634732aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion
1634848ae46b56cef87c90638b25d6b2462c475033da8carll   case 0x388: // vmulesw (Multiply Even Signed Word)
1634948ae46b56cef87c90638b25d6b2462c475033da8carll      DIP("vmulesw v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
1635048ae46b56cef87c90638b25d6b2462c475033da8carll      putVReg( vD_addr, MK_Iop_MullOdd32Sx4( mkexpr(vA), mkexpr(vB) ) );
1635148ae46b56cef87c90638b25d6b2462c475033da8carll      break;
1635232aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion
1635332aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion   /* Sum Across Partial */
163544a49b0393204185f87664ea58f2b7a2ae1d37338cerion   case 0x608: { // vsum4ubs (Sum Partial (1/4) UB Saturate, AV p275)
163554a49b0393204185f87664ea58f2b7a2ae1d37338cerion      IRTemp aEE, aEO, aOE, aOO;
163564a49b0393204185f87664ea58f2b7a2ae1d37338cerion      aEE = aEO = aOE = aOO = IRTemp_INVALID;
1635732aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion      DIP("vsum4ubs v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
1635832aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion
163594a49b0393204185f87664ea58f2b7a2ae1d37338cerion      /* vA: V128_8Ux16 -> 4 x V128_32Ux4, sign-extended */
163604a49b0393204185f87664ea58f2b7a2ae1d37338cerion      expand8Ux16( mkexpr(vA), &aEvn, &aOdd ); // (15,13...),(14,12...)
163614a49b0393204185f87664ea58f2b7a2ae1d37338cerion      expand16Ux8( mkexpr(aEvn), &aEE, &aEO ); // (15,11...),(13, 9...)
163624a49b0393204185f87664ea58f2b7a2ae1d37338cerion      expand16Ux8( mkexpr(aOdd), &aOE, &aOO ); // (14,10...),(12, 8...)
163634a49b0393204185f87664ea58f2b7a2ae1d37338cerion
163644a49b0393204185f87664ea58f2b7a2ae1d37338cerion      /* break V128 to 4xI32's, zero-extending to I64's */
163654a49b0393204185f87664ea58f2b7a2ae1d37338cerion      breakV128to4x64U( mkexpr(aEE), &a15, &a11, &a7, &a3 );
163664a49b0393204185f87664ea58f2b7a2ae1d37338cerion      breakV128to4x64U( mkexpr(aOE), &a14, &a10, &a6, &a2 );
163674a49b0393204185f87664ea58f2b7a2ae1d37338cerion      breakV128to4x64U( mkexpr(aEO), &a13, &a9,  &a5, &a1 );
163684a49b0393204185f87664ea58f2b7a2ae1d37338cerion      breakV128to4x64U( mkexpr(aOO), &a12, &a8,  &a4, &a0 );
163694a49b0393204185f87664ea58f2b7a2ae1d37338cerion      breakV128to4x64U( mkexpr(vB),  &b3,  &b2,  &b1, &b0 );
163704a49b0393204185f87664ea58f2b7a2ae1d37338cerion
163714a49b0393204185f87664ea58f2b7a2ae1d37338cerion      /* add lanes */
163724a49b0393204185f87664ea58f2b7a2ae1d37338cerion      assign( z3, binop(Iop_Add64, mkexpr(b3),
163735b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion                     binop(Iop_Add64,
163745b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion                        binop(Iop_Add64, mkexpr(a15), mkexpr(a14)),
163755b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion                        binop(Iop_Add64, mkexpr(a13), mkexpr(a12)))) );
163764a49b0393204185f87664ea58f2b7a2ae1d37338cerion      assign( z2, binop(Iop_Add64, mkexpr(b2),
163775b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion                     binop(Iop_Add64,
163785b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion                         binop(Iop_Add64, mkexpr(a11), mkexpr(a10)),
163795b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion                         binop(Iop_Add64, mkexpr(a9), mkexpr(a8)))) );
163804a49b0393204185f87664ea58f2b7a2ae1d37338cerion      assign( z1, binop(Iop_Add64, mkexpr(b1),
163815b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion                     binop(Iop_Add64,
163825b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion                         binop(Iop_Add64, mkexpr(a7), mkexpr(a6)),
163835b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion                         binop(Iop_Add64, mkexpr(a5), mkexpr(a4)))) );
163844a49b0393204185f87664ea58f2b7a2ae1d37338cerion      assign( z0, binop(Iop_Add64, mkexpr(b0),
163855b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion                     binop(Iop_Add64,
163865b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion                         binop(Iop_Add64, mkexpr(a3), mkexpr(a2)),
163875b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion                         binop(Iop_Add64, mkexpr(a1), mkexpr(a0)))) );
163884a49b0393204185f87664ea58f2b7a2ae1d37338cerion
163894a49b0393204185f87664ea58f2b7a2ae1d37338cerion      /* saturate-narrow to 32bit, and combine to V128 */
163904a49b0393204185f87664ea58f2b7a2ae1d37338cerion      putVReg( vD_addr, mkV128from4x64U( mkexpr(z3), mkexpr(z2),
163914a49b0393204185f87664ea58f2b7a2ae1d37338cerion                                         mkexpr(z1), mkexpr(z0)) );
163924a49b0393204185f87664ea58f2b7a2ae1d37338cerion      break;
163934a49b0393204185f87664ea58f2b7a2ae1d37338cerion   }
163944a49b0393204185f87664ea58f2b7a2ae1d37338cerion   case 0x708: { // vsum4sbs (Sum Partial (1/4) SB Saturate, AV p273)
163954a49b0393204185f87664ea58f2b7a2ae1d37338cerion      IRTemp aEE, aEO, aOE, aOO;
163964a49b0393204185f87664ea58f2b7a2ae1d37338cerion      aEE = aEO = aOE = aOO = IRTemp_INVALID;
1639732aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion      DIP("vsum4sbs v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
1639832aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion
163994a49b0393204185f87664ea58f2b7a2ae1d37338cerion      /* vA: V128_8Sx16 -> 4 x V128_32Sx4, sign-extended */
164004a49b0393204185f87664ea58f2b7a2ae1d37338cerion      expand8Sx16( mkexpr(vA), &aEvn, &aOdd ); // (15,13...),(14,12...)
164014a49b0393204185f87664ea58f2b7a2ae1d37338cerion      expand16Sx8( mkexpr(aEvn), &aEE, &aEO ); // (15,11...),(13, 9...)
164024a49b0393204185f87664ea58f2b7a2ae1d37338cerion      expand16Sx8( mkexpr(aOdd), &aOE, &aOO ); // (14,10...),(12, 8...)
164034a49b0393204185f87664ea58f2b7a2ae1d37338cerion
164044a49b0393204185f87664ea58f2b7a2ae1d37338cerion      /* break V128 to 4xI32's, sign-extending to I64's */
164054a49b0393204185f87664ea58f2b7a2ae1d37338cerion      breakV128to4x64S( mkexpr(aEE), &a15, &a11, &a7, &a3 );
164064a49b0393204185f87664ea58f2b7a2ae1d37338cerion      breakV128to4x64S( mkexpr(aOE), &a14, &a10, &a6, &a2 );
164074a49b0393204185f87664ea58f2b7a2ae1d37338cerion      breakV128to4x64S( mkexpr(aEO), &a13, &a9,  &a5, &a1 );
164084a49b0393204185f87664ea58f2b7a2ae1d37338cerion      breakV128to4x64S( mkexpr(aOO), &a12, &a8,  &a4, &a0 );
164094a49b0393204185f87664ea58f2b7a2ae1d37338cerion      breakV128to4x64S( mkexpr(vB),  &b3,  &b2,  &b1, &b0 );
164104a49b0393204185f87664ea58f2b7a2ae1d37338cerion
164114a49b0393204185f87664ea58f2b7a2ae1d37338cerion      /* add lanes */
164124a49b0393204185f87664ea58f2b7a2ae1d37338cerion      assign( z3, binop(Iop_Add64, mkexpr(b3),
164135b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion                     binop(Iop_Add64,
164145b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion                        binop(Iop_Add64, mkexpr(a15), mkexpr(a14)),
164155b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion                        binop(Iop_Add64, mkexpr(a13), mkexpr(a12)))) );
164164a49b0393204185f87664ea58f2b7a2ae1d37338cerion      assign( z2, binop(Iop_Add64, mkexpr(b2),
164175b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion                     binop(Iop_Add64,
164185b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion                        binop(Iop_Add64, mkexpr(a11), mkexpr(a10)),
164195b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion                        binop(Iop_Add64, mkexpr(a9), mkexpr(a8)))) );
164204a49b0393204185f87664ea58f2b7a2ae1d37338cerion      assign( z1, binop(Iop_Add64, mkexpr(b1),
164215b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion                     binop(Iop_Add64,
164225b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion                        binop(Iop_Add64, mkexpr(a7), mkexpr(a6)),
164235b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion                        binop(Iop_Add64, mkexpr(a5), mkexpr(a4)))) );
164244a49b0393204185f87664ea58f2b7a2ae1d37338cerion      assign( z0, binop(Iop_Add64, mkexpr(b0),
164255b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion                     binop(Iop_Add64,
164265b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion                        binop(Iop_Add64, mkexpr(a3), mkexpr(a2)),
164275b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion                        binop(Iop_Add64, mkexpr(a1), mkexpr(a0)))) );
164284a49b0393204185f87664ea58f2b7a2ae1d37338cerion
164294a49b0393204185f87664ea58f2b7a2ae1d37338cerion      /* saturate-narrow to 32bit, and combine to V128 */
164304a49b0393204185f87664ea58f2b7a2ae1d37338cerion      putVReg( vD_addr, mkV128from4x64S( mkexpr(z3), mkexpr(z2),
164314a49b0393204185f87664ea58f2b7a2ae1d37338cerion                                         mkexpr(z1), mkexpr(z0)) );
164324a49b0393204185f87664ea58f2b7a2ae1d37338cerion      break;
164334a49b0393204185f87664ea58f2b7a2ae1d37338cerion   }
164344a49b0393204185f87664ea58f2b7a2ae1d37338cerion   case 0x648: { // vsum4shs (Sum Partial (1/4) SHW Saturate, AV p274)
1643532aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion      DIP("vsum4shs v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
1643632aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion
164374a49b0393204185f87664ea58f2b7a2ae1d37338cerion      /* vA: V128_16Sx8 -> 2 x V128_32Sx4, sign-extended */
164384a49b0393204185f87664ea58f2b7a2ae1d37338cerion      expand16Sx8( mkexpr(vA), &aEvn, &aOdd ); // (7,5...),(6,4...)
164394a49b0393204185f87664ea58f2b7a2ae1d37338cerion
164404a49b0393204185f87664ea58f2b7a2ae1d37338cerion      /* break V128 to 4xI32's, sign-extending to I64's */
164414a49b0393204185f87664ea58f2b7a2ae1d37338cerion      breakV128to4x64S( mkexpr(aEvn), &a7, &a5, &a3, &a1 );
164424a49b0393204185f87664ea58f2b7a2ae1d37338cerion      breakV128to4x64S( mkexpr(aOdd), &a6, &a4, &a2, &a0 );
164434a49b0393204185f87664ea58f2b7a2ae1d37338cerion      breakV128to4x64S( mkexpr(vB),   &b3, &b2, &b1, &b0 );
164444a49b0393204185f87664ea58f2b7a2ae1d37338cerion
164454a49b0393204185f87664ea58f2b7a2ae1d37338cerion      /* add lanes */
164464a49b0393204185f87664ea58f2b7a2ae1d37338cerion      assign( z3, binop(Iop_Add64, mkexpr(b3),
164474a49b0393204185f87664ea58f2b7a2ae1d37338cerion                        binop(Iop_Add64, mkexpr(a7), mkexpr(a6))));
164484a49b0393204185f87664ea58f2b7a2ae1d37338cerion      assign( z2, binop(Iop_Add64, mkexpr(b2),
164494a49b0393204185f87664ea58f2b7a2ae1d37338cerion                        binop(Iop_Add64, mkexpr(a5), mkexpr(a4))));
164504a49b0393204185f87664ea58f2b7a2ae1d37338cerion      assign( z1, binop(Iop_Add64, mkexpr(b1),
164514a49b0393204185f87664ea58f2b7a2ae1d37338cerion                        binop(Iop_Add64, mkexpr(a3), mkexpr(a2))));
164524a49b0393204185f87664ea58f2b7a2ae1d37338cerion      assign( z0, binop(Iop_Add64, mkexpr(b0),
164534a49b0393204185f87664ea58f2b7a2ae1d37338cerion                        binop(Iop_Add64, mkexpr(a1), mkexpr(a0))));
164544a49b0393204185f87664ea58f2b7a2ae1d37338cerion
164554a49b0393204185f87664ea58f2b7a2ae1d37338cerion      /* saturate-narrow to 32bit, and combine to V128 */
164564a49b0393204185f87664ea58f2b7a2ae1d37338cerion      putVReg( vD_addr, mkV128from4x64S( mkexpr(z3), mkexpr(z2),
164574a49b0393204185f87664ea58f2b7a2ae1d37338cerion                                         mkexpr(z1), mkexpr(z0)) );
164584a49b0393204185f87664ea58f2b7a2ae1d37338cerion      break;
164594a49b0393204185f87664ea58f2b7a2ae1d37338cerion   }
164604a49b0393204185f87664ea58f2b7a2ae1d37338cerion   case 0x688: { // vsum2sws (Sum Partial (1/2) SW Saturate, AV p272)
1646132aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion      DIP("vsum2sws v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
1646232aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion
164634a49b0393204185f87664ea58f2b7a2ae1d37338cerion      /* break V128 to 4xI32's, sign-extending to I64's */
164644a49b0393204185f87664ea58f2b7a2ae1d37338cerion      breakV128to4x64S( mkexpr(vA), &a3, &a2, &a1, &a0 );
164654a49b0393204185f87664ea58f2b7a2ae1d37338cerion      breakV128to4x64S( mkexpr(vB), &b3, &b2, &b1, &b0 );
164664a49b0393204185f87664ea58f2b7a2ae1d37338cerion
164674a49b0393204185f87664ea58f2b7a2ae1d37338cerion      /* add lanes */
164684a49b0393204185f87664ea58f2b7a2ae1d37338cerion      assign( z2, binop(Iop_Add64, mkexpr(b2),
164694a49b0393204185f87664ea58f2b7a2ae1d37338cerion                        binop(Iop_Add64, mkexpr(a3), mkexpr(a2))) );
164704a49b0393204185f87664ea58f2b7a2ae1d37338cerion      assign( z0, binop(Iop_Add64, mkexpr(b0),
164714a49b0393204185f87664ea58f2b7a2ae1d37338cerion                        binop(Iop_Add64, mkexpr(a1), mkexpr(a0))) );
164724a49b0393204185f87664ea58f2b7a2ae1d37338cerion
164734a49b0393204185f87664ea58f2b7a2ae1d37338cerion      /* saturate-narrow to 32bit, and combine to V128 */
164744a49b0393204185f87664ea58f2b7a2ae1d37338cerion      putVReg( vD_addr, mkV128from4x64S( mkU64(0), mkexpr(z2),
164754a49b0393204185f87664ea58f2b7a2ae1d37338cerion                                         mkU64(0), mkexpr(z0)) );
164764a49b0393204185f87664ea58f2b7a2ae1d37338cerion      break;
164774a49b0393204185f87664ea58f2b7a2ae1d37338cerion   }
164784a49b0393204185f87664ea58f2b7a2ae1d37338cerion   case 0x788: { // vsumsws  (Sum SW Saturate, AV p271)
1647932aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion      DIP("vsumsws v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
1648032aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion
164814a49b0393204185f87664ea58f2b7a2ae1d37338cerion      /* break V128 to 4xI32's, sign-extending to I64's */
164824a49b0393204185f87664ea58f2b7a2ae1d37338cerion      breakV128to4x64S( mkexpr(vA), &a3, &a2, &a1, &a0 );
164834a49b0393204185f87664ea58f2b7a2ae1d37338cerion      breakV128to4x64S( mkexpr(vB), &b3, &b2, &b1, &b0 );
164844a49b0393204185f87664ea58f2b7a2ae1d37338cerion
164854a49b0393204185f87664ea58f2b7a2ae1d37338cerion      /* add lanes */
164864a49b0393204185f87664ea58f2b7a2ae1d37338cerion      assign( z0, binop(Iop_Add64, mkexpr(b0),
164875b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion                     binop(Iop_Add64,
164885b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion                        binop(Iop_Add64, mkexpr(a3), mkexpr(a2)),
164895b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion                        binop(Iop_Add64, mkexpr(a1), mkexpr(a0)))) );
164904a49b0393204185f87664ea58f2b7a2ae1d37338cerion
164914a49b0393204185f87664ea58f2b7a2ae1d37338cerion      /* saturate-narrow to 32bit, and combine to V128 */
164924a49b0393204185f87664ea58f2b7a2ae1d37338cerion      putVReg( vD_addr, mkV128from4x64S( mkU64(0), mkU64(0),
164934a49b0393204185f87664ea58f2b7a2ae1d37338cerion                                         mkU64(0), mkexpr(z0)) );
164944a49b0393204185f87664ea58f2b7a2ae1d37338cerion      break;
164954a49b0393204185f87664ea58f2b7a2ae1d37338cerion   }
1649632aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion   default:
164975b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion      vex_printf("dis_av_arith(ppc)(opc2=0x%x)\n", opc2);
1649832aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion      return False;
1649932aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion   }
1650032aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion   return True;
1650132aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion}
1650232aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion
1650332aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion/*
1650432aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion  AltiVec Logic Instructions
1650532aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion*/
1650632aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerionstatic Bool dis_av_logic ( UInt theInstr )
1650732aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion{
1650876de5cf615380b23b4b5bcced6541233cd4a93a0cerion   /* VX-Form */
1650976de5cf615380b23b4b5bcced6541233cd4a93a0cerion   UChar opc1    = ifieldOPC(theInstr);
1651076de5cf615380b23b4b5bcced6541233cd4a93a0cerion   UChar vD_addr = ifieldRegDS(theInstr);
1651176de5cf615380b23b4b5bcced6541233cd4a93a0cerion   UChar vA_addr = ifieldRegA(theInstr);
1651276de5cf615380b23b4b5bcced6541233cd4a93a0cerion   UChar vB_addr = ifieldRegB(theInstr);
1651376de5cf615380b23b4b5bcced6541233cd4a93a0cerion   UInt  opc2    = IFIELD( theInstr, 0, 11 );
1651432aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion
16515225a034683024109da729a4d2f080364b9485007cerion   IRTemp vA = newTemp(Ity_V128);
16516225a034683024109da729a4d2f080364b9485007cerion   IRTemp vB = newTemp(Ity_V128);
16517225a034683024109da729a4d2f080364b9485007cerion   assign( vA, getVReg(vA_addr));
16518225a034683024109da729a4d2f080364b9485007cerion   assign( vB, getVReg(vB_addr));
16519225a034683024109da729a4d2f080364b9485007cerion
1652032aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion   if (opc1 != 0x4) {
165215b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion      vex_printf("dis_av_logic(ppc)(opc1 != 0x4)\n");
1652232aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion      return False;
1652332aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion   }
1652432aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion
1652532aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion   switch (opc2) {
1652632aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion   case 0x404: // vand (And, AV p147)
1652732aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion      DIP("vand v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
16528225a034683024109da729a4d2f080364b9485007cerion      putVReg( vD_addr, binop(Iop_AndV128, mkexpr(vA), mkexpr(vB)) );
16529225a034683024109da729a4d2f080364b9485007cerion      break;
1653032aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion
1653132aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion   case 0x444: // vandc (And, AV p148)
1653232aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion      DIP("vandc v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
165336e7a0ea9abe4e6443ebfc451d5681250eece75fdcerion      putVReg( vD_addr, binop(Iop_AndV128, mkexpr(vA),
1653476de5cf615380b23b4b5bcced6541233cd4a93a0cerion                              unop(Iop_NotV128, mkexpr(vB))) );
165356e7a0ea9abe4e6443ebfc451d5681250eece75fdcerion      break;
1653632aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion
1653732aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion   case 0x484: // vor (Or, AV p217)
1653832aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion      DIP("vor v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
16539225a034683024109da729a4d2f080364b9485007cerion      putVReg( vD_addr, binop(Iop_OrV128, mkexpr(vA), mkexpr(vB)) );
16540225a034683024109da729a4d2f080364b9485007cerion      break;
1654132aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion
1654232aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion   case 0x4C4: // vxor (Xor, AV p282)
1654332aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion      DIP("vxor v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
16544225a034683024109da729a4d2f080364b9485007cerion      putVReg( vD_addr, binop(Iop_XorV128, mkexpr(vA), mkexpr(vB)) );
16545225a034683024109da729a4d2f080364b9485007cerion      break;
1654632aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion
1654732aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion   case 0x504: // vnor (Nor, AV p216)
1654832aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion      DIP("vnor v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
165496e7a0ea9abe4e6443ebfc451d5681250eece75fdcerion      putVReg( vD_addr,
165506e7a0ea9abe4e6443ebfc451d5681250eece75fdcerion         unop(Iop_NotV128, binop(Iop_OrV128, mkexpr(vA), mkexpr(vB))) );
165516e7a0ea9abe4e6443ebfc451d5681250eece75fdcerion      break;
1655232aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion
165537deaf9552b546b847528cf39b38898fb7742b5f5carll   case 0x544: // vorc (vA Or'd with complement of vb)
165547deaf9552b546b847528cf39b38898fb7742b5f5carll      DIP("vorc v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
165557deaf9552b546b847528cf39b38898fb7742b5f5carll      putVReg( vD_addr, binop( Iop_OrV128,
165567deaf9552b546b847528cf39b38898fb7742b5f5carll                               mkexpr( vA ),
165577deaf9552b546b847528cf39b38898fb7742b5f5carll                               unop( Iop_NotV128, mkexpr( vB ) ) ) );
165587deaf9552b546b847528cf39b38898fb7742b5f5carll      break;
165597deaf9552b546b847528cf39b38898fb7742b5f5carll
165607deaf9552b546b847528cf39b38898fb7742b5f5carll   case 0x584: // vnand (Nand)
165617deaf9552b546b847528cf39b38898fb7742b5f5carll      DIP("vnand v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
165627deaf9552b546b847528cf39b38898fb7742b5f5carll      putVReg( vD_addr, unop( Iop_NotV128,
165637deaf9552b546b847528cf39b38898fb7742b5f5carll                              binop(Iop_AndV128, mkexpr( vA ),
165647deaf9552b546b847528cf39b38898fb7742b5f5carll                              mkexpr( vB ) ) ) );
165657deaf9552b546b847528cf39b38898fb7742b5f5carll      break;
165667deaf9552b546b847528cf39b38898fb7742b5f5carll
165677deaf9552b546b847528cf39b38898fb7742b5f5carll   case 0x684: // veqv (complemented XOr)
165687deaf9552b546b847528cf39b38898fb7742b5f5carll      DIP("veqv v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
165697deaf9552b546b847528cf39b38898fb7742b5f5carll      putVReg( vD_addr, unop( Iop_NotV128,
165707deaf9552b546b847528cf39b38898fb7742b5f5carll                              binop( Iop_XorV128, mkexpr( vA ),
165717deaf9552b546b847528cf39b38898fb7742b5f5carll                              mkexpr( vB ) ) ) );
165727deaf9552b546b847528cf39b38898fb7742b5f5carll      break;
165737deaf9552b546b847528cf39b38898fb7742b5f5carll
1657432aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion   default:
165755b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion      vex_printf("dis_av_logic(ppc)(opc2=0x%x)\n", opc2);
1657632aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion      return False;
1657732aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion   }
1657832aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion   return True;
1657932aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion}
1658032aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion
1658132aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion/*
1658232aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion  AltiVec Compare Instructions
1658332aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion*/
1658432aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerionstatic Bool dis_av_cmp ( UInt theInstr )
1658532aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion{
1658676de5cf615380b23b4b5bcced6541233cd4a93a0cerion   /* VXR-Form */
1658776de5cf615380b23b4b5bcced6541233cd4a93a0cerion   UChar opc1     = ifieldOPC(theInstr);
1658876de5cf615380b23b4b5bcced6541233cd4a93a0cerion   UChar vD_addr  = ifieldRegDS(theInstr);
1658976de5cf615380b23b4b5bcced6541233cd4a93a0cerion   UChar vA_addr  = ifieldRegA(theInstr);
1659076de5cf615380b23b4b5bcced6541233cd4a93a0cerion   UChar vB_addr  = ifieldRegB(theInstr);
1659176de5cf615380b23b4b5bcced6541233cd4a93a0cerion   UChar flag_rC  = ifieldBIT10(theInstr);
1659276de5cf615380b23b4b5bcced6541233cd4a93a0cerion   UInt  opc2     = IFIELD( theInstr, 0, 10 );
1659332aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion
165940c43922a06643631fb78de1f6d5a00837c189e9bcerion   IRTemp vA = newTemp(Ity_V128);
165950c43922a06643631fb78de1f6d5a00837c189e9bcerion   IRTemp vB = newTemp(Ity_V128);
165960c43922a06643631fb78de1f6d5a00837c189e9bcerion   IRTemp vD = newTemp(Ity_V128);
165970c43922a06643631fb78de1f6d5a00837c189e9bcerion   assign( vA, getVReg(vA_addr));
165980c43922a06643631fb78de1f6d5a00837c189e9bcerion   assign( vB, getVReg(vB_addr));
165990c43922a06643631fb78de1f6d5a00837c189e9bcerion
1660032aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion   if (opc1 != 0x4) {
166015b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion      vex_printf("dis_av_cmp(ppc)(instr)\n");
1660232aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion      return False;
1660332aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion   }
1660432aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion
1660532aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion   switch (opc2) {
1660632aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion   case 0x006: // vcmpequb (Compare Equal-to Unsigned B, AV p160)
166075b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion      DIP("vcmpequb%s v%d,v%d,v%d\n", (flag_rC ? ".":""),
166085b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion                                      vD_addr, vA_addr, vB_addr);
166090c43922a06643631fb78de1f6d5a00837c189e9bcerion      assign( vD, binop(Iop_CmpEQ8x16, mkexpr(vA), mkexpr(vB)) );
166100c43922a06643631fb78de1f6d5a00837c189e9bcerion      break;
1661132aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion
1661232aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion   case 0x046: // vcmpequh (Compare Equal-to Unsigned HW, AV p161)
166135b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion      DIP("vcmpequh%s v%d,v%d,v%d\n", (flag_rC ? ".":""),
166145b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion                                      vD_addr, vA_addr, vB_addr);
166150c43922a06643631fb78de1f6d5a00837c189e9bcerion      assign( vD, binop(Iop_CmpEQ16x8, mkexpr(vA), mkexpr(vB)) );
166160c43922a06643631fb78de1f6d5a00837c189e9bcerion      break;
1661732aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion
1661832aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion   case 0x086: // vcmpequw (Compare Equal-to Unsigned W, AV p162)
166195b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion      DIP("vcmpequw%s v%d,v%d,v%d\n", (flag_rC ? ".":""),
166205b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion                                      vD_addr, vA_addr, vB_addr);
166210c43922a06643631fb78de1f6d5a00837c189e9bcerion      assign( vD, binop(Iop_CmpEQ32x4, mkexpr(vA), mkexpr(vB)) );
166220c43922a06643631fb78de1f6d5a00837c189e9bcerion      break;
1662332aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion
1662448ae46b56cef87c90638b25d6b2462c475033da8carll   case 0x0C7: // vcmpequd (Compare Equal-to Unsigned Doubleword)
1662548ae46b56cef87c90638b25d6b2462c475033da8carll      DIP("vcmpequd%s v%d,v%d,v%d\n", (flag_rC ? ".":""),
1662648ae46b56cef87c90638b25d6b2462c475033da8carll                                      vD_addr, vA_addr, vB_addr);
1662748ae46b56cef87c90638b25d6b2462c475033da8carll      assign( vD, binop(Iop_CmpEQ64x2, mkexpr(vA), mkexpr(vB)) );
1662848ae46b56cef87c90638b25d6b2462c475033da8carll      break;
1662948ae46b56cef87c90638b25d6b2462c475033da8carll
1663032aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion   case 0x206: // vcmpgtub (Compare Greater-than Unsigned B, AV p168)
166315b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion      DIP("vcmpgtub%s v%d,v%d,v%d\n", (flag_rC ? ".":""),
166325b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion                                      vD_addr, vA_addr, vB_addr);
166330c43922a06643631fb78de1f6d5a00837c189e9bcerion      assign( vD, binop(Iop_CmpGT8Ux16, mkexpr(vA), mkexpr(vB)) );
166340c43922a06643631fb78de1f6d5a00837c189e9bcerion      break;
1663532aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion
1663632aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion   case 0x246: // vcmpgtuh (Compare Greater-than Unsigned HW, AV p169)
166375b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion      DIP("vcmpgtuh%s v%d,v%d,v%d\n", (flag_rC ? ".":""),
166385b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion                                      vD_addr, vA_addr, vB_addr);
166390c43922a06643631fb78de1f6d5a00837c189e9bcerion      assign( vD, binop(Iop_CmpGT16Ux8, mkexpr(vA), mkexpr(vB)) );
166400c43922a06643631fb78de1f6d5a00837c189e9bcerion      break;
1664132aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion
1664232aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion   case 0x286: // vcmpgtuw (Compare Greater-than Unsigned W, AV p170)
166435b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion      DIP("vcmpgtuw%s v%d,v%d,v%d\n", (flag_rC ? ".":""),
166445b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion                                       vD_addr, vA_addr, vB_addr);
166450c43922a06643631fb78de1f6d5a00837c189e9bcerion      assign( vD, binop(Iop_CmpGT32Ux4, mkexpr(vA), mkexpr(vB)) );
166460c43922a06643631fb78de1f6d5a00837c189e9bcerion      break;
1664732aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion
1664848ae46b56cef87c90638b25d6b2462c475033da8carll   case 0x2C7: // vcmpgtud (Compare Greater-than Unsigned double)
1664948ae46b56cef87c90638b25d6b2462c475033da8carll      DIP("vcmpgtud%s v%d,v%d,v%d\n", (flag_rC ? ".":""),
1665048ae46b56cef87c90638b25d6b2462c475033da8carll                                      vD_addr, vA_addr, vB_addr);
1665148ae46b56cef87c90638b25d6b2462c475033da8carll      assign( vD, binop(Iop_CmpGT64Ux2, mkexpr(vA), mkexpr(vB)) );
1665248ae46b56cef87c90638b25d6b2462c475033da8carll      break;
1665348ae46b56cef87c90638b25d6b2462c475033da8carll
1665432aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion   case 0x306: // vcmpgtsb (Compare Greater-than Signed B, AV p165)
166555b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion      DIP("vcmpgtsb%s v%d,v%d,v%d\n", (flag_rC ? ".":""),
166565b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion                                       vD_addr, vA_addr, vB_addr);
166570c43922a06643631fb78de1f6d5a00837c189e9bcerion      assign( vD, binop(Iop_CmpGT8Sx16, mkexpr(vA), mkexpr(vB)) );
166580c43922a06643631fb78de1f6d5a00837c189e9bcerion      break;
1665932aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion
1666032aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion   case 0x346: // vcmpgtsh (Compare Greater-than Signed HW, AV p166)
166615b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion      DIP("vcmpgtsh%s v%d,v%d,v%d\n", (flag_rC ? ".":""),
166625b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion                                      vD_addr, vA_addr, vB_addr);
166630c43922a06643631fb78de1f6d5a00837c189e9bcerion      assign( vD, binop(Iop_CmpGT16Sx8, mkexpr(vA), mkexpr(vB)) );
166640c43922a06643631fb78de1f6d5a00837c189e9bcerion      break;
1666532aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion
1666632aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion   case 0x386: // vcmpgtsw (Compare Greater-than Signed W, AV p167)
166675b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion      DIP("vcmpgtsw%s v%d,v%d,v%d\n", (flag_rC ? ".":""),
166685b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion                                      vD_addr, vA_addr, vB_addr);
166690c43922a06643631fb78de1f6d5a00837c189e9bcerion      assign( vD, binop(Iop_CmpGT32Sx4, mkexpr(vA), mkexpr(vB)) );
166700c43922a06643631fb78de1f6d5a00837c189e9bcerion      break;
1667132aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion
1667248ae46b56cef87c90638b25d6b2462c475033da8carll   case 0x3C7: // vcmpgtsd (Compare Greater-than Signed double)
1667348ae46b56cef87c90638b25d6b2462c475033da8carll      DIP("vcmpgtsd%s v%d,v%d,v%d\n", (flag_rC ? ".":""),
1667448ae46b56cef87c90638b25d6b2462c475033da8carll                                      vD_addr, vA_addr, vB_addr);
1667548ae46b56cef87c90638b25d6b2462c475033da8carll      assign( vD, binop(Iop_CmpGT64Sx2, mkexpr(vA), mkexpr(vB)) );
1667648ae46b56cef87c90638b25d6b2462c475033da8carll      break;
1667748ae46b56cef87c90638b25d6b2462c475033da8carll
1667832aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion   default:
166795b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion      vex_printf("dis_av_cmp(ppc)(opc2)\n");
1668032aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion      return False;
1668132aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion   }
166820c43922a06643631fb78de1f6d5a00837c189e9bcerion
166830c43922a06643631fb78de1f6d5a00837c189e9bcerion   putVReg( vD_addr, mkexpr(vD) );
166840c43922a06643631fb78de1f6d5a00837c189e9bcerion
1668576de5cf615380b23b4b5bcced6541233cd4a93a0cerion   if (flag_rC) {
166868ea0d3ebfb8b1e4d8b6f851b0079c47a9886c686cerion      set_AV_CR6( mkexpr(vD), True );
166870c43922a06643631fb78de1f6d5a00837c189e9bcerion   }
1668832aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion   return True;
1668932aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion}
1669032aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion
1669132aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion/*
1669232aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion  AltiVec Multiply-Sum Instructions
1669332aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion*/
1669432aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerionstatic Bool dis_av_multarith ( UInt theInstr )
1669532aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion{
1669676de5cf615380b23b4b5bcced6541233cd4a93a0cerion   /* VA-Form */
1669776de5cf615380b23b4b5bcced6541233cd4a93a0cerion   UChar opc1     = ifieldOPC(theInstr);
1669876de5cf615380b23b4b5bcced6541233cd4a93a0cerion   UChar vD_addr  = ifieldRegDS(theInstr);
1669976de5cf615380b23b4b5bcced6541233cd4a93a0cerion   UChar vA_addr  = ifieldRegA(theInstr);
1670076de5cf615380b23b4b5bcced6541233cd4a93a0cerion   UChar vB_addr  = ifieldRegB(theInstr);
1670176de5cf615380b23b4b5bcced6541233cd4a93a0cerion   UChar vC_addr  = ifieldRegC(theInstr);
1670276de5cf615380b23b4b5bcced6541233cd4a93a0cerion   UChar opc2     = toUChar( IFIELD( theInstr, 0, 6 ) );
1670332aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion
167044a49b0393204185f87664ea58f2b7a2ae1d37338cerion   IRTemp vA    = newTemp(Ity_V128);
167054a49b0393204185f87664ea58f2b7a2ae1d37338cerion   IRTemp vB    = newTemp(Ity_V128);
167064a49b0393204185f87664ea58f2b7a2ae1d37338cerion   IRTemp vC    = newTemp(Ity_V128);
16707197bd17d3ba8ac5204cd5c9ba5fab571249eb791sewardj   IRTemp zeros = newTemp(Ity_V128);
167084a49b0393204185f87664ea58f2b7a2ae1d37338cerion   IRTemp aLo   = newTemp(Ity_V128);
167094a49b0393204185f87664ea58f2b7a2ae1d37338cerion   IRTemp bLo   = newTemp(Ity_V128);
167104a49b0393204185f87664ea58f2b7a2ae1d37338cerion   IRTemp cLo   = newTemp(Ity_V128);
167114a49b0393204185f87664ea58f2b7a2ae1d37338cerion   IRTemp zLo   = newTemp(Ity_V128);
167124a49b0393204185f87664ea58f2b7a2ae1d37338cerion   IRTemp aHi   = newTemp(Ity_V128);
167134a49b0393204185f87664ea58f2b7a2ae1d37338cerion   IRTemp bHi   = newTemp(Ity_V128);
167144a49b0393204185f87664ea58f2b7a2ae1d37338cerion   IRTemp cHi   = newTemp(Ity_V128);
167154a49b0393204185f87664ea58f2b7a2ae1d37338cerion   IRTemp zHi   = newTemp(Ity_V128);
167164a49b0393204185f87664ea58f2b7a2ae1d37338cerion   IRTemp abEvn = newTemp(Ity_V128);
167174a49b0393204185f87664ea58f2b7a2ae1d37338cerion   IRTemp abOdd = newTemp(Ity_V128);
167184a49b0393204185f87664ea58f2b7a2ae1d37338cerion   IRTemp z3    = newTemp(Ity_I64);
167194a49b0393204185f87664ea58f2b7a2ae1d37338cerion   IRTemp z2    = newTemp(Ity_I64);
167204a49b0393204185f87664ea58f2b7a2ae1d37338cerion   IRTemp z1    = newTemp(Ity_I64);
167214a49b0393204185f87664ea58f2b7a2ae1d37338cerion   IRTemp z0    = newTemp(Ity_I64);
167224a49b0393204185f87664ea58f2b7a2ae1d37338cerion   IRTemp ab7, ab6, ab5, ab4, ab3, ab2, ab1, ab0;
167234a49b0393204185f87664ea58f2b7a2ae1d37338cerion   IRTemp c3, c2, c1, c0;
167244a49b0393204185f87664ea58f2b7a2ae1d37338cerion
167254a49b0393204185f87664ea58f2b7a2ae1d37338cerion   ab7 = ab6 = ab5 = ab4 = ab3 = ab2 = ab1 = ab0 = IRTemp_INVALID;
167264a49b0393204185f87664ea58f2b7a2ae1d37338cerion   c3 = c2 = c1 = c0 = IRTemp_INVALID;
167274a49b0393204185f87664ea58f2b7a2ae1d37338cerion
167286f1cc0fd33c0b074bcac7901fe0dd277c73ca01ccerion   assign( vA, getVReg(vA_addr));
167296f1cc0fd33c0b074bcac7901fe0dd277c73ca01ccerion   assign( vB, getVReg(vB_addr));
167306f1cc0fd33c0b074bcac7901fe0dd277c73ca01ccerion   assign( vC, getVReg(vC_addr));
167314a49b0393204185f87664ea58f2b7a2ae1d37338cerion   assign( zeros, unop(Iop_Dup32x4, mkU32(0)) );
167326f1cc0fd33c0b074bcac7901fe0dd277c73ca01ccerion
1673332aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion   if (opc1 != 0x4) {
167345b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion      vex_printf("dis_av_multarith(ppc)(instr)\n");
1673532aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion      return False;
1673632aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion   }
1673732aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion
167386f1cc0fd33c0b074bcac7901fe0dd277c73ca01ccerion   switch (opc2) {
1673932aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion   /* Multiply-Add */
167405b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion   case 0x20: { // vmhaddshs (Mult Hi, Add Signed HW Saturate, AV p185)
167416f1cc0fd33c0b074bcac7901fe0dd277c73ca01ccerion      IRTemp cSigns = newTemp(Ity_V128);
167425b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion      DIP("vmhaddshs v%d,v%d,v%d,v%d\n",
167435b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion          vD_addr, vA_addr, vB_addr, vC_addr);
167445b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion      assign(cSigns, binop(Iop_CmpGT16Sx8, mkexpr(zeros), mkexpr(vC)));
167455b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion      assign(aLo, binop(Iop_InterleaveLO16x8, mkexpr(zeros), mkexpr(vA)));
167465b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion      assign(bLo, binop(Iop_InterleaveLO16x8, mkexpr(zeros), mkexpr(vB)));
167475b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion      assign(cLo, binop(Iop_InterleaveLO16x8, mkexpr(cSigns),mkexpr(vC)));
167485b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion      assign(aHi, binop(Iop_InterleaveHI16x8, mkexpr(zeros), mkexpr(vA)));
167495b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion      assign(bHi, binop(Iop_InterleaveHI16x8, mkexpr(zeros), mkexpr(vB)));
167505b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion      assign(cHi, binop(Iop_InterleaveHI16x8, mkexpr(cSigns),mkexpr(vC)));
167516f1cc0fd33c0b074bcac7901fe0dd277c73ca01ccerion
1675224d06f124e3325e8edcc1c495d15736d5adcda96cerion      assign( zLo, binop(Iop_Add32x4, mkexpr(cLo),
167536f1cc0fd33c0b074bcac7901fe0dd277c73ca01ccerion                         binop(Iop_SarN32x4,
167541ac656a3b8eead55eeb0fb9090efec1c6719f989cerion                               binop(Iop_MullEven16Sx8,
1675524d06f124e3325e8edcc1c495d15736d5adcda96cerion                                     mkexpr(aLo), mkexpr(bLo)),
1675624d06f124e3325e8edcc1c495d15736d5adcda96cerion                               mkU8(15))) );
167576f1cc0fd33c0b074bcac7901fe0dd277c73ca01ccerion
1675824d06f124e3325e8edcc1c495d15736d5adcda96cerion      assign( zHi, binop(Iop_Add32x4, mkexpr(cHi),
167596f1cc0fd33c0b074bcac7901fe0dd277c73ca01ccerion                         binop(Iop_SarN32x4,
167601ac656a3b8eead55eeb0fb9090efec1c6719f989cerion                               binop(Iop_MullEven16Sx8,
1676124d06f124e3325e8edcc1c495d15736d5adcda96cerion                                     mkexpr(aHi), mkexpr(bHi)),
1676224d06f124e3325e8edcc1c495d15736d5adcda96cerion                               mkU8(15))) );
167636f1cc0fd33c0b074bcac7901fe0dd277c73ca01ccerion
167645b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion      putVReg( vD_addr,
167655f438dd73072211989c6d496845bdc9b777ecbecsewardj               binop(Iop_QNarrowBin32Sto16Sx8, mkexpr(zHi), mkexpr(zLo)) );
167666f1cc0fd33c0b074bcac7901fe0dd277c73ca01ccerion      break;
167676f1cc0fd33c0b074bcac7901fe0dd277c73ca01ccerion   }
167685b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion   case 0x21: { // vmhraddshs (Mult High Round, Add Signed HW Saturate, AV p186)
167696f1cc0fd33c0b074bcac7901fe0dd277c73ca01ccerion      IRTemp zKonst = newTemp(Ity_V128);
167706f1cc0fd33c0b074bcac7901fe0dd277c73ca01ccerion      IRTemp cSigns = newTemp(Ity_V128);
167715b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion      DIP("vmhraddshs v%d,v%d,v%d,v%d\n",
167725b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion          vD_addr, vA_addr, vB_addr, vC_addr);
167735b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion      assign(cSigns, binop(Iop_CmpGT16Sx8, mkexpr(zeros), mkexpr(vC)) );
167745b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion      assign(aLo, binop(Iop_InterleaveLO16x8, mkexpr(zeros), mkexpr(vA)));
167755b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion      assign(bLo, binop(Iop_InterleaveLO16x8, mkexpr(zeros), mkexpr(vB)));
167765b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion      assign(cLo, binop(Iop_InterleaveLO16x8, mkexpr(cSigns),mkexpr(vC)));
167775b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion      assign(aHi, binop(Iop_InterleaveHI16x8, mkexpr(zeros), mkexpr(vA)));
167785b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion      assign(bHi, binop(Iop_InterleaveHI16x8, mkexpr(zeros), mkexpr(vB)));
167795b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion      assign(cHi, binop(Iop_InterleaveHI16x8, mkexpr(cSigns),mkexpr(vC)));
167806f1cc0fd33c0b074bcac7901fe0dd277c73ca01ccerion
167816f1cc0fd33c0b074bcac7901fe0dd277c73ca01ccerion      /* shifting our const avoids store/load version of Dup */
167824a49b0393204185f87664ea58f2b7a2ae1d37338cerion      assign( zKonst, binop(Iop_ShlN32x4, unop(Iop_Dup32x4, mkU32(0x1)),
167834a49b0393204185f87664ea58f2b7a2ae1d37338cerion                            mkU8(14)) );
167846f1cc0fd33c0b074bcac7901fe0dd277c73ca01ccerion
1678524d06f124e3325e8edcc1c495d15736d5adcda96cerion      assign( zLo, binop(Iop_Add32x4, mkexpr(cLo),
167866f1cc0fd33c0b074bcac7901fe0dd277c73ca01ccerion                         binop(Iop_SarN32x4,
167876f1cc0fd33c0b074bcac7901fe0dd277c73ca01ccerion                               binop(Iop_Add32x4, mkexpr(zKonst),
167881ac656a3b8eead55eeb0fb9090efec1c6719f989cerion                                     binop(Iop_MullEven16Sx8,
1678924d06f124e3325e8edcc1c495d15736d5adcda96cerion                                           mkexpr(aLo), mkexpr(bLo))),
1679024d06f124e3325e8edcc1c495d15736d5adcda96cerion                               mkU8(15))) );
167916f1cc0fd33c0b074bcac7901fe0dd277c73ca01ccerion
1679224d06f124e3325e8edcc1c495d15736d5adcda96cerion      assign( zHi, binop(Iop_Add32x4, mkexpr(cHi),
167936f1cc0fd33c0b074bcac7901fe0dd277c73ca01ccerion                         binop(Iop_SarN32x4,
167946f1cc0fd33c0b074bcac7901fe0dd277c73ca01ccerion                               binop(Iop_Add32x4, mkexpr(zKonst),
167951ac656a3b8eead55eeb0fb9090efec1c6719f989cerion                                     binop(Iop_MullEven16Sx8,
1679624d06f124e3325e8edcc1c495d15736d5adcda96cerion                                           mkexpr(aHi), mkexpr(bHi))),
1679724d06f124e3325e8edcc1c495d15736d5adcda96cerion                               mkU8(15))) );
167986f1cc0fd33c0b074bcac7901fe0dd277c73ca01ccerion
16799c9bff7dbb37ba2ee5898ef49aefaa92095ab446bsewardj      putVReg( vD_addr,
168005f438dd73072211989c6d496845bdc9b777ecbecsewardj               binop(Iop_QNarrowBin32Sto16Sx8, mkexpr(zHi), mkexpr(zLo)) );
168016f1cc0fd33c0b074bcac7901fe0dd277c73ca01ccerion      break;
168026f1cc0fd33c0b074bcac7901fe0dd277c73ca01ccerion   }
168035b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion   case 0x22: { // vmladduhm (Mult Low, Add Unsigned HW Modulo, AV p194)
168045b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion      DIP("vmladduhm v%d,v%d,v%d,v%d\n",
168055b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion          vD_addr, vA_addr, vB_addr, vC_addr);
168065b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion      assign(aLo, binop(Iop_InterleaveLO16x8, mkexpr(zeros), mkexpr(vA)));
168075b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion      assign(bLo, binop(Iop_InterleaveLO16x8, mkexpr(zeros), mkexpr(vB)));
168085b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion      assign(cLo, binop(Iop_InterleaveLO16x8, mkexpr(zeros), mkexpr(vC)));
168095b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion      assign(aHi, binop(Iop_InterleaveHI16x8, mkexpr(zeros), mkexpr(vA)));
168105b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion      assign(bHi, binop(Iop_InterleaveHI16x8, mkexpr(zeros), mkexpr(vB)));
168115b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion      assign(cHi, binop(Iop_InterleaveHI16x8, mkexpr(zeros), mkexpr(vC)));
168125b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion      assign(zLo, binop(Iop_Add32x4,
168135b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion                     binop(Iop_MullEven16Ux8, mkexpr(aLo), mkexpr(bLo)),
168145b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion                     mkexpr(cLo)) );
168155b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion      assign(zHi, binop(Iop_Add32x4,
168165b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion                     binop(Iop_MullEven16Ux8, mkexpr(aHi), mkexpr(bHi)),
168175b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion                     mkexpr(cHi)));
168185f438dd73072211989c6d496845bdc9b777ecbecsewardj      putVReg( vD_addr,
168195f438dd73072211989c6d496845bdc9b777ecbecsewardj               binop(Iop_NarrowBin32to16x8, mkexpr(zHi), mkexpr(zLo)) );
168206f1cc0fd33c0b074bcac7901fe0dd277c73ca01ccerion      break;
168216f1cc0fd33c0b074bcac7901fe0dd277c73ca01ccerion   }
1682232aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion
1682332aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion
1682432aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion   /* Multiply-Sum */
168256f1cc0fd33c0b074bcac7901fe0dd277c73ca01ccerion   case 0x24: { // vmsumubm (Multiply Sum Unsigned B Modulo, AV p204)
168264a49b0393204185f87664ea58f2b7a2ae1d37338cerion      IRTemp abEE, abEO, abOE, abOO;
168274a49b0393204185f87664ea58f2b7a2ae1d37338cerion      abEE = abEO = abOE = abOO = IRTemp_INVALID;
168285b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion      DIP("vmsumubm v%d,v%d,v%d,v%d\n",
168295b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion          vD_addr, vA_addr, vB_addr, vC_addr);
1683032aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion
168314a49b0393204185f87664ea58f2b7a2ae1d37338cerion      /* multiply vA,vB (unsigned, widening) */
1683224d06f124e3325e8edcc1c495d15736d5adcda96cerion      assign( abEvn, MK_Iop_MullOdd8Ux16( mkexpr(vA), mkexpr(vB) ));
1683324d06f124e3325e8edcc1c495d15736d5adcda96cerion      assign( abOdd, binop(Iop_MullEven8Ux16, mkexpr(vA), mkexpr(vB)) );
168344a49b0393204185f87664ea58f2b7a2ae1d37338cerion
168354a49b0393204185f87664ea58f2b7a2ae1d37338cerion      /* evn,odd: V128_16Ux8 -> 2 x V128_32Ux4, zero-extended */
168364a49b0393204185f87664ea58f2b7a2ae1d37338cerion      expand16Ux8( mkexpr(abEvn), &abEE, &abEO );
168374a49b0393204185f87664ea58f2b7a2ae1d37338cerion      expand16Ux8( mkexpr(abOdd), &abOE, &abOO );
168384a49b0393204185f87664ea58f2b7a2ae1d37338cerion
168396f1cc0fd33c0b074bcac7901fe0dd277c73ca01ccerion      putVReg( vD_addr,
168405b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion         binop(Iop_Add32x4, mkexpr(vC),
168415b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion               binop(Iop_Add32x4,
168425b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion                     binop(Iop_Add32x4, mkexpr(abEE), mkexpr(abEO)),
168435b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion                     binop(Iop_Add32x4, mkexpr(abOE), mkexpr(abOO)))) );
168446f1cc0fd33c0b074bcac7901fe0dd277c73ca01ccerion      break;
168456f1cc0fd33c0b074bcac7901fe0dd277c73ca01ccerion   }
168464a49b0393204185f87664ea58f2b7a2ae1d37338cerion   case 0x25: { // vmsummbm (Multiply Sum Mixed-Sign B Modulo, AV p201)
168474a49b0393204185f87664ea58f2b7a2ae1d37338cerion      IRTemp aEvn, aOdd, bEvn, bOdd;
168484a49b0393204185f87664ea58f2b7a2ae1d37338cerion      IRTemp abEE = newTemp(Ity_V128);
168494a49b0393204185f87664ea58f2b7a2ae1d37338cerion      IRTemp abEO = newTemp(Ity_V128);
168504a49b0393204185f87664ea58f2b7a2ae1d37338cerion      IRTemp abOE = newTemp(Ity_V128);
168514a49b0393204185f87664ea58f2b7a2ae1d37338cerion      IRTemp abOO = newTemp(Ity_V128);
168524a49b0393204185f87664ea58f2b7a2ae1d37338cerion      aEvn = aOdd = bEvn = bOdd = IRTemp_INVALID;
168535b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion      DIP("vmsummbm v%d,v%d,v%d,v%d\n",
168545b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion          vD_addr, vA_addr, vB_addr, vC_addr);
1685532aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion
168564a49b0393204185f87664ea58f2b7a2ae1d37338cerion      /* sign-extend vA, zero-extend vB, for mixed-sign multiply
168574a49b0393204185f87664ea58f2b7a2ae1d37338cerion         (separating out adjacent lanes to different vectors) */
168584a49b0393204185f87664ea58f2b7a2ae1d37338cerion      expand8Sx16( mkexpr(vA), &aEvn, &aOdd );
168594a49b0393204185f87664ea58f2b7a2ae1d37338cerion      expand8Ux16( mkexpr(vB), &bEvn, &bOdd );
168604a49b0393204185f87664ea58f2b7a2ae1d37338cerion
168614a49b0393204185f87664ea58f2b7a2ae1d37338cerion      /* multiply vA, vB, again separating adjacent lanes */
1686224d06f124e3325e8edcc1c495d15736d5adcda96cerion      assign( abEE, MK_Iop_MullOdd16Sx8( mkexpr(aEvn), mkexpr(bEvn) ));
1686324d06f124e3325e8edcc1c495d15736d5adcda96cerion      assign( abEO, binop(Iop_MullEven16Sx8, mkexpr(aEvn), mkexpr(bEvn)) );
1686424d06f124e3325e8edcc1c495d15736d5adcda96cerion      assign( abOE, MK_Iop_MullOdd16Sx8( mkexpr(aOdd), mkexpr(bOdd) ));
1686524d06f124e3325e8edcc1c495d15736d5adcda96cerion      assign( abOO, binop(Iop_MullEven16Sx8, mkexpr(aOdd), mkexpr(bOdd)) );
168664a49b0393204185f87664ea58f2b7a2ae1d37338cerion
168674a49b0393204185f87664ea58f2b7a2ae1d37338cerion      /* add results together, + vC */
168684a49b0393204185f87664ea58f2b7a2ae1d37338cerion      putVReg( vD_addr,
168695b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion         binop(Iop_QAdd32Sx4, mkexpr(vC),
168705b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion               binop(Iop_QAdd32Sx4,
168715b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion                     binop(Iop_QAdd32Sx4, mkexpr(abEE), mkexpr(abEO)),
168725b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion                     binop(Iop_QAdd32Sx4, mkexpr(abOE), mkexpr(abOO)))) );
168734a49b0393204185f87664ea58f2b7a2ae1d37338cerion      break;
168744a49b0393204185f87664ea58f2b7a2ae1d37338cerion   }
168756f1cc0fd33c0b074bcac7901fe0dd277c73ca01ccerion   case 0x26: { // vmsumuhm (Multiply Sum Unsigned HW Modulo, AV p205)
168765b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion      DIP("vmsumuhm v%d,v%d,v%d,v%d\n",
168775b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion          vD_addr, vA_addr, vB_addr, vC_addr);
1687824d06f124e3325e8edcc1c495d15736d5adcda96cerion      assign( abEvn, MK_Iop_MullOdd16Ux8( mkexpr(vA), mkexpr(vB) ));
1687924d06f124e3325e8edcc1c495d15736d5adcda96cerion      assign( abOdd, binop(Iop_MullEven16Ux8, mkexpr(vA), mkexpr(vB)) );
168806f1cc0fd33c0b074bcac7901fe0dd277c73ca01ccerion      putVReg( vD_addr,
168815b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion         binop(Iop_Add32x4, mkexpr(vC),
168825b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion               binop(Iop_Add32x4, mkexpr(abEvn), mkexpr(abOdd))) );
168836f1cc0fd33c0b074bcac7901fe0dd277c73ca01ccerion      break;
168846f1cc0fd33c0b074bcac7901fe0dd277c73ca01ccerion   }
168854a49b0393204185f87664ea58f2b7a2ae1d37338cerion   case 0x27: { // vmsumuhs (Multiply Sum Unsigned HW Saturate, AV p206)
168865b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion      DIP("vmsumuhs v%d,v%d,v%d,v%d\n",
168875b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion          vD_addr, vA_addr, vB_addr, vC_addr);
168884a49b0393204185f87664ea58f2b7a2ae1d37338cerion      /* widening multiply, separating lanes */
1688924d06f124e3325e8edcc1c495d15736d5adcda96cerion      assign( abEvn, MK_Iop_MullOdd16Ux8(mkexpr(vA), mkexpr(vB) ));
1689024d06f124e3325e8edcc1c495d15736d5adcda96cerion      assign( abOdd, binop(Iop_MullEven16Ux8, mkexpr(vA), mkexpr(vB)) );
168914a49b0393204185f87664ea58f2b7a2ae1d37338cerion
168924a49b0393204185f87664ea58f2b7a2ae1d37338cerion      /* break V128 to 4xI32's, zero-extending to I64's */
168934a49b0393204185f87664ea58f2b7a2ae1d37338cerion      breakV128to4x64U( mkexpr(abEvn), &ab7, &ab5, &ab3, &ab1 );
168944a49b0393204185f87664ea58f2b7a2ae1d37338cerion      breakV128to4x64U( mkexpr(abOdd), &ab6, &ab4, &ab2, &ab0 );
168954a49b0393204185f87664ea58f2b7a2ae1d37338cerion      breakV128to4x64U( mkexpr(vC),    &c3,  &c2,  &c1,  &c0  );
168964a49b0393204185f87664ea58f2b7a2ae1d37338cerion
168974a49b0393204185f87664ea58f2b7a2ae1d37338cerion      /* add lanes */
168984a49b0393204185f87664ea58f2b7a2ae1d37338cerion      assign( z3, binop(Iop_Add64, mkexpr(c3),
168994a49b0393204185f87664ea58f2b7a2ae1d37338cerion                        binop(Iop_Add64, mkexpr(ab7), mkexpr(ab6))));
169004a49b0393204185f87664ea58f2b7a2ae1d37338cerion      assign( z2, binop(Iop_Add64, mkexpr(c2),
169014a49b0393204185f87664ea58f2b7a2ae1d37338cerion                        binop(Iop_Add64, mkexpr(ab5), mkexpr(ab4))));
169024a49b0393204185f87664ea58f2b7a2ae1d37338cerion      assign( z1, binop(Iop_Add64, mkexpr(c1),
169034a49b0393204185f87664ea58f2b7a2ae1d37338cerion                        binop(Iop_Add64, mkexpr(ab3), mkexpr(ab2))));
169044a49b0393204185f87664ea58f2b7a2ae1d37338cerion      assign( z0, binop(Iop_Add64, mkexpr(c0),
169054a49b0393204185f87664ea58f2b7a2ae1d37338cerion                        binop(Iop_Add64, mkexpr(ab1), mkexpr(ab0))));
169064a49b0393204185f87664ea58f2b7a2ae1d37338cerion
169074a49b0393204185f87664ea58f2b7a2ae1d37338cerion      /* saturate-narrow to 32bit, and combine to V128 */
169084a49b0393204185f87664ea58f2b7a2ae1d37338cerion      putVReg( vD_addr, mkV128from4x64U( mkexpr(z3), mkexpr(z2),
169094a49b0393204185f87664ea58f2b7a2ae1d37338cerion                                         mkexpr(z1), mkexpr(z0)) );
1691032aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion
169114a49b0393204185f87664ea58f2b7a2ae1d37338cerion      break;
169124a49b0393204185f87664ea58f2b7a2ae1d37338cerion   }
169136f1cc0fd33c0b074bcac7901fe0dd277c73ca01ccerion   case 0x28: { // vmsumshm (Multiply Sum Signed HW Modulo, AV p202)
169145b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion      DIP("vmsumshm v%d,v%d,v%d,v%d\n",
169155b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion          vD_addr, vA_addr, vB_addr, vC_addr);
1691624d06f124e3325e8edcc1c495d15736d5adcda96cerion      assign( abEvn, MK_Iop_MullOdd16Sx8( mkexpr(vA), mkexpr(vB) ));
1691724d06f124e3325e8edcc1c495d15736d5adcda96cerion      assign( abOdd, binop(Iop_MullEven16Sx8, mkexpr(vA), mkexpr(vB)) );
169186f1cc0fd33c0b074bcac7901fe0dd277c73ca01ccerion      putVReg( vD_addr,
169195b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion         binop(Iop_Add32x4, mkexpr(vC),
169205b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion               binop(Iop_Add32x4, mkexpr(abOdd), mkexpr(abEvn))) );
169216f1cc0fd33c0b074bcac7901fe0dd277c73ca01ccerion      break;
169226f1cc0fd33c0b074bcac7901fe0dd277c73ca01ccerion   }
169234a49b0393204185f87664ea58f2b7a2ae1d37338cerion   case 0x29: { // vmsumshs (Multiply Sum Signed HW Saturate, AV p203)
169245b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion      DIP("vmsumshs v%d,v%d,v%d,v%d\n",
169255b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion          vD_addr, vA_addr, vB_addr, vC_addr);
169264a49b0393204185f87664ea58f2b7a2ae1d37338cerion      /* widening multiply, separating lanes */
1692724d06f124e3325e8edcc1c495d15736d5adcda96cerion      assign( abEvn, MK_Iop_MullOdd16Sx8( mkexpr(vA), mkexpr(vB) ));
1692824d06f124e3325e8edcc1c495d15736d5adcda96cerion      assign( abOdd, binop(Iop_MullEven16Sx8, mkexpr(vA), mkexpr(vB)) );
169294a49b0393204185f87664ea58f2b7a2ae1d37338cerion
169304a49b0393204185f87664ea58f2b7a2ae1d37338cerion      /* break V128 to 4xI32's, sign-extending to I64's */
169314a49b0393204185f87664ea58f2b7a2ae1d37338cerion      breakV128to4x64S( mkexpr(abEvn), &ab7, &ab5, &ab3, &ab1 );
169324a49b0393204185f87664ea58f2b7a2ae1d37338cerion      breakV128to4x64S( mkexpr(abOdd), &ab6, &ab4, &ab2, &ab0 );
169334a49b0393204185f87664ea58f2b7a2ae1d37338cerion      breakV128to4x64S( mkexpr(vC),    &c3,  &c2,  &c1,  &c0  );
169344a49b0393204185f87664ea58f2b7a2ae1d37338cerion
169354a49b0393204185f87664ea58f2b7a2ae1d37338cerion      /* add lanes */
169364a49b0393204185f87664ea58f2b7a2ae1d37338cerion      assign( z3, binop(Iop_Add64, mkexpr(c3),
169374a49b0393204185f87664ea58f2b7a2ae1d37338cerion                        binop(Iop_Add64, mkexpr(ab7), mkexpr(ab6))));
169384a49b0393204185f87664ea58f2b7a2ae1d37338cerion      assign( z2, binop(Iop_Add64, mkexpr(c2),
169394a49b0393204185f87664ea58f2b7a2ae1d37338cerion                        binop(Iop_Add64, mkexpr(ab5), mkexpr(ab4))));
169404a49b0393204185f87664ea58f2b7a2ae1d37338cerion      assign( z1, binop(Iop_Add64, mkexpr(c1),
169414a49b0393204185f87664ea58f2b7a2ae1d37338cerion                        binop(Iop_Add64, mkexpr(ab3), mkexpr(ab2))));
169424a49b0393204185f87664ea58f2b7a2ae1d37338cerion      assign( z0, binop(Iop_Add64, mkexpr(c0),
169434a49b0393204185f87664ea58f2b7a2ae1d37338cerion                        binop(Iop_Add64, mkexpr(ab1), mkexpr(ab0))));
169444a49b0393204185f87664ea58f2b7a2ae1d37338cerion
169454a49b0393204185f87664ea58f2b7a2ae1d37338cerion      /* saturate-narrow to 32bit, and combine to V128 */
169464a49b0393204185f87664ea58f2b7a2ae1d37338cerion      putVReg( vD_addr, mkV128from4x64S( mkexpr(z3), mkexpr(z2),
169474a49b0393204185f87664ea58f2b7a2ae1d37338cerion                                         mkexpr(z1), mkexpr(z0)) );
169484a49b0393204185f87664ea58f2b7a2ae1d37338cerion      break;
169494a49b0393204185f87664ea58f2b7a2ae1d37338cerion   }
1695032aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion   default:
169515b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion      vex_printf("dis_av_multarith(ppc)(opc2)\n");
1695232aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion      return False;
1695332aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion   }
1695432aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion   return True;
1695532aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion}
1695632aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion
1695732aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion/*
169587deaf9552b546b847528cf39b38898fb7742b5f5carll  AltiVec Polynomial Multiply-Sum Instructions
169597deaf9552b546b847528cf39b38898fb7742b5f5carll*/
169607deaf9552b546b847528cf39b38898fb7742b5f5carllstatic Bool dis_av_polymultarith ( UInt theInstr )
169617deaf9552b546b847528cf39b38898fb7742b5f5carll{
169627deaf9552b546b847528cf39b38898fb7742b5f5carll   /* VA-Form */
169637deaf9552b546b847528cf39b38898fb7742b5f5carll   UChar opc1     = ifieldOPC(theInstr);
169647deaf9552b546b847528cf39b38898fb7742b5f5carll   UChar vD_addr  = ifieldRegDS(theInstr);
169657deaf9552b546b847528cf39b38898fb7742b5f5carll   UChar vA_addr  = ifieldRegA(theInstr);
169667deaf9552b546b847528cf39b38898fb7742b5f5carll   UChar vB_addr  = ifieldRegB(theInstr);
169677deaf9552b546b847528cf39b38898fb7742b5f5carll   UChar vC_addr  = ifieldRegC(theInstr);
169687deaf9552b546b847528cf39b38898fb7742b5f5carll   UInt  opc2     = IFIELD(theInstr, 0, 11);
169697deaf9552b546b847528cf39b38898fb7742b5f5carll   IRTemp vA    = newTemp(Ity_V128);
169707deaf9552b546b847528cf39b38898fb7742b5f5carll   IRTemp vB    = newTemp(Ity_V128);
169717deaf9552b546b847528cf39b38898fb7742b5f5carll   IRTemp vC    = newTemp(Ity_V128);
169727deaf9552b546b847528cf39b38898fb7742b5f5carll
169737deaf9552b546b847528cf39b38898fb7742b5f5carll   assign( vA, getVReg(vA_addr));
169747deaf9552b546b847528cf39b38898fb7742b5f5carll   assign( vB, getVReg(vB_addr));
169757deaf9552b546b847528cf39b38898fb7742b5f5carll   assign( vC, getVReg(vC_addr));
169767deaf9552b546b847528cf39b38898fb7742b5f5carll
169777deaf9552b546b847528cf39b38898fb7742b5f5carll   if (opc1 != 0x4) {
169787deaf9552b546b847528cf39b38898fb7742b5f5carll      vex_printf("dis_av_polymultarith(ppc)(instr)\n");
169797deaf9552b546b847528cf39b38898fb7742b5f5carll      return False;
169807deaf9552b546b847528cf39b38898fb7742b5f5carll   }
169817deaf9552b546b847528cf39b38898fb7742b5f5carll
169827deaf9552b546b847528cf39b38898fb7742b5f5carll   switch (opc2) {
169837deaf9552b546b847528cf39b38898fb7742b5f5carll      /* Polynomial Multiply-Add */
169847deaf9552b546b847528cf39b38898fb7742b5f5carll      case 0x408:  // vpmsumb   Vector Polynomial Multipy-sum Byte
169857deaf9552b546b847528cf39b38898fb7742b5f5carll         DIP("vpmsumb v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
169867deaf9552b546b847528cf39b38898fb7742b5f5carll         putVReg( vD_addr, binop(Iop_PolynomialMulAdd8x16,
169877deaf9552b546b847528cf39b38898fb7742b5f5carll                                 mkexpr(vA), mkexpr(vB)) );
169887deaf9552b546b847528cf39b38898fb7742b5f5carll         break;
169897deaf9552b546b847528cf39b38898fb7742b5f5carll      case 0x448:  // vpmsumd   Vector Polynomial Multipy-sum Double Word
169907deaf9552b546b847528cf39b38898fb7742b5f5carll         DIP("vpmsumd v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
169917deaf9552b546b847528cf39b38898fb7742b5f5carll         putVReg( vD_addr, binop(Iop_PolynomialMulAdd64x2,
169927deaf9552b546b847528cf39b38898fb7742b5f5carll                                 mkexpr(vA), mkexpr(vB)) );
169937deaf9552b546b847528cf39b38898fb7742b5f5carll         break;
169947deaf9552b546b847528cf39b38898fb7742b5f5carll      case 0x488:  // vpmsumw   Vector Polynomial Multipy-sum Word
169957deaf9552b546b847528cf39b38898fb7742b5f5carll         DIP("vpmsumw v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
169967deaf9552b546b847528cf39b38898fb7742b5f5carll         putVReg( vD_addr, binop(Iop_PolynomialMulAdd32x4,
169977deaf9552b546b847528cf39b38898fb7742b5f5carll                                 mkexpr(vA), mkexpr(vB)) );
169987deaf9552b546b847528cf39b38898fb7742b5f5carll         break;
169997deaf9552b546b847528cf39b38898fb7742b5f5carll      case 0x4C8:  // vpmsumh   Vector Polynomial Multipy-sum Half Word
170007deaf9552b546b847528cf39b38898fb7742b5f5carll         DIP("vpmsumh v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
170017deaf9552b546b847528cf39b38898fb7742b5f5carll         putVReg( vD_addr, binop(Iop_PolynomialMulAdd16x8,
170027deaf9552b546b847528cf39b38898fb7742b5f5carll                                 mkexpr(vA), mkexpr(vB)) );
170037deaf9552b546b847528cf39b38898fb7742b5f5carll         break;
170047deaf9552b546b847528cf39b38898fb7742b5f5carll      default:
170057deaf9552b546b847528cf39b38898fb7742b5f5carll         vex_printf("dis_av_polymultarith(ppc)(opc2=0x%x)\n", opc2);
170067deaf9552b546b847528cf39b38898fb7742b5f5carll         return False;
170077deaf9552b546b847528cf39b38898fb7742b5f5carll   }
170087deaf9552b546b847528cf39b38898fb7742b5f5carll   return True;
170097deaf9552b546b847528cf39b38898fb7742b5f5carll}
170107deaf9552b546b847528cf39b38898fb7742b5f5carll
170117deaf9552b546b847528cf39b38898fb7742b5f5carll/*
1701232aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion  AltiVec Shift/Rotate Instructions
1701332aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion*/
1701432aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerionstatic Bool dis_av_shift ( UInt theInstr )
1701532aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion{
1701676de5cf615380b23b4b5bcced6541233cd4a93a0cerion   /* VX-Form */
1701776de5cf615380b23b4b5bcced6541233cd4a93a0cerion   UChar opc1    = ifieldOPC(theInstr);
1701876de5cf615380b23b4b5bcced6541233cd4a93a0cerion   UChar vD_addr = ifieldRegDS(theInstr);
1701976de5cf615380b23b4b5bcced6541233cd4a93a0cerion   UChar vA_addr = ifieldRegA(theInstr);
1702076de5cf615380b23b4b5bcced6541233cd4a93a0cerion   UChar vB_addr = ifieldRegB(theInstr);
1702176de5cf615380b23b4b5bcced6541233cd4a93a0cerion   UInt  opc2    = IFIELD( theInstr, 0, 11 );
1702232aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion
1702327b3d7ec17c3a0814d4980db87defbb4f07339bfcerion   IRTemp vA = newTemp(Ity_V128);
1702427b3d7ec17c3a0814d4980db87defbb4f07339bfcerion   IRTemp vB = newTemp(Ity_V128);
1702527b3d7ec17c3a0814d4980db87defbb4f07339bfcerion   assign( vA, getVReg(vA_addr));
1702627b3d7ec17c3a0814d4980db87defbb4f07339bfcerion   assign( vB, getVReg(vB_addr));
1702727b3d7ec17c3a0814d4980db87defbb4f07339bfcerion
1702832aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion   if (opc1 != 0x4){
170295b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion      vex_printf("dis_av_shift(ppc)(instr)\n");
1703032aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion      return False;
1703132aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion   }
1703232aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion
1703332aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion   switch (opc2) {
1703432aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion   /* Rotate */
1703532aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion   case 0x004: // vrlb (Rotate Left Integer B, AV p234)
1703632aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion      DIP("vrlb v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
170371bee561912427ca8f8998c89b62d86ba2ee49732sewardj      putVReg( vD_addr, binop(Iop_Rol8x16, mkexpr(vA), mkexpr(vB)) );
170380a7b4f40d11db65d00af3b0f51c23807dd83817fcerion      break;
1703932aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion
1704032aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion   case 0x044: // vrlh (Rotate Left Integer HW, AV p235)
1704132aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion      DIP("vrlh v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
170421bee561912427ca8f8998c89b62d86ba2ee49732sewardj      putVReg( vD_addr, binop(Iop_Rol16x8, mkexpr(vA), mkexpr(vB)) );
170430a7b4f40d11db65d00af3b0f51c23807dd83817fcerion      break;
1704432aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion
1704532aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion   case 0x084: // vrlw (Rotate Left Integer W, AV p236)
1704632aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion      DIP("vrlw v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
170471bee561912427ca8f8998c89b62d86ba2ee49732sewardj      putVReg( vD_addr, binop(Iop_Rol32x4, mkexpr(vA), mkexpr(vB)) );
170480a7b4f40d11db65d00af3b0f51c23807dd83817fcerion      break;
1704932aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion
1705048ae46b56cef87c90638b25d6b2462c475033da8carll   case 0x0C4: // vrld (Rotate Left Integer Double Word)
1705148ae46b56cef87c90638b25d6b2462c475033da8carll      DIP("vrld v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
1705248ae46b56cef87c90638b25d6b2462c475033da8carll      putVReg( vD_addr, binop(Iop_Rol64x2, mkexpr(vA), mkexpr(vB)) );
1705348ae46b56cef87c90638b25d6b2462c475033da8carll      break;
1705448ae46b56cef87c90638b25d6b2462c475033da8carll
1705532aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion
1705632aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion   /* Shift Left */
1705732aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion   case 0x104: // vslb (Shift Left Integer B, AV p240)
1705832aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion      DIP("vslb v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
170590a7b4f40d11db65d00af3b0f51c23807dd83817fcerion      putVReg( vD_addr, binop(Iop_Shl8x16, mkexpr(vA), mkexpr(vB)) );
170600a7b4f40d11db65d00af3b0f51c23807dd83817fcerion      break;
1706132aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion
1706232aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion   case 0x144: // vslh (Shift Left Integer HW, AV p242)
1706332aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion      DIP("vslh v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
170640a7b4f40d11db65d00af3b0f51c23807dd83817fcerion      putVReg( vD_addr, binop(Iop_Shl16x8, mkexpr(vA), mkexpr(vB)) );
170650a7b4f40d11db65d00af3b0f51c23807dd83817fcerion      break;
1706632aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion
1706732aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion   case 0x184: // vslw (Shift Left Integer W, AV p244)
1706832aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion      DIP("vslw v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
170690a7b4f40d11db65d00af3b0f51c23807dd83817fcerion      putVReg( vD_addr, binop(Iop_Shl32x4, mkexpr(vA), mkexpr(vB)) );
170700a7b4f40d11db65d00af3b0f51c23807dd83817fcerion      break;
1707132aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion
1707248ae46b56cef87c90638b25d6b2462c475033da8carll   case 0x5C4: // vsld (Shift Left Integer Double Word)
1707348ae46b56cef87c90638b25d6b2462c475033da8carll      DIP("vsld v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
1707448ae46b56cef87c90638b25d6b2462c475033da8carll      putVReg( vD_addr, binop(Iop_Shl64x2, mkexpr(vA), mkexpr(vB)) );
1707548ae46b56cef87c90638b25d6b2462c475033da8carll      break;
1707648ae46b56cef87c90638b25d6b2462c475033da8carll
170770a7b4f40d11db65d00af3b0f51c23807dd83817fcerion   case 0x1C4: { // vsl (Shift Left, AV p239)
170780a7b4f40d11db65d00af3b0f51c23807dd83817fcerion      IRTemp sh = newTemp(Ity_I8);
17079197bd17d3ba8ac5204cd5c9ba5fab571249eb791sewardj      DIP("vsl v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
170800a7b4f40d11db65d00af3b0f51c23807dd83817fcerion      assign( sh, binop(Iop_And8, mkU8(0x7),
170810a7b4f40d11db65d00af3b0f51c23807dd83817fcerion                        unop(Iop_32to8,
170820a7b4f40d11db65d00af3b0f51c23807dd83817fcerion                             unop(Iop_V128to32, mkexpr(vB)))) );
170830a7b4f40d11db65d00af3b0f51c23807dd83817fcerion      putVReg( vD_addr,
170840a7b4f40d11db65d00af3b0f51c23807dd83817fcerion               binop(Iop_ShlV128, mkexpr(vA), mkexpr(sh)) );
170850a7b4f40d11db65d00af3b0f51c23807dd83817fcerion      break;
170860a7b4f40d11db65d00af3b0f51c23807dd83817fcerion   }
170870a7b4f40d11db65d00af3b0f51c23807dd83817fcerion   case 0x40C: { // vslo (Shift Left by Octet, AV p243)
170880a7b4f40d11db65d00af3b0f51c23807dd83817fcerion      IRTemp sh = newTemp(Ity_I8);
17089197bd17d3ba8ac5204cd5c9ba5fab571249eb791sewardj      DIP("vslo v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
170900a7b4f40d11db65d00af3b0f51c23807dd83817fcerion      assign( sh, binop(Iop_And8, mkU8(0x78),
170910a7b4f40d11db65d00af3b0f51c23807dd83817fcerion                        unop(Iop_32to8,
170920a7b4f40d11db65d00af3b0f51c23807dd83817fcerion                             unop(Iop_V128to32, mkexpr(vB)))) );
170930a7b4f40d11db65d00af3b0f51c23807dd83817fcerion      putVReg( vD_addr,
170940a7b4f40d11db65d00af3b0f51c23807dd83817fcerion               binop(Iop_ShlV128, mkexpr(vA), mkexpr(sh)) );
170950a7b4f40d11db65d00af3b0f51c23807dd83817fcerion      break;
170960a7b4f40d11db65d00af3b0f51c23807dd83817fcerion   }
170970a7b4f40d11db65d00af3b0f51c23807dd83817fcerion
1709832aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion
1709932aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion   /* Shift Right */
1710032aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion   case 0x204: // vsrb (Shift Right B, AV p256)
1710132aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion      DIP("vsrb v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
171020a7b4f40d11db65d00af3b0f51c23807dd83817fcerion      putVReg( vD_addr, binop(Iop_Shr8x16, mkexpr(vA), mkexpr(vB)) );
171030a7b4f40d11db65d00af3b0f51c23807dd83817fcerion      break;
1710432aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion
1710532aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion   case 0x244: // vsrh (Shift Right HW, AV p257)
1710632aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion      DIP("vsrh v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
171070a7b4f40d11db65d00af3b0f51c23807dd83817fcerion      putVReg( vD_addr, binop(Iop_Shr16x8, mkexpr(vA), mkexpr(vB)) );
171080a7b4f40d11db65d00af3b0f51c23807dd83817fcerion      break;
1710932aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion
1711032aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion   case 0x284: // vsrw (Shift Right W, AV p259)
1711132aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion      DIP("vsrw v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
171120a7b4f40d11db65d00af3b0f51c23807dd83817fcerion      putVReg( vD_addr, binop(Iop_Shr32x4, mkexpr(vA), mkexpr(vB)) );
171130a7b4f40d11db65d00af3b0f51c23807dd83817fcerion      break;
1711432aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion
1711527b3d7ec17c3a0814d4980db87defbb4f07339bfcerion   case 0x2C4: { // vsr (Shift Right, AV p251)
1711627b3d7ec17c3a0814d4980db87defbb4f07339bfcerion      IRTemp sh = newTemp(Ity_I8);
17117197bd17d3ba8ac5204cd5c9ba5fab571249eb791sewardj      DIP("vsr v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
1711827b3d7ec17c3a0814d4980db87defbb4f07339bfcerion      assign( sh, binop(Iop_And8, mkU8(0x7),
1711927b3d7ec17c3a0814d4980db87defbb4f07339bfcerion                        unop(Iop_32to8,
1712027b3d7ec17c3a0814d4980db87defbb4f07339bfcerion                             unop(Iop_V128to32, mkexpr(vB)))) );
1712127b3d7ec17c3a0814d4980db87defbb4f07339bfcerion      putVReg( vD_addr,
1712227b3d7ec17c3a0814d4980db87defbb4f07339bfcerion               binop(Iop_ShrV128, mkexpr(vA), mkexpr(sh)) );
1712327b3d7ec17c3a0814d4980db87defbb4f07339bfcerion      break;
1712427b3d7ec17c3a0814d4980db87defbb4f07339bfcerion   }
171255b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion   case 0x304: // vsrab (Shift Right Alg B, AV p253)
1712632aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion      DIP("vsrab v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
171270a7b4f40d11db65d00af3b0f51c23807dd83817fcerion      putVReg( vD_addr, binop(Iop_Sar8x16, mkexpr(vA), mkexpr(vB)) );
171280a7b4f40d11db65d00af3b0f51c23807dd83817fcerion      break;
1712932aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion
171305b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion   case 0x344: // vsrah (Shift Right Alg HW, AV p254)
1713132aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion      DIP("vsrah v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
171320a7b4f40d11db65d00af3b0f51c23807dd83817fcerion      putVReg( vD_addr, binop(Iop_Sar16x8, mkexpr(vA), mkexpr(vB)) );
171330a7b4f40d11db65d00af3b0f51c23807dd83817fcerion      break;
1713432aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion
171355b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion   case 0x384: // vsraw (Shift Right Alg W, AV p255)
1713632aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion      DIP("vsraw v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
171370a7b4f40d11db65d00af3b0f51c23807dd83817fcerion      putVReg( vD_addr, binop(Iop_Sar32x4, mkexpr(vA), mkexpr(vB)) );
171380a7b4f40d11db65d00af3b0f51c23807dd83817fcerion      break;
1713932aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion
1714048ae46b56cef87c90638b25d6b2462c475033da8carll   case 0x3C4: // vsrad (Shift Right Alg Double Word)
1714148ae46b56cef87c90638b25d6b2462c475033da8carll      DIP("vsrad v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
1714248ae46b56cef87c90638b25d6b2462c475033da8carll      putVReg( vD_addr, binop(Iop_Sar64x2, mkexpr(vA), mkexpr(vB)) );
1714348ae46b56cef87c90638b25d6b2462c475033da8carll      break;
1714448ae46b56cef87c90638b25d6b2462c475033da8carll
171450a7b4f40d11db65d00af3b0f51c23807dd83817fcerion   case 0x44C: { // vsro (Shift Right by Octet, AV p258)
171460a7b4f40d11db65d00af3b0f51c23807dd83817fcerion      IRTemp sh = newTemp(Ity_I8);
17147197bd17d3ba8ac5204cd5c9ba5fab571249eb791sewardj      DIP("vsro v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
171480a7b4f40d11db65d00af3b0f51c23807dd83817fcerion      assign( sh, binop(Iop_And8, mkU8(0x78),
171490a7b4f40d11db65d00af3b0f51c23807dd83817fcerion                        unop(Iop_32to8,
171500a7b4f40d11db65d00af3b0f51c23807dd83817fcerion                             unop(Iop_V128to32, mkexpr(vB)))) );
171510a7b4f40d11db65d00af3b0f51c23807dd83817fcerion      putVReg( vD_addr,
171520a7b4f40d11db65d00af3b0f51c23807dd83817fcerion               binop(Iop_ShrV128, mkexpr(vA), mkexpr(sh)) );
171530a7b4f40d11db65d00af3b0f51c23807dd83817fcerion      break;
171540a7b4f40d11db65d00af3b0f51c23807dd83817fcerion   }
1715532aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion
1715648ae46b56cef87c90638b25d6b2462c475033da8carll   case 0x6C4: // vsrd (Shift Right Double Word)
1715748ae46b56cef87c90638b25d6b2462c475033da8carll      DIP("vsrd v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
1715848ae46b56cef87c90638b25d6b2462c475033da8carll      putVReg( vD_addr, binop(Iop_Shr64x2, mkexpr(vA), mkexpr(vB)) );
1715948ae46b56cef87c90638b25d6b2462c475033da8carll      break;
1716048ae46b56cef87c90638b25d6b2462c475033da8carll
1716148ae46b56cef87c90638b25d6b2462c475033da8carll
1716232aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion   default:
171635b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion      vex_printf("dis_av_shift(ppc)(opc2)\n");
1716432aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion      return False;
1716532aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion   }
1716632aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion   return True;
1716732aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion}
1716832aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion
1716932aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion/*
1717032aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion  AltiVec Permute Instructions
1717132aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion*/
1717232aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerionstatic Bool dis_av_permute ( UInt theInstr )
1717332aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion{
1717476de5cf615380b23b4b5bcced6541233cd4a93a0cerion   /* VA-Form, VX-Form */
1717576de5cf615380b23b4b5bcced6541233cd4a93a0cerion   UChar opc1      = ifieldOPC(theInstr);
1717676de5cf615380b23b4b5bcced6541233cd4a93a0cerion   UChar vD_addr   = ifieldRegDS(theInstr);
1717776de5cf615380b23b4b5bcced6541233cd4a93a0cerion   UChar vA_addr   = ifieldRegA(theInstr);
1717876de5cf615380b23b4b5bcced6541233cd4a93a0cerion   UChar UIMM_5    = vA_addr;
1717976de5cf615380b23b4b5bcced6541233cd4a93a0cerion   UChar vB_addr   = ifieldRegB(theInstr);
1718076de5cf615380b23b4b5bcced6541233cd4a93a0cerion   UChar vC_addr   = ifieldRegC(theInstr);
1718176de5cf615380b23b4b5bcced6541233cd4a93a0cerion   UChar b10       = ifieldBIT10(theInstr);
1718276de5cf615380b23b4b5bcced6541233cd4a93a0cerion   UChar SHB_uimm4 = toUChar( IFIELD( theInstr, 6, 4 ) );
1718376de5cf615380b23b4b5bcced6541233cd4a93a0cerion   UInt  opc2      = toUChar( IFIELD( theInstr, 0, 6 ) );
1718476de5cf615380b23b4b5bcced6541233cd4a93a0cerion
1718576de5cf615380b23b4b5bcced6541233cd4a93a0cerion   UChar SIMM_8 = extend_s_5to8(UIMM_5);
1718632aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion
171876e7a0ea9abe4e6443ebfc451d5681250eece75fdcerion   IRTemp vA = newTemp(Ity_V128);
171886e7a0ea9abe4e6443ebfc451d5681250eece75fdcerion   IRTemp vB = newTemp(Ity_V128);
171896e7a0ea9abe4e6443ebfc451d5681250eece75fdcerion   IRTemp vC = newTemp(Ity_V128);
171906e7a0ea9abe4e6443ebfc451d5681250eece75fdcerion   assign( vA, getVReg(vA_addr));
171916e7a0ea9abe4e6443ebfc451d5681250eece75fdcerion   assign( vB, getVReg(vB_addr));
171926e7a0ea9abe4e6443ebfc451d5681250eece75fdcerion   assign( vC, getVReg(vC_addr));
171936e7a0ea9abe4e6443ebfc451d5681250eece75fdcerion
1719432aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion   if (opc1 != 0x4) {
171955b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion      vex_printf("dis_av_permute(ppc)(instr)\n");
1719632aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion      return False;
1719732aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion   }
1719832aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion
1719932aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion   switch (opc2) {
1720032aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion   case 0x2A: // vsel (Conditional Select, AV p238)
1720132aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion      DIP("vsel v%d,v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr, vC_addr);
172026e7a0ea9abe4e6443ebfc451d5681250eece75fdcerion      /* vD = (vA & ~vC) | (vB & vC) */
172036e7a0ea9abe4e6443ebfc451d5681250eece75fdcerion      putVReg( vD_addr, binop(Iop_OrV128,
172046e7a0ea9abe4e6443ebfc451d5681250eece75fdcerion         binop(Iop_AndV128, mkexpr(vA), unop(Iop_NotV128, mkexpr(vC))),
172056e7a0ea9abe4e6443ebfc451d5681250eece75fdcerion         binop(Iop_AndV128, mkexpr(vB), mkexpr(vC))) );
172066e7a0ea9abe4e6443ebfc451d5681250eece75fdcerion      return True;
1720732aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion
1720892d9d876af80d14fa2f319f7109964f2d6231f15cerion   case 0x2B: { // vperm (Permute, AV p218)
1720992d9d876af80d14fa2f319f7109964f2d6231f15cerion      /* limited to two args for IR, so have to play games... */
17210dc1f91317b466ccabbe21bf0feda19658d5b614bsewardj      IRTemp a_perm  = newTemp(Ity_V128);
17211dc1f91317b466ccabbe21bf0feda19658d5b614bsewardj      IRTemp b_perm  = newTemp(Ity_V128);
17212dc1f91317b466ccabbe21bf0feda19658d5b614bsewardj      IRTemp mask    = newTemp(Ity_V128);
17213dc1f91317b466ccabbe21bf0feda19658d5b614bsewardj      IRTemp vC_andF = newTemp(Ity_V128);
172145b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion      DIP("vperm v%d,v%d,v%d,v%d\n",
172155b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion          vD_addr, vA_addr, vB_addr, vC_addr);
17216dc1f91317b466ccabbe21bf0feda19658d5b614bsewardj      /* Limit the Perm8x16 steering values to 0 .. 15 as that is what
17217dc1f91317b466ccabbe21bf0feda19658d5b614bsewardj         IR specifies, and also to hide irrelevant bits from
17218dc1f91317b466ccabbe21bf0feda19658d5b614bsewardj         memcheck */
172195b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion      assign( vC_andF,
172205b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion              binop(Iop_AndV128, mkexpr(vC),
172215b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion                                 unop(Iop_Dup8x16, mkU8(0xF))) );
172225b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion      assign( a_perm,
172235b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion              binop(Iop_Perm8x16, mkexpr(vA), mkexpr(vC_andF)) );
172245b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion      assign( b_perm,
172255b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion              binop(Iop_Perm8x16, mkexpr(vB), mkexpr(vC_andF)) );
1722692d9d876af80d14fa2f319f7109964f2d6231f15cerion      // mask[i8] = (vC[i8]_4 == 1) ? 0xFF : 0x0
1722792d9d876af80d14fa2f319f7109964f2d6231f15cerion      assign( mask, binop(Iop_SarN8x16,
1722892d9d876af80d14fa2f319f7109964f2d6231f15cerion                          binop(Iop_ShlN8x16, mkexpr(vC), mkU8(3)),
1722992d9d876af80d14fa2f319f7109964f2d6231f15cerion                          mkU8(7)) );
1723092d9d876af80d14fa2f319f7109964f2d6231f15cerion      // dst = (a & ~mask) | (b & mask)
1723192d9d876af80d14fa2f319f7109964f2d6231f15cerion      putVReg( vD_addr, binop(Iop_OrV128,
1723292d9d876af80d14fa2f319f7109964f2d6231f15cerion                              binop(Iop_AndV128, mkexpr(a_perm),
1723392d9d876af80d14fa2f319f7109964f2d6231f15cerion                                    unop(Iop_NotV128, mkexpr(mask))),
1723492d9d876af80d14fa2f319f7109964f2d6231f15cerion                              binop(Iop_AndV128, mkexpr(b_perm),
1723592d9d876af80d14fa2f319f7109964f2d6231f15cerion                                    mkexpr(mask))) );
1723692d9d876af80d14fa2f319f7109964f2d6231f15cerion      return True;
1723792d9d876af80d14fa2f319f7109964f2d6231f15cerion   }
1723832aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion   case 0x2C: // vsldoi (Shift Left Double by Octet Imm, AV p241)
1723932aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion      if (b10 != 0) {
172405b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion         vex_printf("dis_av_permute(ppc)(vsldoi)\n");
1724132aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion         return False;
1724232aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion      }
172435b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion      DIP("vsldoi v%d,v%d,v%d,%d\n",
172445b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion          vD_addr, vA_addr, vB_addr, SHB_uimm4);
1724592d9d876af80d14fa2f319f7109964f2d6231f15cerion      if (SHB_uimm4 == 0)
1724692d9d876af80d14fa2f319f7109964f2d6231f15cerion         putVReg( vD_addr, mkexpr(vA) );
1724792d9d876af80d14fa2f319f7109964f2d6231f15cerion      else
1724892d9d876af80d14fa2f319f7109964f2d6231f15cerion         putVReg( vD_addr,
172495b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion            binop(Iop_OrV128,
172505b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion                  binop(Iop_ShlV128, mkexpr(vA), mkU8(SHB_uimm4*8)),
172515b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion                  binop(Iop_ShrV128, mkexpr(vB), mkU8((16-SHB_uimm4)*8))) );
1725292d9d876af80d14fa2f319f7109964f2d6231f15cerion      return True;
172537deaf9552b546b847528cf39b38898fb7742b5f5carll   case 0x2D: {  // vpermxor (Vector Permute and Exclusive-OR)
172547deaf9552b546b847528cf39b38898fb7742b5f5carll      IRTemp a_perm  = newTemp(Ity_V128);
172557deaf9552b546b847528cf39b38898fb7742b5f5carll      IRTemp b_perm  = newTemp(Ity_V128);
172567deaf9552b546b847528cf39b38898fb7742b5f5carll      IRTemp vrc_a   = newTemp(Ity_V128);
172577deaf9552b546b847528cf39b38898fb7742b5f5carll      IRTemp vrc_b   = newTemp(Ity_V128);
172587deaf9552b546b847528cf39b38898fb7742b5f5carll
172597deaf9552b546b847528cf39b38898fb7742b5f5carll      /* IBM index  is 0:7, Change index value to index 7:0 */
172607deaf9552b546b847528cf39b38898fb7742b5f5carll      assign( vrc_b, binop( Iop_AndV128, mkexpr( vC ),
172617deaf9552b546b847528cf39b38898fb7742b5f5carll                            unop( Iop_Dup8x16, mkU8( 0xF ) ) ) );
172627deaf9552b546b847528cf39b38898fb7742b5f5carll      assign( vrc_a, binop( Iop_ShrV128,
172637deaf9552b546b847528cf39b38898fb7742b5f5carll                            binop( Iop_AndV128, mkexpr( vC ),
172647deaf9552b546b847528cf39b38898fb7742b5f5carll                                   unop( Iop_Dup8x16, mkU8( 0xF0 ) ) ),
172657deaf9552b546b847528cf39b38898fb7742b5f5carll                            mkU8 ( 4 ) ) );
172667deaf9552b546b847528cf39b38898fb7742b5f5carll      assign( a_perm, binop( Iop_Perm8x16, mkexpr( vA ), mkexpr( vrc_a ) ) );
172677deaf9552b546b847528cf39b38898fb7742b5f5carll      assign( b_perm, binop( Iop_Perm8x16, mkexpr( vB ), mkexpr( vrc_b ) ) );
172687deaf9552b546b847528cf39b38898fb7742b5f5carll      putVReg( vD_addr, binop( Iop_XorV128,
172697deaf9552b546b847528cf39b38898fb7742b5f5carll                               mkexpr( a_perm ), mkexpr( b_perm) ) );
172707deaf9552b546b847528cf39b38898fb7742b5f5carll      return True;
172717deaf9552b546b847528cf39b38898fb7742b5f5carll   }
1727232aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion   default:
1727332aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion     break; // Fall through...
1727432aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion   }
1727532aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion
1727676de5cf615380b23b4b5bcced6541233cd4a93a0cerion   opc2 = IFIELD( theInstr, 0, 11 );
1727732aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion   switch (opc2) {
1727832aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion
1727932aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion   /* Merge */
1728032aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion   case 0x00C: // vmrghb (Merge High B, AV p195)
1728132aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion      DIP("vmrghb v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
1728292d9d876af80d14fa2f319f7109964f2d6231f15cerion      putVReg( vD_addr,
1728392d9d876af80d14fa2f319f7109964f2d6231f15cerion               binop(Iop_InterleaveHI8x16, mkexpr(vA), mkexpr(vB)) );
1728492d9d876af80d14fa2f319f7109964f2d6231f15cerion      break;
1728532aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion
1728632aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion   case 0x04C: // vmrghh (Merge High HW, AV p196)
1728732aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion      DIP("vmrghh v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
1728892d9d876af80d14fa2f319f7109964f2d6231f15cerion      putVReg( vD_addr,
1728992d9d876af80d14fa2f319f7109964f2d6231f15cerion               binop(Iop_InterleaveHI16x8, mkexpr(vA), mkexpr(vB)) );
1729092d9d876af80d14fa2f319f7109964f2d6231f15cerion      break;
1729132aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion
1729232aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion   case 0x08C: // vmrghw (Merge High W, AV p197)
1729332aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion      DIP("vmrghw v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
1729492d9d876af80d14fa2f319f7109964f2d6231f15cerion      putVReg( vD_addr,
1729592d9d876af80d14fa2f319f7109964f2d6231f15cerion               binop(Iop_InterleaveHI32x4, mkexpr(vA), mkexpr(vB)) );
1729692d9d876af80d14fa2f319f7109964f2d6231f15cerion      break;
1729732aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion
1729832aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion   case 0x10C: // vmrglb (Merge Low B, AV p198)
1729932aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion      DIP("vmrglb v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
1730092d9d876af80d14fa2f319f7109964f2d6231f15cerion      putVReg( vD_addr,
1730192d9d876af80d14fa2f319f7109964f2d6231f15cerion               binop(Iop_InterleaveLO8x16, mkexpr(vA), mkexpr(vB)) );
1730292d9d876af80d14fa2f319f7109964f2d6231f15cerion      break;
1730332aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion
1730432aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion   case 0x14C: // vmrglh (Merge Low HW, AV p199)
1730532aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion      DIP("vmrglh v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
1730692d9d876af80d14fa2f319f7109964f2d6231f15cerion      putVReg( vD_addr,
1730792d9d876af80d14fa2f319f7109964f2d6231f15cerion               binop(Iop_InterleaveLO16x8, mkexpr(vA), mkexpr(vB)) );
1730892d9d876af80d14fa2f319f7109964f2d6231f15cerion      break;
1730932aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion
1731032aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion   case 0x18C: // vmrglw (Merge Low W, AV p200)
1731132aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion      DIP("vmrglw v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
1731292d9d876af80d14fa2f319f7109964f2d6231f15cerion      putVReg( vD_addr,
1731392d9d876af80d14fa2f319f7109964f2d6231f15cerion               binop(Iop_InterleaveLO32x4, mkexpr(vA), mkexpr(vB)) );
1731492d9d876af80d14fa2f319f7109964f2d6231f15cerion      break;
1731592d9d876af80d14fa2f319f7109964f2d6231f15cerion
1731632aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion
1731732aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion   /* Splat */
1731892d9d876af80d14fa2f319f7109964f2d6231f15cerion   case 0x20C: { // vspltb (Splat Byte, AV p245)
1731992d9d876af80d14fa2f319f7109964f2d6231f15cerion      /* vD = Dup8x16( vB[UIMM_5] ) */
17320d14709407df9363767aa888b03f95f08df169dcesewardj      UChar sh_uimm = (15 - (UIMM_5 & 15)) * 8;
17321197bd17d3ba8ac5204cd5c9ba5fab571249eb791sewardj      DIP("vspltb v%d,v%d,%d\n", vD_addr, vB_addr, UIMM_5);
1732292d9d876af80d14fa2f319f7109964f2d6231f15cerion      putVReg( vD_addr, unop(Iop_Dup8x16,
1732392d9d876af80d14fa2f319f7109964f2d6231f15cerion           unop(Iop_32to8, unop(Iop_V128to32,
1732492d9d876af80d14fa2f319f7109964f2d6231f15cerion                binop(Iop_ShrV128, mkexpr(vB), mkU8(sh_uimm))))) );
1732592d9d876af80d14fa2f319f7109964f2d6231f15cerion      break;
1732692d9d876af80d14fa2f319f7109964f2d6231f15cerion   }
1732792d9d876af80d14fa2f319f7109964f2d6231f15cerion   case 0x24C: { // vsplth (Splat Half Word, AV p246)
17328d14709407df9363767aa888b03f95f08df169dcesewardj      UChar sh_uimm = (7 - (UIMM_5 & 7)) * 16;
17329197bd17d3ba8ac5204cd5c9ba5fab571249eb791sewardj      DIP("vsplth v%d,v%d,%d\n", vD_addr, vB_addr, UIMM_5);
1733092d9d876af80d14fa2f319f7109964f2d6231f15cerion      putVReg( vD_addr, unop(Iop_Dup16x8,
1733192d9d876af80d14fa2f319f7109964f2d6231f15cerion           unop(Iop_32to16, unop(Iop_V128to32,
1733292d9d876af80d14fa2f319f7109964f2d6231f15cerion                binop(Iop_ShrV128, mkexpr(vB), mkU8(sh_uimm))))) );
1733392d9d876af80d14fa2f319f7109964f2d6231f15cerion      break;
1733492d9d876af80d14fa2f319f7109964f2d6231f15cerion   }
1733527b3d7ec17c3a0814d4980db87defbb4f07339bfcerion   case 0x28C: { // vspltw (Splat Word, AV p250)
1733627b3d7ec17c3a0814d4980db87defbb4f07339bfcerion      /* vD = Dup32x4( vB[UIMM_5] ) */
17337d14709407df9363767aa888b03f95f08df169dcesewardj      UChar sh_uimm = (3 - (UIMM_5 & 3)) * 32;
17338197bd17d3ba8ac5204cd5c9ba5fab571249eb791sewardj      DIP("vspltw v%d,v%d,%d\n", vD_addr, vB_addr, UIMM_5);
1733927b3d7ec17c3a0814d4980db87defbb4f07339bfcerion      putVReg( vD_addr, unop(Iop_Dup32x4,
1734027b3d7ec17c3a0814d4980db87defbb4f07339bfcerion         unop(Iop_V128to32,
1734127b3d7ec17c3a0814d4980db87defbb4f07339bfcerion              binop(Iop_ShrV128, mkexpr(vB), mkU8(sh_uimm)))) );
1734227b3d7ec17c3a0814d4980db87defbb4f07339bfcerion      break;
1734327b3d7ec17c3a0814d4980db87defbb4f07339bfcerion   }
1734432aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion   case 0x30C: // vspltisb (Splat Immediate Signed B, AV p247)
1734532aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion      DIP("vspltisb v%d,%d\n", vD_addr, (Char)SIMM_8);
1734692d9d876af80d14fa2f319f7109964f2d6231f15cerion      putVReg( vD_addr, unop(Iop_Dup8x16, mkU8(SIMM_8)) );
1734792d9d876af80d14fa2f319f7109964f2d6231f15cerion      break;
1734832aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion
1734932aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion   case 0x34C: // vspltish (Splat Immediate Signed HW, AV p248)
1735032aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion      DIP("vspltish v%d,%d\n", vD_addr, (Char)SIMM_8);
173515b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion      putVReg( vD_addr,
173525b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion               unop(Iop_Dup16x8, mkU16(extend_s_8to32(SIMM_8))) );
1735392d9d876af80d14fa2f319f7109964f2d6231f15cerion      break;
1735432aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion
1735532aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion   case 0x38C: // vspltisw (Splat Immediate Signed W, AV p249)
1735632aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion      DIP("vspltisw v%d,%d\n", vD_addr, (Char)SIMM_8);
173575b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion      putVReg( vD_addr,
173585b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion               unop(Iop_Dup32x4, mkU32(extend_s_8to32(SIMM_8))) );
1735992d9d876af80d14fa2f319f7109964f2d6231f15cerion      break;
1736032aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion
1736148ae46b56cef87c90638b25d6b2462c475033da8carll   case 0x68C: // vmrgow (Merge Odd Word)
1736248ae46b56cef87c90638b25d6b2462c475033da8carll     DIP("vmrgow v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
1736348ae46b56cef87c90638b25d6b2462c475033da8carll      /*   VD[0] <- VA[1]
1736448ae46b56cef87c90638b25d6b2462c475033da8carll           VD[1] <- VB[1]
1736548ae46b56cef87c90638b25d6b2462c475033da8carll           VD[2] <- VA[3]
1736648ae46b56cef87c90638b25d6b2462c475033da8carll           VD[3] <- VB[3]
1736748ae46b56cef87c90638b25d6b2462c475033da8carll      */
1736848ae46b56cef87c90638b25d6b2462c475033da8carll      putVReg( vD_addr,
1736948ae46b56cef87c90638b25d6b2462c475033da8carll               binop(Iop_CatOddLanes32x4, mkexpr(vA), mkexpr(vB) ) );
1737048ae46b56cef87c90638b25d6b2462c475033da8carll      break;
1737148ae46b56cef87c90638b25d6b2462c475033da8carll
1737248ae46b56cef87c90638b25d6b2462c475033da8carll   case 0x78C: // vmrgew (Merge Even Word)
1737348ae46b56cef87c90638b25d6b2462c475033da8carll      DIP("vmrgew v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
1737448ae46b56cef87c90638b25d6b2462c475033da8carll      /*   VD[0] <- VA[0]
1737548ae46b56cef87c90638b25d6b2462c475033da8carll           VD[1] <- VB[0]
1737648ae46b56cef87c90638b25d6b2462c475033da8carll           VD[2] <- VA[2]
1737748ae46b56cef87c90638b25d6b2462c475033da8carll           VD[3] <- VB[2]
1737848ae46b56cef87c90638b25d6b2462c475033da8carll      */
1737948ae46b56cef87c90638b25d6b2462c475033da8carll      putVReg( vD_addr,
1738048ae46b56cef87c90638b25d6b2462c475033da8carll               binop(Iop_CatEvenLanes32x4, mkexpr(vA), mkexpr(vB) ) );
1738148ae46b56cef87c90638b25d6b2462c475033da8carll      break;
1738248ae46b56cef87c90638b25d6b2462c475033da8carll
1738332aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion   default:
173845b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion      vex_printf("dis_av_permute(ppc)(opc2)\n");
1738532aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion      return False;
1738632aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion   }
1738732aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion   return True;
1738832aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion}
1738932aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion
1739032aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion/*
1739132aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion  AltiVec Pack/Unpack Instructions
1739232aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion*/
1739332aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerionstatic Bool dis_av_pack ( UInt theInstr )
1739432aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion{
1739576de5cf615380b23b4b5bcced6541233cd4a93a0cerion   /* VX-Form */
1739676de5cf615380b23b4b5bcced6541233cd4a93a0cerion   UChar opc1     = ifieldOPC(theInstr);
1739776de5cf615380b23b4b5bcced6541233cd4a93a0cerion   UChar vD_addr  = ifieldRegDS(theInstr);
1739876de5cf615380b23b4b5bcced6541233cd4a93a0cerion   UChar vA_addr  = ifieldRegA(theInstr);
1739976de5cf615380b23b4b5bcced6541233cd4a93a0cerion   UChar vB_addr  = ifieldRegB(theInstr);
1740076de5cf615380b23b4b5bcced6541233cd4a93a0cerion   UInt  opc2     = IFIELD( theInstr, 0, 11 );
1740132aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion
17402197bd17d3ba8ac5204cd5c9ba5fab571249eb791sewardj   IRTemp signs = IRTemp_INVALID;
17403197bd17d3ba8ac5204cd5c9ba5fab571249eb791sewardj   IRTemp zeros = IRTemp_INVALID;
1740476de5cf615380b23b4b5bcced6541233cd4a93a0cerion   IRTemp vA    = newTemp(Ity_V128);
1740576de5cf615380b23b4b5bcced6541233cd4a93a0cerion   IRTemp vB    = newTemp(Ity_V128);
174063c052793dacedf702ca4b6ccbfb46a7efa7bc714cerion   assign( vA, getVReg(vA_addr));
174073c052793dacedf702ca4b6ccbfb46a7efa7bc714cerion   assign( vB, getVReg(vB_addr));
174083c052793dacedf702ca4b6ccbfb46a7efa7bc714cerion
1740932aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion   if (opc1 != 0x4) {
174105b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion      vex_printf("dis_av_pack(ppc)(instr)\n");
1741132aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion      return False;
1741232aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion   }
1741332aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion   switch (opc2) {
1741432aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion   /* Packing */
1741532aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion   case 0x00E: // vpkuhum (Pack Unsigned HW Unsigned Modulo, AV p224)
1741632aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion      DIP("vpkuhum v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
174175f438dd73072211989c6d496845bdc9b777ecbecsewardj      putVReg( vD_addr,
174185f438dd73072211989c6d496845bdc9b777ecbecsewardj               binop(Iop_NarrowBin16to8x16, mkexpr(vA), mkexpr(vB)) );
174193c052793dacedf702ca4b6ccbfb46a7efa7bc714cerion      return True;
1742032aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion
1742132aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion   case 0x04E: // vpkuwum (Pack Unsigned W Unsigned Modulo, AV p226)
1742232aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion      DIP("vpkuwum v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
174235f438dd73072211989c6d496845bdc9b777ecbecsewardj      putVReg( vD_addr,
174245f438dd73072211989c6d496845bdc9b777ecbecsewardj               binop(Iop_NarrowBin32to16x8, mkexpr(vA), mkexpr(vB)) );
174253c052793dacedf702ca4b6ccbfb46a7efa7bc714cerion      return True;
1742632aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion
1742732aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion   case 0x08E: // vpkuhus (Pack Unsigned HW Unsigned Saturate, AV p225)
1742832aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion      DIP("vpkuhus v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
174295b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion      putVReg( vD_addr,
174305f438dd73072211989c6d496845bdc9b777ecbecsewardj               binop(Iop_QNarrowBin16Uto8Ux16, mkexpr(vA), mkexpr(vB)) );
174313c052793dacedf702ca4b6ccbfb46a7efa7bc714cerion      // TODO: set VSCR[SAT]
174323c052793dacedf702ca4b6ccbfb46a7efa7bc714cerion      return True;
1743332aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion
1743432aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion   case 0x0CE: // vpkuwus (Pack Unsigned W Unsigned Saturate, AV p227)
1743532aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion      DIP("vpkuwus v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
174365b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion      putVReg( vD_addr,
174375f438dd73072211989c6d496845bdc9b777ecbecsewardj               binop(Iop_QNarrowBin32Uto16Ux8, mkexpr(vA), mkexpr(vB)) );
174383c052793dacedf702ca4b6ccbfb46a7efa7bc714cerion      // TODO: set VSCR[SAT]
174393c052793dacedf702ca4b6ccbfb46a7efa7bc714cerion      return True;
1744032aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion
174413c052793dacedf702ca4b6ccbfb46a7efa7bc714cerion   case 0x10E: { // vpkshus (Pack Signed HW Unsigned Saturate, AV p221)
174423c052793dacedf702ca4b6ccbfb46a7efa7bc714cerion      // This insn does a signed->unsigned saturating conversion.
174433c052793dacedf702ca4b6ccbfb46a7efa7bc714cerion      // Conversion done here, then uses unsigned->unsigned vpk insn:
174443c052793dacedf702ca4b6ccbfb46a7efa7bc714cerion      //  => UnsignedSaturatingNarrow( x & ~ (x >>s 15) )
174453c052793dacedf702ca4b6ccbfb46a7efa7bc714cerion      IRTemp vA_tmp = newTemp(Ity_V128);
174463c052793dacedf702ca4b6ccbfb46a7efa7bc714cerion      IRTemp vB_tmp = newTemp(Ity_V128);
17447197bd17d3ba8ac5204cd5c9ba5fab571249eb791sewardj      DIP("vpkshus v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
174483c052793dacedf702ca4b6ccbfb46a7efa7bc714cerion      assign( vA_tmp, binop(Iop_AndV128, mkexpr(vA),
174493c052793dacedf702ca4b6ccbfb46a7efa7bc714cerion                            unop(Iop_NotV128,
174503c052793dacedf702ca4b6ccbfb46a7efa7bc714cerion                                 binop(Iop_SarN16x8,
174513c052793dacedf702ca4b6ccbfb46a7efa7bc714cerion                                       mkexpr(vA), mkU8(15)))) );
174523c052793dacedf702ca4b6ccbfb46a7efa7bc714cerion      assign( vB_tmp, binop(Iop_AndV128, mkexpr(vB),
174533c052793dacedf702ca4b6ccbfb46a7efa7bc714cerion                            unop(Iop_NotV128,
174543c052793dacedf702ca4b6ccbfb46a7efa7bc714cerion                                 binop(Iop_SarN16x8,
174553c052793dacedf702ca4b6ccbfb46a7efa7bc714cerion                                       mkexpr(vB), mkU8(15)))) );
174565f438dd73072211989c6d496845bdc9b777ecbecsewardj      putVReg( vD_addr, binop(Iop_QNarrowBin16Uto8Ux16,
174573c052793dacedf702ca4b6ccbfb46a7efa7bc714cerion                              mkexpr(vA_tmp), mkexpr(vB_tmp)) );
174583c052793dacedf702ca4b6ccbfb46a7efa7bc714cerion      // TODO: set VSCR[SAT]
174593c052793dacedf702ca4b6ccbfb46a7efa7bc714cerion      return True;
174603c052793dacedf702ca4b6ccbfb46a7efa7bc714cerion   }
174613c052793dacedf702ca4b6ccbfb46a7efa7bc714cerion   case 0x14E: { // vpkswus (Pack Signed W Unsigned Saturate, AV p223)
174623c052793dacedf702ca4b6ccbfb46a7efa7bc714cerion      // This insn does a signed->unsigned saturating conversion.
174633c052793dacedf702ca4b6ccbfb46a7efa7bc714cerion      // Conversion done here, then uses unsigned->unsigned vpk insn:
174643c052793dacedf702ca4b6ccbfb46a7efa7bc714cerion      //  => UnsignedSaturatingNarrow( x & ~ (x >>s 31) )
174653c052793dacedf702ca4b6ccbfb46a7efa7bc714cerion      IRTemp vA_tmp = newTemp(Ity_V128);
174663c052793dacedf702ca4b6ccbfb46a7efa7bc714cerion      IRTemp vB_tmp = newTemp(Ity_V128);
17467197bd17d3ba8ac5204cd5c9ba5fab571249eb791sewardj      DIP("vpkswus v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
174683c052793dacedf702ca4b6ccbfb46a7efa7bc714cerion      assign( vA_tmp, binop(Iop_AndV128, mkexpr(vA),
174693c052793dacedf702ca4b6ccbfb46a7efa7bc714cerion                            unop(Iop_NotV128,
174703c052793dacedf702ca4b6ccbfb46a7efa7bc714cerion                                 binop(Iop_SarN32x4,
174713c052793dacedf702ca4b6ccbfb46a7efa7bc714cerion                                       mkexpr(vA), mkU8(31)))) );
174723c052793dacedf702ca4b6ccbfb46a7efa7bc714cerion      assign( vB_tmp, binop(Iop_AndV128, mkexpr(vB),
174733c052793dacedf702ca4b6ccbfb46a7efa7bc714cerion                            unop(Iop_NotV128,
174743c052793dacedf702ca4b6ccbfb46a7efa7bc714cerion                                 binop(Iop_SarN32x4,
174753c052793dacedf702ca4b6ccbfb46a7efa7bc714cerion                                       mkexpr(vB), mkU8(31)))) );
174765f438dd73072211989c6d496845bdc9b777ecbecsewardj      putVReg( vD_addr, binop(Iop_QNarrowBin32Uto16Ux8,
174773c052793dacedf702ca4b6ccbfb46a7efa7bc714cerion                              mkexpr(vA_tmp), mkexpr(vB_tmp)) );
174783c052793dacedf702ca4b6ccbfb46a7efa7bc714cerion      // TODO: set VSCR[SAT]
174793c052793dacedf702ca4b6ccbfb46a7efa7bc714cerion      return True;
174803c052793dacedf702ca4b6ccbfb46a7efa7bc714cerion   }
1748132aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion   case 0x18E: // vpkshss (Pack Signed HW Signed Saturate, AV p220)
1748232aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion      DIP("vpkshss v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
174835b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion      putVReg( vD_addr,
174845f438dd73072211989c6d496845bdc9b777ecbecsewardj               binop(Iop_QNarrowBin16Sto8Sx16, mkexpr(vA), mkexpr(vB)) );
174853c052793dacedf702ca4b6ccbfb46a7efa7bc714cerion      // TODO: set VSCR[SAT]
174863c052793dacedf702ca4b6ccbfb46a7efa7bc714cerion      return True;
1748732aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion
1748832aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion   case 0x1CE: // vpkswss (Pack Signed W Signed Saturate, AV p222)
1748932aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion      DIP("vpkswss v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
174905b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion      putVReg( vD_addr,
174915f438dd73072211989c6d496845bdc9b777ecbecsewardj               binop(Iop_QNarrowBin32Sto16Sx8, mkexpr(vA), mkexpr(vB)) );
174923c052793dacedf702ca4b6ccbfb46a7efa7bc714cerion      // TODO: set VSCR[SAT]
174933c052793dacedf702ca4b6ccbfb46a7efa7bc714cerion      return True;
1749432aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion
174953c052793dacedf702ca4b6ccbfb46a7efa7bc714cerion   case 0x30E: { // vpkpx (Pack Pixel, AV p219)
174963c052793dacedf702ca4b6ccbfb46a7efa7bc714cerion      /* CAB: Worth a new primop? */
174975b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion      /* Using shifts to compact pixel elements, then packing them */
174983c052793dacedf702ca4b6ccbfb46a7efa7bc714cerion      IRTemp a1 = newTemp(Ity_V128);
174993c052793dacedf702ca4b6ccbfb46a7efa7bc714cerion      IRTemp a2 = newTemp(Ity_V128);
175003c052793dacedf702ca4b6ccbfb46a7efa7bc714cerion      IRTemp a3 = newTemp(Ity_V128);
175013c052793dacedf702ca4b6ccbfb46a7efa7bc714cerion      IRTemp a_tmp = newTemp(Ity_V128);
175023c052793dacedf702ca4b6ccbfb46a7efa7bc714cerion      IRTemp b1 = newTemp(Ity_V128);
175033c052793dacedf702ca4b6ccbfb46a7efa7bc714cerion      IRTemp b2 = newTemp(Ity_V128);
175043c052793dacedf702ca4b6ccbfb46a7efa7bc714cerion      IRTemp b3 = newTemp(Ity_V128);
175053c052793dacedf702ca4b6ccbfb46a7efa7bc714cerion      IRTemp b_tmp = newTemp(Ity_V128);
17506197bd17d3ba8ac5204cd5c9ba5fab571249eb791sewardj      DIP("vpkpx v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
175073c052793dacedf702ca4b6ccbfb46a7efa7bc714cerion      assign( a1, binop(Iop_ShlN16x8,
175083c052793dacedf702ca4b6ccbfb46a7efa7bc714cerion                        binop(Iop_ShrN32x4, mkexpr(vA), mkU8(19)),
175093c052793dacedf702ca4b6ccbfb46a7efa7bc714cerion                        mkU8(10)) );
175103c052793dacedf702ca4b6ccbfb46a7efa7bc714cerion      assign( a2, binop(Iop_ShlN16x8,
175113c052793dacedf702ca4b6ccbfb46a7efa7bc714cerion                        binop(Iop_ShrN16x8, mkexpr(vA), mkU8(11)),
175123c052793dacedf702ca4b6ccbfb46a7efa7bc714cerion                        mkU8(5)) );
175133c052793dacedf702ca4b6ccbfb46a7efa7bc714cerion      assign( a3,  binop(Iop_ShrN16x8,
175143c052793dacedf702ca4b6ccbfb46a7efa7bc714cerion                         binop(Iop_ShlN16x8, mkexpr(vA), mkU8(8)),
175153c052793dacedf702ca4b6ccbfb46a7efa7bc714cerion                         mkU8(11)) );
175163c052793dacedf702ca4b6ccbfb46a7efa7bc714cerion      assign( a_tmp, binop(Iop_OrV128, mkexpr(a1),
175173c052793dacedf702ca4b6ccbfb46a7efa7bc714cerion                           binop(Iop_OrV128, mkexpr(a2), mkexpr(a3))) );
175183c052793dacedf702ca4b6ccbfb46a7efa7bc714cerion
175193c052793dacedf702ca4b6ccbfb46a7efa7bc714cerion      assign( b1, binop(Iop_ShlN16x8,
175203c052793dacedf702ca4b6ccbfb46a7efa7bc714cerion                        binop(Iop_ShrN32x4, mkexpr(vB), mkU8(19)),
175213c052793dacedf702ca4b6ccbfb46a7efa7bc714cerion                        mkU8(10)) );
175223c052793dacedf702ca4b6ccbfb46a7efa7bc714cerion      assign( b2, binop(Iop_ShlN16x8,
175233c052793dacedf702ca4b6ccbfb46a7efa7bc714cerion                        binop(Iop_ShrN16x8, mkexpr(vB), mkU8(11)),
175243c052793dacedf702ca4b6ccbfb46a7efa7bc714cerion                        mkU8(5)) );
175253c052793dacedf702ca4b6ccbfb46a7efa7bc714cerion      assign( b3,  binop(Iop_ShrN16x8,
175263c052793dacedf702ca4b6ccbfb46a7efa7bc714cerion                         binop(Iop_ShlN16x8, mkexpr(vB), mkU8(8)),
175273c052793dacedf702ca4b6ccbfb46a7efa7bc714cerion                         mkU8(11)) );
175283c052793dacedf702ca4b6ccbfb46a7efa7bc714cerion      assign( b_tmp, binop(Iop_OrV128, mkexpr(b1),
175293c052793dacedf702ca4b6ccbfb46a7efa7bc714cerion                           binop(Iop_OrV128, mkexpr(b2), mkexpr(b3))) );
175303c052793dacedf702ca4b6ccbfb46a7efa7bc714cerion
175315f438dd73072211989c6d496845bdc9b777ecbecsewardj      putVReg( vD_addr, binop(Iop_NarrowBin32to16x8,
175323c052793dacedf702ca4b6ccbfb46a7efa7bc714cerion                              mkexpr(a_tmp), mkexpr(b_tmp)) );
175333c052793dacedf702ca4b6ccbfb46a7efa7bc714cerion      return True;
175343c052793dacedf702ca4b6ccbfb46a7efa7bc714cerion   }
1753532aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion
175360c74bb5aa3240f693df0568d578baabf0c376dc4carll   case 0x44E: // vpkudum (Pack Unsigned Double Word Unsigned Modulo)
175370c74bb5aa3240f693df0568d578baabf0c376dc4carll      DIP("vpkudum v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
175380c74bb5aa3240f693df0568d578baabf0c376dc4carll      putVReg( vD_addr,
175390c74bb5aa3240f693df0568d578baabf0c376dc4carll               binop(Iop_NarrowBin64to32x4, mkexpr(vA), mkexpr(vB)) );
175400c74bb5aa3240f693df0568d578baabf0c376dc4carll      return True;
175410c74bb5aa3240f693df0568d578baabf0c376dc4carll
1754248ae46b56cef87c90638b25d6b2462c475033da8carll   case 0x4CE: // vpkudus (Pack Unsigned Double Word Unsigned Saturate)
1754348ae46b56cef87c90638b25d6b2462c475033da8carll      DIP("vpkudus v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
1754448ae46b56cef87c90638b25d6b2462c475033da8carll      putVReg( vD_addr,
1754548ae46b56cef87c90638b25d6b2462c475033da8carll               binop(Iop_QNarrowBin64Uto32Ux4, mkexpr(vA), mkexpr(vB)) );
1754648ae46b56cef87c90638b25d6b2462c475033da8carll      // TODO: set VSCR[SAT]
1754748ae46b56cef87c90638b25d6b2462c475033da8carll      return True;
1754848ae46b56cef87c90638b25d6b2462c475033da8carll
1754948ae46b56cef87c90638b25d6b2462c475033da8carll   case 0x54E: { // vpksdus (Pack Signed Double Word Unsigned Saturate)
1755048ae46b56cef87c90638b25d6b2462c475033da8carll      // This insn does a doubled signed->double unsigned saturating conversion
1755148ae46b56cef87c90638b25d6b2462c475033da8carll      // Conversion done here, then uses unsigned->unsigned vpk insn:
1755248ae46b56cef87c90638b25d6b2462c475033da8carll      //  => UnsignedSaturatingNarrow( x & ~ (x >>s 31) )
1755348ae46b56cef87c90638b25d6b2462c475033da8carll      // This is similar to the technique used for vpkswus, except done
1755448ae46b56cef87c90638b25d6b2462c475033da8carll      // with double word integers versus word integers.
1755548ae46b56cef87c90638b25d6b2462c475033da8carll      IRTemp vA_tmp = newTemp(Ity_V128);
1755648ae46b56cef87c90638b25d6b2462c475033da8carll      IRTemp vB_tmp = newTemp(Ity_V128);
1755748ae46b56cef87c90638b25d6b2462c475033da8carll      DIP("vpksdus v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
1755848ae46b56cef87c90638b25d6b2462c475033da8carll      assign( vA_tmp, binop(Iop_AndV128, mkexpr(vA),
1755948ae46b56cef87c90638b25d6b2462c475033da8carll                            unop(Iop_NotV128,
1756048ae46b56cef87c90638b25d6b2462c475033da8carll                                 binop(Iop_SarN64x2,
1756148ae46b56cef87c90638b25d6b2462c475033da8carll                                       mkexpr(vA), mkU8(63)))) );
1756248ae46b56cef87c90638b25d6b2462c475033da8carll      assign( vB_tmp, binop(Iop_AndV128, mkexpr(vB),
1756348ae46b56cef87c90638b25d6b2462c475033da8carll                            unop(Iop_NotV128,
1756448ae46b56cef87c90638b25d6b2462c475033da8carll                                 binop(Iop_SarN64x2,
1756548ae46b56cef87c90638b25d6b2462c475033da8carll                                       mkexpr(vB), mkU8(63)))) );
1756648ae46b56cef87c90638b25d6b2462c475033da8carll      putVReg( vD_addr, binop(Iop_QNarrowBin64Uto32Ux4,
1756748ae46b56cef87c90638b25d6b2462c475033da8carll                              mkexpr(vA_tmp), mkexpr(vB_tmp)) );
1756848ae46b56cef87c90638b25d6b2462c475033da8carll      // TODO: set VSCR[SAT]
1756948ae46b56cef87c90638b25d6b2462c475033da8carll      return True;
1757048ae46b56cef87c90638b25d6b2462c475033da8carll   }
1757148ae46b56cef87c90638b25d6b2462c475033da8carll
1757248ae46b56cef87c90638b25d6b2462c475033da8carll   case 0x5CE: // vpksdss (Pack Signed double word Signed Saturate)
1757348ae46b56cef87c90638b25d6b2462c475033da8carll      DIP("vpksdss v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
1757448ae46b56cef87c90638b25d6b2462c475033da8carll      putVReg( vD_addr,
1757548ae46b56cef87c90638b25d6b2462c475033da8carll               binop(Iop_QNarrowBin64Sto32Sx4, mkexpr(vA), mkexpr(vB)) );
1757648ae46b56cef87c90638b25d6b2462c475033da8carll      // TODO: set VSCR[SAT]
1757748ae46b56cef87c90638b25d6b2462c475033da8carll      return True;
1757832aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion   default:
1757932aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion      break; // Fall through...
1758032aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion   }
1758132aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion
1758232aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion
1758332aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion   if (vA_addr != 0) {
175845b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion      vex_printf("dis_av_pack(ppc)(vA_addr)\n");
1758532aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion      return False;
1758632aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion   }
1758732aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion
17588197bd17d3ba8ac5204cd5c9ba5fab571249eb791sewardj   signs = newTemp(Ity_V128);
17589197bd17d3ba8ac5204cd5c9ba5fab571249eb791sewardj   zeros = newTemp(Ity_V128);
175903c052793dacedf702ca4b6ccbfb46a7efa7bc714cerion   assign( zeros, unop(Iop_Dup32x4, mkU32(0)) );
175913c052793dacedf702ca4b6ccbfb46a7efa7bc714cerion
1759232aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion   switch (opc2) {
1759332aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion   /* Unpacking */
175943c052793dacedf702ca4b6ccbfb46a7efa7bc714cerion   case 0x20E: { // vupkhsb (Unpack High Signed B, AV p277)
1759532aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion      DIP("vupkhsb v%d,v%d\n", vD_addr, vB_addr);
175963c052793dacedf702ca4b6ccbfb46a7efa7bc714cerion      assign( signs, binop(Iop_CmpGT8Sx16, mkexpr(zeros), mkexpr(vB)) );
175975b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion      putVReg( vD_addr,
175985b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion               binop(Iop_InterleaveHI8x16, mkexpr(signs), mkexpr(vB)) );
175993c052793dacedf702ca4b6ccbfb46a7efa7bc714cerion      break;
176003c052793dacedf702ca4b6ccbfb46a7efa7bc714cerion   }
176013c052793dacedf702ca4b6ccbfb46a7efa7bc714cerion   case 0x24E: { // vupkhsh (Unpack High Signed HW, AV p278)
1760232aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion      DIP("vupkhsh v%d,v%d\n", vD_addr, vB_addr);
176033c052793dacedf702ca4b6ccbfb46a7efa7bc714cerion      assign( signs, binop(Iop_CmpGT16Sx8, mkexpr(zeros), mkexpr(vB)) );
176045b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion      putVReg( vD_addr,
176055b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion               binop(Iop_InterleaveHI16x8, mkexpr(signs), mkexpr(vB)) );
176063c052793dacedf702ca4b6ccbfb46a7efa7bc714cerion      break;
176073c052793dacedf702ca4b6ccbfb46a7efa7bc714cerion   }
176083c052793dacedf702ca4b6ccbfb46a7efa7bc714cerion   case 0x28E: { // vupklsb (Unpack Low Signed B, AV p280)
1760932aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion      DIP("vupklsb v%d,v%d\n", vD_addr, vB_addr);
176103c052793dacedf702ca4b6ccbfb46a7efa7bc714cerion      assign( signs, binop(Iop_CmpGT8Sx16, mkexpr(zeros), mkexpr(vB)) );
176115b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion      putVReg( vD_addr,
176125b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion               binop(Iop_InterleaveLO8x16, mkexpr(signs), mkexpr(vB)) );
176133c052793dacedf702ca4b6ccbfb46a7efa7bc714cerion      break;
176143c052793dacedf702ca4b6ccbfb46a7efa7bc714cerion   }
176153c052793dacedf702ca4b6ccbfb46a7efa7bc714cerion   case 0x2CE: { // vupklsh (Unpack Low Signed HW, AV p281)
1761632aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion      DIP("vupklsh v%d,v%d\n", vD_addr, vB_addr);
176173c052793dacedf702ca4b6ccbfb46a7efa7bc714cerion      assign( signs, binop(Iop_CmpGT16Sx8, mkexpr(zeros), mkexpr(vB)) );
176185b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion      putVReg( vD_addr,
176195b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion               binop(Iop_InterleaveLO16x8, mkexpr(signs), mkexpr(vB)) );
176203c052793dacedf702ca4b6ccbfb46a7efa7bc714cerion      break;
176213c052793dacedf702ca4b6ccbfb46a7efa7bc714cerion   }
176223c052793dacedf702ca4b6ccbfb46a7efa7bc714cerion   case 0x34E: { // vupkhpx (Unpack High Pixel16, AV p276)
176233c052793dacedf702ca4b6ccbfb46a7efa7bc714cerion      /* CAB: Worth a new primop? */
176243c052793dacedf702ca4b6ccbfb46a7efa7bc714cerion      /* Using shifts to isolate pixel elements, then expanding them */
176253c052793dacedf702ca4b6ccbfb46a7efa7bc714cerion      IRTemp z0  = newTemp(Ity_V128);
176263c052793dacedf702ca4b6ccbfb46a7efa7bc714cerion      IRTemp z1  = newTemp(Ity_V128);
176273c052793dacedf702ca4b6ccbfb46a7efa7bc714cerion      IRTemp z01 = newTemp(Ity_V128);
176283c052793dacedf702ca4b6ccbfb46a7efa7bc714cerion      IRTemp z2  = newTemp(Ity_V128);
176293c052793dacedf702ca4b6ccbfb46a7efa7bc714cerion      IRTemp z3  = newTemp(Ity_V128);
176303c052793dacedf702ca4b6ccbfb46a7efa7bc714cerion      IRTemp z23 = newTemp(Ity_V128);
17631197bd17d3ba8ac5204cd5c9ba5fab571249eb791sewardj      DIP("vupkhpx v%d,v%d\n", vD_addr, vB_addr);
176323c052793dacedf702ca4b6ccbfb46a7efa7bc714cerion      assign( z0,  binop(Iop_ShlN16x8,
176333c052793dacedf702ca4b6ccbfb46a7efa7bc714cerion                         binop(Iop_SarN16x8, mkexpr(vB), mkU8(15)),
176343c052793dacedf702ca4b6ccbfb46a7efa7bc714cerion                         mkU8(8)) );
176353c052793dacedf702ca4b6ccbfb46a7efa7bc714cerion      assign( z1,  binop(Iop_ShrN16x8,
176363c052793dacedf702ca4b6ccbfb46a7efa7bc714cerion                         binop(Iop_ShlN16x8, mkexpr(vB), mkU8(1)),
176373c052793dacedf702ca4b6ccbfb46a7efa7bc714cerion                         mkU8(11)) );
176383c052793dacedf702ca4b6ccbfb46a7efa7bc714cerion      assign( z01, binop(Iop_InterleaveHI16x8, mkexpr(zeros),
176393c052793dacedf702ca4b6ccbfb46a7efa7bc714cerion                         binop(Iop_OrV128, mkexpr(z0), mkexpr(z1))) );
176403c052793dacedf702ca4b6ccbfb46a7efa7bc714cerion      assign( z2,  binop(Iop_ShrN16x8,
176413c052793dacedf702ca4b6ccbfb46a7efa7bc714cerion                         binop(Iop_ShlN16x8,
176423c052793dacedf702ca4b6ccbfb46a7efa7bc714cerion                               binop(Iop_ShrN16x8, mkexpr(vB), mkU8(5)),
176433c052793dacedf702ca4b6ccbfb46a7efa7bc714cerion                               mkU8(11)),
176443c052793dacedf702ca4b6ccbfb46a7efa7bc714cerion                         mkU8(3)) );
176453c052793dacedf702ca4b6ccbfb46a7efa7bc714cerion      assign( z3,  binop(Iop_ShrN16x8,
176463c052793dacedf702ca4b6ccbfb46a7efa7bc714cerion                         binop(Iop_ShlN16x8, mkexpr(vB), mkU8(11)),
176473c052793dacedf702ca4b6ccbfb46a7efa7bc714cerion                         mkU8(11)) );
176483c052793dacedf702ca4b6ccbfb46a7efa7bc714cerion      assign( z23, binop(Iop_InterleaveHI16x8, mkexpr(zeros),
176493c052793dacedf702ca4b6ccbfb46a7efa7bc714cerion                         binop(Iop_OrV128, mkexpr(z2), mkexpr(z3))) );
176505b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion      putVReg( vD_addr,
176515b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion               binop(Iop_OrV128,
176525b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion                     binop(Iop_ShlN32x4, mkexpr(z01), mkU8(16)),
176535b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion                     mkexpr(z23)) );
176543c052793dacedf702ca4b6ccbfb46a7efa7bc714cerion      break;
176553c052793dacedf702ca4b6ccbfb46a7efa7bc714cerion   }
176563c052793dacedf702ca4b6ccbfb46a7efa7bc714cerion   case 0x3CE: { // vupklpx (Unpack Low Pixel16, AV p279)
176573c052793dacedf702ca4b6ccbfb46a7efa7bc714cerion      /* identical to vupkhpx, except interleaving LO */
176583c052793dacedf702ca4b6ccbfb46a7efa7bc714cerion      IRTemp z0  = newTemp(Ity_V128);
176593c052793dacedf702ca4b6ccbfb46a7efa7bc714cerion      IRTemp z1  = newTemp(Ity_V128);
176603c052793dacedf702ca4b6ccbfb46a7efa7bc714cerion      IRTemp z01 = newTemp(Ity_V128);
176613c052793dacedf702ca4b6ccbfb46a7efa7bc714cerion      IRTemp z2  = newTemp(Ity_V128);
176623c052793dacedf702ca4b6ccbfb46a7efa7bc714cerion      IRTemp z3  = newTemp(Ity_V128);
176633c052793dacedf702ca4b6ccbfb46a7efa7bc714cerion      IRTemp z23 = newTemp(Ity_V128);
17664197bd17d3ba8ac5204cd5c9ba5fab571249eb791sewardj      DIP("vupklpx v%d,v%d\n", vD_addr, vB_addr);
176653c052793dacedf702ca4b6ccbfb46a7efa7bc714cerion      assign( z0,  binop(Iop_ShlN16x8,
176663c052793dacedf702ca4b6ccbfb46a7efa7bc714cerion                         binop(Iop_SarN16x8, mkexpr(vB), mkU8(15)),
176673c052793dacedf702ca4b6ccbfb46a7efa7bc714cerion                         mkU8(8)) );
176683c052793dacedf702ca4b6ccbfb46a7efa7bc714cerion      assign( z1,  binop(Iop_ShrN16x8,
176693c052793dacedf702ca4b6ccbfb46a7efa7bc714cerion                         binop(Iop_ShlN16x8, mkexpr(vB), mkU8(1)),
176703c052793dacedf702ca4b6ccbfb46a7efa7bc714cerion                         mkU8(11)) );
176713c052793dacedf702ca4b6ccbfb46a7efa7bc714cerion      assign( z01, binop(Iop_InterleaveLO16x8, mkexpr(zeros),
176723c052793dacedf702ca4b6ccbfb46a7efa7bc714cerion                         binop(Iop_OrV128, mkexpr(z0), mkexpr(z1))) );
176733c052793dacedf702ca4b6ccbfb46a7efa7bc714cerion      assign( z2,  binop(Iop_ShrN16x8,
176743c052793dacedf702ca4b6ccbfb46a7efa7bc714cerion                         binop(Iop_ShlN16x8,
176753c052793dacedf702ca4b6ccbfb46a7efa7bc714cerion                               binop(Iop_ShrN16x8, mkexpr(vB), mkU8(5)),
176763c052793dacedf702ca4b6ccbfb46a7efa7bc714cerion                               mkU8(11)),
176773c052793dacedf702ca4b6ccbfb46a7efa7bc714cerion                         mkU8(3)) );
176783c052793dacedf702ca4b6ccbfb46a7efa7bc714cerion      assign( z3,  binop(Iop_ShrN16x8,
176793c052793dacedf702ca4b6ccbfb46a7efa7bc714cerion                         binop(Iop_ShlN16x8, mkexpr(vB), mkU8(11)),
176803c052793dacedf702ca4b6ccbfb46a7efa7bc714cerion                         mkU8(11)) );
176813c052793dacedf702ca4b6ccbfb46a7efa7bc714cerion      assign( z23, binop(Iop_InterleaveLO16x8, mkexpr(zeros),
176823c052793dacedf702ca4b6ccbfb46a7efa7bc714cerion                         binop(Iop_OrV128, mkexpr(z2), mkexpr(z3))) );
176835b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion      putVReg( vD_addr,
176845b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion               binop(Iop_OrV128,
176855b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion                     binop(Iop_ShlN32x4, mkexpr(z01), mkU8(16)),
176865b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion                     mkexpr(z23)) );
176873c052793dacedf702ca4b6ccbfb46a7efa7bc714cerion      break;
176883c052793dacedf702ca4b6ccbfb46a7efa7bc714cerion   }
1768948ae46b56cef87c90638b25d6b2462c475033da8carll   case 0x64E: { // vupkhsw (Unpack High Signed Word)
1769048ae46b56cef87c90638b25d6b2462c475033da8carll      DIP("vupkhsw v%d,v%d\n", vD_addr, vB_addr);
1769148ae46b56cef87c90638b25d6b2462c475033da8carll      assign( signs, binop(Iop_CmpGT32Sx4, mkexpr(zeros), mkexpr(vB)) );
1769248ae46b56cef87c90638b25d6b2462c475033da8carll      putVReg( vD_addr,
1769348ae46b56cef87c90638b25d6b2462c475033da8carll               binop(Iop_InterleaveHI32x4, mkexpr(signs), mkexpr(vB)) );
1769448ae46b56cef87c90638b25d6b2462c475033da8carll      break;
1769548ae46b56cef87c90638b25d6b2462c475033da8carll   }
1769648ae46b56cef87c90638b25d6b2462c475033da8carll   case 0x6CE: { // vupklsw (Unpack Low Signed Word)
1769748ae46b56cef87c90638b25d6b2462c475033da8carll      DIP("vupklsw v%d,v%d\n", vD_addr, vB_addr);
1769848ae46b56cef87c90638b25d6b2462c475033da8carll      assign( signs, binop(Iop_CmpGT32Sx4, mkexpr(zeros), mkexpr(vB)) );
1769948ae46b56cef87c90638b25d6b2462c475033da8carll      putVReg( vD_addr,
1770048ae46b56cef87c90638b25d6b2462c475033da8carll               binop(Iop_InterleaveLO32x4, mkexpr(signs), mkexpr(vB)) );
1770148ae46b56cef87c90638b25d6b2462c475033da8carll      break;
1770248ae46b56cef87c90638b25d6b2462c475033da8carll   }
1770332aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion   default:
177045b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion      vex_printf("dis_av_pack(ppc)(opc2)\n");
1770532aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion      return False;
1770632aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion   }
1770732aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion   return True;
1770832aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion}
1770932aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion
177107deaf9552b546b847528cf39b38898fb7742b5f5carll/*
177117deaf9552b546b847528cf39b38898fb7742b5f5carll  AltiVec Cipher Instructions
177127deaf9552b546b847528cf39b38898fb7742b5f5carll*/
177137deaf9552b546b847528cf39b38898fb7742b5f5carllstatic Bool dis_av_cipher ( UInt theInstr )
177147deaf9552b546b847528cf39b38898fb7742b5f5carll{
177157deaf9552b546b847528cf39b38898fb7742b5f5carll   /* VX-Form */
177167deaf9552b546b847528cf39b38898fb7742b5f5carll   UChar opc1     = ifieldOPC(theInstr);
177177deaf9552b546b847528cf39b38898fb7742b5f5carll   UChar vD_addr  = ifieldRegDS(theInstr);
177187deaf9552b546b847528cf39b38898fb7742b5f5carll   UChar vA_addr  = ifieldRegA(theInstr);
177197deaf9552b546b847528cf39b38898fb7742b5f5carll   UChar vB_addr  = ifieldRegB(theInstr);
177207deaf9552b546b847528cf39b38898fb7742b5f5carll   UInt  opc2     = IFIELD( theInstr, 0, 11 );
177217deaf9552b546b847528cf39b38898fb7742b5f5carll
177227deaf9552b546b847528cf39b38898fb7742b5f5carll   IRTemp vA    = newTemp(Ity_V128);
177237deaf9552b546b847528cf39b38898fb7742b5f5carll   IRTemp vB    = newTemp(Ity_V128);
177247deaf9552b546b847528cf39b38898fb7742b5f5carll   assign( vA, getVReg(vA_addr));
177257deaf9552b546b847528cf39b38898fb7742b5f5carll   assign( vB, getVReg(vB_addr));
177267deaf9552b546b847528cf39b38898fb7742b5f5carll
177277deaf9552b546b847528cf39b38898fb7742b5f5carll   if (opc1 != 0x4) {
177287deaf9552b546b847528cf39b38898fb7742b5f5carll      vex_printf("dis_av_cipher(ppc)(instr)\n");
177297deaf9552b546b847528cf39b38898fb7742b5f5carll      return False;
177307deaf9552b546b847528cf39b38898fb7742b5f5carll   }
177317deaf9552b546b847528cf39b38898fb7742b5f5carll   switch (opc2) {
177327deaf9552b546b847528cf39b38898fb7742b5f5carll      case 0x508: // vcipher (Vector Inverser Cipher)
177337deaf9552b546b847528cf39b38898fb7742b5f5carll         DIP("vcipher v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
177347deaf9552b546b847528cf39b38898fb7742b5f5carll         putVReg( vD_addr,
177357deaf9552b546b847528cf39b38898fb7742b5f5carll                  binop(Iop_CipherV128, mkexpr(vA), mkexpr(vB)) );
177367deaf9552b546b847528cf39b38898fb7742b5f5carll         return True;
177377deaf9552b546b847528cf39b38898fb7742b5f5carll
177387deaf9552b546b847528cf39b38898fb7742b5f5carll      case 0x509: // vcipherlast (Vector Inverser Cipher Last)
177397deaf9552b546b847528cf39b38898fb7742b5f5carll         DIP("vcipherlast v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
177407deaf9552b546b847528cf39b38898fb7742b5f5carll         putVReg( vD_addr,
177417deaf9552b546b847528cf39b38898fb7742b5f5carll                  binop(Iop_CipherLV128, mkexpr(vA), mkexpr(vB)) );
177427deaf9552b546b847528cf39b38898fb7742b5f5carll         return True;
177437deaf9552b546b847528cf39b38898fb7742b5f5carll
177447deaf9552b546b847528cf39b38898fb7742b5f5carll      case 0x548: // vncipher (Vector Inverser Cipher)
177457deaf9552b546b847528cf39b38898fb7742b5f5carll         DIP("vncipher v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
177467deaf9552b546b847528cf39b38898fb7742b5f5carll         putVReg( vD_addr,
177477deaf9552b546b847528cf39b38898fb7742b5f5carll                  binop(Iop_NCipherV128, mkexpr(vA), mkexpr(vB)) );
177487deaf9552b546b847528cf39b38898fb7742b5f5carll         return True;
177497deaf9552b546b847528cf39b38898fb7742b5f5carll
177507deaf9552b546b847528cf39b38898fb7742b5f5carll      case 0x549: // vncipherlast (Vector Inverser Cipher Last)
177517deaf9552b546b847528cf39b38898fb7742b5f5carll         DIP("vncipherlast v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
177527deaf9552b546b847528cf39b38898fb7742b5f5carll         putVReg( vD_addr,
177537deaf9552b546b847528cf39b38898fb7742b5f5carll                  binop(Iop_NCipherLV128, mkexpr(vA), mkexpr(vB)) );
177547deaf9552b546b847528cf39b38898fb7742b5f5carll         return True;
177557deaf9552b546b847528cf39b38898fb7742b5f5carll
177567deaf9552b546b847528cf39b38898fb7742b5f5carll      case 0x5C8: /* vsbox (Vector SubBytes, this does the cipher
177577deaf9552b546b847528cf39b38898fb7742b5f5carll       * subBytes transform)
177587deaf9552b546b847528cf39b38898fb7742b5f5carll       */
177597deaf9552b546b847528cf39b38898fb7742b5f5carll         DIP("vsbox v%d,v%d\n", vD_addr, vA_addr);
177607deaf9552b546b847528cf39b38898fb7742b5f5carll         putVReg( vD_addr,
177617deaf9552b546b847528cf39b38898fb7742b5f5carll                  unop(Iop_CipherSV128, mkexpr(vA) ) );
177627deaf9552b546b847528cf39b38898fb7742b5f5carll         return True;
177637deaf9552b546b847528cf39b38898fb7742b5f5carll
177647deaf9552b546b847528cf39b38898fb7742b5f5carll      default:
177657deaf9552b546b847528cf39b38898fb7742b5f5carll         vex_printf("dis_av_cipher(ppc)(opc2)\n");
177667deaf9552b546b847528cf39b38898fb7742b5f5carll         return False;
177677deaf9552b546b847528cf39b38898fb7742b5f5carll   }
177687deaf9552b546b847528cf39b38898fb7742b5f5carll   return True;
177697deaf9552b546b847528cf39b38898fb7742b5f5carll}
177707deaf9552b546b847528cf39b38898fb7742b5f5carll
177717deaf9552b546b847528cf39b38898fb7742b5f5carll/*
177727deaf9552b546b847528cf39b38898fb7742b5f5carll  AltiVec Secure Hash Instructions
177737deaf9552b546b847528cf39b38898fb7742b5f5carll*/
177747deaf9552b546b847528cf39b38898fb7742b5f5carllstatic Bool dis_av_hash ( UInt theInstr )
177757deaf9552b546b847528cf39b38898fb7742b5f5carll{
177767deaf9552b546b847528cf39b38898fb7742b5f5carll   /* VX-Form */
177777deaf9552b546b847528cf39b38898fb7742b5f5carll   UChar opc1     = ifieldOPC(theInstr);
177787deaf9552b546b847528cf39b38898fb7742b5f5carll   UChar vRT_addr = ifieldRegDS(theInstr);
177797deaf9552b546b847528cf39b38898fb7742b5f5carll   UChar vRA_addr  = ifieldRegA(theInstr);
177807deaf9552b546b847528cf39b38898fb7742b5f5carll   UChar s_field  = IFIELD( theInstr, 11, 5 );  // st and six field
177817deaf9552b546b847528cf39b38898fb7742b5f5carll   UChar st       = IFIELD( theInstr, 15, 1 );  // st
177827deaf9552b546b847528cf39b38898fb7742b5f5carll   UChar six      = IFIELD( theInstr, 11, 4 );  // six field
177837deaf9552b546b847528cf39b38898fb7742b5f5carll   UInt  opc2     = IFIELD( theInstr, 0, 11 );
177847deaf9552b546b847528cf39b38898fb7742b5f5carll
177857deaf9552b546b847528cf39b38898fb7742b5f5carll   IRTemp vA    = newTemp(Ity_V128);
177867deaf9552b546b847528cf39b38898fb7742b5f5carll   IRTemp dst    = newTemp(Ity_V128);
177877deaf9552b546b847528cf39b38898fb7742b5f5carll   assign( vA, getVReg(vRA_addr));
177887deaf9552b546b847528cf39b38898fb7742b5f5carll
177897deaf9552b546b847528cf39b38898fb7742b5f5carll   if (opc1 != 0x4) {
177907deaf9552b546b847528cf39b38898fb7742b5f5carll      vex_printf("dis_av_hash(ppc)(instr)\n");
177917deaf9552b546b847528cf39b38898fb7742b5f5carll      return False;
177927deaf9552b546b847528cf39b38898fb7742b5f5carll   }
177937deaf9552b546b847528cf39b38898fb7742b5f5carll
177947deaf9552b546b847528cf39b38898fb7742b5f5carll   switch (opc2) {
177957deaf9552b546b847528cf39b38898fb7742b5f5carll      case 0x682:  // vshasigmaw
177967deaf9552b546b847528cf39b38898fb7742b5f5carll         DIP("vshasigmaw v%d,v%d,%u,%u\n", vRT_addr, vRA_addr, st, six);
177977deaf9552b546b847528cf39b38898fb7742b5f5carll         assign( dst, binop( Iop_SHA256, mkexpr( vA ), mkU8( s_field) ) );
177987deaf9552b546b847528cf39b38898fb7742b5f5carll         putVReg( vRT_addr, mkexpr(dst));
177997deaf9552b546b847528cf39b38898fb7742b5f5carll         return True;
178007deaf9552b546b847528cf39b38898fb7742b5f5carll
178017deaf9552b546b847528cf39b38898fb7742b5f5carll      case 0x6C2:  // vshasigmad,
178027deaf9552b546b847528cf39b38898fb7742b5f5carll         DIP("vshasigmad v%d,v%d,%u,%u\n", vRT_addr, vRA_addr, st, six);
178037deaf9552b546b847528cf39b38898fb7742b5f5carll         putVReg( vRT_addr, binop( Iop_SHA512, mkexpr( vA ), mkU8( s_field) ) );
178047deaf9552b546b847528cf39b38898fb7742b5f5carll         return True;
178057deaf9552b546b847528cf39b38898fb7742b5f5carll
178067deaf9552b546b847528cf39b38898fb7742b5f5carll      default:
178077deaf9552b546b847528cf39b38898fb7742b5f5carll         vex_printf("dis_av_hash(ppc)(opc2)\n");
178087deaf9552b546b847528cf39b38898fb7742b5f5carll         return False;
178097deaf9552b546b847528cf39b38898fb7742b5f5carll   }
178107deaf9552b546b847528cf39b38898fb7742b5f5carll   return True;
178117deaf9552b546b847528cf39b38898fb7742b5f5carll}
178127deaf9552b546b847528cf39b38898fb7742b5f5carll
178137deaf9552b546b847528cf39b38898fb7742b5f5carll/*
1781460c6bac19ffe055cabab554e7877d73096a8bf17carll * This function is used by the Vector add/subtract [extended] modulo/carry
1781560c6bac19ffe055cabab554e7877d73096a8bf17carll * instructions.
1781660c6bac19ffe055cabab554e7877d73096a8bf17carll *   - For the non-extended add instructions, the cin arg is set to zero.
1781760c6bac19ffe055cabab554e7877d73096a8bf17carll *   - For the extended add instructions, cin is the integer value of
1781860c6bac19ffe055cabab554e7877d73096a8bf17carll *     src3.bit[127].
1781960c6bac19ffe055cabab554e7877d73096a8bf17carll *   - For the non-extended subtract instructions, src1 is added to the one's
1782060c6bac19ffe055cabab554e7877d73096a8bf17carll *     complement of src2 + 1.  We re-use the cin argument to hold the '1'
1782160c6bac19ffe055cabab554e7877d73096a8bf17carll *     value for this operation.
1782260c6bac19ffe055cabab554e7877d73096a8bf17carll *   - For the extended subtract instructions, cin is the integer value of src3.bit[127].
1782360c6bac19ffe055cabab554e7877d73096a8bf17carll */
1782460c6bac19ffe055cabab554e7877d73096a8bf17carllstatic IRTemp _get_quad_modulo_or_carry(IRExpr * vecA, IRExpr * vecB,
1782560c6bac19ffe055cabab554e7877d73096a8bf17carll                                        IRExpr * cin, Bool modulo)
1782660c6bac19ffe055cabab554e7877d73096a8bf17carll{
1782760c6bac19ffe055cabab554e7877d73096a8bf17carll   IRTemp _vecA_32   = IRTemp_INVALID;
1782860c6bac19ffe055cabab554e7877d73096a8bf17carll   IRTemp _vecB_32   = IRTemp_INVALID;
1782960c6bac19ffe055cabab554e7877d73096a8bf17carll   IRTemp res_32     = IRTemp_INVALID;
1783060c6bac19ffe055cabab554e7877d73096a8bf17carll   IRTemp result     = IRTemp_INVALID;
1783160c6bac19ffe055cabab554e7877d73096a8bf17carll   IRTemp tmp_result = IRTemp_INVALID;
1783260c6bac19ffe055cabab554e7877d73096a8bf17carll   IRTemp carry      = IRTemp_INVALID;
1783360c6bac19ffe055cabab554e7877d73096a8bf17carll   Int i;
1783460c6bac19ffe055cabab554e7877d73096a8bf17carll   IRExpr * _vecA_low64 =  unop( Iop_V128to64, vecA );
1783560c6bac19ffe055cabab554e7877d73096a8bf17carll   IRExpr * _vecB_low64 =  unop( Iop_V128to64, vecB );
1783660c6bac19ffe055cabab554e7877d73096a8bf17carll   IRExpr * _vecA_high64 = unop( Iop_V128HIto64, vecA );
1783760c6bac19ffe055cabab554e7877d73096a8bf17carll   IRExpr * _vecB_high64 = unop( Iop_V128HIto64, vecB );
1783860c6bac19ffe055cabab554e7877d73096a8bf17carll
1783960c6bac19ffe055cabab554e7877d73096a8bf17carll   for (i = 0; i < 4; i++) {
1784060c6bac19ffe055cabab554e7877d73096a8bf17carll      _vecA_32 = newTemp(Ity_I32);
1784160c6bac19ffe055cabab554e7877d73096a8bf17carll      _vecB_32 = newTemp(Ity_I32);
1784260c6bac19ffe055cabab554e7877d73096a8bf17carll      res_32   = newTemp(Ity_I32);
1784360c6bac19ffe055cabab554e7877d73096a8bf17carll      switch (i) {
1784460c6bac19ffe055cabab554e7877d73096a8bf17carll      case 0:
1784560c6bac19ffe055cabab554e7877d73096a8bf17carll         assign(_vecA_32, unop( Iop_64to32, _vecA_low64 ) );
1784660c6bac19ffe055cabab554e7877d73096a8bf17carll         assign(_vecB_32, unop( Iop_64to32, _vecB_low64 ) );
1784760c6bac19ffe055cabab554e7877d73096a8bf17carll         break;
1784860c6bac19ffe055cabab554e7877d73096a8bf17carll      case 1:
1784960c6bac19ffe055cabab554e7877d73096a8bf17carll         assign(_vecA_32, unop( Iop_64HIto32, _vecA_low64 ) );
1785060c6bac19ffe055cabab554e7877d73096a8bf17carll         assign(_vecB_32, unop( Iop_64HIto32, _vecB_low64 ) );
1785160c6bac19ffe055cabab554e7877d73096a8bf17carll         break;
1785260c6bac19ffe055cabab554e7877d73096a8bf17carll      case 2:
1785360c6bac19ffe055cabab554e7877d73096a8bf17carll         assign(_vecA_32, unop( Iop_64to32, _vecA_high64 ) );
1785460c6bac19ffe055cabab554e7877d73096a8bf17carll         assign(_vecB_32, unop( Iop_64to32, _vecB_high64 ) );
1785560c6bac19ffe055cabab554e7877d73096a8bf17carll         break;
1785660c6bac19ffe055cabab554e7877d73096a8bf17carll      case 3:
1785760c6bac19ffe055cabab554e7877d73096a8bf17carll         assign(_vecA_32, unop( Iop_64HIto32, _vecA_high64 ) );
1785860c6bac19ffe055cabab554e7877d73096a8bf17carll         assign(_vecB_32, unop( Iop_64HIto32, _vecB_high64 ) );
1785960c6bac19ffe055cabab554e7877d73096a8bf17carll         break;
1786060c6bac19ffe055cabab554e7877d73096a8bf17carll      }
1786160c6bac19ffe055cabab554e7877d73096a8bf17carll
1786260c6bac19ffe055cabab554e7877d73096a8bf17carll      assign(res_32, binop( Iop_Add32,
1786360c6bac19ffe055cabab554e7877d73096a8bf17carll                            binop( Iop_Add32,
1786460c6bac19ffe055cabab554e7877d73096a8bf17carll                                   binop ( Iop_Add32,
1786560c6bac19ffe055cabab554e7877d73096a8bf17carll                                           mkexpr(_vecA_32),
1786660c6bac19ffe055cabab554e7877d73096a8bf17carll                                           mkexpr(_vecB_32) ),
1786760c6bac19ffe055cabab554e7877d73096a8bf17carll                                   (i == 0) ? mkU32(0) : mkexpr(carry) ),
1786860c6bac19ffe055cabab554e7877d73096a8bf17carll                            (i == 0) ? cin : mkU32(0) ) );
1786960c6bac19ffe055cabab554e7877d73096a8bf17carll      if (modulo) {
1787060c6bac19ffe055cabab554e7877d73096a8bf17carll         result = newTemp(Ity_V128);
1787160c6bac19ffe055cabab554e7877d73096a8bf17carll         assign(result, binop( Iop_OrV128,
1787260c6bac19ffe055cabab554e7877d73096a8bf17carll                              (i == 0) ? binop( Iop_64HLtoV128,
1787360c6bac19ffe055cabab554e7877d73096a8bf17carll                                                mkU64(0),
1787460c6bac19ffe055cabab554e7877d73096a8bf17carll                                                mkU64(0) ) : mkexpr(tmp_result),
1787560c6bac19ffe055cabab554e7877d73096a8bf17carll                              binop( Iop_ShlV128,
1787660c6bac19ffe055cabab554e7877d73096a8bf17carll                                     binop( Iop_64HLtoV128,
1787760c6bac19ffe055cabab554e7877d73096a8bf17carll                                            mkU64(0),
1787860c6bac19ffe055cabab554e7877d73096a8bf17carll                                            binop( Iop_32HLto64,
1787960c6bac19ffe055cabab554e7877d73096a8bf17carll                                                   mkU32(0),
1788060c6bac19ffe055cabab554e7877d73096a8bf17carll                                                   mkexpr(res_32) ) ),
1788160c6bac19ffe055cabab554e7877d73096a8bf17carll                                     mkU8(i * 32) ) ) );
1788260c6bac19ffe055cabab554e7877d73096a8bf17carll         tmp_result = newTemp(Ity_V128);
1788360c6bac19ffe055cabab554e7877d73096a8bf17carll         assign(tmp_result, mkexpr(result));
1788460c6bac19ffe055cabab554e7877d73096a8bf17carll      }
1788560c6bac19ffe055cabab554e7877d73096a8bf17carll      carry = newTemp(Ity_I32);
1788660c6bac19ffe055cabab554e7877d73096a8bf17carll      assign(carry, unop(Iop_1Uto32, binop( Iop_CmpLT32U,
1788760c6bac19ffe055cabab554e7877d73096a8bf17carll                                            mkexpr(res_32),
1788860c6bac19ffe055cabab554e7877d73096a8bf17carll                                            mkexpr(_vecA_32 ) ) ) );
1788960c6bac19ffe055cabab554e7877d73096a8bf17carll   }
1789060c6bac19ffe055cabab554e7877d73096a8bf17carll   if (modulo)
1789160c6bac19ffe055cabab554e7877d73096a8bf17carll      return result;
1789260c6bac19ffe055cabab554e7877d73096a8bf17carll   else
1789360c6bac19ffe055cabab554e7877d73096a8bf17carll      return carry;
1789460c6bac19ffe055cabab554e7877d73096a8bf17carll}
1789560c6bac19ffe055cabab554e7877d73096a8bf17carll
1789660c6bac19ffe055cabab554e7877d73096a8bf17carll
1789760c6bac19ffe055cabab554e7877d73096a8bf17carllstatic Bool dis_av_quad ( UInt theInstr )
1789860c6bac19ffe055cabab554e7877d73096a8bf17carll{
1789960c6bac19ffe055cabab554e7877d73096a8bf17carll   /* VX-Form */
1790060c6bac19ffe055cabab554e7877d73096a8bf17carll   UChar opc1     = ifieldOPC(theInstr);
1790160c6bac19ffe055cabab554e7877d73096a8bf17carll   UChar vRT_addr = ifieldRegDS(theInstr);
1790260c6bac19ffe055cabab554e7877d73096a8bf17carll   UChar vRA_addr = ifieldRegA(theInstr);
1790360c6bac19ffe055cabab554e7877d73096a8bf17carll   UChar vRB_addr = ifieldRegB(theInstr);
1790460c6bac19ffe055cabab554e7877d73096a8bf17carll   UChar vRC_addr;
1790560c6bac19ffe055cabab554e7877d73096a8bf17carll   UInt  opc2     = IFIELD( theInstr, 0, 11 );
1790660c6bac19ffe055cabab554e7877d73096a8bf17carll
1790760c6bac19ffe055cabab554e7877d73096a8bf17carll   IRTemp vA    = newTemp(Ity_V128);
1790860c6bac19ffe055cabab554e7877d73096a8bf17carll   IRTemp vB    = newTemp(Ity_V128);
1790960c6bac19ffe055cabab554e7877d73096a8bf17carll   IRTemp vC    = IRTemp_INVALID;
1791060c6bac19ffe055cabab554e7877d73096a8bf17carll   IRTemp cin    = IRTemp_INVALID;
1791160c6bac19ffe055cabab554e7877d73096a8bf17carll   assign( vA, getVReg(vRA_addr));
1791260c6bac19ffe055cabab554e7877d73096a8bf17carll   assign( vB, getVReg(vRB_addr));
1791360c6bac19ffe055cabab554e7877d73096a8bf17carll
1791460c6bac19ffe055cabab554e7877d73096a8bf17carll   if (opc1 != 0x4) {
1791560c6bac19ffe055cabab554e7877d73096a8bf17carll      vex_printf("dis_av_quad(ppc)(instr)\n");
1791660c6bac19ffe055cabab554e7877d73096a8bf17carll      return False;
1791760c6bac19ffe055cabab554e7877d73096a8bf17carll   }
1791860c6bac19ffe055cabab554e7877d73096a8bf17carll
1791960c6bac19ffe055cabab554e7877d73096a8bf17carll   switch (opc2) {
1792060c6bac19ffe055cabab554e7877d73096a8bf17carll   case 0x140:  // vaddcuq
1792160c6bac19ffe055cabab554e7877d73096a8bf17carll     DIP("vaddcuq v%d,v%d,v%d\n", vRT_addr, vRA_addr, vRB_addr);
1792260c6bac19ffe055cabab554e7877d73096a8bf17carll     putVReg( vRT_addr, unop( Iop_32UtoV128,
1792360c6bac19ffe055cabab554e7877d73096a8bf17carll                              mkexpr(_get_quad_modulo_or_carry(mkexpr(vA),
1792460c6bac19ffe055cabab554e7877d73096a8bf17carll                                                               mkexpr(vB),
1792560c6bac19ffe055cabab554e7877d73096a8bf17carll                                                               mkU32(0), False) ) ) );
1792660c6bac19ffe055cabab554e7877d73096a8bf17carll     return True;
1792760c6bac19ffe055cabab554e7877d73096a8bf17carll   case 0x100: // vadduqm
1792860c6bac19ffe055cabab554e7877d73096a8bf17carll      DIP("vadduqm v%d,v%d,v%d\n", vRT_addr, vRA_addr, vRB_addr);
1792960c6bac19ffe055cabab554e7877d73096a8bf17carll      putVReg( vRT_addr, mkexpr(_get_quad_modulo_or_carry(mkexpr(vA),
1793060c6bac19ffe055cabab554e7877d73096a8bf17carll                                                          mkexpr(vB), mkU32(0), True) ) );
1793160c6bac19ffe055cabab554e7877d73096a8bf17carll      return True;
1793260c6bac19ffe055cabab554e7877d73096a8bf17carll   case 0x540: // vsubcuq
1793360c6bac19ffe055cabab554e7877d73096a8bf17carll      DIP("vsubcuq v%d,v%d,v%d\n", vRT_addr, vRA_addr, vRB_addr);
1793460c6bac19ffe055cabab554e7877d73096a8bf17carll      putVReg( vRT_addr,
1793560c6bac19ffe055cabab554e7877d73096a8bf17carll               unop( Iop_32UtoV128,
1793660c6bac19ffe055cabab554e7877d73096a8bf17carll                     mkexpr(_get_quad_modulo_or_carry(mkexpr(vA),
1793760c6bac19ffe055cabab554e7877d73096a8bf17carll                                                      unop( Iop_NotV128,
1793860c6bac19ffe055cabab554e7877d73096a8bf17carll                                                            mkexpr(vB) ),
1793960c6bac19ffe055cabab554e7877d73096a8bf17carll                                                      mkU32(1), False) ) ) );
1794060c6bac19ffe055cabab554e7877d73096a8bf17carll      return True;
1794160c6bac19ffe055cabab554e7877d73096a8bf17carll   case 0x500: // vsubuqm
1794260c6bac19ffe055cabab554e7877d73096a8bf17carll      DIP("vsubuqm v%d,v%d,v%d\n", vRT_addr, vRA_addr, vRB_addr);
1794360c6bac19ffe055cabab554e7877d73096a8bf17carll      putVReg( vRT_addr,
1794460c6bac19ffe055cabab554e7877d73096a8bf17carll               mkexpr(_get_quad_modulo_or_carry(mkexpr(vA),
1794560c6bac19ffe055cabab554e7877d73096a8bf17carll                                                unop( Iop_NotV128, mkexpr(vB) ),
1794660c6bac19ffe055cabab554e7877d73096a8bf17carll                                                mkU32(1), True) ) );
1794760c6bac19ffe055cabab554e7877d73096a8bf17carll      return True;
1794860c6bac19ffe055cabab554e7877d73096a8bf17carll   case 0x054C: // vbpermq
1794960c6bac19ffe055cabab554e7877d73096a8bf17carll   {
1795060c6bac19ffe055cabab554e7877d73096a8bf17carll#define BPERMD_IDX_MASK 0x00000000000000FFULL
1795160c6bac19ffe055cabab554e7877d73096a8bf17carll#define BPERMD_BIT_MASK 0x8000000000000000ULL
1795260c6bac19ffe055cabab554e7877d73096a8bf17carll      int i;
1795360c6bac19ffe055cabab554e7877d73096a8bf17carll      IRExpr * vB_expr = mkexpr(vB);
1795460c6bac19ffe055cabab554e7877d73096a8bf17carll      IRExpr * res = binop(Iop_AndV128, mkV128(0), mkV128(0));
1795560c6bac19ffe055cabab554e7877d73096a8bf17carll      DIP("vbpermq v%d,v%d,v%d\n", vRT_addr, vRA_addr, vRB_addr);
1795660c6bac19ffe055cabab554e7877d73096a8bf17carll      for (i = 0; i < 16; i++) {
1795760c6bac19ffe055cabab554e7877d73096a8bf17carll         IRTemp idx_tmp = newTemp( Ity_V128 );
1795860c6bac19ffe055cabab554e7877d73096a8bf17carll         IRTemp perm_bit = newTemp( Ity_V128 );
1795960c6bac19ffe055cabab554e7877d73096a8bf17carll         IRTemp idx = newTemp( Ity_I8 );
1796060c6bac19ffe055cabab554e7877d73096a8bf17carll         IRTemp idx_LT127 = newTemp( Ity_I1 );
1796160c6bac19ffe055cabab554e7877d73096a8bf17carll         IRTemp idx_LT127_ity128 = newTemp( Ity_V128 );
1796260c6bac19ffe055cabab554e7877d73096a8bf17carll
1796360c6bac19ffe055cabab554e7877d73096a8bf17carll         assign( idx_tmp,
1796460c6bac19ffe055cabab554e7877d73096a8bf17carll                 binop( Iop_AndV128,
1796560c6bac19ffe055cabab554e7877d73096a8bf17carll                        binop( Iop_64HLtoV128,
1796660c6bac19ffe055cabab554e7877d73096a8bf17carll                               mkU64(0),
1796760c6bac19ffe055cabab554e7877d73096a8bf17carll                               mkU64(BPERMD_IDX_MASK) ),
1796860c6bac19ffe055cabab554e7877d73096a8bf17carll                        vB_expr ) );
1796960c6bac19ffe055cabab554e7877d73096a8bf17carll         assign( idx_LT127,
1797060c6bac19ffe055cabab554e7877d73096a8bf17carll                 binop( Iop_CmpEQ32,
1797160c6bac19ffe055cabab554e7877d73096a8bf17carll                        unop ( Iop_64to32,
1797260c6bac19ffe055cabab554e7877d73096a8bf17carll                               unop( Iop_V128to64, binop( Iop_ShrV128,
1797360c6bac19ffe055cabab554e7877d73096a8bf17carll                                                          mkexpr(idx_tmp),
1797460c6bac19ffe055cabab554e7877d73096a8bf17carll                                                          mkU8(7) ) ) ),
1797560c6bac19ffe055cabab554e7877d73096a8bf17carll                        mkU32(0) ) );
1797660c6bac19ffe055cabab554e7877d73096a8bf17carll
1797760c6bac19ffe055cabab554e7877d73096a8bf17carll         /* Below, we set idx to determine which bit of vA to use for the
1797860c6bac19ffe055cabab554e7877d73096a8bf17carll          * perm bit.  If idx_LT127 is 0, the perm bit is forced to '0'.
1797960c6bac19ffe055cabab554e7877d73096a8bf17carll          */
1798060c6bac19ffe055cabab554e7877d73096a8bf17carll         assign( idx,
1798160c6bac19ffe055cabab554e7877d73096a8bf17carll                 binop( Iop_And8,
1798260c6bac19ffe055cabab554e7877d73096a8bf17carll                        unop( Iop_1Sto8,
1798360c6bac19ffe055cabab554e7877d73096a8bf17carll                              mkexpr(idx_LT127) ),
1798460c6bac19ffe055cabab554e7877d73096a8bf17carll                        unop( Iop_32to8,
1798560c6bac19ffe055cabab554e7877d73096a8bf17carll                              unop( Iop_V128to32, mkexpr( idx_tmp ) ) ) ) );
1798660c6bac19ffe055cabab554e7877d73096a8bf17carll
1798760c6bac19ffe055cabab554e7877d73096a8bf17carll         assign( idx_LT127_ity128,
1798860c6bac19ffe055cabab554e7877d73096a8bf17carll                 binop( Iop_64HLtoV128,
1798960c6bac19ffe055cabab554e7877d73096a8bf17carll                        mkU64(0),
1799060c6bac19ffe055cabab554e7877d73096a8bf17carll                        unop( Iop_32Uto64,
1799160c6bac19ffe055cabab554e7877d73096a8bf17carll                              unop( Iop_1Uto32, mkexpr(idx_LT127 ) ) ) ) );
1799260c6bac19ffe055cabab554e7877d73096a8bf17carll         assign( perm_bit,
1799360c6bac19ffe055cabab554e7877d73096a8bf17carll                 binop( Iop_AndV128,
1799460c6bac19ffe055cabab554e7877d73096a8bf17carll                        mkexpr( idx_LT127_ity128 ),
1799560c6bac19ffe055cabab554e7877d73096a8bf17carll                        binop( Iop_ShrV128,
1799660c6bac19ffe055cabab554e7877d73096a8bf17carll                               binop( Iop_AndV128,
1799760c6bac19ffe055cabab554e7877d73096a8bf17carll                                      binop (Iop_64HLtoV128,
1799860c6bac19ffe055cabab554e7877d73096a8bf17carll                                             mkU64( BPERMD_BIT_MASK ),
1799960c6bac19ffe055cabab554e7877d73096a8bf17carll                                             mkU64(0)),
1800060c6bac19ffe055cabab554e7877d73096a8bf17carll                                      binop( Iop_ShlV128,
1800160c6bac19ffe055cabab554e7877d73096a8bf17carll                                             mkexpr( vA ),
1800260c6bac19ffe055cabab554e7877d73096a8bf17carll                                             mkexpr( idx ) ) ),
1800360c6bac19ffe055cabab554e7877d73096a8bf17carll                               mkU8( 127 ) ) ) );
18004bc6db6e02ea0964a8f1da1986ff201d500709a50carll         res = binop( Iop_OrV128,
18005bc6db6e02ea0964a8f1da1986ff201d500709a50carll                      res,
18006bc6db6e02ea0964a8f1da1986ff201d500709a50carll                      binop( Iop_ShlV128,
18007bc6db6e02ea0964a8f1da1986ff201d500709a50carll                             mkexpr( perm_bit ),
18008bc6db6e02ea0964a8f1da1986ff201d500709a50carll                             mkU8( i + 64 ) ) );
1800960c6bac19ffe055cabab554e7877d73096a8bf17carll         vB_expr = binop( Iop_ShrV128, vB_expr, mkU8( 8 ) );
1801060c6bac19ffe055cabab554e7877d73096a8bf17carll      }
1801160c6bac19ffe055cabab554e7877d73096a8bf17carll      putVReg( vRT_addr, res);
1801260c6bac19ffe055cabab554e7877d73096a8bf17carll      return True;
1801360c6bac19ffe055cabab554e7877d73096a8bf17carll#undef BPERMD_IDX_MASK
1801460c6bac19ffe055cabab554e7877d73096a8bf17carll#undef BPERMD_BIT_MASK
1801560c6bac19ffe055cabab554e7877d73096a8bf17carll   }
1801660c6bac19ffe055cabab554e7877d73096a8bf17carll
1801760c6bac19ffe055cabab554e7877d73096a8bf17carll   default:
1801860c6bac19ffe055cabab554e7877d73096a8bf17carll      break;  // fall through
1801960c6bac19ffe055cabab554e7877d73096a8bf17carll   }
1802060c6bac19ffe055cabab554e7877d73096a8bf17carll
1802160c6bac19ffe055cabab554e7877d73096a8bf17carll   opc2     = IFIELD( theInstr, 0, 6 );
1802260c6bac19ffe055cabab554e7877d73096a8bf17carll   vRC_addr = ifieldRegC(theInstr);
1802360c6bac19ffe055cabab554e7877d73096a8bf17carll   vC = newTemp(Ity_V128);
1802460c6bac19ffe055cabab554e7877d73096a8bf17carll   cin = newTemp(Ity_I32);
1802560c6bac19ffe055cabab554e7877d73096a8bf17carll   switch (opc2) {
1802660c6bac19ffe055cabab554e7877d73096a8bf17carll      case 0x3D: // vaddecuq
1802760c6bac19ffe055cabab554e7877d73096a8bf17carll         assign( vC, getVReg(vRC_addr));
1802860c6bac19ffe055cabab554e7877d73096a8bf17carll         DIP("vaddecuq v%d,v%d,v%d,v%d\n", vRT_addr, vRA_addr, vRB_addr,
1802960c6bac19ffe055cabab554e7877d73096a8bf17carll             vRC_addr);
1803060c6bac19ffe055cabab554e7877d73096a8bf17carll         assign(cin, binop( Iop_And32,
1803160c6bac19ffe055cabab554e7877d73096a8bf17carll                            unop( Iop_64to32,
1803260c6bac19ffe055cabab554e7877d73096a8bf17carll                                  unop( Iop_V128to64, mkexpr(vC) ) ),
1803360c6bac19ffe055cabab554e7877d73096a8bf17carll                            mkU32(1) ) );
1803460c6bac19ffe055cabab554e7877d73096a8bf17carll         putVReg( vRT_addr,
1803560c6bac19ffe055cabab554e7877d73096a8bf17carll                  unop( Iop_32UtoV128,
1803660c6bac19ffe055cabab554e7877d73096a8bf17carll                        mkexpr(_get_quad_modulo_or_carry(mkexpr(vA), mkexpr(vB),
1803760c6bac19ffe055cabab554e7877d73096a8bf17carll                                                         mkexpr(cin),
1803860c6bac19ffe055cabab554e7877d73096a8bf17carll                                                         False) ) ) );
1803960c6bac19ffe055cabab554e7877d73096a8bf17carll         return True;
1804060c6bac19ffe055cabab554e7877d73096a8bf17carll      case 0x3C: // vaddeuqm
1804160c6bac19ffe055cabab554e7877d73096a8bf17carll         assign( vC, getVReg(vRC_addr));
1804260c6bac19ffe055cabab554e7877d73096a8bf17carll         DIP("vaddeuqm v%d,v%d,v%d,v%d\n", vRT_addr, vRA_addr, vRB_addr,
1804360c6bac19ffe055cabab554e7877d73096a8bf17carll             vRC_addr);
1804460c6bac19ffe055cabab554e7877d73096a8bf17carll         assign(cin, binop( Iop_And32,
1804560c6bac19ffe055cabab554e7877d73096a8bf17carll                            unop( Iop_64to32,
1804660c6bac19ffe055cabab554e7877d73096a8bf17carll                                  unop( Iop_V128to64, mkexpr(vC) ) ),
1804760c6bac19ffe055cabab554e7877d73096a8bf17carll                            mkU32(1) ) );
1804860c6bac19ffe055cabab554e7877d73096a8bf17carll         putVReg( vRT_addr,
1804960c6bac19ffe055cabab554e7877d73096a8bf17carll                  mkexpr(_get_quad_modulo_or_carry(mkexpr(vA), mkexpr(vB),
1805060c6bac19ffe055cabab554e7877d73096a8bf17carll                                                   mkexpr(cin),
1805160c6bac19ffe055cabab554e7877d73096a8bf17carll                                                   True) ) );
1805260c6bac19ffe055cabab554e7877d73096a8bf17carll         return True;
1805360c6bac19ffe055cabab554e7877d73096a8bf17carll      case 0x3F: // vsubecuq
1805460c6bac19ffe055cabab554e7877d73096a8bf17carll         assign( vC, getVReg(vRC_addr));
1805560c6bac19ffe055cabab554e7877d73096a8bf17carll         DIP("vsubecuq v%d,v%d,v%d,v%d\n", vRT_addr, vRA_addr, vRB_addr,
1805660c6bac19ffe055cabab554e7877d73096a8bf17carll             vRC_addr);
1805760c6bac19ffe055cabab554e7877d73096a8bf17carll         assign(cin, binop( Iop_And32,
1805860c6bac19ffe055cabab554e7877d73096a8bf17carll                            unop( Iop_64to32,
1805960c6bac19ffe055cabab554e7877d73096a8bf17carll                                  unop( Iop_V128to64, mkexpr(vC) ) ),
1806060c6bac19ffe055cabab554e7877d73096a8bf17carll                            mkU32(1) ) );
1806160c6bac19ffe055cabab554e7877d73096a8bf17carll         putVReg( vRT_addr,
1806260c6bac19ffe055cabab554e7877d73096a8bf17carll                  unop( Iop_32UtoV128,
1806360c6bac19ffe055cabab554e7877d73096a8bf17carll                        mkexpr(_get_quad_modulo_or_carry(mkexpr(vA),
1806460c6bac19ffe055cabab554e7877d73096a8bf17carll                                                         unop( Iop_NotV128,
1806560c6bac19ffe055cabab554e7877d73096a8bf17carll                                                               mkexpr(vB) ),
1806660c6bac19ffe055cabab554e7877d73096a8bf17carll                                                         mkexpr(cin),
1806760c6bac19ffe055cabab554e7877d73096a8bf17carll                                                         False) ) ) );
1806860c6bac19ffe055cabab554e7877d73096a8bf17carll         return True;
1806960c6bac19ffe055cabab554e7877d73096a8bf17carll      case 0x3E: // vsubeuqm
1807060c6bac19ffe055cabab554e7877d73096a8bf17carll         assign( vC, getVReg(vRC_addr));
1807160c6bac19ffe055cabab554e7877d73096a8bf17carll         DIP("vsubeuqm v%d,v%d,v%d,v%d\n", vRT_addr, vRA_addr, vRB_addr,
1807260c6bac19ffe055cabab554e7877d73096a8bf17carll             vRC_addr);
1807360c6bac19ffe055cabab554e7877d73096a8bf17carll         assign(cin, binop( Iop_And32,
1807460c6bac19ffe055cabab554e7877d73096a8bf17carll                            unop( Iop_64to32,
1807560c6bac19ffe055cabab554e7877d73096a8bf17carll                                  unop( Iop_V128to64, mkexpr(vC) ) ),
1807660c6bac19ffe055cabab554e7877d73096a8bf17carll                            mkU32(1) ) );
1807760c6bac19ffe055cabab554e7877d73096a8bf17carll         putVReg( vRT_addr,
1807860c6bac19ffe055cabab554e7877d73096a8bf17carll                  mkexpr(_get_quad_modulo_or_carry(mkexpr(vA),
1807960c6bac19ffe055cabab554e7877d73096a8bf17carll                                                   unop( Iop_NotV128, mkexpr(vB) ),
1808060c6bac19ffe055cabab554e7877d73096a8bf17carll                                                   mkexpr(cin),
1808160c6bac19ffe055cabab554e7877d73096a8bf17carll                                                   True) ) );
1808260c6bac19ffe055cabab554e7877d73096a8bf17carll         return True;
1808360c6bac19ffe055cabab554e7877d73096a8bf17carll      default:
1808460c6bac19ffe055cabab554e7877d73096a8bf17carll         vex_printf("dis_av_quad(ppc)(opc2.2)\n");
1808560c6bac19ffe055cabab554e7877d73096a8bf17carll         return False;
1808660c6bac19ffe055cabab554e7877d73096a8bf17carll   }
1808760c6bac19ffe055cabab554e7877d73096a8bf17carll
1808860c6bac19ffe055cabab554e7877d73096a8bf17carll   return True;
1808960c6bac19ffe055cabab554e7877d73096a8bf17carll}
1809060c6bac19ffe055cabab554e7877d73096a8bf17carll
1809160c6bac19ffe055cabab554e7877d73096a8bf17carll
1809260c6bac19ffe055cabab554e7877d73096a8bf17carll/*
180937deaf9552b546b847528cf39b38898fb7742b5f5carll  AltiVec BCD Arithmetic instructions.
180947deaf9552b546b847528cf39b38898fb7742b5f5carll  These instructions modify CR6 for various conditions in the result,
180957deaf9552b546b847528cf39b38898fb7742b5f5carll  including when an overflow occurs.  We could easily detect all conditions
180967deaf9552b546b847528cf39b38898fb7742b5f5carll  except when an overflow occurs.  But since we can't be 100% accurate
180977deaf9552b546b847528cf39b38898fb7742b5f5carll  in our emulation of CR6, it seems best to just not support it all.
180987deaf9552b546b847528cf39b38898fb7742b5f5carll*/
180997deaf9552b546b847528cf39b38898fb7742b5f5carllstatic Bool dis_av_bcd ( UInt theInstr )
181007deaf9552b546b847528cf39b38898fb7742b5f5carll{
181017deaf9552b546b847528cf39b38898fb7742b5f5carll   /* VX-Form */
181027deaf9552b546b847528cf39b38898fb7742b5f5carll   UChar opc1     = ifieldOPC(theInstr);
181037deaf9552b546b847528cf39b38898fb7742b5f5carll   UChar vRT_addr = ifieldRegDS(theInstr);
181047deaf9552b546b847528cf39b38898fb7742b5f5carll   UChar vRA_addr = ifieldRegA(theInstr);
181057deaf9552b546b847528cf39b38898fb7742b5f5carll   UChar vRB_addr = ifieldRegB(theInstr);
181067deaf9552b546b847528cf39b38898fb7742b5f5carll   UChar ps       = IFIELD( theInstr, 9, 1 );
181077deaf9552b546b847528cf39b38898fb7742b5f5carll   UInt  opc2     = IFIELD( theInstr, 0, 9 );
181087deaf9552b546b847528cf39b38898fb7742b5f5carll
181097deaf9552b546b847528cf39b38898fb7742b5f5carll   IRTemp vA    = newTemp(Ity_V128);
181107deaf9552b546b847528cf39b38898fb7742b5f5carll   IRTemp vB    = newTemp(Ity_V128);
181117deaf9552b546b847528cf39b38898fb7742b5f5carll   IRTemp dst    = newTemp(Ity_V128);
181127deaf9552b546b847528cf39b38898fb7742b5f5carll   assign( vA, getVReg(vRA_addr));
181137deaf9552b546b847528cf39b38898fb7742b5f5carll   assign( vB, getVReg(vRB_addr));
181147deaf9552b546b847528cf39b38898fb7742b5f5carll
181157deaf9552b546b847528cf39b38898fb7742b5f5carll   if (opc1 != 0x4) {
181167deaf9552b546b847528cf39b38898fb7742b5f5carll      vex_printf("dis_av_bcd(ppc)(instr)\n");
181177deaf9552b546b847528cf39b38898fb7742b5f5carll      return False;
181187deaf9552b546b847528cf39b38898fb7742b5f5carll   }
181197deaf9552b546b847528cf39b38898fb7742b5f5carll
181207deaf9552b546b847528cf39b38898fb7742b5f5carll   switch (opc2) {
181217deaf9552b546b847528cf39b38898fb7742b5f5carll   case 0x1:  // bcdadd
181227deaf9552b546b847528cf39b38898fb7742b5f5carll     DIP("bcdadd. v%d,v%d,v%d,%u\n", vRT_addr, vRA_addr, vRB_addr, ps);
181237deaf9552b546b847528cf39b38898fb7742b5f5carll     assign( dst, triop( Iop_BCDAdd, mkexpr( vA ),
181247deaf9552b546b847528cf39b38898fb7742b5f5carll                         mkexpr( vB ), mkU8( ps ) ) );
181257deaf9552b546b847528cf39b38898fb7742b5f5carll     putVReg( vRT_addr, mkexpr(dst));
181267deaf9552b546b847528cf39b38898fb7742b5f5carll     return True;
181277deaf9552b546b847528cf39b38898fb7742b5f5carll
181287deaf9552b546b847528cf39b38898fb7742b5f5carll   case 0x41:  // bcdsub
181297deaf9552b546b847528cf39b38898fb7742b5f5carll     DIP("bcdsub. v%d,v%d,v%d,%u\n", vRT_addr, vRA_addr, vRB_addr, ps);
181307deaf9552b546b847528cf39b38898fb7742b5f5carll     assign( dst, triop( Iop_BCDSub, mkexpr( vA ),
181317deaf9552b546b847528cf39b38898fb7742b5f5carll                         mkexpr( vB ), mkU8( ps ) ) );
181327deaf9552b546b847528cf39b38898fb7742b5f5carll     putVReg( vRT_addr, mkexpr(dst));
181337deaf9552b546b847528cf39b38898fb7742b5f5carll     return True;
181347deaf9552b546b847528cf39b38898fb7742b5f5carll
181357deaf9552b546b847528cf39b38898fb7742b5f5carll   default:
181367deaf9552b546b847528cf39b38898fb7742b5f5carll      vex_printf("dis_av_bcd(ppc)(opc2)\n");
181377deaf9552b546b847528cf39b38898fb7742b5f5carll      return False;
181387deaf9552b546b847528cf39b38898fb7742b5f5carll   }
181397deaf9552b546b847528cf39b38898fb7742b5f5carll   return True;
181407deaf9552b546b847528cf39b38898fb7742b5f5carll}
1814132aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion
1814232aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion/*
1814332aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion  AltiVec Floating Point Arithmetic Instructions
1814432aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion*/
1814532aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerionstatic Bool dis_av_fp_arith ( UInt theInstr )
1814632aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion{
1814776de5cf615380b23b4b5bcced6541233cd4a93a0cerion   /* VA-Form */
1814876de5cf615380b23b4b5bcced6541233cd4a93a0cerion   UChar opc1     = ifieldOPC(theInstr);
1814976de5cf615380b23b4b5bcced6541233cd4a93a0cerion   UChar vD_addr  = ifieldRegDS(theInstr);
1815076de5cf615380b23b4b5bcced6541233cd4a93a0cerion   UChar vA_addr  = ifieldRegA(theInstr);
1815176de5cf615380b23b4b5bcced6541233cd4a93a0cerion   UChar vB_addr  = ifieldRegB(theInstr);
1815276de5cf615380b23b4b5bcced6541233cd4a93a0cerion   UChar vC_addr  = ifieldRegC(theInstr);
1815332aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion   UInt  opc2=0;
1815432aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion
181558ea0d3ebfb8b1e4d8b6f851b0079c47a9886c686cerion   IRTemp vA = newTemp(Ity_V128);
181568ea0d3ebfb8b1e4d8b6f851b0079c47a9886c686cerion   IRTemp vB = newTemp(Ity_V128);
181578ea0d3ebfb8b1e4d8b6f851b0079c47a9886c686cerion   IRTemp vC = newTemp(Ity_V128);
181588ea0d3ebfb8b1e4d8b6f851b0079c47a9886c686cerion   assign( vA, getVReg(vA_addr));
181598ea0d3ebfb8b1e4d8b6f851b0079c47a9886c686cerion   assign( vB, getVReg(vB_addr));
181608ea0d3ebfb8b1e4d8b6f851b0079c47a9886c686cerion   assign( vC, getVReg(vC_addr));
181618ea0d3ebfb8b1e4d8b6f851b0079c47a9886c686cerion
1816232aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion   if (opc1 != 0x4) {
181635b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion      vex_printf("dis_av_fp_arith(ppc)(instr)\n");
1816432aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion      return False;
1816532aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion   }
1816632aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion
1816720a760ec66a13a93147a40d3c3530be21d7fe411sewardj   IRTemp rm = newTemp(Ity_I32);
1816820a760ec66a13a93147a40d3c3530be21d7fe411sewardj   assign(rm, get_IR_roundingmode());
1816920a760ec66a13a93147a40d3c3530be21d7fe411sewardj
1817076de5cf615380b23b4b5bcced6541233cd4a93a0cerion   opc2 = IFIELD( theInstr, 0, 6 );
1817132aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion   switch (opc2) {
1817232aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion   case 0x2E: // vmaddfp (Multiply Add FP, AV p177)
181735b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion      DIP("vmaddfp v%d,v%d,v%d,v%d\n",
181745b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion          vD_addr, vA_addr, vC_addr, vB_addr);
181755b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion      putVReg( vD_addr,
1817620a760ec66a13a93147a40d3c3530be21d7fe411sewardj               triop(Iop_Add32Fx4, mkU32(Irrm_NEAREST),
1817720a760ec66a13a93147a40d3c3530be21d7fe411sewardj                     mkexpr(vB),
1817820a760ec66a13a93147a40d3c3530be21d7fe411sewardj                     triop(Iop_Mul32Fx4, mkU32(Irrm_NEAREST),
1817920a760ec66a13a93147a40d3c3530be21d7fe411sewardj                           mkexpr(vA), mkexpr(vC))) );
18180f3f173c1383bb406cf9cd5768712790ac8b5d14bcerion      return True;
1818132aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion
18182f3f173c1383bb406cf9cd5768712790ac8b5d14bcerion   case 0x2F: { // vnmsubfp (Negative Multiply-Subtract FP, AV p215)
181835b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion      DIP("vnmsubfp v%d,v%d,v%d,v%d\n",
181845b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion          vD_addr, vA_addr, vC_addr, vB_addr);
181855b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion      putVReg( vD_addr,
1818620a760ec66a13a93147a40d3c3530be21d7fe411sewardj               triop(Iop_Sub32Fx4, mkU32(Irrm_NEAREST),
181875b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion                     mkexpr(vB),
1818820a760ec66a13a93147a40d3c3530be21d7fe411sewardj                     triop(Iop_Mul32Fx4, mkU32(Irrm_NEAREST),
1818920a760ec66a13a93147a40d3c3530be21d7fe411sewardj                           mkexpr(vA), mkexpr(vC))) );
18190f3f173c1383bb406cf9cd5768712790ac8b5d14bcerion      return True;
18191f3f173c1383bb406cf9cd5768712790ac8b5d14bcerion   }
1819232aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion
1819332aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion   default:
1819432aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion     break; // Fall through...
1819532aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion   }
1819632aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion
1819776de5cf615380b23b4b5bcced6541233cd4a93a0cerion   opc2 = IFIELD( theInstr, 0, 11 );
1819832aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion   switch (opc2) {
1819932aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion   case 0x00A: // vaddfp (Add FP, AV p137)
1820032aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion      DIP("vaddfp v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
1820120a760ec66a13a93147a40d3c3530be21d7fe411sewardj      putVReg( vD_addr, triop(Iop_Add32Fx4,
1820220a760ec66a13a93147a40d3c3530be21d7fe411sewardj                              mkU32(Irrm_NEAREST), mkexpr(vA), mkexpr(vB)) );
182038ea0d3ebfb8b1e4d8b6f851b0079c47a9886c686cerion      return True;
1820432aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion
1820532aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion  case 0x04A: // vsubfp (Subtract FP, AV p261)
1820632aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion      DIP("vsubfp v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
1820720a760ec66a13a93147a40d3c3530be21d7fe411sewardj      putVReg( vD_addr, triop(Iop_Sub32Fx4,
1820820a760ec66a13a93147a40d3c3530be21d7fe411sewardj                              mkU32(Irrm_NEAREST), mkexpr(vA), mkexpr(vB)) );
182098ea0d3ebfb8b1e4d8b6f851b0079c47a9886c686cerion      return True;
1821032aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion
1821132aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion   case 0x40A: // vmaxfp (Maximum FP, AV p178)
1821232aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion      DIP("vmaxfp v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
182138ea0d3ebfb8b1e4d8b6f851b0079c47a9886c686cerion      putVReg( vD_addr, binop(Iop_Max32Fx4, mkexpr(vA), mkexpr(vB)) );
182148ea0d3ebfb8b1e4d8b6f851b0079c47a9886c686cerion      return True;
1821532aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion
1821632aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion   case 0x44A: // vminfp (Minimum FP, AV p187)
1821732aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion      DIP("vminfp v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
182188ea0d3ebfb8b1e4d8b6f851b0079c47a9886c686cerion      putVReg( vD_addr, binop(Iop_Min32Fx4, mkexpr(vA), mkexpr(vB)) );
182198ea0d3ebfb8b1e4d8b6f851b0079c47a9886c686cerion      return True;
1822032aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion
1822132aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion   default:
1822232aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion      break; // Fall through...
1822332aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion   }
1822432aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion
1822532aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion
1822632aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion   if (vA_addr != 0) {
182275b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion      vex_printf("dis_av_fp_arith(ppc)(vA_addr)\n");
1822832aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion      return False;
1822932aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion   }
1823032aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion
1823132aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion   switch (opc2) {
1823232aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion   case 0x10A: // vrefp (Reciprocal Esimate FP, AV p228)
1823332aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion      DIP("vrefp v%d,v%d\n", vD_addr, vB_addr);
182341ddee21008ffdb2ac7f8e6a73445f150f753606fsewardj      putVReg( vD_addr, unop(Iop_RecipEst32Fx4, mkexpr(vB)) );
182358ea0d3ebfb8b1e4d8b6f851b0079c47a9886c686cerion      return True;
1823632aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion
182375b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion   case 0x14A: // vrsqrtefp (Reciprocal Sqrt Estimate FP, AV p237)
1823832aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion      DIP("vrsqrtefp v%d,v%d\n", vD_addr, vB_addr);
182391ddee21008ffdb2ac7f8e6a73445f150f753606fsewardj      putVReg( vD_addr, unop(Iop_RSqrtEst32Fx4, mkexpr(vB)) );
182408ea0d3ebfb8b1e4d8b6f851b0079c47a9886c686cerion      return True;
1824132aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion
1824232aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion   case 0x18A: // vexptefp (2 Raised to the Exp Est FP, AV p173)
1824332aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion      DIP("vexptefp v%d,v%d\n", vD_addr, vB_addr);
1824432aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion      DIP(" => not implemented\n");
1824532aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion      return False;
1824632aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion
1824732aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion   case 0x1CA: // vlogefp (Log2 Estimate FP, AV p175)
1824832aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion      DIP("vlogefp v%d,v%d\n", vD_addr, vB_addr);
1824932aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion      DIP(" => not implemented\n");
1825032aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion      return False;
1825132aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion
1825232aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion   default:
182535b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion      vex_printf("dis_av_fp_arith(ppc)(opc2=0x%x)\n",opc2);
1825432aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion      return False;
1825532aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion   }
1825632aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion   return True;
1825732aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion}
1825832aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion
1825932aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion/*
1826032aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion  AltiVec Floating Point Compare Instructions
1826132aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion*/
1826232aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerionstatic Bool dis_av_fp_cmp ( UInt theInstr )
1826332aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion{
1826476de5cf615380b23b4b5bcced6541233cd4a93a0cerion   /* VXR-Form */
1826576de5cf615380b23b4b5bcced6541233cd4a93a0cerion   UChar opc1     = ifieldOPC(theInstr);
1826676de5cf615380b23b4b5bcced6541233cd4a93a0cerion   UChar vD_addr  = ifieldRegDS(theInstr);
1826776de5cf615380b23b4b5bcced6541233cd4a93a0cerion   UChar vA_addr  = ifieldRegA(theInstr);
1826876de5cf615380b23b4b5bcced6541233cd4a93a0cerion   UChar vB_addr  = ifieldRegB(theInstr);
1826976de5cf615380b23b4b5bcced6541233cd4a93a0cerion   UChar flag_rC  = ifieldBIT10(theInstr);
1827076de5cf615380b23b4b5bcced6541233cd4a93a0cerion   UInt  opc2     = IFIELD( theInstr, 0, 10 );
1827132aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion
182728ea0d3ebfb8b1e4d8b6f851b0079c47a9886c686cerion   Bool cmp_bounds = False;
182738ea0d3ebfb8b1e4d8b6f851b0079c47a9886c686cerion
182748ea0d3ebfb8b1e4d8b6f851b0079c47a9886c686cerion   IRTemp vA = newTemp(Ity_V128);
182758ea0d3ebfb8b1e4d8b6f851b0079c47a9886c686cerion   IRTemp vB = newTemp(Ity_V128);
182768ea0d3ebfb8b1e4d8b6f851b0079c47a9886c686cerion   IRTemp vD = newTemp(Ity_V128);
182778ea0d3ebfb8b1e4d8b6f851b0079c47a9886c686cerion   assign( vA, getVReg(vA_addr));
182788ea0d3ebfb8b1e4d8b6f851b0079c47a9886c686cerion   assign( vB, getVReg(vB_addr));
182798ea0d3ebfb8b1e4d8b6f851b0079c47a9886c686cerion
1828032aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion   if (opc1 != 0x4) {
182815b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion      vex_printf("dis_av_fp_cmp(ppc)(instr)\n");
1828232aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion      return False;
1828332aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion   }
1828432aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion
1828532aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion   switch (opc2) {
1828632aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion   case 0x0C6: // vcmpeqfp (Compare Equal-to FP, AV p159)
182875b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion      DIP("vcmpeqfp%s v%d,v%d,v%d\n", (flag_rC ? ".":""),
182885b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion                                      vD_addr, vA_addr, vB_addr);
182898ea0d3ebfb8b1e4d8b6f851b0079c47a9886c686cerion      assign( vD, binop(Iop_CmpEQ32Fx4, mkexpr(vA), mkexpr(vB)) );
182908ea0d3ebfb8b1e4d8b6f851b0079c47a9886c686cerion      break;
1829132aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion
182925b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion   case 0x1C6: // vcmpgefp (Compare Greater-than-or-Equal-to, AV p163)
182935b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion      DIP("vcmpgefp%s v%d,v%d,v%d\n", (flag_rC ? ".":""),
182945b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion                                      vD_addr, vA_addr, vB_addr);
182958ea0d3ebfb8b1e4d8b6f851b0079c47a9886c686cerion      assign( vD, binop(Iop_CmpGE32Fx4, mkexpr(vA), mkexpr(vB)) );
182968ea0d3ebfb8b1e4d8b6f851b0079c47a9886c686cerion      break;
1829732aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion
1829832aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion   case 0x2C6: // vcmpgtfp (Compare Greater-than FP, AV p164)
182995b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion      DIP("vcmpgtfp%s v%d,v%d,v%d\n", (flag_rC ? ".":""),
183005b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion                                      vD_addr, vA_addr, vB_addr);
183018ea0d3ebfb8b1e4d8b6f851b0079c47a9886c686cerion      assign( vD, binop(Iop_CmpGT32Fx4, mkexpr(vA), mkexpr(vB)) );
183028ea0d3ebfb8b1e4d8b6f851b0079c47a9886c686cerion      break;
1830332aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion
183048ea0d3ebfb8b1e4d8b6f851b0079c47a9886c686cerion   case 0x3C6: { // vcmpbfp (Compare Bounds FP, AV p157)
183058ea0d3ebfb8b1e4d8b6f851b0079c47a9886c686cerion      IRTemp gt      = newTemp(Ity_V128);
183068ea0d3ebfb8b1e4d8b6f851b0079c47a9886c686cerion      IRTemp lt      = newTemp(Ity_V128);
183078ea0d3ebfb8b1e4d8b6f851b0079c47a9886c686cerion      IRTemp zeros   = newTemp(Ity_V128);
183085b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion      DIP("vcmpbfp%s v%d,v%d,v%d\n", (flag_rC ? ".":""),
183095b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion                                     vD_addr, vA_addr, vB_addr);
183108ea0d3ebfb8b1e4d8b6f851b0079c47a9886c686cerion      cmp_bounds = True;
183118ea0d3ebfb8b1e4d8b6f851b0079c47a9886c686cerion      assign( zeros,   unop(Iop_Dup32x4, mkU32(0)) );
183128ea0d3ebfb8b1e4d8b6f851b0079c47a9886c686cerion
183138ea0d3ebfb8b1e4d8b6f851b0079c47a9886c686cerion      /* Note: making use of fact that the ppc backend for compare insns
183145b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion         return zero'd lanes if either of the corresponding arg lanes is
183155b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion         a nan.
183168ea0d3ebfb8b1e4d8b6f851b0079c47a9886c686cerion
183178ea0d3ebfb8b1e4d8b6f851b0079c47a9886c686cerion         Perhaps better to have an irop Iop_isNan32Fx4, but then we'd
183188ea0d3ebfb8b1e4d8b6f851b0079c47a9886c686cerion         need this for the other compares too (vcmpeqfp etc)...
183198ea0d3ebfb8b1e4d8b6f851b0079c47a9886c686cerion         Better still, tighten down the spec for compare irops.
183208ea0d3ebfb8b1e4d8b6f851b0079c47a9886c686cerion       */
183218ea0d3ebfb8b1e4d8b6f851b0079c47a9886c686cerion      assign( gt, unop(Iop_NotV128,
183228ea0d3ebfb8b1e4d8b6f851b0079c47a9886c686cerion                       binop(Iop_CmpLE32Fx4, mkexpr(vA), mkexpr(vB))) );
183238ea0d3ebfb8b1e4d8b6f851b0079c47a9886c686cerion      assign( lt, unop(Iop_NotV128,
183248ea0d3ebfb8b1e4d8b6f851b0079c47a9886c686cerion                       binop(Iop_CmpGE32Fx4, mkexpr(vA),
1832520a760ec66a13a93147a40d3c3530be21d7fe411sewardj                             triop(Iop_Sub32Fx4, mkU32(Irrm_NEAREST),
1832620a760ec66a13a93147a40d3c3530be21d7fe411sewardj                                   mkexpr(zeros),
1832720a760ec66a13a93147a40d3c3530be21d7fe411sewardj                                   mkexpr(vB)))) );
183288ea0d3ebfb8b1e4d8b6f851b0079c47a9886c686cerion
183298ea0d3ebfb8b1e4d8b6f851b0079c47a9886c686cerion      // finally, just shift gt,lt to correct position
183308ea0d3ebfb8b1e4d8b6f851b0079c47a9886c686cerion      assign( vD, binop(Iop_ShlN32x4,
183318ea0d3ebfb8b1e4d8b6f851b0079c47a9886c686cerion                        binop(Iop_OrV128,
183328ea0d3ebfb8b1e4d8b6f851b0079c47a9886c686cerion                              binop(Iop_AndV128, mkexpr(gt),
183338ea0d3ebfb8b1e4d8b6f851b0079c47a9886c686cerion                                    unop(Iop_Dup32x4, mkU32(0x2))),
183348ea0d3ebfb8b1e4d8b6f851b0079c47a9886c686cerion                              binop(Iop_AndV128, mkexpr(lt),
183358ea0d3ebfb8b1e4d8b6f851b0079c47a9886c686cerion                                    unop(Iop_Dup32x4, mkU32(0x1)))),
183368ea0d3ebfb8b1e4d8b6f851b0079c47a9886c686cerion                        mkU8(30)) );
183378ea0d3ebfb8b1e4d8b6f851b0079c47a9886c686cerion      break;
183388ea0d3ebfb8b1e4d8b6f851b0079c47a9886c686cerion   }
1833932aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion
1834032aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion   default:
183415b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion      vex_printf("dis_av_fp_cmp(ppc)(opc2)\n");
1834232aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion      return False;
1834332aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion   }
183448ea0d3ebfb8b1e4d8b6f851b0079c47a9886c686cerion
183458ea0d3ebfb8b1e4d8b6f851b0079c47a9886c686cerion   putVReg( vD_addr, mkexpr(vD) );
183468ea0d3ebfb8b1e4d8b6f851b0079c47a9886c686cerion
1834776de5cf615380b23b4b5bcced6541233cd4a93a0cerion   if (flag_rC) {
183488ea0d3ebfb8b1e4d8b6f851b0079c47a9886c686cerion      set_AV_CR6( mkexpr(vD), !cmp_bounds );
183498ea0d3ebfb8b1e4d8b6f851b0079c47a9886c686cerion   }
1835032aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion   return True;
1835132aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion}
1835232aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion
1835332aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion/*
1835432aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion  AltiVec Floating Point Convert/Round Instructions
1835532aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion*/
1835632aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerionstatic Bool dis_av_fp_convert ( UInt theInstr )
1835732aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion{
1835876de5cf615380b23b4b5bcced6541233cd4a93a0cerion   /* VX-Form */
1835976de5cf615380b23b4b5bcced6541233cd4a93a0cerion   UChar opc1     = ifieldOPC(theInstr);
1836076de5cf615380b23b4b5bcced6541233cd4a93a0cerion   UChar vD_addr  = ifieldRegDS(theInstr);
1836176de5cf615380b23b4b5bcced6541233cd4a93a0cerion   UChar UIMM_5   = ifieldRegA(theInstr);
1836276de5cf615380b23b4b5bcced6541233cd4a93a0cerion   UChar vB_addr  = ifieldRegB(theInstr);
1836376de5cf615380b23b4b5bcced6541233cd4a93a0cerion   UInt  opc2     = IFIELD( theInstr, 0, 11 );
1836476de5cf615380b23b4b5bcced6541233cd4a93a0cerion
1836576de5cf615380b23b4b5bcced6541233cd4a93a0cerion   IRTemp vB        = newTemp(Ity_V128);
1836676de5cf615380b23b4b5bcced6541233cd4a93a0cerion   IRTemp vScale    = newTemp(Ity_V128);
18367d963eb444d05fe1ef210a729ff056e28c330f120cerion   IRTemp vInvScale = newTemp(Ity_V128);
1836841a7b70f888cf73cf3da6a53b31937ce0d26e8f4sewardj
1836941a7b70f888cf73cf3da6a53b31937ce0d26e8f4sewardj   float scale, inv_scale;
1837041a7b70f888cf73cf3da6a53b31937ce0d26e8f4sewardj
18371d963eb444d05fe1ef210a729ff056e28c330f120cerion   assign( vB, getVReg(vB_addr));
18372d963eb444d05fe1ef210a729ff056e28c330f120cerion
18373d963eb444d05fe1ef210a729ff056e28c330f120cerion   /* scale = 2^UIMM, cast to float, reinterpreted as uint */
1837441a7b70f888cf73cf3da6a53b31937ce0d26e8f4sewardj   scale = (float)( (unsigned int) 1<<UIMM_5 );
183752ead522cf1c0069fbc55f7c5d1e8b2a00a044d6bsewardj   assign( vScale, unop(Iop_Dup32x4, mkU32( float_to_bits(scale) )) );
1837641a7b70f888cf73cf3da6a53b31937ce0d26e8f4sewardj   inv_scale = 1/scale;
183775b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion   assign( vInvScale,
183785b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion           unop(Iop_Dup32x4, mkU32( float_to_bits(inv_scale) )) );
18379d963eb444d05fe1ef210a729ff056e28c330f120cerion
1838032aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion   if (opc1 != 0x4) {
183815b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion      vex_printf("dis_av_fp_convert(ppc)(instr)\n");
1838232aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion      return False;
1838332aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion   }
1838432aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion
1838532aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion   switch (opc2) {
1838632aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion   case 0x30A: // vcfux (Convert from Unsigned Fixed-Point W, AV p156)
1838732aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion      DIP("vcfux v%d,v%d,%d\n", vD_addr, vB_addr, UIMM_5);
1838820a760ec66a13a93147a40d3c3530be21d7fe411sewardj      putVReg( vD_addr, triop(Iop_Mul32Fx4, mkU32(Irrm_NEAREST),
18389d963eb444d05fe1ef210a729ff056e28c330f120cerion                              unop(Iop_I32UtoFx4, mkexpr(vB)),
18390d963eb444d05fe1ef210a729ff056e28c330f120cerion                              mkexpr(vInvScale)) );
18391d963eb444d05fe1ef210a729ff056e28c330f120cerion      return True;
1839232aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion
1839332aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion   case 0x34A: // vcfsx (Convert from Signed Fixed-Point W, AV p155)
1839432aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion      DIP("vcfsx v%d,v%d,%d\n", vD_addr, vB_addr, UIMM_5);
18395d963eb444d05fe1ef210a729ff056e28c330f120cerion
1839620a760ec66a13a93147a40d3c3530be21d7fe411sewardj      putVReg( vD_addr, triop(Iop_Mul32Fx4, mkU32(Irrm_NEAREST),
18397d963eb444d05fe1ef210a729ff056e28c330f120cerion                              unop(Iop_I32StoFx4, mkexpr(vB)),
18398d963eb444d05fe1ef210a729ff056e28c330f120cerion                              mkexpr(vInvScale)) );
18399d963eb444d05fe1ef210a729ff056e28c330f120cerion      return True;
1840032aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion
1840132aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion   case 0x38A: // vctuxs (Convert to Unsigned Fixed-Point W Saturate, AV p172)
1840232aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion      DIP("vctuxs v%d,v%d,%d\n", vD_addr, vB_addr, UIMM_5);
18403d963eb444d05fe1ef210a729ff056e28c330f120cerion      putVReg( vD_addr,
18404d963eb444d05fe1ef210a729ff056e28c330f120cerion               unop(Iop_QFtoI32Ux4_RZ,
1840520a760ec66a13a93147a40d3c3530be21d7fe411sewardj                    triop(Iop_Mul32Fx4, mkU32(Irrm_NEAREST),
1840620a760ec66a13a93147a40d3c3530be21d7fe411sewardj                          mkexpr(vB), mkexpr(vScale))) );
18407d963eb444d05fe1ef210a729ff056e28c330f120cerion      return True;
1840832aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion
1840932aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion   case 0x3CA: // vctsxs (Convert to Signed Fixed-Point W Saturate, AV p171)
1841032aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion      DIP("vctsxs v%d,v%d,%d\n", vD_addr, vB_addr, UIMM_5);
18411d963eb444d05fe1ef210a729ff056e28c330f120cerion      putVReg( vD_addr,
18412d963eb444d05fe1ef210a729ff056e28c330f120cerion               unop(Iop_QFtoI32Sx4_RZ,
1841320a760ec66a13a93147a40d3c3530be21d7fe411sewardj                     triop(Iop_Mul32Fx4, mkU32(Irrm_NEAREST),
1841420a760ec66a13a93147a40d3c3530be21d7fe411sewardj                           mkexpr(vB), mkexpr(vScale))) );
18415d963eb444d05fe1ef210a729ff056e28c330f120cerion      return True;
1841632aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion
1841732aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion   default:
1841832aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion     break;    // Fall through...
1841932aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion   }
1842032aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion
1842132aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion   if (UIMM_5 != 0) {
184225b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion      vex_printf("dis_av_fp_convert(ppc)(UIMM_5)\n");
1842332aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion      return False;
1842432aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion   }
1842532aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion
1842632aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion   switch (opc2) {
1842732aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion   case 0x20A: // vrfin (Round to FP Integer Nearest, AV p231)
1842832aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion      DIP("vrfin v%d,v%d\n", vD_addr, vB_addr);
18429d963eb444d05fe1ef210a729ff056e28c330f120cerion      putVReg( vD_addr, unop(Iop_RoundF32x4_RN, mkexpr(vB)) );
18430d963eb444d05fe1ef210a729ff056e28c330f120cerion      break;
1843132aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion
1843232aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion   case 0x24A: // vrfiz (Round to FP Integer toward zero, AV p233)
1843332aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion      DIP("vrfiz v%d,v%d\n", vD_addr, vB_addr);
18434d963eb444d05fe1ef210a729ff056e28c330f120cerion      putVReg( vD_addr, unop(Iop_RoundF32x4_RZ, mkexpr(vB)) );
18435d963eb444d05fe1ef210a729ff056e28c330f120cerion      break;
1843632aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion
1843732aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion   case 0x28A: // vrfip (Round to FP Integer toward +inf, AV p232)
1843832aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion      DIP("vrfip v%d,v%d\n", vD_addr, vB_addr);
18439d963eb444d05fe1ef210a729ff056e28c330f120cerion      putVReg( vD_addr, unop(Iop_RoundF32x4_RP, mkexpr(vB)) );
18440d963eb444d05fe1ef210a729ff056e28c330f120cerion      break;
1844132aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion
1844232aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion   case 0x2CA: // vrfim (Round to FP Integer toward -inf, AV p230)
1844332aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion      DIP("vrfim v%d,v%d\n", vD_addr, vB_addr);
18444d963eb444d05fe1ef210a729ff056e28c330f120cerion      putVReg( vD_addr, unop(Iop_RoundF32x4_RM, mkexpr(vB)) );
18445d963eb444d05fe1ef210a729ff056e28c330f120cerion      break;
1844632aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion
1844732aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion   default:
184485b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion      vex_printf("dis_av_fp_convert(ppc)(opc2)\n");
1844932aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion      return False;
1845032aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion   }
1845132aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion   return True;
1845232aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion}
18453b51f0f4f33256638ed953156a2635aa739b232f1sewardj
184548943d02aa373f45c6e5fdcbe5947620285d442b1carllstatic Bool dis_transactional_memory ( UInt theInstr, UInt nextInstr,
18455cacba8e675988fbf21b08feea1f317a9c896c053florian                                       const VexAbiInfo* vbi,
184568943d02aa373f45c6e5fdcbe5947620285d442b1carll                                       /*OUT*/DisResult* dres,
18457beac530a718fcc646bc61fe60a86f599df54e1d7florian                                       Bool (*resteerOkFn)(void*,Addr),
184588943d02aa373f45c6e5fdcbe5947620285d442b1carll                                       void* callback_opaque )
184598943d02aa373f45c6e5fdcbe5947620285d442b1carll{
184608943d02aa373f45c6e5fdcbe5947620285d442b1carll   UInt   opc2      = IFIELD( theInstr, 1, 10 );
184618943d02aa373f45c6e5fdcbe5947620285d442b1carll
184628943d02aa373f45c6e5fdcbe5947620285d442b1carll   switch (opc2) {
184638943d02aa373f45c6e5fdcbe5947620285d442b1carll   case 0x28E: {        //tbegin.
184648943d02aa373f45c6e5fdcbe5947620285d442b1carll      /* The current implementation is to just fail the tbegin and execute
184658943d02aa373f45c6e5fdcbe5947620285d442b1carll       * the failure path.  The failure path is assumed to be functionaly
184668943d02aa373f45c6e5fdcbe5947620285d442b1carll       * equivalent to the transactional path with the needed data locking
184678943d02aa373f45c6e5fdcbe5947620285d442b1carll       * to ensure correctness.  The tend is just a noop and shouldn't
184688943d02aa373f45c6e5fdcbe5947620285d442b1carll       * actually get executed.
184698943d02aa373f45c6e5fdcbe5947620285d442b1carll       *   1) set cr0 to 0x2
184708943d02aa373f45c6e5fdcbe5947620285d442b1carll       *   2) Initialize TFHAR to CIA+4
184718943d02aa373f45c6e5fdcbe5947620285d442b1carll       *   3) Initialize TEXASR
184728943d02aa373f45c6e5fdcbe5947620285d442b1carll       *   4) Initialize TFIAR (probably to CIA, ie, the address of tbegin.)
184738943d02aa373f45c6e5fdcbe5947620285d442b1carll       *   5) Continue executing at the next instruction.
184748943d02aa373f45c6e5fdcbe5947620285d442b1carll       */
184758943d02aa373f45c6e5fdcbe5947620285d442b1carll      UInt R = IFIELD( theInstr, 21, 1 );
184768943d02aa373f45c6e5fdcbe5947620285d442b1carll
184778943d02aa373f45c6e5fdcbe5947620285d442b1carll      ULong tm_reason;
184788943d02aa373f45c6e5fdcbe5947620285d442b1carll      UInt failure_code = 0;  /* Forcing failure, will not be due to tabort
184798943d02aa373f45c6e5fdcbe5947620285d442b1carll                               * or treclaim.
184808943d02aa373f45c6e5fdcbe5947620285d442b1carll                               */
184818943d02aa373f45c6e5fdcbe5947620285d442b1carll      UInt persistant = 1;    /* set persistant since we are always failing
184828943d02aa373f45c6e5fdcbe5947620285d442b1carll                               * the tbegin.
184838943d02aa373f45c6e5fdcbe5947620285d442b1carll                               */
184848943d02aa373f45c6e5fdcbe5947620285d442b1carll      UInt nest_overflow = 1; /* Alowed nesting depth overflow, we use this
184858943d02aa373f45c6e5fdcbe5947620285d442b1carll                                 as the reason for failing the trasaction */
184868943d02aa373f45c6e5fdcbe5947620285d442b1carll      UInt tm_exact   = 1;    /* have exact address for failure */
184878943d02aa373f45c6e5fdcbe5947620285d442b1carll
184888943d02aa373f45c6e5fdcbe5947620285d442b1carll      DIP("tbegin. %d\n", R);
184898943d02aa373f45c6e5fdcbe5947620285d442b1carll
184908943d02aa373f45c6e5fdcbe5947620285d442b1carll      /* Set the CR0 field to indicate the tbegin failed.  Then let
184918943d02aa373f45c6e5fdcbe5947620285d442b1carll       * the code do the branch to the failure path.
184928943d02aa373f45c6e5fdcbe5947620285d442b1carll       *
184938943d02aa373f45c6e5fdcbe5947620285d442b1carll       * 000 || 0  Transaction initiation successful,
184948943d02aa373f45c6e5fdcbe5947620285d442b1carll       *           unnested (Transaction state of
184958943d02aa373f45c6e5fdcbe5947620285d442b1carll       *           Non-transactional prior to tbegin.)
184968943d02aa373f45c6e5fdcbe5947620285d442b1carll       * 010 || 0  Transaction initiation successful, nested
184978943d02aa373f45c6e5fdcbe5947620285d442b1carll       *           (Transaction state of Transactional
184988943d02aa373f45c6e5fdcbe5947620285d442b1carll       *           prior to tbegin.)
184998943d02aa373f45c6e5fdcbe5947620285d442b1carll       * 001 || 0  Transaction initiation unsuccessful,
185008943d02aa373f45c6e5fdcbe5947620285d442b1carll       *           (Transaction state of Suspended prior
185018943d02aa373f45c6e5fdcbe5947620285d442b1carll       *           to tbegin.)
185028943d02aa373f45c6e5fdcbe5947620285d442b1carll       */
185038943d02aa373f45c6e5fdcbe5947620285d442b1carll      putCR321( 0, mkU8( 0x2 ) );
185048943d02aa373f45c6e5fdcbe5947620285d442b1carll
185058943d02aa373f45c6e5fdcbe5947620285d442b1carll      tm_reason = generate_TMreason( failure_code, persistant,
185068943d02aa373f45c6e5fdcbe5947620285d442b1carll                                     nest_overflow, tm_exact );
185078943d02aa373f45c6e5fdcbe5947620285d442b1carll
185088943d02aa373f45c6e5fdcbe5947620285d442b1carll      storeTMfailure( guest_CIA_curr_instr, tm_reason,
185098943d02aa373f45c6e5fdcbe5947620285d442b1carll                      guest_CIA_curr_instr+4 );
185108943d02aa373f45c6e5fdcbe5947620285d442b1carll
185118943d02aa373f45c6e5fdcbe5947620285d442b1carll      return True;
185128943d02aa373f45c6e5fdcbe5947620285d442b1carll
185138943d02aa373f45c6e5fdcbe5947620285d442b1carll      break;
185148943d02aa373f45c6e5fdcbe5947620285d442b1carll   }
185158943d02aa373f45c6e5fdcbe5947620285d442b1carll
185168943d02aa373f45c6e5fdcbe5947620285d442b1carll   case 0x2AE: {        //tend.
185178943d02aa373f45c6e5fdcbe5947620285d442b1carll      /* The tend. is just a noop.  Do nothing */
185188943d02aa373f45c6e5fdcbe5947620285d442b1carll      UInt A = IFIELD( theInstr, 25, 1 );
185198943d02aa373f45c6e5fdcbe5947620285d442b1carll
185208943d02aa373f45c6e5fdcbe5947620285d442b1carll      DIP("tend. %d\n", A);
185218943d02aa373f45c6e5fdcbe5947620285d442b1carll      break;
185228943d02aa373f45c6e5fdcbe5947620285d442b1carll   }
185238943d02aa373f45c6e5fdcbe5947620285d442b1carll
185248943d02aa373f45c6e5fdcbe5947620285d442b1carll   case 0x2EE: {        //tsr.
185258943d02aa373f45c6e5fdcbe5947620285d442b1carll      /* The tsr. is just a noop.  Do nothing */
185268943d02aa373f45c6e5fdcbe5947620285d442b1carll      UInt L = IFIELD( theInstr, 21, 1 );
185278943d02aa373f45c6e5fdcbe5947620285d442b1carll
185288943d02aa373f45c6e5fdcbe5947620285d442b1carll      DIP("tsr. %d\n", L);
185298943d02aa373f45c6e5fdcbe5947620285d442b1carll      break;
185308943d02aa373f45c6e5fdcbe5947620285d442b1carll   }
185318943d02aa373f45c6e5fdcbe5947620285d442b1carll
185328943d02aa373f45c6e5fdcbe5947620285d442b1carll   case 0x2CE: {        //tcheck.
185338943d02aa373f45c6e5fdcbe5947620285d442b1carll      /* The tcheck. is just a noop.  Do nothing */
185348943d02aa373f45c6e5fdcbe5947620285d442b1carll      UInt BF = IFIELD( theInstr, 25, 1 );
185358943d02aa373f45c6e5fdcbe5947620285d442b1carll
185368943d02aa373f45c6e5fdcbe5947620285d442b1carll      DIP("tcheck. %d\n", BF);
185378943d02aa373f45c6e5fdcbe5947620285d442b1carll      break;
185388943d02aa373f45c6e5fdcbe5947620285d442b1carll   }
185398943d02aa373f45c6e5fdcbe5947620285d442b1carll
185408943d02aa373f45c6e5fdcbe5947620285d442b1carll   case 0x30E: {        //tbortwc.
185418943d02aa373f45c6e5fdcbe5947620285d442b1carll      /* The tabortwc. is just a noop.  Do nothing */
185428943d02aa373f45c6e5fdcbe5947620285d442b1carll      UInt TO = IFIELD( theInstr, 25, 1 );
185438943d02aa373f45c6e5fdcbe5947620285d442b1carll      UInt RA = IFIELD( theInstr, 16, 5 );
185448943d02aa373f45c6e5fdcbe5947620285d442b1carll      UInt RB = IFIELD( theInstr, 11, 5 );
185458943d02aa373f45c6e5fdcbe5947620285d442b1carll
185468943d02aa373f45c6e5fdcbe5947620285d442b1carll      DIP("tabortwc. %d,%d,%d\n", TO, RA, RB);
185478943d02aa373f45c6e5fdcbe5947620285d442b1carll      break;
185488943d02aa373f45c6e5fdcbe5947620285d442b1carll   }
185498943d02aa373f45c6e5fdcbe5947620285d442b1carll
185508943d02aa373f45c6e5fdcbe5947620285d442b1carll   case 0x32E: {        //tbortdc.
185518943d02aa373f45c6e5fdcbe5947620285d442b1carll      /* The tabortdc. is just a noop.  Do nothing */
185528943d02aa373f45c6e5fdcbe5947620285d442b1carll      UInt TO = IFIELD( theInstr, 25, 1 );
185538943d02aa373f45c6e5fdcbe5947620285d442b1carll      UInt RA = IFIELD( theInstr, 16, 5 );
185548943d02aa373f45c6e5fdcbe5947620285d442b1carll      UInt RB = IFIELD( theInstr, 11, 5 );
185558943d02aa373f45c6e5fdcbe5947620285d442b1carll
185568943d02aa373f45c6e5fdcbe5947620285d442b1carll      DIP("tabortdc. %d,%d,%d\n", TO, RA, RB);
185578943d02aa373f45c6e5fdcbe5947620285d442b1carll      break;
185588943d02aa373f45c6e5fdcbe5947620285d442b1carll   }
185598943d02aa373f45c6e5fdcbe5947620285d442b1carll
185608943d02aa373f45c6e5fdcbe5947620285d442b1carll   case 0x34E: {        //tbortwci.
185618943d02aa373f45c6e5fdcbe5947620285d442b1carll      /* The tabortwci. is just a noop.  Do nothing */
185628943d02aa373f45c6e5fdcbe5947620285d442b1carll      UInt TO = IFIELD( theInstr, 25, 1 );
185638943d02aa373f45c6e5fdcbe5947620285d442b1carll      UInt RA = IFIELD( theInstr, 16, 5 );
185648943d02aa373f45c6e5fdcbe5947620285d442b1carll      UInt SI = IFIELD( theInstr, 11, 5 );
185658943d02aa373f45c6e5fdcbe5947620285d442b1carll
185668943d02aa373f45c6e5fdcbe5947620285d442b1carll      DIP("tabortwci. %d,%d,%d\n", TO, RA, SI);
185678943d02aa373f45c6e5fdcbe5947620285d442b1carll      break;
185688943d02aa373f45c6e5fdcbe5947620285d442b1carll   }
185698943d02aa373f45c6e5fdcbe5947620285d442b1carll
185708943d02aa373f45c6e5fdcbe5947620285d442b1carll   case 0x36E: {        //tbortdci.
185718943d02aa373f45c6e5fdcbe5947620285d442b1carll      /* The tabortdci. is just a noop.  Do nothing */
185728943d02aa373f45c6e5fdcbe5947620285d442b1carll      UInt TO = IFIELD( theInstr, 25, 1 );
185738943d02aa373f45c6e5fdcbe5947620285d442b1carll      UInt RA = IFIELD( theInstr, 16, 5 );
185748943d02aa373f45c6e5fdcbe5947620285d442b1carll      UInt SI = IFIELD( theInstr, 11, 5 );
185758943d02aa373f45c6e5fdcbe5947620285d442b1carll
185768943d02aa373f45c6e5fdcbe5947620285d442b1carll      DIP("tabortdci. %d,%d,%d\n", TO, RA, SI);
185778943d02aa373f45c6e5fdcbe5947620285d442b1carll      break;
185788943d02aa373f45c6e5fdcbe5947620285d442b1carll   }
185798943d02aa373f45c6e5fdcbe5947620285d442b1carll
185808943d02aa373f45c6e5fdcbe5947620285d442b1carll   case 0x38E: {        //tbort.
185818943d02aa373f45c6e5fdcbe5947620285d442b1carll      /* The tabort. is just a noop.  Do nothing */
185828943d02aa373f45c6e5fdcbe5947620285d442b1carll      UInt RA = IFIELD( theInstr, 16, 5 );
185838943d02aa373f45c6e5fdcbe5947620285d442b1carll
185848943d02aa373f45c6e5fdcbe5947620285d442b1carll      DIP("tabort. %d\n", RA);
185858943d02aa373f45c6e5fdcbe5947620285d442b1carll      break;
185868943d02aa373f45c6e5fdcbe5947620285d442b1carll   }
185878943d02aa373f45c6e5fdcbe5947620285d442b1carll
18588fcce5f8ca9ad1fbb5939b8c94d7470b4d51a7387carll   case 0x3AE: {        //treclaim.
18589fcce5f8ca9ad1fbb5939b8c94d7470b4d51a7387carll      /* The treclaim. is just a noop.  Do nothing */
18590fcce5f8ca9ad1fbb5939b8c94d7470b4d51a7387carll      UInt RA = IFIELD( theInstr, 16, 5 );
18591fcce5f8ca9ad1fbb5939b8c94d7470b4d51a7387carll
18592fcce5f8ca9ad1fbb5939b8c94d7470b4d51a7387carll      DIP("treclaim. %d\n", RA);
18593fcce5f8ca9ad1fbb5939b8c94d7470b4d51a7387carll      break;
18594fcce5f8ca9ad1fbb5939b8c94d7470b4d51a7387carll   }
18595fcce5f8ca9ad1fbb5939b8c94d7470b4d51a7387carll
18596fcce5f8ca9ad1fbb5939b8c94d7470b4d51a7387carll   case 0x3EE: {        //trechkpt.
18597fcce5f8ca9ad1fbb5939b8c94d7470b4d51a7387carll      /* The trechkpt. is just a noop.  Do nothing */
18598fcce5f8ca9ad1fbb5939b8c94d7470b4d51a7387carll      DIP("trechkpt.\n");
18599fcce5f8ca9ad1fbb5939b8c94d7470b4d51a7387carll      break;
18600fcce5f8ca9ad1fbb5939b8c94d7470b4d51a7387carll   }
18601fcce5f8ca9ad1fbb5939b8c94d7470b4d51a7387carll
186028943d02aa373f45c6e5fdcbe5947620285d442b1carll   default:
186038943d02aa373f45c6e5fdcbe5947620285d442b1carll      vex_printf("dis_transactional_memory(ppc): unrecognized instruction\n");
186048943d02aa373f45c6e5fdcbe5947620285d442b1carll      return False;
186058943d02aa373f45c6e5fdcbe5947620285d442b1carll   }
186068943d02aa373f45c6e5fdcbe5947620285d442b1carll
186078943d02aa373f45c6e5fdcbe5947620285d442b1carll   return True;
186088943d02aa373f45c6e5fdcbe5947620285d442b1carll}
186098943d02aa373f45c6e5fdcbe5947620285d442b1carll
18610a982c0503d8c0c6069ae453bfe70657bd2c134aecerion
1861166d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj/* The 0x3C primary opcode (VSX category) uses several different forms of
1861266d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj * extended opcodes:
1861366d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj *   o XX2-form:
1861466d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj *      - [10:2] (IBM notation [21:29])
1861566d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj *   o XX3-form variants:
1861666d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj *       - variant 1: [10:3] (IBM notation [21:28])
1861766d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj *       - variant 2: [9:3] (IBM notation [22:28])
1861866d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj *       - variant 3: [7:3] (IBM notation [24:28])
1861966d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj *   o XX-4 form:
1862066d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj *      - [10:6] (IBM notation [21:25])
1862166d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj *
1862266d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj * The XX2-form needs bit 0 masked from the standard extended opcode
1862366d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj * as returned by ifieldOPClo10; the XX3-form needs bits 0 and 1 masked;
1862466d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj * and the XX4-form needs bits 0, 1, and 2 masked.  Additionally, the
1862566d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj * XX4 and XX3 (variants 2 and 3) forms need certain bits masked on the
1862666d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj * front end since their encoding does not begin at bit 21 like the standard
1862766d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj * format.
1862866d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj *
1862966d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj * The get_VSX60_opc2() function uses the vsx_insn array below to obtain the
1863066d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj * secondary opcode for such VSX instructions.
1863166d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj *
1863266d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj*/
18633a982c0503d8c0c6069ae453bfe70657bd2c134aecerion
18634a982c0503d8c0c6069ae453bfe70657bd2c134aecerion
1863566d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardjstruct vsx_insn {
1863666d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj   UInt opcode;
1863755085f8680acc89d727e321f3b34cae1a8c4093aflorian   const HChar * name;
1863866d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj};
1863966d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj
1864066d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj//  ATTENTION:  Keep this array sorted on the opcocde!!!
1864166d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardjstatic struct vsx_insn vsx_all[] = {
186426c758b64a77c254065ab7450576bbd3a0b583595carll      { 0x0, "xsaddsp" },
186436c758b64a77c254065ab7450576bbd3a0b583595carll      { 0x4, "xsmaddasp" },
1864466d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj      { 0x8, "xxsldwi" },
186456c758b64a77c254065ab7450576bbd3a0b583595carll      { 0x14, "xsrsqrtesp" },
186466c758b64a77c254065ab7450576bbd3a0b583595carll      { 0x16, "xssqrtsp" },
1864766d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj      { 0x18, "xxsel" },
186486c758b64a77c254065ab7450576bbd3a0b583595carll      { 0x20, "xssubsp" },
186496c758b64a77c254065ab7450576bbd3a0b583595carll      { 0x24, "xsmaddmsp" },
1865066d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj      { 0x28, "xxpermdi" },
186516c758b64a77c254065ab7450576bbd3a0b583595carll      { 0x34, "xsresp" },
186526c758b64a77c254065ab7450576bbd3a0b583595carll      { 0x40, "xsmulsp" },
186536c758b64a77c254065ab7450576bbd3a0b583595carll      { 0x44, "xsmsubasp" },
1865466d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj      { 0x48, "xxmrghw" },
186556c758b64a77c254065ab7450576bbd3a0b583595carll      { 0x60, "xsdivsp" },
186566c758b64a77c254065ab7450576bbd3a0b583595carll      { 0x64, "xsmsubmsp" },
1865766d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj      { 0x80, "xsadddp" },
1865866d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj      { 0x84, "xsmaddadp" },
1865966d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj      { 0x8c, "xscmpudp" },
1866066d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj      { 0x90, "xscvdpuxws" },
1866166d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj      { 0x92, "xsrdpi" },
1866266d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj      { 0x94, "xsrsqrtedp" },
1866366d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj      { 0x96, "xssqrtdp" },
1866466d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj      { 0xa0, "xssubdp" },
1866566d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj      { 0xa4, "xsmaddmdp" },
1866666d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj      { 0xac, "xscmpodp" },
1866766d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj      { 0xb0, "xscvdpsxws" },
1866866d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj      { 0xb2, "xsrdpiz" },
1866966d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj      { 0xb4, "xsredp" },
1867066d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj      { 0xc0, "xsmuldp" },
1867166d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj      { 0xc4, "xsmsubadp" },
1867266d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj      { 0xc8, "xxmrglw" },
1867366d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj      { 0xd2, "xsrdpip" },
1867466d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj      { 0xd4, "xstsqrtdp" },
1867566d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj      { 0xd6, "xsrdpic" },
1867666d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj      { 0xe0, "xsdivdp" },
1867766d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj      { 0xe4, "xsmsubmdp" },
1867866d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj      { 0xf2, "xsrdpim" },
1867966d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj      { 0xf4, "xstdivdp" },
1868066d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj      { 0x100, "xvaddsp" },
1868166d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj      { 0x104, "xvmaddasp" },
1868266d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj      { 0x10c, "xvcmpeqsp" },
1868366d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj      { 0x110, "xvcvspuxws" },
1868466d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj      { 0x112, "xvrspi" },
1868566d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj      { 0x114, "xvrsqrtesp" },
1868666d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj      { 0x116, "xvsqrtsp" },
1868766d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj      { 0x120, "xvsubsp" },
1868866d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj      { 0x124, "xvmaddmsp" },
1868966d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj      { 0x12c, "xvcmpgtsp" },
1869066d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj      { 0x130, "xvcvspsxws" },
1869166d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj      { 0x132, "xvrspiz" },
1869266d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj      { 0x134, "xvresp" },
1869366d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj      { 0x140, "xvmulsp" },
1869466d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj      { 0x144, "xvmsubasp" },
1869566d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj      { 0x148, "xxspltw" },
1869666d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj      { 0x14c, "xvcmpgesp" },
1869766d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj      { 0x150, "xvcvuxwsp" },
1869866d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj      { 0x152, "xvrspip" },
1869966d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj      { 0x154, "xvtsqrtsp" },
1870066d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj      { 0x156, "xvrspic" },
1870166d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj      { 0x160, "xvdivsp" },
1870266d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj      { 0x164, "xvmsubmsp" },
1870366d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj      { 0x170, "xvcvsxwsp" },
1870466d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj      { 0x172, "xvrspim" },
1870566d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj      { 0x174, "xvtdivsp" },
1870666d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj      { 0x180, "xvadddp" },
1870766d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj      { 0x184, "xvmaddadp" },
1870866d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj      { 0x18c, "xvcmpeqdp" },
1870966d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj      { 0x190, "xvcvdpuxws" },
1871066d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj      { 0x192, "xvrdpi" },
1871166d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj      { 0x194, "xvrsqrtedp" },
1871266d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj      { 0x196, "xvsqrtdp" },
1871366d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj      { 0x1a0, "xvsubdp" },
1871466d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj      { 0x1a4, "xvmaddmdp" },
1871566d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj      { 0x1ac, "xvcmpgtdp" },
1871666d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj      { 0x1b0, "xvcvdpsxws" },
1871766d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj      { 0x1b2, "xvrdpiz" },
1871866d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj      { 0x1b4, "xvredp" },
1871966d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj      { 0x1c0, "xvmuldp" },
1872066d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj      { 0x1c4, "xvmsubadp" },
1872166d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj      { 0x1cc, "xvcmpgedp" },
1872266d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj      { 0x1d0, "xvcvuxwdp" },
1872366d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj      { 0x1d2, "xvrdpip" },
1872466d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj      { 0x1d4, "xvtsqrtdp" },
1872566d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj      { 0x1d6, "xvrdpic" },
1872666d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj      { 0x1e0, "xvdivdp" },
1872766d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj      { 0x1e4, "xvmsubmdp" },
1872866d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj      { 0x1f0, "xvcvsxwdp" },
1872966d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj      { 0x1f2, "xvrdpim" },
1873066d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj      { 0x1f4, "xvtdivdp" },
187316c758b64a77c254065ab7450576bbd3a0b583595carll      { 0x204, "xsnmaddasp" },
1873266d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj      { 0x208, "xxland" },
1873366d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj      { 0x212, "xscvdpsp" },
187340c74bb5aa3240f693df0568d578baabf0c376dc4carll      { 0x216, "xscvdpspn" },
187356c758b64a77c254065ab7450576bbd3a0b583595carll      { 0x224, "xsnmaddmsp" },
1873666d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj      { 0x228, "xxlandc" },
187376c758b64a77c254065ab7450576bbd3a0b583595carll      { 0x232, "xxrsp" },
187386c758b64a77c254065ab7450576bbd3a0b583595carll      { 0x244, "xsnmsubasp" },
187396c758b64a77c254065ab7450576bbd3a0b583595carll      { 0x248, "xxlor" },
187406c758b64a77c254065ab7450576bbd3a0b583595carll      { 0x250, "xscvuxdsp" },
187416c758b64a77c254065ab7450576bbd3a0b583595carll      { 0x264, "xsnmsubmsp" },
1874266d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj      { 0x268, "xxlxor" },
187436c758b64a77c254065ab7450576bbd3a0b583595carll      { 0x270, "xscvsxdsp" },
1874466d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj      { 0x280, "xsmaxdp" },
1874566d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj      { 0x284, "xsnmaddadp" },
1874666d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj      { 0x288, "xxlnor" },
1874766d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj      { 0x290, "xscvdpuxds" },
1874866d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj      { 0x292, "xscvspdp" },
187490c74bb5aa3240f693df0568d578baabf0c376dc4carll      { 0x296, "xscvspdpn" },
1875066d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj      { 0x2a0, "xsmindp" },
1875166d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj      { 0x2a4, "xsnmaddmdp" },
187526c758b64a77c254065ab7450576bbd3a0b583595carll      { 0x2a8, "xxlorc" },
1875366d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj      { 0x2b0, "xscvdpsxds" },
1875466d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj      { 0x2b2, "xsabsdp" },
1875566d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj      { 0x2c0, "xscpsgndp" },
1875666d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj      { 0x2c4, "xsnmsubadp" },
187576c758b64a77c254065ab7450576bbd3a0b583595carll      { 0x2c8, "xxlnand" },
1875866d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj      { 0x2d0, "xscvuxddp" },
1875966d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj      { 0x2d2, "xsnabsdp" },
1876066d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj      { 0x2e4, "xsnmsubmdp" },
187616c758b64a77c254065ab7450576bbd3a0b583595carll      { 0x2e8, "xxleqv" },
1876266d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj      { 0x2f0, "xscvsxddp" },
1876366d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj      { 0x2f2, "xsnegdp" },
1876466d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj      { 0x300, "xvmaxsp" },
1876566d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj      { 0x304, "xvnmaddasp" },
1876666d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj      { 0x30c, "xvcmpeqsp." },
1876766d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj      { 0x310, "xvcvspuxds" },
1876866d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj      { 0x312, "xvcvdpsp" },
1876966d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj      { 0x320, "xvminsp" },
1877066d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj      { 0x324, "xvnmaddmsp" },
1877166d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj      { 0x32c, "xvcmpgtsp." },
1877266d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj      { 0x330, "xvcvspsxds" },
1877366d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj      { 0x332, "xvabssp" },
1877466d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj      { 0x340, "xvcpsgnsp" },
1877566d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj      { 0x344, "xvnmsubasp" },
1877666d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj      { 0x34c, "xvcmpgesp." },
1877766d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj      { 0x350, "xvcvuxdsp" },
1877866d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj      { 0x352, "xvnabssp" },
1877966d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj      { 0x364, "xvnmsubmsp" },
1878066d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj      { 0x370, "xvcvsxdsp" },
1878166d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj      { 0x372, "xvnegsp" },
1878266d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj      { 0x380, "xvmaxdp" },
1878366d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj      { 0x384, "xvnmaddadp" },
1878466d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj      { 0x38c, "xvcmpeqdp." },
1878566d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj      { 0x390, "xvcvdpuxds" },
1878666d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj      { 0x392, "xvcvspdp" },
1878766d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj      { 0x3a0, "xvmindp" },
1878866d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj      { 0x3a4, "xvnmaddmdp" },
1878966d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj      { 0x3ac, "xvcmpgtdp." },
1879066d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj      { 0x3b0, "xvcvdpsxds" },
1879166d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj      { 0x3b2, "xvabsdp" },
1879266d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj      { 0x3c0, "xvcpsgndp" },
1879366d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj      { 0x3c4, "xvnmsubadp" },
1879466d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj      { 0x3cc, "xvcmpgedp." },
1879566d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj      { 0x3d0, "xvcvuxddp" },
1879666d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj      { 0x3d2, "xvnabsdp" },
1879766d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj      { 0x3e4, "xvnmsubmdp" },
1879866d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj      { 0x3f0, "xvcvsxddp" },
1879966d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj      { 0x3f2, "xvnegdp" }
1880066d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj};
188010c74bb5aa3240f693df0568d578baabf0c376dc4carll#define VSX_ALL_LEN (sizeof vsx_all / sizeof *vsx_all)
188020c74bb5aa3240f693df0568d578baabf0c376dc4carll
1880366d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj
1880466d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj// ATTENTION: This search function assumes vsx_all array is sorted.
1880566d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardjstatic Int findVSXextOpCode(UInt opcode)
1880666d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj{
1880766d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj   Int low, mid, high;
1880866d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj   low = 0;
1880966d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj   high = VSX_ALL_LEN - 1;
1881066d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj   while (low <= high) {
1881166d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj      mid = (low + high)/2;
1881266d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj      if (opcode < vsx_all[mid].opcode)
1881366d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj         high = mid - 1;
1881466d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj      else if (opcode > vsx_all[mid].opcode)
1881566d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj         low = mid + 1;
1881666d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj      else
1881766d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj         return mid;
1881866d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj   }
1881966d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj   return -1;
1882066d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj}
1882166d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj
1882266d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj
1882366d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj/* The full 10-bit extended opcode retrieved via ifieldOPClo10 is
188244aa412af1d8166cc11f39a6e721df49431d23618sewardj * passed, and we then try to match it up with one of the VSX forms
188254aa412af1d8166cc11f39a6e721df49431d23618sewardj * below.
1882666d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj */
1882766d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardjstatic UInt get_VSX60_opc2(UInt opc2_full)
1882866d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj{
1882966d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj#define XX2_MASK 0x000003FE
1883066d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj#define XX3_1_MASK 0x000003FC
1883166d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj#define XX3_2_MASK 0x000001FC
1883266d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj#define XX3_3_MASK 0x0000007C
188334aa412af1d8166cc11f39a6e721df49431d23618sewardj#define XX4_MASK 0x00000018
1883466d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj   Int ret;
1883566d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj   UInt vsxExtOpcode = 0;
1883666d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj
1883766d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj   if (( ret = findVSXextOpCode(opc2_full & XX2_MASK)) >= 0)
1883866d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj      vsxExtOpcode = vsx_all[ret].opcode;
1883966d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj   else if (( ret = findVSXextOpCode(opc2_full & XX3_1_MASK)) >= 0)
1884066d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj      vsxExtOpcode = vsx_all[ret].opcode;
1884166d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj   else if (( ret = findVSXextOpCode(opc2_full & XX3_2_MASK)) >= 0)
1884266d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj      vsxExtOpcode = vsx_all[ret].opcode;
1884366d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj   else if (( ret = findVSXextOpCode(opc2_full & XX3_3_MASK)) >= 0)
1884466d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj      vsxExtOpcode = vsx_all[ret].opcode;
1884566d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj   else if (( ret = findVSXextOpCode(opc2_full & XX4_MASK)) >= 0)
1884666d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj      vsxExtOpcode = vsx_all[ret].opcode;
1884766d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj
1884866d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj   return vsxExtOpcode;
1884966d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj}
18850a982c0503d8c0c6069ae453bfe70657bd2c134aecerion
18851a982c0503d8c0c6069ae453bfe70657bd2c134aecerion/*------------------------------------------------------------*/
18852a982c0503d8c0c6069ae453bfe70657bd2c134aecerion/*--- Disassemble a single instruction                     ---*/
18853a982c0503d8c0c6069ae453bfe70657bd2c134aecerion/*------------------------------------------------------------*/
18854a982c0503d8c0c6069ae453bfe70657bd2c134aecerion
18855a982c0503d8c0c6069ae453bfe70657bd2c134aecerion/* Disassemble a single instruction into IR.  The instruction
188569e6491ab55324b8e45e187b1e1e9632ac3cb3e27sewardj   is located in host memory at &guest_code[delta]. */
188579e6491ab55324b8e45e187b1e1e9632ac3cb3e27sewardj
188589e6491ab55324b8e45e187b1e1e9632ac3cb3e27sewardjstatic
188595b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerionDisResult disInstr_PPC_WRK (
18860beac530a718fcc646bc61fe60a86f599df54e1d7florian             Bool         (*resteerOkFn) ( /*opaque*/void*, Addr ),
18861984d9b164dd17f07e603c41fe1e506e641e57d18sewardj             Bool         resteerCisOk,
18862c716aea1cafe66ee431dc7d6909c98f18788a028sewardj             void*        callback_opaque,
188639e6491ab55324b8e45e187b1e1e9632ac3cb3e27sewardj             Long         delta64,
18864cacba8e675988fbf21b08feea1f317a9c896c053florian             const VexArchInfo* archinfo,
18865cacba8e675988fbf21b08feea1f317a9c896c053florian             const VexAbiInfo*  abiinfo,
18866442e51a26cf3bc7f243167a4ff3fbfb02206f6e6sewardj             Bool         sigill_diag
188679e6491ab55324b8e45e187b1e1e9632ac3cb3e27sewardj          )
18868a982c0503d8c0c6069ae453bfe70657bd2c134aecerion{
188699e6491ab55324b8e45e187b1e1e9632ac3cb3e27sewardj   UChar     opc1;
188709e6491ab55324b8e45e187b1e1e9632ac3cb3e27sewardj   UInt      opc2;
188719e6491ab55324b8e45e187b1e1e9632ac3cb3e27sewardj   DisResult dres;
18872a982c0503d8c0c6069ae453bfe70657bd2c134aecerion   UInt      theInstr;
18873d953ebb9b04cbad6891676df597bf0c542b1ec89cerion   IRType    ty = mode64 ? Ity_I64 : Ity_I32;
188745117ce116f47141cb23d1b49cc826e19323add97sewardj   Bool      allow_F  = False;
188755117ce116f47141cb23d1b49cc826e19323add97sewardj   Bool      allow_V  = False;
188765117ce116f47141cb23d1b49cc826e19323add97sewardj   Bool      allow_FX = False;
188775117ce116f47141cb23d1b49cc826e19323add97sewardj   Bool      allow_GX = False;
188784aa412af1d8166cc11f39a6e721df49431d23618sewardj   Bool      allow_VX = False;  // Equates to "supports Power ISA 2.06
18879c66d6fa5d9397f167b162483cf3419051cc01a80sewardj   Bool      allow_DFP = False;
188800c74bb5aa3240f693df0568d578baabf0c376dc4carll   Bool      allow_isa_2_07 = False;
188815117ce116f47141cb23d1b49cc826e19323add97sewardj   UInt      hwcaps = archinfo->hwcaps;
188825117ce116f47141cb23d1b49cc826e19323add97sewardj   Long      delta;
18883a982c0503d8c0c6069ae453bfe70657bd2c134aecerion
18884059601a7feb5aaf41876db86380679c3b202f5a3sewardj   /* What insn variants are we supporting today? */
188855117ce116f47141cb23d1b49cc826e19323add97sewardj   if (mode64) {
188865117ce116f47141cb23d1b49cc826e19323add97sewardj      allow_F  = True;
188875117ce116f47141cb23d1b49cc826e19323add97sewardj      allow_V  = (0 != (hwcaps & VEX_HWCAPS_PPC64_V));
188885117ce116f47141cb23d1b49cc826e19323add97sewardj      allow_FX = (0 != (hwcaps & VEX_HWCAPS_PPC64_FX));
188895117ce116f47141cb23d1b49cc826e19323add97sewardj      allow_GX = (0 != (hwcaps & VEX_HWCAPS_PPC64_GX));
1889066d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj      allow_VX = (0 != (hwcaps & VEX_HWCAPS_PPC64_VX));
18891c66d6fa5d9397f167b162483cf3419051cc01a80sewardj      allow_DFP = (0 != (hwcaps & VEX_HWCAPS_PPC64_DFP));
188920c74bb5aa3240f693df0568d578baabf0c376dc4carll      allow_isa_2_07 = (0 != (hwcaps & VEX_HWCAPS_PPC64_ISA2_07));
188935117ce116f47141cb23d1b49cc826e19323add97sewardj   } else {
188945117ce116f47141cb23d1b49cc826e19323add97sewardj      allow_F  = (0 != (hwcaps & VEX_HWCAPS_PPC32_F));
188955117ce116f47141cb23d1b49cc826e19323add97sewardj      allow_V  = (0 != (hwcaps & VEX_HWCAPS_PPC32_V));
188965117ce116f47141cb23d1b49cc826e19323add97sewardj      allow_FX = (0 != (hwcaps & VEX_HWCAPS_PPC32_FX));
188975117ce116f47141cb23d1b49cc826e19323add97sewardj      allow_GX = (0 != (hwcaps & VEX_HWCAPS_PPC32_GX));
1889866d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj      allow_VX = (0 != (hwcaps & VEX_HWCAPS_PPC32_VX));
18899c66d6fa5d9397f167b162483cf3419051cc01a80sewardj      allow_DFP = (0 != (hwcaps & VEX_HWCAPS_PPC32_DFP));
189000c74bb5aa3240f693df0568d578baabf0c376dc4carll      allow_isa_2_07 = (0 != (hwcaps & VEX_HWCAPS_PPC32_ISA2_07));
189015117ce116f47141cb23d1b49cc826e19323add97sewardj   }
18902059601a7feb5aaf41876db86380679c3b202f5a3sewardj
189039e6491ab55324b8e45e187b1e1e9632ac3cb3e27sewardj   /* The running delta */
189045117ce116f47141cb23d1b49cc826e19323add97sewardj   delta = (Long)mkSzAddr(ty, (ULong)delta64);
189059e6491ab55324b8e45e187b1e1e9632ac3cb3e27sewardj
189069e6491ab55324b8e45e187b1e1e9632ac3cb3e27sewardj   /* Set result defaults. */
189073dee849ec7c38746749065e67dc53b75daa7617dsewardj   dres.whatNext    = Dis_Continue;
189083dee849ec7c38746749065e67dc53b75daa7617dsewardj   dres.len         = 0;
189093dee849ec7c38746749065e67dc53b75daa7617dsewardj   dres.continueAt  = 0;
189103dee849ec7c38746749065e67dc53b75daa7617dsewardj   dres.jk_StopHere = Ijk_INVALID;
18911a982c0503d8c0c6069ae453bfe70657bd2c134aecerion
18912a982c0503d8c0c6069ae453bfe70657bd2c134aecerion   /* At least this is simple on PPC32: insns are all 4 bytes long, and
18913a982c0503d8c0c6069ae453bfe70657bd2c134aecerion      4-aligned.  So just fish the whole thing out of memory right now
18914a982c0503d8c0c6069ae453bfe70657bd2c134aecerion      and have done. */
189158462d113e3efeacceb304222dada8d85f748295aflorian   theInstr = getUIntPPCendianly( &guest_code[delta] );
18916a982c0503d8c0c6069ae453bfe70657bd2c134aecerion
189175117ce116f47141cb23d1b49cc826e19323add97sewardj   if (0) vex_printf("insn: 0x%x\n", theInstr);
18918f0de28cf1a762b0d6f74c93d3532c89a230673bbcerion
189191eb7e6b8f521143c9c4971b2cea36ade611c5da9sewardj   DIP("\t0x%llx:  ", (ULong)guest_CIA_curr_instr);
18920b51f0f4f33256638ed953156a2635aa739b232f1sewardj
18921ce02aa77bc02dbe225a068df0fb6b31faddedcdfsewardj   /* Spot "Special" instructions (see comment at top of file). */
189221eb7e6b8f521143c9c4971b2cea36ade611c5da9sewardj   {
189238462d113e3efeacceb304222dada8d85f748295aflorian      const UChar* code = guest_code + delta;
189241eb7e6b8f521143c9c4971b2cea36ade611c5da9sewardj      /* Spot the 16-byte preamble:
189251eb7e6b8f521143c9c4971b2cea36ade611c5da9sewardj         32-bit mode:
189262171afd42a0168b49b06dbe723b606046e902099sewardj            5400183E  rlwinm 0,0,3,0,31
189272171afd42a0168b49b06dbe723b606046e902099sewardj            5400683E  rlwinm 0,0,13,0,31
189282171afd42a0168b49b06dbe723b606046e902099sewardj            5400E83E  rlwinm 0,0,29,0,31
189292171afd42a0168b49b06dbe723b606046e902099sewardj            5400983E  rlwinm 0,0,19,0,31
189301eb7e6b8f521143c9c4971b2cea36ade611c5da9sewardj         64-bit mode:
189311eb7e6b8f521143c9c4971b2cea36ade611c5da9sewardj            78001800  rotldi 0,0,3
189321eb7e6b8f521143c9c4971b2cea36ade611c5da9sewardj            78006800  rotldi 0,0,13
189331eb7e6b8f521143c9c4971b2cea36ade611c5da9sewardj            7800E802  rotldi 0,0,61
189341eb7e6b8f521143c9c4971b2cea36ade611c5da9sewardj            78009802  rotldi 0,0,51
18935a982c0503d8c0c6069ae453bfe70657bd2c134aecerion      */
189362171afd42a0168b49b06dbe723b606046e902099sewardj      UInt word1 = mode64 ? 0x78001800 : 0x5400183E;
189372171afd42a0168b49b06dbe723b606046e902099sewardj      UInt word2 = mode64 ? 0x78006800 : 0x5400683E;
189382171afd42a0168b49b06dbe723b606046e902099sewardj      UInt word3 = mode64 ? 0x7800E802 : 0x5400E83E;
189392171afd42a0168b49b06dbe723b606046e902099sewardj      UInt word4 = mode64 ? 0x78009802 : 0x5400983E;
18940d2c19b4f340bd22b93538a25ca20e43a0d04dc09mjw      Bool is_special_preamble = False;
189411f5fe1fc3a37ca729925e8eec25aa1025b4a6cdbcarll      if (getUIntPPCendianly(code+ 0) == word1 &&
189421f5fe1fc3a37ca729925e8eec25aa1025b4a6cdbcarll          getUIntPPCendianly(code+ 4) == word2 &&
189431f5fe1fc3a37ca729925e8eec25aa1025b4a6cdbcarll          getUIntPPCendianly(code+ 8) == word3 &&
189441f5fe1fc3a37ca729925e8eec25aa1025b4a6cdbcarll          getUIntPPCendianly(code+12) == word4) {
18945d2c19b4f340bd22b93538a25ca20e43a0d04dc09mjw         is_special_preamble = True;
18946d2c19b4f340bd22b93538a25ca20e43a0d04dc09mjw      } else if (! mode64 &&
18947d2c19b4f340bd22b93538a25ca20e43a0d04dc09mjw                 getUIntPPCendianly(code+ 0) == 0x54001800 &&
18948d2c19b4f340bd22b93538a25ca20e43a0d04dc09mjw                 getUIntPPCendianly(code+ 4) == 0x54006800 &&
18949d2c19b4f340bd22b93538a25ca20e43a0d04dc09mjw                 getUIntPPCendianly(code+ 8) == 0x5400E800 &&
18950d2c19b4f340bd22b93538a25ca20e43a0d04dc09mjw                 getUIntPPCendianly(code+12) == 0x54009800) {
18951d2c19b4f340bd22b93538a25ca20e43a0d04dc09mjw         static Bool reported = False;
18952d2c19b4f340bd22b93538a25ca20e43a0d04dc09mjw         if (!reported) {
18953d2c19b4f340bd22b93538a25ca20e43a0d04dc09mjw            vex_printf("disInstr(ppc): old ppc32 instruction magic detected. Code might clobber r0.\n");
18954d2c19b4f340bd22b93538a25ca20e43a0d04dc09mjw            vex_printf("disInstr(ppc): source needs to be recompiled against latest valgrind.h.\n");
18955d2c19b4f340bd22b93538a25ca20e43a0d04dc09mjw            reported = True;
18956d2c19b4f340bd22b93538a25ca20e43a0d04dc09mjw         }
18957d2c19b4f340bd22b93538a25ca20e43a0d04dc09mjw         is_special_preamble = True;
18958d2c19b4f340bd22b93538a25ca20e43a0d04dc09mjw      }
18959d2c19b4f340bd22b93538a25ca20e43a0d04dc09mjw      if (is_special_preamble) {
18960ce02aa77bc02dbe225a068df0fb6b31faddedcdfsewardj         /* Got a "Special" instruction preamble.  Which one is it? */
189611f5fe1fc3a37ca729925e8eec25aa1025b4a6cdbcarll         if (getUIntPPCendianly(code+16) == 0x7C210B78 /* or 1,1,1 */) {
18962ce02aa77bc02dbe225a068df0fb6b31faddedcdfsewardj            /* %R3 = client_request ( %R4 ) */
18963ce02aa77bc02dbe225a068df0fb6b31faddedcdfsewardj            DIP("r3 = client_request ( %%r4 )\n");
18964ce02aa77bc02dbe225a068df0fb6b31faddedcdfsewardj            delta += 20;
189653dee849ec7c38746749065e67dc53b75daa7617dsewardj            putGST( PPC_GST_CIA, mkSzImm( ty, guest_CIA_bbstart + delta ));
189663dee849ec7c38746749065e67dc53b75daa7617dsewardj            dres.jk_StopHere = Ijk_ClientReq;
189673dee849ec7c38746749065e67dc53b75daa7617dsewardj            dres.whatNext    = Dis_StopHere;
18968ce02aa77bc02dbe225a068df0fb6b31faddedcdfsewardj            goto decode_success;
18969ce02aa77bc02dbe225a068df0fb6b31faddedcdfsewardj         }
18970ce02aa77bc02dbe225a068df0fb6b31faddedcdfsewardj         else
189711f5fe1fc3a37ca729925e8eec25aa1025b4a6cdbcarll         if (getUIntPPCendianly(code+16) == 0x7C421378 /* or 2,2,2 */) {
18972ce02aa77bc02dbe225a068df0fb6b31faddedcdfsewardj            /* %R3 = guest_NRADDR */
18973ce02aa77bc02dbe225a068df0fb6b31faddedcdfsewardj            DIP("r3 = guest_NRADDR\n");
18974ce02aa77bc02dbe225a068df0fb6b31faddedcdfsewardj            delta += 20;
18975ce02aa77bc02dbe225a068df0fb6b31faddedcdfsewardj            dres.len = 20;
18976ce02aa77bc02dbe225a068df0fb6b31faddedcdfsewardj            putIReg(3, IRExpr_Get( OFFB_NRADDR, ty ));
18977ce02aa77bc02dbe225a068df0fb6b31faddedcdfsewardj            goto decode_success;
18978ce02aa77bc02dbe225a068df0fb6b31faddedcdfsewardj         }
18979ce02aa77bc02dbe225a068df0fb6b31faddedcdfsewardj         else
189801f5fe1fc3a37ca729925e8eec25aa1025b4a6cdbcarll         if (getUIntPPCendianly(code+16) == 0x7C631B78 /* or 3,3,3 */) {
18981ce02aa77bc02dbe225a068df0fb6b31faddedcdfsewardj            delta += 20;
189821f5fe1fc3a37ca729925e8eec25aa1025b4a6cdbcarll            if (host_endness == VexEndnessLE) {
189831f5fe1fc3a37ca729925e8eec25aa1025b4a6cdbcarll                /*  branch-and-link-to-noredir %R12 */
189841f5fe1fc3a37ca729925e8eec25aa1025b4a6cdbcarll                DIP("branch-and-link-to-noredir r12\n");
189851f5fe1fc3a37ca729925e8eec25aa1025b4a6cdbcarll                putGST( PPC_GST_LR,
189861f5fe1fc3a37ca729925e8eec25aa1025b4a6cdbcarll                        mkSzImm(ty, guest_CIA_bbstart + (Long)delta) );
189871f5fe1fc3a37ca729925e8eec25aa1025b4a6cdbcarll                putGST( PPC_GST_CIA, getIReg(12));
189881f5fe1fc3a37ca729925e8eec25aa1025b4a6cdbcarll            } else {
189891f5fe1fc3a37ca729925e8eec25aa1025b4a6cdbcarll                /*  branch-and-link-to-noredir %R11 */
189901f5fe1fc3a37ca729925e8eec25aa1025b4a6cdbcarll                DIP("branch-and-link-to-noredir r11\n");
189911f5fe1fc3a37ca729925e8eec25aa1025b4a6cdbcarll                putGST( PPC_GST_LR,
189921f5fe1fc3a37ca729925e8eec25aa1025b4a6cdbcarll                        mkSzImm(ty, guest_CIA_bbstart + (Long)delta) );
189931f5fe1fc3a37ca729925e8eec25aa1025b4a6cdbcarll                putGST( PPC_GST_CIA, getIReg(11));
189941f5fe1fc3a37ca729925e8eec25aa1025b4a6cdbcarll            }
189953dee849ec7c38746749065e67dc53b75daa7617dsewardj            dres.jk_StopHere = Ijk_NoRedir;
189963dee849ec7c38746749065e67dc53b75daa7617dsewardj            dres.whatNext    = Dis_StopHere;
18997ce02aa77bc02dbe225a068df0fb6b31faddedcdfsewardj            goto decode_success;
18998ce02aa77bc02dbe225a068df0fb6b31faddedcdfsewardj         }
189995ff11ddafe3e0080711657a1cf581e1a64dbf117sewardj         else
190001f5fe1fc3a37ca729925e8eec25aa1025b4a6cdbcarll         if (getUIntPPCendianly(code+16) == 0x7C842378 /* or 4,4,4 */) {
190015ff11ddafe3e0080711657a1cf581e1a64dbf117sewardj            /* %R3 = guest_NRADDR_GPR2 */
190025ff11ddafe3e0080711657a1cf581e1a64dbf117sewardj            DIP("r3 = guest_NRADDR_GPR2\n");
190035ff11ddafe3e0080711657a1cf581e1a64dbf117sewardj            delta += 20;
190045ff11ddafe3e0080711657a1cf581e1a64dbf117sewardj            dres.len = 20;
19005aca070a5b3418a6a9b01e3c57a7eb0fbb5050908sewardj            putIReg(3, IRExpr_Get( OFFB_NRADDR_GPR2, ty ));
190065ff11ddafe3e0080711657a1cf581e1a64dbf117sewardj            goto decode_success;
190075ff11ddafe3e0080711657a1cf581e1a64dbf117sewardj         }
190082245ce9e834193d49261b8a433b4a0bd128c878eflorian         else
190091f5fe1fc3a37ca729925e8eec25aa1025b4a6cdbcarll         if (getUIntPPCendianly(code+16) == 0x7CA52B78 /* or 5,5,5 */) {
190102245ce9e834193d49261b8a433b4a0bd128c878eflorian            DIP("IR injection\n");
190111f5fe1fc3a37ca729925e8eec25aa1025b4a6cdbcarll            if (host_endness == VexEndnessBE)
190121f5fe1fc3a37ca729925e8eec25aa1025b4a6cdbcarll               vex_inject_ir(irsb, Iend_BE);
190131f5fe1fc3a37ca729925e8eec25aa1025b4a6cdbcarll            else
190141f5fe1fc3a37ca729925e8eec25aa1025b4a6cdbcarll               vex_inject_ir(irsb, Iend_LE);
190152245ce9e834193d49261b8a433b4a0bd128c878eflorian
190162245ce9e834193d49261b8a433b4a0bd128c878eflorian            delta += 20;
190172245ce9e834193d49261b8a433b4a0bd128c878eflorian            dres.len = 20;
190182245ce9e834193d49261b8a433b4a0bd128c878eflorian
190192245ce9e834193d49261b8a433b4a0bd128c878eflorian            // Invalidate the current insn. The reason is that the IRop we're
190202245ce9e834193d49261b8a433b4a0bd128c878eflorian            // injecting here can change. In which case the translation has to
190212245ce9e834193d49261b8a433b4a0bd128c878eflorian            // be redone. For ease of handling, we simply invalidate all the
190222245ce9e834193d49261b8a433b4a0bd128c878eflorian            // time.
190239e23873d8f6365b9bf64b767b76ff973c014d693florian
1902405f5e0172384dd2983fb16fbb7deebd74d71cd35sewardj            stmt(IRStmt_Put(OFFB_CMSTART, mkSzImm(ty, guest_CIA_curr_instr)));
1902505f5e0172384dd2983fb16fbb7deebd74d71cd35sewardj            stmt(IRStmt_Put(OFFB_CMLEN,   mkSzImm(ty, 20)));
190262245ce9e834193d49261b8a433b4a0bd128c878eflorian
190272245ce9e834193d49261b8a433b4a0bd128c878eflorian            putGST( PPC_GST_CIA, mkSzImm( ty, guest_CIA_bbstart + delta ));
190282245ce9e834193d49261b8a433b4a0bd128c878eflorian            dres.whatNext    = Dis_StopHere;
1902905f5e0172384dd2983fb16fbb7deebd74d71cd35sewardj            dres.jk_StopHere = Ijk_InvalICache;
190302245ce9e834193d49261b8a433b4a0bd128c878eflorian            goto decode_success;
190312245ce9e834193d49261b8a433b4a0bd128c878eflorian         }
19032ce02aa77bc02dbe225a068df0fb6b31faddedcdfsewardj         /* We don't know what it is.  Set opc1/opc2 so decode_failure
19033ce02aa77bc02dbe225a068df0fb6b31faddedcdfsewardj            can print the insn following the Special-insn preamble. */
190341f5fe1fc3a37ca729925e8eec25aa1025b4a6cdbcarll         theInstr = getUIntPPCendianly(code+16);
19035ce02aa77bc02dbe225a068df0fb6b31faddedcdfsewardj         opc1     = ifieldOPC(theInstr);
19036ce02aa77bc02dbe225a068df0fb6b31faddedcdfsewardj         opc2     = ifieldOPClo10(theInstr);
19037ce02aa77bc02dbe225a068df0fb6b31faddedcdfsewardj         goto decode_failure;
19038ce02aa77bc02dbe225a068df0fb6b31faddedcdfsewardj         /*NOTREACHED*/
19039a982c0503d8c0c6069ae453bfe70657bd2c134aecerion      }
19040a982c0503d8c0c6069ae453bfe70657bd2c134aecerion   }
19041a982c0503d8c0c6069ae453bfe70657bd2c134aecerion
1904276de5cf615380b23b4b5bcced6541233cd4a93a0cerion   opc1 = ifieldOPC(theInstr);
19043b51f0f4f33256638ed953156a2635aa739b232f1sewardj   opc2 = ifieldOPClo10(theInstr);
19044a982c0503d8c0c6069ae453bfe70657bd2c134aecerion
19045a982c0503d8c0c6069ae453bfe70657bd2c134aecerion   // Note: all 'reserved' bits must be cleared, else invalid
19046a982c0503d8c0c6069ae453bfe70657bd2c134aecerion   switch (opc1) {
19047a982c0503d8c0c6069ae453bfe70657bd2c134aecerion
19048a982c0503d8c0c6069ae453bfe70657bd2c134aecerion   /* Integer Arithmetic Instructions */
19049a982c0503d8c0c6069ae453bfe70657bd2c134aecerion   case 0x0C: case 0x0D: case 0x0E:  // addic, addic., addi
19050a982c0503d8c0c6069ae453bfe70657bd2c134aecerion   case 0x0F: case 0x07: case 0x08:  // addis, mulli,  subfic
19051a982c0503d8c0c6069ae453bfe70657bd2c134aecerion      if (dis_int_arith( theInstr )) goto decode_success;
19052a982c0503d8c0c6069ae453bfe70657bd2c134aecerion      goto decode_failure;
19053a982c0503d8c0c6069ae453bfe70657bd2c134aecerion
19054a982c0503d8c0c6069ae453bfe70657bd2c134aecerion   /* Integer Compare Instructions */
19055a982c0503d8c0c6069ae453bfe70657bd2c134aecerion   case 0x0B: case 0x0A: // cmpi, cmpli
19056a982c0503d8c0c6069ae453bfe70657bd2c134aecerion      if (dis_int_cmp( theInstr )) goto decode_success;
19057a982c0503d8c0c6069ae453bfe70657bd2c134aecerion      goto decode_failure;
19058a982c0503d8c0c6069ae453bfe70657bd2c134aecerion
19059a982c0503d8c0c6069ae453bfe70657bd2c134aecerion   /* Integer Logical Instructions */
19060a982c0503d8c0c6069ae453bfe70657bd2c134aecerion   case 0x1C: case 0x1D: case 0x18: // andi., andis., ori
19061a982c0503d8c0c6069ae453bfe70657bd2c134aecerion   case 0x19: case 0x1A: case 0x1B: // oris,  xori,   xoris
19062a982c0503d8c0c6069ae453bfe70657bd2c134aecerion      if (dis_int_logic( theInstr )) goto decode_success;
19063a982c0503d8c0c6069ae453bfe70657bd2c134aecerion      goto decode_failure;
19064a982c0503d8c0c6069ae453bfe70657bd2c134aecerion
19065a982c0503d8c0c6069ae453bfe70657bd2c134aecerion   /* Integer Rotate Instructions */
19066a982c0503d8c0c6069ae453bfe70657bd2c134aecerion   case 0x14: case 0x15:  case 0x17: // rlwimi, rlwinm, rlwnm
19067a982c0503d8c0c6069ae453bfe70657bd2c134aecerion      if (dis_int_rot( theInstr )) goto decode_success;
19068a982c0503d8c0c6069ae453bfe70657bd2c134aecerion      goto decode_failure;
19069a982c0503d8c0c6069ae453bfe70657bd2c134aecerion
19070f0de28cf1a762b0d6f74c93d3532c89a230673bbcerion   /* 64bit Integer Rotate Instructions */
19071f0de28cf1a762b0d6f74c93d3532c89a230673bbcerion   case 0x1E: // rldcl, rldcr, rldic, rldicl, rldicr, rldimi
19072bb3f40144f5e72dfbba740d4b2f090b4a91c3876carll      if (!mode64) goto decode_failure;
19073f0de28cf1a762b0d6f74c93d3532c89a230673bbcerion      if (dis_int_rot( theInstr )) goto decode_success;
19074f0de28cf1a762b0d6f74c93d3532c89a230673bbcerion      goto decode_failure;
19075f0de28cf1a762b0d6f74c93d3532c89a230673bbcerion
19076a982c0503d8c0c6069ae453bfe70657bd2c134aecerion   /* Integer Load Instructions */
19077a982c0503d8c0c6069ae453bfe70657bd2c134aecerion   case 0x22: case 0x23: case 0x2A: // lbz,  lbzu, lha
19078a982c0503d8c0c6069ae453bfe70657bd2c134aecerion   case 0x2B: case 0x28: case 0x29: // lhau, lhz,  lhzu
19079a982c0503d8c0c6069ae453bfe70657bd2c134aecerion   case 0x20: case 0x21:            // lwz,  lwzu
19080a982c0503d8c0c6069ae453bfe70657bd2c134aecerion      if (dis_int_load( theInstr )) goto decode_success;
19081a982c0503d8c0c6069ae453bfe70657bd2c134aecerion      goto decode_failure;
19082a982c0503d8c0c6069ae453bfe70657bd2c134aecerion
19083a982c0503d8c0c6069ae453bfe70657bd2c134aecerion   /* Integer Store Instructions */
19084a982c0503d8c0c6069ae453bfe70657bd2c134aecerion   case 0x26: case 0x27: case 0x2C: // stb,  stbu, sth
19085a982c0503d8c0c6069ae453bfe70657bd2c134aecerion   case 0x2D: case 0x24: case 0x25: // sthu, stw,  stwu
19086dd40fdf58cc8a6fe9466c4f00bdfc9fe9bf00449sewardj      if (dis_int_store( theInstr, abiinfo )) goto decode_success;
19087a982c0503d8c0c6069ae453bfe70657bd2c134aecerion      goto decode_failure;
19088a982c0503d8c0c6069ae453bfe70657bd2c134aecerion
190897787af415a9104b601c2f0ce5b56749e4fd86691sewardj   /* Integer Load and Store Multiple Instructions */
190907787af415a9104b601c2f0ce5b56749e4fd86691sewardj   case 0x2E: case 0x2F: // lmw, stmw
190917787af415a9104b601c2f0ce5b56749e4fd86691sewardj      if (dis_int_ldst_mult( theInstr )) goto decode_success;
190927787af415a9104b601c2f0ce5b56749e4fd86691sewardj      goto decode_failure;
19093a982c0503d8c0c6069ae453bfe70657bd2c134aecerion
19094a982c0503d8c0c6069ae453bfe70657bd2c134aecerion   /* Branch Instructions */
19095a982c0503d8c0c6069ae453bfe70657bd2c134aecerion   case 0x12: case 0x10: // b, bc
19096dd40fdf58cc8a6fe9466c4f00bdfc9fe9bf00449sewardj      if (dis_branch(theInstr, abiinfo, &dres,
19097aca070a5b3418a6a9b01e3c57a7eb0fbb5050908sewardj                               resteerOkFn, callback_opaque))
19098c716aea1cafe66ee431dc7d6909c98f18788a028sewardj         goto decode_success;
19099a982c0503d8c0c6069ae453bfe70657bd2c134aecerion      goto decode_failure;
19100a982c0503d8c0c6069ae453bfe70657bd2c134aecerion
19101a982c0503d8c0c6069ae453bfe70657bd2c134aecerion   /* System Linkage Instructions */
19102a982c0503d8c0c6069ae453bfe70657bd2c134aecerion   case 0x11: // sc
19103dd40fdf58cc8a6fe9466c4f00bdfc9fe9bf00449sewardj      if (dis_syslink(theInstr, abiinfo, &dres)) goto decode_success;
19104a982c0503d8c0c6069ae453bfe70657bd2c134aecerion      goto decode_failure;
19105a982c0503d8c0c6069ae453bfe70657bd2c134aecerion
19106334870db22c2eadcaaa48ef8e47337134d150efdsewardj   /* Trap Instructions */
19107bb3f40144f5e72dfbba740d4b2f090b4a91c3876carll   case 0x02:    // tdi
19108bb3f40144f5e72dfbba740d4b2f090b4a91c3876carll      if (!mode64) goto decode_failure;
19109bb3f40144f5e72dfbba740d4b2f090b4a91c3876carll      if (dis_trapi(theInstr, &dres)) goto decode_success;
19110bb3f40144f5e72dfbba740d4b2f090b4a91c3876carll      goto decode_failure;
19111bb3f40144f5e72dfbba740d4b2f090b4a91c3876carll
19112bb3f40144f5e72dfbba740d4b2f090b4a91c3876carll   case 0x03:   // twi
19113334870db22c2eadcaaa48ef8e47337134d150efdsewardj      if (dis_trapi(theInstr, &dres)) goto decode_success;
19114334870db22c2eadcaaa48ef8e47337134d150efdsewardj      goto decode_failure;
19115a982c0503d8c0c6069ae453bfe70657bd2c134aecerion
19116a982c0503d8c0c6069ae453bfe70657bd2c134aecerion   /* Floating Point Load Instructions */
19117a982c0503d8c0c6069ae453bfe70657bd2c134aecerion   case 0x30: case 0x31: case 0x32: // lfs, lfsu, lfd
19118a982c0503d8c0c6069ae453bfe70657bd2c134aecerion   case 0x33:                       // lfdu
191195117ce116f47141cb23d1b49cc826e19323add97sewardj      if (!allow_F) goto decode_noF;
19120a982c0503d8c0c6069ae453bfe70657bd2c134aecerion      if (dis_fp_load( theInstr )) goto decode_success;
19121a982c0503d8c0c6069ae453bfe70657bd2c134aecerion      goto decode_failure;
19122a982c0503d8c0c6069ae453bfe70657bd2c134aecerion
19123a982c0503d8c0c6069ae453bfe70657bd2c134aecerion   /* Floating Point Store Instructions */
19124a982c0503d8c0c6069ae453bfe70657bd2c134aecerion   case 0x34: case 0x35: case 0x36: // stfsx, stfsux, stfdx
19125a982c0503d8c0c6069ae453bfe70657bd2c134aecerion   case 0x37:                       // stfdux
191265117ce116f47141cb23d1b49cc826e19323add97sewardj      if (!allow_F) goto decode_noF;
19127a982c0503d8c0c6069ae453bfe70657bd2c134aecerion      if (dis_fp_store( theInstr )) goto decode_success;
19128a982c0503d8c0c6069ae453bfe70657bd2c134aecerion      goto decode_failure;
19129a982c0503d8c0c6069ae453bfe70657bd2c134aecerion
191307e84630580f89c1022dde97007bffbf6aef81814sewardj      /* Floating Point Load Double Pair Instructions */
191317e84630580f89c1022dde97007bffbf6aef81814sewardj   case 0x39: case 0x3D:
191327e84630580f89c1022dde97007bffbf6aef81814sewardj      if (!allow_F) goto decode_noF;
191337e84630580f89c1022dde97007bffbf6aef81814sewardj      if (dis_fp_pair( theInstr )) goto decode_success;
191347e84630580f89c1022dde97007bffbf6aef81814sewardj      goto decode_failure;
191357e84630580f89c1022dde97007bffbf6aef81814sewardj
1913678850ae9874a90ea625fcee1fd4c359375b7b538carll   /* 128-bit Integer Load */
1913778850ae9874a90ea625fcee1fd4c359375b7b538carll   case 0x38:  // lq
1913878850ae9874a90ea625fcee1fd4c359375b7b538carll      if (dis_int_load( theInstr )) goto decode_success;
1913978850ae9874a90ea625fcee1fd4c359375b7b538carll      goto decode_failure;
1914078850ae9874a90ea625fcee1fd4c359375b7b538carll
19141f0de28cf1a762b0d6f74c93d3532c89a230673bbcerion   /* 64bit Integer Loads */
19142f0de28cf1a762b0d6f74c93d3532c89a230673bbcerion   case 0x3A:  // ld, ldu, lwa
19143f0de28cf1a762b0d6f74c93d3532c89a230673bbcerion      if (!mode64) goto decode_failure;
19144f0de28cf1a762b0d6f74c93d3532c89a230673bbcerion      if (dis_int_load( theInstr )) goto decode_success;
19145f0de28cf1a762b0d6f74c93d3532c89a230673bbcerion      goto decode_failure;
19146f0de28cf1a762b0d6f74c93d3532c89a230673bbcerion
19147e14bb9f862843c6b804097c124961b5567ded4f1sewardj   case 0x3B:
191485117ce116f47141cb23d1b49cc826e19323add97sewardj      if (!allow_F) goto decode_noF;
1914966d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj      opc2 = ifieldOPClo10(theInstr);
19150c6bbd470e9bd9898b84959227a406d3972d95f3bsewardj
1915166d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj      switch (opc2) {
19152c6bbd470e9bd9898b84959227a406d3972d95f3bsewardj         case 0x2:    // dadd - DFP Add
19153c6bbd470e9bd9898b84959227a406d3972d95f3bsewardj         case 0x202:  // dsub - DFP Subtract
19154c6bbd470e9bd9898b84959227a406d3972d95f3bsewardj         case 0x22:   // dmul - DFP Mult
19155c6bbd470e9bd9898b84959227a406d3972d95f3bsewardj         case 0x222:  // ddiv - DFP Divide
19156c66d6fa5d9397f167b162483cf3419051cc01a80sewardj            if (!allow_DFP) goto decode_noDFP;
19157c6bbd470e9bd9898b84959227a406d3972d95f3bsewardj            if (dis_dfp_arith( theInstr ))
19158c6bbd470e9bd9898b84959227a406d3972d95f3bsewardj               goto decode_success;
19159cdc376dcb5a4560b0a35d4abcb2146c499756f0dsewardj         case 0x82:   // dcmpo, DFP comparison ordered instruction
19160cdc376dcb5a4560b0a35d4abcb2146c499756f0dsewardj         case 0x282:  // dcmpu, DFP comparison unordered instruction
191610c4e9e8eef3824b085973cd6e2b1b39a1fd6062ecarll            if (!allow_DFP) goto decode_noDFP;
19162cdc376dcb5a4560b0a35d4abcb2146c499756f0dsewardj            if (dis_dfp_compare( theInstr ) )
19163cdc376dcb5a4560b0a35d4abcb2146c499756f0dsewardj               goto decode_success;
19164cdc376dcb5a4560b0a35d4abcb2146c499756f0dsewardj            goto decode_failure;
1916526217b09205cc1801b842ba5ba8f0d83aabca1b4sewardj         case 0x102: // dctdp  - DFP convert to DFP long
1916626217b09205cc1801b842ba5ba8f0d83aabca1b4sewardj         case 0x302: // drsp   - DFP round to dfp short
1916726217b09205cc1801b842ba5ba8f0d83aabca1b4sewardj         case 0x122: // dctfix - DFP convert to fixed
191680c4e9e8eef3824b085973cd6e2b1b39a1fd6062ecarll            if (!allow_DFP) goto decode_noDFP;
1916926217b09205cc1801b842ba5ba8f0d83aabca1b4sewardj            if (dis_dfp_fmt_conv( theInstr ))
1917026217b09205cc1801b842ba5ba8f0d83aabca1b4sewardj               goto decode_success;
1917126217b09205cc1801b842ba5ba8f0d83aabca1b4sewardj            goto decode_failure;
1917226217b09205cc1801b842ba5ba8f0d83aabca1b4sewardj         case 0x322: // POWER 7 inst, dcffix - DFP convert from fixed
1917326217b09205cc1801b842ba5ba8f0d83aabca1b4sewardj            if (!allow_VX)
1917426217b09205cc1801b842ba5ba8f0d83aabca1b4sewardj               goto decode_failure;
1917526217b09205cc1801b842ba5ba8f0d83aabca1b4sewardj            if (dis_dfp_fmt_conv( theInstr ))
1917626217b09205cc1801b842ba5ba8f0d83aabca1b4sewardj               goto decode_success;
1917726217b09205cc1801b842ba5ba8f0d83aabca1b4sewardj            goto decode_failure;
191784c96e61dd85c172b999d6afc88ce6640aeba9962sewardj         case 0x2A2: // dtstsf - DFP number of significant digits
191790c4e9e8eef3824b085973cd6e2b1b39a1fd6062ecarll            if (!allow_DFP) goto decode_noDFP;
191804c96e61dd85c172b999d6afc88ce6640aeba9962sewardj            if (dis_dfp_significant_digits(theInstr))
191814c96e61dd85c172b999d6afc88ce6640aeba9962sewardj               goto decode_success;
191824c96e61dd85c172b999d6afc88ce6640aeba9962sewardj            goto decode_failure;
191834c96e61dd85c172b999d6afc88ce6640aeba9962sewardj         case 0x142: // ddedpd   DFP Decode DPD to BCD
191844c96e61dd85c172b999d6afc88ce6640aeba9962sewardj         case 0x342: // denbcd   DFP Encode BCD to DPD
191850c4e9e8eef3824b085973cd6e2b1b39a1fd6062ecarll            if (!allow_DFP) goto decode_noDFP;
191864c96e61dd85c172b999d6afc88ce6640aeba9962sewardj            if (dis_dfp_bcd(theInstr))
191874c96e61dd85c172b999d6afc88ce6640aeba9962sewardj               goto decode_success;
191884c96e61dd85c172b999d6afc88ce6640aeba9962sewardj            goto decode_failure;
19189cdc376dcb5a4560b0a35d4abcb2146c499756f0dsewardj         case 0x162:  // dxex - Extract exponent
19190cdc376dcb5a4560b0a35d4abcb2146c499756f0dsewardj         case 0x362:  // diex - Insert exponent
191910c4e9e8eef3824b085973cd6e2b1b39a1fd6062ecarll            if (!allow_DFP) goto decode_noDFP;
19192cdc376dcb5a4560b0a35d4abcb2146c499756f0dsewardj            if (dis_dfp_extract_insert( theInstr ) )
19193cdc376dcb5a4560b0a35d4abcb2146c499756f0dsewardj               goto decode_success;
19194cdc376dcb5a4560b0a35d4abcb2146c499756f0dsewardj            goto decode_failure;
191954aa412af1d8166cc11f39a6e721df49431d23618sewardj         case 0x3CE: // fcfidus (implemented as native insn)
1919666d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj            if (!allow_VX)
1919766d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj               goto decode_noVX;
1919866d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj            if (dis_fp_round( theInstr ))
1919966d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj               goto decode_success;
1920066d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj            goto decode_failure;
1920166d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj         case 0x34E: // fcfids
1920266d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj            if (dis_fp_round( theInstr ))
1920366d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj               goto decode_success;
1920466d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj            goto decode_failure;
1920566d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj      }
1920666d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj
1920726217b09205cc1801b842ba5ba8f0d83aabca1b4sewardj      opc2 = ifieldOPClo9( theInstr );
1920826217b09205cc1801b842ba5ba8f0d83aabca1b4sewardj      switch (opc2) {
1920926217b09205cc1801b842ba5ba8f0d83aabca1b4sewardj      case 0x42: // dscli, DFP shift left
1921026217b09205cc1801b842ba5ba8f0d83aabca1b4sewardj      case 0x62: // dscri, DFP shift right
192110c4e9e8eef3824b085973cd6e2b1b39a1fd6062ecarll         if (!allow_DFP) goto decode_noDFP;
1921226217b09205cc1801b842ba5ba8f0d83aabca1b4sewardj         if (dis_dfp_shift( theInstr ))
1921326217b09205cc1801b842ba5ba8f0d83aabca1b4sewardj            goto decode_success;
1921426217b09205cc1801b842ba5ba8f0d83aabca1b4sewardj         goto decode_failure;
192155eff1c502e995d1f9668cc9def72d5db59f21b13sewardj      case 0xc2:  // dtstdc, DFP test data class
192165eff1c502e995d1f9668cc9def72d5db59f21b13sewardj      case 0xe2:  // dtstdg, DFP test data group
192170c4e9e8eef3824b085973cd6e2b1b39a1fd6062ecarll         if (!allow_DFP) goto decode_noDFP;
192185eff1c502e995d1f9668cc9def72d5db59f21b13sewardj         if (dis_dfp_class_test( theInstr ))
192195eff1c502e995d1f9668cc9def72d5db59f21b13sewardj            goto decode_success;
192205eff1c502e995d1f9668cc9def72d5db59f21b13sewardj         goto decode_failure;
1922126217b09205cc1801b842ba5ba8f0d83aabca1b4sewardj      }
1922226217b09205cc1801b842ba5ba8f0d83aabca1b4sewardj
19223cdc376dcb5a4560b0a35d4abcb2146c499756f0dsewardj      opc2 = ifieldOPClo8( theInstr );
19224cdc376dcb5a4560b0a35d4abcb2146c499756f0dsewardj      switch (opc2) {
19225cdc376dcb5a4560b0a35d4abcb2146c499756f0dsewardj      case 0x3:   // dqua  - DFP Quantize
19226cdc376dcb5a4560b0a35d4abcb2146c499756f0dsewardj      case 0x23:  // drrnd - DFP Reround
19227cdc376dcb5a4560b0a35d4abcb2146c499756f0dsewardj      case 0x43:  // dquai - DFP Quantize immediate
192280c4e9e8eef3824b085973cd6e2b1b39a1fd6062ecarll         if (!allow_DFP) goto decode_noDFP;
19229cdc376dcb5a4560b0a35d4abcb2146c499756f0dsewardj         if (dis_dfp_quantize_sig_rrnd( theInstr ) )
19230cdc376dcb5a4560b0a35d4abcb2146c499756f0dsewardj            goto decode_success;
19231cdc376dcb5a4560b0a35d4abcb2146c499756f0dsewardj         goto decode_failure;
192325eff1c502e995d1f9668cc9def72d5db59f21b13sewardj      case 0xA2: // dtstex - DFP Test exponent
192330c4e9e8eef3824b085973cd6e2b1b39a1fd6062ecarll         if (!allow_DFP) goto decode_noDFP;
192345eff1c502e995d1f9668cc9def72d5db59f21b13sewardj         if (dis_dfp_exponent_test( theInstr ) )
192355eff1c502e995d1f9668cc9def72d5db59f21b13sewardj            goto decode_success;
192365eff1c502e995d1f9668cc9def72d5db59f21b13sewardj         goto decode_failure;
19237cdc376dcb5a4560b0a35d4abcb2146c499756f0dsewardj      case 0x63: // drintx - Round to an integer value
19238cdc376dcb5a4560b0a35d4abcb2146c499756f0dsewardj      case 0xE3: // drintn - Round to an integer value
192390c4e9e8eef3824b085973cd6e2b1b39a1fd6062ecarll         if (!allow_DFP) goto decode_noDFP;
19240cdc376dcb5a4560b0a35d4abcb2146c499756f0dsewardj         if (dis_dfp_round( theInstr ) ) {
19241cdc376dcb5a4560b0a35d4abcb2146c499756f0dsewardj            goto decode_success;
19242cdc376dcb5a4560b0a35d4abcb2146c499756f0dsewardj         }
19243cdc376dcb5a4560b0a35d4abcb2146c499756f0dsewardj         goto decode_failure;
19244cdc376dcb5a4560b0a35d4abcb2146c499756f0dsewardj      default:
19245cdc376dcb5a4560b0a35d4abcb2146c499756f0dsewardj         break;  /* fall through to next opc2 check */
19246cdc376dcb5a4560b0a35d4abcb2146c499756f0dsewardj      }
19247cdc376dcb5a4560b0a35d4abcb2146c499756f0dsewardj
1924876de5cf615380b23b4b5bcced6541233cd4a93a0cerion      opc2 = IFIELD(theInstr, 1, 5);
19249e14bb9f862843c6b804097c124961b5567ded4f1sewardj      switch (opc2) {
19250d953ebb9b04cbad6891676df597bf0c542b1ec89cerion      /* Floating Point Arith Instructions */
19251d953ebb9b04cbad6891676df597bf0c542b1ec89cerion      case 0x12: case 0x14: case 0x15: // fdivs,  fsubs, fadds
192525117ce116f47141cb23d1b49cc826e19323add97sewardj      case 0x19:                       // fmuls
19253d953ebb9b04cbad6891676df597bf0c542b1ec89cerion         if (dis_fp_arith(theInstr)) goto decode_success;
19254d953ebb9b04cbad6891676df597bf0c542b1ec89cerion         goto decode_failure;
192555117ce116f47141cb23d1b49cc826e19323add97sewardj      case 0x16:                       // fsqrts
192565117ce116f47141cb23d1b49cc826e19323add97sewardj         if (!allow_FX) goto decode_noFX;
192575117ce116f47141cb23d1b49cc826e19323add97sewardj         if (dis_fp_arith(theInstr)) goto decode_success;
192585117ce116f47141cb23d1b49cc826e19323add97sewardj         goto decode_failure;
192595117ce116f47141cb23d1b49cc826e19323add97sewardj      case 0x18:                       // fres
192605117ce116f47141cb23d1b49cc826e19323add97sewardj         if (!allow_GX) goto decode_noGX;
192615117ce116f47141cb23d1b49cc826e19323add97sewardj         if (dis_fp_arith(theInstr)) goto decode_success;
192625117ce116f47141cb23d1b49cc826e19323add97sewardj         goto decode_failure;
192635117ce116f47141cb23d1b49cc826e19323add97sewardj
19264d953ebb9b04cbad6891676df597bf0c542b1ec89cerion      /* Floating Point Mult-Add Instructions */
19265d953ebb9b04cbad6891676df597bf0c542b1ec89cerion      case 0x1C: case 0x1D: case 0x1E: // fmsubs, fmadds, fnmsubs
19266d953ebb9b04cbad6891676df597bf0c542b1ec89cerion      case 0x1F:                       // fnmadds
19267d953ebb9b04cbad6891676df597bf0c542b1ec89cerion         if (dis_fp_multadd(theInstr)) goto decode_success;
19268d953ebb9b04cbad6891676df597bf0c542b1ec89cerion         goto decode_failure;
1926979fd33f4e243276b8109fe56c3eb1d4c9ccea7ccsewardj
1927079fd33f4e243276b8109fe56c3eb1d4c9ccea7ccsewardj      case 0x1A:                       // frsqrtes
1927179fd33f4e243276b8109fe56c3eb1d4c9ccea7ccsewardj         if (!allow_GX) goto decode_noGX;
1927279fd33f4e243276b8109fe56c3eb1d4c9ccea7ccsewardj         if (dis_fp_arith(theInstr)) goto decode_success;
1927379fd33f4e243276b8109fe56c3eb1d4c9ccea7ccsewardj         goto decode_failure;
1927466d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj
19275d953ebb9b04cbad6891676df597bf0c542b1ec89cerion      default:
19276d953ebb9b04cbad6891676df597bf0c542b1ec89cerion         goto decode_failure;
19277e14bb9f862843c6b804097c124961b5567ded4f1sewardj      }
19278e14bb9f862843c6b804097c124961b5567ded4f1sewardj      break;
19279a982c0503d8c0c6069ae453bfe70657bd2c134aecerion
1928066d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj   case 0x3C: // VSX instructions (except load/store)
1928166d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj   {
19282dc7948f8051acfd10087c8e3b66304c0ba0d1b37florian      // All of these VSX instructions use some VMX facilities, so
19283dc7948f8051acfd10087c8e3b66304c0ba0d1b37florian      // if allow_V is not set, we'll skip trying to decode.
19284dc7948f8051acfd10087c8e3b66304c0ba0d1b37florian      if (!allow_V) goto decode_noVX;
19285dc7948f8051acfd10087c8e3b66304c0ba0d1b37florian
1928666d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj      UInt vsxOpc2 = get_VSX60_opc2(opc2);
1928766d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj      /* The vsxOpc2 returned is the "normalized" value, representing the
1928866d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj       * instructions secondary opcode as taken from the standard secondary
1928966d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj       * opcode field [21:30] (IBM notatition), even if the actual field
1929066d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj       * is non-standard.  These normalized values are given in the opcode
1929166d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj       * appendices of the ISA 2.06 document.
1929266d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj       */
1929366d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj
1929466d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj      switch (vsxOpc2) {
1929566d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj         case 0x8: case 0x28: case 0x48: case 0xc8: // xxsldwi, xxpermdi, xxmrghw, xxmrglw
192964aa412af1d8166cc11f39a6e721df49431d23618sewardj         case 0x018: case 0x148: // xxsel, xxspltw
192974aa412af1d8166cc11f39a6e721df49431d23618sewardj            if (dis_vx_permute_misc(theInstr, vsxOpc2)) goto decode_success;
1929866d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj            goto decode_failure;
192996c758b64a77c254065ab7450576bbd3a0b583595carll         case 0x268: case 0x248: case 0x288: // xxlxor, xxlor, xxlnor,
193006c758b64a77c254065ab7450576bbd3a0b583595carll         case 0x208: case 0x228: case 0x2A8: // xxland, xxlandc, xxlorc
193016c758b64a77c254065ab7450576bbd3a0b583595carll         case 0x2C8: case 0x2E8: // xxlnand, xxleqv
1930266d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj            if (dis_vx_logic(theInstr, vsxOpc2)) goto decode_success;
1930366d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj            goto decode_failure;
193044aa412af1d8166cc11f39a6e721df49431d23618sewardj         case 0x2B2: case 0x2C0: // xsabsdp, xscpsgndp
193054aa412af1d8166cc11f39a6e721df49431d23618sewardj         case 0x2D2: case 0x2F2: // xsnabsdp, xsnegdp
193064aa412af1d8166cc11f39a6e721df49431d23618sewardj         case 0x280: case 0x2A0: // xsmaxdp, xsmindp
193074aa412af1d8166cc11f39a6e721df49431d23618sewardj         case 0x0F2: case 0x0D2: // xsrdpim, xsrdpip
193086c758b64a77c254065ab7450576bbd3a0b583595carll         case 0x034: case 0x014: // xsresp, xsrsqrtesp
19309e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj         case 0x0B4: case 0x094: // xsredp, xsrsqrtedp
19310e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj         case 0x0D6: case 0x0B2: // xsrdpic, xsrdpiz
193116c758b64a77c254065ab7450576bbd3a0b583595carll         case 0x092: case 0x232: // xsrdpi, xsrsp
193124aa412af1d8166cc11f39a6e721df49431d23618sewardj            if (dis_vxs_misc(theInstr, vsxOpc2)) goto decode_success;
1931366d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj            goto decode_failure;
1931466d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj         case 0x08C: case 0x0AC: // xscmpudp, xscmpodp
1931566d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj            if (dis_vx_cmp(theInstr, vsxOpc2)) goto decode_success;
1931666d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj            goto decode_failure;
193176c758b64a77c254065ab7450576bbd3a0b583595carll         case 0x0:   case 0x020: // xsaddsp, xssubsp
193186c758b64a77c254065ab7450576bbd3a0b583595carll         case 0x080:             // xsadddp
193196c758b64a77c254065ab7450576bbd3a0b583595carll         case 0x060: case 0x0E0: // xsdivsp, xsdivdp
193206c758b64a77c254065ab7450576bbd3a0b583595carll         case 0x004: case 0x024: // xsmaddasp, xsmaddmsp
1932166d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj         case 0x084: case 0x0A4: // xsmaddadp, xsmaddmdp
193226c758b64a77c254065ab7450576bbd3a0b583595carll         case 0x044: case 0x064: // xsmsubasp, xsmsubmsp
1932366d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj         case 0x0C4: case 0x0E4: // xsmsubadp, xsmsubmdp
193246c758b64a77c254065ab7450576bbd3a0b583595carll         case 0x204: case 0x224: // xsnmaddasp, xsnmaddmsp
1932566d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj         case 0x284: case 0x2A4: // xsnmaddadp, xsnmaddmdp
193266c758b64a77c254065ab7450576bbd3a0b583595carll         case 0x244: case 0x264: // xsnmsubasp, xsnmsubmsp
193274aa412af1d8166cc11f39a6e721df49431d23618sewardj         case 0x2C4: case 0x2E4: // xsnmsubadp, xsnmsubmdp
193286c758b64a77c254065ab7450576bbd3a0b583595carll         case 0x040: case 0x0C0: // xsmulsp, xsmuldp
193296c758b64a77c254065ab7450576bbd3a0b583595carll         case 0x0A0:             // xssubdp
193306c758b64a77c254065ab7450576bbd3a0b583595carll         case 0x016: case 0x096: // xssqrtsp,xssqrtdp
193316c758b64a77c254065ab7450576bbd3a0b583595carll         case 0x0F4: case 0x0D4: // xstdivdp, xstsqrtdp
193324aa412af1d8166cc11f39a6e721df49431d23618sewardj            if (dis_vxs_arith(theInstr, vsxOpc2)) goto decode_success;
193334aa412af1d8166cc11f39a6e721df49431d23618sewardj            goto decode_failure;
193344aa412af1d8166cc11f39a6e721df49431d23618sewardj         case 0x180: // xvadddp
193354aa412af1d8166cc11f39a6e721df49431d23618sewardj         case 0x1E0: // xvdivdp
193364aa412af1d8166cc11f39a6e721df49431d23618sewardj         case 0x1C0: // xvmuldp
193374aa412af1d8166cc11f39a6e721df49431d23618sewardj         case 0x1A0: // xvsubdp
193384aa412af1d8166cc11f39a6e721df49431d23618sewardj         case 0x184: case 0x1A4: // xvmaddadp, xvmaddmdp
193394aa412af1d8166cc11f39a6e721df49431d23618sewardj         case 0x1C4: case 0x1E4: // xvmsubadp, xvmsubmdp
193404aa412af1d8166cc11f39a6e721df49431d23618sewardj         case 0x384: case 0x3A4: // xvnmaddadp, xvnmaddmdp
193414aa412af1d8166cc11f39a6e721df49431d23618sewardj         case 0x3C4: case 0x3E4: // xvnmsubadp, xvnmsubmdp
19342e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj         case 0x1D4: case 0x1F4: // xvtsqrtdp, xvtdivdp
19343e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj         case 0x196: // xvsqrtdp
193444aa412af1d8166cc11f39a6e721df49431d23618sewardj            if (dis_vxv_dp_arith(theInstr, vsxOpc2)) goto decode_success;
193454aa412af1d8166cc11f39a6e721df49431d23618sewardj            goto decode_failure;
193464aa412af1d8166cc11f39a6e721df49431d23618sewardj         case 0x100: // xvaddsp
193474aa412af1d8166cc11f39a6e721df49431d23618sewardj         case 0x160: // xvdivsp
193484aa412af1d8166cc11f39a6e721df49431d23618sewardj         case 0x140: // xvmulsp
193494aa412af1d8166cc11f39a6e721df49431d23618sewardj         case 0x120: // xvsubsp
193504aa412af1d8166cc11f39a6e721df49431d23618sewardj         case 0x104: case 0x124: // xvmaddasp, xvmaddmsp
193514aa412af1d8166cc11f39a6e721df49431d23618sewardj         case 0x144: case 0x164: // xvmsubasp, xvmsubmsp
193524aa412af1d8166cc11f39a6e721df49431d23618sewardj         case 0x304: case 0x324: // xvnmaddasp, xvnmaddmsp
193534aa412af1d8166cc11f39a6e721df49431d23618sewardj         case 0x344: case 0x364: // xvnmsubasp, xvnmsubmsp
19354e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj         case 0x154: case 0x174: // xvtsqrtsp, xvtdivsp
19355e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj         case 0x116: // xvsqrtsp
193564aa412af1d8166cc11f39a6e721df49431d23618sewardj            if (dis_vxv_sp_arith(theInstr, vsxOpc2)) goto decode_success;
1935766d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj            goto decode_failure;
193584aa412af1d8166cc11f39a6e721df49431d23618sewardj
193596c758b64a77c254065ab7450576bbd3a0b583595carll         case 0x250:             // xscvuxdsp
19360dc7948f8051acfd10087c8e3b66304c0ba0d1b37florian         case 0x2D0: case 0x3d0: // xscvuxddp, xvcvuxddp
19361dc7948f8051acfd10087c8e3b66304c0ba0d1b37florian         case 0x350: case 0x1d0: // xvcvuxdsp, xvcvuxwdp
19362dc7948f8051acfd10087c8e3b66304c0ba0d1b37florian         case 0x090: // xscvdpuxws
19363dc7948f8051acfd10087c8e3b66304c0ba0d1b37florian            // The above VSX conversion instructions employ some ISA 2.06
19364dc7948f8051acfd10087c8e3b66304c0ba0d1b37florian            // floating point conversion instructions under the covers,
19365dc7948f8051acfd10087c8e3b66304c0ba0d1b37florian            // so if allow_VX (which means "supports ISA 2.06") is not set,
19366dc7948f8051acfd10087c8e3b66304c0ba0d1b37florian            // we'll skip the decode.
19367dc7948f8051acfd10087c8e3b66304c0ba0d1b37florian            if (!allow_VX) goto decode_noVX;
19368dc7948f8051acfd10087c8e3b66304c0ba0d1b37florian            if (dis_vx_conv(theInstr, vsxOpc2)) goto decode_success;
19369dc7948f8051acfd10087c8e3b66304c0ba0d1b37florian            goto decode_failure;
19370dc7948f8051acfd10087c8e3b66304c0ba0d1b37florian
193716c758b64a77c254065ab7450576bbd3a0b583595carll         case 0x2B0: // xscvdpsxds
193726c758b64a77c254065ab7450576bbd3a0b583595carll         case 0x270: case 0x2F0: // xscvsxdsp, xscvsxddp
193734aa412af1d8166cc11f39a6e721df49431d23618sewardj         case 0x1b0: case 0x130: // xvcvdpsxws, xvcvspsxws
193744aa412af1d8166cc11f39a6e721df49431d23618sewardj         case 0x0b0: case 0x290: // xscvdpsxws, xscvdpuxds
193750c74bb5aa3240f693df0568d578baabf0c376dc4carll         case 0x212: case 0x216: // xscvdpsp, xscvdpspn
193760c74bb5aa3240f693df0568d578baabf0c376dc4carll         case 0x292: case 0x296: // xscvspdp, xscvspdpn
193770c74bb5aa3240f693df0568d578baabf0c376dc4carll         case 0x312: // xvcvdpsp
19378e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj         case 0x390: case 0x190: // xvcvdpuxds, xvcvdpuxws
19379e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj         case 0x3B0: case 0x310: // xvcvdpsxds, xvcvspuxds
19380e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj         case 0x392: case 0x330: // xvcvspdp, xvcvspsxds
19381e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj         case 0x110: case 0x3f0: // xvcvspuxws, xvcvsxddp
19382e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj         case 0x370: case 0x1f0: // xvcvsxdsp, xvcvsxwdp
19383e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj         case 0x170: case 0x150: // xvcvsxwsp, xvcvuxwsp
1938466d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj            if (dis_vx_conv(theInstr, vsxOpc2)) goto decode_success;
1938566d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj            goto decode_failure;
1938666d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj
193874aa412af1d8166cc11f39a6e721df49431d23618sewardj         case 0x18C: case 0x38C: // xvcmpeqdp[.]
193884aa412af1d8166cc11f39a6e721df49431d23618sewardj         case 0x10C: case 0x30C: // xvcmpeqsp[.]
193894aa412af1d8166cc11f39a6e721df49431d23618sewardj         case 0x14C: case 0x34C: // xvcmpgesp[.]
193904aa412af1d8166cc11f39a6e721df49431d23618sewardj         case 0x12C: case 0x32C: // xvcmpgtsp[.]
193914aa412af1d8166cc11f39a6e721df49431d23618sewardj         case 0x1CC: case 0x3CC: // xvcmpgedp[.]
193924aa412af1d8166cc11f39a6e721df49431d23618sewardj         case 0x1AC: case 0x3AC: // xvcmpgtdp[.]
193934aa412af1d8166cc11f39a6e721df49431d23618sewardj             if (dis_vvec_cmp(theInstr, vsxOpc2)) goto decode_success;
193944aa412af1d8166cc11f39a6e721df49431d23618sewardj             goto decode_failure;
193954aa412af1d8166cc11f39a6e721df49431d23618sewardj
193964aa412af1d8166cc11f39a6e721df49431d23618sewardj         case 0x134:  // xvresp
19397e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj         case 0x1B4:  // xvredp
19398e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj         case 0x194: case 0x114: // xvrsqrtedp, xvrsqrtesp
19399e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj         case 0x380: case 0x3A0: // xvmaxdp, xvmindp
194004aa412af1d8166cc11f39a6e721df49431d23618sewardj         case 0x300: case 0x320: // xvmaxsp, xvminsp
19401e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj         case 0x3C0: case 0x340: // xvcpsgndp, xvcpsgnsp
19402e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj         case 0x3B2: case 0x332: // xvabsdp, xvabssp
19403e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj         case 0x3D2: case 0x352: // xvnabsdp, xvnabssp
19404e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj         case 0x192: case 0x1D6: // xvrdpi, xvrdpic
19405e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj         case 0x1F2: case 0x1D2: // xvrdpim, xvrdpip
19406e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj         case 0x1B2: case 0x3F2: // xvrdpiz, xvnegdp
19407e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj         case 0x112: case 0x156: // xvrspi, xvrspic
19408e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj         case 0x172: case 0x152: // xvrspim, xvrspip
19409e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj         case 0x132: // xvrspiz
194104aa412af1d8166cc11f39a6e721df49431d23618sewardj            if (dis_vxv_misc(theInstr, vsxOpc2)) goto decode_success;
194114aa412af1d8166cc11f39a6e721df49431d23618sewardj            goto decode_failure;
194124aa412af1d8166cc11f39a6e721df49431d23618sewardj
1941366d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj         default:
1941466d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj            goto decode_failure;
1941566d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj      }
1941666d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj      break;
1941766d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj   }
1941866d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj
19419f0de28cf1a762b0d6f74c93d3532c89a230673bbcerion   /* 64bit Integer Stores */
1942078850ae9874a90ea625fcee1fd4c359375b7b538carll   case 0x3E:  // std, stdu, stq
19421dd40fdf58cc8a6fe9466c4f00bdfc9fe9bf00449sewardj      if (dis_int_store( theInstr, abiinfo )) goto decode_success;
19422f0de28cf1a762b0d6f74c93d3532c89a230673bbcerion      goto decode_failure;
19423f0de28cf1a762b0d6f74c93d3532c89a230673bbcerion
19424a982c0503d8c0c6069ae453bfe70657bd2c134aecerion   case 0x3F:
194255117ce116f47141cb23d1b49cc826e19323add97sewardj      if (!allow_F) goto decode_noF;
194265b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion      /* Instrs using opc[1:5] never overlap instrs using opc[1:10],
19427a982c0503d8c0c6069ae453bfe70657bd2c134aecerion         so we can simply fall through the first switch statement */
194283d870a39e4d145e2f3d9f9a0eeed3475ec934ac1cerion
1942976de5cf615380b23b4b5bcced6541233cd4a93a0cerion      opc2 = IFIELD(theInstr, 1, 5);
194303d870a39e4d145e2f3d9f9a0eeed3475ec934ac1cerion      switch (opc2) {
19431d953ebb9b04cbad6891676df597bf0c542b1ec89cerion      /* Floating Point Arith Instructions */
194325117ce116f47141cb23d1b49cc826e19323add97sewardj      case 0x12: case 0x14: case 0x15: // fdiv, fsub, fadd
194335117ce116f47141cb23d1b49cc826e19323add97sewardj      case 0x19:                       // fmul
194345117ce116f47141cb23d1b49cc826e19323add97sewardj         if (dis_fp_arith(theInstr)) goto decode_success;
194355117ce116f47141cb23d1b49cc826e19323add97sewardj         goto decode_failure;
194365117ce116f47141cb23d1b49cc826e19323add97sewardj      case 0x16:                       // fsqrt
194375117ce116f47141cb23d1b49cc826e19323add97sewardj         if (!allow_FX) goto decode_noFX;
194385117ce116f47141cb23d1b49cc826e19323add97sewardj         if (dis_fp_arith(theInstr)) goto decode_success;
194395117ce116f47141cb23d1b49cc826e19323add97sewardj         goto decode_failure;
194405117ce116f47141cb23d1b49cc826e19323add97sewardj      case 0x17: case 0x1A:            // fsel, frsqrte
194415117ce116f47141cb23d1b49cc826e19323add97sewardj         if (!allow_GX) goto decode_noGX;
19442d953ebb9b04cbad6891676df597bf0c542b1ec89cerion         if (dis_fp_arith(theInstr)) goto decode_success;
19443d953ebb9b04cbad6891676df597bf0c542b1ec89cerion         goto decode_failure;
19444d953ebb9b04cbad6891676df597bf0c542b1ec89cerion
19445d953ebb9b04cbad6891676df597bf0c542b1ec89cerion      /* Floating Point Mult-Add Instructions */
19446d953ebb9b04cbad6891676df597bf0c542b1ec89cerion      case 0x1C: case 0x1D: case 0x1E: // fmsub, fmadd, fnmsub
19447d953ebb9b04cbad6891676df597bf0c542b1ec89cerion      case 0x1F:                       // fnmadd
19448d953ebb9b04cbad6891676df597bf0c542b1ec89cerion         if (dis_fp_multadd(theInstr)) goto decode_success;
1944979fd33f4e243276b8109fe56c3eb1d4c9ccea7ccsewardj         goto decode_failure;
1945079fd33f4e243276b8109fe56c3eb1d4c9ccea7ccsewardj
1945179fd33f4e243276b8109fe56c3eb1d4c9ccea7ccsewardj      case 0x18:                       // fre
1945279fd33f4e243276b8109fe56c3eb1d4c9ccea7ccsewardj         if (!allow_GX) goto decode_noGX;
1945379fd33f4e243276b8109fe56c3eb1d4c9ccea7ccsewardj         if (dis_fp_arith(theInstr)) goto decode_success;
19454d953ebb9b04cbad6891676df597bf0c542b1ec89cerion         goto decode_failure;
194550c74bb5aa3240f693df0568d578baabf0c376dc4carll
19456d953ebb9b04cbad6891676df597bf0c542b1ec89cerion      default:
19457d953ebb9b04cbad6891676df597bf0c542b1ec89cerion         break; // Fall through
194583d870a39e4d145e2f3d9f9a0eeed3475ec934ac1cerion      }
194593d870a39e4d145e2f3d9f9a0eeed3475ec934ac1cerion
1946076de5cf615380b23b4b5bcced6541233cd4a93a0cerion      opc2 = IFIELD(theInstr, 1, 10);
19461e14bb9f862843c6b804097c124961b5567ded4f1sewardj      switch (opc2) {
19462c6bbd470e9bd9898b84959227a406d3972d95f3bsewardj      /* 128-bit DFP instructions */
19463c6bbd470e9bd9898b84959227a406d3972d95f3bsewardj      case 0x2:    // daddq - DFP Add
19464c6bbd470e9bd9898b84959227a406d3972d95f3bsewardj      case 0x202:  // dsubq - DFP Subtract
19465c6bbd470e9bd9898b84959227a406d3972d95f3bsewardj      case 0x22:   // dmulq - DFP Mult
19466c6bbd470e9bd9898b84959227a406d3972d95f3bsewardj      case 0x222:  // ddivq - DFP Divide
19467c66d6fa5d9397f167b162483cf3419051cc01a80sewardj         if (!allow_DFP) goto decode_noDFP;
19468c6bbd470e9bd9898b84959227a406d3972d95f3bsewardj         if (dis_dfp_arithq( theInstr ))
19469c6bbd470e9bd9898b84959227a406d3972d95f3bsewardj            goto decode_success;
19470c6bbd470e9bd9898b84959227a406d3972d95f3bsewardj         goto decode_failure;
19471cdc376dcb5a4560b0a35d4abcb2146c499756f0dsewardj      case 0x162:  // dxexq - DFP Extract exponent
19472cdc376dcb5a4560b0a35d4abcb2146c499756f0dsewardj      case 0x362:  // diexq - DFP Insert exponent
194730c4e9e8eef3824b085973cd6e2b1b39a1fd6062ecarll         if (!allow_DFP) goto decode_noDFP;
19474cdc376dcb5a4560b0a35d4abcb2146c499756f0dsewardj         if (dis_dfp_extract_insertq( theInstr ))
19475cdc376dcb5a4560b0a35d4abcb2146c499756f0dsewardj            goto decode_success;
19476cdc376dcb5a4560b0a35d4abcb2146c499756f0dsewardj         goto decode_failure;
19477cdc376dcb5a4560b0a35d4abcb2146c499756f0dsewardj
19478cdc376dcb5a4560b0a35d4abcb2146c499756f0dsewardj      case 0x82:   // dcmpoq, DFP comparison ordered instruction
19479cdc376dcb5a4560b0a35d4abcb2146c499756f0dsewardj      case 0x282:  // dcmpuq, DFP comparison unordered instruction
194800c4e9e8eef3824b085973cd6e2b1b39a1fd6062ecarll         if (!allow_DFP) goto decode_noDFP;
19481cdc376dcb5a4560b0a35d4abcb2146c499756f0dsewardj         if (dis_dfp_compare( theInstr ) )
19482cdc376dcb5a4560b0a35d4abcb2146c499756f0dsewardj            goto decode_success;
19483cdc376dcb5a4560b0a35d4abcb2146c499756f0dsewardj         goto decode_failure;
19484c6bbd470e9bd9898b84959227a406d3972d95f3bsewardj
1948526217b09205cc1801b842ba5ba8f0d83aabca1b4sewardj      case 0x102: // dctqpq  - DFP convert to DFP extended
1948626217b09205cc1801b842ba5ba8f0d83aabca1b4sewardj      case 0x302: // drdpq   - DFP round to dfp Long
1948726217b09205cc1801b842ba5ba8f0d83aabca1b4sewardj      case 0x122: // dctfixq - DFP convert to fixed quad
1948826217b09205cc1801b842ba5ba8f0d83aabca1b4sewardj      case 0x322: // dcffixq - DFP convert from fixed quad
194890c4e9e8eef3824b085973cd6e2b1b39a1fd6062ecarll         if (!allow_DFP) goto decode_noDFP;
1949026217b09205cc1801b842ba5ba8f0d83aabca1b4sewardj         if (dis_dfp_fmt_convq( theInstr ))
1949126217b09205cc1801b842ba5ba8f0d83aabca1b4sewardj            goto decode_success;
1949226217b09205cc1801b842ba5ba8f0d83aabca1b4sewardj         goto decode_failure;
1949326217b09205cc1801b842ba5ba8f0d83aabca1b4sewardj
194944c96e61dd85c172b999d6afc88ce6640aeba9962sewardj      case 0x2A2: // dtstsfq - DFP number of significant digits
194950c4e9e8eef3824b085973cd6e2b1b39a1fd6062ecarll         if (!allow_DFP) goto decode_noDFP;
194964c96e61dd85c172b999d6afc88ce6640aeba9962sewardj         if (dis_dfp_significant_digits(theInstr))
194974c96e61dd85c172b999d6afc88ce6640aeba9962sewardj            goto decode_success;
194984c96e61dd85c172b999d6afc88ce6640aeba9962sewardj         goto decode_failure;
194994c96e61dd85c172b999d6afc88ce6640aeba9962sewardj
195004c96e61dd85c172b999d6afc88ce6640aeba9962sewardj      case 0x142: // ddedpdq   DFP Decode DPD to BCD
195014c96e61dd85c172b999d6afc88ce6640aeba9962sewardj      case 0x342: // denbcdq   DFP Encode BCD to DPD
195020c4e9e8eef3824b085973cd6e2b1b39a1fd6062ecarll         if (!allow_DFP) goto decode_noDFP;
195034c96e61dd85c172b999d6afc88ce6640aeba9962sewardj         if (dis_dfp_bcdq(theInstr))
195044c96e61dd85c172b999d6afc88ce6640aeba9962sewardj            goto decode_success;
195054c96e61dd85c172b999d6afc88ce6640aeba9962sewardj         goto decode_failure;
195064c96e61dd85c172b999d6afc88ce6640aeba9962sewardj
19507d953ebb9b04cbad6891676df597bf0c542b1ec89cerion      /* Floating Point Compare Instructions */
19508d953ebb9b04cbad6891676df597bf0c542b1ec89cerion      case 0x000: // fcmpu
19509d953ebb9b04cbad6891676df597bf0c542b1ec89cerion      case 0x020: // fcmpo
19510d953ebb9b04cbad6891676df597bf0c542b1ec89cerion         if (dis_fp_cmp(theInstr)) goto decode_success;
19511d953ebb9b04cbad6891676df597bf0c542b1ec89cerion         goto decode_failure;
195122831b00c4950d6c2b061def05fd67528fe132ececerion
1951366d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj      case 0x080: // ftdiv
19514e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj      case 0x0A0: // ftsqrt
19515e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj         if (dis_fp_tests(theInstr)) goto decode_success;
1951666d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj         goto decode_failure;
1951766d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj
19518d953ebb9b04cbad6891676df597bf0c542b1ec89cerion      /* Floating Point Rounding/Conversion Instructions */
19519d953ebb9b04cbad6891676df597bf0c542b1ec89cerion      case 0x00C: // frsp
19520d953ebb9b04cbad6891676df597bf0c542b1ec89cerion      case 0x00E: // fctiw
19521d953ebb9b04cbad6891676df597bf0c542b1ec89cerion      case 0x00F: // fctiwz
195226be67235ba2829b0bc34c3a0876cee4eac340d95sewardj      case 0x32E: // fctid
195236be67235ba2829b0bc34c3a0876cee4eac340d95sewardj      case 0x32F: // fctidz
195246be67235ba2829b0bc34c3a0876cee4eac340d95sewardj      case 0x34E: // fcfid
19525d953ebb9b04cbad6891676df597bf0c542b1ec89cerion         if (dis_fp_round(theInstr)) goto decode_success;
19526d953ebb9b04cbad6891676df597bf0c542b1ec89cerion         goto decode_failure;
195274aa412af1d8166cc11f39a6e721df49431d23618sewardj      case 0x3CE: case 0x3AE: case 0x3AF: // fcfidu, fctidu[z] (implemented as native insns)
195284aa412af1d8166cc11f39a6e721df49431d23618sewardj      case 0x08F: case 0x08E: // fctiwu[z] (implemented as native insns)
1952966d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj         if (!allow_VX) goto decode_noVX;
1953066d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj         if (dis_fp_round(theInstr)) goto decode_success;
1953166d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj         goto decode_failure;
1953266d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj
195330f1ef86a99d5129e04ed188e44d16a344d2bc42asewardj      /* Power6 rounding stuff */
195340f1ef86a99d5129e04ed188e44d16a344d2bc42asewardj      case 0x1E8: // frim
195350f1ef86a99d5129e04ed188e44d16a344d2bc42asewardj      case 0x1C8: // frip
195360f1ef86a99d5129e04ed188e44d16a344d2bc42asewardj      case 0x188: // frin
195370f1ef86a99d5129e04ed188e44d16a344d2bc42asewardj      case 0x1A8: // friz
195387e84630580f89c1022dde97007bffbf6aef81814sewardj         /* A hack to check for P6 capability . . . */
195397e84630580f89c1022dde97007bffbf6aef81814sewardj         if ((allow_F && allow_V && allow_FX && allow_GX) &&
195407e84630580f89c1022dde97007bffbf6aef81814sewardj             (dis_fp_round(theInstr)))
195410f1ef86a99d5129e04ed188e44d16a344d2bc42asewardj            goto decode_success;
195420f1ef86a99d5129e04ed188e44d16a344d2bc42asewardj         goto decode_failure;
19543d953ebb9b04cbad6891676df597bf0c542b1ec89cerion
19544d953ebb9b04cbad6891676df597bf0c542b1ec89cerion      /* Floating Point Move Instructions */
195457e84630580f89c1022dde97007bffbf6aef81814sewardj      case 0x008: // fcpsgn
19546d953ebb9b04cbad6891676df597bf0c542b1ec89cerion      case 0x028: // fneg
19547d953ebb9b04cbad6891676df597bf0c542b1ec89cerion      case 0x048: // fmr
19548d953ebb9b04cbad6891676df597bf0c542b1ec89cerion      case 0x088: // fnabs
19549d953ebb9b04cbad6891676df597bf0c542b1ec89cerion      case 0x108: // fabs
19550d953ebb9b04cbad6891676df597bf0c542b1ec89cerion         if (dis_fp_move( theInstr )) goto decode_success;
19551d953ebb9b04cbad6891676df597bf0c542b1ec89cerion         goto decode_failure;
19552d953ebb9b04cbad6891676df597bf0c542b1ec89cerion
1955378850ae9874a90ea625fcee1fd4c359375b7b538carll      case 0x3c6: case 0x346:          // fmrgew, fmrgow
1955478850ae9874a90ea625fcee1fd4c359375b7b538carll         if (dis_fp_merge( theInstr )) goto decode_success;
1955578850ae9874a90ea625fcee1fd4c359375b7b538carll         goto decode_failure;
1955678850ae9874a90ea625fcee1fd4c359375b7b538carll
19557d953ebb9b04cbad6891676df597bf0c542b1ec89cerion      /* Floating Point Status/Control Register Instructions */
195583ea49ee14d8c061bc0e7c3e90a22849de1c59d73cerion      case 0x026: // mtfsb1
19559496b88f208ea5cca7b03d41209fba7f4e1ae9c9bsewardj      case 0x040: // mcrfs
19560d953ebb9b04cbad6891676df597bf0c542b1ec89cerion      case 0x046: // mtfsb0
19561d953ebb9b04cbad6891676df597bf0c542b1ec89cerion      case 0x086: // mtfsfi
19562d953ebb9b04cbad6891676df597bf0c542b1ec89cerion      case 0x247: // mffs
19563d953ebb9b04cbad6891676df597bf0c542b1ec89cerion      case 0x2C7: // mtfsf
19564c6bbd470e9bd9898b84959227a406d3972d95f3bsewardj         // Some of the above instructions need to know more about the
19565c6bbd470e9bd9898b84959227a406d3972d95f3bsewardj         // ISA level supported by the host.
19566c6bbd470e9bd9898b84959227a406d3972d95f3bsewardj         if (dis_fp_scr( theInstr, allow_GX )) goto decode_success;
19567d953ebb9b04cbad6891676df597bf0c542b1ec89cerion         goto decode_failure;
19568f0de28cf1a762b0d6f74c93d3532c89a230673bbcerion
19569d953ebb9b04cbad6891676df597bf0c542b1ec89cerion      default:
1957026217b09205cc1801b842ba5ba8f0d83aabca1b4sewardj         break; // Fall through...
1957126217b09205cc1801b842ba5ba8f0d83aabca1b4sewardj      }
1957226217b09205cc1801b842ba5ba8f0d83aabca1b4sewardj
1957326217b09205cc1801b842ba5ba8f0d83aabca1b4sewardj      opc2 = ifieldOPClo9( theInstr );
1957426217b09205cc1801b842ba5ba8f0d83aabca1b4sewardj      switch (opc2) {
1957526217b09205cc1801b842ba5ba8f0d83aabca1b4sewardj      case 0x42: // dscli, DFP shift left
1957626217b09205cc1801b842ba5ba8f0d83aabca1b4sewardj      case 0x62: // dscri, DFP shift right
195770c4e9e8eef3824b085973cd6e2b1b39a1fd6062ecarll         if (!allow_DFP) goto decode_noDFP;
1957826217b09205cc1801b842ba5ba8f0d83aabca1b4sewardj         if (dis_dfp_shiftq( theInstr ))
1957926217b09205cc1801b842ba5ba8f0d83aabca1b4sewardj            goto decode_success;
1958026217b09205cc1801b842ba5ba8f0d83aabca1b4sewardj         goto decode_failure;
195815eff1c502e995d1f9668cc9def72d5db59f21b13sewardj      case 0xc2:  // dtstdc, DFP test data class
195825eff1c502e995d1f9668cc9def72d5db59f21b13sewardj      case 0xe2:  // dtstdg, DFP test data group
195830c4e9e8eef3824b085973cd6e2b1b39a1fd6062ecarll         if (!allow_DFP) goto decode_noDFP;
195845eff1c502e995d1f9668cc9def72d5db59f21b13sewardj         if (dis_dfp_class_test( theInstr ))
195855eff1c502e995d1f9668cc9def72d5db59f21b13sewardj            goto decode_success;
195865eff1c502e995d1f9668cc9def72d5db59f21b13sewardj         goto decode_failure;
1958726217b09205cc1801b842ba5ba8f0d83aabca1b4sewardj      default:
1958826217b09205cc1801b842ba5ba8f0d83aabca1b4sewardj         break;
19589e14bb9f862843c6b804097c124961b5567ded4f1sewardj      }
19590cdc376dcb5a4560b0a35d4abcb2146c499756f0dsewardj
19591cdc376dcb5a4560b0a35d4abcb2146c499756f0dsewardj      opc2 = ifieldOPClo8( theInstr );
19592cdc376dcb5a4560b0a35d4abcb2146c499756f0dsewardj      switch (opc2) {
19593cdc376dcb5a4560b0a35d4abcb2146c499756f0dsewardj      case 0x3:   // dquaq  - DFP Quantize Quad
19594cdc376dcb5a4560b0a35d4abcb2146c499756f0dsewardj      case 0x23:  // drrndq - DFP Reround Quad
19595cdc376dcb5a4560b0a35d4abcb2146c499756f0dsewardj      case 0x43:  // dquaiq - DFP Quantize immediate Quad
195960c4e9e8eef3824b085973cd6e2b1b39a1fd6062ecarll         if (!allow_DFP) goto decode_noDFP;
19597cdc376dcb5a4560b0a35d4abcb2146c499756f0dsewardj         if (dis_dfp_quantize_sig_rrndq( theInstr ))
19598cdc376dcb5a4560b0a35d4abcb2146c499756f0dsewardj            goto decode_success;
19599cdc376dcb5a4560b0a35d4abcb2146c499756f0dsewardj         goto decode_failure;
196005eff1c502e995d1f9668cc9def72d5db59f21b13sewardj      case 0xA2: // dtstexq - DFP Test exponent Quad
196015eff1c502e995d1f9668cc9def72d5db59f21b13sewardj         if (dis_dfp_exponent_test( theInstr ) )
196025eff1c502e995d1f9668cc9def72d5db59f21b13sewardj            goto decode_success;
196035eff1c502e995d1f9668cc9def72d5db59f21b13sewardj         goto decode_failure;
19604cdc376dcb5a4560b0a35d4abcb2146c499756f0dsewardj      case 0x63:  // drintxq - DFP Round to an integer value
19605cdc376dcb5a4560b0a35d4abcb2146c499756f0dsewardj      case 0xE3:  // drintnq - DFP Round to an integer value
196060c4e9e8eef3824b085973cd6e2b1b39a1fd6062ecarll         if (!allow_DFP) goto decode_noDFP;
19607cdc376dcb5a4560b0a35d4abcb2146c499756f0dsewardj         if (dis_dfp_roundq( theInstr ))
19608cdc376dcb5a4560b0a35d4abcb2146c499756f0dsewardj            goto decode_success;
19609cdc376dcb5a4560b0a35d4abcb2146c499756f0dsewardj         goto decode_failure;
19610cdc376dcb5a4560b0a35d4abcb2146c499756f0dsewardj
19611cdc376dcb5a4560b0a35d4abcb2146c499756f0dsewardj      default:
19612cdc376dcb5a4560b0a35d4abcb2146c499756f0dsewardj         goto decode_failure;
19613cdc376dcb5a4560b0a35d4abcb2146c499756f0dsewardj      }
196143d870a39e4d145e2f3d9f9a0eeed3475ec934ac1cerion      break;
1961526217b09205cc1801b842ba5ba8f0d83aabca1b4sewardj
1961691ad5368eb6354ad4fabc86f2b2e641736997a38cerion   case 0x13:
19617b85e8bba97fdae7d892f7bfd12e4601307e4721dcerion      switch (opc2) {
19618b85e8bba97fdae7d892f7bfd12e4601307e4721dcerion
19619d953ebb9b04cbad6891676df597bf0c542b1ec89cerion      /* Condition Register Logical Instructions */
19620d953ebb9b04cbad6891676df597bf0c542b1ec89cerion      case 0x101: case 0x081: case 0x121: // crand,  crandc, creqv
19621d953ebb9b04cbad6891676df597bf0c542b1ec89cerion      case 0x0E1: case 0x021: case 0x1C1: // crnand, crnor,  cror
19622d953ebb9b04cbad6891676df597bf0c542b1ec89cerion      case 0x1A1: case 0x0C1: case 0x000: // crorc,  crxor,  mcrf
19623d953ebb9b04cbad6891676df597bf0c542b1ec89cerion         if (dis_cond_logic( theInstr )) goto decode_success;
19624d953ebb9b04cbad6891676df597bf0c542b1ec89cerion         goto decode_failure;
19625d953ebb9b04cbad6891676df597bf0c542b1ec89cerion
19626d953ebb9b04cbad6891676df597bf0c542b1ec89cerion      /* Branch Instructions */
19627d953ebb9b04cbad6891676df597bf0c542b1ec89cerion      case 0x210: case 0x010: // bcctr, bclr
19628dd40fdf58cc8a6fe9466c4f00bdfc9fe9bf00449sewardj         if (dis_branch(theInstr, abiinfo, &dres,
19629aca070a5b3418a6a9b01e3c57a7eb0fbb5050908sewardj                                  resteerOkFn, callback_opaque))
19630c716aea1cafe66ee431dc7d6909c98f18788a028sewardj            goto decode_success;
19631d953ebb9b04cbad6891676df597bf0c542b1ec89cerion         goto decode_failure;
19632d953ebb9b04cbad6891676df597bf0c542b1ec89cerion
19633d953ebb9b04cbad6891676df597bf0c542b1ec89cerion      /* Memory Synchronization Instructions */
19634d953ebb9b04cbad6891676df597bf0c542b1ec89cerion      case 0x096: // isync
19635d953ebb9b04cbad6891676df597bf0c542b1ec89cerion         if (dis_memsync( theInstr )) goto decode_success;
19636d953ebb9b04cbad6891676df597bf0c542b1ec89cerion         goto decode_failure;
1963778850ae9874a90ea625fcee1fd4c359375b7b538carll
19638d953ebb9b04cbad6891676df597bf0c542b1ec89cerion      default:
19639d953ebb9b04cbad6891676df597bf0c542b1ec89cerion         goto decode_failure;
19640b85e8bba97fdae7d892f7bfd12e4601307e4721dcerion      }
19641b85e8bba97fdae7d892f7bfd12e4601307e4721dcerion      break;
196427aa4bbc850d2978cccd8e12cd7c4cfeaa5ab3e4dcerion
19643b0004f748b0f580e733a9dcb9d92f511920d3dd7cerion
19644b85e8bba97fdae7d892f7bfd12e4601307e4721dcerion   case 0x1F:
19645e9d361ab43518b6dfbd3d846f48859534659dee0cerion
19646e9d361ab43518b6dfbd3d846f48859534659dee0cerion      /* For arith instns, bit10 is the OE flag (overflow enable) */
19647e9d361ab43518b6dfbd3d846f48859534659dee0cerion
1964876de5cf615380b23b4b5bcced6541233cd4a93a0cerion      opc2 = IFIELD(theInstr, 1, 9);
19649b85e8bba97fdae7d892f7bfd12e4601307e4721dcerion      switch (opc2) {
19650d953ebb9b04cbad6891676df597bf0c542b1ec89cerion      /* Integer Arithmetic Instructions */
19651d953ebb9b04cbad6891676df597bf0c542b1ec89cerion      case 0x10A: case 0x00A: case 0x08A: // add,   addc,  adde
19652d953ebb9b04cbad6891676df597bf0c542b1ec89cerion      case 0x0EA: case 0x0CA: case 0x1EB: // addme, addze, divw
19653d953ebb9b04cbad6891676df597bf0c542b1ec89cerion      case 0x1CB: case 0x04B: case 0x00B: // divwu, mulhw, mulhwu
19654d953ebb9b04cbad6891676df597bf0c542b1ec89cerion      case 0x0EB: case 0x068: case 0x028: // mullw, neg,   subf
19655d953ebb9b04cbad6891676df597bf0c542b1ec89cerion      case 0x008: case 0x088: case 0x0E8: // subfc, subfe, subfme
196564aa412af1d8166cc11f39a6e721df49431d23618sewardj      case 0x0C8: // subfze
196574aa412af1d8166cc11f39a6e721df49431d23618sewardj         if (dis_int_arith( theInstr )) goto decode_success;
196584aa412af1d8166cc11f39a6e721df49431d23618sewardj         goto decode_failure;
196594aa412af1d8166cc11f39a6e721df49431d23618sewardj
196604aa412af1d8166cc11f39a6e721df49431d23618sewardj      case 0x18B: // divweu (implemented as native insn)
19661e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj      case 0x1AB: // divwe (implemented as native insn)
196624aa412af1d8166cc11f39a6e721df49431d23618sewardj         if (!allow_VX) goto decode_noVX;
19663d953ebb9b04cbad6891676df597bf0c542b1ec89cerion         if (dis_int_arith( theInstr )) goto decode_success;
19664d953ebb9b04cbad6891676df597bf0c542b1ec89cerion         goto decode_failure;
19665f0de28cf1a762b0d6f74c93d3532c89a230673bbcerion
19666f0de28cf1a762b0d6f74c93d3532c89a230673bbcerion      /* 64bit Integer Arithmetic */
19667f0de28cf1a762b0d6f74c93d3532c89a230673bbcerion      case 0x009: case 0x049: case 0x0E9: // mulhdu, mulhd, mulld
196684aa412af1d8166cc11f39a6e721df49431d23618sewardj      case 0x1C9: case 0x1E9: // divdu, divd
196694aa412af1d8166cc11f39a6e721df49431d23618sewardj         if (!mode64) goto decode_failure;
196704aa412af1d8166cc11f39a6e721df49431d23618sewardj         if (dis_int_arith( theInstr )) goto decode_success;
196714aa412af1d8166cc11f39a6e721df49431d23618sewardj         goto decode_failure;
196724aa412af1d8166cc11f39a6e721df49431d23618sewardj
196734aa412af1d8166cc11f39a6e721df49431d23618sewardj      case 0x1A9: //  divde (implemented as native insn)
19674e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj      case 0x189: //  divdeuo (implemented as native insn)
196754aa412af1d8166cc11f39a6e721df49431d23618sewardj         if (!allow_VX) goto decode_noVX;
19676f0de28cf1a762b0d6f74c93d3532c89a230673bbcerion         if (!mode64) goto decode_failure;
19677f0de28cf1a762b0d6f74c93d3532c89a230673bbcerion         if (dis_int_arith( theInstr )) goto decode_success;
19678f0de28cf1a762b0d6f74c93d3532c89a230673bbcerion         goto decode_failure;
19679f0de28cf1a762b0d6f74c93d3532c89a230673bbcerion
196807e84630580f89c1022dde97007bffbf6aef81814sewardj      case 0x1FC:                         // cmpb
196817e84630580f89c1022dde97007bffbf6aef81814sewardj         if (dis_int_logic( theInstr )) goto decode_success;
196827e84630580f89c1022dde97007bffbf6aef81814sewardj         goto decode_failure;
196837e84630580f89c1022dde97007bffbf6aef81814sewardj
19684d953ebb9b04cbad6891676df597bf0c542b1ec89cerion      default:
19685d953ebb9b04cbad6891676df597bf0c542b1ec89cerion         break;  // Fall through...
19686b85e8bba97fdae7d892f7bfd12e4601307e4721dcerion      }
19687b85e8bba97fdae7d892f7bfd12e4601307e4721dcerion
19688e9d361ab43518b6dfbd3d846f48859534659dee0cerion      /* All remaining opcodes use full 10 bits. */
19689e9d361ab43518b6dfbd3d846f48859534659dee0cerion
1969076de5cf615380b23b4b5bcced6541233cd4a93a0cerion      opc2 = IFIELD(theInstr, 1, 10);
19691b85e8bba97fdae7d892f7bfd12e4601307e4721dcerion      switch (opc2) {
19692e9d361ab43518b6dfbd3d846f48859534659dee0cerion      /* Integer Compare Instructions  */
19693e9d361ab43518b6dfbd3d846f48859534659dee0cerion      case 0x000: case 0x020: // cmp, cmpl
19694e9d361ab43518b6dfbd3d846f48859534659dee0cerion         if (dis_int_cmp( theInstr )) goto decode_success;
19695b85e8bba97fdae7d892f7bfd12e4601307e4721dcerion         goto decode_failure;
19696b85e8bba97fdae7d892f7bfd12e4601307e4721dcerion
19697e9d361ab43518b6dfbd3d846f48859534659dee0cerion      /* Integer Logical Instructions */
19698e9d361ab43518b6dfbd3d846f48859534659dee0cerion      case 0x01C: case 0x03C: case 0x01A: // and,  andc,  cntlzw
19699e9d361ab43518b6dfbd3d846f48859534659dee0cerion      case 0x11C: case 0x3BA: case 0x39A: // eqv,  extsb, extsh
19700e9d361ab43518b6dfbd3d846f48859534659dee0cerion      case 0x1DC: case 0x07C: case 0x1BC: // nand, nor,   or
19701e9d361ab43518b6dfbd3d846f48859534659dee0cerion      case 0x19C: case 0x13C:             // orc,  xor
197027e84630580f89c1022dde97007bffbf6aef81814sewardj      case 0x2DF: case 0x25F:            // mftgpr, mffgpr
19703e9d361ab43518b6dfbd3d846f48859534659dee0cerion         if (dis_int_logic( theInstr )) goto decode_success;
19704b85e8bba97fdae7d892f7bfd12e4601307e4721dcerion         goto decode_failure;
19705b85e8bba97fdae7d892f7bfd12e4601307e4721dcerion
197068943d02aa373f45c6e5fdcbe5947620285d442b1carll      case 0x28E: case 0x2AE:             // tbegin., tend.
197078943d02aa373f45c6e5fdcbe5947620285d442b1carll      case 0x2EE: case 0x2CE: case 0x30E: // tsr., tcheck., tabortwc.
197088943d02aa373f45c6e5fdcbe5947620285d442b1carll      case 0x32E: case 0x34E: case 0x36E: // tabortdc., tabortwci., tabortdci.
19709fcce5f8ca9ad1fbb5939b8c94d7470b4d51a7387carll      case 0x38E: case 0x3AE: case 0x3EE: // tabort., treclaim., trechkpt.
197108943d02aa373f45c6e5fdcbe5947620285d442b1carll      if (dis_transactional_memory( theInstr,
197118462d113e3efeacceb304222dada8d85f748295aflorian                                    getUIntPPCendianly( &guest_code[delta + 4]),
197128943d02aa373f45c6e5fdcbe5947620285d442b1carll                                    abiinfo, &dres,
197138943d02aa373f45c6e5fdcbe5947620285d442b1carll                                    resteerOkFn, callback_opaque))
197148943d02aa373f45c6e5fdcbe5947620285d442b1carll            goto decode_success;
197158943d02aa373f45c6e5fdcbe5947620285d442b1carll         goto decode_failure;
197168943d02aa373f45c6e5fdcbe5947620285d442b1carll
19717f0de28cf1a762b0d6f74c93d3532c89a230673bbcerion      /* 64bit Integer Logical Instructions */
1971807b07a966a2fdbcf621251a0c1a8ab84807fb120cerion      case 0x3DA: case 0x03A: // extsw, cntlzd
19719f0de28cf1a762b0d6f74c93d3532c89a230673bbcerion         if (!mode64) goto decode_failure;
19720f0de28cf1a762b0d6f74c93d3532c89a230673bbcerion         if (dis_int_logic( theInstr )) goto decode_success;
19721f0de28cf1a762b0d6f74c93d3532c89a230673bbcerion         goto decode_failure;
19722f0de28cf1a762b0d6f74c93d3532c89a230673bbcerion
197237e84630580f89c1022dde97007bffbf6aef81814sewardj         /* 64bit Integer Parity Instructions */
19724bb3f40144f5e72dfbba740d4b2f090b4a91c3876carll      case 0xba: // prtyd
19725bb3f40144f5e72dfbba740d4b2f090b4a91c3876carll         if (!mode64) goto decode_failure;
19726bb3f40144f5e72dfbba740d4b2f090b4a91c3876carll         if (dis_int_parity( theInstr )) goto decode_success;
19727bb3f40144f5e72dfbba740d4b2f090b4a91c3876carll         goto decode_failure;
19728bb3f40144f5e72dfbba740d4b2f090b4a91c3876carll
19729bb3f40144f5e72dfbba740d4b2f090b4a91c3876carll      case 0x9a: // prtyw
197307e84630580f89c1022dde97007bffbf6aef81814sewardj         if (dis_int_parity( theInstr )) goto decode_success;
197317e84630580f89c1022dde97007bffbf6aef81814sewardj         goto decode_failure;
197327e84630580f89c1022dde97007bffbf6aef81814sewardj
19733e9d361ab43518b6dfbd3d846f48859534659dee0cerion      /* Integer Shift Instructions */
19734e9d361ab43518b6dfbd3d846f48859534659dee0cerion      case 0x018: case 0x318: case 0x338: // slw, sraw, srawi
19735e9d361ab43518b6dfbd3d846f48859534659dee0cerion      case 0x218:                         // srw
19736e9d361ab43518b6dfbd3d846f48859534659dee0cerion         if (dis_int_shift( theInstr )) goto decode_success;
19737b85e8bba97fdae7d892f7bfd12e4601307e4721dcerion         goto decode_failure;
19738b85e8bba97fdae7d892f7bfd12e4601307e4721dcerion
19739f0de28cf1a762b0d6f74c93d3532c89a230673bbcerion      /* 64bit Integer Shift Instructions */
19740f0de28cf1a762b0d6f74c93d3532c89a230673bbcerion      case 0x01B: case 0x31A: // sld, srad
1974107b07a966a2fdbcf621251a0c1a8ab84807fb120cerion      case 0x33A: case 0x33B: // sradi
19742f0de28cf1a762b0d6f74c93d3532c89a230673bbcerion      case 0x21B:             // srd
19743f0de28cf1a762b0d6f74c93d3532c89a230673bbcerion         if (!mode64) goto decode_failure;
19744f0de28cf1a762b0d6f74c93d3532c89a230673bbcerion         if (dis_int_shift( theInstr )) goto decode_success;
19745f0de28cf1a762b0d6f74c93d3532c89a230673bbcerion         goto decode_failure;
19746f0de28cf1a762b0d6f74c93d3532c89a230673bbcerion
19747e9d361ab43518b6dfbd3d846f48859534659dee0cerion      /* Integer Load Instructions */
19748e9d361ab43518b6dfbd3d846f48859534659dee0cerion      case 0x057: case 0x077: case 0x157: // lbzx,  lbzux, lhax
19749e9d361ab43518b6dfbd3d846f48859534659dee0cerion      case 0x177: case 0x117: case 0x137: // lhaux, lhzx,  lhzux
19750e9d361ab43518b6dfbd3d846f48859534659dee0cerion      case 0x017: case 0x037:             // lwzx,  lwzux
19751e9d361ab43518b6dfbd3d846f48859534659dee0cerion         if (dis_int_load( theInstr )) goto decode_success;
19752b85e8bba97fdae7d892f7bfd12e4601307e4721dcerion         goto decode_failure;
19753b85e8bba97fdae7d892f7bfd12e4601307e4721dcerion
19754f0de28cf1a762b0d6f74c93d3532c89a230673bbcerion      /* 64bit Integer Load Instructions */
19755f0de28cf1a762b0d6f74c93d3532c89a230673bbcerion      case 0x035: case 0x015:             // ldux,  ldx
19756f0de28cf1a762b0d6f74c93d3532c89a230673bbcerion      case 0x175: case 0x155:             // lwaux, lwax
19757f0de28cf1a762b0d6f74c93d3532c89a230673bbcerion         if (!mode64) goto decode_failure;
19758f0de28cf1a762b0d6f74c93d3532c89a230673bbcerion         if (dis_int_load( theInstr )) goto decode_success;
19759f0de28cf1a762b0d6f74c93d3532c89a230673bbcerion         goto decode_failure;
19760f0de28cf1a762b0d6f74c93d3532c89a230673bbcerion
19761b51f0f4f33256638ed953156a2635aa739b232f1sewardj      /* Integer Store Instructions */
19762e9d361ab43518b6dfbd3d846f48859534659dee0cerion      case 0x0F7: case 0x0D7: case 0x1B7: // stbux, stbx,  sthux
19763e9d361ab43518b6dfbd3d846f48859534659dee0cerion      case 0x197: case 0x0B7: case 0x097: // sthx,  stwux, stwx
19764dd40fdf58cc8a6fe9466c4f00bdfc9fe9bf00449sewardj         if (dis_int_store( theInstr, abiinfo )) goto decode_success;
19765b85e8bba97fdae7d892f7bfd12e4601307e4721dcerion         goto decode_failure;
19766b85e8bba97fdae7d892f7bfd12e4601307e4721dcerion
19767f0de28cf1a762b0d6f74c93d3532c89a230673bbcerion      /* 64bit Integer Store Instructions */
19768f0de28cf1a762b0d6f74c93d3532c89a230673bbcerion      case 0x0B5: case 0x095: // stdux, stdx
19769f0de28cf1a762b0d6f74c93d3532c89a230673bbcerion         if (!mode64) goto decode_failure;
19770dd40fdf58cc8a6fe9466c4f00bdfc9fe9bf00449sewardj         if (dis_int_store( theInstr, abiinfo )) goto decode_success;
19771f0de28cf1a762b0d6f74c93d3532c89a230673bbcerion         goto decode_failure;
19772f0de28cf1a762b0d6f74c93d3532c89a230673bbcerion
19773602857d30b8aa87c202517e2be6c7df6d40ee922sewardj      /* Integer Load and Store with Byte Reverse Instructions */
19774bb3f40144f5e72dfbba740d4b2f090b4a91c3876carll      case 0x214: case 0x294: // ldbrx, stdbrx
19775bb3f40144f5e72dfbba740d4b2f090b4a91c3876carll         if (!mode64) goto decode_failure;
19776bb3f40144f5e72dfbba740d4b2f090b4a91c3876carll         if (dis_int_ldst_rev( theInstr )) goto decode_success;
19777bb3f40144f5e72dfbba740d4b2f090b4a91c3876carll         goto decode_failure;
19778bb3f40144f5e72dfbba740d4b2f090b4a91c3876carll
19779bb3f40144f5e72dfbba740d4b2f090b4a91c3876carll      case 0x216: case 0x316: case 0x296:    // lwbrx, lhbrx, stwbrx
19780bb3f40144f5e72dfbba740d4b2f090b4a91c3876carll      case 0x396:                            // sthbrx
19781602857d30b8aa87c202517e2be6c7df6d40ee922sewardj         if (dis_int_ldst_rev( theInstr )) goto decode_success;
19782602857d30b8aa87c202517e2be6c7df6d40ee922sewardj         goto decode_failure;
19783602857d30b8aa87c202517e2be6c7df6d40ee922sewardj
1978487e651f40360a8f1c9418710e79c482028759f8csewardj      /* Integer Load and Store String Instructions */
1978587e651f40360a8f1c9418710e79c482028759f8csewardj      case 0x255: case 0x215: case 0x2D5: // lswi, lswx, stswi
1978687e651f40360a8f1c9418710e79c482028759f8csewardj      case 0x295: {                       // stswx
1978787e651f40360a8f1c9418710e79c482028759f8csewardj         Bool stopHere = False;
1978887e651f40360a8f1c9418710e79c482028759f8csewardj         Bool ok = dis_int_ldst_str( theInstr, &stopHere );
1978987e651f40360a8f1c9418710e79c482028759f8csewardj         if (!ok) goto decode_failure;
1979087e651f40360a8f1c9418710e79c482028759f8csewardj         if (stopHere) {
197913dee849ec7c38746749065e67dc53b75daa7617dsewardj            putGST( PPC_GST_CIA, mkSzImm(ty, nextInsnAddr()) );
197923dee849ec7c38746749065e67dc53b75daa7617dsewardj            dres.jk_StopHere = Ijk_Boring;
197933dee849ec7c38746749065e67dc53b75daa7617dsewardj            dres.whatNext    = Dis_StopHere;
1979487e651f40360a8f1c9418710e79c482028759f8csewardj         }
1979587e651f40360a8f1c9418710e79c482028759f8csewardj         goto decode_success;
1979687e651f40360a8f1c9418710e79c482028759f8csewardj      }
19797b85e8bba97fdae7d892f7bfd12e4601307e4721dcerion
19798e9d361ab43518b6dfbd3d846f48859534659dee0cerion      /* Memory Synchronization Instructions */
19799d826889bd512ded2fbbc4781c595ecf0513f46f6carll      case 0x034: case 0x074:             // lbarx, lharx
19800d826889bd512ded2fbbc4781c595ecf0513f46f6carll      case 0x2B6: case 0x2D6:             // stbcx, sthcx
19801d826889bd512ded2fbbc4781c595ecf0513f46f6carll         if (!allow_isa_2_07) goto decode_noP8;
19802d826889bd512ded2fbbc4781c595ecf0513f46f6carll         if (dis_memsync( theInstr )) goto decode_success;
19803d826889bd512ded2fbbc4781c595ecf0513f46f6carll         goto decode_failure;
19804d826889bd512ded2fbbc4781c595ecf0513f46f6carll
19805e9d361ab43518b6dfbd3d846f48859534659dee0cerion      case 0x356: case 0x014: case 0x096: // eieio, lwarx, stwcx.
19806e9d361ab43518b6dfbd3d846f48859534659dee0cerion      case 0x256:                         // sync
19807e9d361ab43518b6dfbd3d846f48859534659dee0cerion         if (dis_memsync( theInstr )) goto decode_success;
19808b85e8bba97fdae7d892f7bfd12e4601307e4721dcerion         goto decode_failure;
19809b85e8bba97fdae7d892f7bfd12e4601307e4721dcerion
19810f0de28cf1a762b0d6f74c93d3532c89a230673bbcerion      /* 64bit Memory Synchronization Instructions */
19811f0de28cf1a762b0d6f74c93d3532c89a230673bbcerion      case 0x054: case 0x0D6: // ldarx, stdcx.
19812f0de28cf1a762b0d6f74c93d3532c89a230673bbcerion         if (!mode64) goto decode_failure;
19813f0de28cf1a762b0d6f74c93d3532c89a230673bbcerion         if (dis_memsync( theInstr )) goto decode_success;
19814f0de28cf1a762b0d6f74c93d3532c89a230673bbcerion         goto decode_failure;
19815f0de28cf1a762b0d6f74c93d3532c89a230673bbcerion
1981678850ae9874a90ea625fcee1fd4c359375b7b538carll      case 0x114: case 0x0B6: // lqarx, stqcx.
1981778850ae9874a90ea625fcee1fd4c359375b7b538carll         if (dis_memsync( theInstr )) goto decode_success;
1981878850ae9874a90ea625fcee1fd4c359375b7b538carll         goto decode_failure;
1981978850ae9874a90ea625fcee1fd4c359375b7b538carll
19820e9d361ab43518b6dfbd3d846f48859534659dee0cerion      /* Processor Control Instructions */
1982178850ae9874a90ea625fcee1fd4c359375b7b538carll      case 0x33:  case 0x73: // mfvsrd, mfvsrwz
1982278850ae9874a90ea625fcee1fd4c359375b7b538carll      case 0xB3:  case 0xD3: case 0xF3: // mtvsrd, mtvsrwa, mtvsrwz
19823e9d361ab43518b6dfbd3d846f48859534659dee0cerion      case 0x200: case 0x013: case 0x153: // mcrxr, mfcr,  mfspr
19824e9d361ab43518b6dfbd3d846f48859534659dee0cerion      case 0x173: case 0x090: case 0x1D3: // mftb,  mtcrf, mtspr
1982578850ae9874a90ea625fcee1fd4c359375b7b538carll      case 0x220:                         // mcrxrt
19826dd40fdf58cc8a6fe9466c4f00bdfc9fe9bf00449sewardj         if (dis_proc_ctl( abiinfo, theInstr )) goto decode_success;
19827b85e8bba97fdae7d892f7bfd12e4601307e4721dcerion         goto decode_failure;
19828b85e8bba97fdae7d892f7bfd12e4601307e4721dcerion
19829e9d361ab43518b6dfbd3d846f48859534659dee0cerion      /* Cache Management Instructions */
19830e9d361ab43518b6dfbd3d846f48859534659dee0cerion      case 0x2F6: case 0x056: case 0x036: // dcba, dcbf,   dcbst
19831e9d361ab43518b6dfbd3d846f48859534659dee0cerion      case 0x116: case 0x0F6: case 0x3F6: // dcbt, dcbtst, dcbz
19832e9d361ab43518b6dfbd3d846f48859534659dee0cerion      case 0x3D6:                         // icbi
198331f5fe1fc3a37ca729925e8eec25aa1025b4a6cdbcarll         if (dis_cache_manage( theInstr, &dres, archinfo ))
19834d94b73a4ece194130f7a59cca9262d44cf9dbb91sewardj            goto decode_success;
19835b85e8bba97fdae7d892f7bfd12e4601307e4721dcerion         goto decode_failure;
19836b85e8bba97fdae7d892f7bfd12e4601307e4721dcerion
19837b51f0f4f33256638ed953156a2635aa739b232f1sewardj//zz       /* External Control Instructions */
19838b51f0f4f33256638ed953156a2635aa739b232f1sewardj//zz       case 0x136: case 0x1B6: // eciwx, ecowx
19839b51f0f4f33256638ed953156a2635aa739b232f1sewardj//zz          DIP("external control op => not implemented\n");
19840b51f0f4f33256638ed953156a2635aa739b232f1sewardj//zz          goto decode_failure;
1984159c0d8f0997bd03e0f8d90b9144dc0aeb6fe9a3asewardj
1984259c0d8f0997bd03e0f8d90b9144dc0aeb6fe9a3asewardj      /* Trap Instructions */
19843bb3f40144f5e72dfbba740d4b2f090b4a91c3876carll      case 0x004:             // tw
19844bb3f40144f5e72dfbba740d4b2f090b4a91c3876carll         if (dis_trap(theInstr, &dres)) goto decode_success;
19845bb3f40144f5e72dfbba740d4b2f090b4a91c3876carll         goto decode_failure;
19846bb3f40144f5e72dfbba740d4b2f090b4a91c3876carll
19847bb3f40144f5e72dfbba740d4b2f090b4a91c3876carll      case 0x044:             // td
19848bb3f40144f5e72dfbba740d4b2f090b4a91c3876carll         if (!mode64) goto decode_failure;
1984959c0d8f0997bd03e0f8d90b9144dc0aeb6fe9a3asewardj         if (dis_trap(theInstr, &dres)) goto decode_success;
1985059c0d8f0997bd03e0f8d90b9144dc0aeb6fe9a3asewardj         goto decode_failure;
19851e14bb9f862843c6b804097c124961b5567ded4f1sewardj
19852e14bb9f862843c6b804097c124961b5567ded4f1sewardj      /* Floating Point Load Instructions */
19853e14bb9f862843c6b804097c124961b5567ded4f1sewardj      case 0x217: case 0x237: case 0x257: // lfsx, lfsux, lfdx
19854e14bb9f862843c6b804097c124961b5567ded4f1sewardj      case 0x277:                         // lfdux
198555117ce116f47141cb23d1b49cc826e19323add97sewardj         if (!allow_F) goto decode_noF;
19856e14bb9f862843c6b804097c124961b5567ded4f1sewardj         if (dis_fp_load( theInstr )) goto decode_success;
19857e14bb9f862843c6b804097c124961b5567ded4f1sewardj         goto decode_failure;
19858e14bb9f862843c6b804097c124961b5567ded4f1sewardj
19859e14bb9f862843c6b804097c124961b5567ded4f1sewardj      /* Floating Point Store Instructions */
19860e14bb9f862843c6b804097c124961b5567ded4f1sewardj      case 0x297: case 0x2B7: case 0x2D7: // stfs,  stfsu, stfd
198615117ce116f47141cb23d1b49cc826e19323add97sewardj      case 0x2F7:                         // stfdu, stfiwx
198625117ce116f47141cb23d1b49cc826e19323add97sewardj         if (!allow_F) goto decode_noF;
198635117ce116f47141cb23d1b49cc826e19323add97sewardj         if (dis_fp_store( theInstr )) goto decode_success;
198645117ce116f47141cb23d1b49cc826e19323add97sewardj         goto decode_failure;
198655117ce116f47141cb23d1b49cc826e19323add97sewardj      case 0x3D7:                         // stfiwx
198665117ce116f47141cb23d1b49cc826e19323add97sewardj         if (!allow_F) goto decode_noF;
198675117ce116f47141cb23d1b49cc826e19323add97sewardj         if (!allow_GX) goto decode_noGX;
19868e14bb9f862843c6b804097c124961b5567ded4f1sewardj         if (dis_fp_store( theInstr )) goto decode_success;
19869e14bb9f862843c6b804097c124961b5567ded4f1sewardj         goto decode_failure;
19870e14bb9f862843c6b804097c124961b5567ded4f1sewardj
198717e84630580f89c1022dde97007bffbf6aef81814sewardj         /* Floating Point Double Pair Indexed Instructions */
198727e84630580f89c1022dde97007bffbf6aef81814sewardj      case 0x317: // lfdpx (Power6)
198737e84630580f89c1022dde97007bffbf6aef81814sewardj      case 0x397: // stfdpx (Power6)
198747e84630580f89c1022dde97007bffbf6aef81814sewardj         if (!allow_F) goto decode_noF;
198757e84630580f89c1022dde97007bffbf6aef81814sewardj         if (dis_fp_pair(theInstr)) goto decode_success;
198767e84630580f89c1022dde97007bffbf6aef81814sewardj         goto decode_failure;
198777e84630580f89c1022dde97007bffbf6aef81814sewardj
198787e84630580f89c1022dde97007bffbf6aef81814sewardj      case 0x357:                         // lfiwax
198797e84630580f89c1022dde97007bffbf6aef81814sewardj         if (!allow_F) goto decode_noF;
198807e84630580f89c1022dde97007bffbf6aef81814sewardj         if (dis_fp_load( theInstr )) goto decode_success;
198817e84630580f89c1022dde97007bffbf6aef81814sewardj         goto decode_failure;
198827e84630580f89c1022dde97007bffbf6aef81814sewardj
1988366d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj      case 0x377:                         // lfiwzx
1988466d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj         if (!allow_F) goto decode_noF;
1988566d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj         if (dis_fp_load( theInstr )) goto decode_success;
1988666d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj         goto decode_failure;
1988766d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj
1988832aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion      /* AltiVec instructions */
1988932aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion
1989032aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion      /* AV Cache Control - Data streams */
1989132aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion      case 0x156: case 0x176: case 0x336: // dst, dstst, dss
198925117ce116f47141cb23d1b49cc826e19323add97sewardj         if (!allow_V) goto decode_noV;
1989332aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion         if (dis_av_datastream( theInstr )) goto decode_success;
1989432aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion         goto decode_failure;
19895a982c0503d8c0c6069ae453bfe70657bd2c134aecerion
19896a982c0503d8c0c6069ae453bfe70657bd2c134aecerion      /* AV Load */
19897a982c0503d8c0c6069ae453bfe70657bd2c134aecerion      case 0x006: case 0x026:             // lvsl, lvsr
19898a982c0503d8c0c6069ae453bfe70657bd2c134aecerion      case 0x007: case 0x027: case 0x047: // lvebx, lvehx, lvewx
19899a982c0503d8c0c6069ae453bfe70657bd2c134aecerion      case 0x067: case 0x167:             // lvx, lvxl
199005117ce116f47141cb23d1b49cc826e19323add97sewardj         if (!allow_V) goto decode_noV;
19901dd40fdf58cc8a6fe9466c4f00bdfc9fe9bf00449sewardj         if (dis_av_load( abiinfo, theInstr )) goto decode_success;
19902a982c0503d8c0c6069ae453bfe70657bd2c134aecerion         goto decode_failure;
19903a982c0503d8c0c6069ae453bfe70657bd2c134aecerion
19904a982c0503d8c0c6069ae453bfe70657bd2c134aecerion      /* AV Store */
19905a982c0503d8c0c6069ae453bfe70657bd2c134aecerion      case 0x087: case 0x0A7: case 0x0C7: // stvebx, stvehx, stvewx
19906a982c0503d8c0c6069ae453bfe70657bd2c134aecerion      case 0x0E7: case 0x1E7:             // stvx, stvxl
199075117ce116f47141cb23d1b49cc826e19323add97sewardj         if (!allow_V) goto decode_noV;
19908a982c0503d8c0c6069ae453bfe70657bd2c134aecerion         if (dis_av_store( theInstr )) goto decode_success;
19909a982c0503d8c0c6069ae453bfe70657bd2c134aecerion         goto decode_failure;
19910a982c0503d8c0c6069ae453bfe70657bd2c134aecerion
1991166d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj      /* VSX Load */
199126c758b64a77c254065ab7450576bbd3a0b583595carll      case 0x00C: // lxsiwzx
199136c758b64a77c254065ab7450576bbd3a0b583595carll      case 0x04C: // lxsiwax
199146c758b64a77c254065ab7450576bbd3a0b583595carll      case 0x20C: // lxsspx
1991566d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj      case 0x24C: // lxsdx
1991666d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj      case 0x34C: // lxvd2x
1991766d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj      case 0x14C: // lxvdsx
1991866d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj      case 0x30C: // lxvw4x
19919dc7948f8051acfd10087c8e3b66304c0ba0d1b37florian        // All of these VSX load instructions use some VMX facilities, so
19920dc7948f8051acfd10087c8e3b66304c0ba0d1b37florian        // if allow_V is not set, we'll skip trying to decode.
19921dc7948f8051acfd10087c8e3b66304c0ba0d1b37florian        if (!allow_V) goto decode_noV;
19922dc7948f8051acfd10087c8e3b66304c0ba0d1b37florian
199231f5fe1fc3a37ca729925e8eec25aa1025b4a6cdbcarll	if (dis_vx_load( theInstr )) goto decode_success;
1992466d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj          goto decode_failure;
1992566d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj
1992666d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj      /* VSX Store */
199276c758b64a77c254065ab7450576bbd3a0b583595carll      case 0x08C: // stxsiwx
199286c758b64a77c254065ab7450576bbd3a0b583595carll      case 0x28C: // stxsspx
1992966d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj      case 0x2CC: // stxsdx
1993066d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj      case 0x3CC: // stxvd2x
1993166d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj      case 0x38C: // stxvw4x
19932dc7948f8051acfd10087c8e3b66304c0ba0d1b37florian        // All of these VSX store instructions use some VMX facilities, so
19933dc7948f8051acfd10087c8e3b66304c0ba0d1b37florian        // if allow_V is not set, we'll skip trying to decode.
19934dc7948f8051acfd10087c8e3b66304c0ba0d1b37florian        if (!allow_V) goto decode_noV;
19935dc7948f8051acfd10087c8e3b66304c0ba0d1b37florian
199361f5fe1fc3a37ca729925e8eec25aa1025b4a6cdbcarll	if (dis_vx_store( theInstr )) goto decode_success;
1993766d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj    	  goto decode_failure;
1993866d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj
1993966d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj      /* Miscellaneous ISA 2.06 instructions */
1994066d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj      case 0x1FA: // popcntd
19941e71e56a90e91ce37b0ee846a4ff94493d59f2095sewardj      case 0x17A: // popcntw
19942738d9dddf788cd66fc04081f5fca872f38859813philippe      case 0x7A:  // popcntb
199431f5fe1fc3a37ca729925e8eec25aa1025b4a6cdbcarll	  if (dis_int_logic( theInstr )) goto decode_success;
1994466d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj    	  goto decode_failure;
1994566d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj
199464aa412af1d8166cc11f39a6e721df49431d23618sewardj      case 0x0FC: // bpermd
19947bb3f40144f5e72dfbba740d4b2f090b4a91c3876carll         if (!mode64) goto decode_failure;
199484aa412af1d8166cc11f39a6e721df49431d23618sewardj         if (dis_int_logic( theInstr )) goto decode_success;
199494aa412af1d8166cc11f39a6e721df49431d23618sewardj         goto decode_failure;
199504aa412af1d8166cc11f39a6e721df49431d23618sewardj
19951a982c0503d8c0c6069ae453bfe70657bd2c134aecerion      default:
19952cb07be2425eee24e72932432059663e1e620e681sewardj         /* Deal with some other cases that we would otherwise have
19953cb07be2425eee24e72932432059663e1e620e681sewardj            punted on. */
19954cb07be2425eee24e72932432059663e1e620e681sewardj         /* --- ISEL (PowerISA_V2.05.pdf, p74) --- */
199551685c2887bec68514f0830a45c082bbcfe5fa3e2sewardj         /* only decode this insn when reserved bit 0 (31 in IBM's
199561685c2887bec68514f0830a45c082bbcfe5fa3e2sewardj            notation) is zero */
199571685c2887bec68514f0830a45c082bbcfe5fa3e2sewardj         if (IFIELD(theInstr, 0, 6) == (15<<1)) {
19958cb07be2425eee24e72932432059663e1e620e681sewardj            UInt rT = ifieldRegDS( theInstr );
19959cb07be2425eee24e72932432059663e1e620e681sewardj            UInt rA = ifieldRegA( theInstr );
19960cb07be2425eee24e72932432059663e1e620e681sewardj            UInt rB = ifieldRegB( theInstr );
19961cb07be2425eee24e72932432059663e1e620e681sewardj            UInt bi = ifieldRegC( theInstr );
19962cb07be2425eee24e72932432059663e1e620e681sewardj            putIReg(
19963cb07be2425eee24e72932432059663e1e620e681sewardj               rT,
1996499dd03e04a6914d90d5fee727d61d76905334becflorian               IRExpr_ITE( binop(Iop_CmpNE32, getCRbit( bi ), mkU32(0)),
1996599dd03e04a6914d90d5fee727d61d76905334becflorian                           rA == 0 ? (mode64 ? mkU64(0) : mkU32(0))
1996699dd03e04a6914d90d5fee727d61d76905334becflorian                                   : getIReg(rA),
1996799dd03e04a6914d90d5fee727d61d76905334becflorian                           getIReg(rB))
1996899dd03e04a6914d90d5fee727d61d76905334becflorian
19969cb07be2425eee24e72932432059663e1e620e681sewardj            );
19970cb07be2425eee24e72932432059663e1e620e681sewardj            DIP("isel r%u,r%u,r%u,crb%u\n", rT,rA,rB,bi);
19971cb07be2425eee24e72932432059663e1e620e681sewardj            goto decode_success;
19972cb07be2425eee24e72932432059663e1e620e681sewardj         }
19973a982c0503d8c0c6069ae453bfe70657bd2c134aecerion         goto decode_failure;
19974a982c0503d8c0c6069ae453bfe70657bd2c134aecerion      }
19975a982c0503d8c0c6069ae453bfe70657bd2c134aecerion      break;
19976a982c0503d8c0c6069ae453bfe70657bd2c134aecerion
19977a982c0503d8c0c6069ae453bfe70657bd2c134aecerion
1997832aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion   case 0x04:
1997932aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion      /* AltiVec instructions */
1998032aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion
1998176de5cf615380b23b4b5bcced6541233cd4a93a0cerion      opc2 = IFIELD(theInstr, 0, 6);
1998232aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion      switch (opc2) {
1998332aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion      /* AV Mult-Add, Mult-Sum */
1998432aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion      case 0x20: case 0x21: case 0x22: // vmhaddshs, vmhraddshs, vmladduhm
1998532aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion      case 0x24: case 0x25: case 0x26: // vmsumubm, vmsummbm, vmsumuhm
1998632aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion      case 0x27: case 0x28: case 0x29: // vmsumuhs, vmsumshm, vmsumshs
199875117ce116f47141cb23d1b49cc826e19323add97sewardj         if (!allow_V) goto decode_noV;
1998832aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion         if (dis_av_multarith( theInstr )) goto decode_success;
1998932aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion         goto decode_failure;
1999032aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion
1999132aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion      /* AV Permutations */
1999232aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion      case 0x2A:                       // vsel
1999332aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion      case 0x2B:                       // vperm
1999432aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion      case 0x2C:                       // vsldoi
199955117ce116f47141cb23d1b49cc826e19323add97sewardj         if (!allow_V) goto decode_noV;
1999692d9d876af80d14fa2f319f7109964f2d6231f15cerion         if (dis_av_permute( theInstr )) goto decode_success;
1999732aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion         goto decode_failure;
1999832aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion
199997deaf9552b546b847528cf39b38898fb7742b5f5carll      case 0x2D:                       // vpermxor
200007deaf9552b546b847528cf39b38898fb7742b5f5carll         if (!allow_isa_2_07) goto decode_noP8;
200017deaf9552b546b847528cf39b38898fb7742b5f5carll         if (dis_av_permute( theInstr )) goto decode_success;
200027deaf9552b546b847528cf39b38898fb7742b5f5carll         goto decode_failure;
200037deaf9552b546b847528cf39b38898fb7742b5f5carll
2000432aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion      /* AV Floating Point Mult-Add/Sub */
2000532aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion      case 0x2E: case 0x2F:            // vmaddfp, vnmsubfp
200065117ce116f47141cb23d1b49cc826e19323add97sewardj         if (!allow_V) goto decode_noV;
2000732aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion         if (dis_av_fp_arith( theInstr )) goto decode_success;
2000832aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion         goto decode_failure;
2000932aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion
2001060c6bac19ffe055cabab554e7877d73096a8bf17carll      case 0x3D: case 0x3C:            // vaddecuq, vaddeuqm
2001160c6bac19ffe055cabab554e7877d73096a8bf17carll      case 0x3F: case 0x3E:            // vsubecuq, vsubeuqm
2001260c6bac19ffe055cabab554e7877d73096a8bf17carll         if (!allow_V) goto decode_noV;
2001360c6bac19ffe055cabab554e7877d73096a8bf17carll         if (dis_av_quad( theInstr)) goto decode_success;
2001460c6bac19ffe055cabab554e7877d73096a8bf17carll         goto decode_failure;
2001560c6bac19ffe055cabab554e7877d73096a8bf17carll
2001632aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion      default:
2001732aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion         break;  // Fall through...
2001832aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion      }
2001932aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion
200207deaf9552b546b847528cf39b38898fb7742b5f5carll      opc2 = IFIELD(theInstr, 0, 9);
200217deaf9552b546b847528cf39b38898fb7742b5f5carll      switch (opc2) {
200227deaf9552b546b847528cf39b38898fb7742b5f5carll      /* BCD arithmetic */
200237deaf9552b546b847528cf39b38898fb7742b5f5carll      case 0x1: case 0x41:             // bcdadd, bcdsub
200247deaf9552b546b847528cf39b38898fb7742b5f5carll         if (!allow_isa_2_07) goto decode_noP8;
200257deaf9552b546b847528cf39b38898fb7742b5f5carll         if (dis_av_bcd( theInstr )) goto decode_success;
200267deaf9552b546b847528cf39b38898fb7742b5f5carll         goto decode_failure;
200277deaf9552b546b847528cf39b38898fb7742b5f5carll
200287deaf9552b546b847528cf39b38898fb7742b5f5carll      default:
200297deaf9552b546b847528cf39b38898fb7742b5f5carll         break;  // Fall through...
200307deaf9552b546b847528cf39b38898fb7742b5f5carll      }
200317deaf9552b546b847528cf39b38898fb7742b5f5carll
2003276de5cf615380b23b4b5bcced6541233cd4a93a0cerion      opc2 = IFIELD(theInstr, 0, 11);
2003332aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion      switch (opc2) {
2003432aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion      /* AV Arithmetic */
2003532aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion      case 0x180:                         // vaddcuw
2003632aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion      case 0x000: case 0x040: case 0x080: // vaddubm, vadduhm, vadduwm
2003732aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion      case 0x200: case 0x240: case 0x280: // vaddubs, vadduhs, vadduws
2003832aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion      case 0x300: case 0x340: case 0x380: // vaddsbs, vaddshs, vaddsws
2003932aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion      case 0x580:                         // vsubcuw
2004032aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion      case 0x400: case 0x440: case 0x480: // vsububm, vsubuhm, vsubuwm
2004132aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion      case 0x600: case 0x640: case 0x680: // vsububs, vsubuhs, vsubuws
2004232aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion      case 0x700: case 0x740: case 0x780: // vsubsbs, vsubshs, vsubsws
2004332aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion      case 0x402: case 0x442: case 0x482: // vavgub, vavguh, vavguw
2004432aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion      case 0x502: case 0x542: case 0x582: // vavgsb, vavgsh, vavgsw
2004532aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion      case 0x002: case 0x042: case 0x082: // vmaxub, vmaxuh, vmaxuw
2004632aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion      case 0x102: case 0x142: case 0x182: // vmaxsb, vmaxsh, vmaxsw
2004732aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion      case 0x202: case 0x242: case 0x282: // vminub, vminuh, vminuw
2004832aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion      case 0x302: case 0x342: case 0x382: // vminsb, vminsh, vminsw
2004932aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion      case 0x008: case 0x048:             // vmuloub, vmulouh
2005032aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion      case 0x108: case 0x148:             // vmulosb, vmulosh
2005132aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion      case 0x208: case 0x248:             // vmuleub, vmuleuh
2005232aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion      case 0x308: case 0x348:             // vmulesb, vmulesh
2005332aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion      case 0x608: case 0x708: case 0x648: // vsum4ubs, vsum4sbs, vsum4shs
2005432aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion      case 0x688: case 0x788:             // vsum2sws, vsumsws
200555117ce116f47141cb23d1b49cc826e19323add97sewardj         if (!allow_V) goto decode_noV;
2005632aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion         if (dis_av_arith( theInstr )) goto decode_success;
2005732aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion         goto decode_failure;
2005832aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion
2005948ae46b56cef87c90638b25d6b2462c475033da8carll      case 0x088: case 0x089:             // vmulouw, vmuluwm
2006048ae46b56cef87c90638b25d6b2462c475033da8carll      case 0x0C0: case 0x0C2:             // vaddudm, vmaxud
2006148ae46b56cef87c90638b25d6b2462c475033da8carll      case 0x1C2: case 0x2C2: case 0x3C2: // vnaxsd, vminud, vminsd
2006248ae46b56cef87c90638b25d6b2462c475033da8carll      case 0x188: case 0x288: case 0x388: // vmulosw, vmuleuw, vmulesw
2006348ae46b56cef87c90638b25d6b2462c475033da8carll      case 0x4C0:                         // vsubudm
200640c74bb5aa3240f693df0568d578baabf0c376dc4carll         if (!allow_isa_2_07) goto decode_noP8;
200650c74bb5aa3240f693df0568d578baabf0c376dc4carll         if (dis_av_arith( theInstr )) goto decode_success;
200660c74bb5aa3240f693df0568d578baabf0c376dc4carll         goto decode_failure;
200670c74bb5aa3240f693df0568d578baabf0c376dc4carll
200687deaf9552b546b847528cf39b38898fb7742b5f5carll      /* AV Polynomial Vector Multiply Add */
200697deaf9552b546b847528cf39b38898fb7742b5f5carll      case 0x408: case 0x448:            // vpmsumb, vpmsumd
200707deaf9552b546b847528cf39b38898fb7742b5f5carll      case 0x488: case 0x4C8:            // vpmsumw, vpmsumh
200717deaf9552b546b847528cf39b38898fb7742b5f5carll         if (!allow_isa_2_07) goto decode_noP8;
200727deaf9552b546b847528cf39b38898fb7742b5f5carll         if (dis_av_polymultarith( theInstr )) goto decode_success;
200737deaf9552b546b847528cf39b38898fb7742b5f5carll         goto decode_failure;
200747deaf9552b546b847528cf39b38898fb7742b5f5carll
2007532aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion      /* AV Rotate, Shift */
2007632aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion      case 0x004: case 0x044: case 0x084: // vrlb, vrlh, vrlw
2007732aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion      case 0x104: case 0x144: case 0x184: // vslb, vslh, vslw
2007832aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion      case 0x204: case 0x244: case 0x284: // vsrb, vsrh, vsrw
2007932aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion      case 0x304: case 0x344: case 0x384: // vsrab, vsrah, vsraw
2008032aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion      case 0x1C4: case 0x2C4:             // vsl, vsr
2008132aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion      case 0x40C: case 0x44C:             // vslo, vsro
200825117ce116f47141cb23d1b49cc826e19323add97sewardj         if (!allow_V) goto decode_noV;
2008332aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion         if (dis_av_shift( theInstr )) goto decode_success;
2008432aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion         goto decode_failure;
2008532aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion
2008648ae46b56cef87c90638b25d6b2462c475033da8carll      case 0x0C4:                         // vrld
2008748ae46b56cef87c90638b25d6b2462c475033da8carll      case 0x3C4: case 0x5C4: case 0x6C4: // vsrad, vsld, vsrd
2008848ae46b56cef87c90638b25d6b2462c475033da8carll          if (!allow_isa_2_07) goto decode_noP8;
2008948ae46b56cef87c90638b25d6b2462c475033da8carll          if (dis_av_shift( theInstr )) goto decode_success;
2009048ae46b56cef87c90638b25d6b2462c475033da8carll          goto decode_failure;
2009148ae46b56cef87c90638b25d6b2462c475033da8carll
2009232aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion      /* AV Logic */
2009332aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion      case 0x404: case 0x444: case 0x484: // vand, vandc, vor
2009432aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion      case 0x4C4: case 0x504:             // vxor, vnor
200955117ce116f47141cb23d1b49cc826e19323add97sewardj         if (!allow_V) goto decode_noV;
2009632aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion         if (dis_av_logic( theInstr )) goto decode_success;
2009732aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion         goto decode_failure;
2009832aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion
200997deaf9552b546b847528cf39b38898fb7742b5f5carll      case 0x544:                         // vorc
201007deaf9552b546b847528cf39b38898fb7742b5f5carll      case 0x584: case 0x684:             // vnand, veqv
201017deaf9552b546b847528cf39b38898fb7742b5f5carll         if (!allow_isa_2_07) goto decode_noP8;
201027deaf9552b546b847528cf39b38898fb7742b5f5carll         if (dis_av_logic( theInstr )) goto decode_success;
201037deaf9552b546b847528cf39b38898fb7742b5f5carll         goto decode_failure;
201047deaf9552b546b847528cf39b38898fb7742b5f5carll
2010532aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion      /* AV Processor Control */
2010632aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion      case 0x604: case 0x644:             // mfvscr, mtvscr
201075117ce116f47141cb23d1b49cc826e19323add97sewardj         if (!allow_V) goto decode_noV;
2010832aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion         if (dis_av_procctl( theInstr )) goto decode_success;
2010932aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion         goto decode_failure;
2011032aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion
2011132aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion      /* AV Floating Point Arithmetic */
2011232aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion      case 0x00A: case 0x04A:             // vaddfp, vsubfp
2011332aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion      case 0x10A: case 0x14A: case 0x18A: // vrefp, vrsqrtefp, vexptefp
2011432aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion      case 0x1CA:                         // vlogefp
2011532aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion      case 0x40A: case 0x44A:             // vmaxfp, vminfp
201165117ce116f47141cb23d1b49cc826e19323add97sewardj         if (!allow_V) goto decode_noV;
2011732aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion         if (dis_av_fp_arith( theInstr )) goto decode_success;
2011832aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion         goto decode_failure;
2011932aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion
2012032aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion      /* AV Floating Point Round/Convert */
2012132aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion      case 0x20A: case 0x24A: case 0x28A: // vrfin, vrfiz, vrfip
2012232aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion      case 0x2CA:                         // vrfim
2012332aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion      case 0x30A: case 0x34A: case 0x38A: // vcfux, vcfsx, vctuxs
2012432aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion      case 0x3CA:                         // vctsxs
201255117ce116f47141cb23d1b49cc826e19323add97sewardj         if (!allow_V) goto decode_noV;
2012632aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion         if (dis_av_fp_convert( theInstr )) goto decode_success;
2012732aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion         goto decode_failure;
2012832aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion
2012932aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion      /* AV Merge, Splat */
2013032aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion      case 0x00C: case 0x04C: case 0x08C: // vmrghb, vmrghh, vmrghw
2013132aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion      case 0x10C: case 0x14C: case 0x18C: // vmrglb, vmrglh, vmrglw
2013232aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion      case 0x20C: case 0x24C: case 0x28C: // vspltb, vsplth, vspltw
2013332aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion      case 0x30C: case 0x34C: case 0x38C: // vspltisb, vspltish, vspltisw
201345117ce116f47141cb23d1b49cc826e19323add97sewardj         if (!allow_V) goto decode_noV;
2013532aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion         if (dis_av_permute( theInstr )) goto decode_success;
2013632aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion         goto decode_failure;
2013732aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion
2013848ae46b56cef87c90638b25d6b2462c475033da8carll      case 0x68C: case 0x78C:             // vmrgow, vmrgew
2013948ae46b56cef87c90638b25d6b2462c475033da8carll          if (!allow_isa_2_07) goto decode_noP8;
2014048ae46b56cef87c90638b25d6b2462c475033da8carll          if (dis_av_permute( theInstr )) goto decode_success;
2014148ae46b56cef87c90638b25d6b2462c475033da8carll          goto decode_failure;
2014248ae46b56cef87c90638b25d6b2462c475033da8carll
2014332aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion      /* AV Pack, Unpack */
2014432aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion      case 0x00E: case 0x04E: case 0x08E: // vpkuhum, vpkuwum, vpkuhus
2014532aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion      case 0x0CE:                         // vpkuwus
2014632aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion      case 0x10E: case 0x14E: case 0x18E: // vpkshus, vpkswus, vpkshss
2014732aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion      case 0x1CE:                         // vpkswss
2014832aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion      case 0x20E: case 0x24E: case 0x28E: // vupkhsb, vupkhsh, vupklsb
2014932aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion      case 0x2CE:                         // vupklsh
2015032aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion      case 0x30E: case 0x34E: case 0x3CE: // vpkpx, vupkhpx, vupklpx
2015148ae46b56cef87c90638b25d6b2462c475033da8carll          if (!allow_V) goto decode_noV;
2015248ae46b56cef87c90638b25d6b2462c475033da8carll          if (dis_av_pack( theInstr )) goto decode_success;
2015348ae46b56cef87c90638b25d6b2462c475033da8carll          goto decode_failure;
2015432aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion
2015548ae46b56cef87c90638b25d6b2462c475033da8carll      case 0x44E: case 0x4CE: case 0x54E: // vpkudum, vpkudus, vpksdus
2015648ae46b56cef87c90638b25d6b2462c475033da8carll      case 0x5CE: case 0x64E: case 0x6cE: // vpksdss, vupkhsw, vupklsw
201570c74bb5aa3240f693df0568d578baabf0c376dc4carll         if (!allow_isa_2_07) goto decode_noP8;
201580c74bb5aa3240f693df0568d578baabf0c376dc4carll         if (dis_av_pack( theInstr )) goto decode_success;
201590c74bb5aa3240f693df0568d578baabf0c376dc4carll         goto decode_failure;
201600c74bb5aa3240f693df0568d578baabf0c376dc4carll
201617deaf9552b546b847528cf39b38898fb7742b5f5carll      case 0x508: case 0x509:             // vcipher, vcipherlast
201627deaf9552b546b847528cf39b38898fb7742b5f5carll      case 0x548: case 0x549:             // vncipher, vncipherlast
201637deaf9552b546b847528cf39b38898fb7742b5f5carll      case 0x5C8:                         // vsbox
201647deaf9552b546b847528cf39b38898fb7742b5f5carll         if (!allow_isa_2_07) goto decode_noP8;
201657deaf9552b546b847528cf39b38898fb7742b5f5carll         if (dis_av_cipher( theInstr )) goto decode_success;
201667deaf9552b546b847528cf39b38898fb7742b5f5carll         goto decode_failure;
201677deaf9552b546b847528cf39b38898fb7742b5f5carll
201687deaf9552b546b847528cf39b38898fb7742b5f5carll      case 0x6C2: case 0x682:             // vshasigmaw, vshasigmad
201697deaf9552b546b847528cf39b38898fb7742b5f5carll         if (!allow_isa_2_07) goto decode_noP8;
201707deaf9552b546b847528cf39b38898fb7742b5f5carll         if (dis_av_hash( theInstr )) goto decode_success;
201717deaf9552b546b847528cf39b38898fb7742b5f5carll         goto decode_failure;
201727deaf9552b546b847528cf39b38898fb7742b5f5carll
201737deaf9552b546b847528cf39b38898fb7742b5f5carll      case 0x702: case 0x742:             // vclzb, vclzh
201747deaf9552b546b847528cf39b38898fb7742b5f5carll      case 0x782: case 0x7c2:             // vclzw, vclzd
201757deaf9552b546b847528cf39b38898fb7742b5f5carll         if (!allow_isa_2_07) goto decode_noP8;
2017660c6bac19ffe055cabab554e7877d73096a8bf17carll         if (dis_av_count_bitTranspose( theInstr, opc2 )) goto decode_success;
201777deaf9552b546b847528cf39b38898fb7742b5f5carll         goto decode_failure;
201787deaf9552b546b847528cf39b38898fb7742b5f5carll
201797deaf9552b546b847528cf39b38898fb7742b5f5carll      case 0x703: case 0x743:             // vpopcntb, vpopcnth
201807deaf9552b546b847528cf39b38898fb7742b5f5carll      case 0x783: case 0x7c3:             // vpopcntw, vpopcntd
201817deaf9552b546b847528cf39b38898fb7742b5f5carll         if (!allow_isa_2_07) goto decode_noP8;
2018260c6bac19ffe055cabab554e7877d73096a8bf17carll         if (dis_av_count_bitTranspose( theInstr, opc2 )) goto decode_success;
2018360c6bac19ffe055cabab554e7877d73096a8bf17carll         goto decode_failure;
2018460c6bac19ffe055cabab554e7877d73096a8bf17carll
2018560c6bac19ffe055cabab554e7877d73096a8bf17carll      case 0x50c:                         // vgbbd
2018660c6bac19ffe055cabab554e7877d73096a8bf17carll         if (!allow_isa_2_07) goto decode_noP8;
2018760c6bac19ffe055cabab554e7877d73096a8bf17carll         if (dis_av_count_bitTranspose( theInstr, opc2 )) goto decode_success;
2018860c6bac19ffe055cabab554e7877d73096a8bf17carll         goto decode_failure;
2018960c6bac19ffe055cabab554e7877d73096a8bf17carll
2019060c6bac19ffe055cabab554e7877d73096a8bf17carll      case 0x140: case 0x100:             // vaddcuq, vadduqm
2019160c6bac19ffe055cabab554e7877d73096a8bf17carll      case 0x540: case 0x500:             // vsubcuq, vsubuqm
2019260c6bac19ffe055cabab554e7877d73096a8bf17carll      case 0x54C:                         // vbpermq
2019360c6bac19ffe055cabab554e7877d73096a8bf17carll         if (!allow_V) goto decode_noV;
2019460c6bac19ffe055cabab554e7877d73096a8bf17carll         if (dis_av_quad( theInstr)) goto decode_success;
201957deaf9552b546b847528cf39b38898fb7742b5f5carll         goto decode_failure;
201967deaf9552b546b847528cf39b38898fb7742b5f5carll
2019732aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion      default:
2019832aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion         break;  // Fall through...
2019932aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion      }
2020032aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion
2020176de5cf615380b23b4b5bcced6541233cd4a93a0cerion      opc2 = IFIELD(theInstr, 0, 10);
2020232aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion      switch (opc2) {
2020332aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion
2020432aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion      /* AV Compare */
2020532aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion      case 0x006: case 0x046: case 0x086: // vcmpequb, vcmpequh, vcmpequw
2020632aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion      case 0x206: case 0x246: case 0x286: // vcmpgtub, vcmpgtuh, vcmpgtuw
2020732aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion      case 0x306: case 0x346: case 0x386: // vcmpgtsb, vcmpgtsh, vcmpgtsw
202085117ce116f47141cb23d1b49cc826e19323add97sewardj         if (!allow_V) goto decode_noV;
2020932aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion         if (dis_av_cmp( theInstr )) goto decode_success;
2021032aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion         goto decode_failure;
2021132aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion
2021248ae46b56cef87c90638b25d6b2462c475033da8carll      case 0x0C7:                         // vcmpequd
2021348ae46b56cef87c90638b25d6b2462c475033da8carll      case 0x2C7:                         // vcmpgtud
2021448ae46b56cef87c90638b25d6b2462c475033da8carll      case 0x3C7:                         // vcmpgtsd
2021548ae46b56cef87c90638b25d6b2462c475033da8carll          if (!allow_isa_2_07) goto decode_noP8;
2021648ae46b56cef87c90638b25d6b2462c475033da8carll          if (dis_av_cmp( theInstr )) goto decode_success;
2021748ae46b56cef87c90638b25d6b2462c475033da8carll          goto decode_failure;
2021848ae46b56cef87c90638b25d6b2462c475033da8carll
2021932aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion      /* AV Floating Point Compare */
2022032aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion      case 0x0C6: case 0x1C6: case 0x2C6: // vcmpeqfp, vcmpgefp, vcmpgtfp
2022132aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion      case 0x3C6:                         // vcmpbfp
202225117ce116f47141cb23d1b49cc826e19323add97sewardj         if (!allow_V) goto decode_noV;
2022332aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion         if (dis_av_fp_cmp( theInstr )) goto decode_success;
2022432aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion         goto decode_failure;
2022532aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion
2022632aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion      default:
2022732aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion         goto decode_failure;
2022832aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion      }
2022932aad40348e96b4a26a6dc0d3b91ecdaacfd8ff1cerion      break;
202307aa4bbc850d2978cccd8e12cd7c4cfeaa5ab3e4dcerion
20231896a1373cfdbaa25f4ab73ed4f27554016defecccerion   default:
202325b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion      goto decode_failure;
202335b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion
202345117ce116f47141cb23d1b49cc826e19323add97sewardj   decode_noF:
202355117ce116f47141cb23d1b49cc826e19323add97sewardj      vassert(!allow_F);
202360c4e9e8eef3824b085973cd6e2b1b39a1fd6062ecarll      vex_printf("disInstr(ppc): found the Floating Point instruction 0x%x that\n"
202370c4e9e8eef3824b085973cd6e2b1b39a1fd6062ecarll		 "can't be handled by Valgrind on this host.  This instruction\n"
202380c4e9e8eef3824b085973cd6e2b1b39a1fd6062ecarll		 "requires a host that supports Floating Point instructions.\n",
202390c4e9e8eef3824b085973cd6e2b1b39a1fd6062ecarll		 theInstr);
202400c4e9e8eef3824b085973cd6e2b1b39a1fd6062ecarll      goto not_supported;
202415117ce116f47141cb23d1b49cc826e19323add97sewardj   decode_noV:
202425117ce116f47141cb23d1b49cc826e19323add97sewardj      vassert(!allow_V);
202430c4e9e8eef3824b085973cd6e2b1b39a1fd6062ecarll      vex_printf("disInstr(ppc): found an AltiVec or an e500 instruction 0x%x\n"
202440c4e9e8eef3824b085973cd6e2b1b39a1fd6062ecarll		 "that can't be handled by Valgrind.  If this instruction is an\n"
202450c4e9e8eef3824b085973cd6e2b1b39a1fd6062ecarll		 "Altivec instruction, Valgrind must be run on a host that supports"
202460c4e9e8eef3824b085973cd6e2b1b39a1fd6062ecarll		 "AltiVec instructions.  If the application was compiled for e500, then\n"
202470c4e9e8eef3824b085973cd6e2b1b39a1fd6062ecarll		 "unfortunately Valgrind does not yet support e500 instructions.\n",
202480c4e9e8eef3824b085973cd6e2b1b39a1fd6062ecarll		 theInstr);
202490c4e9e8eef3824b085973cd6e2b1b39a1fd6062ecarll      goto not_supported;
2025066d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj   decode_noVX:
2025166d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj      vassert(!allow_VX);
202520c4e9e8eef3824b085973cd6e2b1b39a1fd6062ecarll      vex_printf("disInstr(ppc): found the instruction 0x%x that is defined in the\n"
202530c4e9e8eef3824b085973cd6e2b1b39a1fd6062ecarll		 "Power ISA 2.06 ABI but can't be handled by Valgrind on this host.\n"
202540c4e9e8eef3824b085973cd6e2b1b39a1fd6062ecarll		 "This instruction \nrequires a host that supports the ISA 2.06 ABI.\n",
202550c4e9e8eef3824b085973cd6e2b1b39a1fd6062ecarll		 theInstr);
202560c4e9e8eef3824b085973cd6e2b1b39a1fd6062ecarll      goto not_supported;
202575117ce116f47141cb23d1b49cc826e19323add97sewardj   decode_noFX:
202587c5458604bde543a8567e16df74fb2157b79e844sewardj      vassert(!allow_FX);
202590c4e9e8eef3824b085973cd6e2b1b39a1fd6062ecarll      vex_printf("disInstr(ppc): found the General Purpose-Optional instruction 0x%x\n"
202600c4e9e8eef3824b085973cd6e2b1b39a1fd6062ecarll		 "that can't be handled by Valgrind on this host. This instruction\n"
202610c4e9e8eef3824b085973cd6e2b1b39a1fd6062ecarll		 "requires a host that supports the General Purpose-Optional instructions.\n",
202620c4e9e8eef3824b085973cd6e2b1b39a1fd6062ecarll		 theInstr);
202630c4e9e8eef3824b085973cd6e2b1b39a1fd6062ecarll      goto not_supported;
202645117ce116f47141cb23d1b49cc826e19323add97sewardj   decode_noGX:
202657c5458604bde543a8567e16df74fb2157b79e844sewardj      vassert(!allow_GX);
202660c4e9e8eef3824b085973cd6e2b1b39a1fd6062ecarll      vex_printf("disInstr(ppc): found the Graphics-Optional instruction 0x%x\n"
202670c4e9e8eef3824b085973cd6e2b1b39a1fd6062ecarll		 "that can't be handled by Valgrind on this host. This instruction\n"
202680c4e9e8eef3824b085973cd6e2b1b39a1fd6062ecarll		 "requires a host that supports the Graphic-Optional instructions.\n",
202690c4e9e8eef3824b085973cd6e2b1b39a1fd6062ecarll		 theInstr);
202700c4e9e8eef3824b085973cd6e2b1b39a1fd6062ecarll      goto not_supported;
20271c66d6fa5d9397f167b162483cf3419051cc01a80sewardj   decode_noDFP:
20272c66d6fa5d9397f167b162483cf3419051cc01a80sewardj      vassert(!allow_DFP);
202730c4e9e8eef3824b085973cd6e2b1b39a1fd6062ecarll      vex_printf("disInstr(ppc): found the decimal floating point (DFP) instruction 0x%x\n"
202740c4e9e8eef3824b085973cd6e2b1b39a1fd6062ecarll		 "that can't be handled by Valgrind on this host.  This instruction\n"
202750c4e9e8eef3824b085973cd6e2b1b39a1fd6062ecarll		 "requires a host that supports DFP instructions.\n",
202760c4e9e8eef3824b085973cd6e2b1b39a1fd6062ecarll		 theInstr);
202770c4e9e8eef3824b085973cd6e2b1b39a1fd6062ecarll      goto not_supported;
202780c74bb5aa3240f693df0568d578baabf0c376dc4carll   decode_noP8:
202790c74bb5aa3240f693df0568d578baabf0c376dc4carll      vassert(!allow_isa_2_07);
202800c4e9e8eef3824b085973cd6e2b1b39a1fd6062ecarll      vex_printf("disInstr(ppc): found the Power 8 instruction 0x%x that can't be handled\n"
202810c4e9e8eef3824b085973cd6e2b1b39a1fd6062ecarll		 "by Valgrind on this host.  This instruction requires a host that\n"
202820c4e9e8eef3824b085973cd6e2b1b39a1fd6062ecarll		 "supports Power 8 instructions.\n",
202830c4e9e8eef3824b085973cd6e2b1b39a1fd6062ecarll		 theInstr);
202840c4e9e8eef3824b085973cd6e2b1b39a1fd6062ecarll      goto not_supported;
20285c66d6fa5d9397f167b162483cf3419051cc01a80sewardj
202865b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion
20287896a1373cfdbaa25f4ab73ed4f27554016defecccerion   decode_failure:
20288896a1373cfdbaa25f4ab73ed4f27554016defecccerion   /* All decode failures end up here. */
20289225a034683024109da729a4d2f080364b9485007cerion   opc2 = (theInstr) & 0x7FF;
20290442e51a26cf3bc7f243167a4ff3fbfb02206f6e6sewardj   if (sigill_diag) {
20291442e51a26cf3bc7f243167a4ff3fbfb02206f6e6sewardj      vex_printf("disInstr(ppc): unhandled instruction: "
20292442e51a26cf3bc7f243167a4ff3fbfb02206f6e6sewardj                 "0x%x\n", theInstr);
20293442e51a26cf3bc7f243167a4ff3fbfb02206f6e6sewardj      vex_printf("                 primary %d(0x%x), secondary %u(0x%x)\n",
20294442e51a26cf3bc7f243167a4ff3fbfb02206f6e6sewardj                 opc1, opc1, opc2, opc2);
20295442e51a26cf3bc7f243167a4ff3fbfb02206f6e6sewardj   }
20296995bc3600091747f64a3ac2d9a7fed6b41c3c88dcerion
202970c4e9e8eef3824b085973cd6e2b1b39a1fd6062ecarll   not_supported:
2029801a9e808708130f82e935336c887c1bee2d89036sewardj   /* Tell the dispatcher that this insn cannot be decoded, and so has
2029901a9e808708130f82e935336c887c1bee2d89036sewardj      not been executed, and (is currently) the next to be executed.
2030001a9e808708130f82e935336c887c1bee2d89036sewardj      CIA should be up-to-date since it made so at the start of each
2030101a9e808708130f82e935336c887c1bee2d89036sewardj      insn, but nevertheless be paranoid and update it again right
2030201a9e808708130f82e935336c887c1bee2d89036sewardj      now. */
203032831b00c4950d6c2b061def05fd67528fe132ececerion   putGST( PPC_GST_CIA, mkSzImm(ty, guest_CIA_curr_instr) );
203042faf591d71d355911e35cbcd351fe78b6c986207philippe   dres.len         = 0;
203053dee849ec7c38746749065e67dc53b75daa7617dsewardj   dres.whatNext    = Dis_StopHere;
203063dee849ec7c38746749065e67dc53b75daa7617dsewardj   dres.jk_StopHere = Ijk_NoDecode;
203072faf591d71d355911e35cbcd351fe78b6c986207philippe   dres.continueAt  = 0;
203089e6491ab55324b8e45e187b1e1e9632ac3cb3e27sewardj   return dres;
20309896a1373cfdbaa25f4ab73ed4f27554016defecccerion   } /* switch (opc) for the main (primary) opcode switch. */
20310896a1373cfdbaa25f4ab73ed4f27554016defecccerion
20311896a1373cfdbaa25f4ab73ed4f27554016defecccerion  decode_success:
20312896a1373cfdbaa25f4ab73ed4f27554016defecccerion   /* All decode successes end up here. */
203133dee849ec7c38746749065e67dc53b75daa7617dsewardj   switch (dres.whatNext) {
203143dee849ec7c38746749065e67dc53b75daa7617dsewardj      case Dis_Continue:
203153dee849ec7c38746749065e67dc53b75daa7617dsewardj         putGST( PPC_GST_CIA, mkSzImm(ty, guest_CIA_curr_instr + 4));
203163dee849ec7c38746749065e67dc53b75daa7617dsewardj         break;
203173dee849ec7c38746749065e67dc53b75daa7617dsewardj      case Dis_ResteerU:
203183dee849ec7c38746749065e67dc53b75daa7617dsewardj      case Dis_ResteerC:
203193dee849ec7c38746749065e67dc53b75daa7617dsewardj         putGST( PPC_GST_CIA, mkSzImm(ty, dres.continueAt));
203203dee849ec7c38746749065e67dc53b75daa7617dsewardj         break;
203213dee849ec7c38746749065e67dc53b75daa7617dsewardj      case Dis_StopHere:
203223dee849ec7c38746749065e67dc53b75daa7617dsewardj         break;
203233dee849ec7c38746749065e67dc53b75daa7617dsewardj      default:
203243dee849ec7c38746749065e67dc53b75daa7617dsewardj         vassert(0);
203253dee849ec7c38746749065e67dc53b75daa7617dsewardj   }
20326896a1373cfdbaa25f4ab73ed4f27554016defecccerion   DIP("\n");
20327896a1373cfdbaa25f4ab73ed4f27554016defecccerion
20328ce02aa77bc02dbe225a068df0fb6b31faddedcdfsewardj   if (dres.len == 0) {
20329ce02aa77bc02dbe225a068df0fb6b31faddedcdfsewardj      dres.len = 4;
20330ce02aa77bc02dbe225a068df0fb6b31faddedcdfsewardj   } else {
20331ce02aa77bc02dbe225a068df0fb6b31faddedcdfsewardj      vassert(dres.len == 20);
20332ce02aa77bc02dbe225a068df0fb6b31faddedcdfsewardj   }
203339e6491ab55324b8e45e187b1e1e9632ac3cb3e27sewardj   return dres;
20334896a1373cfdbaa25f4ab73ed4f27554016defecccerion}
20335896a1373cfdbaa25f4ab73ed4f27554016defecccerion
20336896a1373cfdbaa25f4ab73ed4f27554016defecccerion#undef DIP
20337896a1373cfdbaa25f4ab73ed4f27554016defecccerion#undef DIS
20338896a1373cfdbaa25f4ab73ed4f27554016defecccerion
203399e6491ab55324b8e45e187b1e1e9632ac3cb3e27sewardj
203409e6491ab55324b8e45e187b1e1e9632ac3cb3e27sewardj/*------------------------------------------------------------*/
203419e6491ab55324b8e45e187b1e1e9632ac3cb3e27sewardj/*--- Top-level fn                                         ---*/
203429e6491ab55324b8e45e187b1e1e9632ac3cb3e27sewardj/*------------------------------------------------------------*/
203439e6491ab55324b8e45e187b1e1e9632ac3cb3e27sewardj
203449e6491ab55324b8e45e187b1e1e9632ac3cb3e27sewardj/* Disassemble a single instruction into IR.  The instruction
203459e6491ab55324b8e45e187b1e1e9632ac3cb3e27sewardj   is located in host memory at &guest_code[delta]. */
203469e6491ab55324b8e45e187b1e1e9632ac3cb3e27sewardj
20347dd40fdf58cc8a6fe9466c4f00bdfc9fe9bf00449sewardjDisResult disInstr_PPC ( IRSB*        irsb_IN,
20348beac530a718fcc646bc61fe60a86f599df54e1d7florian                         Bool         (*resteerOkFn) ( void*, Addr ),
20349984d9b164dd17f07e603c41fe1e506e641e57d18sewardj                         Bool         resteerCisOk,
20350c716aea1cafe66ee431dc7d6909c98f18788a028sewardj                         void*        callback_opaque,
203518462d113e3efeacceb304222dada8d85f748295aflorian                         const UChar* guest_code_IN,
203525b2325f209f6d3c7ab9c4e819d15060f8d1f09efcerion                         Long         delta,
20353d4cc0deec55ec0be1f2ac3b20f0d340265341f83florian                         Addr         guest_IP,
20354a5f55da7e956978fddad927436da5fab9568f3f1sewardj                         VexArch      guest_arch,
20355cacba8e675988fbf21b08feea1f317a9c896c053florian                         const VexArchInfo* archinfo,
20356cacba8e675988fbf21b08feea1f317a9c896c053florian                         const VexAbiInfo*  abiinfo,
203579b76916dcc1628e133d57db001563429c6e3a590sewardj                         VexEndness   host_endness_IN,
20358442e51a26cf3bc7f243167a4ff3fbfb02206f6e6sewardj                         Bool         sigill_diag_IN )
203599e6491ab55324b8e45e187b1e1e9632ac3cb3e27sewardj{
203605df65bb742f389a45657a0a6f4a9e46a33025407sewardj   IRType     ty;
203615df65bb742f389a45657a0a6f4a9e46a33025407sewardj   DisResult  dres;
203625117ce116f47141cb23d1b49cc826e19323add97sewardj   UInt       mask32, mask64;
203635117ce116f47141cb23d1b49cc826e19323add97sewardj   UInt hwcaps_guest = archinfo->hwcaps;
203645117ce116f47141cb23d1b49cc826e19323add97sewardj
20365a5f55da7e956978fddad927436da5fab9568f3f1sewardj   vassert(guest_arch == VexArchPPC32 || guest_arch == VexArchPPC64);
20366a5f55da7e956978fddad927436da5fab9568f3f1sewardj
203675117ce116f47141cb23d1b49cc826e19323add97sewardj   /* global -- ick */
20368a5f55da7e956978fddad927436da5fab9568f3f1sewardj   mode64 = guest_arch == VexArchPPC64;
20369a5f55da7e956978fddad927436da5fab9568f3f1sewardj   ty = mode64 ? Ity_I64 : Ity_I32;
203701f5fe1fc3a37ca729925e8eec25aa1025b4a6cdbcarll   if (!mode64 && (host_endness_IN == VexEndnessLE)) {
203711f5fe1fc3a37ca729925e8eec25aa1025b4a6cdbcarll      vex_printf("disInstr(ppc): Little Endian 32-bit mode is not supported\n");
203722faf591d71d355911e35cbcd351fe78b6c986207philippe      dres.len         = 0;
203731f5fe1fc3a37ca729925e8eec25aa1025b4a6cdbcarll      dres.whatNext    = Dis_StopHere;
203741f5fe1fc3a37ca729925e8eec25aa1025b4a6cdbcarll      dres.jk_StopHere = Ijk_NoDecode;
2037599af243417cc0182062d4c3ea8f521940a1089f1philippe      dres.continueAt   = 0;
203761f5fe1fc3a37ca729925e8eec25aa1025b4a6cdbcarll      return dres;
203771f5fe1fc3a37ca729925e8eec25aa1025b4a6cdbcarll   }
203785df65bb742f389a45657a0a6f4a9e46a33025407sewardj
20379a5f55da7e956978fddad927436da5fab9568f3f1sewardj   /* do some sanity checks */
203805117ce116f47141cb23d1b49cc826e19323add97sewardj   mask32 = VEX_HWCAPS_PPC32_F | VEX_HWCAPS_PPC32_V
20381c66d6fa5d9397f167b162483cf3419051cc01a80sewardj            | VEX_HWCAPS_PPC32_FX | VEX_HWCAPS_PPC32_GX | VEX_HWCAPS_PPC32_VX
203820c74bb5aa3240f693df0568d578baabf0c376dc4carll            | VEX_HWCAPS_PPC32_DFP | VEX_HWCAPS_PPC32_ISA2_07;
203835117ce116f47141cb23d1b49cc826e19323add97sewardj
2038466d5ef2c2a31fb52cdd4f02304489e30268ea13fsewardj   mask64 = VEX_HWCAPS_PPC64_V | VEX_HWCAPS_PPC64_FX
203850c74bb5aa3240f693df0568d578baabf0c376dc4carll            | VEX_HWCAPS_PPC64_GX | VEX_HWCAPS_PPC64_VX | VEX_HWCAPS_PPC64_DFP
203860c74bb5aa3240f693df0568d578baabf0c376dc4carll            | VEX_HWCAPS_PPC64_ISA2_07;
203875117ce116f47141cb23d1b49cc826e19323add97sewardj
20388a5f55da7e956978fddad927436da5fab9568f3f1sewardj   if (mode64) {
20389a5f55da7e956978fddad927436da5fab9568f3f1sewardj      vassert((hwcaps_guest & mask32) == 0);
20390a5f55da7e956978fddad927436da5fab9568f3f1sewardj   } else {
20391a5f55da7e956978fddad927436da5fab9568f3f1sewardj      vassert((hwcaps_guest & mask64) == 0);
20392a5f55da7e956978fddad927436da5fab9568f3f1sewardj   }
203939e6491ab55324b8e45e187b1e1e9632ac3cb3e27sewardj
203949e6491ab55324b8e45e187b1e1e9632ac3cb3e27sewardj   /* Set globals (see top of this file) */
203959e6491ab55324b8e45e187b1e1e9632ac3cb3e27sewardj   guest_code           = guest_code_IN;
20396dd40fdf58cc8a6fe9466c4f00bdfc9fe9bf00449sewardj   irsb                 = irsb_IN;
203979b76916dcc1628e133d57db001563429c6e3a590sewardj   host_endness         = host_endness_IN;
20398d953ebb9b04cbad6891676df597bf0c542b1ec89cerion
203992831b00c4950d6c2b061def05fd67528fe132ececerion   guest_CIA_curr_instr = mkSzAddr(ty, guest_IP);
204002831b00c4950d6c2b061def05fd67528fe132ececerion   guest_CIA_bbstart    = mkSzAddr(ty, guest_IP - delta);
204019e6491ab55324b8e45e187b1e1e9632ac3cb3e27sewardj
204023dee849ec7c38746749065e67dc53b75daa7617dsewardj   dres = disInstr_PPC_WRK ( resteerOkFn, resteerCisOk, callback_opaque,
204031f5fe1fc3a37ca729925e8eec25aa1025b4a6cdbcarll                             delta, archinfo, abiinfo, sigill_diag_IN);
204049e6491ab55324b8e45e187b1e1e9632ac3cb3e27sewardj
204059e6491ab55324b8e45e187b1e1e9632ac3cb3e27sewardj   return dres;
204069e6491ab55324b8e45e187b1e1e9632ac3cb3e27sewardj}
204079e6491ab55324b8e45e187b1e1e9632ac3cb3e27sewardj
204089e6491ab55324b8e45e187b1e1e9632ac3cb3e27sewardj
20409c808ef7dfe40c18e589490ab1f3980b7b04789ecsewardj/*------------------------------------------------------------*/
20410c808ef7dfe40c18e589490ab1f3980b7b04789ecsewardj/*--- Unused stuff                                         ---*/
20411c808ef7dfe40c18e589490ab1f3980b7b04789ecsewardj/*------------------------------------------------------------*/
20412c808ef7dfe40c18e589490ab1f3980b7b04789ecsewardj
20413c808ef7dfe40c18e589490ab1f3980b7b04789ecsewardj///* A potentially more memcheck-friendly implementation of Clz32, with
20414c808ef7dfe40c18e589490ab1f3980b7b04789ecsewardj//   the boundary case Clz32(0) = 32, which is what ppc requires. */
20415c808ef7dfe40c18e589490ab1f3980b7b04789ecsewardj//
20416c808ef7dfe40c18e589490ab1f3980b7b04789ecsewardj//static IRExpr* /* :: Ity_I32 */ verbose_Clz32 ( IRTemp arg )
20417c808ef7dfe40c18e589490ab1f3980b7b04789ecsewardj//{
20418c808ef7dfe40c18e589490ab1f3980b7b04789ecsewardj//   /* Welcome ... to SSA R Us. */
20419c808ef7dfe40c18e589490ab1f3980b7b04789ecsewardj//   IRTemp n1  = newTemp(Ity_I32);
20420c808ef7dfe40c18e589490ab1f3980b7b04789ecsewardj//   IRTemp n2  = newTemp(Ity_I32);
20421c808ef7dfe40c18e589490ab1f3980b7b04789ecsewardj//   IRTemp n3  = newTemp(Ity_I32);
20422c808ef7dfe40c18e589490ab1f3980b7b04789ecsewardj//   IRTemp n4  = newTemp(Ity_I32);
20423c808ef7dfe40c18e589490ab1f3980b7b04789ecsewardj//   IRTemp n5  = newTemp(Ity_I32);
20424c808ef7dfe40c18e589490ab1f3980b7b04789ecsewardj//   IRTemp n6  = newTemp(Ity_I32);
20425c808ef7dfe40c18e589490ab1f3980b7b04789ecsewardj//   IRTemp n7  = newTemp(Ity_I32);
20426c808ef7dfe40c18e589490ab1f3980b7b04789ecsewardj//   IRTemp n8  = newTemp(Ity_I32);
20427c808ef7dfe40c18e589490ab1f3980b7b04789ecsewardj//   IRTemp n9  = newTemp(Ity_I32);
20428c808ef7dfe40c18e589490ab1f3980b7b04789ecsewardj//   IRTemp n10 = newTemp(Ity_I32);
20429c808ef7dfe40c18e589490ab1f3980b7b04789ecsewardj//   IRTemp n11 = newTemp(Ity_I32);
20430c808ef7dfe40c18e589490ab1f3980b7b04789ecsewardj//   IRTemp n12 = newTemp(Ity_I32);
20431c808ef7dfe40c18e589490ab1f3980b7b04789ecsewardj//
20432c808ef7dfe40c18e589490ab1f3980b7b04789ecsewardj//   /* First, propagate the most significant 1-bit into all lower
20433c808ef7dfe40c18e589490ab1f3980b7b04789ecsewardj//      positions in the word. */
20434c808ef7dfe40c18e589490ab1f3980b7b04789ecsewardj//   /* unsigned int clz ( unsigned int n )
20435c808ef7dfe40c18e589490ab1f3980b7b04789ecsewardj//      {
20436c808ef7dfe40c18e589490ab1f3980b7b04789ecsewardj//         n |= (n >> 1);
20437c808ef7dfe40c18e589490ab1f3980b7b04789ecsewardj//         n |= (n >> 2);
20438c808ef7dfe40c18e589490ab1f3980b7b04789ecsewardj//         n |= (n >> 4);
20439c808ef7dfe40c18e589490ab1f3980b7b04789ecsewardj//         n |= (n >> 8);
20440c808ef7dfe40c18e589490ab1f3980b7b04789ecsewardj//         n |= (n >> 16);
20441c808ef7dfe40c18e589490ab1f3980b7b04789ecsewardj//         return bitcount(~n);
20442c808ef7dfe40c18e589490ab1f3980b7b04789ecsewardj//      }
20443c808ef7dfe40c18e589490ab1f3980b7b04789ecsewardj//   */
20444c808ef7dfe40c18e589490ab1f3980b7b04789ecsewardj//   assign(n1, mkexpr(arg));
20445c808ef7dfe40c18e589490ab1f3980b7b04789ecsewardj//   assign(n2, binop(Iop_Or32, mkexpr(n1), binop(Iop_Shr32, mkexpr(n1), mkU8(1))));
20446c808ef7dfe40c18e589490ab1f3980b7b04789ecsewardj//   assign(n3, binop(Iop_Or32, mkexpr(n2), binop(Iop_Shr32, mkexpr(n2), mkU8(2))));
20447c808ef7dfe40c18e589490ab1f3980b7b04789ecsewardj//   assign(n4, binop(Iop_Or32, mkexpr(n3), binop(Iop_Shr32, mkexpr(n3), mkU8(4))));
20448c808ef7dfe40c18e589490ab1f3980b7b04789ecsewardj//   assign(n5, binop(Iop_Or32, mkexpr(n4), binop(Iop_Shr32, mkexpr(n4), mkU8(8))));
20449c808ef7dfe40c18e589490ab1f3980b7b04789ecsewardj//   assign(n6, binop(Iop_Or32, mkexpr(n5), binop(Iop_Shr32, mkexpr(n5), mkU8(16))));
20450c808ef7dfe40c18e589490ab1f3980b7b04789ecsewardj//   /* This gives a word of the form 0---01---1.  Now invert it, giving
20451c808ef7dfe40c18e589490ab1f3980b7b04789ecsewardj//      a word of the form 1---10---0, then do a population-count idiom
20452c808ef7dfe40c18e589490ab1f3980b7b04789ecsewardj//      (to count the 1s, which is the number of leading zeroes, or 32
20453c808ef7dfe40c18e589490ab1f3980b7b04789ecsewardj//      if the original word was 0. */
20454c808ef7dfe40c18e589490ab1f3980b7b04789ecsewardj//   assign(n7, unop(Iop_Not32, mkexpr(n6)));
20455c808ef7dfe40c18e589490ab1f3980b7b04789ecsewardj//
20456c808ef7dfe40c18e589490ab1f3980b7b04789ecsewardj//   /* unsigned int bitcount ( unsigned int n )
20457c808ef7dfe40c18e589490ab1f3980b7b04789ecsewardj//      {
20458c808ef7dfe40c18e589490ab1f3980b7b04789ecsewardj//         n = n - ((n >> 1) & 0x55555555);
20459c808ef7dfe40c18e589490ab1f3980b7b04789ecsewardj//         n = (n & 0x33333333) + ((n >> 2) & 0x33333333);
20460c808ef7dfe40c18e589490ab1f3980b7b04789ecsewardj//         n = (n + (n >> 4)) & 0x0F0F0F0F;
20461c808ef7dfe40c18e589490ab1f3980b7b04789ecsewardj//         n = n + (n >> 8);
20462c808ef7dfe40c18e589490ab1f3980b7b04789ecsewardj//         n = (n + (n >> 16)) & 0x3F;
20463c808ef7dfe40c18e589490ab1f3980b7b04789ecsewardj//         return n;
20464c808ef7dfe40c18e589490ab1f3980b7b04789ecsewardj//      }
20465c808ef7dfe40c18e589490ab1f3980b7b04789ecsewardj//   */
20466c808ef7dfe40c18e589490ab1f3980b7b04789ecsewardj//   assign(n8,
20467c808ef7dfe40c18e589490ab1f3980b7b04789ecsewardj//          binop(Iop_Sub32,
20468c808ef7dfe40c18e589490ab1f3980b7b04789ecsewardj//                mkexpr(n7),
20469c808ef7dfe40c18e589490ab1f3980b7b04789ecsewardj//                binop(Iop_And32,
20470c808ef7dfe40c18e589490ab1f3980b7b04789ecsewardj//                      binop(Iop_Shr32, mkexpr(n7), mkU8(1)),
20471c808ef7dfe40c18e589490ab1f3980b7b04789ecsewardj//                      mkU32(0x55555555))));
20472c808ef7dfe40c18e589490ab1f3980b7b04789ecsewardj//   assign(n9,
20473c808ef7dfe40c18e589490ab1f3980b7b04789ecsewardj//          binop(Iop_Add32,
20474c808ef7dfe40c18e589490ab1f3980b7b04789ecsewardj//                binop(Iop_And32, mkexpr(n8), mkU32(0x33333333)),
20475c808ef7dfe40c18e589490ab1f3980b7b04789ecsewardj//                binop(Iop_And32,
20476c808ef7dfe40c18e589490ab1f3980b7b04789ecsewardj//                      binop(Iop_Shr32, mkexpr(n8), mkU8(2)),
20477c808ef7dfe40c18e589490ab1f3980b7b04789ecsewardj//                      mkU32(0x33333333))));
20478c808ef7dfe40c18e589490ab1f3980b7b04789ecsewardj//   assign(n10,
20479c808ef7dfe40c18e589490ab1f3980b7b04789ecsewardj//          binop(Iop_And32,
20480c808ef7dfe40c18e589490ab1f3980b7b04789ecsewardj//                binop(Iop_Add32,
20481c808ef7dfe40c18e589490ab1f3980b7b04789ecsewardj//                      mkexpr(n9),
20482c808ef7dfe40c18e589490ab1f3980b7b04789ecsewardj//                      binop(Iop_Shr32, mkexpr(n9), mkU8(4))),
20483c808ef7dfe40c18e589490ab1f3980b7b04789ecsewardj//                mkU32(0x0F0F0F0F)));
20484c808ef7dfe40c18e589490ab1f3980b7b04789ecsewardj//   assign(n11,
20485c808ef7dfe40c18e589490ab1f3980b7b04789ecsewardj//          binop(Iop_Add32,
20486c808ef7dfe40c18e589490ab1f3980b7b04789ecsewardj//                mkexpr(n10),
20487c808ef7dfe40c18e589490ab1f3980b7b04789ecsewardj//                binop(Iop_Shr32, mkexpr(n10), mkU8(8))));
20488c808ef7dfe40c18e589490ab1f3980b7b04789ecsewardj//   assign(n12,
20489c808ef7dfe40c18e589490ab1f3980b7b04789ecsewardj//          binop(Iop_Add32,
20490c808ef7dfe40c18e589490ab1f3980b7b04789ecsewardj//                mkexpr(n11),
20491c808ef7dfe40c18e589490ab1f3980b7b04789ecsewardj//                binop(Iop_Shr32, mkexpr(n11), mkU8(16))));
20492c808ef7dfe40c18e589490ab1f3980b7b04789ecsewardj//   return
20493c808ef7dfe40c18e589490ab1f3980b7b04789ecsewardj//      binop(Iop_And32, mkexpr(n12), mkU32(0x3F));
20494c808ef7dfe40c18e589490ab1f3980b7b04789ecsewardj//}
20495c808ef7dfe40c18e589490ab1f3980b7b04789ecsewardj
20496896a1373cfdbaa25f4ab73ed4f27554016defecccerion/*--------------------------------------------------------------------*/
20497cef7d3e3df4796e35b4521158d9dc058f034aa87sewardj/*--- end                                         guest_ppc_toIR.c ---*/
20498896a1373cfdbaa25f4ab73ed4f27554016defecccerion/*--------------------------------------------------------------------*/
20499