1ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
3ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*--------------------------------------------------------------------*/
4ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*--- begin                                       guest_ppc_toIR.c ---*/
5ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*--------------------------------------------------------------------*/
6ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
7ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*
8ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   This file is part of Valgrind, a dynamic binary instrumentation
9ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   framework.
10ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
11b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   Copyright (C) 2004-2011 OpenWorks LLP
12ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      info@open-works.net
13ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
14ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   This program is free software; you can redistribute it and/or
15ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   modify it under the terms of the GNU General Public License as
16ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   published by the Free Software Foundation; either version 2 of the
17ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   License, or (at your option) any later version.
18ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
19ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   This program is distributed in the hope that it will be useful, but
20ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   WITHOUT ANY WARRANTY; without even the implied warranty of
21ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
22ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   General Public License for more details.
23ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
24ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   You should have received a copy of the GNU General Public License
25ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   along with this program; if not, write to the Free Software
26ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
27ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   02110-1301, USA.
28ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
29ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   The GNU General Public License is contained in the file COPYING.
30ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
31ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   Neither the names of the U.S. Department of Energy nor the
32ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   University of California nor the names of its contributors may be
33ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   used to endorse or promote products derived from this software
34ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   without prior written permission.
35ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown*/
36ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
37ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* TODO 18/Nov/05:
38ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
39ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   Spot rld... cases which are simply left/right shifts and emit
40ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   Shl64/Shr64 accordingly.
41ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
42ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   Altivec
43ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   - datastream insns
44ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   - lvxl,stvxl: load/store with 'least recently used' hint
45ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   - vexptefp, vlogefp
46ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
47ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   LIMITATIONS:
48ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
49ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   Various, including:
50ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
51ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   - Some invalid forms of lswi and lswx are accepted when they should
52ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     not be.
53ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
54ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   - Floating Point:
55ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     - All exceptions disabled in FPSCR
56ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     - condition codes not set in FPSCR
57ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
58ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   - Altivec floating point:
59ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     - vmaddfp, vnmsubfp
60ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown       Because we're using Java/IEEE mode (FPSCR[NJ]), rather than the
61ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown       system default of Non-Java mode, we get some small errors
62ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown       (lowest bit only).
63ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown       This is because Non-Java mode brutally hacks denormalised results
64ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown       to zero, whereas we keep maximum accuracy.  However, using
65ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown       Non-Java mode would give us more inaccuracy, as our intermediate
66ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown       results would then be zeroed, too.
67ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
68ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   - AbiHints for the stack red zone are only emitted for
69ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown       unconditional calls and returns (bl, blr).  They should also be
70ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown       emitted for conditional calls and returns, but we don't have a
71ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown       way to express that right now.  Ah well.
72ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown*/
73ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
74ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* "Special" instructions.
75ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
76ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   This instruction decoder can decode four special instructions
77ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   which mean nothing natively (are no-ops as far as regs/mem are
78ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   concerned) but have meaning for supporting Valgrind.  A special
79ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   instruction is flagged by a 16-byte preamble:
80ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
81ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      32-bit mode: 54001800 54006800 5400E800 54009800
82ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                   (rlwinm 0,0,3,0,0; rlwinm 0,0,13,0,0;
83ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                    rlwinm 0,0,29,0,0; rlwinm 0,0,19,0,0)
84ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
85ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      64-bit mode: 78001800 78006800 7800E802 78009802
86ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                   (rotldi 0,0,3; rotldi 0,0,13;
87ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                    rotldi 0,0,61; rotldi 0,0,51)
88ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
89ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   Following that, one of the following 3 are allowed
90ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   (standard interpretation in parentheses):
91ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
92ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      7C210B78 (or 1,1,1)   %R3 = client_request ( %R4 )
93ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      7C421378 (or 2,2,2)   %R3 = guest_NRADDR
94ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      7C631B78 (or 3,3,3)   branch-and-link-to-noredir %R11
95ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      7C842378 (or 4,4,4)   %R3 = guest_NRADDR_GPR2
96ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
97ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   Any other bytes following the 16-byte preamble are illegal and
98ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   constitute a failure in instruction decoding.  This all assumes
99ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   that the preamble will never occur except in specific code
100ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   fragments designed for Valgrind to catch.
101ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown*/
102ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
103ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
104ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* Translates PPC32/64 code to IR. */
105ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
106ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* References
107ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
108ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define PPC32
109ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   "PowerPC Microprocessor Family:
110ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    The Programming Environments Manual for 32-Bit Microprocessors"
111ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    02/21/2000
112ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    http://www-3.ibm.com/chips/techlib/techlib.nsf/techdocs/852569B20050FF778525699600719DF2
113ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
114ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define PPC64
115ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   "PowerPC Microprocessor Family:
116ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    Programming Environments Manual for 64-Bit Microprocessors"
117ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    06/10/2003
118ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   http://www-3.ibm.com/chips/techlib/techlib.nsf/techdocs/F7E732FF811F783187256FDD004D3797
119ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
120ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define AV
121ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   "PowerPC Microprocessor Family:
122ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    AltiVec(TM) Technology Programming Environments Manual"
123ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    07/10/2003
124ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   http://www-3.ibm.com/chips/techlib/techlib.nsf/techdocs/FBFA164F824370F987256D6A006F424D
125ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown*/
126ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
127ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#include "libvex_basictypes.h"
128ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#include "libvex_ir.h"
129ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#include "libvex.h"
130ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#include "libvex_guest_ppc32.h"
131ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#include "libvex_guest_ppc64.h"
132ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
133ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#include "main_util.h"
134ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#include "main_globals.h"
135ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#include "guest_generic_bb_to_IR.h"
136ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#include "guest_ppc_defs.h"
137ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
138ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
139ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*------------------------------------------------------------*/
140ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*--- Globals                                              ---*/
141ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*------------------------------------------------------------*/
142ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
143ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* These are set at the start of the translation of an insn, right
144ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   down in disInstr_PPC, so that we don't have to pass them around
145ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   endlessly.  They are all constant during the translation of any
146ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   given insn. */
147ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
148ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* We need to know this to do sub-register accesses correctly. */
149ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic Bool host_is_bigendian;
150ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
151ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* Pointer to the guest code area. */
152ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic UChar* guest_code;
153ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
154ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* The guest address corresponding to guest_code[0]. */
155ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic Addr64 guest_CIA_bbstart;
156ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
157ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* The guest address for the instruction currently being
158ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   translated. */
159ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic Addr64 guest_CIA_curr_instr;
160ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
161ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* The IRSB* into which we're generating code. */
162ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic IRSB* irsb;
163ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
164ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* Is our guest binary 32 or 64bit?  Set at each call to
165ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   disInstr_PPC below. */
166ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic Bool mode64 = False;
167ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
168ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// Given a pointer to a function as obtained by "& functionname" in C,
169ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// produce a pointer to the actual entry point for the function.  For
170ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// most platforms it's the identity function.  Unfortunately, on
171ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// ppc64-linux it isn't (sigh) and ditto for ppc32-aix5 and
172ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// ppc64-aix5.
173ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic void* fnptr_to_fnentry( VexAbiInfo* vbi, void* f )
174ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
175ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (vbi->host_ppc_calls_use_fndescrs) {
176ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* f is a pointer to a 3-word function descriptor, of which the
177ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         first word is the entry address. */
178ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* note, this is correct even with cross-jitting, since this is
179ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         purely a host issue, not a guest one. */
180ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      HWord* fdescr = (HWord*)f;
181ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      return (void*)(fdescr[0]);
182ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   } else {
183ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* Simple; "& f" points directly at the code for f. */
184ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      return f;
185ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
186ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
187ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
188b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov#define SIGN_BIT  0x8000000000000000ULL
189b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov#define SIGN_MASK 0x7fffffffffffffffULL
190b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov#define SIGN_BIT32  0x80000000
191b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov#define SIGN_MASK32 0x7fffffff
192b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
193ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
194ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*------------------------------------------------------------*/
195ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*--- Debugging output                                     ---*/
196ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*------------------------------------------------------------*/
197ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
198ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define DIP(format, args...)           \
199ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (vex_traceflags & VEX_TRACE_FE)  \
200ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      vex_printf(format, ## args)
201ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
202ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define DIS(buf, format, args...)      \
203ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (vex_traceflags & VEX_TRACE_FE)  \
204ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      vex_sprintf(buf, format, ## args)
205ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
206ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
207ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*------------------------------------------------------------*/
208ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*--- Offsets of various parts of the ppc32/64 guest state ---*/
209ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*------------------------------------------------------------*/
210ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
211ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define offsetofPPCGuestState(_x) \
212ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   (mode64 ? offsetof(VexGuestPPC64State, _x) : \
213ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown             offsetof(VexGuestPPC32State, _x))
214ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
215ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define OFFB_CIA         offsetofPPCGuestState(guest_CIA)
216ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define OFFB_IP_AT_SYSCALL offsetofPPCGuestState(guest_IP_AT_SYSCALL)
217ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define OFFB_SPRG3_RO    offsetofPPCGuestState(guest_SPRG3_RO)
218ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define OFFB_LR          offsetofPPCGuestState(guest_LR)
219ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define OFFB_CTR         offsetofPPCGuestState(guest_CTR)
220ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define OFFB_XER_SO      offsetofPPCGuestState(guest_XER_SO)
221ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define OFFB_XER_OV      offsetofPPCGuestState(guest_XER_OV)
222ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define OFFB_XER_CA      offsetofPPCGuestState(guest_XER_CA)
223ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define OFFB_XER_BC      offsetofPPCGuestState(guest_XER_BC)
224ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define OFFB_FPROUND     offsetofPPCGuestState(guest_FPROUND)
225ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define OFFB_VRSAVE      offsetofPPCGuestState(guest_VRSAVE)
226ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define OFFB_VSCR        offsetofPPCGuestState(guest_VSCR)
227ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define OFFB_EMWARN      offsetofPPCGuestState(guest_EMWARN)
228ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define OFFB_TISTART     offsetofPPCGuestState(guest_TISTART)
229ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define OFFB_TILEN       offsetofPPCGuestState(guest_TILEN)
230ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define OFFB_NRADDR      offsetofPPCGuestState(guest_NRADDR)
231ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define OFFB_NRADDR_GPR2 offsetofPPCGuestState(guest_NRADDR_GPR2)
232ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
233ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
234ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*------------------------------------------------------------*/
235ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*--- Extract instruction fields                          --- */
236ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*------------------------------------------------------------*/
237ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
238ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* Extract field from insn, given idx (zero = lsb) and field length */
239ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define IFIELD( insn, idx, len ) ((insn >> idx) & ((1<<len)-1))
240ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
241ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* Extract primary opcode, instr[31:26] */
242ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic UChar ifieldOPC( UInt instr ) {
243ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   return toUChar( IFIELD( instr, 26, 6 ) );
244ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
245ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
246ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* Extract 10-bit secondary opcode, instr[10:1] */
247ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic UInt ifieldOPClo10 ( UInt instr) {
248ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   return IFIELD( instr, 1, 10 );
249ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
250ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
251ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* Extract 9-bit secondary opcode, instr[9:1] */
252ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic UInt ifieldOPClo9 ( UInt instr) {
253ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   return IFIELD( instr, 1, 9 );
254ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
255ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
256ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* Extract 5-bit secondary opcode, instr[5:1] */
257ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic UInt ifieldOPClo5 ( UInt instr) {
258ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   return IFIELD( instr, 1, 5 );
259ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
260ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
261ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* Extract RD (destination register) field, instr[25:21] */
262ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic UChar ifieldRegDS( UInt instr ) {
263ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   return toUChar( IFIELD( instr, 21, 5 ) );
264ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
265ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
266b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov/* Extract XT (destination register) field, instr[0,25:21] */
267b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanovstatic UChar ifieldRegXT ( UInt instr )
268b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov{
269b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov  UChar upper_bit = toUChar (IFIELD (instr, 0, 1));
270b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov  UChar lower_bits = toUChar (IFIELD (instr, 21, 5));
271b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov  return (upper_bit << 5) | lower_bits;
272b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov}
273b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
274b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov/* Extract XS (store source register) field, instr[0,25:21] */
275b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanovstatic inline UChar ifieldRegXS ( UInt instr )
276b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov{
277b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov  return ifieldRegXT ( instr );
278b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov}
279b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
280ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* Extract RA (1st source register) field, instr[20:16] */
281ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic UChar ifieldRegA ( UInt instr ) {
282ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   return toUChar( IFIELD( instr, 16, 5 ) );
283ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
284ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
285b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov/* Extract XA (1st source register) field, instr[2,20:16] */
286b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanovstatic UChar ifieldRegXA ( UInt instr )
287b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov{
288b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov  UChar upper_bit = toUChar (IFIELD (instr, 2, 1));
289b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov  UChar lower_bits = toUChar (IFIELD (instr, 16, 5));
290b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov  return (upper_bit << 5) | lower_bits;
291b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov}
292b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
293ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* Extract RB (2nd source register) field, instr[15:11] */
294ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic UChar ifieldRegB ( UInt instr ) {
295ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   return toUChar( IFIELD( instr, 11, 5 ) );
296ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
297ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
298b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov/* Extract XB (2nd source register) field, instr[1,15:11] */
299b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanovstatic UChar ifieldRegXB ( UInt instr )
300b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov{
301b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov  UChar upper_bit = toUChar (IFIELD (instr, 1, 1));
302b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov  UChar lower_bits = toUChar (IFIELD (instr, 11, 5));
303b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov  return (upper_bit << 5) | lower_bits;
304b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov}
305b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
306ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* Extract RC (3rd source register) field, instr[10:6] */
307ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic UChar ifieldRegC ( UInt instr ) {
308ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   return toUChar( IFIELD( instr, 6, 5 ) );
309ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
310ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
311b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov/* Extract XC (3rd source register) field, instr[3,10:6] */
312b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanovstatic UChar ifieldRegXC ( UInt instr )
313b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov{
314b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov  UChar upper_bit = toUChar (IFIELD (instr, 3, 1));
315b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov  UChar lower_bits = toUChar (IFIELD (instr, 6, 5));
316b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov  return (upper_bit << 5) | lower_bits;
317b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov}
318b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
319b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov/* Extract bit 10, instr[10] */
320ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic UChar ifieldBIT10 ( UInt instr ) {
321ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   return toUChar( IFIELD( instr, 10, 1 ) );
322ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
323ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
324ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* Extract 2nd lowest bit, instr[1] */
325ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic UChar ifieldBIT1 ( UInt instr ) {
326ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   return toUChar( IFIELD( instr, 1, 1 ) );
327ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
328ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
329ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* Extract lowest bit, instr[0] */
330ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic UChar ifieldBIT0 ( UInt instr ) {
331ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   return toUChar( instr & 0x1 );
332ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
333ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
334ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* Extract unsigned bottom half, instr[15:0] */
335ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic UInt ifieldUIMM16 ( UInt instr ) {
336ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   return instr & 0xFFFF;
337ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
338ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
339ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* Extract unsigned bottom 26 bits, instr[25:0] */
340ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic UInt ifieldUIMM26 ( UInt instr ) {
341ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   return instr & 0x3FFFFFF;
342ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
343ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
344b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov/* Extract DM field, instr[9:8] */
345b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanovstatic UChar ifieldDM ( UInt instr ) {
346b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   return toUChar( IFIELD( instr, 8, 2 ) );
347b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov}
348b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
349b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov/* Extract SHW field, instr[9:8] */
350b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanovstatic inline UChar ifieldSHW ( UInt instr )
351b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov{
352b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov  return ifieldDM ( instr );
353b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov}
354ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
355ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*------------------------------------------------------------*/
356ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*--- Guest-state identifiers                              ---*/
357ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*------------------------------------------------------------*/
358ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
359ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Browntypedef enum {
360ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    PPC_GST_CIA,    // Current Instruction Address
361ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    PPC_GST_LR,     // Link Register
362ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    PPC_GST_CTR,    // Count Register
363ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    PPC_GST_XER,    // Overflow, carry flags, byte count
364ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    PPC_GST_CR,     // Condition Register
365ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    PPC_GST_FPSCR,  // Floating Point Status/Control Register
366ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    PPC_GST_VRSAVE, // Vector Save/Restore Register
367ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    PPC_GST_VSCR,   // Vector Status and Control Register
368ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    PPC_GST_EMWARN, // Emulation warnings
369ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    PPC_GST_TISTART,// For icbi: start of area to invalidate
370ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    PPC_GST_TILEN,  // For icbi: length of area to invalidate
371ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    PPC_GST_IP_AT_SYSCALL, // the CIA of the most recently executed SC insn
372ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    PPC_GST_SPRG3_RO, // SPRG3
373ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    PPC_GST_MAX
374ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown} PPC_GST;
375ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
376ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define MASK_FPSCR_RN   0x3
377ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define MASK_FPSCR_FPRF 0x1F000
378ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define MASK_VSCR_VALID 0x00010001
379ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
380ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
381ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*------------------------------------------------------------*/
382ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*---  FP Helpers                                          ---*/
383ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*------------------------------------------------------------*/
384ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
385ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* Produce the 32-bit pattern corresponding to the supplied
386ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   float. */
387ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic UInt float_to_bits ( Float f )
388ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
389ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   union { UInt i; Float f; } u;
390ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   vassert(4 == sizeof(UInt));
391ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   vassert(4 == sizeof(Float));
392ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   vassert(4 == sizeof(u));
393ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   u.f = f;
394ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   return u.i;
395ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
396ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
397ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
398ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*------------------------------------------------------------*/
399ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*--- Misc Helpers                                         ---*/
400ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*------------------------------------------------------------*/
401ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
402ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* Generate mask with 1's from 'begin' through 'end',
403ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   wrapping if begin > end.
404ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   begin->end works from right to left, 0=lsb
405ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown*/
406ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic UInt MASK32( UInt begin, UInt end )
407ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
408ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   UInt m1, m2, mask;
409ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   vassert(begin < 32);
410ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   vassert(end < 32);
411ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   m1   = ((UInt)(-1)) << begin;
412ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   m2   = ((UInt)(-1)) << end << 1;
413ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   mask = m1 ^ m2;
414ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (begin > end) mask = ~mask;  // wrap mask
415ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   return mask;
416ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
417ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
418ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* ditto for 64bit mask */
419ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic ULong MASK64( UInt begin, UInt end )
420ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
421ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   ULong m1, m2, mask;
422ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   vassert(begin < 64);
423ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   vassert(end < 64);
424ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   m1   = ((ULong)(-1)) << begin;
425ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   m2   = ((ULong)(-1)) << end << 1;
426ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   mask = m1 ^ m2;
427ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (begin > end) mask = ~mask;  // wrap mask
428ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   return mask;
429ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
430ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
431ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic Addr64 nextInsnAddr( void )
432ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
433ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   return guest_CIA_curr_instr + 4;
434ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
435ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
436ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
437ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*------------------------------------------------------------*/
438ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*--- Helper bits and pieces for deconstructing the        ---*/
439ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*--- ppc32/64 insn stream.                                ---*/
440ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*------------------------------------------------------------*/
441ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
442ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* Add a statement to the list held by "irsb". */
443ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic void stmt ( IRStmt* st )
444ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
445ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   addStmtToIRSB( irsb, st );
446ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
447ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
448ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* Generate a new temporary of the given type. */
449ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic IRTemp newTemp ( IRType ty )
450ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
451ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   vassert(isPlausibleIRType(ty));
452ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   return newIRTemp( irsb->tyenv, ty );
453ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
454ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
455ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* Various simple conversions */
456ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
457ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic UChar extend_s_5to8 ( UChar x )
458ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
459ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   return toUChar((((Int)x) << 27) >> 27);
460ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
461ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
462ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic UInt extend_s_8to32( UChar x )
463ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
464ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   return (UInt)((((Int)x) << 24) >> 24);
465ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
466ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
467ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic UInt extend_s_16to32 ( UInt x )
468ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
469ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   return (UInt)((((Int)x) << 16) >> 16);
470ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
471ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
472ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic ULong extend_s_16to64 ( UInt x )
473ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
474ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   return (ULong)((((Long)x) << 48) >> 48);
475ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
476ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
477ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic ULong extend_s_26to64 ( UInt x )
478ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
479ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   return (ULong)((((Long)x) << 38) >> 38);
480ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
481ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
482ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic ULong extend_s_32to64 ( UInt x )
483ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
484ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   return (ULong)((((Long)x) << 32) >> 32);
485ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
486ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
487ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* Do a big-endian load of a 32-bit word, regardless of the endianness
488ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   of the underlying host. */
489ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic UInt getUIntBigendianly ( UChar* p )
490ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
491ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   UInt w = 0;
492ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   w = (w << 8) | p[0];
493ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   w = (w << 8) | p[1];
494ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   w = (w << 8) | p[2];
495ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   w = (w << 8) | p[3];
496ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   return w;
497ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
498ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
499ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
500ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*------------------------------------------------------------*/
501ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*--- Helpers for constructing IR.                         ---*/
502ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*------------------------------------------------------------*/
503ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
504ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic void assign ( IRTemp dst, IRExpr* e )
505ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
506ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   stmt( IRStmt_WrTmp(dst, e) );
507ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
508ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
509ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* This generates a normal (non store-conditional) store. */
510ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic void storeBE ( IRExpr* addr, IRExpr* data )
511ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
512ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   IRType tyA = typeOfIRExpr(irsb->tyenv, addr);
513ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   vassert(tyA == Ity_I32 || tyA == Ity_I64);
514ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   stmt( IRStmt_Store(Iend_BE, addr, data) );
515ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
516ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
517ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic IRExpr* unop ( IROp op, IRExpr* a )
518ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
519ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   return IRExpr_Unop(op, a);
520ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
521ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
522ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic IRExpr* binop ( IROp op, IRExpr* a1, IRExpr* a2 )
523ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
524ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   return IRExpr_Binop(op, a1, a2);
525ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
526ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
527ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic IRExpr* triop ( IROp op, IRExpr* a1, IRExpr* a2, IRExpr* a3 )
528ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
529ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   return IRExpr_Triop(op, a1, a2, a3);
530ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
531ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
532ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic IRExpr* qop ( IROp op, IRExpr* a1, IRExpr* a2,
533ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                              IRExpr* a3, IRExpr* a4 )
534ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
535ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   return IRExpr_Qop(op, a1, a2, a3, a4);
536ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
537ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
538ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic IRExpr* mkexpr ( IRTemp tmp )
539ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
540ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   return IRExpr_RdTmp(tmp);
541ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
542ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
543ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic IRExpr* mkU8 ( UChar i )
544ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
545ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   return IRExpr_Const(IRConst_U8(i));
546ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
547ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
548ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic IRExpr* mkU16 ( UInt i )
549ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
550ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   return IRExpr_Const(IRConst_U16(i));
551ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
552ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
553ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic IRExpr* mkU32 ( UInt i )
554ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
555ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   return IRExpr_Const(IRConst_U32(i));
556ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
557ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
558ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic IRExpr* mkU64 ( ULong i )
559ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
560ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   return IRExpr_Const(IRConst_U64(i));
561ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
562ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
563b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanovstatic IRExpr* mkV128 ( UShort i )
564b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov{
565b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   vassert(i == 0 || i == 0xffff);
566b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   return IRExpr_Const(IRConst_V128(i));
567b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov}
568b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
569ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* This generates a normal (non load-linked) load. */
570ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic IRExpr* loadBE ( IRType ty, IRExpr* addr )
571ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
572ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   return IRExpr_Load(Iend_BE, ty, addr);
573ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
574ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
575ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic IRExpr* mkOR1 ( IRExpr* arg1, IRExpr* arg2 )
576ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
577ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   vassert(typeOfIRExpr(irsb->tyenv, arg1) == Ity_I1);
578ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   vassert(typeOfIRExpr(irsb->tyenv, arg2) == Ity_I1);
579ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   return unop(Iop_32to1, binop(Iop_Or32, unop(Iop_1Uto32, arg1),
580ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                          unop(Iop_1Uto32, arg2)));
581ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
582ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
583ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic IRExpr* mkAND1 ( IRExpr* arg1, IRExpr* arg2 )
584ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
585ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   vassert(typeOfIRExpr(irsb->tyenv, arg1) == Ity_I1);
586ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   vassert(typeOfIRExpr(irsb->tyenv, arg2) == Ity_I1);
587ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   return unop(Iop_32to1, binop(Iop_And32, unop(Iop_1Uto32, arg1),
588ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                           unop(Iop_1Uto32, arg2)));
589ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
590ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
591ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* expand V128_8Ux16 to 2x V128_16Ux8's */
592ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic void expand8Ux16( IRExpr* vIn,
593ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                         /*OUTs*/ IRTemp* vEvn, IRTemp* vOdd )
594ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
595ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   IRTemp ones8x16 = newTemp(Ity_V128);
596ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
597ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   vassert(typeOfIRExpr(irsb->tyenv, vIn) == Ity_V128);
598ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   vassert(vEvn && *vEvn == IRTemp_INVALID);
599ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   vassert(vOdd && *vOdd == IRTemp_INVALID);
600ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   *vEvn = newTemp(Ity_V128);
601ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   *vOdd = newTemp(Ity_V128);
602ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
603ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   assign( ones8x16, unop(Iop_Dup8x16, mkU8(0x1)) );
604ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   assign( *vOdd, binop(Iop_MullEven8Ux16, mkexpr(ones8x16), vIn) );
605ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   assign( *vEvn, binop(Iop_MullEven8Ux16, mkexpr(ones8x16),
606ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                        binop(Iop_ShrV128, vIn, mkU8(8))) );
607ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
608ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
609ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* expand V128_8Sx16 to 2x V128_16Sx8's */
610ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic void expand8Sx16( IRExpr* vIn,
611ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                         /*OUTs*/ IRTemp* vEvn, IRTemp* vOdd )
612ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
613ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   IRTemp ones8x16 = newTemp(Ity_V128);
614ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
615ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   vassert(typeOfIRExpr(irsb->tyenv, vIn) == Ity_V128);
616ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   vassert(vEvn && *vEvn == IRTemp_INVALID);
617ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   vassert(vOdd && *vOdd == IRTemp_INVALID);
618ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   *vEvn = newTemp(Ity_V128);
619ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   *vOdd = newTemp(Ity_V128);
620ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
621ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   assign( ones8x16, unop(Iop_Dup8x16, mkU8(0x1)) );
622ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   assign( *vOdd, binop(Iop_MullEven8Sx16, mkexpr(ones8x16), vIn) );
623ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   assign( *vEvn, binop(Iop_MullEven8Sx16, mkexpr(ones8x16),
624ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                        binop(Iop_ShrV128, vIn, mkU8(8))) );
625ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
626ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
627ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* expand V128_16Uto8 to 2x V128_32Ux4's */
628ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic void expand16Ux8( IRExpr* vIn,
629ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                         /*OUTs*/ IRTemp* vEvn, IRTemp* vOdd )
630ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
631ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   IRTemp ones16x8 = newTemp(Ity_V128);
632ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
633ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   vassert(typeOfIRExpr(irsb->tyenv, vIn) == Ity_V128);
634ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   vassert(vEvn && *vEvn == IRTemp_INVALID);
635ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   vassert(vOdd && *vOdd == IRTemp_INVALID);
636ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   *vEvn = newTemp(Ity_V128);
637ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   *vOdd = newTemp(Ity_V128);
638ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
639ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   assign( ones16x8, unop(Iop_Dup16x8, mkU16(0x1)) );
640ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   assign( *vOdd, binop(Iop_MullEven16Ux8, mkexpr(ones16x8), vIn) );
641ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   assign( *vEvn, binop(Iop_MullEven16Ux8, mkexpr(ones16x8),
642ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                        binop(Iop_ShrV128, vIn, mkU8(16))) );
643ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
644ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
645ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* expand V128_16Sto8 to 2x V128_32Sx4's */
646ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic void expand16Sx8( IRExpr* vIn,
647ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                         /*OUTs*/ IRTemp* vEvn, IRTemp* vOdd )
648ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
649ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   IRTemp ones16x8 = newTemp(Ity_V128);
650ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
651ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   vassert(typeOfIRExpr(irsb->tyenv, vIn) == Ity_V128);
652ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   vassert(vEvn && *vEvn == IRTemp_INVALID);
653ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   vassert(vOdd && *vOdd == IRTemp_INVALID);
654ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   *vEvn = newTemp(Ity_V128);
655ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   *vOdd = newTemp(Ity_V128);
656ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
657ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   assign( ones16x8, unop(Iop_Dup16x8, mkU16(0x1)) );
658ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   assign( *vOdd, binop(Iop_MullEven16Sx8, mkexpr(ones16x8), vIn) );
659ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   assign( *vEvn, binop(Iop_MullEven16Sx8, mkexpr(ones16x8),
660ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                       binop(Iop_ShrV128, vIn, mkU8(16))) );
661ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
662ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
663b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov/* break V128 to 4xF64's*/
664b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanovstatic void breakV128to4xF64( IRExpr* t128,
665b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                              /*OUTs*/
666b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                              IRTemp* t3, IRTemp* t2,
667b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                              IRTemp* t1, IRTemp* t0 )
668b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov{
669b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   IRTemp hi64 = newTemp(Ity_I64);
670b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   IRTemp lo64 = newTemp(Ity_I64);
671b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
672b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   vassert(typeOfIRExpr(irsb->tyenv, t128) == Ity_V128);
673b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   vassert(t0 && *t0 == IRTemp_INVALID);
674b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   vassert(t1 && *t1 == IRTemp_INVALID);
675b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   vassert(t2 && *t2 == IRTemp_INVALID);
676b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   vassert(t3 && *t3 == IRTemp_INVALID);
677b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   *t0 = newTemp(Ity_F64);
678b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   *t1 = newTemp(Ity_F64);
679b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   *t2 = newTemp(Ity_F64);
680b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   *t3 = newTemp(Ity_F64);
681b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
682b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   assign( hi64, unop(Iop_V128HIto64, t128) );
683b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   assign( lo64, unop(Iop_V128to64,   t128) );
684b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   assign( *t3,
685b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov           unop( Iop_F32toF64,
686b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                 unop( Iop_ReinterpI32asF32,
687b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                       unop( Iop_64HIto32, mkexpr( hi64 ) ) ) ) );
688b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   assign( *t2,
689b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov           unop( Iop_F32toF64,
690b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                 unop( Iop_ReinterpI32asF32, unop( Iop_64to32, mkexpr( hi64 ) ) ) ) );
691b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   assign( *t1,
692b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov           unop( Iop_F32toF64,
693b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                 unop( Iop_ReinterpI32asF32,
694b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                       unop( Iop_64HIto32, mkexpr( lo64 ) ) ) ) );
695b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   assign( *t0,
696b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov           unop( Iop_F32toF64,
697b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                 unop( Iop_ReinterpI32asF32, unop( Iop_64to32, mkexpr( lo64 ) ) ) ) );
698b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov}
699b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
700b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
701ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* break V128 to 4xI32's, then sign-extend to I64's */
702ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic void breakV128to4x64S( IRExpr* t128,
703ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                              /*OUTs*/
704ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                              IRTemp* t3, IRTemp* t2,
705ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                              IRTemp* t1, IRTemp* t0 )
706ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
707ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   IRTemp hi64 = newTemp(Ity_I64);
708ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   IRTemp lo64 = newTemp(Ity_I64);
709ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
710ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   vassert(typeOfIRExpr(irsb->tyenv, t128) == Ity_V128);
711ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   vassert(t0 && *t0 == IRTemp_INVALID);
712ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   vassert(t1 && *t1 == IRTemp_INVALID);
713ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   vassert(t2 && *t2 == IRTemp_INVALID);
714ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   vassert(t3 && *t3 == IRTemp_INVALID);
715ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   *t0 = newTemp(Ity_I64);
716ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   *t1 = newTemp(Ity_I64);
717ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   *t2 = newTemp(Ity_I64);
718ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   *t3 = newTemp(Ity_I64);
719ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
720ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   assign( hi64, unop(Iop_V128HIto64, t128) );
721ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   assign( lo64, unop(Iop_V128to64,   t128) );
722ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   assign( *t3, unop(Iop_32Sto64, unop(Iop_64HIto32, mkexpr(hi64))) );
723ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   assign( *t2, unop(Iop_32Sto64, unop(Iop_64to32,   mkexpr(hi64))) );
724ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   assign( *t1, unop(Iop_32Sto64, unop(Iop_64HIto32, mkexpr(lo64))) );
725ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   assign( *t0, unop(Iop_32Sto64, unop(Iop_64to32,   mkexpr(lo64))) );
726ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
727ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
728ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* break V128 to 4xI32's, then zero-extend to I64's */
729ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic void breakV128to4x64U ( IRExpr* t128,
730ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                               /*OUTs*/
731ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                               IRTemp* t3, IRTemp* t2,
732ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                               IRTemp* t1, IRTemp* t0 )
733ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
734ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   IRTemp hi64 = newTemp(Ity_I64);
735ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   IRTemp lo64 = newTemp(Ity_I64);
736ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
737ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   vassert(typeOfIRExpr(irsb->tyenv, t128) == Ity_V128);
738ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   vassert(t0 && *t0 == IRTemp_INVALID);
739ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   vassert(t1 && *t1 == IRTemp_INVALID);
740ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   vassert(t2 && *t2 == IRTemp_INVALID);
741ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   vassert(t3 && *t3 == IRTemp_INVALID);
742ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   *t0 = newTemp(Ity_I64);
743ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   *t1 = newTemp(Ity_I64);
744ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   *t2 = newTemp(Ity_I64);
745ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   *t3 = newTemp(Ity_I64);
746ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
747ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   assign( hi64, unop(Iop_V128HIto64, t128) );
748ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   assign( lo64, unop(Iop_V128to64,   t128) );
749ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   assign( *t3, unop(Iop_32Uto64, unop(Iop_64HIto32, mkexpr(hi64))) );
750ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   assign( *t2, unop(Iop_32Uto64, unop(Iop_64to32,   mkexpr(hi64))) );
751ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   assign( *t1, unop(Iop_32Uto64, unop(Iop_64HIto32, mkexpr(lo64))) );
752ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   assign( *t0, unop(Iop_32Uto64, unop(Iop_64to32,   mkexpr(lo64))) );
753ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
754ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
755b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanovstatic void breakV128to4x32( IRExpr* t128,
756b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                              /*OUTs*/
757b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                              IRTemp* t3, IRTemp* t2,
758b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                              IRTemp* t1, IRTemp* t0 )
759b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov{
760b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   IRTemp hi64 = newTemp(Ity_I64);
761b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   IRTemp lo64 = newTemp(Ity_I64);
762b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
763b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   vassert(typeOfIRExpr(irsb->tyenv, t128) == Ity_V128);
764b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   vassert(t0 && *t0 == IRTemp_INVALID);
765b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   vassert(t1 && *t1 == IRTemp_INVALID);
766b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   vassert(t2 && *t2 == IRTemp_INVALID);
767b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   vassert(t3 && *t3 == IRTemp_INVALID);
768b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   *t0 = newTemp(Ity_I32);
769b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   *t1 = newTemp(Ity_I32);
770b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   *t2 = newTemp(Ity_I32);
771b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   *t3 = newTemp(Ity_I32);
772b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
773b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   assign( hi64, unop(Iop_V128HIto64, t128) );
774b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   assign( lo64, unop(Iop_V128to64,   t128) );
775b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   assign( *t3, unop(Iop_64HIto32, mkexpr(hi64)) );
776b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   assign( *t2, unop(Iop_64to32,   mkexpr(hi64)) );
777b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   assign( *t1, unop(Iop_64HIto32, mkexpr(lo64)) );
778b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   assign( *t0, unop(Iop_64to32,   mkexpr(lo64)) );
779b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov}
780b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
781b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
782ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* Signed saturating narrow 64S to 32 */
783ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic IRExpr* mkQNarrow64Sto32 ( IRExpr* t64 )
784ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
785ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   IRTemp hi32 = newTemp(Ity_I32);
786ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   IRTemp lo32 = newTemp(Ity_I32);
787ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
788ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   vassert(typeOfIRExpr(irsb->tyenv, t64) == Ity_I64);
789ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
790ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   assign( hi32, unop(Iop_64HIto32, t64));
791ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   assign( lo32, unop(Iop_64to32,   t64));
792ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
793ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   return IRExpr_Mux0X(
794ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown             /* if (hi32 == (lo32 >>s 31)) */
795ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown             unop(Iop_1Uto8,
796ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  binop(Iop_CmpEQ32, mkexpr(hi32),
797ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                        binop( Iop_Sar32, mkexpr(lo32), mkU8(31)))),
798ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown             /* else: sign dep saturate: 1->0x80000000, 0->0x7FFFFFFF */
799ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown             binop(Iop_Add32, mkU32(0x7FFFFFFF),
800ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                   binop(Iop_Shr32, mkexpr(hi32), mkU8(31))),
801ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown             /* then: within signed-32 range: lo half good enough */
802ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown             mkexpr(lo32) );
803ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
804ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
805ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* Unsigned saturating narrow 64S to 32 */
806ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic IRExpr* mkQNarrow64Uto32 ( IRExpr* t64 )
807ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
808ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   IRTemp hi32 = newTemp(Ity_I32);
809ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   IRTemp lo32 = newTemp(Ity_I32);
810ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
811ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   vassert(typeOfIRExpr(irsb->tyenv, t64) == Ity_I64);
812ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
813ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   assign( hi32, unop(Iop_64HIto32, t64));
814ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   assign( lo32, unop(Iop_64to32,   t64));
815ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
816ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   return IRExpr_Mux0X(
817ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            /* if (top 32 bits of t64 are 0) */
818ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            unop(Iop_1Uto8, binop(Iop_CmpEQ32, mkexpr(hi32), mkU32(0))),
819ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            /* else: positive saturate -> 0xFFFFFFFF */
820ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            mkU32(0xFFFFFFFF),
821ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            /* then: within unsigned-32 range: lo half good enough */
822ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            mkexpr(lo32) );
823ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
824ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
825ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* Signed saturate narrow 64->32, combining to V128 */
826ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic IRExpr* mkV128from4x64S ( IRExpr* t3, IRExpr* t2,
827ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                 IRExpr* t1, IRExpr* t0 )
828ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
829ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   vassert(typeOfIRExpr(irsb->tyenv, t3) == Ity_I64);
830ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   vassert(typeOfIRExpr(irsb->tyenv, t2) == Ity_I64);
831ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   vassert(typeOfIRExpr(irsb->tyenv, t1) == Ity_I64);
832ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   vassert(typeOfIRExpr(irsb->tyenv, t0) == Ity_I64);
833ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   return binop(Iop_64HLtoV128,
834ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                binop(Iop_32HLto64,
835ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                      mkQNarrow64Sto32( t3 ),
836ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                      mkQNarrow64Sto32( t2 )),
837ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                binop(Iop_32HLto64,
838ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                      mkQNarrow64Sto32( t1 ),
839ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                      mkQNarrow64Sto32( t0 )));
840ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
841ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
842ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* Unsigned saturate narrow 64->32, combining to V128 */
843ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic IRExpr* mkV128from4x64U ( IRExpr* t3, IRExpr* t2,
844ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                 IRExpr* t1, IRExpr* t0 )
845ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
846ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   vassert(typeOfIRExpr(irsb->tyenv, t3) == Ity_I64);
847ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   vassert(typeOfIRExpr(irsb->tyenv, t2) == Ity_I64);
848ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   vassert(typeOfIRExpr(irsb->tyenv, t1) == Ity_I64);
849ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   vassert(typeOfIRExpr(irsb->tyenv, t0) == Ity_I64);
850ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   return binop(Iop_64HLtoV128,
851ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                binop(Iop_32HLto64,
852ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                      mkQNarrow64Uto32( t3 ),
853ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                      mkQNarrow64Uto32( t2 )),
854ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                binop(Iop_32HLto64,
855ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                      mkQNarrow64Uto32( t1 ),
856ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                      mkQNarrow64Uto32( t0 )));
857ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
858ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
859ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* Simulate irops Iop_MullOdd*, since we don't have them  */
860ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define MK_Iop_MullOdd8Ux16( expr_vA, expr_vB ) \
861ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      binop(Iop_MullEven8Ux16, \
862ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            binop(Iop_ShrV128, expr_vA, mkU8(8)), \
863ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            binop(Iop_ShrV128, expr_vB, mkU8(8)))
864ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
865ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define MK_Iop_MullOdd8Sx16( expr_vA, expr_vB ) \
866ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      binop(Iop_MullEven8Sx16, \
867ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            binop(Iop_ShrV128, expr_vA, mkU8(8)), \
868ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            binop(Iop_ShrV128, expr_vB, mkU8(8)))
869ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
870ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define MK_Iop_MullOdd16Ux8( expr_vA, expr_vB ) \
871ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      binop(Iop_MullEven16Ux8, \
872ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            binop(Iop_ShrV128, expr_vA, mkU8(16)), \
873ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            binop(Iop_ShrV128, expr_vB, mkU8(16)))
874ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
875ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define MK_Iop_MullOdd16Sx8( expr_vA, expr_vB ) \
876ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      binop(Iop_MullEven16Sx8, \
877ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            binop(Iop_ShrV128, expr_vA, mkU8(16)), \
878ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            binop(Iop_ShrV128, expr_vB, mkU8(16)))
879ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
880ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic IRExpr* /* :: Ity_I64 */ mk64lo32Sto64 ( IRExpr* src )
881ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
882ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   vassert(typeOfIRExpr(irsb->tyenv, src) == Ity_I64);
883ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   return unop(Iop_32Sto64, unop(Iop_64to32, src));
884ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
885ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
886ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic IRExpr* /* :: Ity_I64 */ mk64lo32Uto64 ( IRExpr* src )
887ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
888ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   vassert(typeOfIRExpr(irsb->tyenv, src) == Ity_I64);
889ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   return unop(Iop_32Uto64, unop(Iop_64to32, src));
890ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
891ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
892ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic IROp mkSzOp ( IRType ty, IROp op8 )
893ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
894ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   Int adj;
895ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   vassert(ty == Ity_I8  || ty == Ity_I16 ||
896ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown           ty == Ity_I32 || ty == Ity_I64);
897ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   vassert(op8 == Iop_Add8   || op8 == Iop_Sub8   || op8 == Iop_Mul8 ||
898ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown           op8 == Iop_Or8    || op8 == Iop_And8   || op8 == Iop_Xor8 ||
899ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown           op8 == Iop_Shl8   || op8 == Iop_Shr8   || op8 == Iop_Sar8 ||
900ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown           op8 == Iop_CmpEQ8 || op8 == Iop_CmpNE8 ||
901ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown           op8 == Iop_Not8 );
902ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   adj = ty==Ity_I8 ? 0 : (ty==Ity_I16 ? 1 : (ty==Ity_I32 ? 2 : 3));
903ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   return adj + op8;
904ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
905ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
906ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* Make sure we get valid 32 and 64bit addresses */
907ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic Addr64 mkSzAddr ( IRType ty, Addr64 addr )
908ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
909ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   vassert(ty == Ity_I32 || ty == Ity_I64);
910ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   return ( ty == Ity_I64 ?
911ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            (Addr64)addr :
912ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            (Addr64)extend_s_32to64( toUInt(addr) ) );
913ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
914ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
915ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* sz, ULong -> IRExpr */
916ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic IRExpr* mkSzImm ( IRType ty, ULong imm64 )
917ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
918ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   vassert(ty == Ity_I32 || ty == Ity_I64);
919ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   return ty == Ity_I64 ? mkU64(imm64) : mkU32((UInt)imm64);
920ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
921ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
922ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* sz, ULong -> IRConst */
923ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic IRConst* mkSzConst ( IRType ty, ULong imm64 )
924ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
925ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   vassert(ty == Ity_I32 || ty == Ity_I64);
926ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   return ( ty == Ity_I64 ?
927ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            IRConst_U64(imm64) :
928ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            IRConst_U32((UInt)imm64) );
929ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
930ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
931ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* Sign extend imm16 -> IRExpr* */
932ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic IRExpr* mkSzExtendS16 ( IRType ty, UInt imm16 )
933ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
934ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   vassert(ty == Ity_I32 || ty == Ity_I64);
935ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   return ( ty == Ity_I64 ?
936ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            mkU64(extend_s_16to64(imm16)) :
937ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            mkU32(extend_s_16to32(imm16)) );
938ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
939ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
940ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* Sign extend imm32 -> IRExpr* */
941ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic IRExpr* mkSzExtendS32 ( IRType ty, UInt imm32 )
942ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
943ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   vassert(ty == Ity_I32 || ty == Ity_I64);
944ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   return ( ty == Ity_I64 ?
945ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            mkU64(extend_s_32to64(imm32)) :
946ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            mkU32(imm32) );
947ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
948ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
949ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* IR narrows I32/I64 -> I8/I16/I32 */
950ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic IRExpr* mkNarrowTo8 ( IRType ty, IRExpr* src )
951ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
952ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   vassert(ty == Ity_I32 || ty == Ity_I64);
953ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   return ty == Ity_I64 ? unop(Iop_64to8, src) : unop(Iop_32to8, src);
954ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
955ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
956ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic IRExpr* mkNarrowTo16 ( IRType ty, IRExpr* src )
957ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
958ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   vassert(ty == Ity_I32 || ty == Ity_I64);
959ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   return ty == Ity_I64 ? unop(Iop_64to16, src) : unop(Iop_32to16, src);
960ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
961ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
962ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic IRExpr* mkNarrowTo32 ( IRType ty, IRExpr* src )
963ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
964ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   vassert(ty == Ity_I32 || ty == Ity_I64);
965ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   return ty == Ity_I64 ? unop(Iop_64to32, src) : src;
966ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
967ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
968ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* Signed/Unsigned IR widens I8/I16/I32 -> I32/I64 */
969ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic IRExpr* mkWidenFrom8 ( IRType ty, IRExpr* src, Bool sined )
970ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
971ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   IROp op;
972ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   vassert(ty == Ity_I32 || ty == Ity_I64);
973ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (sined) op = (ty==Ity_I32) ? Iop_8Sto32 : Iop_8Sto64;
974ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   else       op = (ty==Ity_I32) ? Iop_8Uto32 : Iop_8Uto64;
975ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   return unop(op, src);
976ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
977ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
978ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic IRExpr* mkWidenFrom16 ( IRType ty, IRExpr* src, Bool sined )
979ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
980ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   IROp op;
981ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   vassert(ty == Ity_I32 || ty == Ity_I64);
982ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (sined) op = (ty==Ity_I32) ? Iop_16Sto32 : Iop_16Sto64;
983ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   else       op = (ty==Ity_I32) ? Iop_16Uto32 : Iop_16Uto64;
984ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   return unop(op, src);
985ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
986ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
987ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic IRExpr* mkWidenFrom32 ( IRType ty, IRExpr* src, Bool sined )
988ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
989ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   vassert(ty == Ity_I32 || ty == Ity_I64);
990ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (ty == Ity_I32)
991ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      return src;
992ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   return (sined) ? unop(Iop_32Sto64, src) : unop(Iop_32Uto64, src);
993ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
994ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
995ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
996ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic Int integerGuestRegOffset ( UInt archreg )
997ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
998ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   vassert(archreg < 32);
999ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1000ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   // jrs: probably not necessary; only matters if we reference sub-parts
1001ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   // of the ppc registers, but that isn't the case
1002ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   // later: this might affect Altivec though?
1003ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   vassert(host_is_bigendian);
1004ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1005ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   switch (archreg) {
1006ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   case  0: return offsetofPPCGuestState(guest_GPR0);
1007ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   case  1: return offsetofPPCGuestState(guest_GPR1);
1008ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   case  2: return offsetofPPCGuestState(guest_GPR2);
1009ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   case  3: return offsetofPPCGuestState(guest_GPR3);
1010ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   case  4: return offsetofPPCGuestState(guest_GPR4);
1011ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   case  5: return offsetofPPCGuestState(guest_GPR5);
1012ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   case  6: return offsetofPPCGuestState(guest_GPR6);
1013ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   case  7: return offsetofPPCGuestState(guest_GPR7);
1014ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   case  8: return offsetofPPCGuestState(guest_GPR8);
1015ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   case  9: return offsetofPPCGuestState(guest_GPR9);
1016ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   case 10: return offsetofPPCGuestState(guest_GPR10);
1017ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   case 11: return offsetofPPCGuestState(guest_GPR11);
1018ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   case 12: return offsetofPPCGuestState(guest_GPR12);
1019ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   case 13: return offsetofPPCGuestState(guest_GPR13);
1020ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   case 14: return offsetofPPCGuestState(guest_GPR14);
1021ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   case 15: return offsetofPPCGuestState(guest_GPR15);
1022ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   case 16: return offsetofPPCGuestState(guest_GPR16);
1023ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   case 17: return offsetofPPCGuestState(guest_GPR17);
1024ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   case 18: return offsetofPPCGuestState(guest_GPR18);
1025ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   case 19: return offsetofPPCGuestState(guest_GPR19);
1026ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   case 20: return offsetofPPCGuestState(guest_GPR20);
1027ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   case 21: return offsetofPPCGuestState(guest_GPR21);
1028ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   case 22: return offsetofPPCGuestState(guest_GPR22);
1029ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   case 23: return offsetofPPCGuestState(guest_GPR23);
1030ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   case 24: return offsetofPPCGuestState(guest_GPR24);
1031ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   case 25: return offsetofPPCGuestState(guest_GPR25);
1032ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   case 26: return offsetofPPCGuestState(guest_GPR26);
1033ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   case 27: return offsetofPPCGuestState(guest_GPR27);
1034ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   case 28: return offsetofPPCGuestState(guest_GPR28);
1035ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   case 29: return offsetofPPCGuestState(guest_GPR29);
1036ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   case 30: return offsetofPPCGuestState(guest_GPR30);
1037ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   case 31: return offsetofPPCGuestState(guest_GPR31);
1038ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   default: break;
1039ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
1040ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   vpanic("integerGuestRegOffset(ppc,be)"); /*notreached*/
1041ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
1042ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1043ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic IRExpr* getIReg ( UInt archreg )
1044ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
1045ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   IRType ty = mode64 ? Ity_I64 : Ity_I32;
1046ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   vassert(archreg < 32);
1047ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   return IRExpr_Get( integerGuestRegOffset(archreg), ty );
1048ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
1049ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1050ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* Ditto, but write to a reg instead. */
1051ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic void putIReg ( UInt archreg, IRExpr* e )
1052ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
1053ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   IRType ty = mode64 ? Ity_I64 : Ity_I32;
1054ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   vassert(archreg < 32);
1055ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   vassert(typeOfIRExpr(irsb->tyenv, e) == ty );
1056ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   stmt( IRStmt_Put(integerGuestRegOffset(archreg), e) );
1057ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
1058ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1059ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1060b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov/* Floating point egisters are mapped to VSX registers[0..31]. */
1061ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic Int floatGuestRegOffset ( UInt archreg )
1062ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
1063ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   vassert(archreg < 32);
1064ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1065ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   switch (archreg) {
1066b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   case  0: return offsetofPPCGuestState(guest_VSR0);
1067b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   case  1: return offsetofPPCGuestState(guest_VSR1);
1068b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   case  2: return offsetofPPCGuestState(guest_VSR2);
1069b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   case  3: return offsetofPPCGuestState(guest_VSR3);
1070b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   case  4: return offsetofPPCGuestState(guest_VSR4);
1071b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   case  5: return offsetofPPCGuestState(guest_VSR5);
1072b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   case  6: return offsetofPPCGuestState(guest_VSR6);
1073b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   case  7: return offsetofPPCGuestState(guest_VSR7);
1074b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   case  8: return offsetofPPCGuestState(guest_VSR8);
1075b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   case  9: return offsetofPPCGuestState(guest_VSR9);
1076b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   case 10: return offsetofPPCGuestState(guest_VSR10);
1077b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   case 11: return offsetofPPCGuestState(guest_VSR11);
1078b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   case 12: return offsetofPPCGuestState(guest_VSR12);
1079b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   case 13: return offsetofPPCGuestState(guest_VSR13);
1080b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   case 14: return offsetofPPCGuestState(guest_VSR14);
1081b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   case 15: return offsetofPPCGuestState(guest_VSR15);
1082b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   case 16: return offsetofPPCGuestState(guest_VSR16);
1083b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   case 17: return offsetofPPCGuestState(guest_VSR17);
1084b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   case 18: return offsetofPPCGuestState(guest_VSR18);
1085b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   case 19: return offsetofPPCGuestState(guest_VSR19);
1086b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   case 20: return offsetofPPCGuestState(guest_VSR20);
1087b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   case 21: return offsetofPPCGuestState(guest_VSR21);
1088b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   case 22: return offsetofPPCGuestState(guest_VSR22);
1089b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   case 23: return offsetofPPCGuestState(guest_VSR23);
1090b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   case 24: return offsetofPPCGuestState(guest_VSR24);
1091b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   case 25: return offsetofPPCGuestState(guest_VSR25);
1092b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   case 26: return offsetofPPCGuestState(guest_VSR26);
1093b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   case 27: return offsetofPPCGuestState(guest_VSR27);
1094b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   case 28: return offsetofPPCGuestState(guest_VSR28);
1095b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   case 29: return offsetofPPCGuestState(guest_VSR29);
1096b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   case 30: return offsetofPPCGuestState(guest_VSR30);
1097b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   case 31: return offsetofPPCGuestState(guest_VSR31);
1098ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   default: break;
1099ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
1100ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   vpanic("floatGuestRegOffset(ppc)"); /*notreached*/
1101ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
1102ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1103ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic IRExpr* getFReg ( UInt archreg )
1104ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
1105ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   vassert(archreg < 32);
1106ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   return IRExpr_Get( floatGuestRegOffset(archreg), Ity_F64 );
1107ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
1108ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1109ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* Ditto, but write to a reg instead. */
1110ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic void putFReg ( UInt archreg, IRExpr* e )
1111ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
1112ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   vassert(archreg < 32);
1113ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   vassert(typeOfIRExpr(irsb->tyenv, e) == Ity_F64);
1114ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   stmt( IRStmt_Put(floatGuestRegOffset(archreg), e) );
1115ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
1116ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1117b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanovstatic Int vsxGuestRegOffset ( UInt archreg )
1118b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov{
1119b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   vassert(archreg < 64);
1120b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   switch (archreg) {
1121b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   case  0: return offsetofPPCGuestState(guest_VSR0);
1122b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   case  1: return offsetofPPCGuestState(guest_VSR1);
1123b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   case  2: return offsetofPPCGuestState(guest_VSR2);
1124b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   case  3: return offsetofPPCGuestState(guest_VSR3);
1125b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   case  4: return offsetofPPCGuestState(guest_VSR4);
1126b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   case  5: return offsetofPPCGuestState(guest_VSR5);
1127b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   case  6: return offsetofPPCGuestState(guest_VSR6);
1128b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   case  7: return offsetofPPCGuestState(guest_VSR7);
1129b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   case  8: return offsetofPPCGuestState(guest_VSR8);
1130b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   case  9: return offsetofPPCGuestState(guest_VSR9);
1131b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   case 10: return offsetofPPCGuestState(guest_VSR10);
1132b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   case 11: return offsetofPPCGuestState(guest_VSR11);
1133b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   case 12: return offsetofPPCGuestState(guest_VSR12);
1134b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   case 13: return offsetofPPCGuestState(guest_VSR13);
1135b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   case 14: return offsetofPPCGuestState(guest_VSR14);
1136b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   case 15: return offsetofPPCGuestState(guest_VSR15);
1137b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   case 16: return offsetofPPCGuestState(guest_VSR16);
1138b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   case 17: return offsetofPPCGuestState(guest_VSR17);
1139b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   case 18: return offsetofPPCGuestState(guest_VSR18);
1140b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   case 19: return offsetofPPCGuestState(guest_VSR19);
1141b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   case 20: return offsetofPPCGuestState(guest_VSR20);
1142b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   case 21: return offsetofPPCGuestState(guest_VSR21);
1143b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   case 22: return offsetofPPCGuestState(guest_VSR22);
1144b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   case 23: return offsetofPPCGuestState(guest_VSR23);
1145b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   case 24: return offsetofPPCGuestState(guest_VSR24);
1146b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   case 25: return offsetofPPCGuestState(guest_VSR25);
1147b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   case 26: return offsetofPPCGuestState(guest_VSR26);
1148b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   case 27: return offsetofPPCGuestState(guest_VSR27);
1149b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   case 28: return offsetofPPCGuestState(guest_VSR28);
1150b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   case 29: return offsetofPPCGuestState(guest_VSR29);
1151b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   case 30: return offsetofPPCGuestState(guest_VSR30);
1152b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   case 31: return offsetofPPCGuestState(guest_VSR31);
1153b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   case 32: return offsetofPPCGuestState(guest_VSR32);
1154b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   case 33: return offsetofPPCGuestState(guest_VSR33);
1155b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   case 34: return offsetofPPCGuestState(guest_VSR34);
1156b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   case 35: return offsetofPPCGuestState(guest_VSR35);
1157b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   case 36: return offsetofPPCGuestState(guest_VSR36);
1158b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   case 37: return offsetofPPCGuestState(guest_VSR37);
1159b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   case 38: return offsetofPPCGuestState(guest_VSR38);
1160b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   case 39: return offsetofPPCGuestState(guest_VSR39);
1161b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   case 40: return offsetofPPCGuestState(guest_VSR40);
1162b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   case 41: return offsetofPPCGuestState(guest_VSR41);
1163b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   case 42: return offsetofPPCGuestState(guest_VSR42);
1164b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   case 43: return offsetofPPCGuestState(guest_VSR43);
1165b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   case 44: return offsetofPPCGuestState(guest_VSR44);
1166b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   case 45: return offsetofPPCGuestState(guest_VSR45);
1167b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   case 46: return offsetofPPCGuestState(guest_VSR46);
1168b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   case 47: return offsetofPPCGuestState(guest_VSR47);
1169b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   case 48: return offsetofPPCGuestState(guest_VSR48);
1170b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   case 49: return offsetofPPCGuestState(guest_VSR49);
1171b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   case 50: return offsetofPPCGuestState(guest_VSR50);
1172b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   case 51: return offsetofPPCGuestState(guest_VSR51);
1173b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   case 52: return offsetofPPCGuestState(guest_VSR52);
1174b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   case 53: return offsetofPPCGuestState(guest_VSR53);
1175b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   case 54: return offsetofPPCGuestState(guest_VSR54);
1176b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   case 55: return offsetofPPCGuestState(guest_VSR55);
1177b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   case 56: return offsetofPPCGuestState(guest_VSR56);
1178b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   case 57: return offsetofPPCGuestState(guest_VSR57);
1179b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   case 58: return offsetofPPCGuestState(guest_VSR58);
1180b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   case 59: return offsetofPPCGuestState(guest_VSR59);
1181b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   case 60: return offsetofPPCGuestState(guest_VSR60);
1182b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   case 61: return offsetofPPCGuestState(guest_VSR61);
1183b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   case 62: return offsetofPPCGuestState(guest_VSR62);
1184b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   case 63: return offsetofPPCGuestState(guest_VSR63);
1185b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   default: break;
1186b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   }
1187b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   vpanic("vsxGuestRegOffset(ppc)"); /*notreached*/
1188b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov}
1189ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1190b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov/* Vector registers are mapped to VSX registers[32..63]. */
1191ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic Int vectorGuestRegOffset ( UInt archreg )
1192ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
1193ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   vassert(archreg < 32);
1194ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1195ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   switch (archreg) {
1196b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   case  0: return offsetofPPCGuestState(guest_VSR32);
1197b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   case  1: return offsetofPPCGuestState(guest_VSR33);
1198b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   case  2: return offsetofPPCGuestState(guest_VSR34);
1199b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   case  3: return offsetofPPCGuestState(guest_VSR35);
1200b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   case  4: return offsetofPPCGuestState(guest_VSR36);
1201b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   case  5: return offsetofPPCGuestState(guest_VSR37);
1202b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   case  6: return offsetofPPCGuestState(guest_VSR38);
1203b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   case  7: return offsetofPPCGuestState(guest_VSR39);
1204b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   case  8: return offsetofPPCGuestState(guest_VSR40);
1205b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   case  9: return offsetofPPCGuestState(guest_VSR41);
1206b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   case 10: return offsetofPPCGuestState(guest_VSR42);
1207b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   case 11: return offsetofPPCGuestState(guest_VSR43);
1208b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   case 12: return offsetofPPCGuestState(guest_VSR44);
1209b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   case 13: return offsetofPPCGuestState(guest_VSR45);
1210b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   case 14: return offsetofPPCGuestState(guest_VSR46);
1211b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   case 15: return offsetofPPCGuestState(guest_VSR47);
1212b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   case 16: return offsetofPPCGuestState(guest_VSR48);
1213b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   case 17: return offsetofPPCGuestState(guest_VSR49);
1214b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   case 18: return offsetofPPCGuestState(guest_VSR50);
1215b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   case 19: return offsetofPPCGuestState(guest_VSR51);
1216b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   case 20: return offsetofPPCGuestState(guest_VSR52);
1217b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   case 21: return offsetofPPCGuestState(guest_VSR53);
1218b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   case 22: return offsetofPPCGuestState(guest_VSR54);
1219b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   case 23: return offsetofPPCGuestState(guest_VSR55);
1220b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   case 24: return offsetofPPCGuestState(guest_VSR56);
1221b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   case 25: return offsetofPPCGuestState(guest_VSR57);
1222b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   case 26: return offsetofPPCGuestState(guest_VSR58);
1223b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   case 27: return offsetofPPCGuestState(guest_VSR59);
1224b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   case 28: return offsetofPPCGuestState(guest_VSR60);
1225b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   case 29: return offsetofPPCGuestState(guest_VSR61);
1226b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   case 30: return offsetofPPCGuestState(guest_VSR62);
1227b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   case 31: return offsetofPPCGuestState(guest_VSR63);
1228ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   default: break;
1229ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
1230ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   vpanic("vextorGuestRegOffset(ppc)"); /*notreached*/
1231ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
1232ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1233ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic IRExpr* getVReg ( UInt archreg )
1234ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
1235ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   vassert(archreg < 32);
1236ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   return IRExpr_Get( vectorGuestRegOffset(archreg), Ity_V128 );
1237ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
1238ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1239ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* Ditto, but write to a reg instead. */
1240ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic void putVReg ( UInt archreg, IRExpr* e )
1241ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
1242ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   vassert(archreg < 32);
1243ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   vassert(typeOfIRExpr(irsb->tyenv, e) == Ity_V128);
1244ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   stmt( IRStmt_Put(vectorGuestRegOffset(archreg), e) );
1245ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
1246ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1247b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov/* Get contents of VSX guest register */
1248b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanovstatic IRExpr* getVSReg ( UInt archreg )
1249b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov{
1250b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   vassert(archreg < 64);
1251b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   return IRExpr_Get( vsxGuestRegOffset(archreg), Ity_V128 );
1252b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov}
1253b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
1254b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov/* Ditto, but write to a VSX reg instead. */
1255b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanovstatic void putVSReg ( UInt archreg, IRExpr* e )
1256b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov{
1257b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   vassert(archreg < 64);
1258b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   vassert(typeOfIRExpr(irsb->tyenv, e) == Ity_V128);
1259b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   stmt( IRStmt_Put(vsxGuestRegOffset(archreg), e) );
1260b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov}
1261b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
1262b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
1263ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic Int guestCR321offset ( UInt cr )
1264ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
1265ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   switch (cr) {
1266ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   case 0: return offsetofPPCGuestState(guest_CR0_321 );
1267ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   case 1: return offsetofPPCGuestState(guest_CR1_321 );
1268ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   case 2: return offsetofPPCGuestState(guest_CR2_321 );
1269ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   case 3: return offsetofPPCGuestState(guest_CR3_321 );
1270ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   case 4: return offsetofPPCGuestState(guest_CR4_321 );
1271ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   case 5: return offsetofPPCGuestState(guest_CR5_321 );
1272ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   case 6: return offsetofPPCGuestState(guest_CR6_321 );
1273ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   case 7: return offsetofPPCGuestState(guest_CR7_321 );
1274ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   default: vpanic("guestCR321offset(ppc)");
1275ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
1276ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
1277ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1278ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic Int guestCR0offset ( UInt cr )
1279ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
1280ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   switch (cr) {
1281ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   case 0: return offsetofPPCGuestState(guest_CR0_0 );
1282ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   case 1: return offsetofPPCGuestState(guest_CR1_0 );
1283ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   case 2: return offsetofPPCGuestState(guest_CR2_0 );
1284ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   case 3: return offsetofPPCGuestState(guest_CR3_0 );
1285ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   case 4: return offsetofPPCGuestState(guest_CR4_0 );
1286ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   case 5: return offsetofPPCGuestState(guest_CR5_0 );
1287ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   case 6: return offsetofPPCGuestState(guest_CR6_0 );
1288ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   case 7: return offsetofPPCGuestState(guest_CR7_0 );
1289ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   default: vpanic("guestCR3offset(ppc)");
1290ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
1291ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
1292ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1293b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov/* Generate an IR sequence to do a popcount operation on the supplied
1294b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   IRTemp, and return a new IRTemp holding the result.  'ty' may be
1295b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   Ity_I32 or Ity_I64 only. */
1296b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanovstatic IRTemp gen_POPCOUNT ( IRType ty, IRTemp src )
1297b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov{
1298b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   Int i, shift[6];
1299b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   IRTemp mask[6];
1300b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   IRTemp old = IRTemp_INVALID;
1301b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   IRTemp nyu = IRTemp_INVALID;
1302b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
1303b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   vassert(ty == Ity_I64 || ty == Ity_I32);
1304b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
1305b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   if (ty == Ity_I32) {
1306b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      for (i = 0; i < 5; i++) {
1307b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         mask[i]  = newTemp(ty);
1308b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         shift[i] = 1 << i;
1309b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      }
1310b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      assign(mask[0], mkU32(0x55555555));
1311b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      assign(mask[1], mkU32(0x33333333));
1312b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      assign(mask[2], mkU32(0x0F0F0F0F));
1313b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      assign(mask[3], mkU32(0x00FF00FF));
1314b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      assign(mask[4], mkU32(0x0000FFFF));
1315b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      old = src;
1316b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      for (i = 0; i < 5; i++) {
1317b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         nyu = newTemp(ty);
1318b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         assign(nyu,
1319b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                binop(Iop_Add32,
1320b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                      binop(Iop_And32,
1321b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                            mkexpr(old),
1322b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                            mkexpr(mask[i])),
1323b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                      binop(Iop_And32,
1324b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                            binop(Iop_Shr32, mkexpr(old), mkU8(shift[i])),
1325b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                            mkexpr(mask[i]))));
1326b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         old = nyu;
1327b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      }
1328b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      return nyu;
1329b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   }
1330b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov// else, ty == Ity_I64
1331b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   for (i = 0; i < 6; i++) {
1332b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      mask[i] = newTemp( Ity_I64 );
1333b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      shift[i] = 1 << i;
1334b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   }
1335b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   assign( mask[0], mkU64( 0x5555555555555555ULL ) );
1336b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   assign( mask[1], mkU64( 0x3333333333333333ULL ) );
1337b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   assign( mask[2], mkU64( 0x0F0F0F0F0F0F0F0FULL ) );
1338b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   assign( mask[3], mkU64( 0x00FF00FF00FF00FFULL ) );
1339b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   assign( mask[4], mkU64( 0x0000FFFF0000FFFFULL ) );
1340b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   assign( mask[5], mkU64( 0x00000000FFFFFFFFULL ) );
1341b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   old = src;
1342b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   for (i = 0; i < 6; i++) {
1343b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      nyu = newTemp( Ity_I64 );
1344b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      assign( nyu,
1345b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov              binop( Iop_Add64,
1346b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                     binop( Iop_And64, mkexpr( old ), mkexpr( mask[i] ) ),
1347b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                     binop( Iop_And64,
1348b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                            binop( Iop_Shr64, mkexpr( old ), mkU8( shift[i] ) ),
1349b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                            mkexpr( mask[i] ) ) ) );
1350b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      old = nyu;
1351b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   }
1352b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   return nyu;
1353b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov}
1354b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
1355b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
1356ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// ROTL(src32/64, rot_amt5/6)
1357ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic IRExpr* /* :: Ity_I32/64 */ ROTL ( IRExpr* src,
1358ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                          IRExpr* rot_amt )
1359ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
1360ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   IRExpr *mask, *rot;
1361ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   vassert(typeOfIRExpr(irsb->tyenv,rot_amt) == Ity_I8);
1362ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1363ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (typeOfIRExpr(irsb->tyenv,src) == Ity_I64) {
1364ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      // rot = (src << rot_amt) | (src >> (64-rot_amt))
1365ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      mask = binop(Iop_And8, rot_amt, mkU8(63));
1366ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      rot  = binop(Iop_Or64,
1367ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                binop(Iop_Shl64, src, mask),
1368ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                binop(Iop_Shr64, src, binop(Iop_Sub8, mkU8(64), mask)));
1369ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   } else {
1370ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      // rot = (src << rot_amt) | (src >> (32-rot_amt))
1371ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      mask = binop(Iop_And8, rot_amt, mkU8(31));
1372ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      rot  = binop(Iop_Or32,
1373ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                binop(Iop_Shl32, src, mask),
1374ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                binop(Iop_Shr32, src, binop(Iop_Sub8, mkU8(32), mask)));
1375ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
1376ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* Note: the MuxOX is not merely an optimisation; it's needed
1377ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      because otherwise the Shr is a shift by the word size when
1378ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      mask denotes zero.  For rotates by immediates, a lot of
1379ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      this junk gets folded out. */
1380ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   return IRExpr_Mux0X( mask, /*     zero rotate */ src,
1381ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                              /* non-zero rotate */ rot );
1382ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
1383ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1384ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* Standard effective address calc: (rA + rB) */
1385ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic IRExpr* ea_rA_idxd ( UInt rA, UInt rB )
1386ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
1387ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   IRType ty = mode64 ? Ity_I64 : Ity_I32;
1388ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   vassert(rA < 32);
1389ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   vassert(rB < 32);
1390ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   return binop(mkSzOp(ty, Iop_Add8), getIReg(rA), getIReg(rB));
1391ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
1392ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1393ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* Standard effective address calc: (rA + simm) */
1394ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic IRExpr* ea_rA_simm ( UInt rA, UInt simm16 )
1395ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
1396ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   IRType ty = mode64 ? Ity_I64 : Ity_I32;
1397ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   vassert(rA < 32);
1398ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   return binop(mkSzOp(ty, Iop_Add8), getIReg(rA),
1399ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                mkSzExtendS16(ty, simm16));
1400ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
1401ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1402ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* Standard effective address calc: (rA|0) */
1403ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic IRExpr* ea_rAor0 ( UInt rA )
1404ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
1405ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   IRType ty = mode64 ? Ity_I64 : Ity_I32;
1406ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   vassert(rA < 32);
1407ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (rA == 0) {
1408ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      return mkSzImm(ty, 0);
1409ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   } else {
1410ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      return getIReg(rA);
1411ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
1412ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
1413ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1414ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* Standard effective address calc: (rA|0) + rB */
1415ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic IRExpr* ea_rAor0_idxd ( UInt rA, UInt rB )
1416ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
1417ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   vassert(rA < 32);
1418ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   vassert(rB < 32);
1419ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   return (rA == 0) ? getIReg(rB) : ea_rA_idxd( rA, rB );
1420ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
1421ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1422ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* Standard effective address calc: (rA|0) + simm16 */
1423ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic IRExpr* ea_rAor0_simm ( UInt rA, UInt simm16 )
1424ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
1425ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   IRType ty = mode64 ? Ity_I64 : Ity_I32;
1426ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   vassert(rA < 32);
1427ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (rA == 0) {
1428ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      return mkSzExtendS16(ty, simm16);
1429ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   } else {
1430ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      return ea_rA_simm( rA, simm16 );
1431ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
1432ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
1433ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1434ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1435ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* Align effective address */
1436ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic IRExpr* addr_align( IRExpr* addr, UChar align )
1437ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
1438ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   IRType ty = mode64 ? Ity_I64 : Ity_I32;
1439ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   Long mask;
1440ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   switch (align) {
1441ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   case 1:  return addr;                    // byte aligned
1442ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   case 2:  mask = ((Long)-1) << 1; break;  // half-word aligned
1443ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   case 4:  mask = ((Long)-1) << 2; break;  // word aligned
1444ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   case 16: mask = ((Long)-1) << 4; break;  // quad-word aligned
1445ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   default:
1446ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      vex_printf("addr_align: align = %u\n", align);
1447ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      vpanic("addr_align(ppc)");
1448ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
1449ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1450ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   vassert(typeOfIRExpr(irsb->tyenv,addr) == ty);
1451ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   return binop( mkSzOp(ty, Iop_And8), addr, mkSzImm(ty, mask) );
1452ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
1453ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1454ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1455ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* Exit the trace if ADDR (intended to be a guest memory address) is
1456ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   not ALIGN-aligned, generating a request for a SIGBUS followed by a
1457ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   restart of the current insn. */
1458ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic void gen_SIGBUS_if_misaligned ( IRTemp addr, UChar align )
1459ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
1460ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   vassert(align == 4 || align == 8);
1461ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (mode64) {
1462ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      vassert(typeOfIRTemp(irsb->tyenv, addr) == Ity_I64);
1463ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      stmt(
1464ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         IRStmt_Exit(
1465ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            binop(Iop_CmpNE64,
1466ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  binop(Iop_And64, mkexpr(addr), mkU64(align-1)),
1467ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  mkU64(0)),
1468ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            Ijk_SigBUS,
1469ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            IRConst_U64( guest_CIA_curr_instr )
1470ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         )
1471ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      );
1472ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   } else {
1473ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      vassert(typeOfIRTemp(irsb->tyenv, addr) == Ity_I32);
1474ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      stmt(
1475ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         IRStmt_Exit(
1476ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            binop(Iop_CmpNE32,
1477ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  binop(Iop_And32, mkexpr(addr), mkU32(align-1)),
1478ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  mkU32(0)),
1479ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            Ijk_SigBUS,
1480ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            IRConst_U32( guest_CIA_curr_instr )
1481ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         )
1482ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      );
1483ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
1484ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
1485ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1486ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1487ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* Generate AbiHints which mark points at which the ELF or PowerOpen
1488ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   ABIs say that the stack red zone (viz, -N(r1) .. -1(r1), for some
1489ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   N) becomes undefined.  That is at function calls and returns.  ELF
1490ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   ppc32 doesn't have this "feature" (how fortunate for it).  nia is
1491ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   the address of the next instruction to be executed.
1492ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown*/
1493ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic void make_redzone_AbiHint ( VexAbiInfo* vbi,
1494ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                   IRTemp nia, HChar* who )
1495ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
1496ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   Int szB = vbi->guest_stack_redzone_size;
1497ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (0) vex_printf("AbiHint: %s\n", who);
1498ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   vassert(szB >= 0);
1499ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (szB > 0) {
1500ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (mode64) {
1501ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         vassert(typeOfIRTemp(irsb->tyenv, nia) == Ity_I64);
1502ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         stmt( IRStmt_AbiHint(
1503ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  binop(Iop_Sub64, getIReg(1), mkU64(szB)),
1504ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  szB,
1505ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  mkexpr(nia)
1506ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         ));
1507ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      } else {
1508ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         vassert(typeOfIRTemp(irsb->tyenv, nia) == Ity_I32);
1509ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         stmt( IRStmt_AbiHint(
1510ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  binop(Iop_Sub32, getIReg(1), mkU32(szB)),
1511ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  szB,
1512ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  mkexpr(nia)
1513ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         ));
1514ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
1515ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
1516ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
1517ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1518ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1519ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*------------------------------------------------------------*/
1520ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*--- Helpers for condition codes.                         ---*/
1521ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*------------------------------------------------------------*/
1522ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1523ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* Condition register layout.
1524ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1525ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   In the hardware, CR is laid out like this.  The leftmost end is the
1526ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   most significant bit in the register; however the IBM documentation
1527ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   numbers the bits backwards for some reason.
1528ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1529ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   CR0      CR1    ..........   CR6       CR7
1530ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   0 .. 3   .......................  28 .. 31    (IBM bit numbering)
1531ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   31  28                             3    0     (normal bit numbering)
1532ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1533ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   Each CR field is 4 bits:  [<,>,==,SO]
1534ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1535ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   Hence in IBM's notation, BI=0 is CR7[SO], BI=1 is CR7[==], etc.
1536ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1537ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   Indexing from BI to guest state:
1538ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1539ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     let    n = BI / 4
1540ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown          off = BI % 4
1541ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     this references CR n:
1542ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1543ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        off==0   ->  guest_CRn_321 >> 3
1544ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        off==1   ->  guest_CRn_321 >> 2
1545ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        off==2   ->  guest_CRn_321 >> 1
1546ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        off==3   ->  guest_CRn_SO
1547ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1548ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   Bear in mind the only significant bit in guest_CRn_SO is bit 0
1549ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   (normal notation) and in guest_CRn_321 the significant bits are
1550ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   3, 2 and 1 (normal notation).
1551ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown*/
1552ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1553ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic void putCR321 ( UInt cr, IRExpr* e )
1554ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
1555ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   vassert(cr < 8);
1556ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   vassert(typeOfIRExpr(irsb->tyenv, e) == Ity_I8);
1557ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   stmt( IRStmt_Put(guestCR321offset(cr), e) );
1558ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
1559ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1560ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic void putCR0 ( UInt cr, IRExpr* e )
1561ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
1562ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   vassert(cr < 8);
1563ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   vassert(typeOfIRExpr(irsb->tyenv, e) == Ity_I8);
1564ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   stmt( IRStmt_Put(guestCR0offset(cr), e) );
1565ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
1566ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1567ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic IRExpr* /* :: Ity_I8 */ getCR0 ( UInt cr )
1568ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
1569ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   vassert(cr < 8);
1570ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   return IRExpr_Get(guestCR0offset(cr), Ity_I8);
1571ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
1572ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1573ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic IRExpr* /* :: Ity_I8 */ getCR321 ( UInt cr )
1574ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
1575ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   vassert(cr < 8);
1576ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   return IRExpr_Get(guestCR321offset(cr), Ity_I8);
1577ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
1578ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1579ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* Fetch the specified CR bit (as per IBM/hardware notation) and
1580ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   return it at the bottom of an I32; the top 31 bits are guaranteed
1581ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   to be zero. */
1582ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic IRExpr* /* :: Ity_I32 */ getCRbit ( UInt bi )
1583ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
1584ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   UInt n   = bi / 4;
1585ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   UInt off = bi % 4;
1586ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   vassert(bi < 32);
1587ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (off == 3) {
1588ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* Fetch the SO bit for this CR field */
1589ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* Note: And32 is redundant paranoia iff guest state only has 0
1590ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         or 1 in that slot. */
1591ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      return binop(Iop_And32, unop(Iop_8Uto32, getCR0(n)), mkU32(1));
1592ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   } else {
1593ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* Fetch the <, > or == bit for this CR field */
1594ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      return binop( Iop_And32,
1595ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                    binop( Iop_Shr32,
1596ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                           unop(Iop_8Uto32, getCR321(n)),
1597ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                           mkU8(toUChar(3-off)) ),
1598ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                    mkU32(1) );
1599ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
1600ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
1601ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1602ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* Dually, write the least significant bit of BIT to the specified CR
1603ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   bit.  Indexing as per getCRbit. */
1604ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic void putCRbit ( UInt bi, IRExpr* bit )
1605ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
1606ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   UInt    n, off;
1607ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   IRExpr* safe;
1608ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   vassert(typeOfIRExpr(irsb->tyenv,bit) == Ity_I32);
1609ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   safe = binop(Iop_And32, bit, mkU32(1));
1610ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   n   = bi / 4;
1611ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   off = bi % 4;
1612ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   vassert(bi < 32);
1613ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (off == 3) {
1614ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* This is the SO bit for this CR field */
1615ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      putCR0(n, unop(Iop_32to8, safe));
1616ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   } else {
1617ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      off = 3 - off;
1618ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      vassert(off == 1 || off == 2 || off == 3);
1619ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      putCR321(
1620ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         n,
1621ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         unop( Iop_32to8,
1622ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               binop( Iop_Or32,
1623ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                      /* old value with field masked out */
1624ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                      binop(Iop_And32, unop(Iop_8Uto32, getCR321(n)),
1625ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                       mkU32(~(1 << off))),
1626ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                      /* new value in the right place */
1627ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                      binop(Iop_Shl32, safe, mkU8(toUChar(off)))
1628ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               )
1629ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         )
1630ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      );
1631ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
1632ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
1633ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1634ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* Fetch the specified CR bit (as per IBM/hardware notation) and
1635ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   return it somewhere in an I32; it does not matter where, but
1636ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   whichever bit it is, all other bits are guaranteed to be zero.  In
1637ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   other words, the I32-typed expression will be zero if the bit is
1638ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   zero and nonzero if the bit is 1.  Write into *where the index
1639ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   of where the bit will be. */
1640ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1641ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic
1642ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownIRExpr* /* :: Ity_I32 */ getCRbit_anywhere ( UInt bi, Int* where )
1643ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
1644ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   UInt n   = bi / 4;
1645ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   UInt off = bi % 4;
1646ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   vassert(bi < 32);
1647ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (off == 3) {
1648ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* Fetch the SO bit for this CR field */
1649ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* Note: And32 is redundant paranoia iff guest state only has 0
1650ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         or 1 in that slot. */
1651ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      *where = 0;
1652ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      return binop(Iop_And32, unop(Iop_8Uto32, getCR0(n)), mkU32(1));
1653ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   } else {
1654ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* Fetch the <, > or == bit for this CR field */
1655ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      *where = 3-off;
1656ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      return binop( Iop_And32,
1657ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                    unop(Iop_8Uto32, getCR321(n)),
1658ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                    mkU32(1 << (3-off)) );
1659ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
1660ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
1661ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1662ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* Set the CR0 flags following an arithmetic operation.
1663ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   (Condition Register CR0 Field Definition, PPC32 p60)
1664ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown*/
1665ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic IRExpr* getXER_SO ( void );
1666ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic void set_CR0 ( IRExpr* result )
1667ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
1668ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   vassert(typeOfIRExpr(irsb->tyenv,result) == Ity_I32 ||
1669ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown           typeOfIRExpr(irsb->tyenv,result) == Ity_I64);
1670ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (mode64) {
1671ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      putCR321( 0, unop(Iop_64to8,
1672ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                        binop(Iop_CmpORD64S, result, mkU64(0))) );
1673ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   } else {
1674ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      putCR321( 0, unop(Iop_32to8,
1675ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                        binop(Iop_CmpORD32S, result, mkU32(0))) );
1676ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
1677ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   putCR0( 0, getXER_SO() );
1678ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
1679ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1680ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1681b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov/* Set the CR6 flags following an AltiVec compare operation.
1682b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov * NOTE: This also works for VSX single-precision compares.
1683b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov * */
1684ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic void set_AV_CR6 ( IRExpr* result, Bool test_all_ones )
1685ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
1686ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* CR6[0:3] = {all_ones, 0, all_zeros, 0}
1687ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      all_ones  = (v[0] && v[1] && v[2] && v[3])
1688ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      all_zeros = ~(v[0] || v[1] || v[2] || v[3])
1689ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   */
1690ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   IRTemp v0 = newTemp(Ity_V128);
1691ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   IRTemp v1 = newTemp(Ity_V128);
1692ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   IRTemp v2 = newTemp(Ity_V128);
1693ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   IRTemp v3 = newTemp(Ity_V128);
1694ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   IRTemp rOnes  = newTemp(Ity_I8);
1695ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   IRTemp rZeros = newTemp(Ity_I8);
1696ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1697ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   vassert(typeOfIRExpr(irsb->tyenv,result) == Ity_V128);
1698ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1699ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   assign( v0, result );
1700ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   assign( v1, binop(Iop_ShrV128, result, mkU8(32)) );
1701ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   assign( v2, binop(Iop_ShrV128, result, mkU8(64)) );
1702ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   assign( v3, binop(Iop_ShrV128, result, mkU8(96)) );
1703ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1704ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   assign( rZeros, unop(Iop_1Uto8,
1705ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown       binop(Iop_CmpEQ32, mkU32(0xFFFFFFFF),
1706ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown             unop(Iop_Not32,
1707ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  unop(Iop_V128to32,
1708ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                       binop(Iop_OrV128,
1709ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                             binop(Iop_OrV128, mkexpr(v0), mkexpr(v1)),
1710ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                             binop(Iop_OrV128, mkexpr(v2), mkexpr(v3))))
1711ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  ))) );
1712ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1713ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (test_all_ones) {
1714ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      assign( rOnes, unop(Iop_1Uto8,
1715ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         binop(Iop_CmpEQ32, mkU32(0xFFFFFFFF),
1716ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               unop(Iop_V128to32,
1717ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                    binop(Iop_AndV128,
1718ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                          binop(Iop_AndV128, mkexpr(v0), mkexpr(v1)),
1719ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                          binop(Iop_AndV128, mkexpr(v2), mkexpr(v3)))
1720ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                    ))) );
1721ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      putCR321( 6, binop(Iop_Or8,
1722ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                         binop(Iop_Shl8, mkexpr(rOnes),  mkU8(3)),
1723ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                         binop(Iop_Shl8, mkexpr(rZeros), mkU8(1))) );
1724ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   } else {
1725ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      putCR321( 6, binop(Iop_Shl8, mkexpr(rZeros), mkU8(1)) );
1726ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
1727ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   putCR0( 6, mkU8(0) );
1728ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
1729ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1730ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1731ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1732ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*------------------------------------------------------------*/
1733ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*--- Helpers for XER flags.                               ---*/
1734ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*------------------------------------------------------------*/
1735ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1736ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic void putXER_SO ( IRExpr* e )
1737ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
1738ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   IRExpr* so;
1739ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   vassert(typeOfIRExpr(irsb->tyenv, e) == Ity_I8);
1740ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   so = binop(Iop_And8, e, mkU8(1));
1741ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   stmt( IRStmt_Put( OFFB_XER_SO, so ) );
1742ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
1743ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1744ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic void putXER_OV ( IRExpr* e )
1745ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
1746ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   IRExpr* ov;
1747ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   vassert(typeOfIRExpr(irsb->tyenv, e) == Ity_I8);
1748ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   ov = binop(Iop_And8, e, mkU8(1));
1749ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   stmt( IRStmt_Put( OFFB_XER_OV, ov ) );
1750ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
1751ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1752ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic void putXER_CA ( IRExpr* e )
1753ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
1754ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   IRExpr* ca;
1755ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   vassert(typeOfIRExpr(irsb->tyenv, e) == Ity_I8);
1756ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   ca = binop(Iop_And8, e, mkU8(1));
1757ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   stmt( IRStmt_Put( OFFB_XER_CA, ca ) );
1758ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
1759ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1760ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic void putXER_BC ( IRExpr* e )
1761ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
1762ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   IRExpr* bc;
1763ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   vassert(typeOfIRExpr(irsb->tyenv, e) == Ity_I8);
1764ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   bc = binop(Iop_And8, e, mkU8(0x7F));
1765ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   stmt( IRStmt_Put( OFFB_XER_BC, bc ) );
1766ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
1767ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1768ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic IRExpr* /* :: Ity_I8 */ getXER_SO ( void )
1769ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
1770ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   return IRExpr_Get( OFFB_XER_SO, Ity_I8 );
1771ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
1772ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1773ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic IRExpr* /* :: Ity_I32 */ getXER_SO32 ( void )
1774ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
1775ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   return binop( Iop_And32, unop(Iop_8Uto32, getXER_SO()), mkU32(1) );
1776ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
1777ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1778ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic IRExpr* /* :: Ity_I8 */ getXER_OV ( void )
1779ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
1780ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   return IRExpr_Get( OFFB_XER_OV, Ity_I8 );
1781ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
1782ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1783ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic IRExpr* /* :: Ity_I32 */ getXER_OV32 ( void )
1784ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
1785ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   return binop( Iop_And32, unop(Iop_8Uto32, getXER_OV()), mkU32(1) );
1786ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
1787ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1788ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic IRExpr* /* :: Ity_I32 */ getXER_CA32 ( void )
1789ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
1790ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   IRExpr* ca = IRExpr_Get( OFFB_XER_CA, Ity_I8 );
1791ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   return binop( Iop_And32, unop(Iop_8Uto32, ca ), mkU32(1) );
1792ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
1793ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1794ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic IRExpr* /* :: Ity_I8 */ getXER_BC ( void )
1795ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
1796ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   return IRExpr_Get( OFFB_XER_BC, Ity_I8 );
1797ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
1798ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1799ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic IRExpr* /* :: Ity_I32 */ getXER_BC32 ( void )
1800ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
1801ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   IRExpr* bc = IRExpr_Get( OFFB_XER_BC, Ity_I8 );
1802ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   return binop( Iop_And32, unop(Iop_8Uto32, bc), mkU32(0x7F) );
1803ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
1804ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1805ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1806ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* RES is the result of doing OP on ARGL and ARGR.  Set %XER.OV and
1807ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   %XER.SO accordingly. */
1808ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1809ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic void set_XER_OV_32( UInt op, IRExpr* res,
1810ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                           IRExpr* argL, IRExpr* argR )
1811ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
1812ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   IRTemp  t64;
1813ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   IRExpr* xer_ov;
1814ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   vassert(op < PPCG_FLAG_OP_NUMBER);
1815ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   vassert(typeOfIRExpr(irsb->tyenv,res)  == Ity_I32);
1816ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   vassert(typeOfIRExpr(irsb->tyenv,argL) == Ity_I32);
1817ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   vassert(typeOfIRExpr(irsb->tyenv,argR) == Ity_I32);
1818ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1819ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#  define INT32_MIN 0x80000000
1820ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1821ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#  define XOR2(_aa,_bb) \
1822ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      binop(Iop_Xor32,(_aa),(_bb))
1823ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1824ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#  define XOR3(_cc,_dd,_ee) \
1825ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      binop(Iop_Xor32,binop(Iop_Xor32,(_cc),(_dd)),(_ee))
1826ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1827ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#  define AND3(_ff,_gg,_hh) \
1828ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      binop(Iop_And32,binop(Iop_And32,(_ff),(_gg)),(_hh))
1829ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1830ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define NOT(_jj) \
1831ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      unop(Iop_Not32, (_jj))
1832ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1833ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   switch (op) {
1834ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   case /* 0  */ PPCG_FLAG_OP_ADD:
1835ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   case /* 1  */ PPCG_FLAG_OP_ADDE:
1836ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* (argL^argR^-1) & (argL^res) & (1<<31)  ?1:0 */
1837ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      // i.e. ((both_same_sign) & (sign_changed) & (sign_mask))
1838ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      xer_ov
1839ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         = AND3( XOR3(argL,argR,mkU32(-1)),
1840ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                 XOR2(argL,res),
1841ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                 mkU32(INT32_MIN) );
1842ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* xer_ov can only be 0 or 1<<31 */
1843ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      xer_ov
1844ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         = binop(Iop_Shr32, xer_ov, mkU8(31) );
1845ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      break;
1846ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1847ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   case /* 2  */ PPCG_FLAG_OP_DIVW:
1848ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* (argL == INT32_MIN && argR == -1) || argR == 0 */
1849ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      xer_ov
1850ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         = mkOR1(
1851ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown              mkAND1(
1852ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                 binop(Iop_CmpEQ32, argL, mkU32(INT32_MIN)),
1853ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                 binop(Iop_CmpEQ32, argR, mkU32(-1))
1854ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown              ),
1855ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown              binop(Iop_CmpEQ32, argR, mkU32(0) )
1856ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown           );
1857ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      xer_ov
1858ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         = unop(Iop_1Uto32, xer_ov);
1859ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      break;
1860ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1861ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   case /* 3  */ PPCG_FLAG_OP_DIVWU:
1862ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* argR == 0 */
1863ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      xer_ov
1864ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         = unop(Iop_1Uto32, binop(Iop_CmpEQ32, argR, mkU32(0)));
1865ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      break;
1866ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1867ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   case /* 4  */ PPCG_FLAG_OP_MULLW:
1868ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* OV true if result can't be represented in 32 bits
1869ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         i.e sHi != sign extension of sLo */
1870ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      t64 = newTemp(Ity_I64);
1871ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      assign( t64, binop(Iop_MullS32, argL, argR) );
1872ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      xer_ov
1873ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         = binop( Iop_CmpNE32,
1874ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  unop(Iop_64HIto32, mkexpr(t64)),
1875ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  binop( Iop_Sar32,
1876ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                         unop(Iop_64to32, mkexpr(t64)),
1877ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                         mkU8(31))
1878ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  );
1879ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      xer_ov
1880ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         = unop(Iop_1Uto32, xer_ov);
1881ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      break;
1882ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1883ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   case /* 5  */ PPCG_FLAG_OP_NEG:
1884ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* argL == INT32_MIN */
1885ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      xer_ov
1886ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         = unop( Iop_1Uto32,
1887ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                 binop(Iop_CmpEQ32, argL, mkU32(INT32_MIN)) );
1888ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      break;
1889ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1890ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   case /* 6  */ PPCG_FLAG_OP_SUBF:
1891ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   case /* 7  */ PPCG_FLAG_OP_SUBFC:
1892ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   case /* 8  */ PPCG_FLAG_OP_SUBFE:
1893ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* ((~argL)^argR^-1) & ((~argL)^res) & (1<<31) ?1:0; */
1894ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      xer_ov
1895ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         = AND3( XOR3(NOT(argL),argR,mkU32(-1)),
1896ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                 XOR2(NOT(argL),res),
1897ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                 mkU32(INT32_MIN) );
1898ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* xer_ov can only be 0 or 1<<31 */
1899ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      xer_ov
1900ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         = binop(Iop_Shr32, xer_ov, mkU8(31) );
1901ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      break;
1902ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1903b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   case PPCG_FLAG_OP_DIVWEU:
1904b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      xer_ov
1905b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov               = binop( Iop_Or32,
1906b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                        unop( Iop_1Uto32, binop( Iop_CmpEQ32, argR, mkU32( 0 ) ) ),
1907b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                        unop( Iop_1Uto32, binop( Iop_CmpLT32U, argR, argL ) ) );
1908b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      break;
1909b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
1910b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   case PPCG_FLAG_OP_DIVWE:
1911b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
1912b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      /* If argR == 0 of if the result cannot fit in the 32-bit destination register,
1913b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov       * then OV <- 1.   If dest reg is 0 AND both dividend and divisor are non-zero,
1914b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov       * an overflow is implied.
1915b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov       */
1916b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      xer_ov = binop( Iop_Or32,
1917b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                      unop( Iop_1Uto32, binop( Iop_CmpEQ32, argR, mkU32( 0 ) ) ),
1918b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                      unop( Iop_1Uto32, mkAND1( binop( Iop_CmpEQ32, res, mkU32( 0 ) ),
1919b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                              mkAND1( binop( Iop_CmpNE32, argL, mkU32( 0 ) ),
1920b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                                      binop( Iop_CmpNE32, argR, mkU32( 0 ) ) ) ) ) );
1921b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      break;
1922b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
1923b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
1924b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
1925ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   default:
1926ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      vex_printf("set_XER_OV: op = %u\n", op);
1927ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      vpanic("set_XER_OV(ppc)");
1928ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
1929ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1930ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* xer_ov MUST denote either 0 or 1, no other value allowed */
1931ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   putXER_OV( unop(Iop_32to8, xer_ov) );
1932ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1933ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* Update the summary overflow */
1934ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   putXER_SO( binop(Iop_Or8, getXER_SO(), getXER_OV()) );
1935ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1936ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#  undef INT32_MIN
1937ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#  undef AND3
1938ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#  undef XOR3
1939ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#  undef XOR2
1940ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#  undef NOT
1941ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
1942ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1943ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic void set_XER_OV_64( UInt op, IRExpr* res,
1944ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                           IRExpr* argL, IRExpr* argR )
1945ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
1946ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   IRExpr* xer_ov;
1947ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   vassert(op < PPCG_FLAG_OP_NUMBER);
1948ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   vassert(typeOfIRExpr(irsb->tyenv,res)  == Ity_I64);
1949ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   vassert(typeOfIRExpr(irsb->tyenv,argL) == Ity_I64);
1950ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   vassert(typeOfIRExpr(irsb->tyenv,argR) == Ity_I64);
1951ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1952ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#  define INT64_MIN 0x8000000000000000ULL
1953ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1954ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#  define XOR2(_aa,_bb) \
1955ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      binop(Iop_Xor64,(_aa),(_bb))
1956ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1957ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#  define XOR3(_cc,_dd,_ee) \
1958ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      binop(Iop_Xor64,binop(Iop_Xor64,(_cc),(_dd)),(_ee))
1959ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1960ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#  define AND3(_ff,_gg,_hh) \
1961ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      binop(Iop_And64,binop(Iop_And64,(_ff),(_gg)),(_hh))
1962ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1963ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define NOT(_jj) \
1964ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      unop(Iop_Not64, (_jj))
1965ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1966ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   switch (op) {
1967ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   case /* 0  */ PPCG_FLAG_OP_ADD:
1968ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   case /* 1  */ PPCG_FLAG_OP_ADDE:
1969ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* (argL^argR^-1) & (argL^res) & (1<<63)  ? 1:0 */
1970ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      // i.e. ((both_same_sign) & (sign_changed) & (sign_mask))
1971ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      xer_ov
1972ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         = AND3( XOR3(argL,argR,mkU64(-1)),
1973ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                 XOR2(argL,res),
1974ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                 mkU64(INT64_MIN) );
1975ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* xer_ov can only be 0 or 1<<63 */
1976ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      xer_ov
1977ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         = unop(Iop_64to1, binop(Iop_Shr64, xer_ov, mkU8(63)));
1978ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      break;
1979ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1980ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   case /* 2  */ PPCG_FLAG_OP_DIVW:
1981ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* (argL == INT64_MIN && argR == -1) || argR == 0 */
1982ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      xer_ov
1983ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         = mkOR1(
1984ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown              mkAND1(
1985ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                 binop(Iop_CmpEQ64, argL, mkU64(INT64_MIN)),
1986ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                 binop(Iop_CmpEQ64, argR, mkU64(-1))
1987ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown              ),
1988ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown              binop(Iop_CmpEQ64, argR, mkU64(0) )
1989ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown           );
1990ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      break;
1991ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1992ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   case /* 3  */ PPCG_FLAG_OP_DIVWU:
1993ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* argR == 0 */
1994ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      xer_ov
1995ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         = binop(Iop_CmpEQ64, argR, mkU64(0));
1996ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      break;
1997ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1998ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   case /* 4  */ PPCG_FLAG_OP_MULLW: {
1999ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* OV true if result can't be represented in 64 bits
2000ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         i.e sHi != sign extension of sLo */
2001ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      xer_ov
2002ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         = binop( Iop_CmpNE32,
2003ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  unop(Iop_64HIto32, res),
2004ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  binop( Iop_Sar32,
2005ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                         unop(Iop_64to32, res),
2006ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                         mkU8(31))
2007ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  );
2008ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      break;
2009ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
2010ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2011ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   case /* 5  */ PPCG_FLAG_OP_NEG:
2012ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* argL == INT64_MIN */
2013ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      xer_ov
2014ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         = binop(Iop_CmpEQ64, argL, mkU64(INT64_MIN));
2015ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      break;
2016ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2017ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   case /* 6  */ PPCG_FLAG_OP_SUBF:
2018ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   case /* 7  */ PPCG_FLAG_OP_SUBFC:
2019ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   case /* 8  */ PPCG_FLAG_OP_SUBFE:
2020ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* ((~argL)^argR^-1) & ((~argL)^res) & (1<<63) ?1:0; */
2021ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      xer_ov
2022ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         = AND3( XOR3(NOT(argL),argR,mkU64(-1)),
2023ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                 XOR2(NOT(argL),res),
2024ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                 mkU64(INT64_MIN) );
2025ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* xer_ov can only be 0 or 1<<63 */
2026ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      xer_ov
2027ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         = unop(Iop_64to1, binop(Iop_Shr64, xer_ov, mkU8(63)));
2028ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      break;
2029ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2030b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   case PPCG_FLAG_OP_DIVDE:
2031b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
2032b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      /* If argR == 0, we must set the OV bit.  But there's another condition
2033b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov       * where we can get overflow set for divde . . . when the
2034b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov       * result cannot fit in the 64-bit destination register.  If dest reg is 0 AND
2035b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov       * both dividend and divisor are non-zero, it implies an overflow.
2036b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov       */
2037b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      xer_ov
2038b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                  = mkOR1( binop( Iop_CmpEQ64, argR, mkU64( 0 ) ),
2039b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                           mkAND1( binop( Iop_CmpEQ64, res, mkU64( 0 ) ),
2040b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                                   mkAND1( binop( Iop_CmpNE64, argL, mkU64( 0 ) ),
2041b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                                           binop( Iop_CmpNE64, argR, mkU64( 0 ) ) ) ) );
2042b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      break;
2043b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
2044b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   case PPCG_FLAG_OP_DIVDEU:
2045b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov     /* If argR == 0 or if argL >= argR, set OV. */
2046b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov     xer_ov = mkOR1( binop( Iop_CmpEQ64, argR, mkU64( 0 ) ),
2047b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                         binop( Iop_CmpLE64U, argR, argL ) );
2048b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov     break;
2049b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
2050ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   default:
2051ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      vex_printf("set_XER_OV: op = %u\n", op);
2052ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      vpanic("set_XER_OV(ppc64)");
2053ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
2054ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2055ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* xer_ov MUST denote either 0 or 1, no other value allowed */
2056ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   putXER_OV( unop(Iop_1Uto8, xer_ov) );
2057ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2058ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* Update the summary overflow */
2059ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   putXER_SO( binop(Iop_Or8, getXER_SO(), getXER_OV()) );
2060ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2061ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#  undef INT64_MIN
2062ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#  undef AND3
2063ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#  undef XOR3
2064ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#  undef XOR2
2065ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#  undef NOT
2066ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
2067ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2068ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic void set_XER_OV ( IRType ty, UInt op, IRExpr* res,
2069ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                         IRExpr* argL, IRExpr* argR )
2070ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
2071ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (ty == Ity_I32)
2072ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      set_XER_OV_32( op, res, argL, argR );
2073ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   else
2074ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      set_XER_OV_64( op, res, argL, argR );
2075ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
2076ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2077ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2078ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2079ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* RES is the result of doing OP on ARGL and ARGR with the old %XER.CA
2080ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   value being OLDCA.  Set %XER.CA accordingly. */
2081ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2082ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic void set_XER_CA_32 ( UInt op, IRExpr* res,
2083ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                            IRExpr* argL, IRExpr* argR, IRExpr* oldca )
2084ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
2085ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   IRExpr* xer_ca;
2086ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   vassert(op < PPCG_FLAG_OP_NUMBER);
2087ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   vassert(typeOfIRExpr(irsb->tyenv,res)   == Ity_I32);
2088ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   vassert(typeOfIRExpr(irsb->tyenv,argL)  == Ity_I32);
2089ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   vassert(typeOfIRExpr(irsb->tyenv,argR)  == Ity_I32);
2090ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   vassert(typeOfIRExpr(irsb->tyenv,oldca) == Ity_I32);
2091ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2092ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* Incoming oldca is assumed to hold the values 0 or 1 only.  This
2093ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      seems reasonable given that it's always generated by
2094ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      getXER_CA32(), which masks it accordingly.  In any case it being
2095ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      0 or 1 is an invariant of the ppc guest state representation;
2096ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if it has any other value, that invariant has been violated. */
2097ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2098ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   switch (op) {
2099ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   case /* 0 */ PPCG_FLAG_OP_ADD:
2100ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* res <u argL */
2101ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      xer_ca
2102ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         = unop(Iop_1Uto32, binop(Iop_CmpLT32U, res, argL));
2103ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      break;
2104ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2105ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   case /* 1 */ PPCG_FLAG_OP_ADDE:
2106ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* res <u argL || (old_ca==1 && res==argL) */
2107ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      xer_ca
2108ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         = mkOR1(
2109ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown              binop(Iop_CmpLT32U, res, argL),
2110ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown              mkAND1(
2111ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                 binop(Iop_CmpEQ32, oldca, mkU32(1)),
2112ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                 binop(Iop_CmpEQ32, res, argL)
2113ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown              )
2114ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown           );
2115ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      xer_ca
2116ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         = unop(Iop_1Uto32, xer_ca);
2117ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      break;
2118ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2119ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   case /* 8 */ PPCG_FLAG_OP_SUBFE:
2120ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* res <u argR || (old_ca==1 && res==argR) */
2121ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      xer_ca
2122ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         = mkOR1(
2123ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown              binop(Iop_CmpLT32U, res, argR),
2124ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown              mkAND1(
2125ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                 binop(Iop_CmpEQ32, oldca, mkU32(1)),
2126ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                 binop(Iop_CmpEQ32, res, argR)
2127ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown              )
2128ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown           );
2129ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      xer_ca
2130ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         = unop(Iop_1Uto32, xer_ca);
2131ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      break;
2132ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2133ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   case /* 7 */ PPCG_FLAG_OP_SUBFC:
2134ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   case /* 9 */ PPCG_FLAG_OP_SUBFI:
2135ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* res <=u argR */
2136ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      xer_ca
2137ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         = unop(Iop_1Uto32, binop(Iop_CmpLE32U, res, argR));
2138ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      break;
2139ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2140ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   case /* 10 */ PPCG_FLAG_OP_SRAW:
2141ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* The shift amount is guaranteed to be in 0 .. 63 inclusive.
2142ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         If it is <= 31, behave like SRAWI; else XER.CA is the sign
2143ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         bit of argL. */
2144ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* This term valid for shift amount < 32 only */
2145ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      xer_ca
2146ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         = binop(
2147ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown              Iop_And32,
2148ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown              binop(Iop_Sar32, argL, mkU8(31)),
2149ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown              binop( Iop_And32,
2150ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                     argL,
2151ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                     binop( Iop_Sub32,
2152ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                            binop(Iop_Shl32, mkU32(1),
2153ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                             unop(Iop_32to8,argR)),
2154ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                            mkU32(1) )
2155ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                     )
2156ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown              );
2157ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      xer_ca
2158ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         = IRExpr_Mux0X(
2159ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown              /* shift amt > 31 ? */
2160ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown              unop(Iop_1Uto8, binop(Iop_CmpLT32U, mkU32(31), argR)),
2161ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown              /* no -- be like srawi */
2162ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown              unop(Iop_1Uto32, binop(Iop_CmpNE32, xer_ca, mkU32(0))),
2163ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown              /* yes -- get sign bit of argL */
2164ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown              binop(Iop_Shr32, argL, mkU8(31))
2165ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown           );
2166ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      break;
2167ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2168ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   case /* 11 */ PPCG_FLAG_OP_SRAWI:
2169ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* xer_ca is 1 iff src was negative and bits_shifted_out !=
2170ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         0.  Since the shift amount is known to be in the range
2171ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         0 .. 31 inclusive the following seems viable:
2172ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         xer.ca == 1 iff the following is nonzero:
2173ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         (argL >>s 31)           -- either all 0s or all 1s
2174ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         & (argL & (1<<argR)-1)  -- the stuff shifted out */
2175ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      xer_ca
2176ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         = binop(
2177ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown              Iop_And32,
2178ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown              binop(Iop_Sar32, argL, mkU8(31)),
2179ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown              binop( Iop_And32,
2180ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                     argL,
2181ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                     binop( Iop_Sub32,
2182ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                            binop(Iop_Shl32, mkU32(1),
2183ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                             unop(Iop_32to8,argR)),
2184ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                            mkU32(1) )
2185ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                     )
2186ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown              );
2187ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      xer_ca
2188ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         = unop(Iop_1Uto32, binop(Iop_CmpNE32, xer_ca, mkU32(0)));
2189ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      break;
2190ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2191ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   default:
2192ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      vex_printf("set_XER_CA: op = %u\n", op);
2193ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      vpanic("set_XER_CA(ppc)");
2194ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
2195ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2196ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* xer_ca MUST denote either 0 or 1, no other value allowed */
2197ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   putXER_CA( unop(Iop_32to8, xer_ca) );
2198ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
2199ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2200ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic void set_XER_CA_64 ( UInt op, IRExpr* res,
2201ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                            IRExpr* argL, IRExpr* argR, IRExpr* oldca )
2202ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
2203ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   IRExpr* xer_ca;
2204ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   vassert(op < PPCG_FLAG_OP_NUMBER);
2205ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   vassert(typeOfIRExpr(irsb->tyenv,res)   == Ity_I64);
2206ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   vassert(typeOfIRExpr(irsb->tyenv,argL)  == Ity_I64);
2207ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   vassert(typeOfIRExpr(irsb->tyenv,argR)  == Ity_I64);
2208ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   vassert(typeOfIRExpr(irsb->tyenv,oldca) == Ity_I64);
2209ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2210ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* Incoming oldca is assumed to hold the values 0 or 1 only.  This
2211ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      seems reasonable given that it's always generated by
2212ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      getXER_CA32(), which masks it accordingly.  In any case it being
2213ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      0 or 1 is an invariant of the ppc guest state representation;
2214ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if it has any other value, that invariant has been violated. */
2215ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2216ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   switch (op) {
2217ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   case /* 0 */ PPCG_FLAG_OP_ADD:
2218ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* res <u argL */
2219ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      xer_ca
2220ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         = unop(Iop_1Uto32, binop(Iop_CmpLT64U, res, argL));
2221ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      break;
2222ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2223ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   case /* 1 */ PPCG_FLAG_OP_ADDE:
2224ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* res <u argL || (old_ca==1 && res==argL) */
2225ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      xer_ca
2226ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         = mkOR1(
2227ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown              binop(Iop_CmpLT64U, res, argL),
2228ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown              mkAND1(
2229ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                 binop(Iop_CmpEQ64, oldca, mkU64(1)),
2230ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                 binop(Iop_CmpEQ64, res, argL)
2231ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                 )
2232ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown              );
2233ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      xer_ca
2234ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         = unop(Iop_1Uto32, xer_ca);
2235ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      break;
2236ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2237ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   case /* 8 */ PPCG_FLAG_OP_SUBFE:
2238ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* res <u argR || (old_ca==1 && res==argR) */
2239ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      xer_ca
2240ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         = mkOR1(
2241ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown              binop(Iop_CmpLT64U, res, argR),
2242ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown              mkAND1(
2243ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                 binop(Iop_CmpEQ64, oldca, mkU64(1)),
2244ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                 binop(Iop_CmpEQ64, res, argR)
2245ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown              )
2246ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown           );
2247ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      xer_ca
2248ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         = unop(Iop_1Uto32, xer_ca);
2249ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      break;
2250ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2251ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   case /* 7 */ PPCG_FLAG_OP_SUBFC:
2252ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   case /* 9 */ PPCG_FLAG_OP_SUBFI:
2253ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* res <=u argR */
2254ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      xer_ca
2255ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         = unop(Iop_1Uto32, binop(Iop_CmpLE64U, res, argR));
2256ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      break;
2257ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2258ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2259ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   case /* 10 */ PPCG_FLAG_OP_SRAW:
2260ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* The shift amount is guaranteed to be in 0 .. 31 inclusive.
2261ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         If it is <= 31, behave like SRAWI; else XER.CA is the sign
2262ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         bit of argL. */
2263ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         /* This term valid for shift amount < 31 only */
2264ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2265ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      xer_ca
2266ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         = binop(
2267ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown              Iop_And64,
2268ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown              binop(Iop_Sar64, argL, mkU8(31)),
2269ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown              binop( Iop_And64,
2270ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                     argL,
2271ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                     binop( Iop_Sub64,
2272ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                            binop(Iop_Shl64, mkU64(1),
2273ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                             unop(Iop_64to8,argR)),
2274ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                            mkU64(1) )
2275ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown              )
2276ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown           );
2277ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      xer_ca
2278ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         = IRExpr_Mux0X(
2279ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown              /* shift amt > 31 ? */
2280ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown              unop(Iop_1Uto8, binop(Iop_CmpLT64U, mkU64(31), argR)),
2281ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown              /* no -- be like srawi */
2282ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown              unop(Iop_1Uto32, binop(Iop_CmpNE64, xer_ca, mkU64(0))),
2283ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown              /* yes -- get sign bit of argL */
2284ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown              unop(Iop_64to32, binop(Iop_Shr64, argL, mkU8(63)))
2285ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown           );
2286ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      break;
2287ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2288ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   case /* 11 */ PPCG_FLAG_OP_SRAWI:
2289ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* xer_ca is 1 iff src was negative and bits_shifted_out != 0.
2290ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         Since the shift amount is known to be in the range 0 .. 31
2291ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         inclusive the following seems viable:
2292ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         xer.ca == 1 iff the following is nonzero:
2293ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         (argL >>s 31)           -- either all 0s or all 1s
2294ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         & (argL & (1<<argR)-1)  -- the stuff shifted out */
2295ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2296ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      xer_ca
2297ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         = binop(
2298ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown              Iop_And64,
2299ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown              binop(Iop_Sar64, argL, mkU8(31)),
2300ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown              binop( Iop_And64,
2301ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                     argL,
2302ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                     binop( Iop_Sub64,
2303ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                            binop(Iop_Shl64, mkU64(1),
2304ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                             unop(Iop_64to8,argR)),
2305ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                            mkU64(1) )
2306ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown              )
2307ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown           );
2308ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      xer_ca
2309ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         = unop(Iop_1Uto32, binop(Iop_CmpNE64, xer_ca, mkU64(0)));
2310ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      break;
2311ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2312ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2313ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   case /* 12 */ PPCG_FLAG_OP_SRAD:
2314ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* The shift amount is guaranteed to be in 0 .. 63 inclusive.
2315ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         If it is <= 63, behave like SRADI; else XER.CA is the sign
2316ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         bit of argL. */
2317ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         /* This term valid for shift amount < 63 only */
2318ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2319ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      xer_ca
2320ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         = binop(
2321ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown              Iop_And64,
2322ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown              binop(Iop_Sar64, argL, mkU8(63)),
2323ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown              binop( Iop_And64,
2324ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                     argL,
2325ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                     binop( Iop_Sub64,
2326ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                            binop(Iop_Shl64, mkU64(1),
2327ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                             unop(Iop_64to8,argR)),
2328ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                            mkU64(1) )
2329ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown              )
2330ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown           );
2331ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      xer_ca
2332ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         = IRExpr_Mux0X(
2333ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown              /* shift amt > 63 ? */
2334ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown              unop(Iop_1Uto8, binop(Iop_CmpLT64U, mkU64(63), argR)),
2335ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown              /* no -- be like sradi */
2336ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown              unop(Iop_1Uto32, binop(Iop_CmpNE64, xer_ca, mkU64(0))),
2337ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown              /* yes -- get sign bit of argL */
2338ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown              unop(Iop_64to32, binop(Iop_Shr64, argL, mkU8(63)))
2339ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown           );
2340ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      break;
2341ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2342ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2343ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   case /* 13 */ PPCG_FLAG_OP_SRADI:
2344ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* xer_ca is 1 iff src was negative and bits_shifted_out != 0.
2345ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         Since the shift amount is known to be in the range 0 .. 63
2346ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         inclusive, the following seems viable:
2347ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         xer.ca == 1 iff the following is nonzero:
2348ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         (argL >>s 63)           -- either all 0s or all 1s
2349ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         & (argL & (1<<argR)-1)  -- the stuff shifted out */
2350ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2351ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      xer_ca
2352ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         = binop(
2353ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown              Iop_And64,
2354ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown              binop(Iop_Sar64, argL, mkU8(63)),
2355ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown              binop( Iop_And64,
2356ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                     argL,
2357ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                     binop( Iop_Sub64,
2358ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                            binop(Iop_Shl64, mkU64(1),
2359ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                             unop(Iop_64to8,argR)),
2360ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                            mkU64(1) )
2361ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown              )
2362ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown           );
2363ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      xer_ca
2364ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         = unop(Iop_1Uto32, binop(Iop_CmpNE64, xer_ca, mkU64(0)));
2365ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      break;
2366ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2367ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   default:
2368ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      vex_printf("set_XER_CA: op = %u\n", op);
2369ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      vpanic("set_XER_CA(ppc64)");
2370ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
2371ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2372ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* xer_ca MUST denote either 0 or 1, no other value allowed */
2373ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   putXER_CA( unop(Iop_32to8, xer_ca) );
2374ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
2375ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2376ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic void set_XER_CA ( IRType ty, UInt op, IRExpr* res,
2377ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                         IRExpr* argL, IRExpr* argR, IRExpr* oldca )
2378ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
2379ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (ty == Ity_I32)
2380ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      set_XER_CA_32( op, res, argL, argR, oldca );
2381ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   else
2382ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      set_XER_CA_64( op, res, argL, argR, oldca );
2383ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
2384ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2385ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2386ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2387ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*------------------------------------------------------------*/
2388ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*--- Read/write to guest-state                           --- */
2389ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*------------------------------------------------------------*/
2390ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2391ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic IRExpr* /* :: Ity_I32/64 */ getGST ( PPC_GST reg )
2392ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
2393ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   IRType ty = mode64 ? Ity_I64 : Ity_I32;
2394ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   switch (reg) {
2395ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   case PPC_GST_SPRG3_RO:
2396ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      return IRExpr_Get( OFFB_SPRG3_RO, ty );
2397ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2398ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   case PPC_GST_CIA:
2399ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      return IRExpr_Get( OFFB_CIA, ty );
2400ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2401ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   case PPC_GST_LR:
2402ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      return IRExpr_Get( OFFB_LR, ty );
2403ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2404ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   case PPC_GST_CTR:
2405ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      return IRExpr_Get( OFFB_CTR, ty );
2406ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2407ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   case PPC_GST_VRSAVE:
2408ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      return IRExpr_Get( OFFB_VRSAVE, Ity_I32 );
2409ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2410ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   case PPC_GST_VSCR:
2411ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      return binop(Iop_And32, IRExpr_Get( OFFB_VSCR,Ity_I32 ),
2412ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                              mkU32(MASK_VSCR_VALID));
2413ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2414ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   case PPC_GST_CR: {
2415ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* Synthesise the entire CR into a single word.  Expensive. */
2416ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#     define FIELD(_n)                                               \
2417ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         binop(Iop_Shl32,                                            \
2418ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               unop(Iop_8Uto32,                                      \
2419ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                    binop(Iop_Or8,                                   \
2420ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                          binop(Iop_And8, getCR321(_n), mkU8(7<<1)), \
2421ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                          binop(Iop_And8, getCR0(_n), mkU8(1))       \
2422ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                    )                                                \
2423ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               ),                                                    \
2424ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               mkU8(4 * (7-(_n)))                                    \
2425ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         )
2426ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      return binop(Iop_Or32,
2427ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                   binop(Iop_Or32,
2428ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                         binop(Iop_Or32, FIELD(0), FIELD(1)),
2429ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                         binop(Iop_Or32, FIELD(2), FIELD(3))
2430ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                         ),
2431ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                   binop(Iop_Or32,
2432ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                         binop(Iop_Or32, FIELD(4), FIELD(5)),
2433ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                         binop(Iop_Or32, FIELD(6), FIELD(7))
2434ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                         )
2435ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                   );
2436ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#     undef FIELD
2437ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
2438ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2439ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   case PPC_GST_XER:
2440ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      return binop(Iop_Or32,
2441ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                   binop(Iop_Or32,
2442ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                         binop( Iop_Shl32, getXER_SO32(), mkU8(31)),
2443ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                         binop( Iop_Shl32, getXER_OV32(), mkU8(30))),
2444ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                   binop(Iop_Or32,
2445ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                         binop( Iop_Shl32, getXER_CA32(), mkU8(29)),
2446ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                         getXER_BC32()));
2447ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2448ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   default:
2449ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      vex_printf("getGST(ppc): reg = %u", reg);
2450ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      vpanic("getGST(ppc)");
2451ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
2452ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
2453ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2454ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* Get a masked word from the given reg */
2455ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic IRExpr* /* ::Ity_I32 */ getGST_masked ( PPC_GST reg, UInt mask )
2456ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
2457ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   IRTemp val = newTemp(Ity_I32);
2458ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   vassert( reg < PPC_GST_MAX );
2459ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2460ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   switch (reg) {
2461ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2462ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   case PPC_GST_FPSCR: {
2463ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* Vex-generated code expects the FPSCR to be set as follows:
2464ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         all exceptions masked, round-to-nearest.
2465ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         This corresponds to a FPSCR value of 0x0. */
2466ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2467ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* We're only keeping track of the rounding mode,
2468ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         so if the mask isn't asking for this, just return 0x0 */
2469ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (mask & (MASK_FPSCR_RN|MASK_FPSCR_FPRF)) {
2470ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         assign( val, IRExpr_Get( OFFB_FPROUND, Ity_I32 ) );
2471ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      } else {
2472ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         assign( val, mkU32(0x0) );
2473ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
2474ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      break;
2475ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
2476ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2477ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   default:
2478ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      vex_printf("getGST_masked(ppc): reg = %u", reg);
2479ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      vpanic("getGST_masked(ppc)");
2480ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
2481ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2482ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (mask != 0xFFFFFFFF) {
2483ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      return binop(Iop_And32, mkexpr(val), mkU32(mask));
2484ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   } else {
2485ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      return mkexpr(val);
2486ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
2487ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
2488ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2489ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* Fetch the specified REG[FLD] nibble (as per IBM/hardware notation)
2490ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   and return it at the bottom of an I32; the top 27 bits are
2491ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   guaranteed to be zero. */
2492ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic IRExpr* /* ::Ity_I32 */ getGST_field ( PPC_GST reg, UInt fld )
2493ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
2494ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   UInt shft, mask;
2495ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2496ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   vassert( fld < 8 );
2497ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   vassert( reg < PPC_GST_MAX );
2498ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2499ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   shft = 4*(7-fld);
2500ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   mask = 0xF<<shft;
2501ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2502ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   switch (reg) {
2503ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   case PPC_GST_XER:
2504ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      vassert(fld ==7);
2505ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      return binop(Iop_Or32,
2506ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                   binop(Iop_Or32,
2507ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                         binop(Iop_Shl32, getXER_SO32(), mkU8(3)),
2508ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                         binop(Iop_Shl32, getXER_OV32(), mkU8(2))),
2509ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                   binop(      Iop_Shl32, getXER_CA32(), mkU8(1)));
2510ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      break;
2511ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2512ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   default:
2513ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (shft == 0)
2514ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return getGST_masked( reg, mask );
2515ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      else
2516ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return binop(Iop_Shr32,
2517ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                      getGST_masked( reg, mask ),
2518ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                      mkU8(toUChar( shft )));
2519ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
2520ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
2521ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2522ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic void putGST ( PPC_GST reg, IRExpr* src )
2523ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
2524ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   IRType ty     = mode64 ? Ity_I64 : Ity_I32;
2525ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   IRType ty_src = typeOfIRExpr(irsb->tyenv,src );
2526ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   vassert( reg < PPC_GST_MAX );
2527ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   switch (reg) {
2528ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   case PPC_GST_IP_AT_SYSCALL:
2529ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      vassert( ty_src == ty );
2530ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      stmt( IRStmt_Put( OFFB_IP_AT_SYSCALL, src ) );
2531ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      break;
2532ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   case PPC_GST_CIA:
2533ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      vassert( ty_src == ty );
2534ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      stmt( IRStmt_Put( OFFB_CIA, src ) );
2535ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      break;
2536ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   case PPC_GST_LR:
2537ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      vassert( ty_src == ty );
2538ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      stmt( IRStmt_Put( OFFB_LR, src ) );
2539ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      break;
2540ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   case PPC_GST_CTR:
2541ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      vassert( ty_src == ty );
2542ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      stmt( IRStmt_Put( OFFB_CTR, src ) );
2543ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      break;
2544ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   case PPC_GST_VRSAVE:
2545ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      vassert( ty_src == Ity_I32 );
2546ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      stmt( IRStmt_Put( OFFB_VRSAVE,src));
2547ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      break;
2548ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   case PPC_GST_VSCR:
2549ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      vassert( ty_src == Ity_I32 );
2550ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      stmt( IRStmt_Put( OFFB_VSCR,
2551ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                        binop(Iop_And32, src,
2552ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                              mkU32(MASK_VSCR_VALID)) ) );
2553ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      break;
2554ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   case PPC_GST_XER:
2555ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      vassert( ty_src == Ity_I32 );
2556ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      putXER_SO( unop(Iop_32to8, binop(Iop_Shr32, src, mkU8(31))) );
2557ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      putXER_OV( unop(Iop_32to8, binop(Iop_Shr32, src, mkU8(30))) );
2558ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      putXER_CA( unop(Iop_32to8, binop(Iop_Shr32, src, mkU8(29))) );
2559ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      putXER_BC( unop(Iop_32to8, src) );
2560ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      break;
2561ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2562ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   case PPC_GST_EMWARN:
2563ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      vassert( ty_src == Ity_I32 );
2564ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      stmt( IRStmt_Put( OFFB_EMWARN,src) );
2565ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      break;
2566ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2567ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   case PPC_GST_TISTART:
2568ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      vassert( ty_src == ty );
2569ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      stmt( IRStmt_Put( OFFB_TISTART, src) );
2570ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      break;
2571ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2572ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   case PPC_GST_TILEN:
2573ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      vassert( ty_src == ty );
2574ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      stmt( IRStmt_Put( OFFB_TILEN, src) );
2575ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      break;
2576ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2577ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   default:
2578ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      vex_printf("putGST(ppc): reg = %u", reg);
2579ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      vpanic("putGST(ppc)");
2580ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
2581ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
2582ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2583ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* Write masked src to the given reg */
2584ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic void putGST_masked ( PPC_GST reg, IRExpr* src, UInt mask )
2585ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
2586ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   IRType ty = mode64 ? Ity_I64 : Ity_I32;
2587ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   vassert( reg < PPC_GST_MAX );
2588ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   vassert( typeOfIRExpr(irsb->tyenv,src ) == Ity_I32 );
2589ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2590ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   switch (reg) {
2591ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   case PPC_GST_FPSCR: {
2592ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* Allow writes to Rounding Mode */
2593ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (mask & (MASK_FPSCR_RN|MASK_FPSCR_FPRF)) {
2594ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         /* construct new fpround from new and old values as per mask:
2595ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            new fpround = (src & (3 & mask)) | (fpround & (3 & ~mask)) */
2596ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         stmt(
2597ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            IRStmt_Put(
2598ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               OFFB_FPROUND,
2599ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               binop(
2600ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  Iop_Or32,
2601ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  binop(Iop_And32, src, mkU32((MASK_FPSCR_RN|MASK_FPSCR_FPRF) & mask)),
2602ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  binop(
2603ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                     Iop_And32,
2604ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                     IRExpr_Get(OFFB_FPROUND,Ity_I32),
2605ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                     mkU32((MASK_FPSCR_RN|MASK_FPSCR_FPRF) & ~mask)
2606ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  )
2607ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               )
2608ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            )
2609ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         );
2610ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
2611ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2612ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* Give EmWarn for attempted writes to:
2613ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         - Exception Controls
2614ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         - Non-IEEE Mode
2615ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      */
2616ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (mask & 0xFC) {  // Exception Control, Non-IEE mode
2617ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         VexEmWarn ew = EmWarn_PPCexns;
2618ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2619ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         /* If any of the src::exception_control bits are actually set,
2620ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            side-exit to the next insn, reporting the warning,
2621ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            so that Valgrind's dispatcher sees the warning. */
2622ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         putGST( PPC_GST_EMWARN, mkU32(ew) );
2623ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         stmt(
2624ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            IRStmt_Exit(
2625ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               binop(Iop_CmpNE32, mkU32(ew), mkU32(EmWarn_NONE)),
2626ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               Ijk_EmWarn,
2627ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               mkSzConst( ty, nextInsnAddr()) ));
2628ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
2629ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2630ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* Ignore all other writes */
2631ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      break;
2632ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
2633ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2634ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   default:
2635ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      vex_printf("putGST_masked(ppc): reg = %u", reg);
2636ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      vpanic("putGST_masked(ppc)");
2637ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
2638ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
2639ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2640ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* Write the least significant nibble of src to the specified
2641ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   REG[FLD] (as per IBM/hardware notation). */
2642ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic void putGST_field ( PPC_GST reg, IRExpr* src, UInt fld )
2643ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
2644ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   UInt shft, mask;
2645ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2646ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   vassert( typeOfIRExpr(irsb->tyenv,src ) == Ity_I32 );
2647ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   vassert( fld < 8 );
2648ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   vassert( reg < PPC_GST_MAX );
2649ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2650ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   shft = 4*(7-fld);
2651ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   mask = 0xF<<shft;
2652ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2653ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   switch (reg) {
2654ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   case PPC_GST_CR:
2655ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      putCR0  (fld, binop(Iop_And8, mkU8(1   ), unop(Iop_32to8, src)));
2656ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      putCR321(fld, binop(Iop_And8, mkU8(7<<1), unop(Iop_32to8, src)));
2657ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      break;
2658ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2659ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   default:
2660ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (shft == 0) {
2661ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         putGST_masked( reg, src, mask );
2662ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      } else {
2663ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         putGST_masked( reg,
2664ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                        binop(Iop_Shl32, src, mkU8(toUChar(shft))),
2665ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                        mask );
2666ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
2667ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
2668ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
2669ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2670b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov/*------------------------------------------------------------*/
2671b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov/* Helpers for VSX instructions that do floating point
2672b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov * operations and need to determine if a src contains a
2673b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov * special FP value.
2674b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov *
2675b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov *------------------------------------------------------------*/
2676b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
2677b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov#define NONZERO_FRAC_MASK 0x000fffffffffffffULL
2678b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov#define FP_FRAC_PART(x) binop( Iop_And64, \
2679b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                               mkexpr( x ), \
2680b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                               mkU64( NONZERO_FRAC_MASK ) )
2681b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
2682b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov// Returns exponent part of a single precision floating point as I32
2683b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanovstatic IRExpr * fp_exp_part_sp(IRTemp src)
2684b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov{
2685b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   return binop( Iop_And32,
2686b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                 binop( Iop_Shr32, mkexpr( src ), mkU8( 23 ) ),
2687b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                 mkU32( 0xff ) );
2688b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov}
2689b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
2690b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov// Returns exponent part of floating point as I32
2691b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanovstatic IRExpr * fp_exp_part(IRTemp src, Bool sp)
2692b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov{
2693b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   IRExpr * exp;
2694b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   if (sp)
2695b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      return fp_exp_part_sp(src);
2696b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
2697b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   if (!mode64)
2698b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      exp = binop( Iop_And32, binop( Iop_Shr32, unop( Iop_64HIto32,
2699b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                                                      mkexpr( src ) ),
2700b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                                     mkU8( 20 ) ), mkU32( 0x7ff ) );
2701b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   else
2702b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      exp = unop( Iop_64to32,
2703b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                  binop( Iop_And64,
2704b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                         binop( Iop_Shr64, mkexpr( src ), mkU8( 52 ) ),
2705b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                         mkU64( 0x7ff ) ) );
2706b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   return exp;
2707b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov}
2708b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
2709b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanovstatic IRExpr * is_Inf_sp(IRTemp src)
2710b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov{
2711b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   IRTemp frac_part = newTemp(Ity_I32);
2712b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   IRExpr * Inf_exp;
2713b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
2714b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   assign( frac_part, binop( Iop_And32, mkexpr(src), mkU32(0x007fffff)) );
2715b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   Inf_exp = binop( Iop_CmpEQ32, fp_exp_part( src, True /*single precision*/ ), mkU32( 0xff ) );
2716b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   return mkAND1( Inf_exp, binop( Iop_CmpEQ32, mkexpr( frac_part ), mkU32( 0 ) ) );
2717b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov}
2718b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
2719ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2720b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov// Infinity: exp = 7ff and fraction is zero; s = 0/1
2721b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanovstatic IRExpr * is_Inf(IRTemp src, Bool sp)
2722b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov{
2723b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   IRExpr * Inf_exp, * hi32, * low32;
2724b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   IRTemp frac_part;
2725b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
2726b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   if (sp)
2727b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      return is_Inf_sp(src);
2728b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
2729b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   frac_part = newTemp(Ity_I64);
2730b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   assign( frac_part, FP_FRAC_PART(src) );
2731b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   Inf_exp = binop( Iop_CmpEQ32, fp_exp_part( src, False /*not single precision*/  ), mkU32( 0x7ff ) );
2732b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   hi32 = unop( Iop_64HIto32, mkexpr( frac_part ) );
2733b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   low32 = unop( Iop_64to32, mkexpr( frac_part ) );
2734b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   return mkAND1( Inf_exp, binop( Iop_CmpEQ32, binop( Iop_Or32, low32, hi32 ),
2735b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                                  mkU32( 0 ) ) );
2736b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov}
2737b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
2738b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanovstatic IRExpr * is_Zero_sp(IRTemp src)
2739b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov{
2740b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   IRTemp sign_less_part = newTemp(Ity_I32);
2741b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   assign( sign_less_part, binop( Iop_And32, mkexpr( src ), mkU32( SIGN_MASK32 ) ) );
2742b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   return binop( Iop_CmpEQ32, mkexpr( sign_less_part ), mkU32( 0 ) );
2743b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov}
2744b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
2745b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov// Zero: exp is zero and fraction is zero; s = 0/1
2746b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanovstatic IRExpr * is_Zero(IRTemp src, Bool sp)
2747b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov{
2748b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   IRExpr * hi32, * low32;
2749b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   IRTemp sign_less_part;
2750b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   if (sp)
2751b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      return is_Zero_sp(src);
2752b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
2753b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   sign_less_part = newTemp(Ity_I64);
2754b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
2755b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   assign( sign_less_part, binop( Iop_And64, mkexpr( src ), mkU64( SIGN_MASK ) ) );
2756b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   hi32 = unop( Iop_64HIto32, mkexpr( sign_less_part ) );
2757b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   low32 = unop( Iop_64to32, mkexpr( sign_less_part ) );
2758b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   return binop( Iop_CmpEQ32, binop( Iop_Or32, low32, hi32 ),
2759b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                              mkU32( 0 ) );
2760b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov}
2761b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
2762b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov/*  SNAN: s = 1/0; exp = 0x7ff; fraction is nonzero, with highest bit '1'
2763b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov *  QNAN: s = 1/0; exp = 0x7ff; fraction is nonzero, with highest bit '0'
2764b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov *  This function returns an IRExpr value of '1' for any type of NaN.
2765b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov */
2766b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanovstatic IRExpr * is_NaN(IRTemp src)
2767b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov{
2768b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   IRExpr * NaN_exp, * hi32, * low32;
2769b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   IRTemp frac_part = newTemp(Ity_I64);
2770b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
2771b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   assign( frac_part, FP_FRAC_PART(src) );
2772b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   hi32 = unop( Iop_64HIto32, mkexpr( frac_part ) );
2773b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   low32 = unop( Iop_64to32, mkexpr( frac_part ) );
2774b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   NaN_exp = binop( Iop_CmpEQ32, fp_exp_part( src, False /*not single precision*/ ),
2775b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                    mkU32( 0x7ff ) );
2776b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
2777b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   return mkAND1( NaN_exp, binop( Iop_CmpNE32, binop( Iop_Or32, low32, hi32 ),
2778b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                                               mkU32( 0 ) ) );
2779b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov}
2780b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
2781b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov/* This function returns an IRExpr value of '1' for any type of NaN.
2782b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov * The passed 'src' argument is assumed to be Ity_I32.
2783b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov */
2784b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanovstatic IRExpr * is_NaN_32(IRTemp src)
2785b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov{
2786b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov#define NONZERO_FRAC_MASK32 0x007fffffULL
2787b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov#define FP_FRAC_PART32(x) binop( Iop_And32, \
2788b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                                 mkexpr( x ), \
2789b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                                 mkU32( NONZERO_FRAC_MASK32 ) )
2790b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
2791b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   IRExpr * frac_part = FP_FRAC_PART32(src);
2792b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   IRExpr * exp_part = binop( Iop_And32,
2793b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                              binop( Iop_Shr32, mkexpr( src ), mkU8( 23 ) ),
2794b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                              mkU32( 0x0ff ) );
2795b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   IRExpr * NaN_exp = binop( Iop_CmpEQ32, exp_part, mkU32( 0xff ) );
2796b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
2797b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   return mkAND1( NaN_exp, binop( Iop_CmpNE32, frac_part, mkU32( 0 ) ) );
2798b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov}
2799b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
2800b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov/* This helper function performs the negation part of operations of the form:
2801b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov *    "Negate Multiply-<op>"
2802b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov *  where "<op>" is either "Add" or "Sub".
2803b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov *
2804b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov * This function takes one argument -- the floating point intermediate result (converted to
2805b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov * Ity_I64 via Iop_ReinterpF64asI64) that was obtained from the "Multip-<op>" part of
2806b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov * the operation described above.
2807b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov */
2808b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanovstatic IRTemp getNegatedResult(IRTemp intermediateResult)
2809b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov{
2810b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   ULong signbit_mask = 0x8000000000000000ULL;
2811b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   IRTemp signbit_32 = newTemp(Ity_I32);
2812b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   IRTemp resultantSignbit = newTemp(Ity_I1);
2813b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   IRTemp negatedResult = newTemp(Ity_I64);
2814b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   assign( signbit_32, binop( Iop_Shr32,
2815b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                          unop( Iop_64HIto32,
2816b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                                 binop( Iop_And64, mkexpr( intermediateResult ),
2817b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                                        mkU64( signbit_mask ) ) ),
2818b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                                 mkU8( 31 ) ) );
2819b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   /* We negate the signbit if and only if the intermediate result from the
2820b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov    * multiply-<op> was NOT a NaN.  This is an XNOR predicate.
2821b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov    */
2822b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   assign( resultantSignbit,
2823b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov        unop( Iop_Not1,
2824b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov              binop( Iop_CmpEQ32,
2825b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                     binop( Iop_Xor32,
2826b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                            mkexpr( signbit_32 ),
2827b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                            unop( Iop_1Uto32, is_NaN( intermediateResult ) ) ),
2828b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                     mkU32( 1 ) ) ) );
2829b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
2830b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   assign( negatedResult,
2831b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov        binop( Iop_Or64,
2832b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov               binop( Iop_And64,
2833b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                      mkexpr( intermediateResult ),
2834b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                      mkU64( ~signbit_mask ) ),
2835b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov               binop( Iop_32HLto64,
2836b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                      binop( Iop_Shl32,
2837b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                             unop( Iop_1Uto32, mkexpr( resultantSignbit ) ),
2838b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                             mkU8( 31 ) ),
2839b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                      mkU32( 0 ) ) ) );
2840b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
2841b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   return negatedResult;
2842b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov}
2843b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
2844b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov/* This helper function performs the negation part of operations of the form:
2845b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov *    "Negate Multiply-<op>"
2846b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov *  where "<op>" is either "Add" or "Sub".
2847b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov *
2848b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov * This function takes one argument -- the floating point intermediate result (converted to
2849b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov * Ity_I32 via Iop_ReinterpF32asI32) that was obtained from the "Multip-<op>" part of
2850b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov * the operation described above.
2851b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov */
2852b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanovstatic IRTemp getNegatedResult_32(IRTemp intermediateResult)
2853b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov{
2854b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   UInt signbit_mask = 0x80000000;
2855b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   IRTemp signbit_32 = newTemp(Ity_I32);
2856b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   IRTemp resultantSignbit = newTemp(Ity_I1);
2857b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   IRTemp negatedResult = newTemp(Ity_I32);
2858b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   assign( signbit_32, binop( Iop_Shr32,
2859b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                                 binop( Iop_And32, mkexpr( intermediateResult ),
2860b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                                        mkU32( signbit_mask ) ),
2861b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                                 mkU8( 31 ) ) );
2862b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   /* We negate the signbit if and only if the intermediate result from the
2863b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov    * multiply-<op> was NOT a NaN.  This is an XNOR predicate.
2864b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov    */
2865b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   assign( resultantSignbit,
2866b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov        unop( Iop_Not1,
2867b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov              binop( Iop_CmpEQ32,
2868b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                     binop( Iop_Xor32,
2869b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                            mkexpr( signbit_32 ),
2870b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                            unop( Iop_1Uto32, is_NaN_32( intermediateResult ) ) ),
2871b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                     mkU32( 1 ) ) ) );
2872b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
2873b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   assign( negatedResult,
2874b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov           binop( Iop_Or32,
2875b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                  binop( Iop_And32,
2876b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                         mkexpr( intermediateResult ),
2877b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                         mkU32( ~signbit_mask ) ),
2878b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                  binop( Iop_Shl32,
2879b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                         unop( Iop_1Uto32, mkexpr( resultantSignbit ) ),
2880b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                         mkU8( 31 ) ) ) );
2881b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
2882b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   return negatedResult;
2883b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov}
2884ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2885ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*------------------------------------------------------------*/
2886ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*--- Integer Instruction Translation                     --- */
2887ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*------------------------------------------------------------*/
2888ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2889ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*
2890ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  Integer Arithmetic Instructions
2891ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown*/
2892ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic Bool dis_int_arith ( UInt theInstr )
2893ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
2894ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* D-Form, XO-Form */
2895ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   UChar opc1    = ifieldOPC(theInstr);
2896ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   UChar rD_addr = ifieldRegDS(theInstr);
2897ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   UChar rA_addr = ifieldRegA(theInstr);
2898ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   UInt  uimm16  = ifieldUIMM16(theInstr);
2899ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   UChar rB_addr = ifieldRegB(theInstr);
2900ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   UChar flag_OE = ifieldBIT10(theInstr);
2901ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   UInt  opc2    = ifieldOPClo9(theInstr);
2902ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   UChar flag_rC = ifieldBIT0(theInstr);
2903ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2904ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   Long   simm16 = extend_s_16to64(uimm16);
2905ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   IRType ty     = mode64 ? Ity_I64 : Ity_I32;
2906ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   IRTemp rA     = newTemp(ty);
2907ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   IRTemp rB     = newTemp(ty);
2908ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   IRTemp rD     = newTemp(ty);
2909ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2910ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   Bool do_rc = False;
2911ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2912ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   assign( rA, getIReg(rA_addr) );
2913ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   assign( rB, getIReg(rB_addr) );         // XO-Form: rD, rA, rB
2914ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2915ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   switch (opc1) {
2916ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* D-Form */
2917ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   case 0x0C: // addic  (Add Immediate Carrying, PPC32 p351
2918ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      DIP("addic r%u,r%u,%d\n", rD_addr, rA_addr, (Int)simm16);
2919ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      assign( rD, binop( mkSzOp(ty, Iop_Add8), mkexpr(rA),
2920ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                         mkSzExtendS16(ty, uimm16) ) );
2921ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      set_XER_CA( ty, PPCG_FLAG_OP_ADD,
2922ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  mkexpr(rD), mkexpr(rA), mkSzExtendS16(ty, uimm16),
2923ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  mkSzImm(ty, 0)/*old xer.ca, which is ignored*/ );
2924ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      break;
2925ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2926ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   case 0x0D: // addic. (Add Immediate Carrying and Record, PPC32 p352)
2927ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      DIP("addic. r%u,r%u,%d\n", rD_addr, rA_addr, (Int)simm16);
2928ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      assign( rD, binop( mkSzOp(ty, Iop_Add8), mkexpr(rA),
2929ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                         mkSzExtendS16(ty, uimm16) ) );
2930ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      set_XER_CA( ty, PPCG_FLAG_OP_ADD,
2931ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  mkexpr(rD), mkexpr(rA), mkSzExtendS16(ty, uimm16),
2932ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  mkSzImm(ty, 0)/*old xer.ca, which is ignored*/ );
2933ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      do_rc = True;  // Always record to CR
2934ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      flag_rC = 1;
2935ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      break;
2936ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2937ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   case 0x0E: // addi   (Add Immediate, PPC32 p350)
2938ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      // li rD,val   == addi rD,0,val
2939ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      // la disp(rA) == addi rD,rA,disp
2940ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if ( rA_addr == 0 ) {
2941ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         DIP("li r%u,%d\n", rD_addr, (Int)simm16);
2942ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         assign( rD, mkSzExtendS16(ty, uimm16) );
2943ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      } else {
2944ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         DIP("addi r%u,r%u,%d\n", rD_addr, rA_addr, (Int)simm16);
2945ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         assign( rD, binop( mkSzOp(ty, Iop_Add8), mkexpr(rA),
2946ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                            mkSzExtendS16(ty, uimm16) ) );
2947ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
2948ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      break;
2949ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2950ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   case 0x0F: // addis  (Add Immediate Shifted, PPC32 p353)
2951ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      // lis rD,val == addis rD,0,val
2952ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if ( rA_addr == 0 ) {
2953ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         DIP("lis r%u,%d\n", rD_addr, (Int)simm16);
2954ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         assign( rD, mkSzExtendS32(ty, uimm16 << 16) );
2955ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      } else {
2956ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         DIP("addis r%u,r%u,0x%x\n", rD_addr, rA_addr, (Int)simm16);
2957ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         assign( rD, binop( mkSzOp(ty, Iop_Add8), mkexpr(rA),
2958ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                            mkSzExtendS32(ty, uimm16 << 16) ) );
2959ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
2960ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      break;
2961ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2962ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   case 0x07: // mulli    (Multiply Low Immediate, PPC32 p490)
2963ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      DIP("mulli r%u,r%u,%d\n", rD_addr, rA_addr, (Int)simm16);
2964ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (mode64)
2965ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         assign( rD, unop(Iop_128to64,
2966ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                          binop(Iop_MullS64, mkexpr(rA),
2967ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                mkSzExtendS16(ty, uimm16))) );
2968ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      else
2969ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         assign( rD, unop(Iop_64to32,
2970ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                          binop(Iop_MullS32, mkexpr(rA),
2971ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                mkSzExtendS16(ty, uimm16))) );
2972ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      break;
2973ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2974ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   case 0x08: // subfic   (Subtract from Immediate Carrying, PPC32 p540)
2975ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      DIP("subfic r%u,r%u,%d\n", rD_addr, rA_addr, (Int)simm16);
2976ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      // rD = simm16 - rA
2977ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      assign( rD, binop( mkSzOp(ty, Iop_Sub8),
2978ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                         mkSzExtendS16(ty, uimm16),
2979ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                         mkexpr(rA)) );
2980ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      set_XER_CA( ty, PPCG_FLAG_OP_SUBFI,
2981ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  mkexpr(rD), mkexpr(rA), mkSzExtendS16(ty, uimm16),
2982ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  mkSzImm(ty, 0)/*old xer.ca, which is ignored*/ );
2983ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      break;
2984ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2985ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* XO-Form */
2986ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   case 0x1F:
2987ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      do_rc = True;    // All below record to CR
2988ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2989ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      switch (opc2) {
2990ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case 0x10A: // add  (Add, PPC32 p347)
2991ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         DIP("add%s%s r%u,r%u,r%u\n",
2992ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown             flag_OE ? "o" : "", flag_rC ? ".":"",
2993ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown             rD_addr, rA_addr, rB_addr);
2994ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         assign( rD, binop( mkSzOp(ty, Iop_Add8),
2995ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                            mkexpr(rA), mkexpr(rB) ) );
2996ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         if (flag_OE) {
2997ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            set_XER_OV( ty, PPCG_FLAG_OP_ADD,
2998ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                        mkexpr(rD), mkexpr(rA), mkexpr(rB) );
2999ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         }
3000ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         break;
3001ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3002ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case 0x00A: // addc      (Add Carrying, PPC32 p348)
3003ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         DIP("addc%s%s r%u,r%u,r%u\n",
3004ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown             flag_OE ? "o" : "", flag_rC ? ".":"",
3005ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown             rD_addr, rA_addr, rB_addr);
3006ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         assign( rD, binop( mkSzOp(ty, Iop_Add8),
3007ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                            mkexpr(rA), mkexpr(rB)) );
3008ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         set_XER_CA( ty, PPCG_FLAG_OP_ADD,
3009ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                     mkexpr(rD), mkexpr(rA), mkexpr(rB),
3010ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                     mkSzImm(ty, 0)/*old xer.ca, which is ignored*/ );
3011ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         if (flag_OE) {
3012ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            set_XER_OV( ty, PPCG_FLAG_OP_ADD,
3013ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                        mkexpr(rD), mkexpr(rA), mkexpr(rB) );
3014ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         }
3015ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         break;
3016ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3017ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case 0x08A: { // adde      (Add Extended, PPC32 p349)
3018ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         IRTemp old_xer_ca = newTemp(ty);
3019ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         DIP("adde%s%s r%u,r%u,r%u\n",
3020ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown             flag_OE ? "o" : "", flag_rC ? ".":"",
3021ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown             rD_addr, rA_addr, rB_addr);
3022ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         // rD = rA + rB + XER[CA]
3023ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         assign( old_xer_ca, mkWidenFrom32(ty, getXER_CA32(), False) );
3024ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         assign( rD, binop( mkSzOp(ty, Iop_Add8), mkexpr(rA),
3025ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                            binop( mkSzOp(ty, Iop_Add8),
3026ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                   mkexpr(rB), mkexpr(old_xer_ca))) );
3027ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         set_XER_CA( ty, PPCG_FLAG_OP_ADDE,
3028ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                     mkexpr(rD), mkexpr(rA), mkexpr(rB),
3029ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                     mkexpr(old_xer_ca) );
3030ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         if (flag_OE) {
3031ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            set_XER_OV( ty, PPCG_FLAG_OP_ADDE,
3032ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                        mkexpr(rD), mkexpr(rA), mkexpr(rB) );
3033ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         }
3034ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         break;
3035ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
3036ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3037ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case 0x0EA: { // addme     (Add to Minus One Extended, PPC32 p354)
3038ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         IRTemp old_xer_ca = newTemp(ty);
3039ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         IRExpr *min_one;
3040ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         if (rB_addr != 0) {
3041ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            vex_printf("dis_int_arith(ppc)(addme,rB_addr)\n");
3042ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            return False;
3043ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         }
3044ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         DIP("addme%s%s r%u,r%u,r%u\n",
3045ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown             flag_OE ? "o" : "", flag_rC ? ".":"",
3046ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown             rD_addr, rA_addr, rB_addr);
3047ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         // rD = rA + (-1) + XER[CA]
3048ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         // => Just another form of adde
3049ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         assign( old_xer_ca, mkWidenFrom32(ty, getXER_CA32(), False) );
3050ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         min_one = mkSzImm(ty, (Long)-1);
3051ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         assign( rD, binop( mkSzOp(ty, Iop_Add8), mkexpr(rA),
3052ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                            binop( mkSzOp(ty, Iop_Add8),
3053ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                   min_one, mkexpr(old_xer_ca)) ));
3054ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         set_XER_CA( ty, PPCG_FLAG_OP_ADDE,
3055ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                     mkexpr(rD), mkexpr(rA), min_one,
3056ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                     mkexpr(old_xer_ca) );
3057ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         if (flag_OE) {
3058ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            set_XER_OV( ty, PPCG_FLAG_OP_ADDE,
3059ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                        mkexpr(rD), mkexpr(rA), min_one );
3060ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         }
3061ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         break;
3062ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
3063ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3064ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case 0x0CA: { // addze      (Add to Zero Extended, PPC32 p355)
3065ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         IRTemp old_xer_ca = newTemp(ty);
3066ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         if (rB_addr != 0) {
3067ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            vex_printf("dis_int_arith(ppc)(addze,rB_addr)\n");
3068ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            return False;
3069ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         }
3070ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         DIP("addze%s%s r%u,r%u,r%u\n",
3071ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown             flag_OE ? "o" : "", flag_rC ? ".":"",
3072ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown             rD_addr, rA_addr, rB_addr);
3073ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         // rD = rA + (0) + XER[CA]
3074ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         // => Just another form of adde
3075ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         assign( old_xer_ca, mkWidenFrom32(ty, getXER_CA32(), False) );
3076ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         assign( rD, binop( mkSzOp(ty, Iop_Add8),
3077ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                            mkexpr(rA), mkexpr(old_xer_ca)) );
3078ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         set_XER_CA( ty, PPCG_FLAG_OP_ADDE,
3079ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                     mkexpr(rD), mkexpr(rA), mkSzImm(ty, 0),
3080ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                     mkexpr(old_xer_ca) );
3081ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         if (flag_OE) {
3082ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            set_XER_OV( ty, PPCG_FLAG_OP_ADDE,
3083ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                        mkexpr(rD), mkexpr(rA), mkSzImm(ty, 0) );
3084ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         }
3085ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         break;
3086ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
3087ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3088ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case 0x1EB: // divw       (Divide Word, PPC32 p388)
3089ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         DIP("divw%s%s r%u,r%u,r%u\n",
3090ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown             flag_OE ? "o" : "", flag_rC ? ".":"",
3091ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown             rD_addr, rA_addr, rB_addr);
3092ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         if (mode64) {
3093ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            /* Note:
3094ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               XER settings are mode independent, and reflect the
3095ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               overflow of the low-order 32bit result
3096ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               CR0[LT|GT|EQ] are undefined if flag_rC && mode64
3097ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            */
3098ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            /* rD[hi32] are undefined: setting them to sign of lo32
3099ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                - makes set_CR0 happy */
3100ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            IRExpr* dividend = mk64lo32Sto64( mkexpr(rA) );
3101ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            IRExpr* divisor  = mk64lo32Sto64( mkexpr(rB) );
3102ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            assign( rD, mk64lo32Uto64( binop(Iop_DivS64, dividend,
3103ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                                         divisor) ) );
3104ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            if (flag_OE) {
3105ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               set_XER_OV( ty, PPCG_FLAG_OP_DIVW,
3106ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                           mkexpr(rD), dividend, divisor );
3107ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            }
3108ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         } else {
3109ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            assign( rD, binop(Iop_DivS32, mkexpr(rA), mkexpr(rB)) );
3110ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            if (flag_OE) {
3111ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               set_XER_OV( ty, PPCG_FLAG_OP_DIVW,
3112ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                           mkexpr(rD), mkexpr(rA), mkexpr(rB) );
3113ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            }
3114ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         }
3115ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         /* Note:
3116ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            if (0x8000_0000 / -1) or (x / 0)
3117ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            => rD=undef, if(flag_rC) CR7=undef, if(flag_OE) XER_OV=1
3118ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            => But _no_ exception raised. */
3119ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         break;
3120ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3121ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case 0x1CB: // divwu      (Divide Word Unsigned, PPC32 p389)
3122ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         DIP("divwu%s%s r%u,r%u,r%u\n",
3123ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown             flag_OE ? "o" : "", flag_rC ? ".":"",
3124ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown             rD_addr, rA_addr, rB_addr);
3125ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         if (mode64) {
3126ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            /* Note:
3127ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               XER settings are mode independent, and reflect the
3128ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               overflow of the low-order 32bit result
3129ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               CR0[LT|GT|EQ] are undefined if flag_rC && mode64
3130ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            */
3131ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            IRExpr* dividend = mk64lo32Uto64( mkexpr(rA) );
3132ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            IRExpr* divisor  = mk64lo32Uto64( mkexpr(rB) );
3133ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            assign( rD, mk64lo32Uto64( binop(Iop_DivU64, dividend,
3134ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                                         divisor) ) );
3135ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            if (flag_OE) {
3136ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               set_XER_OV( ty, PPCG_FLAG_OP_DIVWU,
3137ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                           mkexpr(rD), dividend, divisor );
3138ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            }
3139ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         } else {
3140ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            assign( rD, binop(Iop_DivU32, mkexpr(rA), mkexpr(rB)) );
3141ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            if (flag_OE) {
3142ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               set_XER_OV( ty, PPCG_FLAG_OP_DIVWU,
3143ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                           mkexpr(rD), mkexpr(rA), mkexpr(rB) );
3144ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            }
3145ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         }
3146ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         /* Note: ditto comment divw, for (x / 0) */
3147ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         break;
3148ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3149ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case 0x04B: // mulhw      (Multiply High Word, PPC32 p488)
3150ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         if (flag_OE != 0) {
3151ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            vex_printf("dis_int_arith(ppc)(mulhw,flag_OE)\n");
3152ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            return False;
3153ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         }
3154ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         DIP("mulhw%s r%u,r%u,r%u\n", flag_rC ? ".":"",
3155ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown             rD_addr, rA_addr, rB_addr);
3156ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         if (mode64) {
3157ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            /* rD[hi32] are undefined: setting them to sign of lo32
3158ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                - makes set_CR0 happy */
3159ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            assign( rD, binop(Iop_Sar64,
3160ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                           binop(Iop_Mul64,
3161ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                 mk64lo32Sto64( mkexpr(rA) ),
3162ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                 mk64lo32Sto64( mkexpr(rB) )),
3163ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                              mkU8(32)) );
3164ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         } else {
3165ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            assign( rD, unop(Iop_64HIto32,
3166ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                             binop(Iop_MullS32,
3167ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                   mkexpr(rA), mkexpr(rB))) );
3168ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         }
3169ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         break;
3170ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3171ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case 0x00B: // mulhwu    (Multiply High Word Unsigned, PPC32 p489)
3172ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         if (flag_OE != 0) {
3173ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            vex_printf("dis_int_arith(ppc)(mulhwu,flag_OE)\n");
3174ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            return False;
3175ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         }
3176ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         DIP("mulhwu%s r%u,r%u,r%u\n", flag_rC ? ".":"",
3177ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown             rD_addr, rA_addr, rB_addr);
3178ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         if (mode64) {
3179ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            /* rD[hi32] are undefined: setting them to sign of lo32
3180ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                - makes set_CR0 happy */
3181ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            assign( rD, binop(Iop_Sar64,
3182ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                           binop(Iop_Mul64,
3183ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                 mk64lo32Uto64( mkexpr(rA) ),
3184ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                 mk64lo32Uto64( mkexpr(rB) ) ),
3185ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                              mkU8(32)) );
3186ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         } else {
3187ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            assign( rD, unop(Iop_64HIto32,
3188ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                             binop(Iop_MullU32,
3189ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                   mkexpr(rA), mkexpr(rB))) );
3190ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         }
3191ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         break;
3192ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3193ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case 0x0EB: // mullw      (Multiply Low Word, PPC32 p491)
3194ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         DIP("mullw%s%s r%u,r%u,r%u\n",
3195ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown             flag_OE ? "o" : "", flag_rC ? ".":"",
3196ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown             rD_addr, rA_addr, rB_addr);
3197ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         if (mode64) {
3198ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            /* rD[hi32] are undefined: setting them to sign of lo32
3199ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                - set_XER_OV() and set_CR0() depend on this */
3200ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            IRExpr *a = unop(Iop_64to32, mkexpr(rA) );
3201ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            IRExpr *b = unop(Iop_64to32, mkexpr(rB) );
3202ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            assign( rD, binop(Iop_MullS32, a, b) );
3203ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            if (flag_OE) {
3204ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               set_XER_OV( ty, PPCG_FLAG_OP_MULLW,
3205ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                           mkexpr(rD),
3206ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                           unop(Iop_32Uto64, a), unop(Iop_32Uto64, b) );
3207ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            }
3208ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         } else {
3209ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            assign( rD, unop(Iop_64to32,
3210ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                             binop(Iop_MullU32,
3211ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                   mkexpr(rA), mkexpr(rB))) );
3212ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            if (flag_OE) {
3213ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               set_XER_OV( ty, PPCG_FLAG_OP_MULLW,
3214ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                           mkexpr(rD), mkexpr(rA), mkexpr(rB) );
3215ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            }
3216ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         }
3217ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         break;
3218ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3219ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case 0x068: // neg        (Negate, PPC32 p493)
3220ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         if (rB_addr != 0) {
3221ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            vex_printf("dis_int_arith(ppc)(neg,rB_addr)\n");
3222ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            return False;
3223ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         }
3224ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         DIP("neg%s%s r%u,r%u\n",
3225ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown             flag_OE ? "o" : "", flag_rC ? ".":"",
3226ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown             rD_addr, rA_addr);
3227ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         // rD = (~rA) + 1
3228ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         assign( rD, binop( mkSzOp(ty, Iop_Add8),
3229ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                            unop( mkSzOp(ty, Iop_Not8), mkexpr(rA) ),
3230ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                            mkSzImm(ty, 1)) );
3231ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         if (flag_OE) {
3232ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            set_XER_OV( ty, PPCG_FLAG_OP_NEG,
3233ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                        mkexpr(rD), mkexpr(rA), mkexpr(rB) );
3234ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         }
3235ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         break;
3236ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3237ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case 0x028: // subf       (Subtract From, PPC32 p537)
3238ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         DIP("subf%s%s r%u,r%u,r%u\n",
3239ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown             flag_OE ? "o" : "", flag_rC ? ".":"",
3240ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown             rD_addr, rA_addr, rB_addr);
3241ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         // rD = rB - rA
3242ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         assign( rD, binop( mkSzOp(ty, Iop_Sub8),
3243ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                            mkexpr(rB), mkexpr(rA)) );
3244ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         if (flag_OE) {
3245ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            set_XER_OV( ty, PPCG_FLAG_OP_SUBF,
3246ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                        mkexpr(rD), mkexpr(rA), mkexpr(rB) );
3247ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         }
3248ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         break;
3249ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3250ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case 0x008: // subfc      (Subtract from Carrying, PPC32 p538)
3251ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         DIP("subfc%s%s r%u,r%u,r%u\n",
3252ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown             flag_OE ? "o" : "", flag_rC ? ".":"",
3253ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown             rD_addr, rA_addr, rB_addr);
3254ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         // rD = rB - rA
3255ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         assign( rD, binop( mkSzOp(ty, Iop_Sub8),
3256ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                            mkexpr(rB), mkexpr(rA)) );
3257ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         set_XER_CA( ty, PPCG_FLAG_OP_SUBFC,
3258ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                     mkexpr(rD), mkexpr(rA), mkexpr(rB),
3259ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                     mkSzImm(ty, 0)/*old xer.ca, which is ignored*/ );
3260ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         if (flag_OE) {
3261ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            set_XER_OV( ty, PPCG_FLAG_OP_SUBFC,
3262ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                        mkexpr(rD), mkexpr(rA), mkexpr(rB) );
3263ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         }
3264ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         break;
3265ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3266ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case 0x088: {// subfe      (Subtract from Extended, PPC32 p539)
3267ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         IRTemp old_xer_ca = newTemp(ty);
3268ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         DIP("subfe%s%s r%u,r%u,r%u\n",
3269ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown             flag_OE ? "o" : "", flag_rC ? ".":"",
3270ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown             rD_addr, rA_addr, rB_addr);
3271ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         // rD = (log not)rA + rB + XER[CA]
3272ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         assign( old_xer_ca, mkWidenFrom32(ty, getXER_CA32(), False) );
3273ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         assign( rD, binop( mkSzOp(ty, Iop_Add8),
3274ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                            unop( mkSzOp(ty, Iop_Not8), mkexpr(rA)),
3275ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                            binop( mkSzOp(ty, Iop_Add8),
3276ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                   mkexpr(rB), mkexpr(old_xer_ca))) );
3277ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         set_XER_CA( ty, PPCG_FLAG_OP_SUBFE,
3278ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                     mkexpr(rD), mkexpr(rA), mkexpr(rB),
3279ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                     mkexpr(old_xer_ca) );
3280ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         if (flag_OE) {
3281ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            set_XER_OV( ty, PPCG_FLAG_OP_SUBFE,
3282ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                        mkexpr(rD), mkexpr(rA), mkexpr(rB) );
3283ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         }
3284ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         break;
3285ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
3286ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3287ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case 0x0E8: { // subfme    (Subtract from -1 Extended, PPC32 p541)
3288ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         IRTemp old_xer_ca = newTemp(ty);
3289ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         IRExpr *min_one;
3290ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         if (rB_addr != 0) {
3291ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            vex_printf("dis_int_arith(ppc)(subfme,rB_addr)\n");
3292ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            return False;
3293ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         }
3294ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         DIP("subfme%s%s r%u,r%u\n",
3295ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown             flag_OE ? "o" : "", flag_rC ? ".":"",
3296ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown             rD_addr, rA_addr);
3297ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         // rD = (log not)rA + (-1) + XER[CA]
3298ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         // => Just another form of subfe
3299ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         assign( old_xer_ca, mkWidenFrom32(ty, getXER_CA32(), False) );
3300ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         min_one = mkSzImm(ty, (Long)-1);
3301ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         assign( rD, binop( mkSzOp(ty, Iop_Add8),
3302ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                            unop( mkSzOp(ty, Iop_Not8), mkexpr(rA)),
3303ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                            binop( mkSzOp(ty, Iop_Add8),
3304ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                   min_one, mkexpr(old_xer_ca))) );
3305ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         set_XER_CA( ty, PPCG_FLAG_OP_SUBFE,
3306ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                     mkexpr(rD), mkexpr(rA), min_one,
3307ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                     mkexpr(old_xer_ca) );
3308ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         if (flag_OE) {
3309ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            set_XER_OV( ty, PPCG_FLAG_OP_SUBFE,
3310ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                        mkexpr(rD), mkexpr(rA), min_one );
3311ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         }
3312ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         break;
3313ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
3314ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3315ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case 0x0C8: { // subfze  (Subtract from Zero Extended, PPC32 p542)
3316ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         IRTemp old_xer_ca = newTemp(ty);
3317ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         if (rB_addr != 0) {
3318ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            vex_printf("dis_int_arith(ppc)(subfze,rB_addr)\n");
3319ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            return False;
3320ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         }
3321ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         DIP("subfze%s%s r%u,r%u\n",
3322ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown             flag_OE ? "o" : "", flag_rC ? ".":"",
3323ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown             rD_addr, rA_addr);
3324ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         // rD = (log not)rA + (0) + XER[CA]
3325ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         // => Just another form of subfe
3326ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         assign( old_xer_ca, mkWidenFrom32(ty, getXER_CA32(), False) );
3327ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         assign( rD, binop( mkSzOp(ty, Iop_Add8),
3328ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                           unop( mkSzOp(ty, Iop_Not8),
3329ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                 mkexpr(rA)), mkexpr(old_xer_ca)) );
3330ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         set_XER_CA( ty, PPCG_FLAG_OP_SUBFE,
3331ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                     mkexpr(rD), mkexpr(rA), mkSzImm(ty, 0),
3332ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                     mkexpr(old_xer_ca) );
3333ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         if (flag_OE) {
3334ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            set_XER_OV( ty, PPCG_FLAG_OP_SUBFE,
3335ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                        mkexpr(rD), mkexpr(rA), mkSzImm(ty, 0) );
3336ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         }
3337ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         break;
3338ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
3339ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3340ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3341ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* 64bit Arithmetic */
3342ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case 0x49:  // mulhd (Multiply High DWord, PPC64 p539)
3343ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         if (flag_OE != 0) {
3344ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            vex_printf("dis_int_arith(ppc)(mulhd,flagOE)\n");
3345ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            return False;
3346ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         }
3347ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         DIP("mulhd%s r%u,r%u,r%u\n", flag_rC ? ".":"",
3348ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown             rD_addr, rA_addr, rB_addr);
3349ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         assign( rD, unop(Iop_128HIto64,
3350ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                          binop(Iop_MullS64,
3351ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                mkexpr(rA), mkexpr(rB))) );
3352ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3353ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         break;
3354ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3355ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case 0x9:   // mulhdu  (Multiply High DWord Unsigned, PPC64 p540)
3356ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         if (flag_OE != 0) {
3357ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            vex_printf("dis_int_arith(ppc)(mulhdu,flagOE)\n");
3358ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            return False;
3359ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         }
3360ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         DIP("mulhdu%s r%u,r%u,r%u\n", flag_rC ? ".":"",
3361ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown             rD_addr, rA_addr, rB_addr);
3362ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         assign( rD, unop(Iop_128HIto64,
3363ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                          binop(Iop_MullU64,
3364ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                mkexpr(rA), mkexpr(rB))) );
3365ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         break;
3366ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3367ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case 0xE9:  // mulld (Multiply Low DWord, PPC64 p543)
3368ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         DIP("mulld%s%s r%u,r%u,r%u\n",
3369ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown             flag_OE ? "o" : "", flag_rC ? ".":"",
3370ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown             rD_addr, rA_addr, rB_addr);
3371ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         assign( rD, binop(Iop_Mul64, mkexpr(rA), mkexpr(rB)) );
3372ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         if (flag_OE) {
3373ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            set_XER_OV( ty, PPCG_FLAG_OP_MULLW,
3374ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                        mkexpr(rD), mkexpr(rA), mkexpr(rB) );
3375ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         }
3376ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         break;
3377ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3378ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case 0x1E9: // divd (Divide DWord, PPC64 p419)
3379ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         DIP("divd%s%s r%u,r%u,r%u\n",
3380ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown             flag_OE ? "o" : "", flag_rC ? ".":"",
3381ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown             rD_addr, rA_addr, rB_addr);
3382ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         assign( rD, binop(Iop_DivS64, mkexpr(rA), mkexpr(rB)) );
3383ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         if (flag_OE) {
3384ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            set_XER_OV( ty, PPCG_FLAG_OP_DIVW,
3385ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                        mkexpr(rD), mkexpr(rA), mkexpr(rB) );
3386ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         }
3387ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         break;
3388ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         /* Note:
3389ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            if (0x8000_0000_0000_0000 / -1) or (x / 0)
3390ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            => rD=undef, if(flag_rC) CR7=undef, if(flag_OE) XER_OV=1
3391ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            => But _no_ exception raised. */
3392ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3393ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case 0x1C9: // divdu (Divide DWord Unsigned, PPC64 p420)
3394ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         DIP("divdu%s%s r%u,r%u,r%u\n",
3395ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown             flag_OE ? "o" : "", flag_rC ? ".":"",
3396ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown             rD_addr, rA_addr, rB_addr);
3397ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         assign( rD, binop(Iop_DivU64, mkexpr(rA), mkexpr(rB)) );
3398ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         if (flag_OE) {
3399ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            set_XER_OV( ty, PPCG_FLAG_OP_DIVWU,
3400ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                        mkexpr(rD), mkexpr(rA), mkexpr(rB) );
3401ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         }
3402ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         break;
3403ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         /* Note: ditto comment divd, for (x / 0) */
3404ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3405b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      case 0x18B: // divweu (Divide Word Extended Unsigned)
3406b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      {
3407b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov        /*
3408b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         *  If (RA) >= (RB), or if an attempt is made to perform the division
3409b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         *         <anything> / 0
3410b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         * then the contents of register RD are undefined as are (if Rc=1) the contents of
3411b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         * the LT, GT, and EQ bits of CR Field 0. In these cases, if OE=1 then OV is set
3412b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         * to 1.
3413b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         */
3414b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         IRTemp res = newTemp(Ity_I32);
3415b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         IRExpr * dividend, * divisor;
3416b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         DIP("divweu%s%s r%u,r%u,r%u\n",
3417b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov             flag_OE ? "o" : "", flag_rC ? ".":"",
3418b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                                         rD_addr, rA_addr, rB_addr);
3419b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         if (mode64) {
3420b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov            dividend = unop( Iop_64to32, mkexpr( rA ) );
3421b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov            divisor = unop( Iop_64to32, mkexpr( rB ) );
3422b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov            assign( res, binop( Iop_DivU32E, dividend, divisor ) );
3423b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov            assign( rD, binop( Iop_32HLto64, mkU32( 0 ), mkexpr( res ) ) );
3424b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         } else {
3425b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov            dividend = mkexpr( rA );
3426b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov            divisor =  mkexpr( rB );
3427b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov            assign( res, binop( Iop_DivU32E, dividend, divisor ) );
3428b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov            assign( rD, mkexpr( res) );
3429b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         }
3430b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
3431b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         if (flag_OE) {
3432b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov            set_XER_OV_32( PPCG_FLAG_OP_DIVWEU,
3433b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                           mkexpr(res), dividend, divisor );
3434b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         }
3435b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         break;
3436b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      }
3437b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
3438b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      case 0x1AB: // divwe (Divide Word Extended)
3439b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      {
3440b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         /*
3441b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov          * If the quotient cannot be represented in 32 bits, or if an
3442b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov          * attempt is made to perform the division
3443b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov          *      <anything> / 0
3444b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov          * then the contents of register RD are undefined as are (if
3445b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov          * Rc=1) the contents of the LT, GT, and EQ bits of CR
3446b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov          * Field 0. In these cases, if OE=1 then OV is set to 1.
3447b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov          */
3448b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
3449b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         IRTemp res = newTemp(Ity_I32);
3450b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         IRExpr * dividend, * divisor;
3451b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         DIP("divwe%s%s r%u,r%u,r%u\n",
3452b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov             flag_OE ? "o" : "", flag_rC ? ".":"",
3453b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                                         rD_addr, rA_addr, rB_addr);
3454b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         if (mode64) {
3455b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov            dividend = unop( Iop_64to32, mkexpr( rA ) );
3456b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov            divisor = unop( Iop_64to32, mkexpr( rB ) );
3457b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov            assign( res, binop( Iop_DivS32E, dividend, divisor ) );
3458b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov            assign( rD, binop( Iop_32HLto64, mkU32( 0 ), mkexpr( res ) ) );
3459b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         } else {
3460b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov            dividend = mkexpr( rA );
3461b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov            divisor =  mkexpr( rB );
3462b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov            assign( res, binop( Iop_DivS32E, dividend, divisor ) );
3463b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov            assign( rD, mkexpr( res) );
3464b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         }
3465b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
3466b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         if (flag_OE) {
3467b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov            set_XER_OV_32( PPCG_FLAG_OP_DIVWE,
3468b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                           mkexpr(res), dividend, divisor );
3469b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         }
3470b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         break;
3471b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      }
3472b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
3473b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
3474b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      case 0x1A9: // divde (Divide Doubleword Extended)
3475b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov        /*
3476b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         * If the quotient cannot be represented in 64 bits, or if an
3477b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         * attempt is made to perform the division
3478b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         *      <anything> / 0
3479b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         * then the contents of register RD are undefined as are (if
3480b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         * Rc=1) the contents of the LT, GT, and EQ bits of CR
3481b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         * Field 0. In these cases, if OE=1 then OV is set to 1.
3482b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         */
3483b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         DIP("divde%s%s r%u,r%u,r%u\n",
3484b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov             flag_OE ? "o" : "", flag_rC ? ".":"",
3485b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov             rD_addr, rA_addr, rB_addr);
3486b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         assign( rD, binop(Iop_DivS64E, mkexpr(rA), mkexpr(rB)) );
3487b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         if (flag_OE) {
3488b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov            set_XER_OV_64( PPCG_FLAG_OP_DIVDE, mkexpr( rD ),
3489b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                           mkexpr( rA ), mkexpr( rB ) );
3490b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         }
3491b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         break;
3492b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
3493b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      case 0x189: //  divdeuo (Divide Doubleword Extended Unsigned)
3494b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov        // Same CR and OV rules as given for divweu above
3495b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov        DIP("divdeu%s%s r%u,r%u,r%u\n",
3496b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov            flag_OE ? "o" : "", flag_rC ? ".":"",
3497b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov            rD_addr, rA_addr, rB_addr);
3498b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov        assign( rD, binop(Iop_DivU64E, mkexpr(rA), mkexpr(rB)) );
3499b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov        if (flag_OE) {
3500b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov           set_XER_OV_64( PPCG_FLAG_OP_DIVDEU, mkexpr( rD ),
3501b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                          mkexpr( rA ), mkexpr( rB ) );
3502b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov        }
3503b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov        break;
3504b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
3505ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      default:
3506ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         vex_printf("dis_int_arith(ppc)(opc2)\n");
3507ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return False;
3508ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
3509ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      break;
3510ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3511ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   default:
3512ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      vex_printf("dis_int_arith(ppc)(opc1)\n");
3513ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      return False;
3514ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
3515ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3516ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   putIReg( rD_addr, mkexpr(rD) );
3517ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3518ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (do_rc && flag_rC) {
3519ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      set_CR0( mkexpr(rD) );
3520ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
3521ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   return True;
3522ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
3523ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3524ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3525ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3526ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*
3527ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  Integer Compare Instructions
3528ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown*/
3529ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic Bool dis_int_cmp ( UInt theInstr )
3530ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
3531ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* D-Form, X-Form */
3532ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   UChar opc1    = ifieldOPC(theInstr);
3533ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   UChar crfD    = toUChar( IFIELD( theInstr, 23, 3 ) );
3534ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   UChar b22     = toUChar( IFIELD( theInstr, 22, 1 ) );
3535ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   UChar flag_L  = toUChar( IFIELD( theInstr, 21, 1 ) );
3536ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   UChar rA_addr = ifieldRegA(theInstr);
3537ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   UInt  uimm16  = ifieldUIMM16(theInstr);
3538ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   UChar rB_addr = ifieldRegB(theInstr);
3539ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   UInt  opc2    = ifieldOPClo10(theInstr);
3540ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   UChar b0      = ifieldBIT0(theInstr);
3541ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3542ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   IRType ty = mode64 ? Ity_I64 : Ity_I32;
3543ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   IRExpr *a = getIReg(rA_addr);
3544ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   IRExpr *b;
3545ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3546ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (!mode64 && flag_L==1) {  // L==1 invalid for 32 bit.
3547ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      vex_printf("dis_int_cmp(ppc)(flag_L)\n");
3548ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      return False;
3549ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
3550ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3551ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (b22 != 0) {
3552ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      vex_printf("dis_int_cmp(ppc)(b22)\n");
3553ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      return False;
3554ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
3555ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3556ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   switch (opc1) {
3557ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   case 0x0B: // cmpi (Compare Immediate, PPC32 p368)
3558ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      DIP("cmpi cr%u,%u,r%u,%d\n", crfD, flag_L, rA_addr,
3559ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown          (Int)extend_s_16to32(uimm16));
3560ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      b = mkSzExtendS16( ty, uimm16 );
3561ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (flag_L == 1) {
3562ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         putCR321(crfD, unop(Iop_64to8, binop(Iop_CmpORD64S, a, b)));
3563ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      } else {
3564ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         a = mkNarrowTo32( ty, a );
3565ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         b = mkNarrowTo32( ty, b );
3566ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         putCR321(crfD, unop(Iop_32to8, binop(Iop_CmpORD32S, a, b)));
3567ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
3568ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      putCR0( crfD, getXER_SO() );
3569ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      break;
3570ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3571ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   case 0x0A: // cmpli (Compare Logical Immediate, PPC32 p370)
3572ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      DIP("cmpli cr%u,%u,r%u,0x%x\n", crfD, flag_L, rA_addr, uimm16);
3573ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      b = mkSzImm( ty, uimm16 );
3574ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (flag_L == 1) {
3575ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         putCR321(crfD, unop(Iop_64to8, binop(Iop_CmpORD64U, a, b)));
3576ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      } else {
3577ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         a = mkNarrowTo32( ty, a );
3578ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         b = mkNarrowTo32( ty, b );
3579ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         putCR321(crfD, unop(Iop_32to8, binop(Iop_CmpORD32U, a, b)));
3580ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
3581ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      putCR0( crfD, getXER_SO() );
3582ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      break;
3583ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3584ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* X Form */
3585ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   case 0x1F:
3586ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (b0 != 0) {
3587ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         vex_printf("dis_int_cmp(ppc)(0x1F,b0)\n");
3588ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return False;
3589ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
3590ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      b = getIReg(rB_addr);
3591ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3592ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      switch (opc2) {
3593ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case 0x000: // cmp (Compare, PPC32 p367)
3594ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         DIP("cmp cr%u,%u,r%u,r%u\n", crfD, flag_L, rA_addr, rB_addr);
3595ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         /* Comparing a reg with itself produces a result which
3596ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            doesn't depend on the contents of the reg.  Therefore
3597ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            remove the false dependency, which has been known to cause
3598ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            memcheck to produce false errors. */
3599ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         if (rA_addr == rB_addr)
3600ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            a = b = typeOfIRExpr(irsb->tyenv,a) == Ity_I64
3601ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                    ? mkU64(0)  : mkU32(0);
3602ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         if (flag_L == 1) {
3603ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            putCR321(crfD, unop(Iop_64to8, binop(Iop_CmpORD64S, a, b)));
3604ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         } else {
3605ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            a = mkNarrowTo32( ty, a );
3606ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            b = mkNarrowTo32( ty, b );
3607ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            putCR321(crfD, unop(Iop_32to8,binop(Iop_CmpORD32S, a, b)));
3608ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         }
3609ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         putCR0( crfD, getXER_SO() );
3610ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         break;
3611ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3612ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case 0x020: // cmpl (Compare Logical, PPC32 p369)
3613ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         DIP("cmpl cr%u,%u,r%u,r%u\n", crfD, flag_L, rA_addr, rB_addr);
3614ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         /* Comparing a reg with itself produces a result which
3615ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            doesn't depend on the contents of the reg.  Therefore
3616ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            remove the false dependency, which has been known to cause
3617ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            memcheck to produce false errors. */
3618ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         if (rA_addr == rB_addr)
3619ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            a = b = typeOfIRExpr(irsb->tyenv,a) == Ity_I64
3620ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                    ? mkU64(0)  : mkU32(0);
3621ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         if (flag_L == 1) {
3622ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            putCR321(crfD, unop(Iop_64to8, binop(Iop_CmpORD64U, a, b)));
3623ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         } else {
3624ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            a = mkNarrowTo32( ty, a );
3625ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            b = mkNarrowTo32( ty, b );
3626ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            putCR321(crfD, unop(Iop_32to8, binop(Iop_CmpORD32U, a, b)));
3627ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         }
3628ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         putCR0( crfD, getXER_SO() );
3629ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         break;
3630ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3631ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      default:
3632ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         vex_printf("dis_int_cmp(ppc)(opc2)\n");
3633ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return False;
3634ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
3635ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      break;
3636ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3637ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   default:
3638ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      vex_printf("dis_int_cmp(ppc)(opc1)\n");
3639ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      return False;
3640ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
3641ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3642ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   return True;
3643ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
3644ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3645ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3646ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*
3647ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  Integer Logical Instructions
3648ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown*/
3649ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic Bool dis_int_logic ( UInt theInstr )
3650ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
3651ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* D-Form, X-Form */
3652ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   UChar opc1    = ifieldOPC(theInstr);
3653ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   UChar rS_addr = ifieldRegDS(theInstr);
3654ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   UChar rA_addr = ifieldRegA(theInstr);
3655ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   UInt  uimm16  = ifieldUIMM16(theInstr);
3656ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   UChar rB_addr = ifieldRegB(theInstr);
3657ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   UInt  opc2    = ifieldOPClo10(theInstr);
3658ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   UChar flag_rC = ifieldBIT0(theInstr);
3659ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3660ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   IRType ty     = mode64 ? Ity_I64 : Ity_I32;
3661ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   IRTemp rS     = newTemp(ty);
3662ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   IRTemp rA     = newTemp(ty);
3663ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   IRTemp rB     = newTemp(ty);
3664ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   IRExpr* irx;
3665ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   Bool do_rc    = False;
3666ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3667ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   assign( rS, getIReg(rS_addr) );
3668ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   assign( rB, getIReg(rB_addr) );
3669ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3670ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   switch (opc1) {
3671ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   case 0x1C: // andi. (AND Immediate, PPC32 p358)
3672ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      DIP("andi. r%u,r%u,0x%x\n", rA_addr, rS_addr, uimm16);
3673ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      assign( rA, binop( mkSzOp(ty, Iop_And8), mkexpr(rS),
3674ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                         mkSzImm(ty, uimm16)) );
3675ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      do_rc = True;  // Always record to CR
3676ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      flag_rC = 1;
3677ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      break;
3678ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3679ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   case 0x1D: // andis. (AND Immediate Shifted, PPC32 p359)
3680ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      DIP("andis r%u,r%u,0x%x\n", rA_addr, rS_addr, uimm16);
3681ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      assign( rA, binop( mkSzOp(ty, Iop_And8), mkexpr(rS),
3682ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                         mkSzImm(ty, uimm16 << 16)) );
3683ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      do_rc = True;  // Always record to CR
3684ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      flag_rC = 1;
3685ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      break;
3686ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3687ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   case 0x18: // ori (OR Immediate, PPC32 p497)
3688ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      DIP("ori r%u,r%u,0x%x\n", rA_addr, rS_addr, uimm16);
3689ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      assign( rA, binop( mkSzOp(ty, Iop_Or8), mkexpr(rS),
3690ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                         mkSzImm(ty, uimm16)) );
3691ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      break;
3692ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3693ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   case 0x19: // oris (OR Immediate Shifted, PPC32 p498)
3694ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      DIP("oris r%u,r%u,0x%x\n", rA_addr, rS_addr, uimm16);
3695ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      assign( rA, binop( mkSzOp(ty, Iop_Or8), mkexpr(rS),
3696ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                         mkSzImm(ty, uimm16 << 16)) );
3697ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      break;
3698ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3699ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   case 0x1A: // xori (XOR Immediate, PPC32 p550)
3700ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      DIP("xori r%u,r%u,0x%x\n", rA_addr, rS_addr, uimm16);
3701ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      assign( rA, binop( mkSzOp(ty, Iop_Xor8), mkexpr(rS),
3702ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                         mkSzImm(ty, uimm16)) );
3703ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      break;
3704ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3705ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   case 0x1B: // xoris (XOR Immediate Shifted, PPC32 p551)
3706ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      DIP("xoris r%u,r%u,0x%x\n", rA_addr, rS_addr, uimm16);
3707ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      assign( rA, binop( mkSzOp(ty, Iop_Xor8), mkexpr(rS),
3708ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                         mkSzImm(ty, uimm16 << 16)) );
3709ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      break;
3710ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3711ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* X Form */
3712ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   case 0x1F:
3713b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      do_rc = True; // All below record to CR, except for where we return at case end.
3714ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3715ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      switch (opc2) {
3716ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case 0x01C: // and (AND, PPC32 p356)
3717ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         DIP("and%s r%u,r%u,r%u\n",
3718ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown             flag_rC ? ".":"", rA_addr, rS_addr, rB_addr);
3719ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         assign(rA, binop( mkSzOp(ty, Iop_And8),
3720ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                           mkexpr(rS), mkexpr(rB)));
3721ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         break;
3722ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3723ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case 0x03C: // andc (AND with Complement, PPC32 p357)
3724ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         DIP("andc%s r%u,r%u,r%u\n",
3725ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown             flag_rC ? ".":"", rA_addr, rS_addr, rB_addr);
3726ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         assign(rA, binop( mkSzOp(ty, Iop_And8), mkexpr(rS),
3727ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                           unop( mkSzOp(ty, Iop_Not8),
3728ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                 mkexpr(rB))));
3729ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         break;
3730ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3731ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case 0x01A: { // cntlzw (Count Leading Zeros Word, PPC32 p371)
3732ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         IRExpr* lo32;
3733ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         if (rB_addr!=0) {
3734ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            vex_printf("dis_int_logic(ppc)(cntlzw,rB_addr)\n");
3735ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            return False;
3736ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         }
3737ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         DIP("cntlzw%s r%u,r%u\n",
3738ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown             flag_rC ? ".":"", rA_addr, rS_addr);
3739ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3740ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         // mode64: count in low word only
3741ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         lo32 = mode64 ? unop(Iop_64to32, mkexpr(rS)) : mkexpr(rS);
3742ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3743ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         // Iop_Clz32 undefined for arg==0, so deal with that case:
3744ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         irx =  binop(Iop_CmpNE32, lo32, mkU32(0));
3745ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         assign(rA, mkWidenFrom32(ty,
3746ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                         IRExpr_Mux0X( unop(Iop_1Uto8, irx),
3747ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                       mkU32(32),
3748ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                       unop(Iop_Clz32, lo32)),
3749ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                         False));
3750ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3751ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         // TODO: alternatively: assign(rA, verbose_Clz32(rS));
3752ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         break;
3753ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
3754ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3755ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case 0x11C: // eqv (Equivalent, PPC32 p396)
3756ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         DIP("eqv%s r%u,r%u,r%u\n",
3757ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown             flag_rC ? ".":"", rA_addr, rS_addr, rB_addr);
3758ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         assign( rA, unop( mkSzOp(ty, Iop_Not8),
3759ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                           binop( mkSzOp(ty, Iop_Xor8),
3760ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                  mkexpr(rS), mkexpr(rB))) );
3761ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         break;
3762ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3763ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case 0x3BA: // extsb (Extend Sign Byte, PPC32 p397
3764ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         if (rB_addr!=0) {
3765ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            vex_printf("dis_int_logic(ppc)(extsb,rB_addr)\n");
3766ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            return False;
3767ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         }
3768ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         DIP("extsb%s r%u,r%u\n",
3769ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown             flag_rC ? ".":"", rA_addr, rS_addr);
3770ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         if (mode64)
3771ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            assign( rA, unop(Iop_8Sto64, unop(Iop_64to8, mkexpr(rS))) );
3772ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         else
3773ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            assign( rA, unop(Iop_8Sto32, unop(Iop_32to8, mkexpr(rS))) );
3774ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         break;
3775ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3776ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case 0x39A: // extsh (Extend Sign Half Word, PPC32 p398)
3777ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         if (rB_addr!=0) {
3778ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            vex_printf("dis_int_logic(ppc)(extsh,rB_addr)\n");
3779ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            return False;
3780ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         }
3781ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         DIP("extsh%s r%u,r%u\n",
3782ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown             flag_rC ? ".":"", rA_addr, rS_addr);
3783ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         if (mode64)
3784ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            assign( rA, unop(Iop_16Sto64,
3785ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                             unop(Iop_64to16, mkexpr(rS))) );
3786ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         else
3787ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            assign( rA, unop(Iop_16Sto32,
3788ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                             unop(Iop_32to16, mkexpr(rS))) );
3789ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         break;
3790ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3791ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case 0x1DC: // nand (NAND, PPC32 p492)
3792ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         DIP("nand%s r%u,r%u,r%u\n",
3793ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown             flag_rC ? ".":"", rA_addr, rS_addr, rB_addr);
3794ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         assign( rA, unop( mkSzOp(ty, Iop_Not8),
3795ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                           binop( mkSzOp(ty, Iop_And8),
3796ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                  mkexpr(rS), mkexpr(rB))) );
3797ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         break;
3798ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3799ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case 0x07C: // nor (NOR, PPC32 p494)
3800ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         DIP("nor%s r%u,r%u,r%u\n",
3801ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown             flag_rC ? ".":"", rA_addr, rS_addr, rB_addr);
3802ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         assign( rA, unop( mkSzOp(ty, Iop_Not8),
3803ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                           binop( mkSzOp(ty, Iop_Or8),
3804ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                  mkexpr(rS), mkexpr(rB))) );
3805ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         break;
3806ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3807ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case 0x1BC: // or (OR, PPC32 p495)
3808ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         if ((!flag_rC) && rS_addr == rB_addr) {
3809ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            DIP("mr r%u,r%u\n", rA_addr, rS_addr);
3810ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            assign( rA, mkexpr(rS) );
3811ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         } else {
3812ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            DIP("or%s r%u,r%u,r%u\n",
3813ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                flag_rC ? ".":"", rA_addr, rS_addr, rB_addr);
3814ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            assign( rA, binop( mkSzOp(ty, Iop_Or8),
3815ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                               mkexpr(rS), mkexpr(rB)) );
3816ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         }
3817ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         break;
3818ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3819ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case 0x19C: // orc  (OR with Complement, PPC32 p496)
3820ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         DIP("orc%s r%u,r%u,r%u\n",
3821ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown             flag_rC ? ".":"", rA_addr, rS_addr, rB_addr);
3822ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         assign( rA, binop( mkSzOp(ty, Iop_Or8), mkexpr(rS),
3823ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                            unop(mkSzOp(ty, Iop_Not8), mkexpr(rB))));
3824ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         break;
3825ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3826ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case 0x13C: // xor (XOR, PPC32 p549)
3827ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         DIP("xor%s r%u,r%u,r%u\n",
3828ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown             flag_rC ? ".":"", rA_addr, rS_addr, rB_addr);
3829ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         assign( rA, binop( mkSzOp(ty, Iop_Xor8),
3830ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                            mkexpr(rS), mkexpr(rB)) );
3831ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         break;
3832ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3833ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3834ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* 64bit Integer Logical Instructions */
3835ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case 0x3DA: // extsw (Extend Sign Word, PPC64 p430)
3836ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         if (rB_addr!=0) {
3837ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            vex_printf("dis_int_logic(ppc)(extsw,rB_addr)\n");
3838ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            return False;
3839ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         }
3840ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         DIP("extsw%s r%u,r%u\n", flag_rC ? ".":"", rA_addr, rS_addr);
3841ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         assign(rA, unop(Iop_32Sto64, unop(Iop_64to32, mkexpr(rS))));
3842ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         break;
3843ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3844ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case 0x03A: // cntlzd (Count Leading Zeros DWord, PPC64 p401)
3845ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         if (rB_addr!=0) {
3846ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            vex_printf("dis_int_logic(ppc)(cntlzd,rB_addr)\n");
3847ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            return False;
3848ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         }
3849ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         DIP("cntlzd%s r%u,r%u\n",
3850ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown             flag_rC ? ".":"", rA_addr, rS_addr);
3851ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         // Iop_Clz64 undefined for arg==0, so deal with that case:
3852ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         irx =  binop(Iop_CmpNE64, mkexpr(rS), mkU64(0));
3853ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         assign(rA, IRExpr_Mux0X( unop(Iop_1Uto8, irx),
3854ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                  mkU64(64),
3855ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                  unop(Iop_Clz64, mkexpr(rS)) ));
3856ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         // TODO: alternatively: assign(rA, verbose_Clz64(rS));
3857ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         break;
3858ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3859ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case 0x1FC: // cmpb (Power6: compare bytes)
3860ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         DIP("cmpb r%u,r%u,r%u\n", rA_addr, rS_addr, rB_addr);
3861ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3862ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         if (mode64)
3863ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            assign( rA, unop( Iop_V128to64,
3864ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                              binop( Iop_CmpEQ8x16,
3865ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                     binop( Iop_64HLtoV128, mkU64(0), mkexpr(rS) ),
3866ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                     binop( Iop_64HLtoV128, mkU64(0), mkexpr(rB) )
3867ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                     )) );
3868ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         else
3869ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            assign( rA, unop( Iop_V128to32,
3870ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                              binop( Iop_CmpEQ8x16,
3871ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                     unop( Iop_32UtoV128, mkexpr(rS) ),
3872ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                     unop( Iop_32UtoV128, mkexpr(rB) )
3873ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                     )) );
3874ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         break;
3875ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3876ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case 0x2DF: { // mftgpr (move floating-point to general purpose register)
3877ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         IRTemp frB = newTemp(Ity_F64);
3878ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         DIP("mftgpr r%u,fr%u\n", rS_addr, rB_addr);
3879ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3880ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         assign( frB, getFReg(rB_addr));  // always F64
3881ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         if (mode64)
3882ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            assign( rA, unop( Iop_ReinterpF64asI64, mkexpr(frB)) );
3883ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         else
3884ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            assign( rA, unop( Iop_64to32, unop( Iop_ReinterpF64asI64, mkexpr(frB))) );
3885ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3886ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         putIReg( rS_addr, mkexpr(rA));
3887ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return True;
3888ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
3889ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3890ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case 0x25F: { // mffgpr (move floating-point from general purpose register)
3891ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         IRTemp frA = newTemp(Ity_F64);
3892ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         DIP("mffgpr fr%u,r%u\n", rS_addr, rB_addr);
3893ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3894ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         if (mode64)
3895ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            assign( frA, unop( Iop_ReinterpI64asF64, mkexpr(rB)) );
3896ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         else
3897ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            assign( frA, unop( Iop_ReinterpI64asF64, unop( Iop_32Uto64, mkexpr(rB))) );
3898ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3899ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         putFReg( rS_addr, mkexpr(frA));
3900ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return True;
3901ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
3902b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      case 0x1FA: // popcntd (population count doubleword
3903b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      {
3904b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov    	  DIP("popcntd r%u,r%u\n", rA_addr, rS_addr);
3905b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov        IRTemp result = gen_POPCOUNT(ty, rS);
3906b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov    	  putIReg( rA_addr, mkexpr(result) );
3907b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov    	  return True;
3908b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      }
3909b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      case 0x17A: // popcntw (Population Count Words)
3910b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      {
3911b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         DIP("popcntw r%u,r%u\n", rA_addr, rS_addr);
3912b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         if (mode64) {
3913b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov            IRTemp resultHi, resultLo;
3914b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov            IRTemp argLo = newTemp(Ity_I32);
3915b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov            IRTemp argHi = newTemp(Ity_I32);
3916b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov            assign(argLo, unop(Iop_64to32, mkexpr(rS)));
3917b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov            assign(argHi, unop(Iop_64HIto32, mkexpr(rS)));
3918b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov            resultLo = gen_POPCOUNT(Ity_I32, argLo);
3919b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov            resultHi = gen_POPCOUNT(Ity_I32, argHi);
3920b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov            putIReg( rA_addr, binop(Iop_32HLto64, mkexpr(resultHi), mkexpr(resultLo)));
3921b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         } else {
3922b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov            IRTemp result = gen_POPCOUNT(ty, rS);
3923b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov            putIReg( rA_addr, mkexpr(result) );
3924b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         }
3925b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         return True;
3926b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      }
3927b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov       case 0x0FC: // bpermd (Bit Permute Doubleword)
3928b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov       {
3929b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov          /* This is a lot of rigmarole to emulate bpermd like this, as it
3930b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov           * could be done much faster by implementing a call to the native
3931b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov           * instruction.  However, where possible I want to avoid using new
3932b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov           * native instructions so that we can use valgrind to emulate those
3933b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov           * instructions on older PPC64 hardware.
3934b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov           */
3935b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov #define BPERMD_IDX_MASK 0x00000000000000FFULL
3936b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov #define BPERMD_BIT_MASK 0x8000000000000000ULL
3937b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov          int i;
3938b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov          IRExpr * rS_expr = mkexpr(rS);
3939b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov          IRExpr * res = binop(Iop_And64, mkU64(0), mkU64(0));
3940b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov          DIP("bpermd r%u,r%u,r%u\n", rA_addr, rS_addr, rB_addr);
3941b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov          for (i = 0; i < 8; i++) {
3942b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov             IRTemp idx_tmp = newTemp( Ity_I64 );
3943b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov             IRTemp perm_bit = newTemp( Ity_I64 );
3944b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov             IRTemp idx = newTemp( Ity_I8 );
3945b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov             IRTemp idx_LT64 = newTemp( Ity_I1 );
3946b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov             IRTemp idx_LT64_ity64 = newTemp( Ity_I64 );
3947b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
3948b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov             assign( idx_tmp,
3949b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                     binop( Iop_And64, mkU64( BPERMD_IDX_MASK ), rS_expr ) );
3950b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov             assign( idx_LT64,
3951b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                           binop( Iop_CmpLT64U, mkexpr( idx_tmp ), mkU64( 64 ) ) );
3952b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov             assign( idx,
3953b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                           binop( Iop_And8,
3954b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                                  unop( Iop_1Sto8,
3955b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                                        mkexpr(idx_LT64) ),
3956b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                                  unop( Iop_64to8, mkexpr( idx_tmp ) ) ) );
3957b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov             /* If idx_LT64 == 0, we must force the perm bit to '0'. Below, we se idx
3958b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov              * to determine which bit of rB to use for the perm bit, and then we shift
3959b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov              * that bit to the MSB position.  We AND that with a 64-bit-ized idx_LT64
3960b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov              * to set the final perm bit.
3961b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov              */
3962b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov             assign( idx_LT64_ity64,
3963b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                           unop( Iop_32Uto64, unop( Iop_1Uto32, mkexpr(idx_LT64 ) ) ) );
3964b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov             assign( perm_bit,
3965b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                           binop( Iop_And64,
3966b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                                  mkexpr( idx_LT64_ity64 ),
3967b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                                  binop( Iop_Shr64,
3968b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                                         binop( Iop_And64,
3969b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                                                mkU64( BPERMD_BIT_MASK ),
3970b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                                                binop( Iop_Shl64,
3971b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                                                       mkexpr( rB ),
3972b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                                                       mkexpr( idx ) ) ),
3973b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                                         mkU8( 63 ) ) ) );
3974b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov             res = binop( Iop_Or64,
3975b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                                res,
3976b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                                binop( Iop_Shl64,
3977b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                                       mkexpr( perm_bit ),
3978b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                                       mkU8( i ) ) );
3979b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov             rS_expr = binop( Iop_Shr64, rS_expr, mkU8( 8 ) );
3980b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov          }
3981b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov          putIReg(rA_addr, res);
3982b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov          return True;
3983b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov       }
3984ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3985ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      default:
3986ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         vex_printf("dis_int_logic(ppc)(opc2)\n");
3987ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return False;
3988ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
3989ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      break;
3990ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3991ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   default:
3992ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      vex_printf("dis_int_logic(ppc)(opc1)\n");
3993ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      return False;
3994ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
3995ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3996ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   putIReg( rA_addr, mkexpr(rA) );
3997ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3998ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (do_rc && flag_rC) {
3999ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      set_CR0( mkexpr(rA) );
4000ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
4001ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   return True;
4002ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
4003ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
4004ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*
4005ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  Integer Parity Instructions
4006ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown*/
4007ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic Bool dis_int_parity ( UInt theInstr )
4008ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
4009ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* X-Form */
4010ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   UChar opc1    = ifieldOPC(theInstr);
4011ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   UChar rS_addr = ifieldRegDS(theInstr);
4012ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   UChar rA_addr = ifieldRegA(theInstr);
4013ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   UChar rB_addr = ifieldRegB(theInstr);
4014ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   UInt  opc2    = ifieldOPClo10(theInstr);
4015ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   UChar b0      = ifieldBIT0(theInstr);
4016ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   IRType ty     = mode64 ? Ity_I64 : Ity_I32;
4017ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
4018ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   IRTemp rS     = newTemp(ty);
4019ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   IRTemp rA     = newTemp(ty);
4020ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   IRTemp iTot1  = newTemp(Ity_I32);
4021ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   IRTemp iTot2  = newTemp(Ity_I32);
4022ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   IRTemp iTot3  = newTemp(Ity_I32);
4023ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   IRTemp iTot4  = newTemp(Ity_I32);
4024ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   IRTemp iTot5  = newTemp(Ity_I32);
4025ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   IRTemp iTot6  = newTemp(Ity_I32);
4026ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   IRTemp iTot7  = newTemp(Ity_I32);
4027ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   IRTemp iTot8  = newTemp(Ity_I32);
4028ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   IRTemp rS1    = newTemp(ty);
4029ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   IRTemp rS2    = newTemp(ty);
4030ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   IRTemp rS3    = newTemp(ty);
4031ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   IRTemp rS4    = newTemp(ty);
4032ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   IRTemp rS5    = newTemp(ty);
4033ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   IRTemp rS6    = newTemp(ty);
4034ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   IRTemp rS7    = newTemp(ty);
4035ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   IRTemp iHi    = newTemp(Ity_I32);
4036ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   IRTemp iLo    = newTemp(Ity_I32);
4037ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   IROp to_bit   = (mode64 ? Iop_64to1 : Iop_32to1);
4038ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   IROp shr_op   = (mode64 ? Iop_Shr64 : Iop_Shr32);
4039ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
4040ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (opc1 != 0x1f || rB_addr || b0) {
4041ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      vex_printf("dis_int_parity(ppc)(0x1F,opc1:rB|b0)\n");
4042ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      return False;
4043ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
4044ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
4045ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   assign( rS, getIReg(rS_addr) );
4046ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
4047ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   switch (opc2) {
4048ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   case 0xba:  // prtyd (Parity Doubleword, ISA 2.05 p320)
4049ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      DIP("prtyd r%u,r%u\n", rA_addr, rS_addr);
4050ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      assign( iTot1, unop(Iop_1Uto32, unop(to_bit, mkexpr(rS))) );
4051ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      assign( rS1, binop(shr_op, mkexpr(rS), mkU8(8)) );
4052ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      assign( iTot2, binop(Iop_Add32,
4053ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                           unop(Iop_1Uto32, unop(to_bit, mkexpr(rS1))),
4054ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                           mkexpr(iTot1)) );
4055ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      assign( rS2, binop(shr_op, mkexpr(rS1), mkU8(8)) );
4056ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      assign( iTot3, binop(Iop_Add32,
4057ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                           unop(Iop_1Uto32, unop(to_bit, mkexpr(rS2))),
4058ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                           mkexpr(iTot2)) );
4059ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      assign( rS3, binop(shr_op, mkexpr(rS2), mkU8(8)) );
4060ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      assign( iTot4, binop(Iop_Add32,
4061ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                           unop(Iop_1Uto32, unop(to_bit, mkexpr(rS3))),
4062ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                           mkexpr(iTot3)) );
4063ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (mode64) {
4064ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         assign( rS4, binop(shr_op, mkexpr(rS3), mkU8(8)) );
4065ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         assign( iTot5, binop(Iop_Add32,
4066ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                              unop(Iop_1Uto32, unop(to_bit, mkexpr(rS4))),
4067ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                              mkexpr(iTot4)) );
4068ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         assign( rS5, binop(shr_op, mkexpr(rS4), mkU8(8)) );
4069ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         assign( iTot6, binop(Iop_Add32,
4070ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                              unop(Iop_1Uto32, unop(to_bit, mkexpr(rS5))),
4071ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                              mkexpr(iTot5)) );
4072ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         assign( rS6, binop(shr_op, mkexpr(rS5), mkU8(8)) );
4073ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         assign( iTot7, binop(Iop_Add32,
4074ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                              unop(Iop_1Uto32, unop(to_bit, mkexpr(rS6))),
4075ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                              mkexpr(iTot6)) );
4076ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         assign( rS7, binop(shr_op, mkexpr(rS6), mkU8(8)) );
4077ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         assign( iTot8, binop(Iop_Add32,
4078ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                              unop(Iop_1Uto32, unop(to_bit, mkexpr(rS7))),
4079ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                              mkexpr(iTot7)) );
4080ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         assign( rA, unop(Iop_32Uto64,
4081ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                          binop(Iop_And32, mkexpr(iTot8), mkU32(1))) );
4082ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      } else
4083ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         assign( rA, mkexpr(iTot4) );
4084ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
4085ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      break;
4086ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   case 0x9a:  // prtyw (Parity Word, ISA 2.05 p320)
4087ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      assign( iTot1, unop(Iop_1Uto32, unop(to_bit, mkexpr(rS))) );
4088ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      assign( rS1, binop(shr_op, mkexpr(rS), mkU8(8)) );
4089ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      assign( iTot2, binop(Iop_Add32,
4090ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                           unop(Iop_1Uto32, unop(to_bit, mkexpr(rS1))),
4091ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                           mkexpr(iTot1)) );
4092ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      assign( rS2, binop(shr_op, mkexpr(rS1), mkU8(8)) );
4093ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      assign( iTot3, binop(Iop_Add32,
4094ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                           unop(Iop_1Uto32, unop(to_bit, mkexpr(rS2))),
4095ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                           mkexpr(iTot2)) );
4096ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      assign( rS3, binop(shr_op, mkexpr(rS2), mkU8(8)) );
4097ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      assign( iTot4, binop(Iop_Add32,
4098ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                           unop(Iop_1Uto32, unop(to_bit, mkexpr(rS3))),
4099ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                           mkexpr(iTot3)) );
4100ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      assign( iLo, unop(Iop_1Uto32, unop(Iop_32to1, mkexpr(iTot4) )) );
4101ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
4102ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (mode64) {
4103ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         assign( rS4, binop(shr_op, mkexpr(rS3), mkU8(8)) );
4104ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         assign( iTot5, unop(Iop_1Uto32, unop(to_bit, mkexpr(rS4))) );
4105ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         assign( rS5, binop(shr_op, mkexpr(rS4), mkU8(8)) );
4106ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         assign( iTot6, binop(Iop_Add32,
4107ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                              unop(Iop_1Uto32, unop(to_bit, mkexpr(rS5))),
4108ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                              mkexpr(iTot5)) );
4109ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         assign( rS6, binop(shr_op, mkexpr(rS5), mkU8(8)) );
4110ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         assign( iTot7, binop(Iop_Add32,
4111ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                              unop(Iop_1Uto32, unop(to_bit, mkexpr(rS6))),
4112ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                              mkexpr(iTot6)) );
4113ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         assign( rS7, binop(shr_op, mkexpr(rS6), mkU8(8)));
4114ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         assign( iTot8, binop(Iop_Add32,
4115ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                              unop(Iop_1Uto32, unop(to_bit, mkexpr(rS7))),
4116ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                              mkexpr(iTot7)) );
4117ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         assign( iHi, binop(Iop_And32, mkU32(1), mkexpr(iTot8)) ),
4118ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            assign( rA, binop(Iop_32HLto64, mkexpr(iHi), mkexpr(iLo)) );
4119ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      } else
4120ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         assign( rA, binop(Iop_Or32, mkU32(0), mkexpr(iLo)) );
4121ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      break;
4122ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   default:
4123ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      vex_printf("dis_int_parity(ppc)(opc2)\n");
4124ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      return False;
4125ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
4126ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
4127ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   putIReg( rA_addr, mkexpr(rA) );
4128ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
4129ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   return True;
4130ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
4131ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
4132ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
4133ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*
4134ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  Integer Rotate Instructions
4135ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown*/
4136ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic Bool dis_int_rot ( UInt theInstr )
4137ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
4138ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* M-Form, MDS-Form */
4139ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   UChar opc1    = ifieldOPC(theInstr);
4140ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   UChar rS_addr = ifieldRegDS(theInstr);
4141ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   UChar rA_addr = ifieldRegA(theInstr);
4142ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   UChar rB_addr = ifieldRegB(theInstr);
4143ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   UChar sh_imm  = rB_addr;
4144ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   UChar MaskBeg = toUChar( IFIELD( theInstr, 6, 5 ) );
4145ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   UChar MaskEnd = toUChar( IFIELD( theInstr, 1, 5 ) );
4146ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   UChar msk_imm = toUChar( IFIELD( theInstr, 5, 6 ) );
4147ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   UChar opc2    = toUChar( IFIELD( theInstr, 2, 3 ) );
4148ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   UChar b1      = ifieldBIT1(theInstr);
4149ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   UChar flag_rC = ifieldBIT0(theInstr);
4150ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
4151ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   IRType ty     = mode64 ? Ity_I64 : Ity_I32;
4152ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   IRTemp rS     = newTemp(ty);
4153ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   IRTemp rA     = newTemp(ty);
4154ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   IRTemp rB     = newTemp(ty);
4155ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   IRTemp rot    = newTemp(ty);
4156ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   IRExpr *r;
4157ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   UInt   mask32;
4158ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   ULong  mask64;
4159ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
4160ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   assign( rS, getIReg(rS_addr) );
4161ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   assign( rB, getIReg(rB_addr) );
4162ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
4163ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   switch (opc1) {
4164ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   case 0x14: {
4165ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      // rlwimi (Rotate Left Word Imm then Mask Insert, PPC32 p500)
4166ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      DIP("rlwimi%s r%u,r%u,%d,%d,%d\n", flag_rC ? ".":"",
4167ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown          rA_addr, rS_addr, sh_imm, MaskBeg, MaskEnd);
4168ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (mode64) {
4169ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         // tmp32 = (ROTL(rS_Lo32, Imm)
4170ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         // rA = ((tmp32 || tmp32) & mask64) | (rA & ~mask64)
4171ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         mask64 = MASK64(31-MaskEnd, 31-MaskBeg);
4172ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         r = ROTL( unop(Iop_64to32, mkexpr(rS) ), mkU8(sh_imm) );
4173ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         r = unop(Iop_32Uto64, r);
4174ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         assign( rot, binop(Iop_Or64, r,
4175ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                            binop(Iop_Shl64, r, mkU8(32))) );
4176ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         assign( rA,
4177ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            binop(Iop_Or64,
4178ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  binop(Iop_And64, mkexpr(rot), mkU64(mask64)),
4179ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  binop(Iop_And64, getIReg(rA_addr), mkU64(~mask64))) );
4180ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
4181ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      else {
4182ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         // rA = (ROTL(rS, Imm) & mask) | (rA & ~mask);
4183ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         mask32 = MASK32(31-MaskEnd, 31-MaskBeg);
4184ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         r = ROTL(mkexpr(rS), mkU8(sh_imm));
4185ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         assign( rA,
4186ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            binop(Iop_Or32,
4187ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  binop(Iop_And32, mkU32(mask32), r),
4188ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  binop(Iop_And32, getIReg(rA_addr), mkU32(~mask32))) );
4189ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
4190ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      break;
4191ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
4192ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
4193ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   case 0x15: {
4194ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      // rlwinm (Rotate Left Word Imm then AND with Mask, PPC32 p501)
4195ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      vassert(MaskBeg < 32);
4196ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      vassert(MaskEnd < 32);
4197ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      vassert(sh_imm  < 32);
4198ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
4199ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (mode64) {
4200ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         IRTemp rTmp = newTemp(Ity_I64);
4201ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         mask64 = MASK64(31-MaskEnd, 31-MaskBeg);
4202ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         DIP("rlwinm%s r%u,r%u,%d,%d,%d\n", flag_rC ? ".":"",
4203ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown             rA_addr, rS_addr, sh_imm, MaskBeg, MaskEnd);
4204ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         // tmp32 = (ROTL(rS_Lo32, Imm)
4205ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         // rA = ((tmp32 || tmp32) & mask64)
4206ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         r = ROTL( unop(Iop_64to32, mkexpr(rS) ), mkU8(sh_imm) );
4207ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         r = unop(Iop_32Uto64, r);
4208ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         assign( rTmp, r );
4209ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         r = NULL;
4210ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         assign( rot, binop(Iop_Or64, mkexpr(rTmp),
4211ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                            binop(Iop_Shl64, mkexpr(rTmp), mkU8(32))) );
4212ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         assign( rA, binop(Iop_And64, mkexpr(rot), mkU64(mask64)) );
4213ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
4214ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      else {
4215ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         if (MaskBeg == 0 && sh_imm+MaskEnd == 31) {
4216ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            /* Special-case the ,n,0,31-n form as that is just n-bit
4217ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               shift left, PPC32 p501 */
4218ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            DIP("slwi%s r%u,r%u,%d\n", flag_rC ? ".":"",
4219ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                rA_addr, rS_addr, sh_imm);
4220ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            assign( rA, binop(Iop_Shl32, mkexpr(rS), mkU8(sh_imm)) );
4221ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         }
4222ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         else if (MaskEnd == 31 && sh_imm+MaskBeg == 32) {
4223ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            /* Special-case the ,32-n,n,31 form as that is just n-bit
4224ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               unsigned shift right, PPC32 p501 */
4225ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            DIP("srwi%s r%u,r%u,%d\n", flag_rC ? ".":"",
4226ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                rA_addr, rS_addr, MaskBeg);
4227ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            assign( rA, binop(Iop_Shr32, mkexpr(rS), mkU8(MaskBeg)) );
4228ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         }
4229ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         else {
4230ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            /* General case. */
4231ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            mask32 = MASK32(31-MaskEnd, 31-MaskBeg);
4232ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            DIP("rlwinm%s r%u,r%u,%d,%d,%d\n", flag_rC ? ".":"",
4233ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                rA_addr, rS_addr, sh_imm, MaskBeg, MaskEnd);
4234ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            // rA = ROTL(rS, Imm) & mask
4235ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            assign( rA, binop(Iop_And32,
4236ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                              ROTL(mkexpr(rS), mkU8(sh_imm)),
4237ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                              mkU32(mask32)) );
4238ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         }
4239ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
4240ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      break;
4241ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
4242ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
4243ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   case 0x17: {
4244ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      // rlwnm (Rotate Left Word then AND with Mask, PPC32 p503
4245ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      DIP("rlwnm%s r%u,r%u,r%u,%d,%d\n", flag_rC ? ".":"",
4246ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown          rA_addr, rS_addr, rB_addr, MaskBeg, MaskEnd);
4247ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (mode64) {
4248ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         mask64 = MASK64(31-MaskEnd, 31-MaskBeg);
4249ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         /* weird insn alert!
4250ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            tmp32 = (ROTL(rS_Lo32, rB[0-4])
4251ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            rA = ((tmp32 || tmp32) & mask64)
4252ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         */
4253ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         // note, ROTL does the masking, so we don't do it here
4254ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         r = ROTL( unop(Iop_64to32, mkexpr(rS)),
4255ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                   unop(Iop_64to8, mkexpr(rB)) );
4256ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         r = unop(Iop_32Uto64, r);
4257ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         assign(rot, binop(Iop_Or64, r, binop(Iop_Shl64, r, mkU8(32))));
4258ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         assign( rA, binop(Iop_And64, mkexpr(rot), mkU64(mask64)) );
4259ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      } else {
4260ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         mask32 = MASK32(31-MaskEnd, 31-MaskBeg);
4261ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         // rA = ROTL(rS, rB[0-4]) & mask
4262ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         // note, ROTL does the masking, so we don't do it here
4263ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         assign( rA, binop(Iop_And32,
4264ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                           ROTL(mkexpr(rS),
4265ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                unop(Iop_32to8, mkexpr(rB))),
4266ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                           mkU32(mask32)) );
4267ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
4268ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      break;
4269ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
4270ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
4271ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* 64bit Integer Rotates */
4272ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   case 0x1E: {
4273ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      msk_imm = ((msk_imm & 1) << 5) | (msk_imm >> 1);
4274ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      sh_imm |= b1 << 5;
4275ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
4276ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      vassert( msk_imm < 64 );
4277ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      vassert( sh_imm < 64 );
4278ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
4279ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      switch (opc2) {
4280ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case 0x4: {
4281ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         /* r = ROTL64( rS, rB_lo6) */
4282ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         r = ROTL( mkexpr(rS), unop(Iop_64to8, mkexpr(rB)) );
4283ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
4284ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         if (b1 == 0) { // rldcl (Rotl DWord, Clear Left, PPC64 p555)
4285ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            DIP("rldcl%s r%u,r%u,r%u,%u\n", flag_rC ? ".":"",
4286ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                rA_addr, rS_addr, rB_addr, msk_imm);
4287ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            // note, ROTL does the masking, so we don't do it here
4288ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            mask64 = MASK64(0, 63-msk_imm);
4289ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            assign( rA, binop(Iop_And64, r, mkU64(mask64)) );
4290ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            break;
4291ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         } else {       // rldcr (Rotl DWord, Clear Right, PPC64 p556)
4292ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            DIP("rldcr%s r%u,r%u,r%u,%u\n", flag_rC ? ".":"",
4293ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                rA_addr, rS_addr, rB_addr, msk_imm);
4294ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            mask64 = MASK64(63-msk_imm, 63);
4295ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            assign( rA, binop(Iop_And64, r, mkU64(mask64)) );
4296ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            break;
4297ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         }
4298ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         break;
4299ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
4300ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case 0x2: // rldic (Rotl DWord Imm, Clear, PPC64 p557)
4301ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         DIP("rldic%s r%u,r%u,%u,%u\n", flag_rC ? ".":"",
4302ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown             rA_addr, rS_addr, sh_imm, msk_imm);
4303ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         r = ROTL(mkexpr(rS), mkU8(sh_imm));
4304ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         mask64 = MASK64(sh_imm, 63-msk_imm);
4305ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         assign( rA, binop(Iop_And64, r, mkU64(mask64)) );
4306ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         break;
4307ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         // later: deal with special case: (msk_imm==0) => SHL(sh_imm)
4308ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         /*
4309ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown           Hmm... looks like this'll do the job more simply:
4310ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown           r = SHL(rS, sh_imm)
4311ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown           m = ~(1 << (63-msk_imm))
4312ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown           assign(rA, r & m);
4313ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         */
4314ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
4315ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case 0x0: // rldicl (Rotl DWord Imm, Clear Left, PPC64 p558)
4316ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         if (mode64
4317ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown             && sh_imm + msk_imm == 64 && msk_imm >= 1 && msk_imm <= 63) {
4318ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            /* special-case the ,64-n,n form as that is just
4319ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               unsigned shift-right by n */
4320ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            DIP("srdi%s r%u,r%u,%u\n",
4321ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                flag_rC ? ".":"", rA_addr, rS_addr, msk_imm);
4322ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            assign( rA, binop(Iop_Shr64, mkexpr(rS), mkU8(msk_imm)) );
4323ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         } else {
4324ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            DIP("rldicl%s r%u,r%u,%u,%u\n", flag_rC ? ".":"",
4325ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                rA_addr, rS_addr, sh_imm, msk_imm);
4326ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            r = ROTL(mkexpr(rS), mkU8(sh_imm));
4327ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            mask64 = MASK64(0, 63-msk_imm);
4328ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            assign( rA, binop(Iop_And64, r, mkU64(mask64)) );
4329ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         }
4330ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         break;
4331ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
4332ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case 0x1: // rldicr (Rotl DWord Imm, Clear Right, PPC64 p559)
4333ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         if (mode64
4334ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown             && sh_imm + msk_imm == 63 && sh_imm >= 1 && sh_imm <= 63) {
4335ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            /* special-case the ,n,63-n form as that is just
4336ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               shift-left by n */
4337ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            DIP("sldi%s r%u,r%u,%u\n",
4338ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                flag_rC ? ".":"", rA_addr, rS_addr, sh_imm);
4339ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            assign( rA, binop(Iop_Shl64, mkexpr(rS), mkU8(sh_imm)) );
4340ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         } else {
4341ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            DIP("rldicr%s r%u,r%u,%u,%u\n", flag_rC ? ".":"",
4342ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                rA_addr, rS_addr, sh_imm, msk_imm);
4343ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            r = ROTL(mkexpr(rS), mkU8(sh_imm));
4344ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            mask64 = MASK64(63-msk_imm, 63);
4345ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            assign( rA, binop(Iop_And64, r, mkU64(mask64)) );
4346ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         }
4347ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         break;
4348ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
4349ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case 0x3: { // rldimi (Rotl DWord Imm, Mask Insert, PPC64 p560)
4350ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         IRTemp rA_orig = newTemp(ty);
4351ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         DIP("rldimi%s r%u,r%u,%u,%u\n", flag_rC ? ".":"",
4352ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown             rA_addr, rS_addr, sh_imm, msk_imm);
4353ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         r = ROTL(mkexpr(rS), mkU8(sh_imm));
4354ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         mask64 = MASK64(sh_imm, 63-msk_imm);
4355ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         assign( rA_orig, getIReg(rA_addr) );
4356ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         assign( rA, binop(Iop_Or64,
4357ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                           binop(Iop_And64, mkU64(mask64),  r),
4358ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                           binop(Iop_And64, mkU64(~mask64),
4359ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                            mkexpr(rA_orig))) );
4360ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         break;
4361ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
4362ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      default:
4363ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         vex_printf("dis_int_rot(ppc)(opc2)\n");
4364ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return False;
4365ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
4366ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      break;
4367ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
4368ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
4369ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   default:
4370ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      vex_printf("dis_int_rot(ppc)(opc1)\n");
4371ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      return False;
4372ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
4373ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
4374ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   putIReg( rA_addr, mkexpr(rA) );
4375ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
4376ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (flag_rC) {
4377ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      set_CR0( mkexpr(rA) );
4378ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
4379ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   return True;
4380ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
4381ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
4382ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
4383ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*
4384ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  Integer Load Instructions
4385ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown*/
4386ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic Bool dis_int_load ( UInt theInstr )
4387ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
4388ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* D-Form, X-Form, DS-Form */
4389ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   UChar opc1     = ifieldOPC(theInstr);
4390ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   UChar rD_addr  = ifieldRegDS(theInstr);
4391ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   UChar rA_addr  = ifieldRegA(theInstr);
4392ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   UInt  uimm16   = ifieldUIMM16(theInstr);
4393ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   UChar rB_addr  = ifieldRegB(theInstr);
4394ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   UInt  opc2     = ifieldOPClo10(theInstr);
4395ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   UChar b1       = ifieldBIT1(theInstr);
4396ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   UChar b0       = ifieldBIT0(theInstr);
4397ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
4398ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   Int     simm16 = extend_s_16to32(uimm16);
4399ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   IRType  ty     = mode64 ? Ity_I64 : Ity_I32;
4400ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   IRTemp  EA     = newTemp(ty);
4401ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   IRExpr* val;
4402ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
4403ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   switch (opc1) {
4404ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   case 0x1F: // register offset
4405ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      assign( EA, ea_rAor0_idxd( rA_addr, rB_addr ) );
4406ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      break;
4407ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   case 0x3A: // immediate offset: 64bit: ld/ldu/lwa: mask off
4408ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown              // lowest 2 bits of immediate before forming EA
4409ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      simm16 = simm16 & 0xFFFFFFFC;
4410ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   default:   // immediate offset
4411ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      assign( EA, ea_rAor0_simm( rA_addr, simm16  ) );
4412ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      break;
4413ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
4414ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
4415ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   switch (opc1) {
4416ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   case 0x22: // lbz (Load B & Zero, PPC32 p433)
4417ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      DIP("lbz r%u,%d(r%u)\n", rD_addr, (Int)simm16, rA_addr);
4418ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      val = loadBE(Ity_I8, mkexpr(EA));
4419ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      putIReg( rD_addr, mkWidenFrom8(ty, val, False) );
4420ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      break;
4421ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
4422ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   case 0x23: // lbzu (Load B & Zero, Update, PPC32 p434)
4423ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (rA_addr == 0 || rA_addr == rD_addr) {
4424ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         vex_printf("dis_int_load(ppc)(lbzu,rA_addr|rD_addr)\n");
4425ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return False;
4426ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
4427ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      DIP("lbzu r%u,%d(r%u)\n", rD_addr, (Int)simm16, rA_addr);
4428ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      val = loadBE(Ity_I8, mkexpr(EA));
4429ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      putIReg( rD_addr, mkWidenFrom8(ty, val, False) );
4430ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      putIReg( rA_addr, mkexpr(EA) );
4431ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      break;
4432ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
4433ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   case 0x2A: // lha (Load HW Alg, PPC32 p445)
4434ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      DIP("lha r%u,%d(r%u)\n", rD_addr, (Int)simm16, rA_addr);
4435ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      val = loadBE(Ity_I16, mkexpr(EA));
4436ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      putIReg( rD_addr, mkWidenFrom16(ty, val, True) );
4437ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      break;
4438ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
4439ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   case 0x2B: // lhau (Load HW Alg, Update, PPC32 p446)
4440ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (rA_addr == 0 || rA_addr == rD_addr) {
4441ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         vex_printf("dis_int_load(ppc)(lhau,rA_addr|rD_addr)\n");
4442ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return False;
4443ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
4444ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      DIP("lhau r%u,%d(r%u)\n", rD_addr, (Int)simm16, rA_addr);
4445ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      val = loadBE(Ity_I16, mkexpr(EA));
4446ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      putIReg( rD_addr, mkWidenFrom16(ty, val, True) );
4447ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      putIReg( rA_addr, mkexpr(EA) );
4448ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      break;
4449ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
4450ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   case 0x28: // lhz (Load HW & Zero, PPC32 p450)
4451ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      DIP("lhz r%u,%d(r%u)\n", rD_addr, (Int)simm16, rA_addr);
4452ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      val = loadBE(Ity_I16, mkexpr(EA));
4453ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      putIReg( rD_addr, mkWidenFrom16(ty, val, False) );
4454ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      break;
4455ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
4456ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   case 0x29: // lhzu (Load HW & and Zero, Update, PPC32 p451)
4457ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (rA_addr == 0 || rA_addr == rD_addr) {
4458ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         vex_printf("dis_int_load(ppc)(lhzu,rA_addr|rD_addr)\n");
4459ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return False;
4460ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
4461ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      DIP("lhzu r%u,%d(r%u)\n", rD_addr, (Int)simm16, rA_addr);
4462ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      val = loadBE(Ity_I16, mkexpr(EA));
4463ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      putIReg( rD_addr, mkWidenFrom16(ty, val, False) );
4464ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      putIReg( rA_addr, mkexpr(EA) );
4465ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      break;
4466ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
4467ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   case 0x20: // lwz (Load W & Zero, PPC32 p460)
4468ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      DIP("lwz r%u,%d(r%u)\n", rD_addr, (Int)simm16, rA_addr);
4469ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      val = loadBE(Ity_I32, mkexpr(EA));
4470ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      putIReg( rD_addr, mkWidenFrom32(ty, val, False) );
4471ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      break;
4472ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
4473ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   case 0x21: // lwzu (Load W & Zero, Update, PPC32 p461))
4474ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (rA_addr == 0 || rA_addr == rD_addr) {
4475ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         vex_printf("dis_int_load(ppc)(lwzu,rA_addr|rD_addr)\n");
4476ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return False;
4477ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
4478ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      DIP("lwzu r%u,%d(r%u)\n", rD_addr, (Int)simm16, rA_addr);
4479ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      val = loadBE(Ity_I32, mkexpr(EA));
4480ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      putIReg( rD_addr, mkWidenFrom32(ty, val, False) );
4481ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      putIReg( rA_addr, mkexpr(EA) );
4482ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      break;
4483ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
4484ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* X Form */
4485ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   case 0x1F:
4486ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (b0 != 0) {
4487ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         vex_printf("dis_int_load(ppc)(Ox1F,b0)\n");
4488ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return False;
4489ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
4490ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
4491ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      switch (opc2) {
4492ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case 0x077: // lbzux (Load B & Zero, Update Indexed, PPC32 p435)
4493ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         DIP("lbzux r%u,r%u,r%u\n", rD_addr, rA_addr, rB_addr);
4494ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         if (rA_addr == 0 || rA_addr == rD_addr) {
4495ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            vex_printf("dis_int_load(ppc)(lwzux,rA_addr|rD_addr)\n");
4496ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            return False;
4497ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         }
4498ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         val = loadBE(Ity_I8, mkexpr(EA));
4499ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         putIReg( rD_addr, mkWidenFrom8(ty, val, False) );
4500ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         putIReg( rA_addr, mkexpr(EA) );
4501ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         break;
4502ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
4503ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case 0x057: // lbzx (Load B & Zero, Indexed, PPC32 p436)
4504ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         DIP("lbzx r%u,r%u,r%u\n", rD_addr, rA_addr, rB_addr);
4505ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         val = loadBE(Ity_I8, mkexpr(EA));
4506ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         putIReg( rD_addr, mkWidenFrom8(ty, val, False) );
4507ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         break;
4508ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
4509ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case 0x177: // lhaux (Load HW Alg, Update Indexed, PPC32 p447)
4510ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         if (rA_addr == 0 || rA_addr == rD_addr) {
4511ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            vex_printf("dis_int_load(ppc)(lhaux,rA_addr|rD_addr)\n");
4512ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            return False;
4513ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         }
4514ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         DIP("lhaux r%u,r%u,r%u\n", rD_addr, rA_addr, rB_addr);
4515ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         val = loadBE(Ity_I16, mkexpr(EA));
4516ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         putIReg( rD_addr, mkWidenFrom16(ty, val, True) );
4517ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         putIReg( rA_addr, mkexpr(EA) );
4518ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         break;
4519ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
4520ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case 0x157: // lhax (Load HW Alg, Indexed, PPC32 p448)
4521ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         DIP("lhax r%u,r%u,r%u\n", rD_addr, rA_addr, rB_addr);
4522ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         val = loadBE(Ity_I16, mkexpr(EA));
4523ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         putIReg( rD_addr, mkWidenFrom16(ty, val, True) );
4524ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         break;
4525ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
4526ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case 0x137: // lhzux (Load HW & Zero, Update Indexed, PPC32 p452)
4527ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         if (rA_addr == 0 || rA_addr == rD_addr) {
4528ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            vex_printf("dis_int_load(ppc)(lhzux,rA_addr|rD_addr)\n");
4529ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            return False;
4530ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         }
4531ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         DIP("lhzux r%u,r%u,r%u\n", rD_addr, rA_addr, rB_addr);
4532ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         val = loadBE(Ity_I16, mkexpr(EA));
4533ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         putIReg( rD_addr, mkWidenFrom16(ty, val, False) );
4534ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         putIReg( rA_addr, mkexpr(EA) );
4535ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         break;
4536ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
4537ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case 0x117: // lhzx (Load HW & Zero, Indexed, PPC32 p453)
4538ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         DIP("lhzx r%u,r%u,r%u\n", rD_addr, rA_addr, rB_addr);
4539ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         val = loadBE(Ity_I16, mkexpr(EA));
4540ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         putIReg( rD_addr, mkWidenFrom16(ty, val, False) );
4541ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         break;
4542ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
4543ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case 0x037: // lwzux (Load W & Zero, Update Indexed, PPC32 p462)
4544ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         if (rA_addr == 0 || rA_addr == rD_addr) {
4545ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            vex_printf("dis_int_load(ppc)(lwzux,rA_addr|rD_addr)\n");
4546ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            return False;
4547ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         }
4548ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         DIP("lwzux r%u,r%u,r%u\n", rD_addr, rA_addr, rB_addr);
4549ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         val = loadBE(Ity_I32, mkexpr(EA));
4550ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         putIReg( rD_addr, mkWidenFrom32(ty, val, False) );
4551ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         putIReg( rA_addr, mkexpr(EA) );
4552ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         break;
4553ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
4554ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case 0x017: // lwzx (Load W & Zero, Indexed, PPC32 p463)
4555ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         DIP("lwzx r%u,r%u,r%u\n", rD_addr, rA_addr, rB_addr);
4556ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         val = loadBE(Ity_I32, mkexpr(EA));
4557ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         putIReg( rD_addr, mkWidenFrom32(ty, val, False) );
4558ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         break;
4559ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
4560ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
4561ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* 64bit Loads */
4562ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case 0x035: // ldux (Load DWord, Update Indexed, PPC64 p475)
4563ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         if (rA_addr == 0 || rA_addr == rD_addr) {
4564ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            vex_printf("dis_int_load(ppc)(ldux,rA_addr|rD_addr)\n");
4565ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            return False;
4566ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         }
4567ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         DIP("ldux r%u,r%u,r%u\n", rD_addr, rA_addr, rB_addr);
4568ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         putIReg( rD_addr, loadBE(Ity_I64, mkexpr(EA)) );
4569ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         putIReg( rA_addr, mkexpr(EA) );
4570ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         break;
4571ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
4572ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case 0x015: // ldx (Load DWord, Indexed, PPC64 p476)
4573ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         DIP("ldx r%u,r%u,r%u\n", rD_addr, rA_addr, rB_addr);
4574ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         putIReg( rD_addr, loadBE(Ity_I64, mkexpr(EA)) );
4575ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         break;
4576ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
4577ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case 0x175: // lwaux (Load W Alg, Update Indexed, PPC64 p501)
4578ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         if (rA_addr == 0 || rA_addr == rD_addr) {
4579ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            vex_printf("dis_int_load(ppc)(lwaux,rA_addr|rD_addr)\n");
4580ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            return False;
4581ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         }
4582ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         DIP("lwaux r%u,r%u,r%u\n", rD_addr, rA_addr, rB_addr);
4583ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         putIReg( rD_addr,
4584ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  unop(Iop_32Sto64, loadBE(Ity_I32, mkexpr(EA))) );
4585ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         putIReg( rA_addr, mkexpr(EA) );
4586ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         break;
4587ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
4588ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case 0x155: // lwax (Load W Alg, Indexed, PPC64 p502)
4589ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         DIP("lwax r%u,r%u,r%u\n", rD_addr, rA_addr, rB_addr);
4590ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         putIReg( rD_addr,
4591ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  unop(Iop_32Sto64, loadBE(Ity_I32, mkexpr(EA))) );
4592ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         break;
4593ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
4594ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      default:
4595ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         vex_printf("dis_int_load(ppc)(opc2)\n");
4596ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return False;
4597ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
4598ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      break;
4599ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
4600ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* DS Form - 64bit Loads.  In each case EA will have been formed
4601ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      with the lowest 2 bits masked off the immediate offset. */
4602ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   case 0x3A:
4603ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      switch ((b1<<1) | b0) {
4604ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case 0x0: // ld (Load DWord, PPC64 p472)
4605ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         DIP("ld r%u,%d(r%u)\n", rD_addr, simm16, rA_addr);
4606ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         putIReg( rD_addr, loadBE(Ity_I64, mkexpr(EA)) );
4607ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         break;
4608ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
4609ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case 0x1: // ldu (Load DWord, Update, PPC64 p474)
4610ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         if (rA_addr == 0 || rA_addr == rD_addr) {
4611ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            vex_printf("dis_int_load(ppc)(ldu,rA_addr|rD_addr)\n");
4612ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            return False;
4613ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         }
4614ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         DIP("ldu r%u,%d(r%u)\n", rD_addr, simm16, rA_addr);
4615ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         putIReg( rD_addr, loadBE(Ity_I64, mkexpr(EA)) );
4616ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         putIReg( rA_addr, mkexpr(EA) );
4617ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         break;
4618ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
4619ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case 0x2: // lwa (Load Word Alg, PPC64 p499)
4620ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         DIP("lwa r%u,%d(r%u)\n", rD_addr, simm16, rA_addr);
4621ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         putIReg( rD_addr,
4622ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  unop(Iop_32Sto64, loadBE(Ity_I32, mkexpr(EA))) );
4623ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         break;
4624ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
4625ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      default:
4626ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         vex_printf("dis_int_load(ppc)(0x3A, opc2)\n");
4627ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return False;
4628ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
4629ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      break;
4630ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
4631ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   default:
4632ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      vex_printf("dis_int_load(ppc)(opc1)\n");
4633ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      return False;
4634ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
4635ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   return True;
4636ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
4637ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
4638ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
4639ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
4640ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*
4641ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  Integer Store Instructions
4642ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown*/
4643ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic Bool dis_int_store ( UInt theInstr, VexAbiInfo* vbi )
4644ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
4645ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* D-Form, X-Form, DS-Form */
4646ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   UChar opc1    = ifieldOPC(theInstr);
4647ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   UInt  rS_addr = ifieldRegDS(theInstr);
4648ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   UInt  rA_addr = ifieldRegA(theInstr);
4649ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   UInt  uimm16  = ifieldUIMM16(theInstr);
4650ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   UInt  rB_addr = ifieldRegB(theInstr);
4651ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   UInt  opc2    = ifieldOPClo10(theInstr);
4652ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   UChar b1      = ifieldBIT1(theInstr);
4653ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   UChar b0      = ifieldBIT0(theInstr);
4654ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
4655ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   Int    simm16 = extend_s_16to32(uimm16);
4656ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   IRType ty     = mode64 ? Ity_I64 : Ity_I32;
4657ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   IRTemp rS     = newTemp(ty);
4658ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   IRTemp rB     = newTemp(ty);
4659ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   IRTemp EA     = newTemp(ty);
4660ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
4661ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   assign( rB, getIReg(rB_addr) );
4662ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   assign( rS, getIReg(rS_addr) );
4663ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
4664ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   switch (opc1) {
4665ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   case 0x1F: // register offset
4666ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      assign( EA, ea_rAor0_idxd( rA_addr, rB_addr ) );
4667ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      break;
4668ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   case 0x3E: // immediate offset: 64bit: std/stdu: mask off
4669ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown              // lowest 2 bits of immediate before forming EA
4670ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      simm16 = simm16 & 0xFFFFFFFC;
4671ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   default:   // immediate offset
4672ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      assign( EA, ea_rAor0_simm( rA_addr, simm16  ) );
4673ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      break;
4674ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
4675ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
4676ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   switch (opc1) {
4677ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   case 0x26: // stb (Store B, PPC32 p509)
4678ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      DIP("stb r%u,%d(r%u)\n", rS_addr, simm16, rA_addr);
4679ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      storeBE( mkexpr(EA), mkNarrowTo8(ty, mkexpr(rS)) );
4680ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      break;
4681ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
4682ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   case 0x27: // stbu (Store B, Update, PPC32 p510)
4683ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (rA_addr == 0 ) {
4684ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         vex_printf("dis_int_store(ppc)(stbu,rA_addr)\n");
4685ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return False;
4686ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
4687ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      DIP("stbu r%u,%d(r%u)\n", rS_addr, simm16, rA_addr);
4688ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      putIReg( rA_addr, mkexpr(EA) );
4689ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      storeBE( mkexpr(EA), mkNarrowTo8(ty, mkexpr(rS)) );
4690ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      break;
4691ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
4692ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   case 0x2C: // sth (Store HW, PPC32 p522)
4693ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      DIP("sth r%u,%d(r%u)\n", rS_addr, simm16, rA_addr);
4694ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      storeBE( mkexpr(EA), mkNarrowTo16(ty, mkexpr(rS)) );
4695ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      break;
4696ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
4697ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   case 0x2D: // sthu (Store HW, Update, PPC32 p524)
4698ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (rA_addr == 0) {
4699ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         vex_printf("dis_int_store(ppc)(sthu,rA_addr)\n");
4700ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return False;
4701ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
4702ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      DIP("sthu r%u,%d(r%u)\n", rS_addr, simm16, rA_addr);
4703ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      putIReg( rA_addr, mkexpr(EA) );
4704ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      storeBE( mkexpr(EA), mkNarrowTo16(ty, mkexpr(rS)) );
4705ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      break;
4706ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
4707ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   case 0x24: // stw (Store W, PPC32 p530)
4708ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      DIP("stw r%u,%d(r%u)\n", rS_addr, simm16, rA_addr);
4709ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      storeBE( mkexpr(EA), mkNarrowTo32(ty, mkexpr(rS)) );
4710ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      break;
4711ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
4712ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   case 0x25: // stwu (Store W, Update, PPC32 p534)
4713ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (rA_addr == 0) {
4714ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         vex_printf("dis_int_store(ppc)(stwu,rA_addr)\n");
4715ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return False;
4716ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
4717ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      DIP("stwu r%u,%d(r%u)\n", rS_addr, simm16, rA_addr);
4718ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      putIReg( rA_addr, mkexpr(EA) );
4719ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      storeBE( mkexpr(EA), mkNarrowTo32(ty, mkexpr(rS)) );
4720ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      break;
4721ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
4722ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* X Form : all these use EA_indexed */
4723ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   case 0x1F:
4724ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (b0 != 0) {
4725ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         vex_printf("dis_int_store(ppc)(0x1F,b0)\n");
4726ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return False;
4727ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
4728ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
4729ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      switch (opc2) {
4730ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case 0x0F7: // stbux (Store B, Update Indexed, PPC32 p511)
4731ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         if (rA_addr == 0) {
4732ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            vex_printf("dis_int_store(ppc)(stbux,rA_addr)\n");
4733ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            return False;
4734ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         }
4735ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         DIP("stbux r%u,r%u,r%u\n", rS_addr, rA_addr, rB_addr);
4736ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         putIReg( rA_addr, mkexpr(EA) );
4737ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         storeBE( mkexpr(EA), mkNarrowTo8(ty, mkexpr(rS)) );
4738ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         break;
4739ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
4740ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case 0x0D7: // stbx (Store B Indexed, PPC32 p512)
4741ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         DIP("stbx r%u,r%u,r%u\n", rS_addr, rA_addr, rB_addr);
4742ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         storeBE( mkexpr(EA), mkNarrowTo8(ty, mkexpr(rS)) );
4743ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         break;
4744ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
4745ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case 0x1B7: // sthux (Store HW, Update Indexed, PPC32 p525)
4746ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         if (rA_addr == 0) {
4747ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            vex_printf("dis_int_store(ppc)(sthux,rA_addr)\n");
4748ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            return False;
4749ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         }
4750ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         DIP("sthux r%u,r%u,r%u\n", rS_addr, rA_addr, rB_addr);
4751ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         putIReg( rA_addr, mkexpr(EA) );
4752ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         storeBE( mkexpr(EA), mkNarrowTo16(ty, mkexpr(rS)) );
4753ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         break;
4754ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
4755ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case 0x197: // sthx (Store HW Indexed, PPC32 p526)
4756ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         DIP("sthx r%u,r%u,r%u\n", rS_addr, rA_addr, rB_addr);
4757ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         storeBE( mkexpr(EA), mkNarrowTo16(ty, mkexpr(rS)) );
4758ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         break;
4759ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
4760ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case 0x0B7: // stwux (Store W, Update Indexed, PPC32 p535)
4761ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         if (rA_addr == 0) {
4762ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            vex_printf("dis_int_store(ppc)(stwux,rA_addr)\n");
4763ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            return False;
4764ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         }
4765ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         DIP("stwux r%u,r%u,r%u\n", rS_addr, rA_addr, rB_addr);
4766ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         putIReg( rA_addr, mkexpr(EA) );
4767ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         storeBE( mkexpr(EA), mkNarrowTo32(ty, mkexpr(rS)) );
4768ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         break;
4769ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
4770ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case 0x097: // stwx (Store W Indexed, PPC32 p536)
4771ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         DIP("stwx r%u,r%u,r%u\n", rS_addr, rA_addr, rB_addr);
4772ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         storeBE( mkexpr(EA), mkNarrowTo32(ty, mkexpr(rS)) );
4773ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         break;
4774ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
4775ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
4776ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* 64bit Stores */
4777ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case 0x0B5: // stdux (Store DWord, Update Indexed, PPC64 p584)
4778ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         if (rA_addr == 0) {
4779ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            vex_printf("dis_int_store(ppc)(stdux,rA_addr)\n");
4780ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            return False;
4781ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         }
4782ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         DIP("stdux r%u,r%u,r%u\n", rS_addr, rA_addr, rB_addr);
4783ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         putIReg( rA_addr, mkexpr(EA) );
4784ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         storeBE( mkexpr(EA), mkexpr(rS) );
4785ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         break;
4786ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
4787ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case 0x095: // stdx (Store DWord Indexed, PPC64 p585)
4788ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         DIP("stdx r%u,r%u,r%u\n", rS_addr, rA_addr, rB_addr);
4789ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         storeBE( mkexpr(EA), mkexpr(rS) );
4790ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         break;
4791ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
4792ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      default:
4793ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         vex_printf("dis_int_store(ppc)(opc2)\n");
4794ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return False;
4795ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
4796ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      break;
4797ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
4798ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* DS Form - 64bit Stores.  In each case EA will have been formed
4799ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      with the lowest 2 bits masked off the immediate offset. */
4800ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   case 0x3E:
4801ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      switch ((b1<<1) | b0) {
4802ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case 0x0: // std (Store DWord, PPC64 p580)
4803ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         DIP("std r%u,%d(r%u)\n", rS_addr, simm16, rA_addr);
4804ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         storeBE( mkexpr(EA), mkexpr(rS) );
4805ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         break;
4806ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
4807ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case 0x1: // stdu (Store DWord, Update, PPC64 p583)
4808ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         DIP("stdu r%u,%d(r%u)\n", rS_addr, simm16, rA_addr);
4809ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         putIReg( rA_addr, mkexpr(EA) );
4810ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         storeBE( mkexpr(EA), mkexpr(rS) );
4811ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         break;
4812ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
4813ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      default:
4814ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         vex_printf("dis_int_load(ppc)(0x3A, opc2)\n");
4815ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return False;
4816ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
4817ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      break;
4818ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
4819ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   default:
4820ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      vex_printf("dis_int_store(ppc)(opc1)\n");
4821ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      return False;
4822ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
4823ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   return True;
4824ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
4825ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
4826ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
4827ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
4828ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*
4829ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  Integer Load/Store Multiple Instructions
4830ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown*/
4831ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic Bool dis_int_ldst_mult ( UInt theInstr )
4832ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
4833ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* D-Form */
4834ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   UChar opc1     = ifieldOPC(theInstr);
4835ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   UChar rD_addr  = ifieldRegDS(theInstr);
4836ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   UChar rS_addr  = rD_addr;
4837ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   UChar rA_addr  = ifieldRegA(theInstr);
4838ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   UInt  uimm16   = ifieldUIMM16(theInstr);
4839ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
4840ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   Int     simm16 = extend_s_16to32(uimm16);
4841ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   IRType  ty     = mode64 ? Ity_I64 : Ity_I32;
4842ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   IRTemp  EA     = newTemp(ty);
4843ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   UInt    r      = 0;
4844ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   UInt    ea_off = 0;
4845ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   IRExpr* irx_addr;
4846ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
4847ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   assign( EA, ea_rAor0_simm( rA_addr, simm16 ) );
4848ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
4849ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   switch (opc1) {
4850ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   case 0x2E: // lmw (Load Multiple Word, PPC32 p454)
4851ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (rA_addr >= rD_addr) {
4852ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         vex_printf("dis_int_ldst_mult(ppc)(lmw,rA_addr)\n");
4853ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return False;
4854ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
4855ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      DIP("lmw r%u,%d(r%u)\n", rD_addr, simm16, rA_addr);
4856ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      for (r = rD_addr; r <= 31; r++) {
4857ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         irx_addr = binop(Iop_Add32, mkexpr(EA), mkU32(ea_off));
4858ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         putIReg( r, mkWidenFrom32(ty, loadBE(Ity_I32, irx_addr ),
4859ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                       False) );
4860ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         ea_off += 4;
4861ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
4862ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      break;
4863ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
4864ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   case 0x2F: // stmw (Store Multiple Word, PPC32 p527)
4865ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      DIP("stmw r%u,%d(r%u)\n", rS_addr, simm16, rA_addr);
4866ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      for (r = rS_addr; r <= 31; r++) {
4867ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         irx_addr = binop(Iop_Add32, mkexpr(EA), mkU32(ea_off));
4868ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         storeBE( irx_addr, mkNarrowTo32(ty, getIReg(r)) );
4869ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         ea_off += 4;
4870ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
4871ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      break;
4872ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
4873ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   default:
4874ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      vex_printf("dis_int_ldst_mult(ppc)(opc1)\n");
4875ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      return False;
4876ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
4877ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   return True;
4878ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
4879ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
4880ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
4881ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
4882ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*
4883ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  Integer Load/Store String Instructions
4884ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown*/
4885ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic
4886ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid generate_lsw_sequence ( IRTemp tNBytes,   // # bytes, :: Ity_I32
4887ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                             IRTemp EA,        // EA
4888ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                             Int    rD,        // first dst register
4889ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                             Int    maxBytes ) // 32 or 128
4890ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
4891ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   Int     i, shift = 24;
4892ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   IRExpr* e_nbytes = mkexpr(tNBytes);
4893ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   IRExpr* e_EA     = mkexpr(EA);
4894ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   IRType  ty       = mode64 ? Ity_I64 : Ity_I32;
4895ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
4896ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   vassert(rD >= 0 && rD < 32);
4897ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   rD--; if (rD < 0) rD = 31;
4898ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
4899ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   for (i = 0; i < maxBytes; i++) {
4900ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* if (nBytes < (i+1)) goto NIA; */
4901ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      stmt( IRStmt_Exit( binop(Iop_CmpLT32U, e_nbytes, mkU32(i+1)),
4902ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                         Ijk_Boring,
4903ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                         mkSzConst( ty, nextInsnAddr()) ));
4904ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* when crossing into a new dest register, set it to zero. */
4905ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if ((i % 4) == 0) {
4906ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         rD++; if (rD == 32) rD = 0;
4907ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         putIReg(rD, mkSzImm(ty, 0));
4908ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         shift = 24;
4909ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
4910ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* rD |=  (8Uto32(*(EA+i))) << shift */
4911ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      vassert(shift == 0 || shift == 8 || shift == 16 || shift == 24);
4912ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      putIReg(
4913ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         rD,
4914ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         mkWidenFrom32(
4915ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            ty,
4916ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            binop(
4917ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               Iop_Or32,
4918ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               mkNarrowTo32(ty, getIReg(rD)),
4919ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               binop(
4920ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  Iop_Shl32,
4921ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  unop(
4922ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                     Iop_8Uto32,
4923ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                     loadBE(Ity_I8,
4924ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                            binop(mkSzOp(ty,Iop_Add8), e_EA, mkSzImm(ty,i)))
4925ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  ),
4926ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  mkU8(toUChar(shift))
4927ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               )
4928ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            ),
4929ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            /*Signed*/False
4930ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	 )
4931ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      );
4932ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      shift -= 8;
4933ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
4934ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
4935ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
4936ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic
4937ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid generate_stsw_sequence ( IRTemp tNBytes,   // # bytes, :: Ity_I32
4938ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                              IRTemp EA,        // EA
4939ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                              Int    rS,        // first src register
4940ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                              Int    maxBytes ) // 32 or 128
4941ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
4942ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   Int     i, shift = 24;
4943ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   IRExpr* e_nbytes = mkexpr(tNBytes);
4944ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   IRExpr* e_EA     = mkexpr(EA);
4945ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   IRType  ty       = mode64 ? Ity_I64 : Ity_I32;
4946ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
4947ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   vassert(rS >= 0 && rS < 32);
4948ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   rS--; if (rS < 0) rS = 31;
4949ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
4950ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   for (i = 0; i < maxBytes; i++) {
4951ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* if (nBytes < (i+1)) goto NIA; */
4952ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      stmt( IRStmt_Exit( binop(Iop_CmpLT32U, e_nbytes, mkU32(i+1)),
4953ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                         Ijk_Boring,
4954ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                         mkSzConst( ty, nextInsnAddr() ) ));
4955ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* check for crossing into a new src register. */
4956ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if ((i % 4) == 0) {
4957ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         rS++; if (rS == 32) rS = 0;
4958ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         shift = 24;
4959ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
4960ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* *(EA+i) = 32to8(rS >> shift) */
4961ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      vassert(shift == 0 || shift == 8 || shift == 16 || shift == 24);
4962ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      storeBE(
4963ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         binop(mkSzOp(ty,Iop_Add8), e_EA, mkSzImm(ty,i)),
4964ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         unop(Iop_32to8,
4965ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown              binop(Iop_Shr32,
4966ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                    mkNarrowTo32(ty, getIReg(rS)),
4967ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                    mkU8(toUChar(shift))))
4968ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      );
4969ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      shift -= 8;
4970ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
4971ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
4972ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
4973ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic Bool dis_int_ldst_str ( UInt theInstr, /*OUT*/Bool* stopHere )
4974ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
4975ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* X-Form */
4976ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   UChar opc1     = ifieldOPC(theInstr);
4977ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   UChar rD_addr  = ifieldRegDS(theInstr);
4978ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   UChar rS_addr  = rD_addr;
4979ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   UChar rA_addr  = ifieldRegA(theInstr);
4980ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   UChar rB_addr  = ifieldRegB(theInstr);
4981ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   UChar NumBytes = rB_addr;
4982ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   UInt  opc2     = ifieldOPClo10(theInstr);
4983ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   UChar b0       = ifieldBIT0(theInstr);
4984ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
4985ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   IRType ty      = mode64 ? Ity_I64 : Ity_I32;
4986ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   IRTemp t_EA    = newTemp(ty);
4987ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   IRTemp t_nbytes = IRTemp_INVALID;
4988ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
4989ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   *stopHere = False;
4990ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
4991ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (opc1 != 0x1F || b0 != 0) {
4992ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      vex_printf("dis_int_ldst_str(ppc)(opc1)\n");
4993ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      return False;
4994ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
4995ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
4996ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   switch (opc2) {
4997ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   case 0x255: // lswi (Load String Word Immediate, PPC32 p455)
4998ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* NB: does not reject the case where RA is in the range of
4999ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         registers to be loaded.  It should. */
5000ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      DIP("lswi r%u,r%u,%d\n", rD_addr, rA_addr, NumBytes);
5001ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      assign( t_EA, ea_rAor0(rA_addr) );
5002ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (NumBytes == 8 && !mode64) {
5003ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         /* Special case hack */
5004ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         /* rD = Mem[EA]; (rD+1)%32 = Mem[EA+4] */
5005ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         putIReg( rD_addr,
5006ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  loadBE(Ity_I32, mkexpr(t_EA)) );
5007ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         putIReg( (rD_addr+1) % 32,
5008ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  loadBE(Ity_I32,
5009ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                         binop(Iop_Add32, mkexpr(t_EA), mkU32(4))) );
5010ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      } else {
5011ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         t_nbytes = newTemp(Ity_I32);
5012ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         assign( t_nbytes, mkU32(NumBytes==0 ? 32 : NumBytes) );
5013ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         generate_lsw_sequence( t_nbytes, t_EA, rD_addr, 32 );
5014ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         *stopHere = True;
5015ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
5016ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      return True;
5017ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
5018ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   case 0x215: // lswx (Load String Word Indexed, PPC32 p456)
5019ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* NB: does not reject the case where RA is in the range of
5020ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         registers to be loaded.  It should.  Although considering
5021ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         that that can only be detected at run time, it's not easy to
5022ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         do so. */
5023ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (rD_addr == rA_addr || rD_addr == rB_addr)
5024ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return False;
5025ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (rD_addr == 0 && rA_addr == 0)
5026ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return False;
5027ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      DIP("lswx r%u,r%u,r%u\n", rD_addr, rA_addr, rB_addr);
5028ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      t_nbytes = newTemp(Ity_I32);
5029ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      assign( t_EA, ea_rAor0_idxd(rA_addr,rB_addr) );
5030ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      assign( t_nbytes, unop( Iop_8Uto32, getXER_BC() ) );
5031ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      generate_lsw_sequence( t_nbytes, t_EA, rD_addr, 128 );
5032ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      *stopHere = True;
5033ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      return True;
5034ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
5035ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   case 0x2D5: // stswi (Store String Word Immediate, PPC32 p528)
5036ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      DIP("stswi r%u,r%u,%d\n", rS_addr, rA_addr, NumBytes);
5037ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      assign( t_EA, ea_rAor0(rA_addr) );
5038ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (NumBytes == 8 && !mode64) {
5039ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         /* Special case hack */
5040ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         /* Mem[EA] = rD; Mem[EA+4] = (rD+1)%32 */
5041ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         storeBE( mkexpr(t_EA),
5042ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  getIReg(rD_addr) );
5043ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         storeBE( binop(Iop_Add32, mkexpr(t_EA), mkU32(4)),
5044ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  getIReg((rD_addr+1) % 32) );
5045ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      } else {
5046ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         t_nbytes = newTemp(Ity_I32);
5047ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         assign( t_nbytes, mkU32(NumBytes==0 ? 32 : NumBytes) );
5048ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         generate_stsw_sequence( t_nbytes, t_EA, rD_addr, 32 );
5049ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         *stopHere = True;
5050ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
5051ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      return True;
5052ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
5053ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   case 0x295: // stswx (Store String Word Indexed, PPC32 p529)
5054ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      DIP("stswx r%u,r%u,r%u\n", rS_addr, rA_addr, rB_addr);
5055ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      t_nbytes = newTemp(Ity_I32);
5056ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      assign( t_EA, ea_rAor0_idxd(rA_addr,rB_addr) );
5057ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      assign( t_nbytes, unop( Iop_8Uto32, getXER_BC() ) );
5058ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      generate_stsw_sequence( t_nbytes, t_EA, rS_addr, 128 );
5059ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      *stopHere = True;
5060ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      return True;
5061ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
5062ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   default:
5063ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      vex_printf("dis_int_ldst_str(ppc)(opc2)\n");
5064ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      return False;
5065ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
5066ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   return True;
5067ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
5068ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
5069ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
5070ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* ------------------------------------------------------------------
5071ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   Integer Branch Instructions
5072ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   ------------------------------------------------------------------ */
5073ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
5074ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*
5075ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  Branch helper function
5076ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  ok = BO[2] | ((CTR[0] != 0) ^ BO[1])
5077ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  Returns an I32 which is 0x00000000 if the ctr condition failed
5078ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  and 0xFFFFFFFF otherwise.
5079ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown*/
5080ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic IRExpr* /* :: Ity_I32 */ branch_ctr_ok( UInt BO )
5081ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
5082ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   IRType ty = mode64 ? Ity_I64 : Ity_I32;
5083ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   IRTemp ok = newTemp(Ity_I32);
5084ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
5085ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if ((BO >> 2) & 1) {     // independent of ctr
5086ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      assign( ok, mkU32(0xFFFFFFFF) );
5087ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   } else {
5088ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if ((BO >> 1) & 1) {  // ctr == 0 ?
5089ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         assign( ok, unop( Iop_1Sto32,
5090ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                           binop( mkSzOp(ty, Iop_CmpEQ8),
5091ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                  getGST( PPC_GST_CTR ),
5092ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                  mkSzImm(ty,0))) );
5093ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      } else {              // ctr != 0 ?
5094ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         assign( ok, unop( Iop_1Sto32,
5095ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                           binop( mkSzOp(ty, Iop_CmpNE8),
5096ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                  getGST( PPC_GST_CTR ),
5097ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                  mkSzImm(ty,0))) );
5098ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
5099ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
5100ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   return mkexpr(ok);
5101ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
5102ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
5103ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
5104ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*
5105ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  Branch helper function cond_ok = BO[4] | (CR[BI] == BO[3])
5106ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  Returns an I32 which is either 0 if the condition failed or
5107ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  some arbitrary nonzero value otherwise. */
5108ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
5109ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic IRExpr* /* :: Ity_I32 */ branch_cond_ok( UInt BO, UInt BI )
5110ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
5111ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   Int where;
5112ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   IRTemp res   = newTemp(Ity_I32);
5113ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   IRTemp cr_bi = newTemp(Ity_I32);
5114ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
5115ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if ((BO >> 4) & 1) {
5116ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      assign( res, mkU32(1) );
5117ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   } else {
5118ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      // ok = (CR[BI] == BO[3]) Note, the following relies on
5119ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      // getCRbit_anywhere returning a value which
5120ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      // is either zero or has exactly 1 bit set.
5121ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      assign( cr_bi, getCRbit_anywhere( BI, &where ) );
5122ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
5123ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if ((BO >> 3) & 1) {
5124ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         /* We can use cr_bi as-is. */
5125ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         assign( res, mkexpr(cr_bi) );
5126ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      } else {
5127ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         /* We have to invert the sense of the information held in
5128ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            cr_bi.  For that we need to know which bit
5129ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            getCRbit_anywhere regards as significant. */
5130ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         assign( res, binop(Iop_Xor32, mkexpr(cr_bi),
5131ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                       mkU32(1<<where)) );
5132ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
5133ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
5134ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   return mkexpr(res);
5135ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
5136ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
5137ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
5138ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*
5139ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  Integer Branch Instructions
5140ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown*/
5141ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic Bool dis_branch ( UInt theInstr,
5142ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                         VexAbiInfo* vbi,
5143ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                         /*OUT*/DisResult* dres,
5144ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                         Bool (*resteerOkFn)(void*,Addr64),
5145ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                         void* callback_opaque )
5146ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
5147ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   UChar opc1    = ifieldOPC(theInstr);
5148ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   UChar BO      = ifieldRegDS(theInstr);
5149ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   UChar BI      = ifieldRegA(theInstr);
5150ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   UInt  BD_u16  = ifieldUIMM16(theInstr) & 0xFFFFFFFC; /* mask off */
5151ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   UChar b11to15 = ifieldRegB(theInstr);
5152ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   UInt  opc2    = ifieldOPClo10(theInstr);
5153ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   UInt  LI_u26  = ifieldUIMM26(theInstr) & 0xFFFFFFFC; /* mask off */
5154ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   UChar flag_AA = ifieldBIT1(theInstr);
5155ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   UChar flag_LK = ifieldBIT0(theInstr);
5156ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
5157ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   IRType   ty        = mode64 ? Ity_I64 : Ity_I32;
5158ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   Addr64   tgt       = 0;
5159ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   Int      BD        = extend_s_16to32(BD_u16);
5160ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   IRTemp   do_branch = newTemp(Ity_I32);
5161ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   IRTemp   ctr_ok    = newTemp(Ity_I32);
5162ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   IRTemp   cond_ok   = newTemp(Ity_I32);
5163ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   IRExpr*  e_nia     = mkSzImm(ty, nextInsnAddr());
5164ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   IRConst* c_nia     = mkSzConst(ty, nextInsnAddr());
5165ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   IRTemp   lr_old    = newTemp(ty);
5166ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
5167ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* Hack to pass through code that just wants to read the PC */
5168ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (theInstr == 0x429F0005) {
5169ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      DIP("bcl 0x%x, 0x%x (a.k.a mr lr,cia+4)\n", BO, BI);
5170ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      putGST( PPC_GST_LR, e_nia );
5171ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      return True;
5172ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
5173ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
5174ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* The default what-next.  Individual cases can override it. */
5175ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   dres->whatNext = Dis_StopHere;
5176ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
5177ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   switch (opc1) {
5178ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   case 0x12: // b     (Branch, PPC32 p360)
5179ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (flag_AA) {
5180ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         tgt = mkSzAddr( ty, extend_s_26to64(LI_u26) );
5181ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      } else {
5182ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         tgt = mkSzAddr( ty, guest_CIA_curr_instr +
5183ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                             (Long)extend_s_26to64(LI_u26) );
5184ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
5185ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (mode64) {
5186ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         DIP("b%s%s 0x%llx\n",
5187ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown             flag_LK ? "l" : "", flag_AA ? "a" : "", tgt);
5188ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      } else {
5189ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         DIP("b%s%s 0x%x\n",
5190ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown             flag_LK ? "l" : "", flag_AA ? "a" : "", (Addr32)tgt);
5191ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
5192ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
5193ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (flag_LK) {
5194ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         putGST( PPC_GST_LR, e_nia );
5195ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         if (vbi->guest_ppc_zap_RZ_at_bl
5196ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown             && vbi->guest_ppc_zap_RZ_at_bl( (ULong)tgt) ) {
5197ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            IRTemp t_tgt = newTemp(ty);
5198ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            assign(t_tgt, mode64 ? mkU64(tgt) : mkU32(tgt) );
5199ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            make_redzone_AbiHint( vbi, t_tgt,
5200ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                  "branch-and-link (unconditional call)" );
5201ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         }
5202ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
5203ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
5204ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (resteerOkFn( callback_opaque, tgt )) {
5205ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         dres->whatNext   = Dis_ResteerU;
5206ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         dres->continueAt = tgt;
5207ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      } else {
5208ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         irsb->jumpkind = flag_LK ? Ijk_Call : Ijk_Boring;
5209ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         irsb->next     = mkSzImm(ty, tgt);
5210ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
5211ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      break;
5212ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
5213ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   case 0x10: // bc    (Branch Conditional, PPC32 p361)
5214ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      DIP("bc%s%s 0x%x, 0x%x, 0x%x\n",
5215ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown          flag_LK ? "l" : "", flag_AA ? "a" : "", BO, BI, BD);
5216ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
5217ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (!(BO & 0x4)) {
5218ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         putGST( PPC_GST_CTR,
5219ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                 binop(mkSzOp(ty, Iop_Sub8),
5220ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                       getGST( PPC_GST_CTR ), mkSzImm(ty, 1)) );
5221ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
5222ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
5223ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* This is a bit subtle.  ctr_ok is either all 0s or all 1s.
5224ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         cond_ok is either zero or nonzero, since that's the cheapest
5225ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         way to compute it.  Anding them together gives a value which
5226ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         is either zero or non zero and so that's what we must test
5227ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         for in the IRStmt_Exit. */
5228ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      assign( ctr_ok,  branch_ctr_ok( BO ) );
5229ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      assign( cond_ok, branch_cond_ok( BO, BI ) );
5230ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      assign( do_branch,
5231ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown              binop(Iop_And32, mkexpr(cond_ok), mkexpr(ctr_ok)) );
5232ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
5233ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (flag_AA) {
5234ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         tgt = mkSzAddr(ty, extend_s_16to64(BD_u16));
5235ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      } else {
5236ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         tgt = mkSzAddr(ty, guest_CIA_curr_instr +
5237ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                            (Long)extend_s_16to64(BD_u16));
5238ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
5239ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (flag_LK)
5240ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         putGST( PPC_GST_LR, e_nia );
5241ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
5242ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      stmt( IRStmt_Exit(
5243ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               binop(Iop_CmpNE32, mkexpr(do_branch), mkU32(0)),
5244ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               flag_LK ? Ijk_Call : Ijk_Boring,
5245ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               mkSzConst(ty, tgt) ) );
5246ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
5247ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      irsb->jumpkind = Ijk_Boring;
5248ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      irsb->next     = e_nia;
5249ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      break;
5250ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
5251ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   case 0x13:
5252ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* For bclr and bcctr, it appears that the lowest two bits of
5253ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         b11to15 are a branch hint, and so we only need to ensure it's
5254ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         of the form 000XX. */
5255ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if ((b11to15 & ~3) != 0) {
5256ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         vex_printf("dis_int_branch(ppc)(0x13,b11to15)(%d)\n", (Int)b11to15);
5257ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return False;
5258ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
5259ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
5260ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      switch (opc2) {
5261ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case 0x210: // bcctr (Branch Cond. to Count Register, PPC32 p363)
5262ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         if ((BO & 0x4) == 0) { // "decr and test CTR" option invalid
5263ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            vex_printf("dis_int_branch(ppc)(bcctr,BO)\n");
5264ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            return False;
5265ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         }
5266ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         DIP("bcctr%s 0x%x, 0x%x\n", flag_LK ? "l" : "", BO, BI);
5267ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
5268ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         assign( cond_ok, branch_cond_ok( BO, BI ) );
5269ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
5270ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         /* FIXME: this is confusing.  lr_old holds the old value
5271ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            of ctr, not lr :-) */
5272ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         assign( lr_old, addr_align( getGST( PPC_GST_CTR ), 4 ));
5273ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
5274ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         if (flag_LK)
5275ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            putGST( PPC_GST_LR, e_nia );
5276ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
5277ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         stmt( IRStmt_Exit(
5278ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  binop(Iop_CmpEQ32, mkexpr(cond_ok), mkU32(0)),
5279ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  Ijk_Boring,
5280ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  c_nia ));
5281ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
5282ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         if (flag_LK && vbi->guest_ppc_zap_RZ_at_bl) {
5283ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            make_redzone_AbiHint( vbi, lr_old,
5284ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                  "b-ctr-l (indirect call)" );
5285ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	 }
5286ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
5287ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         irsb->jumpkind = flag_LK ? Ijk_Call : Ijk_Boring;
5288ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         irsb->next     = mkexpr(lr_old);
5289ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         break;
5290ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
5291ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case 0x010: { // bclr (Branch Cond. to Link Register, PPC32 p365)
5292ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         Bool vanilla_return = False;
5293ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         if ((BO & 0x14 /* 1z1zz */) == 0x14 && flag_LK == 0) {
5294ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            DIP("blr\n");
5295ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            vanilla_return = True;
5296ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         } else {
5297ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            DIP("bclr%s 0x%x, 0x%x\n", flag_LK ? "l" : "", BO, BI);
5298ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         }
5299ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
5300ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         if (!(BO & 0x4)) {
5301ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            putGST( PPC_GST_CTR,
5302ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                    binop(mkSzOp(ty, Iop_Sub8),
5303ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                          getGST( PPC_GST_CTR ), mkSzImm(ty, 1)) );
5304ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         }
5305ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
5306ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         /* See comments above for 'bc' about this */
5307ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         assign( ctr_ok,  branch_ctr_ok( BO ) );
5308ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         assign( cond_ok, branch_cond_ok( BO, BI ) );
5309ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         assign( do_branch,
5310ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                 binop(Iop_And32, mkexpr(cond_ok), mkexpr(ctr_ok)) );
5311ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
5312ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         assign( lr_old, addr_align( getGST( PPC_GST_LR ), 4 ));
5313ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
5314ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         if (flag_LK)
5315ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            putGST( PPC_GST_LR,  e_nia );
5316ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
5317ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         stmt( IRStmt_Exit(
5318ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  binop(Iop_CmpEQ32, mkexpr(do_branch), mkU32(0)),
5319ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  Ijk_Boring,
5320ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  c_nia ));
5321ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
5322ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         if (vanilla_return && vbi->guest_ppc_zap_RZ_at_blr) {
5323ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            make_redzone_AbiHint( vbi, lr_old,
5324ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                  "branch-to-lr (unconditional return)" );
5325ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         }
5326ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
5327ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         /* blrl is pretty strange; it's like a return that sets the
5328ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            return address of its caller to the insn following this
5329ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            one.  Mark it as a return. */
5330ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         irsb->jumpkind = Ijk_Ret;  /* was flag_LK ? Ijk_Call : Ijk_Ret; */
5331ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         irsb->next     = mkexpr(lr_old);
5332ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         break;
5333ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
5334ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      default:
5335ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         vex_printf("dis_int_branch(ppc)(opc2)\n");
5336ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return False;
5337ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
5338ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      break;
5339ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
5340ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   default:
5341ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      vex_printf("dis_int_branch(ppc)(opc1)\n");
5342ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      return False;
5343ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
5344ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
5345ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   return True;
5346ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
5347ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
5348ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
5349ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
5350ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*
5351ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  Condition Register Logical Instructions
5352ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown*/
5353ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic Bool dis_cond_logic ( UInt theInstr )
5354ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
5355ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* XL-Form */
5356ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   UChar opc1      = ifieldOPC(theInstr);
5357ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   UChar crbD_addr = ifieldRegDS(theInstr);
5358ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   UChar crfD_addr = toUChar( IFIELD(theInstr, 23, 3) );
5359ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   UChar crbA_addr = ifieldRegA(theInstr);
5360ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   UChar crfS_addr = toUChar( IFIELD(theInstr, 18, 3) );
5361ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   UChar crbB_addr = ifieldRegB(theInstr);
5362ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   UInt  opc2      = ifieldOPClo10(theInstr);
5363ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   UChar b0        = ifieldBIT0(theInstr);
5364ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
5365ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   IRTemp crbD     = newTemp(Ity_I32);
5366ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   IRTemp crbA     = newTemp(Ity_I32);
5367ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   IRTemp crbB     = newTemp(Ity_I32);
5368ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
5369ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (opc1 != 19 || b0 != 0) {
5370ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      vex_printf("dis_cond_logic(ppc)(opc1)\n");
5371ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      return False;
5372ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
5373ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
5374ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (opc2 == 0) {  // mcrf    (Move Cond Reg Field, PPC32 p464)
5375ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (((crbD_addr & 0x3) != 0) ||
5376ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown          ((crbA_addr & 0x3) != 0) || (crbB_addr != 0)) {
5377ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         vex_printf("dis_cond_logic(ppc)(crbD|crbA|crbB != 0)\n");
5378ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return False;
5379ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
5380ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      DIP("mcrf cr%u,cr%u\n", crfD_addr, crfS_addr);
5381ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      putCR0(   crfD_addr, getCR0(  crfS_addr) );
5382ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      putCR321( crfD_addr, getCR321(crfS_addr) );
5383ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   } else {
5384ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      assign( crbA, getCRbit(crbA_addr) );
5385ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (crbA_addr == crbB_addr)
5386ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         crbB = crbA;
5387ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      else
5388ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         assign( crbB, getCRbit(crbB_addr) );
5389ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
5390ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      switch (opc2) {
5391ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case 0x101: // crand   (Cond Reg AND, PPC32 p372)
5392ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         DIP("crand crb%d,crb%d,crb%d\n", crbD_addr, crbA_addr, crbB_addr);
5393ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         assign( crbD, binop(Iop_And32, mkexpr(crbA), mkexpr(crbB)) );
5394ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         break;
5395ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case 0x081: // crandc  (Cond Reg AND w. Complement, PPC32 p373)
5396ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         DIP("crandc crb%d,crb%d,crb%d\n", crbD_addr, crbA_addr, crbB_addr);
5397ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         assign( crbD, binop(Iop_And32,
5398ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                             mkexpr(crbA),
5399ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                             unop(Iop_Not32, mkexpr(crbB))) );
5400ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         break;
5401ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case 0x121: // creqv   (Cond Reg Equivalent, PPC32 p374)
5402ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         DIP("creqv crb%d,crb%d,crb%d\n", crbD_addr, crbA_addr, crbB_addr);
5403ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         assign( crbD, unop(Iop_Not32,
5404ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                            binop(Iop_Xor32, mkexpr(crbA), mkexpr(crbB))) );
5405ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         break;
5406ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case 0x0E1: // crnand  (Cond Reg NAND, PPC32 p375)
5407ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         DIP("crnand crb%d,crb%d,crb%d\n", crbD_addr, crbA_addr, crbB_addr);
5408ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         assign( crbD, unop(Iop_Not32,
5409ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                            binop(Iop_And32, mkexpr(crbA), mkexpr(crbB))) );
5410ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         break;
5411ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case 0x021: // crnor   (Cond Reg NOR, PPC32 p376)
5412ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         DIP("crnor crb%d,crb%d,crb%d\n", crbD_addr, crbA_addr, crbB_addr);
5413ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         assign( crbD, unop(Iop_Not32,
5414ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                            binop(Iop_Or32, mkexpr(crbA), mkexpr(crbB))) );
5415ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         break;
5416ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case 0x1C1: // cror    (Cond Reg OR, PPC32 p377)
5417ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         DIP("cror crb%d,crb%d,crb%d\n", crbD_addr, crbA_addr, crbB_addr);
5418ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         assign( crbD, binop(Iop_Or32, mkexpr(crbA), mkexpr(crbB)) );
5419ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         break;
5420ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case 0x1A1: // crorc   (Cond Reg OR w. Complement, PPC32 p378)
5421ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         DIP("crorc crb%d,crb%d,crb%d\n", crbD_addr, crbA_addr, crbB_addr);
5422ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         assign( crbD, binop(Iop_Or32,
5423ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                             mkexpr(crbA),
5424ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                             unop(Iop_Not32, mkexpr(crbB))) );
5425ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         break;
5426ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case 0x0C1: // crxor   (Cond Reg XOR, PPC32 p379)
5427ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         DIP("crxor crb%d,crb%d,crb%d\n", crbD_addr, crbA_addr, crbB_addr);
5428ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         assign( crbD, binop(Iop_Xor32, mkexpr(crbA), mkexpr(crbB)) );
5429ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         break;
5430ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      default:
5431ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         vex_printf("dis_cond_logic(ppc)(opc2)\n");
5432ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return False;
5433ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
5434ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
5435ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      putCRbit( crbD_addr, mkexpr(crbD) );
5436ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
5437ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   return True;
5438ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
5439ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
5440ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
5441ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*
5442ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  Trap instructions
5443ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown*/
5444ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
5445ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* Do the code generation for a trap.  Returned Bool is true iff
5446ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   this is an unconditional trap.  If the two arg IRExpr*s are
5447ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   Ity_I32s then the comparison is 32-bit.  If they are Ity_I64s
5448ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   then they are 64-bit, and we must be disassembling 64-bit
5449ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   instructions. */
5450ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic Bool do_trap ( UChar TO,
5451ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                      IRExpr* argL0, IRExpr* argR0, Addr64 cia )
5452ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
5453ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   IRTemp argL, argR;
5454ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   IRExpr *argLe, *argRe, *cond, *tmp;
5455ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
5456ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   Bool    is32bit = typeOfIRExpr(irsb->tyenv, argL0 ) == Ity_I32;
5457ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
5458ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   IROp    opAND     = is32bit ? Iop_And32     : Iop_And64;
5459ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   IROp    opOR      = is32bit ? Iop_Or32      : Iop_Or64;
5460ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   IROp    opCMPORDS = is32bit ? Iop_CmpORD32S : Iop_CmpORD64S;
5461ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   IROp    opCMPORDU = is32bit ? Iop_CmpORD32U : Iop_CmpORD64U;
5462ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   IROp    opCMPNE   = is32bit ? Iop_CmpNE32   : Iop_CmpNE64;
5463ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   IROp    opCMPEQ   = is32bit ? Iop_CmpEQ32   : Iop_CmpEQ64;
5464ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   IRExpr* const0    = is32bit ? mkU32(0)      : mkU64(0);
5465ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   IRExpr* const2    = is32bit ? mkU32(2)      : mkU64(2);
5466ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   IRExpr* const4    = is32bit ? mkU32(4)      : mkU64(4);
5467ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   IRExpr* const8    = is32bit ? mkU32(8)      : mkU64(8);
5468ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
5469ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   const UChar b11100 = 0x1C;
5470ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   const UChar b00111 = 0x07;
5471ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
5472ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (is32bit) {
5473ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      vassert( typeOfIRExpr(irsb->tyenv, argL0) == Ity_I32 );
5474ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      vassert( typeOfIRExpr(irsb->tyenv, argR0) == Ity_I32 );
5475ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   } else {
5476ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      vassert( typeOfIRExpr(irsb->tyenv, argL0) == Ity_I64 );
5477ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      vassert( typeOfIRExpr(irsb->tyenv, argR0) == Ity_I64 );
5478ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      vassert( mode64 );
5479ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
5480ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
5481ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if ((TO & b11100) == b11100 || (TO & b00111) == b00111) {
5482ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* Unconditional trap.  Just do the exit without
5483ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         testing the arguments. */
5484ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      stmt( IRStmt_Exit(
5485ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               binop(opCMPEQ, const0, const0),
5486ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               Ijk_SigTRAP,
5487ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               mode64 ? IRConst_U64(cia) : IRConst_U32((UInt)cia)
5488ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      ));
5489ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      return True; /* unconditional trap */
5490ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
5491ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
5492ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (is32bit) {
5493ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      argL = newTemp(Ity_I32);
5494ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      argR = newTemp(Ity_I32);
5495ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   } else {
5496ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      argL = newTemp(Ity_I64);
5497ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      argR = newTemp(Ity_I64);
5498ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
5499ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
5500ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   assign( argL, argL0 );
5501ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   assign( argR, argR0 );
5502ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
5503ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   argLe = mkexpr(argL);
5504ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   argRe = mkexpr(argR);
5505ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
5506ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   cond = const0;
5507ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (TO & 16) { // L <s R
5508ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      tmp = binop(opAND, binop(opCMPORDS, argLe, argRe), const8);
5509ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      cond = binop(opOR, tmp, cond);
5510ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
5511ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (TO & 8) { // L >s R
5512ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      tmp = binop(opAND, binop(opCMPORDS, argLe, argRe), const4);
5513ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      cond = binop(opOR, tmp, cond);
5514ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
5515ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (TO & 4) { // L == R
5516ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      tmp = binop(opAND, binop(opCMPORDS, argLe, argRe), const2);
5517ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      cond = binop(opOR, tmp, cond);
5518ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
5519ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (TO & 2) { // L <u R
5520ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      tmp = binop(opAND, binop(opCMPORDU, argLe, argRe), const8);
5521ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      cond = binop(opOR, tmp, cond);
5522ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
5523ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (TO & 1) { // L >u R
5524ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      tmp = binop(opAND, binop(opCMPORDU, argLe, argRe), const4);
5525ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      cond = binop(opOR, tmp, cond);
5526ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
5527ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   stmt( IRStmt_Exit(
5528ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            binop(opCMPNE, cond, const0),
5529ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            Ijk_SigTRAP,
5530ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            mode64 ? IRConst_U64(cia) : IRConst_U32((UInt)cia)
5531ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   ));
5532ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   return False; /* not an unconditional trap */
5533ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
5534ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
5535ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic Bool dis_trapi ( UInt theInstr,
5536ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                        /*OUT*/DisResult* dres )
5537ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
5538ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* D-Form */
5539ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   UChar  opc1    = ifieldOPC(theInstr);
5540ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   UChar  TO      = ifieldRegDS(theInstr);
5541ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   UChar  rA_addr = ifieldRegA(theInstr);
5542ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   UInt   uimm16  = ifieldUIMM16(theInstr);
5543ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   ULong  simm16  = extend_s_16to64(uimm16);
5544ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   Addr64 cia     = guest_CIA_curr_instr;
5545ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   IRType ty      = mode64 ? Ity_I64 : Ity_I32;
5546ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   Bool   uncond  = False;
5547ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
5548ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   switch (opc1) {
5549ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   case 0x03: // twi  (Trap Word Immediate, PPC32 p548)
5550ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      uncond = do_trap( TO,
5551ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                        mode64 ? unop(Iop_64to32, getIReg(rA_addr))
5552ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                               : getIReg(rA_addr),
5553ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                        mkU32( (UInt)simm16 ),
5554ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                        cia );
5555ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (TO == 4) {
5556ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         DIP("tweqi r%u,%d\n", (UInt)rA_addr, (Int)simm16);
5557ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      } else {
5558ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         DIP("tw%di r%u,%d\n", (Int)TO, (UInt)rA_addr, (Int)simm16);
5559ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
5560ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      break;
5561ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   case 0x02: // tdi
5562ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (!mode64)
5563ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return False;
5564ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      uncond = do_trap( TO, getIReg(rA_addr), mkU64( (ULong)simm16 ), cia );
5565ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (TO == 4) {
5566ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         DIP("tdeqi r%u,%d\n", (UInt)rA_addr, (Int)simm16);
5567ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      } else {
5568ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         DIP("td%di r%u,%d\n", (Int)TO, (UInt)rA_addr, (Int)simm16);
5569ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
5570ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      break;
5571ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   default:
5572ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      return False;
5573ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
5574ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
5575ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (uncond) {
5576ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* If the trap shows signs of being unconditional, don't
5577ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         continue decoding past it. */
5578ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      irsb->next     = mkSzImm( ty, nextInsnAddr() );
5579ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      irsb->jumpkind = Ijk_Boring;
5580ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      dres->whatNext = Dis_StopHere;
5581ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
5582ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
5583ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   return True;
5584ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
5585ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
5586ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic Bool dis_trap ( UInt theInstr,
5587ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                        /*OUT*/DisResult* dres )
5588ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
5589ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* X-Form */
5590ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   UInt   opc2    = ifieldOPClo10(theInstr);
5591ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   UChar  TO      = ifieldRegDS(theInstr);
5592ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   UChar  rA_addr = ifieldRegA(theInstr);
5593ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   UChar  rB_addr = ifieldRegB(theInstr);
5594ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   Addr64 cia     = guest_CIA_curr_instr;
5595ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   IRType ty      = mode64 ? Ity_I64 : Ity_I32;
5596ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   Bool   uncond  = False;
5597ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
5598ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (ifieldBIT0(theInstr) != 0)
5599ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      return False;
5600ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
5601ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   switch (opc2) {
5602ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   case 0x004: // tw  (Trap Word, PPC64 p540)
5603ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      uncond = do_trap( TO,
5604ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                        mode64 ? unop(Iop_64to32, getIReg(rA_addr))
5605ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                               : getIReg(rA_addr),
5606ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                        mode64 ? unop(Iop_64to32, getIReg(rB_addr))
5607ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                               : getIReg(rB_addr),
5608ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                        cia );
5609ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (TO == 4) {
5610ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         DIP("tweq r%u,r%u\n", (UInt)rA_addr, (UInt)rB_addr);
5611ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      } else {
5612ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         DIP("tw%d r%u,r%u\n", (Int)TO, (UInt)rA_addr, (UInt)rB_addr);
5613ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
5614ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      break;
5615ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   case 0x044: // td (Trap Doubleword, PPC64 p534)
5616ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (!mode64)
5617ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return False;
5618ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      uncond = do_trap( TO, getIReg(rA_addr), getIReg(rB_addr), cia );
5619ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (TO == 4) {
5620ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         DIP("tdeq r%u,r%u\n", (UInt)rA_addr, (UInt)rB_addr);
5621ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      } else {
5622ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         DIP("td%d r%u,r%u\n", (Int)TO, (UInt)rA_addr, (UInt)rB_addr);
5623ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
5624ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      break;
5625ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   default:
5626ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      return False;
5627ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
5628ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
5629ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (uncond) {
5630ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* If the trap shows signs of being unconditional, don't
5631ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         continue decoding past it. */
5632ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      irsb->next     = mkSzImm( ty, nextInsnAddr() );
5633ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      irsb->jumpkind = Ijk_Boring;
5634ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      dres->whatNext = Dis_StopHere;
5635ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
5636ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
5637ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   return True;
5638ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
5639ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
5640ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
5641ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*
5642ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  System Linkage Instructions
5643ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown*/
5644ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic Bool dis_syslink ( UInt theInstr,
5645ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                          VexAbiInfo* abiinfo, DisResult* dres )
5646ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
5647ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   IRType ty = mode64 ? Ity_I64 : Ity_I32;
5648ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
5649ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (theInstr != 0x44000002) {
5650ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      vex_printf("dis_syslink(ppc)(theInstr)\n");
5651ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      return False;
5652ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
5653ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
5654ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   // sc  (System Call, PPC32 p504)
5655ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   DIP("sc\n");
5656ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
5657ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* Copy CIA into the IP_AT_SYSCALL pseudo-register, so that on AIX
5658ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      Valgrind can back the guest up to this instruction if it needs
5659ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      to restart the syscall. */
5660ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   putGST( PPC_GST_IP_AT_SYSCALL, getGST( PPC_GST_CIA ) );
5661ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
5662ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* It's important that all ArchRegs carry their up-to-date value
5663ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      at this point.  So we declare an end-of-block here, which
5664ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      forces any TempRegs caching ArchRegs to be flushed. */
5665ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   irsb->next     = abiinfo->guest_ppc_sc_continues_at_LR
5666ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                       ? getGST( PPC_GST_LR )
5667ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                       : mkSzImm( ty, nextInsnAddr() );
5668ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   irsb->jumpkind = Ijk_Sys_syscall;
5669ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
5670ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   dres->whatNext = Dis_StopHere;
5671ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   return True;
5672ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
5673ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
5674ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
5675ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*
5676ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  Memory Synchronization Instructions
5677ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
5678ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  Note on Reservations:
5679ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  We rely on the assumption that V will in fact only allow one thread at
5680ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  once to run.  In effect, a thread can make a reservation, but we don't
5681ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  check any stores it does.  Instead, the reservation is cancelled when
5682ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  the scheduler switches to another thread (run_thread_for_a_while()).
5683ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown*/
5684ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic Bool dis_memsync ( UInt theInstr )
5685ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
5686ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* X-Form, XL-Form */
5687ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   UChar opc1    = ifieldOPC(theInstr);
5688ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   UInt  b11to25 = IFIELD(theInstr, 11, 15);
5689ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   UChar flag_L  = ifieldRegDS(theInstr);
5690ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   UInt  b11to20 = IFIELD(theInstr, 11, 10);
5691ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   UChar rD_addr = ifieldRegDS(theInstr);
5692ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   UChar rS_addr = rD_addr;
5693ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   UChar rA_addr = ifieldRegA(theInstr);
5694ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   UChar rB_addr = ifieldRegB(theInstr);
5695ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   UInt  opc2    = ifieldOPClo10(theInstr);
5696ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   UChar b0      = ifieldBIT0(theInstr);
5697ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
5698ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   IRType ty     = mode64 ? Ity_I64 : Ity_I32;
5699ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   IRTemp EA     = newTemp(ty);
5700ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
5701ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   assign( EA, ea_rAor0_idxd( rA_addr, rB_addr ) );
5702ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
5703ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   switch (opc1) {
5704ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* XL-Form */
5705ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   case 0x13:   // isync (Instruction Synchronize, PPC32 p432)
5706ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (opc2 != 0x096) {
5707ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         vex_printf("dis_memsync(ppc)(0x13,opc2)\n");
5708ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return False;
5709ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
5710ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (b11to25 != 0 || b0 != 0) {
5711ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         vex_printf("dis_memsync(ppc)(0x13,b11to25|b0)\n");
5712ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return False;
5713ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
5714ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      DIP("isync\n");
5715ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      stmt( IRStmt_MBE(Imbe_Fence) );
5716ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      break;
5717ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
5718ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* X-Form */
5719ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   case 0x1F:
5720ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      switch (opc2) {
5721ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case 0x356: // eieio (Enforce In-Order Exec of I/O, PPC32 p394)
5722ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         if (b11to25 != 0 || b0 != 0) {
5723ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            vex_printf("dis_memsync(ppc)(eiei0,b11to25|b0)\n");
5724ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            return False;
5725ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         }
5726ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         DIP("eieio\n");
5727ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         /* Insert a memory fence, just to be on the safe side. */
5728ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         stmt( IRStmt_MBE(Imbe_Fence) );
5729ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         break;
5730ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
5731ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case 0x014: { // lwarx (Load Word and Reserve Indexed, PPC32 p458)
5732ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         IRTemp res;
5733ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         /* According to the PowerPC ISA version 2.05, b0 (called EH
5734ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            in the documentation) is merely a hint bit to the
5735ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            hardware, I think as to whether or not contention is
5736ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            likely.  So we can just ignore it. */
5737ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         DIP("lwarx r%u,r%u,r%u,EH=%u\n", rD_addr, rA_addr, rB_addr, (UInt)b0);
5738ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
5739ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         // trap if misaligned
5740ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         gen_SIGBUS_if_misaligned( EA, 4 );
5741ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
5742ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         // and actually do the load
5743ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         res = newTemp(Ity_I32);
5744ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         stmt( IRStmt_LLSC(Iend_BE, res, mkexpr(EA), NULL/*this is a load*/) );
5745ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
5746ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         putIReg( rD_addr, mkWidenFrom32(ty, mkexpr(res), False) );
5747ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         break;
5748ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
5749ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
5750ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case 0x096: {
5751ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         // stwcx. (Store Word Conditional Indexed, PPC32 p532)
5752ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         // Note this has to handle stwcx. in both 32- and 64-bit modes,
5753ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         // so isn't quite as straightforward as it might otherwise be.
5754ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         IRTemp rS = newTemp(Ity_I32);
5755ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         IRTemp resSC;
5756ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         if (b0 != 1) {
5757ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            vex_printf("dis_memsync(ppc)(stwcx.,b0)\n");
5758ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            return False;
5759ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         }
5760ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         DIP("stwcx. r%u,r%u,r%u\n", rS_addr, rA_addr, rB_addr);
5761ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
5762ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         // trap if misaligned
5763ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         gen_SIGBUS_if_misaligned( EA, 4 );
5764ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
5765ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         // Get the data to be stored, and narrow to 32 bits if necessary
5766ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         assign( rS, mkNarrowTo32(ty, getIReg(rS_addr)) );
5767ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
5768ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         // Do the store, and get success/failure bit into resSC
5769ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         resSC = newTemp(Ity_I1);
5770ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         stmt( IRStmt_LLSC(Iend_BE, resSC, mkexpr(EA), mkexpr(rS)) );
5771ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
5772ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         // Set CR0[LT GT EQ S0] = 0b000 || XER[SO]  on failure
5773ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         // Set CR0[LT GT EQ S0] = 0b001 || XER[SO]  on success
5774ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         putCR321(0, binop(Iop_Shl8, unop(Iop_1Uto8, mkexpr(resSC)), mkU8(1)));
5775ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         putCR0(0, getXER_SO());
5776ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
5777ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         /* Note:
5778ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            If resaddr != lwarx_resaddr, CR0[EQ] is undefined, and
5779ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            whether rS is stored is dependent on that value. */
5780ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         /* So I guess we can just ignore this case? */
5781ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         break;
5782ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
5783ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
5784ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case 0x256: // sync (Synchronize, PPC32 p543),
5785ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  // also lwsync (L==1), ptesync (L==2)
5786ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         /* http://sources.redhat.com/ml/binutils/2000-12/msg00311.html
5787ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
5788ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            The PowerPC architecture used in IBM chips has expanded
5789ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            the sync instruction into two variants: lightweight sync
5790ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            and heavyweight sync.  The original sync instruction is
5791ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            the new heavyweight sync and lightweight sync is a strict
5792ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            subset of the heavyweight sync functionality. This allows
5793ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            the programmer to specify a less expensive operation on
5794ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            high-end systems when the full sync functionality is not
5795ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            necessary.
5796ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
5797ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            The basic "sync" mnemonic now utilizes an operand. "sync"
5798ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            without an operand now becomes a extended mnemonic for
5799ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            heavyweight sync.  Processors without the lwsync
5800ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            instruction will not decode the L field and will perform a
5801ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            heavyweight sync.  Everything is backward compatible.
5802ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
5803ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            sync    =       sync 0
5804ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            lwsync  =       sync 1
5805ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            ptesync =       sync 2    *** TODO - not implemented ***
5806ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         */
5807ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         if (b11to20 != 0 || b0 != 0) {
5808ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            vex_printf("dis_memsync(ppc)(sync/lwsync,b11to20|b0)\n");
5809ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            return False;
5810ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         }
5811ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         if (flag_L != 0/*sync*/ && flag_L != 1/*lwsync*/) {
5812ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            vex_printf("dis_memsync(ppc)(sync/lwsync,flag_L)\n");
5813ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            return False;
5814ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         }
5815ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         DIP("%ssync\n", flag_L == 1 ? "lw" : "");
5816ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         /* Insert a memory fence.  It's sometimes important that these
5817ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            are carried through to the generated code. */
5818ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         stmt( IRStmt_MBE(Imbe_Fence) );
5819ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         break;
5820ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
5821ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* 64bit Memsync */
5822ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case 0x054: { // ldarx (Load DWord and Reserve Indexed, PPC64 p473)
5823ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         IRTemp res;
5824ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         /* According to the PowerPC ISA version 2.05, b0 (called EH
5825ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            in the documentation) is merely a hint bit to the
5826ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            hardware, I think as to whether or not contention is
5827ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            likely.  So we can just ignore it. */
5828ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         if (!mode64)
5829ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            return False;
5830ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         DIP("ldarx r%u,r%u,r%u,EH=%u\n", rD_addr, rA_addr, rB_addr, (UInt)b0);
5831ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
5832ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         // trap if misaligned
5833ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         gen_SIGBUS_if_misaligned( EA, 8 );
5834ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
5835ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         // and actually do the load
5836ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         res = newTemp(Ity_I64);
5837ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         stmt( IRStmt_LLSC(Iend_BE, res, mkexpr(EA), NULL/*this is a load*/) );
5838ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
5839ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         putIReg( rD_addr, mkexpr(res) );
5840ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         break;
5841ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
5842ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
5843ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case 0x0D6: { // stdcx. (Store DWord Condition Indexd, PPC64 p581)
5844ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         // A marginally simplified version of the stwcx. case
5845ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         IRTemp rS = newTemp(Ity_I64);
5846ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         IRTemp resSC;
5847ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         if (b0 != 1) {
5848ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            vex_printf("dis_memsync(ppc)(stdcx.,b0)\n");
5849ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            return False;
5850ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         }
5851ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         if (!mode64)
5852ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            return False;
5853ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         DIP("stdcx. r%u,r%u,r%u\n", rS_addr, rA_addr, rB_addr);
5854ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
5855ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         // trap if misaligned
5856ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         gen_SIGBUS_if_misaligned( EA, 8 );
5857ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
5858ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         // Get the data to be stored
5859ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         assign( rS, getIReg(rS_addr) );
5860ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
5861ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         // Do the store, and get success/failure bit into resSC
5862ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         resSC = newTemp(Ity_I1);
5863ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         stmt( IRStmt_LLSC(Iend_BE, resSC, mkexpr(EA), mkexpr(rS)) );
5864ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
5865ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         // Set CR0[LT GT EQ S0] = 0b000 || XER[SO]  on failure
5866ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         // Set CR0[LT GT EQ S0] = 0b001 || XER[SO]  on success
5867ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         putCR321(0, binop(Iop_Shl8, unop(Iop_1Uto8, mkexpr(resSC)), mkU8(1)));
5868ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         putCR0(0, getXER_SO());
5869ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
5870ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         /* Note:
5871ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            If resaddr != lwarx_resaddr, CR0[EQ] is undefined, and
5872ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            whether rS is stored is dependent on that value. */
5873ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         /* So I guess we can just ignore this case? */
5874ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         break;
5875ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
5876ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
5877ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      default:
5878ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         vex_printf("dis_memsync(ppc)(opc2)\n");
5879ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return False;
5880ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
5881ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      break;
5882ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
5883ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   default:
5884ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      vex_printf("dis_memsync(ppc)(opc1)\n");
5885ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      return False;
5886ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
5887ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   return True;
5888ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
5889ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
5890ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
5891ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
5892ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*
5893ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  Integer Shift Instructions
5894ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown*/
5895ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic Bool dis_int_shift ( UInt theInstr )
5896ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
5897ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* X-Form, XS-Form */
5898ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   UChar opc1    = ifieldOPC(theInstr);
5899ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   UChar rS_addr = ifieldRegDS(theInstr);
5900ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   UChar rA_addr = ifieldRegA(theInstr);
5901ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   UChar rB_addr = ifieldRegB(theInstr);
5902ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   UChar sh_imm  = rB_addr;
5903ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   UInt  opc2    = ifieldOPClo10(theInstr);
5904ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   UChar b1      = ifieldBIT1(theInstr);
5905ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   UChar flag_rC = ifieldBIT0(theInstr);
5906ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
5907ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   IRType  ty         = mode64 ? Ity_I64 : Ity_I32;
5908ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   IRTemp  rA         = newTemp(ty);
5909ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   IRTemp  rS         = newTemp(ty);
5910ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   IRTemp  rB         = newTemp(ty);
5911ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   IRTemp  outofrange = newTemp(Ity_I8);
5912ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   IRTemp  rS_lo32    = newTemp(Ity_I32);
5913ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   IRTemp  rB_lo32    = newTemp(Ity_I32);
5914ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   IRExpr* e_tmp;
5915ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
5916ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   assign( rS, getIReg(rS_addr) );
5917ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   assign( rB, getIReg(rB_addr) );
5918ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   assign( rS_lo32, mkNarrowTo32(ty, mkexpr(rS)) );
5919ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   assign( rB_lo32, mkNarrowTo32(ty, mkexpr(rB)) );
5920ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
5921ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (opc1 == 0x1F) {
5922ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      switch (opc2) {
5923ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case 0x018: { // slw (Shift Left Word, PPC32 p505)
5924ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         DIP("slw%s r%u,r%u,r%u\n", flag_rC ? ".":"",
5925ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown             rA_addr, rS_addr, rB_addr);
5926ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         /* rA = rS << rB */
5927ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         /* ppc32 semantics are:
5928ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            slw(x,y) = (x << (y & 31))         -- primary result
5929ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                       & ~((y << 26) >>s 31)   -- make result 0
5930ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                                  for y in 32 .. 63
5931ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         */
5932ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         e_tmp =
5933ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            binop( Iop_And32,
5934ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               binop( Iop_Shl32,
5935ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                      mkexpr(rS_lo32),
5936ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                      unop( Iop_32to8,
5937ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                            binop(Iop_And32,
5938ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                  mkexpr(rB_lo32), mkU32(31)))),
5939ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               unop( Iop_Not32,
5940ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                     binop( Iop_Sar32,
5941ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                            binop(Iop_Shl32, mkexpr(rB_lo32), mkU8(26)),
5942ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                            mkU8(31))) );
5943ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         assign( rA, mkWidenFrom32(ty, e_tmp, /* Signed */False) );
5944ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         break;
5945ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
5946ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
5947ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case 0x318: { // sraw (Shift Right Alg Word, PPC32 p506)
5948ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         IRTemp sh_amt = newTemp(Ity_I32);
5949ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         DIP("sraw%s r%u,r%u,r%u\n", flag_rC ? ".":"",
5950ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown             rA_addr, rS_addr, rB_addr);
5951ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         /* JRS: my reading of the (poorly worded) PPC32 doc p506 is:
5952ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            amt = rB & 63
5953ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            rA = Sar32( rS, amt > 31 ? 31 : amt )
5954ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            XER.CA = amt > 31 ? sign-of-rS : (computation as per srawi)
5955ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         */
5956ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         assign( sh_amt, binop(Iop_And32, mkU32(0x3F),
5957ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                          mkexpr(rB_lo32)) );
5958ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         assign( outofrange,
5959ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                 unop( Iop_1Uto8,
5960ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                       binop(Iop_CmpLT32U, mkU32(31),
5961ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                           mkexpr(sh_amt)) ));
5962ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         e_tmp = binop( Iop_Sar32,
5963ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                        mkexpr(rS_lo32),
5964ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                        unop( Iop_32to8,
5965ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                              IRExpr_Mux0X( mkexpr(outofrange),
5966ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                            mkexpr(sh_amt),
5967ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                            mkU32(31)) ) );
5968ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         assign( rA, mkWidenFrom32(ty, e_tmp, /* Signed */True) );
5969ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
5970ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         set_XER_CA( ty, PPCG_FLAG_OP_SRAW,
5971ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                     mkexpr(rA),
5972ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                     mkWidenFrom32(ty, mkexpr(rS_lo32), True),
5973ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                     mkWidenFrom32(ty, mkexpr(sh_amt), True ),
5974ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                     mkWidenFrom32(ty, getXER_CA32(), True) );
5975ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         break;
5976ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
5977ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
5978ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case 0x338: // srawi (Shift Right Alg Word Immediate, PPC32 p507)
5979ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         DIP("srawi%s r%u,r%u,%d\n", flag_rC ? ".":"",
5980ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown             rA_addr, rS_addr, sh_imm);
5981ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         vassert(sh_imm < 32);
5982ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         if (mode64) {
5983ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            assign( rA, binop(Iop_Sar64,
5984ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                              binop(Iop_Shl64, getIReg(rS_addr),
5985ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                               mkU8(32)),
5986ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                              mkU8(32 + sh_imm)) );
5987ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         } else {
5988ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            assign( rA, binop(Iop_Sar32, mkexpr(rS_lo32),
5989ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                         mkU8(sh_imm)) );
5990ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         }
5991ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
5992ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         set_XER_CA( ty, PPCG_FLAG_OP_SRAWI,
5993ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                     mkexpr(rA),
5994ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                     mkWidenFrom32(ty, mkexpr(rS_lo32), /* Syned */True),
5995ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                     mkSzImm(ty, sh_imm),
5996ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                     mkWidenFrom32(ty, getXER_CA32(), /* Syned */False) );
5997ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         break;
5998ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
5999ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case 0x218: // srw (Shift Right Word, PPC32 p508)
6000ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         DIP("srw%s r%u,r%u,r%u\n", flag_rC ? ".":"",
6001ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown             rA_addr, rS_addr, rB_addr);
6002ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         /* rA = rS >>u rB */
6003ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         /* ppc32 semantics are:
6004ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            srw(x,y) = (x >>u (y & 31))        -- primary result
6005ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                       & ~((y << 26) >>s 31)   -- make result 0
6006ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                                  for y in 32 .. 63
6007ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         */
6008ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         e_tmp =
6009ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            binop(
6010ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               Iop_And32,
6011ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               binop( Iop_Shr32,
6012ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                      mkexpr(rS_lo32),
6013ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                      unop( Iop_32to8,
6014ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                            binop(Iop_And32, mkexpr(rB_lo32),
6015ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                             mkU32(31)))),
6016ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               unop( Iop_Not32,
6017ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                     binop( Iop_Sar32,
6018ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                            binop(Iop_Shl32, mkexpr(rB_lo32),
6019ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                             mkU8(26)),
6020ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                            mkU8(31))));
6021ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         assign( rA, mkWidenFrom32(ty, e_tmp, /* Signed */False) );
6022ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         break;
6023ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
6024ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
6025ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* 64bit Shifts */
6026ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case 0x01B: // sld (Shift Left DWord, PPC64 p568)
6027ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         DIP("sld%s r%u,r%u,r%u\n",
6028ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown             flag_rC ? ".":"", rA_addr, rS_addr, rB_addr);
6029ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         /* rA = rS << rB */
6030ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         /* ppc64 semantics are:
6031ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            slw(x,y) = (x << (y & 63))         -- primary result
6032ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                       & ~((y << 57) >>s 63)   -- make result 0
6033ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                                  for y in 64 ..
6034ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         */
6035ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         assign( rA,
6036ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            binop(
6037ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               Iop_And64,
6038ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               binop( Iop_Shl64,
6039ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                      mkexpr(rS),
6040ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                      unop( Iop_64to8,
6041ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                            binop(Iop_And64, mkexpr(rB), mkU64(63)))),
6042ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               unop( Iop_Not64,
6043ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                     binop( Iop_Sar64,
6044ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                            binop(Iop_Shl64, mkexpr(rB), mkU8(57)),
6045ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                            mkU8(63)))) );
6046ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         break;
6047ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
6048ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case 0x31A: { // srad (Shift Right Alg DWord, PPC64 p570)
6049ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         IRTemp sh_amt = newTemp(Ity_I64);
6050ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         DIP("srad%s r%u,r%u,r%u\n",
6051ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown             flag_rC ? ".":"", rA_addr, rS_addr, rB_addr);
6052ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         /* amt = rB & 127
6053ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            rA = Sar64( rS, amt > 63 ? 63 : amt )
6054ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            XER.CA = amt > 63 ? sign-of-rS : (computation as per srawi)
6055ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         */
6056ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         assign( sh_amt, binop(Iop_And64, mkU64(0x7F), mkexpr(rB)) );
6057ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         assign( outofrange,
6058ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                 unop( Iop_1Uto8,
6059ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                       binop(Iop_CmpLT64U, mkU64(63),
6060ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                           mkexpr(sh_amt)) ));
6061ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         assign( rA,
6062ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                 binop( Iop_Sar64,
6063ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                        mkexpr(rS),
6064ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                        unop( Iop_64to8,
6065ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                              IRExpr_Mux0X( mkexpr(outofrange),
6066ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                            mkexpr(sh_amt),
6067ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                            mkU64(63)) ))
6068ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               );
6069ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         set_XER_CA( ty, PPCG_FLAG_OP_SRAD,
6070ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                     mkexpr(rA), mkexpr(rS), mkexpr(sh_amt),
6071ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                     mkWidenFrom32(ty, getXER_CA32(), /* Syned */False) );
6072ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         break;
6073ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
6074ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
6075ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case 0x33A: case 0x33B: // sradi (Shr Alg DWord Imm, PPC64 p571)
6076ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         sh_imm |= b1<<5;
6077ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         vassert(sh_imm < 64);
6078ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         DIP("sradi%s r%u,r%u,%u\n",
6079ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown             flag_rC ? ".":"", rA_addr, rS_addr, sh_imm);
6080ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         assign( rA, binop(Iop_Sar64, getIReg(rS_addr), mkU8(sh_imm)) );
6081ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
6082ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         set_XER_CA( ty, PPCG_FLAG_OP_SRADI,
6083ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                     mkexpr(rA),
6084ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                     getIReg(rS_addr),
6085ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                     mkU64(sh_imm),
6086ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                     mkWidenFrom32(ty, getXER_CA32(), /* Syned */False) );
6087ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         break;
6088ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
6089ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case 0x21B: // srd (Shift Right DWord, PPC64 p574)
6090ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         DIP("srd%s r%u,r%u,r%u\n",
6091ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown             flag_rC ? ".":"", rA_addr, rS_addr, rB_addr);
6092ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         /* rA = rS >>u rB */
6093ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         /* ppc semantics are:
6094ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            srw(x,y) = (x >>u (y & 63))        -- primary result
6095ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                       & ~((y << 57) >>s 63)   -- make result 0
6096ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                                  for y in 64 .. 127
6097ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         */
6098ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         assign( rA,
6099ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            binop(
6100ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               Iop_And64,
6101ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               binop( Iop_Shr64,
6102ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                      mkexpr(rS),
6103ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                      unop( Iop_64to8,
6104ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                            binop(Iop_And64, mkexpr(rB), mkU64(63)))),
6105ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               unop( Iop_Not64,
6106ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                     binop( Iop_Sar64,
6107ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                            binop(Iop_Shl64, mkexpr(rB), mkU8(57)),
6108ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                            mkU8(63)))) );
6109ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         break;
6110ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
6111ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      default:
6112ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         vex_printf("dis_int_shift(ppc)(opc2)\n");
6113ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return False;
6114ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
6115ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   } else {
6116ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      vex_printf("dis_int_shift(ppc)(opc1)\n");
6117ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      return False;
6118ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
6119ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
6120ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   putIReg( rA_addr, mkexpr(rA) );
6121ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
6122ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (flag_rC) {
6123ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      set_CR0( mkexpr(rA) );
6124ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
6125ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   return True;
6126ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
6127ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
6128ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
6129ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
6130ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*
6131ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  Integer Load/Store Reverse Instructions
6132ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown*/
6133ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* Generates code to swap the byte order in an Ity_I32. */
6134ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic IRExpr* /* :: Ity_I32 */ gen_byterev32 ( IRTemp t )
6135ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
6136ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   vassert(typeOfIRTemp(irsb->tyenv, t) == Ity_I32);
6137ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   return
6138ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      binop(Iop_Or32,
6139ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         binop(Iop_Shl32, mkexpr(t), mkU8(24)),
6140ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      binop(Iop_Or32,
6141ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         binop(Iop_And32, binop(Iop_Shl32, mkexpr(t), mkU8(8)),
6142ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                          mkU32(0x00FF0000)),
6143ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      binop(Iop_Or32,
6144ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         binop(Iop_And32, binop(Iop_Shr32, mkexpr(t), mkU8(8)),
6145ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                          mkU32(0x0000FF00)),
6146ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         binop(Iop_And32, binop(Iop_Shr32, mkexpr(t), mkU8(24)),
6147ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                          mkU32(0x000000FF) )
6148ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      )));
6149ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
6150ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
6151ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* Generates code to swap the byte order in the lower half of an Ity_I32,
6152ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   and zeroes the upper half. */
6153ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic IRExpr* /* :: Ity_I32 */ gen_byterev16 ( IRTemp t )
6154ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
6155ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   vassert(typeOfIRTemp(irsb->tyenv, t) == Ity_I32);
6156ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   return
6157ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      binop(Iop_Or32,
6158ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         binop(Iop_And32, binop(Iop_Shl32, mkexpr(t), mkU8(8)),
6159ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                          mkU32(0x0000FF00)),
6160ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         binop(Iop_And32, binop(Iop_Shr32, mkexpr(t), mkU8(8)),
6161ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                          mkU32(0x000000FF))
6162ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      );
6163ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
6164ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
6165ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic Bool dis_int_ldst_rev ( UInt theInstr )
6166ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
6167ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* X-Form */
6168ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   UChar opc1    = ifieldOPC(theInstr);
6169ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   UChar rD_addr = ifieldRegDS(theInstr);
6170ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   UChar rS_addr = rD_addr;
6171ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   UChar rA_addr = ifieldRegA(theInstr);
6172ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   UChar rB_addr = ifieldRegB(theInstr);
6173ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   UInt  opc2    = ifieldOPClo10(theInstr);
6174ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   UChar b0      = ifieldBIT0(theInstr);
6175ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
6176ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   IRType ty = mode64 ? Ity_I64 : Ity_I32;
6177ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   IRTemp EA = newTemp(ty);
6178ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   IRTemp w1 = newTemp(Ity_I32);
6179ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   IRTemp w2 = newTemp(Ity_I32);
6180ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
6181ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (opc1 != 0x1F || b0 != 0) {
6182ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      vex_printf("dis_int_ldst_rev(ppc)(opc1|b0)\n");
6183ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      return False;
6184ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
6185ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
6186ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   assign( EA, ea_rAor0_idxd( rA_addr, rB_addr ) );
6187ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
6188ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   switch (opc2) {
6189ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
6190ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case 0x316: // lhbrx (Load Halfword Byte-Reverse Indexed, PPC32 p449)
6191ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         DIP("lhbrx r%u,r%u,r%u\n", rD_addr, rA_addr, rB_addr);
6192ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         assign( w1, unop(Iop_16Uto32, loadBE(Ity_I16, mkexpr(EA))) );
6193ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         assign( w2, gen_byterev16(w1) );
6194ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         putIReg( rD_addr, mkWidenFrom32(ty, mkexpr(w2),
6195ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                         /* Signed */False) );
6196ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         break;
6197ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
6198ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case 0x216: // lwbrx (Load Word Byte-Reverse Indexed, PPC32 p459)
6199ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         DIP("lwbrx r%u,r%u,r%u\n", rD_addr, rA_addr, rB_addr);
6200ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         assign( w1, loadBE(Ity_I32, mkexpr(EA)) );
6201ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         assign( w2, gen_byterev32(w1) );
6202ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         putIReg( rD_addr, mkWidenFrom32(ty, mkexpr(w2),
6203ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                         /* Signed */False) );
6204ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         break;
6205b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
6206b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      case 0x214: // ldbrx (Load Doubleword Byte-Reverse Indexed)
6207b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      {
6208b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         IRExpr * nextAddr;
6209b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         IRTemp w3 = newTemp( Ity_I32 );
6210b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         IRTemp w4 = newTemp( Ity_I32 );
6211b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         DIP("ldbrx r%u,r%u,r%u\n", rD_addr, rA_addr, rB_addr);
6212b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         assign( w1, loadBE( Ity_I32, mkexpr( EA ) ) );
6213b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         assign( w2, gen_byterev32( w1 ) );
6214b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         nextAddr = binop( mkSzOp( ty, Iop_Add8 ), mkexpr( EA ),
6215b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                           ty == Ity_I64 ? mkU64( 4 ) : mkU32( 4 ) );
6216b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         assign( w3, loadBE( Ity_I32, nextAddr ) );
6217b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         assign( w4, gen_byterev32( w3 ) );
6218b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         putIReg( rD_addr, binop( Iop_32HLto64, mkexpr( w4 ), mkexpr( w2 ) ) );
6219b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         break;
6220b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      }
6221b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
6222ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case 0x396: // sthbrx (Store Half Word Byte-Reverse Indexed, PPC32 p523)
6223ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         DIP("sthbrx r%u,r%u,r%u\n", rS_addr, rA_addr, rB_addr);
6224ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         assign( w1, mkNarrowTo32(ty, getIReg(rS_addr)) );
6225ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         storeBE( mkexpr(EA), unop(Iop_32to16, gen_byterev16(w1)) );
6226ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         break;
6227ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
6228ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case 0x296: // stwbrx (Store Word Byte-Reverse Indxd, PPC32 p531)
6229ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         DIP("stwbrx r%u,r%u,r%u\n", rS_addr, rA_addr, rB_addr);
6230ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         assign( w1, mkNarrowTo32(ty, getIReg(rS_addr)) );
6231ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         storeBE( mkexpr(EA), gen_byterev32(w1) );
6232ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         break;
6233b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
6234b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      case 0x294: // stdbrx (Store Doubleword Byte-Reverse Indexed)
6235b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      {
6236b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         IRTemp lo = newTemp(Ity_I32);
6237b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         IRTemp hi = newTemp(Ity_I32);
6238b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         IRTemp rS = newTemp(Ity_I64);
6239b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         assign( rS, getIReg( rS_addr ) );
6240b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         DIP("stdbrx r%u,r%u,r%u\n", rS_addr, rA_addr, rB_addr);
6241b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         assign(lo, unop(Iop_64HIto32, mkexpr(rS)));
6242b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         assign(hi, unop(Iop_64to32, mkexpr(rS)));
6243b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         storeBE( mkexpr( EA ),
6244b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                  binop( Iop_32HLto64, gen_byterev32( hi ), gen_byterev32( lo ) ) );
6245b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         break;
6246b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      }
6247b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
6248ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      default:
6249ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         vex_printf("dis_int_ldst_rev(ppc)(opc2)\n");
6250ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return False;
6251ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
6252ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   return True;
6253ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
6254ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
6255ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
6256ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
6257ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*
6258ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  Processor Control Instructions
6259ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown*/
6260ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic Bool dis_proc_ctl ( VexAbiInfo* vbi, UInt theInstr )
6261ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
6262ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   UChar opc1     = ifieldOPC(theInstr);
6263ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
6264ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* X-Form */
6265ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   UChar crfD     = toUChar( IFIELD( theInstr, 23, 3 ) );
6266ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   UChar b21to22  = toUChar( IFIELD( theInstr, 21, 2 ) );
6267ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   UChar rD_addr  = ifieldRegDS(theInstr);
6268ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   UInt  b11to20  = IFIELD( theInstr, 11, 10 );
6269ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
6270ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* XFX-Form */
6271ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   UChar rS_addr  = rD_addr;
6272ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   UInt  SPR      = b11to20;
6273ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   UInt  TBR      = b11to20;
6274ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   UChar b20      = toUChar( IFIELD( theInstr, 20, 1 ) );
6275ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   UInt  CRM      = IFIELD( theInstr, 12, 8 );
6276ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   UChar b11      = toUChar( IFIELD( theInstr, 11, 1 ) );
6277ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
6278ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   UInt  opc2     = ifieldOPClo10(theInstr);
6279ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   UChar b0       = ifieldBIT0(theInstr);
6280ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
6281ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   IRType ty = mode64 ? Ity_I64 : Ity_I32;
6282ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   IRTemp rS = newTemp(ty);
6283ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   assign( rS, getIReg(rS_addr) );
6284ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
6285ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* Reorder SPR field as per PPC32 p470 */
6286ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   SPR = ((SPR & 0x1F) << 5) | ((SPR >> 5) & 0x1F);
6287ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* Reorder TBR field as per PPC32 p475 */
6288ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   TBR = ((TBR & 31) << 5) | ((TBR >> 5) & 31);
6289ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
6290ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (opc1 != 0x1F || b0 != 0) {
6291ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      vex_printf("dis_proc_ctl(ppc)(opc1|b0)\n");
6292ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      return False;
6293ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
6294ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
6295ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   switch (opc2) {
6296ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* X-Form */
6297ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   case 0x200: { // mcrxr (Move to Cond Register from XER, PPC32 p466)
6298ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (b21to22 != 0 || b11to20 != 0) {
6299ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         vex_printf("dis_proc_ctl(ppc)(mcrxr,b21to22|b11to20)\n");
6300ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return False;
6301ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
6302ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      DIP("mcrxr crf%d\n", crfD);
6303ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* Move XER[0-3] (the top 4 bits of XER) to CR[crfD] */
6304ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      putGST_field( PPC_GST_CR,
6305ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                    getGST_field( PPC_GST_XER, 7 ),
6306ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                    crfD );
6307ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
6308ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      // Clear XER[0-3]
6309ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      putXER_SO( mkU8(0) );
6310ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      putXER_OV( mkU8(0) );
6311ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      putXER_CA( mkU8(0) );
6312ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      break;
6313ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
6314ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
6315ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   case 0x013:
6316ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      // b11to20==0:      mfcr (Move from Cond Register, PPC32 p467)
6317ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      // b20==1 & b11==0: mfocrf (Move from One CR Field)
6318ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      // However it seems that the 'mfcr' behaviour is an acceptable
6319ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      // implementation of mfocr (from the 2.02 arch spec)
6320ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (b11to20 == 0) {
6321ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         DIP("mfcr r%u\n", rD_addr);
6322ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         putIReg( rD_addr, mkWidenFrom32(ty, getGST( PPC_GST_CR ),
6323ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                         /* Signed */False) );
6324ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         break;
6325ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
6326ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (b20 == 1 && b11 == 0) {
6327ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         DIP("mfocrf r%u,%u\n", rD_addr, CRM);
6328ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         putIReg( rD_addr, mkWidenFrom32(ty, getGST( PPC_GST_CR ),
6329ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                         /* Signed */False) );
6330ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         break;
6331ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
6332ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* not decodable */
6333ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      return False;
6334ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
6335ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* XFX-Form */
6336ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   case 0x153: // mfspr (Move from Special-Purpose Register, PPC32 p470)
6337ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
6338ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      switch (SPR) {  // Choose a register...
6339ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case 0x1:
6340ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         DIP("mfxer r%u\n", rD_addr);
6341ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         putIReg( rD_addr, mkWidenFrom32(ty, getGST( PPC_GST_XER ),
6342ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                         /* Signed */False) );
6343ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         break;
6344ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case 0x8:
6345ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         DIP("mflr r%u\n", rD_addr);
6346ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         putIReg( rD_addr, getGST( PPC_GST_LR ) );
6347ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         break;
6348ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case 0x9:
6349ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         DIP("mfctr r%u\n", rD_addr);
6350ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         putIReg( rD_addr, getGST( PPC_GST_CTR ) );
6351ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         break;
6352ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case 0x100:
6353ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         DIP("mfvrsave r%u\n", rD_addr);
6354ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         putIReg( rD_addr, mkWidenFrom32(ty, getGST( PPC_GST_VRSAVE ),
6355ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                         /* Signed */False) );
6356ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         break;
6357ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
6358ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case 0x103:
6359ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         DIP("mfspr r%u, SPRG3(readonly)\n", rD_addr);
6360ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         putIReg( rD_addr, getGST( PPC_GST_SPRG3_RO ) );
6361ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         break;
6362ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
6363ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* Even a lowly PPC7400 can run the associated helper, so no
6364ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         obvious need for feature testing at this point. */
6365ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case 268 /* 0x10C */:
6366ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case 269 /* 0x10D */: {
6367ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         UInt     arg  = SPR==268 ? 0 : 1;
6368ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         IRTemp   val  = newTemp(Ity_I32);
6369ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         IRExpr** args = mkIRExprVec_1( mkU32(arg) );
6370ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         IRDirty* d    = unsafeIRDirty_1_N(
6371ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                            val,
6372ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                            0/*regparms*/,
6373ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                            "ppc32g_dirtyhelper_MFSPR_268_269",
6374ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                            fnptr_to_fnentry
6375ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                               (vbi, &ppc32g_dirtyhelper_MFSPR_268_269),
6376ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                            args
6377ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                         );
6378ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         /* execute the dirty call, dumping the result in val. */
6379ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         stmt( IRStmt_Dirty(d) );
6380ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         putIReg( rD_addr,
6381ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  mkWidenFrom32(ty, mkexpr(val), False/*unsigned*/) );
6382ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         DIP("mfspr r%u,%u", rD_addr, (UInt)SPR);
6383ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         break;
6384ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
6385ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
6386ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* Again, runs natively on PPC7400 (7447, really).  Not
6387ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         bothering with a feature test. */
6388ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case 287: /* 0x11F */ {
6389ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         IRTemp   val  = newTemp(Ity_I32);
6390ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         IRExpr** args = mkIRExprVec_0();
6391ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         IRDirty* d    = unsafeIRDirty_1_N(
6392ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                            val,
6393ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                            0/*regparms*/,
6394ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                            "ppc32g_dirtyhelper_MFSPR_287",
6395ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                            fnptr_to_fnentry
6396ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                               (vbi, &ppc32g_dirtyhelper_MFSPR_287),
6397ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                            args
6398ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                         );
6399ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         /* execute the dirty call, dumping the result in val. */
6400ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         stmt( IRStmt_Dirty(d) );
6401ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         putIReg( rD_addr,
6402ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  mkWidenFrom32(ty, mkexpr(val), False/*unsigned*/) );
6403ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         DIP("mfspr r%u,%u", rD_addr, (UInt)SPR);
6404ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         break;
6405ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
6406ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
6407ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      default:
6408ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         vex_printf("dis_proc_ctl(ppc)(mfspr,SPR)(0x%x)\n", SPR);
6409ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return False;
6410ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
6411ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      break;
6412ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
6413ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   case 0x173: { // mftb (Move from Time Base, PPC32 p475)
6414ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      IRTemp   val  = newTemp(Ity_I64);
6415ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      IRExpr** args = mkIRExprVec_0();
6416ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      IRDirty* d    = unsafeIRDirty_1_N(
6417ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                              val,
6418ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                              0/*regparms*/,
6419ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                              "ppcg_dirtyhelper_MFTB",
6420ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                              fnptr_to_fnentry(vbi, &ppcg_dirtyhelper_MFTB),
6421ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                              args );
6422ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* execute the dirty call, dumping the result in val. */
6423ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      stmt( IRStmt_Dirty(d) );
6424ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
6425ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      switch (TBR) {
6426ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case 269:
6427ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         DIP("mftbu r%u", rD_addr);
6428ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         putIReg( rD_addr,
6429ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  mkWidenFrom32(ty, unop(Iop_64HIto32, mkexpr(val)),
6430ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                /* Signed */False) );
6431ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         break;
6432ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case 268:
6433ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         DIP("mftb r%u", rD_addr);
6434ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         putIReg( rD_addr, (mode64) ? mkexpr(val) :
6435ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                      unop(Iop_64to32, mkexpr(val)) );
6436ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         break;
6437ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      default:
6438ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return False; /* illegal instruction */
6439ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
6440ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      break;
6441ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
6442ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
6443ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   case 0x090: {
6444ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      // b20==0: mtcrf (Move to Cond Register Fields, PPC32 p477)
6445ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      // b20==1: mtocrf (Move to One Cond Reg Field)
6446ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      Int   cr;
6447ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      UChar shft;
6448ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (b11 != 0)
6449ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return False;
6450ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (b20 == 1) {
6451ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         /* ppc64 v2.02 spec says mtocrf gives undefined outcome if >
6452ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            1 field is written.  It seems more robust to decline to
6453ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            decode the insn if so. */
6454ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         switch (CRM) {
6455ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            case 0x01: case 0x02: case 0x04: case 0x08:
6456ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            case 0x10: case 0x20: case 0x40: case 0x80:
6457ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               break;
6458ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            default:
6459ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               return False;
6460ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         }
6461ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
6462ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      DIP("%s 0x%x,r%u\n", b20==1 ? "mtocrf" : "mtcrf",
6463ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                           CRM, rS_addr);
6464ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* Write to each field specified by CRM */
6465ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      for (cr = 0; cr < 8; cr++) {
6466ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         if ((CRM & (1 << (7-cr))) == 0)
6467ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            continue;
6468ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         shft = 4*(7-cr);
6469ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         putGST_field( PPC_GST_CR,
6470ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                       binop(Iop_Shr32,
6471ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                             mkNarrowTo32(ty, mkexpr(rS)),
6472ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                             mkU8(shft)), cr );
6473ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
6474ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      break;
6475ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
6476ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
6477ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   case 0x1D3: // mtspr (Move to Special-Purpose Register, PPC32 p483)
6478ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
6479ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      switch (SPR) {  // Choose a register...
6480ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case 0x1:
6481ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         DIP("mtxer r%u\n", rS_addr);
6482ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         putGST( PPC_GST_XER, mkNarrowTo32(ty, mkexpr(rS)) );
6483ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         break;
6484ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case 0x8:
6485ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         DIP("mtlr r%u\n", rS_addr);
6486ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         putGST( PPC_GST_LR, mkexpr(rS) );
6487ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         break;
6488ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case 0x9:
6489ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         DIP("mtctr r%u\n", rS_addr);
6490ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         putGST( PPC_GST_CTR, mkexpr(rS) );
6491ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         break;
6492ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case 0x100:
6493ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         DIP("mtvrsave r%u\n", rS_addr);
6494ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         putGST( PPC_GST_VRSAVE, mkNarrowTo32(ty, mkexpr(rS)) );
6495ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         break;
6496ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
6497ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      default:
6498ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         vex_printf("dis_proc_ctl(ppc)(mtspr,SPR)(%u)\n", SPR);
6499ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return False;
6500ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
6501ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      break;
6502ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
6503ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   default:
6504ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      vex_printf("dis_proc_ctl(ppc)(opc2)\n");
6505ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      return False;
6506ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
6507ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   return True;
6508ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
6509ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
6510ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
6511ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*
6512ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  Cache Management Instructions
6513ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown*/
6514ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic Bool dis_cache_manage ( UInt         theInstr,
6515ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                               DisResult*   dres,
6516ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                               VexArchInfo* guest_archinfo )
6517ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
6518ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* X-Form */
6519ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   UChar opc1    = ifieldOPC(theInstr);
6520ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   UChar b21to25 = ifieldRegDS(theInstr);
6521ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   UChar rA_addr = ifieldRegA(theInstr);
6522ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   UChar rB_addr = ifieldRegB(theInstr);
6523ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   UInt  opc2    = ifieldOPClo10(theInstr);
6524ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   UChar b0      = ifieldBIT0(theInstr);
6525ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   UInt  lineszB = guest_archinfo->ppc_cache_line_szB;
6526ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   Bool  is_dcbzl = False;
6527ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
6528ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   IRType ty     = mode64 ? Ity_I64 : Ity_I32;
6529ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
6530ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* For dcbt, the lowest two bits of b21to25 encode an
6531ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      access-direction hint (TH field) which we ignore.  Well, that's
6532ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      what the PowerPC documentation says.  In fact xlc -O4 on POWER5
6533ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      seems to generate values of 8 and 10 for b21to25. */
6534ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (opc1 == 0x1F && opc2 == 0x116) {
6535ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     /* b21to25 &= ~3; */ /* if the docs were true */
6536ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     b21to25 = 0; /* blunt instrument */
6537ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
6538ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (opc1 == 0x1F && opc2 == 0x3F6) { // dcbz
6539ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (b21to25 == 1) {
6540ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         is_dcbzl = True;
6541ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         b21to25 = 0;
6542ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         if (!(guest_archinfo->ppc_dcbzl_szB)) {
6543ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            vex_printf("dis_cache_manage(ppc)(dcbzl not supported by host)\n");
6544ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            return False;
6545ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         }
6546ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
6547ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
6548ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
6549ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (opc1 != 0x1F || b21to25 != 0 || b0 != 0) {
6550ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (0) vex_printf("dis_cache_manage %d %d %d\n",
6551ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                        (Int)opc1, (Int)b21to25, (Int)b0);
6552ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      vex_printf("dis_cache_manage(ppc)(opc1|b21to25|b0)\n");
6553ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      return False;
6554ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
6555ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
6556ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* stay sane .. */
6557ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   vassert(lineszB == 32 || lineszB == 64 || lineszB == 128);
6558ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
6559ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   switch (opc2) {
6560ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//zz    case 0x2F6: // dcba (Data Cache Block Allocate, PPC32 p380)
6561ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//zz       vassert(0); /* AWAITING TEST CASE */
6562ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//zz       DIP("dcba r%u,r%u\n", rA_addr, rB_addr);
6563ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//zz       if (0) vex_printf("vex ppc->IR: kludged dcba\n");
6564ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//zz       break;
6565ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
6566ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   case 0x056: // dcbf (Data Cache Block Flush, PPC32 p382)
6567ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      DIP("dcbf r%u,r%u\n", rA_addr, rB_addr);
6568ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* nop as far as vex is concerned */
6569ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      break;
6570ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
6571ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   case 0x036: // dcbst (Data Cache Block Store, PPC32 p384)
6572ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      DIP("dcbst r%u,r%u\n", rA_addr, rB_addr);
6573ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* nop as far as vex is concerned */
6574ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      break;
6575ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
6576ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   case 0x116: // dcbt (Data Cache Block Touch, PPC32 p385)
6577ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      DIP("dcbt r%u,r%u\n", rA_addr, rB_addr);
6578ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* nop as far as vex is concerned */
6579ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      break;
6580ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
6581ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   case 0x0F6: // dcbtst (Data Cache Block Touch for Store, PPC32 p386)
6582ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      DIP("dcbtst r%u,r%u\n", rA_addr, rB_addr);
6583ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* nop as far as vex is concerned */
6584ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      break;
6585ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
6586ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   case 0x3F6: { // dcbz (Data Cache Block Clear to Zero, PPC32 p387)
6587ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                 // dcbzl (Data Cache Block Clear to Zero Long, bug#135264)
6588ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* Clear all bytes in cache block at (rA|0) + rB. */
6589ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      IRTemp  EA   = newTemp(ty);
6590ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      IRTemp  addr = newTemp(ty);
6591ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      IRExpr* irx_addr;
6592ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      UInt    i;
6593ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      UInt clearszB;
6594ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (is_dcbzl) {
6595ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown          clearszB = guest_archinfo->ppc_dcbzl_szB;
6596ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown          DIP("dcbzl r%u,r%u\n", rA_addr, rB_addr);
6597ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
6598ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      else {
6599ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown          clearszB = guest_archinfo->ppc_dcbz_szB;
6600ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown          DIP("dcbz r%u,r%u\n", rA_addr, rB_addr);
6601ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
6602ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
6603ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      assign( EA, ea_rAor0_idxd(rA_addr, rB_addr) );
6604ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
6605ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (mode64) {
6606ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         /* Round EA down to the start of the containing block. */
6607ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         assign( addr, binop( Iop_And64,
6608ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                              mkexpr(EA),
6609ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                              mkU64( ~((ULong)clearszB-1) )) );
6610ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
6611ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         for (i = 0; i < clearszB / 8; i++) {
6612ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            irx_addr = binop( Iop_Add64, mkexpr(addr), mkU64(i*8) );
6613ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            storeBE( irx_addr, mkU64(0) );
6614ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         }
6615ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      } else {
6616ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         /* Round EA down to the start of the containing block. */
6617ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         assign( addr, binop( Iop_And32,
6618ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                              mkexpr(EA),
6619ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                              mkU32( ~(clearszB-1) )) );
6620ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
6621ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         for (i = 0; i < clearszB / 4; i++) {
6622ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            irx_addr = binop( Iop_Add32, mkexpr(addr), mkU32(i*4) );
6623ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            storeBE( irx_addr, mkU32(0) );
6624ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         }
6625ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
6626ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      break;
6627ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
6628ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
6629ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   case 0x3D6: {
6630ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      // icbi (Instruction Cache Block Invalidate, PPC32 p431)
6631ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* Invalidate all translations containing code from the cache
6632ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         block at (rA|0) + rB. */
6633ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      IRTemp EA   = newTemp(ty);
6634ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      IRTemp addr = newTemp(ty);
6635ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      DIP("icbi r%u,r%u\n", rA_addr, rB_addr);
6636ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      assign( EA, ea_rAor0_idxd(rA_addr, rB_addr) );
6637ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
6638ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* Round EA down to the start of the containing block. */
6639ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      assign( addr, binop( mkSzOp(ty, Iop_And8),
6640ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                           mkexpr(EA),
6641ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                           mkSzImm(ty, ~(((ULong)lineszB)-1) )) );
6642ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      putGST( PPC_GST_TISTART, mkexpr(addr) );
6643ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      putGST( PPC_GST_TILEN, mkSzImm(ty, lineszB) );
6644ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
6645ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* be paranoid ... */
6646ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      stmt( IRStmt_MBE(Imbe_Fence) );
6647ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
6648ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      irsb->jumpkind = Ijk_TInval;
6649ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      irsb->next     = mkSzImm(ty, nextInsnAddr());
6650ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      dres->whatNext = Dis_StopHere;
6651ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      break;
6652ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
6653ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
6654ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   default:
6655ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      vex_printf("dis_cache_manage(ppc)(opc2)\n");
6656ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      return False;
6657ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
6658ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   return True;
6659ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
6660ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
6661ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
6662ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*------------------------------------------------------------*/
6663ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*--- Floating Point Helpers                               ---*/
6664ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*------------------------------------------------------------*/
6665ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
6666ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* --------- Synthesise a 2-bit FPU rounding mode. --------- */
6667ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* Produces a value in 0 .. 3, which is encoded as per the type
6668ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   IRRoundingMode.  PPCRoundingMode encoding is different to
6669ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   IRRoundingMode, so need to map it.
6670ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown*/
6671ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic IRExpr* /* :: Ity_I32 */ get_IR_roundingmode ( void )
6672ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
6673ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*
6674ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   rounding mode | PPC | IR
6675ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   ------------------------
6676ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   to nearest    | 00  | 00
6677ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   to zero       | 01  | 11
6678ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   to +infinity  | 10  | 10
6679ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   to -infinity  | 11  | 01
6680ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown*/
6681ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   IRTemp rm_PPC32 = newTemp(Ity_I32);
6682ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   assign( rm_PPC32, getGST_masked( PPC_GST_FPSCR, MASK_FPSCR_RN ) );
6683ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
6684ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   // rm_IR = XOR( rm_PPC32, (rm_PPC32 << 1) & 2)
6685ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   return binop( Iop_Xor32,
6686ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                 mkexpr(rm_PPC32),
6687ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                 binop( Iop_And32,
6688ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                        binop(Iop_Shl32, mkexpr(rm_PPC32), mkU8(1)),
6689ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                        mkU32(2) ));
6690ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
6691ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
6692ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
6693ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*------------------------------------------------------------*/
6694ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*--- Floating Point Instruction Translation               ---*/
6695ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*------------------------------------------------------------*/
6696ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
6697ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*
6698ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  Floating Point Load Instructions
6699ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown*/
6700ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic Bool dis_fp_load ( UInt theInstr )
6701ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
6702ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* X-Form, D-Form */
6703ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   UChar opc1      = ifieldOPC(theInstr);
6704ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   UChar frD_addr  = ifieldRegDS(theInstr);
6705ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   UChar rA_addr   = ifieldRegA(theInstr);
6706ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   UChar rB_addr   = ifieldRegB(theInstr);
6707ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   UInt  opc2      = ifieldOPClo10(theInstr);
6708ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   UChar b0        = ifieldBIT0(theInstr);
6709ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   UInt  uimm16    = ifieldUIMM16(theInstr);
6710ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
6711ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   Int    simm16 = extend_s_16to32(uimm16);
6712ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   IRType ty     = mode64 ? Ity_I64 : Ity_I32;
6713ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   IRTemp EA     = newTemp(ty);
6714ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   IRTemp rA     = newTemp(ty);
6715ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   IRTemp rB     = newTemp(ty);
6716ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   IRTemp iHi    = newTemp(Ity_I32);
6717ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   IRTemp iLo    = newTemp(Ity_I32);
6718ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
6719ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   assign( rA, getIReg(rA_addr) );
6720ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   assign( rB, getIReg(rB_addr) );
6721ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
6722ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* These are completely straightforward from a rounding and status
6723ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      bits perspective: no rounding involved and no funny status or CR
6724ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      bits affected. */
6725ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
6726ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   switch (opc1) {
6727ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   case 0x30: // lfs (Load Float Single, PPC32 p441)
6728ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      DIP("lfs fr%u,%d(r%u)\n", frD_addr, simm16, rA_addr);
6729ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      assign( EA, ea_rAor0_simm(rA_addr, simm16) );
6730ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      putFReg( frD_addr,
6731ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               unop(Iop_F32toF64, loadBE(Ity_F32, mkexpr(EA))) );
6732ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      break;
6733ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
6734ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   case 0x31: // lfsu (Load Float Single, Update, PPC32 p442)
6735ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (rA_addr == 0)
6736ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return False;
6737ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      DIP("lfsu fr%u,%d(r%u)\n", frD_addr, simm16, rA_addr);
6738ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      assign( EA, ea_rA_simm(rA_addr, simm16) );
6739ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      putFReg( frD_addr,
6740ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               unop(Iop_F32toF64, loadBE(Ity_F32, mkexpr(EA))) );
6741ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      putIReg( rA_addr, mkexpr(EA) );
6742ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      break;
6743ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
6744ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   case 0x32: // lfd (Load Float Double, PPC32 p437)
6745ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      DIP("lfd fr%u,%d(r%u)\n", frD_addr, simm16, rA_addr);
6746ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      assign( EA, ea_rAor0_simm(rA_addr, simm16) );
6747ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      putFReg( frD_addr, loadBE(Ity_F64, mkexpr(EA)) );
6748ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      break;
6749ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
6750ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   case 0x33: // lfdu (Load Float Double, Update, PPC32 p438)
6751ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (rA_addr == 0)
6752ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return False;
6753ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      DIP("lfdu fr%u,%d(r%u)\n", frD_addr, simm16, rA_addr);
6754ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      assign( EA, ea_rA_simm(rA_addr, simm16) );
6755ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      putFReg( frD_addr, loadBE(Ity_F64, mkexpr(EA)) );
6756ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      putIReg( rA_addr, mkexpr(EA) );
6757ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      break;
6758ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
6759ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   case 0x1F:
6760ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (b0 != 0) {
6761ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         vex_printf("dis_fp_load(ppc)(instr,b0)\n");
6762ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return False;
6763ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
6764ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
6765ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      switch(opc2) {
6766ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case 0x217: // lfsx (Load Float Single Indexed, PPC32 p444)
6767ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         DIP("lfsx fr%u,r%u,r%u\n", frD_addr, rA_addr, rB_addr);
6768ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         assign( EA, ea_rAor0_idxd(rA_addr, rB_addr) );
6769ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         putFReg( frD_addr, unop( Iop_F32toF64,
6770ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                  loadBE(Ity_F32, mkexpr(EA))) );
6771ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         break;
6772ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
6773ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case 0x237: // lfsux (Load Float Single, Update Indxd, PPC32 p443)
6774ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         if (rA_addr == 0)
6775ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            return False;
6776ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         DIP("lfsux fr%u,r%u,r%u\n", frD_addr, rA_addr, rB_addr);
6777ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         assign( EA, ea_rA_idxd(rA_addr, rB_addr) );
6778ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         putFReg( frD_addr,
6779ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  unop(Iop_F32toF64, loadBE(Ity_F32, mkexpr(EA))) );
6780ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         putIReg( rA_addr, mkexpr(EA) );
6781ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         break;
6782ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
6783ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case 0x257: // lfdx (Load Float Double Indexed, PPC32 p440)
6784ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         DIP("lfdx fr%u,r%u,r%u\n", frD_addr, rA_addr, rB_addr);
6785ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         assign( EA, ea_rAor0_idxd(rA_addr, rB_addr) );
6786ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         putFReg( frD_addr, loadBE(Ity_F64, mkexpr(EA)) );
6787ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         break;
6788ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
6789ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case 0x277: // lfdux (Load Float Double, Update Indxd, PPC32 p439)
6790ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         if (rA_addr == 0)
6791ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            return False;
6792ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         DIP("lfdux fr%u,r%u,r%u\n", frD_addr, rA_addr, rB_addr);
6793ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         assign( EA, ea_rA_idxd(rA_addr, rB_addr) );
6794ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         putFReg( frD_addr, loadBE(Ity_F64, mkexpr(EA)) );
6795ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         putIReg( rA_addr, mkexpr(EA) );
6796ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         break;
6797ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
6798ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case 0x357: // lfiwax (Load Float As Integer, Indxd, ISA 2.05 p120)
6799ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         DIP("lfiwax fr%u,r%u,r%u\n", frD_addr, rA_addr, rB_addr);
6800ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         assign( EA, ea_rAor0_idxd( rA_addr, rB_addr ) );
6801ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         assign( iLo, loadBE(Ity_I32, mkexpr(EA)) );
6802ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         assign( iHi, binop(Iop_Sub32,
6803ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                            mkU32(0),
6804ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                            binop(Iop_Shr32, mkexpr(iLo), mkU8(31)))  );
6805ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         putFReg( frD_addr, unop(Iop_ReinterpI64asF64,
6806ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                 binop(Iop_32HLto64, mkexpr(iHi), mkexpr(iLo))) );
6807ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         break;
6808ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
6809b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      case 0x377: // lfiwzx (Load floating-point as integer word, zero indexed
6810b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      {
6811b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         IRTemp dw = newTemp( Ity_I64 );
6812b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         DIP("lfiwzx fr%u,r%u,r%u\n", frD_addr, rA_addr, rB_addr);
6813b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         assign( EA, ea_rAor0_idxd( rA_addr, rB_addr ) );
6814b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         assign( iLo, loadBE(Ity_I32, mkexpr(EA)) );
6815b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         assign( dw, binop( Iop_32HLto64, mkU32( 0 ), mkexpr( iLo ) ) );
6816b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         putFReg( frD_addr, unop( Iop_ReinterpI64asF64, mkexpr( dw ) ) );
6817b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         break;
6818b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      }
6819b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
6820ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      default:
6821ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         vex_printf("dis_fp_load(ppc)(opc2)\n");
6822ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return False;
6823ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
6824ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      break;
6825ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
6826ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   default:
6827ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      vex_printf("dis_fp_load(ppc)(opc1)\n");
6828ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      return False;
6829ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
6830ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   return True;
6831ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
6832ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
6833ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
6834ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
6835ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*
6836ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  Floating Point Store Instructions
6837ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown*/
6838ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic Bool dis_fp_store ( UInt theInstr )
6839ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
6840ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* X-Form, D-Form */
6841ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   UChar opc1      = ifieldOPC(theInstr);
6842ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   UChar frS_addr  = ifieldRegDS(theInstr);
6843ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   UChar rA_addr   = ifieldRegA(theInstr);
6844ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   UChar rB_addr   = ifieldRegB(theInstr);
6845ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   UInt  opc2      = ifieldOPClo10(theInstr);
6846ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   UChar b0        = ifieldBIT0(theInstr);
6847ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   Int   uimm16    = ifieldUIMM16(theInstr);
6848ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
6849ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   Int    simm16 = extend_s_16to32(uimm16);
6850ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   IRTemp frS    = newTemp(Ity_F64);
6851ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   IRType ty     = mode64 ? Ity_I64 : Ity_I32;
6852ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   IRTemp EA     = newTemp(ty);
6853ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   IRTemp rA     = newTemp(ty);
6854ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   IRTemp rB     = newTemp(ty);
6855ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
6856ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   assign( frS, getFReg(frS_addr) );
6857ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   assign( rA,  getIReg(rA_addr) );
6858ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   assign( rB,  getIReg(rB_addr) );
6859ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
6860ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* These are straightforward from a status bits perspective: no
6861ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      funny status or CR bits affected.  For single precision stores,
6862ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      the values are truncated and denormalised (not rounded) to turn
6863ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      them into single precision values. */
6864ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
6865ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   switch (opc1) {
6866ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
6867ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   case 0x34: // stfs (Store Float Single, PPC32 p518)
6868ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      DIP("stfs fr%u,%d(r%u)\n", frS_addr, simm16, rA_addr);
6869ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      assign( EA, ea_rAor0_simm(rA_addr, simm16) );
6870ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* Use Iop_TruncF64asF32 to truncate and possible denormalise
6871ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         the value to be stored in the correct way, without any
6872ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         rounding. */
6873ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      storeBE( mkexpr(EA),
6874ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               unop(Iop_TruncF64asF32, mkexpr(frS)) );
6875ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      break;
6876ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
6877ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   case 0x35: // stfsu (Store Float Single, Update, PPC32 p519)
6878ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (rA_addr == 0)
6879ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return False;
6880ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      DIP("stfsu fr%u,%d(r%u)\n", frS_addr, simm16, rA_addr);
6881ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      assign( EA, ea_rA_simm(rA_addr, simm16) );
6882ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* See comment for stfs */
6883ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      storeBE( mkexpr(EA),
6884ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               unop(Iop_TruncF64asF32, mkexpr(frS)) );
6885ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      putIReg( rA_addr, mkexpr(EA) );
6886ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      break;
6887ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
6888ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   case 0x36: // stfd (Store Float Double, PPC32 p513)
6889ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      DIP("stfd fr%u,%d(r%u)\n", frS_addr, simm16, rA_addr);
6890ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      assign( EA, ea_rAor0_simm(rA_addr, simm16) );
6891ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      storeBE( mkexpr(EA), mkexpr(frS) );
6892ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      break;
6893ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
6894ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   case 0x37: // stfdu (Store Float Double, Update, PPC32 p514)
6895ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (rA_addr == 0)
6896ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return False;
6897ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      DIP("stfdu fr%u,%d(r%u)\n", frS_addr, simm16, rA_addr);
6898ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      assign( EA, ea_rA_simm(rA_addr, simm16) );
6899ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      storeBE( mkexpr(EA), mkexpr(frS) );
6900ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      putIReg( rA_addr, mkexpr(EA) );
6901ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      break;
6902ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
6903ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   case 0x1F:
6904ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (b0 != 0) {
6905ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         vex_printf("dis_fp_store(ppc)(instr,b0)\n");
6906ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return False;
6907ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
6908ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      switch(opc2) {
6909ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case 0x297: // stfsx (Store Float Single Indexed, PPC32 p521)
6910ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         DIP("stfsx fr%u,r%u,r%u\n", frS_addr, rA_addr, rB_addr);
6911ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         assign( EA, ea_rAor0_idxd(rA_addr, rB_addr) );
6912ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         /* See note for stfs */
6913ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         storeBE( mkexpr(EA),
6914ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  unop(Iop_TruncF64asF32, mkexpr(frS)) );
6915ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         break;
6916ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
6917ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case 0x2B7: // stfsux (Store Float Sgl, Update Indxd, PPC32 p520)
6918ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         if (rA_addr == 0)
6919ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            return False;
6920ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         DIP("stfsux fr%u,r%u,r%u\n", frS_addr, rA_addr, rB_addr);
6921ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         assign( EA, ea_rA_idxd(rA_addr, rB_addr) );
6922ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         /* See note for stfs */
6923ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         storeBE( mkexpr(EA),
6924ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  unop(Iop_TruncF64asF32, mkexpr(frS)) );
6925ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         putIReg( rA_addr, mkexpr(EA) );
6926ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         break;
6927ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
6928ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case 0x2D7: // stfdx (Store Float Double Indexed, PPC32 p516)
6929ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         DIP("stfdx fr%u,r%u,r%u\n", frS_addr, rA_addr, rB_addr);
6930ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         assign( EA, ea_rAor0_idxd(rA_addr, rB_addr) );
6931ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         storeBE( mkexpr(EA), mkexpr(frS) );
6932ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         break;
6933ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
6934ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case 0x2F7: // stfdux (Store Float Dbl, Update Indxd, PPC32 p515)
6935ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         if (rA_addr == 0)
6936ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            return False;
6937ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         DIP("stfdux fr%u,r%u,r%u\n", frS_addr, rA_addr, rB_addr);
6938ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         assign( EA, ea_rA_idxd(rA_addr, rB_addr) );
6939ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         storeBE( mkexpr(EA), mkexpr(frS) );
6940ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         putIReg( rA_addr, mkexpr(EA) );
6941ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         break;
6942ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
6943ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case 0x3D7: // stfiwx (Store Float as Int, Indexed, PPC32 p517)
6944ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         // NOTE: POWERPC OPTIONAL, "Graphics Group" (PPC32_GX)
6945ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         DIP("stfiwx fr%u,r%u,r%u\n", frS_addr, rA_addr, rB_addr);
6946ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         assign( EA, ea_rAor0_idxd(rA_addr, rB_addr) );
6947ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         storeBE( mkexpr(EA),
6948ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  unop(Iop_64to32, unop(Iop_ReinterpF64asI64, mkexpr(frS))) );
6949ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         break;
6950ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
6951ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      default:
6952ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         vex_printf("dis_fp_store(ppc)(opc2)\n");
6953ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return False;
6954ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
6955ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      break;
6956ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
6957ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   default:
6958ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      vex_printf("dis_fp_store(ppc)(opc1)\n");
6959ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      return False;
6960ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
6961ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   return True;
6962ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
6963ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
6964ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
6965ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
6966ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*
6967ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  Floating Point Arith Instructions
6968ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown*/
6969ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic Bool dis_fp_arith ( UInt theInstr )
6970ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
6971ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* A-Form */
6972ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   UChar opc1     = ifieldOPC(theInstr);
6973ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   UChar frD_addr = ifieldRegDS(theInstr);
6974ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   UChar frA_addr = ifieldRegA(theInstr);
6975ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   UChar frB_addr = ifieldRegB(theInstr);
6976ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   UChar frC_addr = ifieldRegC(theInstr);
6977ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   UChar opc2     = ifieldOPClo5(theInstr);
6978ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   UChar flag_rC  = ifieldBIT0(theInstr);
6979ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
6980ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   IRTemp  frD = newTemp(Ity_F64);
6981ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   IRTemp  frA = newTemp(Ity_F64);
6982ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   IRTemp  frB = newTemp(Ity_F64);
6983ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   IRTemp  frC = newTemp(Ity_F64);
6984ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   IRExpr* rm  = get_IR_roundingmode();
6985ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
6986ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* By default, we will examine the results of the operation and set
6987ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      fpscr[FPRF] accordingly. */
6988ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   Bool set_FPRF = True;
6989ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
6990ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* By default, if flag_RC is set, we will clear cr1 after the
6991ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      operation.  In reality we should set cr1 to indicate the
6992ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      exception status of the operation, but since we're not
6993ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      simulating exceptions, the exception status will appear to be
6994ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      zero.  Hence cr1 should be cleared if this is a . form insn. */
6995ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   Bool clear_CR1 = True;
6996ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
6997ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   assign( frA, getFReg(frA_addr));
6998ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   assign( frB, getFReg(frB_addr));
6999ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   assign( frC, getFReg(frC_addr));
7000ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
7001ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   switch (opc1) {
7002ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   case 0x3B:
7003ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      switch (opc2) {
7004ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case 0x12: // fdivs (Floating Divide Single, PPC32 p407)
7005ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         if (frC_addr != 0)
7006ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            return False;
7007ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         DIP("fdivs%s fr%u,fr%u,fr%u\n", flag_rC ? ".":"",
7008ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown             frD_addr, frA_addr, frB_addr);
7009ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         assign( frD, triop( Iop_DivF64r32,
7010ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                             rm, mkexpr(frA), mkexpr(frB) ));
7011ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         break;
7012ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
7013ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case 0x14: // fsubs (Floating Subtract Single, PPC32 p430)
7014ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         if (frC_addr != 0)
7015ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            return False;
7016ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         DIP("fsubs%s fr%u,fr%u,fr%u\n", flag_rC ? ".":"",
7017ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown             frD_addr, frA_addr, frB_addr);
7018ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         assign( frD, triop( Iop_SubF64r32,
7019ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                             rm, mkexpr(frA), mkexpr(frB) ));
7020ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         break;
7021ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
7022ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case 0x15: // fadds (Floating Add Single, PPC32 p401)
7023ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         if (frC_addr != 0)
7024ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            return False;
7025ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         DIP("fadds%s fr%u,fr%u,fr%u\n", flag_rC ? ".":"",
7026ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown             frD_addr, frA_addr, frB_addr);
7027ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         assign( frD, triop( Iop_AddF64r32,
7028ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                             rm, mkexpr(frA), mkexpr(frB) ));
7029ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         break;
7030ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
7031ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case 0x16: // fsqrts (Floating SqRt (Single-Precision), PPC32 p428)
7032ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         // NOTE: POWERPC OPTIONAL, "General-Purpose Group" (PPC32_FX)
7033ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         if (frA_addr != 0 || frC_addr != 0)
7034ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            return False;
7035ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         DIP("fsqrts%s fr%u,fr%u\n", flag_rC ? ".":"",
7036ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown             frD_addr, frB_addr);
7037ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         // however illogically, on ppc970 this insn behaves identically
7038ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         // to fsqrt (double-precision).  So use SqrtF64, not SqrtF64r32.
7039ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         assign( frD, binop( Iop_SqrtF64, rm, mkexpr(frB) ));
7040ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         break;
7041ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
7042ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case 0x18: // fres (Floating Reciprocal Estimate Single, PPC32 p421)
7043ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         // NOTE: POWERPC OPTIONAL, "Graphics Group" (PPC32_GX)
7044ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         if (frA_addr != 0 || frC_addr != 0)
7045ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            return False;
7046ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         DIP("fres%s fr%u,fr%u\n", flag_rC ? ".":"",
7047ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown             frD_addr, frB_addr);
7048ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         { IRExpr* ieee_one
7049ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown              = IRExpr_Const(IRConst_F64i(0x3ff0000000000000ULL));
7050ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown           assign( frD, triop( Iop_DivF64r32,
7051ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                               rm,
7052ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                               ieee_one, mkexpr(frB) ));
7053ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         }
7054ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         break;
7055ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
7056ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case 0x19: // fmuls (Floating Multiply Single, PPC32 p414)
7057ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         if (frB_addr != 0)
7058ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            return False;
7059ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         DIP("fmuls%s fr%u,fr%u,fr%u\n", flag_rC ? ".":"",
7060ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown             frD_addr, frA_addr, frC_addr);
7061ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         assign( frD, triop( Iop_MulF64r32,
7062ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                             rm, mkexpr(frA), mkexpr(frC) ));
7063ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         break;
7064ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
7065ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case 0x1A: // frsqrtes (Floating Recip SqRt Est Single)
7066ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         // NOTE: POWERPC OPTIONAL, "Graphics Group" (PPC32_GX)
7067ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         // Undocumented instruction?
7068ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         if (frA_addr != 0 || frC_addr != 0)
7069ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            return False;
7070ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         DIP("frsqrtes%s fr%u,fr%u\n", flag_rC ? ".":"",
7071ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown             frD_addr, frB_addr);
7072ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         assign( frD, unop(Iop_Est5FRSqrt, mkexpr(frB)) );
7073ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         break;
7074ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
7075ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      default:
7076ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         vex_printf("dis_fp_arith(ppc)(3B: opc2)\n");
7077ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return False;
7078ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
7079ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      break;
7080ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
7081ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   case 0x3F:
7082ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      switch (opc2) {
7083ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case 0x12: // fdiv (Floating Div (Double-Precision), PPC32 p406)
7084ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         if (frC_addr != 0)
7085ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            return False;
7086ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         DIP("fdiv%s fr%u,fr%u,fr%u\n", flag_rC ? ".":"",
7087ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown             frD_addr, frA_addr, frB_addr);
7088ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         assign( frD, triop(Iop_DivF64, rm, mkexpr(frA), mkexpr(frB)) );
7089ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         break;
7090ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
7091ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case 0x14: // fsub (Floating Sub (Double-Precision), PPC32 p429)
7092ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         if (frC_addr != 0)
7093ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            return False;
7094ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         DIP("fsub%s fr%u,fr%u,fr%u\n", flag_rC ? ".":"",
7095ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown             frD_addr, frA_addr, frB_addr);
7096ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         assign( frD, triop(Iop_SubF64, rm, mkexpr(frA), mkexpr(frB)) );
7097ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         break;
7098ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
7099ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case 0x15: // fadd (Floating Add (Double-Precision), PPC32 p400)
7100ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         if (frC_addr != 0)
7101ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            return False;
7102ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         DIP("fadd%s fr%u,fr%u,fr%u\n", flag_rC ? ".":"",
7103ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown             frD_addr, frA_addr, frB_addr);
7104ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         assign( frD, triop(Iop_AddF64, rm, mkexpr(frA), mkexpr(frB)) );
7105ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         break;
7106ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
7107ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case 0x16: // fsqrt (Floating SqRt (Double-Precision), PPC32 p427)
7108ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         // NOTE: POWERPC OPTIONAL, "General-Purpose Group" (PPC32_FX)
7109ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         if (frA_addr != 0 || frC_addr != 0)
7110ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            return False;
7111ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         DIP("fsqrt%s fr%u,fr%u\n", flag_rC ? ".":"",
7112ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown             frD_addr, frB_addr);
7113ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         assign( frD, binop(Iop_SqrtF64, rm, mkexpr(frB)) );
7114ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         break;
7115ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
7116ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case 0x17: { // fsel (Floating Select, PPC32 p426)
7117ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         // NOTE: POWERPC OPTIONAL, "Graphics Group" (PPC32_GX)
7118ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         IRTemp cc    = newTemp(Ity_I32);
7119ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         IRTemp cc_b0 = newTemp(Ity_I32);
7120ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
7121ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         DIP("fsel%s fr%u,fr%u,fr%u,fr%u\n", flag_rC ? ".":"",
7122ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown             frD_addr, frA_addr, frC_addr, frB_addr);
7123ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
7124ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         // cc: UN == 0x41, LT == 0x01, GT == 0x00, EQ == 0x40
7125ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         // => GT|EQ == (cc & 0x1 == 0)
7126ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         assign( cc, binop(Iop_CmpF64, mkexpr(frA),
7127ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                       IRExpr_Const(IRConst_F64(0))) );
7128ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         assign( cc_b0, binop(Iop_And32, mkexpr(cc), mkU32(1)) );
7129ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
7130ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         // frD = (frA >= 0.0) ? frC : frB
7131ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         //     = (cc_b0 == 0) ? frC : frB
7132ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         assign( frD,
7133ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                 IRExpr_Mux0X(
7134ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                    unop(Iop_1Uto8,
7135ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                         binop(Iop_CmpEQ32, mkexpr(cc_b0), mkU32(0))),
7136ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                    mkexpr(frB),
7137ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                    mkexpr(frC) ));
7138ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
7139ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         /* One of the rare ones which don't mess with FPRF */
7140ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         set_FPRF = False;
7141ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         break;
7142ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
7143ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
7144ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case 0x18: // fre (Floating Reciprocal Estimate)
7145ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         // NOTE: POWERPC OPTIONAL, "Graphics Group" (PPC32_GX)
7146ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         // Note: unclear whether this insn really exists or not
7147ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         // ppc970 doesn't have it, but POWER5 does
7148ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         if (frA_addr != 0 || frC_addr != 0)
7149ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            return False;
7150ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         DIP("fre%s fr%u,fr%u\n", flag_rC ? ".":"",
7151ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown             frD_addr, frB_addr);
7152ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         { IRExpr* ieee_one
7153ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown              = IRExpr_Const(IRConst_F64i(0x3ff0000000000000ULL));
7154ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown           assign( frD, triop( Iop_DivF64,
7155ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                               rm,
7156ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                               ieee_one, mkexpr(frB) ));
7157ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         }
7158ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         break;
7159ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
7160ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case 0x19: // fmul (Floating Mult (Double Precision), PPC32 p413)
7161ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         if (frB_addr != 0)
7162ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            vex_printf("dis_fp_arith(ppc)(instr,fmul)\n");
7163ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         DIP("fmul%s fr%u,fr%u,fr%u\n", flag_rC ? ".":"",
7164ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown             frD_addr, frA_addr, frC_addr);
7165ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         assign( frD, triop(Iop_MulF64, rm, mkexpr(frA), mkexpr(frC)) );
7166ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         break;
7167ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
7168ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case 0x1A: // frsqrte (Floating Recip SqRt Est., PPC32 p424)
7169ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         // NOTE: POWERPC OPTIONAL, "Graphics Group" (PPC32_GX)
7170ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         if (frA_addr != 0 || frC_addr != 0)
7171ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            return False;
7172ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         DIP("frsqrte%s fr%u,fr%u\n", flag_rC ? ".":"",
7173ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown             frD_addr, frB_addr);
7174ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         assign( frD, unop(Iop_Est5FRSqrt, mkexpr(frB)) );
7175ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         break;
7176ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
7177ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      default:
7178ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         vex_printf("dis_fp_arith(ppc)(3F: opc2)\n");
7179ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return False;
7180ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
7181ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      break;
7182ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
7183ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   default:
7184ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      vex_printf("dis_fp_arith(ppc)(opc1)\n");
7185ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      return False;
7186ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
7187ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
7188ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   putFReg( frD_addr, mkexpr(frD) );
7189ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
7190ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (set_FPRF) {
7191ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      // XXX XXX XXX FIXME
7192ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      // set FPRF from frD
7193ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
7194ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
7195ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (flag_rC && clear_CR1) {
7196ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      putCR321( 1, mkU8(0) );
7197ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      putCR0( 1, mkU8(0) );
7198ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
7199ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
7200ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   return True;
7201ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
7202ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
7203ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
7204ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
7205ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*
7206ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  Floating Point Mult-Add Instructions
7207ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown*/
7208ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic Bool dis_fp_multadd ( UInt theInstr )
7209ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
7210ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* A-Form */
7211ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   UChar opc1     = ifieldOPC(theInstr);
7212ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   UChar frD_addr = ifieldRegDS(theInstr);
7213ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   UChar frA_addr = ifieldRegA(theInstr);
7214ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   UChar frB_addr = ifieldRegB(theInstr);
7215ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   UChar frC_addr = ifieldRegC(theInstr);
7216ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   UChar opc2     = ifieldOPClo5(theInstr);
7217ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   UChar flag_rC  = ifieldBIT0(theInstr);
7218ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
7219ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   IRTemp  frD = newTemp(Ity_F64);
7220ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   IRTemp  frA = newTemp(Ity_F64);
7221ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   IRTemp  frB = newTemp(Ity_F64);
7222ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   IRTemp  frC = newTemp(Ity_F64);
7223ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   IRTemp  rmt = newTemp(Ity_I32);
7224ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   IRExpr* rm;
7225ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
7226ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* By default, we will examine the results of the operation and set
7227ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      fpscr[FPRF] accordingly. */
7228ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   Bool set_FPRF = True;
7229ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
7230ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* By default, if flag_RC is set, we will clear cr1 after the
7231ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      operation.  In reality we should set cr1 to indicate the
7232ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      exception status of the operation, but since we're not
7233ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      simulating exceptions, the exception status will appear to be
7234ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      zero.  Hence cr1 should be cleared if this is a . form insn. */
7235ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   Bool clear_CR1 = True;
7236ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
7237ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* Bind the rounding mode expression to a temp; there's no
7238ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      point in creating gratuitous CSEs, as we know we'll need
7239ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      to use it twice. */
7240ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   assign( rmt, get_IR_roundingmode() );
7241ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   rm = mkexpr(rmt);
7242ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
7243ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   assign( frA, getFReg(frA_addr));
7244ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   assign( frB, getFReg(frB_addr));
7245ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   assign( frC, getFReg(frC_addr));
7246ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
7247ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* The rounding in this is all a bit dodgy.  The idea is to only do
7248ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      one rounding.  That clearly isn't achieveable without dedicated
7249ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      four-input IR primops, although in the single precision case we
7250ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      can sort-of simulate it by doing the inner multiply in double
7251ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      precision.
7252ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
7253ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      In the negated cases, the negation happens after rounding. */
7254ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
7255ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   switch (opc1) {
7256ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   case 0x3B:
7257ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      switch (opc2) {
7258ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case 0x1C: // fmsubs (Floating Mult-Subtr Single, PPC32 p412)
7259ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         DIP("fmsubs%s fr%u,fr%u,fr%u,fr%u\n", flag_rC ? ".":"",
7260ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown             frD_addr, frA_addr, frC_addr, frB_addr);
7261ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         assign( frD, qop( Iop_MSubF64r32, rm,
7262ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                           mkexpr(frA), mkexpr(frC), mkexpr(frB) ));
7263ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         break;
7264ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
7265ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case 0x1D: // fmadds (Floating Mult-Add Single, PPC32 p409)
7266ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         DIP("fmadds%s fr%u,fr%u,fr%u,fr%u\n", flag_rC ? ".":"",
7267ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown             frD_addr, frA_addr, frC_addr, frB_addr);
7268ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         assign( frD, qop( Iop_MAddF64r32, rm,
7269ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                           mkexpr(frA), mkexpr(frC), mkexpr(frB) ));
7270ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         break;
7271ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
7272ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case 0x1E: // fnmsubs (Float Neg Mult-Subtr Single, PPC32 p420)
7273ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         DIP("fnmsubs%s fr%u,fr%u,fr%u,fr%u\n", flag_rC ? ".":"",
7274ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown             frD_addr, frA_addr, frC_addr, frB_addr);
7275ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         assign( frD, unop( Iop_NegF64,
7276ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                      qop( Iop_MSubF64r32, rm,
7277ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                           mkexpr(frA), mkexpr(frC), mkexpr(frB) )));
7278ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         break;
7279ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
7280ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case 0x1F: // fnmadds (Floating Negative Multiply-Add Single, PPC32 p418)
7281ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         DIP("fnmadds%s fr%u,fr%u,fr%u,fr%u\n", flag_rC ? ".":"",
7282ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown             frD_addr, frA_addr, frC_addr, frB_addr);
7283ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         assign( frD, unop( Iop_NegF64,
7284ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                      qop( Iop_MAddF64r32, rm,
7285ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                           mkexpr(frA), mkexpr(frC), mkexpr(frB) )));
7286ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         break;
7287ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
7288ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      default:
7289ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         vex_printf("dis_fp_multadd(ppc)(3B: opc2)\n");
7290ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return False;
7291ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
7292ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      break;
7293ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
7294ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   case 0x3F:
7295ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      switch (opc2) {
7296ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case 0x1C: // fmsub (Float Mult-Sub (Dbl Precision), PPC32 p411)
7297ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         DIP("fmsub%s fr%u,fr%u,fr%u,fr%u\n", flag_rC ? ".":"",
7298ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown             frD_addr, frA_addr, frC_addr, frB_addr);
7299ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         assign( frD, qop( Iop_MSubF64, rm,
7300ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                           mkexpr(frA), mkexpr(frC), mkexpr(frB) ));
7301ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         break;
7302ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
7303ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case 0x1D: // fmadd (Float Mult-Add (Dbl Precision), PPC32 p408)
7304ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         DIP("fmadd%s fr%u,fr%u,fr%u,fr%u\n", flag_rC ? ".":"",
7305ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown             frD_addr, frA_addr, frC_addr, frB_addr);
7306ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         assign( frD, qop( Iop_MAddF64, rm,
7307ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                           mkexpr(frA), mkexpr(frC), mkexpr(frB) ));
7308ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         break;
7309ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
7310ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case 0x1E: // fnmsub (Float Neg Mult-Subtr (Dbl Precision), PPC32 p419)
7311ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         DIP("fnmsub%s fr%u,fr%u,fr%u,fr%u\n", flag_rC ? ".":"",
7312ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown             frD_addr, frA_addr, frC_addr, frB_addr);
7313ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         assign( frD, unop( Iop_NegF64,
7314ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                      qop( Iop_MSubF64, rm,
7315ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                           mkexpr(frA), mkexpr(frC), mkexpr(frB) )));
7316ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         break;
7317ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
7318ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case 0x1F: // fnmadd (Float Neg Mult-Add (Dbl Precision), PPC32 p417)
7319ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         DIP("fnmadd%s fr%u,fr%u,fr%u,fr%u\n", flag_rC ? ".":"",
7320ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown             frD_addr, frA_addr, frC_addr, frB_addr);
7321ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         assign( frD, unop( Iop_NegF64,
7322ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                      qop( Iop_MAddF64, rm,
7323ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                           mkexpr(frA), mkexpr(frC), mkexpr(frB) )));
7324ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         break;
7325ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
7326ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      default:
7327ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         vex_printf("dis_fp_multadd(ppc)(3F: opc2)\n");
7328ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return False;
7329ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
7330ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      break;
7331ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
7332ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   default:
7333ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      vex_printf("dis_fp_multadd(ppc)(opc1)\n");
7334ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      return False;
7335ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
7336ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
7337ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   putFReg( frD_addr, mkexpr(frD) );
7338ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
7339ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (set_FPRF) {
7340ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      // XXX XXX XXX FIXME
7341ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      // set FPRF from frD
7342ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
7343ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
7344ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (flag_rC && clear_CR1) {
7345ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      putCR321( 1, mkU8(0) );
7346ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      putCR0( 1, mkU8(0) );
7347ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
7348ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
7349ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   return True;
7350ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
7351ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
7352b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov/*
7353b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov * fe_flag is set to 1 if any of the following conditions occurs:
7354b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov *  - The floating-point operand in register FRB is a Zero, a
7355b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov *    NaN, an Infinity, or a negative value.
7356b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov *  - e_b is less than or equal to: -970 for double precision; -103 for single precision
7357b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov *  Otherwise fe_flag is set to 0.
7358b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov *
7359b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov * fg_flag is set to 1 if either of the following conditions occurs.
7360b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov *   - The floating-point operand in register FRB is a Zero, an
7361b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov *     Infinity, or a denormalized value.
7362b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov *  Otherwise fg_flag is set to 0.
7363b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov *
7364b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov */
7365b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanovstatic void do_fp_tsqrt(IRTemp frB_Int, Bool sp, IRTemp * fe_flag_tmp, IRTemp * fg_flag_tmp)
7366b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov{
7367b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   // The following temps are for holding intermediate results
7368b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   IRTemp e_b = newTemp(Ity_I32);
7369b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   IRExpr * fe_flag,  * fg_flag;
7370b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   IRTemp frB_exp_shR = newTemp(Ity_I32);
7371b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   UInt bias = sp? 127 : 1023;
7372b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   IRExpr * frbNaN, * frbDenorm, * frBNeg;
7373b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   IRExpr * eb_LTE;
7374b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   IRTemp  frbZero_tmp = newTemp(Ity_I1);
7375b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   IRTemp  frbInf_tmp = newTemp(Ity_I1);
7376b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   *fe_flag_tmp = newTemp(Ity_I32);
7377b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   *fg_flag_tmp = newTemp(Ity_I32);
7378b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   assign( frB_exp_shR, fp_exp_part( frB_Int, sp ) );
7379b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   assign(e_b, binop( Iop_Sub32, mkexpr(frB_exp_shR), mkU32( bias ) ));
7380b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
7381b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   //////////////////  fe_flag tests BEGIN //////////////////////
7382b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   /* We first do all tests that may result in setting fe_flag to '1'.
7383b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov    * (NOTE: These tests are similar to those used for ftdiv.  See do_fp_tdiv()
7384b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov    * for details.)
7385b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov    */
7386b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   frbNaN = sp ? is_NaN_32(frB_Int) : is_NaN(frB_Int);
7387b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   assign( frbInf_tmp, is_Inf(frB_Int, sp) );
7388b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   assign( frbZero_tmp, is_Zero(frB_Int, sp ) );
7389b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   {
7390b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      // Test_value = -970 for double precision
7391b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      UInt test_value = sp ? 0xffffff99 : 0xfffffc36;
7392b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      eb_LTE = binop( Iop_CmpLE32S, mkexpr( e_b ), mkU32( test_value ) );
7393b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   }
7394b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   frBNeg = binop( Iop_CmpEQ32,
7395b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                   binop( Iop_Shr32,
7396b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                          sp ? mkexpr( frB_Int ) : unop( Iop_64HIto32, mkexpr( frB_Int ) ),
7397b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                          mkU8( 31 ) ),
7398b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                   mkU32( 1 ) );
7399b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   //////////////////  fe_flag tests END //////////////////////
7400b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
7401b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   //////////////////  fg_flag tests BEGIN //////////////////////
7402b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   /*
7403b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov    * The following tests were already performed above in the fe_flag
7404b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov    * tests.  So these conditions will result in both fe_ and fg_ flags
7405b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov    * being set.
7406b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov    *   - Test if FRB is Zero
7407b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov    *   - Test if FRB is an Infinity
7408b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov    */
7409b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
7410b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   /*
7411b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov    * Test if FRB holds a denormalized value.  A denormalized value is one where
7412b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov    * the exp is 0 and the fraction is non-zero.
7413b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov    */
7414b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   if (sp) {
7415b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      IRTemp frac_part = newTemp(Ity_I32);
7416b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      assign( frac_part, binop( Iop_And32, mkexpr(frB_Int), mkU32(0x007fffff)) );
7417b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      frbDenorm
7418b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov               = mkAND1( binop( Iop_CmpEQ32, mkexpr( frB_exp_shR ), mkU32( 0 ) ),
7419b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                         binop( Iop_CmpNE32, mkexpr( frac_part ), mkU32( 0 ) ) );
7420b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   } else {
7421b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      IRExpr * hi32, * low32, * fraction_is_nonzero;
7422b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      IRTemp frac_part = newTemp(Ity_I64);
7423b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
7424b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      assign( frac_part, FP_FRAC_PART(frB_Int) );
7425b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      hi32 = unop( Iop_64HIto32, mkexpr( frac_part ) );
7426b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      low32 = unop( Iop_64to32, mkexpr( frac_part ) );
7427b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      fraction_is_nonzero = binop( Iop_CmpNE32, binop( Iop_Or32, low32, hi32 ),
7428b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                                                mkU32( 0 ) );
7429b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      frbDenorm
7430b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov               = mkAND1( binop( Iop_CmpEQ32, mkexpr( frB_exp_shR ), mkU32( 0 ) ),
7431b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                         fraction_is_nonzero );
7432b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   }
7433b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   //////////////////  fg_flag tests END //////////////////////
7434b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
7435b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   /////////////////////////
7436b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   fe_flag = mkOR1( mkexpr( frbZero_tmp ),
7437b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                    mkOR1( frbNaN,
7438b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                           mkOR1( mkexpr( frbInf_tmp ),
7439b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                                  mkOR1( frBNeg, eb_LTE ) ) ) );
7440b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
7441b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   fe_flag = unop(Iop_1Uto32, fe_flag);
7442b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
7443b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   fg_flag = mkOR1( mkexpr( frbZero_tmp ),
7444b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                    mkOR1( mkexpr( frbInf_tmp ), frbDenorm ) );
7445b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   fg_flag = unop(Iop_1Uto32, fg_flag);
7446b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   assign (*fg_flag_tmp, fg_flag);
7447b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   assign (*fe_flag_tmp, fe_flag);
7448b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov}
7449b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov/*
7450b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov * fe_flag is set to 1 if any of the following conditions occurs:
7451b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov *  - The double-precision floating-point operand in register FRA is a NaN or an
7452b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov *    Infinity.
7453b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov *  - The double-precision floating-point operand in register FRB is a Zero, a
7454b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov *    NaN, or an Infinity.
7455b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov *  - e_b is less than or equal to -1022.
7456b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov *  - e_b is greater than or equal to 1021.
7457b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov *  - The double-precision floating-point operand in register FRA is not a zero
7458b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov *    and the difference, e_a - e_b, is greater than or equal to 1023.
7459b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov *  - The double-precision floating-point operand in register FRA is not a zero
7460b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov *    and the difference, e_a - e_b, is less than or equal to -1021.
7461b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov *  - The double-precision floating-point operand in register FRA is not a zero
7462b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov *    and e_a is less than or equal to -970
7463b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov *  Otherwise fe_flag is set to 0.
7464b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov *
7465b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov * fg_flag is set to 1 if either of the following conditions occurs.
7466b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov *   - The double-precision floating-point operand in register FRA is an Infinity.
7467b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov *   - The double-precision floating-point operand in register FRB is a Zero, an
7468b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov *     Infinity, or a denormalized value.
7469b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov *  Otherwise fg_flag is set to 0.
7470b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov *
7471b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov */
7472b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanovstatic void _do_fp_tdiv(IRTemp frA_int, IRTemp frB_int, Bool sp, IRTemp * fe_flag_tmp, IRTemp * fg_flag_tmp)
7473b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov{
7474b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   // The following temps are for holding intermediate results
7475b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   IRTemp e_a = newTemp(Ity_I32);
7476b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   IRTemp e_b = newTemp(Ity_I32);
7477b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   IRTemp frA_exp_shR = newTemp(Ity_I32);
7478b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   IRTemp frB_exp_shR = newTemp(Ity_I32);
7479b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
7480b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   UInt bias = sp? 127 : 1023;
7481b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   *fe_flag_tmp = newTemp(Ity_I32);
7482b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   *fg_flag_tmp = newTemp(Ity_I32);
7483b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
7484b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   /* The following variables hold boolean results from tests
7485b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov    * that are OR'ed together for setting the fe_ and fg_ flags.
7486b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov    * For some cases, the booleans are used more than once, so
7487b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov    * I make those IRTemp's instead of IRExpr's.
7488b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov    */
7489b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   IRExpr * fraNaN, * frbNaN, * frbDenorm;
7490b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   IRExpr * eb_LTE, * eb_GTE, * ea_eb_GTE, * ea_eb_LTE, * ea_LTE;
7491b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   IRTemp  fraInf_tmp = newTemp(Ity_I1);
7492b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   IRTemp  frbZero_tmp = newTemp(Ity_I1);
7493b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   IRTemp  frbInf_tmp = newTemp(Ity_I1);
7494b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   IRTemp  fraNotZero_tmp = newTemp(Ity_I1);
7495b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
7496b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov/* The following are the flags that are set by OR'ing the results of
7497b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov * all the tests done for tdiv.  These flags are the input to the specified CR.
7498b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov */
7499b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   IRExpr * fe_flag, * fg_flag;
7500b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
7501b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   // Create temps that will be used throughout the following tests.
7502b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   assign( frA_exp_shR, fp_exp_part( frA_int, sp ) );
7503b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   assign( frB_exp_shR, fp_exp_part( frB_int, sp ) );
7504b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   /* Let e_[a|b] be the unbiased exponent: i.e. exp - 1023. */
7505b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   assign(e_a, binop( Iop_Sub32, mkexpr(frA_exp_shR), mkU32( bias ) ));
7506b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   assign(e_b, binop( Iop_Sub32, mkexpr(frB_exp_shR), mkU32( bias ) ));
7507b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
7508b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
7509b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   //////////////////  fe_flag tests BEGIN //////////////////////
7510b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   /* We first do all tests that may result in setting fe_flag to '1'. */
7511b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
7512b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   /*
7513b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov    * Test if the double-precision floating-point operand in register FRA is
7514b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov    * a NaN:
7515b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov    */
7516b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   fraNaN = sp ? is_NaN_32(frA_int) : is_NaN(frA_int);
7517b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   /*
7518b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov    * Test if the double-precision floating-point operand in register FRA is
7519b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov    * an Infinity.
7520b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov    */
7521b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   assign(fraInf_tmp, is_Inf(frA_int, sp));
7522b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
7523b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   /*
7524b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov    * Test if the double-precision floating-point operand in register FRB is
7525b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov    * a NaN:
7526b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov    */
7527b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   frbNaN = sp ? is_NaN_32(frB_int) : is_NaN(frB_int);
7528b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   /*
7529b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov    * Test if the double-precision floating-point operand in register FRB is
7530b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov    * an Infinity.
7531b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov    */
7532b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   assign( frbInf_tmp, is_Inf(frB_int, sp) );
7533b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   /*
7534b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov    * Test if the double-precision floating-point operand in register FRB is
7535b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov    * a Zero.
7536b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov    */
7537b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   assign( frbZero_tmp, is_Zero(frB_int, sp) );
7538b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
7539b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   /*
7540b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov    * Test if e_b <= -1022 for double precision;
7541b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov    * or e_b <= -126 for single precision
7542b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov    */
7543b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   {
7544b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      UInt test_value = sp ? 0xffffff82 : 0xfffffc02;
7545b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      eb_LTE = binop(Iop_CmpLE32S, mkexpr(e_b), mkU32(test_value));
7546b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   }
7547b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
7548b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   /*
7549b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov    * Test if e_b >= 1021 (i.e., 1021 < e_b) for double precision;
7550b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov    * or e_b >= -125 (125 < e_b) for single precision
7551b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov    */
7552b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   {
7553b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      Int test_value = sp ? 125 : 1021;
7554b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      eb_GTE = binop(Iop_CmpLT32S, mkU32(test_value), mkexpr(e_b));
7555b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   }
7556b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
7557b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   /*
7558b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov    * Test if FRA != Zero and (e_a - e_b) >= bias
7559b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov    */
7560b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   assign( fraNotZero_tmp, unop( Iop_Not1, is_Zero( frA_int, sp ) ) );
7561b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   ea_eb_GTE = mkAND1( mkexpr( fraNotZero_tmp ),
7562b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                       binop( Iop_CmpLT32S, mkU32( bias ),
7563b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                              binop( Iop_Sub32, mkexpr( e_a ),
7564b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                                     mkexpr( e_b ) ) ) );
7565b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
7566b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   /*
7567b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov    * Test if FRA != Zero and (e_a - e_b) <= [-1021 (double precision) or -125 (single precision)]
7568b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov    */
7569b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   {
7570b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      UInt test_value = sp ? 0xffffff83 : 0xfffffc03;
7571b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
7572b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      ea_eb_LTE = mkAND1( mkexpr( fraNotZero_tmp ),
7573b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                          binop( Iop_CmpLE32S,
7574b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                                 binop( Iop_Sub32,
7575b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                                        mkexpr( e_a ),
7576b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                                        mkexpr( e_b ) ),
7577b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                                        mkU32( test_value ) ) );
7578b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   }
7579b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
7580b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   /*
7581b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov    * Test if FRA != Zero and e_a <= [-970 (double precision) or -103 (single precision)]
7582b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov    */
7583b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   {
7584b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      UInt test_value = 0xfffffc36;  //Int test_value = -970;
7585b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
7586b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      ea_LTE = mkAND1( mkexpr( fraNotZero_tmp ), binop( Iop_CmpLE32S,
7587b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                                                        mkexpr( e_a ),
7588b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                                                        mkU32( test_value ) ) );
7589b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   }
7590b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   //////////////////  fe_flag tests END //////////////////////
7591b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
7592b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   //////////////////  fg_flag tests BEGIN //////////////////////
7593b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   /*
7594b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov    * The following tests were already performed above in the fe_flag
7595b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov    * tests.  So these conditions will result in both fe_ and fg_ flags
7596b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov    * being set.
7597b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov    *   - Test if FRA is an Infinity
7598b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov    *   - Test if FRB ix Zero
7599b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov    *   - Test if FRB is an Infinity
7600b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov    */
7601b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
7602b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   /*
7603b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov    * Test if FRB holds a denormalized value.  A denormalized value is one where
7604b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov    * the exp is 0 and the fraction is non-zero.
7605b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov    */
7606b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   {
7607b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      IRExpr * fraction_is_nonzero;
7608b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
7609b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      if (sp) {
7610b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         fraction_is_nonzero = binop( Iop_CmpNE32, FP_FRAC_PART32(frB_int),
7611b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                                      mkU32( 0 ) );
7612b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      } else {
7613b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         IRExpr * hi32, * low32;
7614b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         IRTemp frac_part = newTemp(Ity_I64);
7615b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         assign( frac_part, FP_FRAC_PART(frB_int) );
7616b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
7617b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         hi32 = unop( Iop_64HIto32, mkexpr( frac_part ) );
7618b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         low32 = unop( Iop_64to32, mkexpr( frac_part ) );
7619b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         fraction_is_nonzero = binop( Iop_CmpNE32, binop( Iop_Or32, low32, hi32 ),
7620b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                                      mkU32( 0 ) );
7621b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      }
7622b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      frbDenorm = mkAND1( binop( Iop_CmpEQ32, mkexpr( frB_exp_shR ),
7623b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                                 mkU32( 0x0 ) ), fraction_is_nonzero );
7624b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
7625b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   }
7626b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   //////////////////  fg_flag tests END //////////////////////
7627b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
7628b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   fe_flag
7629b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   = mkOR1(
7630b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov            fraNaN,
7631b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov            mkOR1(
7632b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                   mkexpr( fraInf_tmp ),
7633b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                   mkOR1(
7634b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                          mkexpr( frbZero_tmp ),
7635b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                          mkOR1(
7636b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                                 frbNaN,
7637b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                                 mkOR1(
7638b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                                        mkexpr( frbInf_tmp ),
7639b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                                        mkOR1( eb_LTE,
7640b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                                               mkOR1( eb_GTE,
7641b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                                                      mkOR1( ea_eb_GTE,
7642b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                                                             mkOR1( ea_eb_LTE,
7643b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                                                                    ea_LTE ) ) ) ) ) ) ) ) );
7644b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
7645b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   fe_flag = unop(Iop_1Uto32, fe_flag);
7646b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
7647b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   fg_flag = mkOR1( mkexpr( fraInf_tmp ), mkOR1( mkexpr( frbZero_tmp ),
7648b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                                                 mkOR1( mkexpr( frbInf_tmp ),
7649b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                                                        frbDenorm ) ) );
7650b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   fg_flag = unop(Iop_1Uto32, fg_flag);
7651b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   assign(*fe_flag_tmp, fe_flag);
7652b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   assign(*fg_flag_tmp, fg_flag);
7653b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov}
7654b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
7655b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov/* See description for _do_fp_tdiv() above. */
7656b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanovstatic IRExpr * do_fp_tdiv(IRTemp frA_int, IRTemp frB_int)
7657b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov{
7658b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   IRTemp  fe_flag, fg_flag;
7659b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   /////////////////////////
7660b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   /* The CR field consists of fl_flag || fg_flag || fe_flag || 0b0
7661b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov    * where fl_flag == 1 on ppc64.
7662b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov    */
7663b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   IRExpr * fl_flag = unop(Iop_Not32, mkU32(0xFFFFFE));
7664b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   fe_flag = fg_flag = IRTemp_INVALID;
7665b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   _do_fp_tdiv(frA_int, frB_int, False/*not single precision*/, &fe_flag, &fg_flag);
7666b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   return binop( Iop_Or32,
7667b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                 binop( Iop_Or32,
7668b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                        binop( Iop_Shl32, fl_flag, mkU8( 3 ) ),
7669b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                        binop( Iop_Shl32, mkexpr(fg_flag), mkU8( 2 ) ) ),
7670b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                 binop( Iop_Shl32, mkexpr(fe_flag), mkU8( 1 ) ) );
7671b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov}
7672b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
7673b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanovstatic Bool dis_fp_tests ( UInt theInstr )
7674b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov{
7675b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   UChar opc1     = ifieldOPC(theInstr);
7676b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   UChar crfD     = toUChar( IFIELD( theInstr, 23, 3 ) );
7677b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   UChar frB_addr = ifieldRegB(theInstr);
7678b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   UChar b0       = ifieldBIT0(theInstr);
7679b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   UInt  opc2     = ifieldOPClo10(theInstr);
7680b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   IRTemp frB_I64     = newTemp(Ity_I64);
7681b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
7682b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   if (opc1 != 0x3F || b0 != 0 ){
7683b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      vex_printf("dis_fp_tests(ppc)(ftdiv)\n");
7684b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      return False;
7685b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   }
7686b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   assign( frB_I64, unop( Iop_ReinterpF64asI64, getFReg( frB_addr ) ) );
7687b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
7688b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   switch (opc2) {
7689b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      case 0x080: // ftdiv
7690b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      {
7691b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         UChar frA_addr = ifieldRegA(theInstr);
7692b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         IRTemp frA_I64     = newTemp(Ity_I64);
7693b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         UChar b21to22  = toUChar( IFIELD( theInstr, 21, 2 ) );
7694b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         if (b21to22 != 0 ) {
7695b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov            vex_printf("dis_fp_tests(ppc)(ftdiv)\n");
7696b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov            return False;
7697b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         }
7698b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
7699b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         assign( frA_I64, unop( Iop_ReinterpF64asI64, getFReg( frA_addr ) ) );
7700b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         putGST_field( PPC_GST_CR, do_fp_tdiv(frA_I64, frB_I64), crfD );
7701b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
7702b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         DIP("ftdiv crf%d,fr%u,fr%u\n", crfD, frA_addr, frB_addr);
7703b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         break;
7704b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      }
7705b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      case 0x0A0: // ftsqrt
7706b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      {
7707b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         IRTemp flags = newTemp(Ity_I32);
7708b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         IRTemp  fe_flag, fg_flag;
7709b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         fe_flag = fg_flag = IRTemp_INVALID;
7710b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         UChar b18to22  = toUChar( IFIELD( theInstr, 18, 5 ) );
7711b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         if ( b18to22 != 0) {
7712b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov            vex_printf("dis_fp_tests(ppc)(ftsqrt)\n");
7713b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov            return False;
7714b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         }
7715b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         DIP("ftsqrt crf%d,fr%u\n", crfD, frB_addr);
7716b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         do_fp_tsqrt(frB_I64, False /* not single precision*/, &fe_flag, &fg_flag);
7717b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         /* The CR field consists of fl_flag || fg_flag || fe_flag || 0b0
7718b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov          * where fl_flag == 1 on ppc64.
7719b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov          */
7720b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         assign( flags,
7721b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                 binop( Iop_Or32,
7722b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                        binop( Iop_Or32, mkU32( 8 ), // fl_flag
7723b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                               binop( Iop_Shl32, mkexpr(fg_flag), mkU8( 2 ) ) ),
7724b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                        binop( Iop_Shl32, mkexpr(fe_flag), mkU8( 1 ) ) ) );
7725b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         putGST_field( PPC_GST_CR, mkexpr(flags), crfD );
7726b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         break;
7727b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      }
7728b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
7729b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      default:
7730b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         vex_printf("dis_fp_tests(ppc)(opc2)\n");
7731b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         return False;
7732ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
7733b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   }
7734b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   return True;
7735b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov}
7736ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
7737ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*
7738ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  Floating Point Compare Instructions
7739ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown*/
7740ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic Bool dis_fp_cmp ( UInt theInstr )
7741ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
7742ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* X-Form */
7743ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   UChar opc1     = ifieldOPC(theInstr);
7744ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   UChar crfD     = toUChar( IFIELD( theInstr, 23, 3 ) );
7745ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   UChar b21to22  = toUChar( IFIELD( theInstr, 21, 2 ) );
7746ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   UChar frA_addr = ifieldRegA(theInstr);
7747ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   UChar frB_addr = ifieldRegB(theInstr);
7748ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   UInt  opc2     = ifieldOPClo10(theInstr);
7749ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   UChar b0       = ifieldBIT0(theInstr);
7750ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
7751ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   IRTemp ccIR    = newTemp(Ity_I32);
7752ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   IRTemp ccPPC32 = newTemp(Ity_I32);
7753ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
7754ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   IRTemp frA     = newTemp(Ity_F64);
7755ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   IRTemp frB     = newTemp(Ity_F64);
7756ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
7757ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (opc1 != 0x3F || b21to22 != 0 || b0 != 0) {
7758ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      vex_printf("dis_fp_cmp(ppc)(instr)\n");
7759ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      return False;
7760ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
7761ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
7762ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   assign( frA, getFReg(frA_addr));
7763ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   assign( frB, getFReg(frB_addr));
7764ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
7765ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   assign( ccIR, binop(Iop_CmpF64, mkexpr(frA), mkexpr(frB)) );
7766ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
7767ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* Map compare result from IR to PPC32 */
7768ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /*
7769ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     FP cmp result | PPC | IR
7770ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     --------------------------
7771ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     UN            | 0x1 | 0x45
7772ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     EQ            | 0x2 | 0x40
7773ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     GT            | 0x4 | 0x00
7774ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     LT            | 0x8 | 0x01
7775ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   */
7776ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
7777ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   // ccPPC32 = Shl(1, (~(ccIR>>5) & 2)
7778ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   //                    | ((ccIR ^ (ccIR>>6)) & 1)
7779ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   assign(
7780ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      ccPPC32,
7781ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      binop(
7782ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         Iop_Shl32,
7783ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         mkU32(1),
7784ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         unop(
7785ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            Iop_32to8,
7786ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            binop(
7787ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               Iop_Or32,
7788ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               binop(
7789ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  Iop_And32,
7790ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  unop(
7791ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                     Iop_Not32,
7792ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                     binop(Iop_Shr32, mkexpr(ccIR), mkU8(5))
7793ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  ),
7794ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  mkU32(2)
7795ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               ),
7796ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               binop(
7797ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  Iop_And32,
7798ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  binop(
7799ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                     Iop_Xor32,
7800ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                     mkexpr(ccIR),
7801ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                     binop(Iop_Shr32, mkexpr(ccIR), mkU8(6))
7802ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  ),
7803ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  mkU32(1)
7804ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               )
7805ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            )
7806ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         )
7807ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      )
7808ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   );
7809ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
7810ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   putGST_field( PPC_GST_CR, mkexpr(ccPPC32), crfD );
7811ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
7812ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* CAB: TODO?: Support writing cc to FPSCR->FPCC ?
7813ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      putGST_field( PPC_GST_FPSCR, mkexpr(ccPPC32), 4 );
7814ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   */
7815ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   // XXX XXX XXX FIXME
7816ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   // Also write the result into FPRF (it's not entirely clear how)
7817ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
7818ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* Note: Differences between fcmpu and fcmpo are only in exception
7819ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      flag settings, which aren't supported anyway. */
7820ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   switch (opc2) {
7821ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   case 0x000: // fcmpu (Floating Compare Unordered, PPC32 p403)
7822ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      DIP("fcmpu crf%d,fr%u,fr%u\n", crfD, frA_addr, frB_addr);
7823ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      break;
7824ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   case 0x020: // fcmpo (Floating Compare Ordered, PPC32 p402)
7825ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      DIP("fcmpo crf%d,fr%u,fr%u\n", crfD, frA_addr, frB_addr);
7826ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      break;
7827ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   default:
7828ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      vex_printf("dis_fp_cmp(ppc)(opc2)\n");
7829ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      return False;
7830ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
7831ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   return True;
7832ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
7833ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
7834ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
7835ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
7836ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*
7837ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  Floating Point Rounding/Conversion Instructions
7838ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown*/
7839ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic Bool dis_fp_round ( UInt theInstr )
7840ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
7841ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* X-Form */
7842ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   UChar opc1     = ifieldOPC(theInstr);
7843ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   UChar b16to20  = ifieldRegA(theInstr);
7844ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   UChar frD_addr = ifieldRegDS(theInstr);
7845ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   UChar frB_addr = ifieldRegB(theInstr);
7846ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   UInt  opc2     = ifieldOPClo10(theInstr);
7847ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   UChar flag_rC  = ifieldBIT0(theInstr);
7848ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
7849ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   IRTemp  frD     = newTemp(Ity_F64);
7850ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   IRTemp  frB     = newTemp(Ity_F64);
7851ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   IRTemp  r_tmp32 = newTemp(Ity_I32);
7852ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   IRTemp  r_tmp64 = newTemp(Ity_I64);
7853ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   IRExpr* rm      = get_IR_roundingmode();
7854ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
7855ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* By default, we will examine the results of the operation and set
7856ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      fpscr[FPRF] accordingly. */
7857ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   Bool set_FPRF = True;
7858ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
7859ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* By default, if flag_RC is set, we will clear cr1 after the
7860ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      operation.  In reality we should set cr1 to indicate the
7861ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      exception status of the operation, but since we're not
7862ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      simulating exceptions, the exception status will appear to be
7863ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      zero.  Hence cr1 should be cleared if this is a . form insn. */
7864ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   Bool clear_CR1 = True;
7865b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   if ((!(opc1 == 0x3F || opc1 == 0x3B)) || b16to20 != 0) {
7866ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      vex_printf("dis_fp_round(ppc)(instr)\n");
7867ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      return False;
7868ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
7869ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
7870ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   assign( frB, getFReg(frB_addr));
7871b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   if (opc1 == 0x3B) {
7872b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      /* The fcfid[u]s instructions (from ISA 2.06) are a bit odd because
7873b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov       * they're very similar to the other instructions handled here, but have
7874b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov       * a different primary opcode.
7875b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov       */
7876b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      switch (opc2) {
7877b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         case 0x34E: // fcfids (Float convert from signed DWord to single precision)
7878b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov            DIP("fcfids%s fr%u,fr%u\n", flag_rC ? ".":"", frD_addr, frB_addr);
7879b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov            assign( r_tmp64, unop( Iop_ReinterpF64asI64, mkexpr(frB)) );
7880b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov            assign( frD, binop( Iop_RoundF64toF32, rm, binop( Iop_I64StoF64, rm,
7881b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                                                              mkexpr( r_tmp64 ) ) ) );
7882b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov            goto putFR;
7883b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
7884b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         case 0x3Ce: // fcfidus (Float convert from unsigned DWord to single precision)
7885b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov            DIP("fcfidus%s fr%u,fr%u\n", flag_rC ? ".":"", frD_addr, frB_addr);
7886b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov            assign( r_tmp64, unop( Iop_ReinterpF64asI64, mkexpr(frB)) );
7887b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov            assign( frD, unop( Iop_F32toF64, binop( Iop_I64UtoF32, rm, mkexpr( r_tmp64 ) ) ) );
7888b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov            goto putFR;
7889b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      }
7890b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   }
7891b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
7892ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
7893ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   switch (opc2) {
7894ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   case 0x00C: // frsp (Float Round to Single, PPC32 p423)
7895ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      DIP("frsp%s fr%u,fr%u\n", flag_rC ? ".":"", frD_addr, frB_addr);
7896ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      assign( frD, binop( Iop_RoundF64toF32, rm, mkexpr(frB) ));
7897ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      break;
7898ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
7899ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   case 0x00E: // fctiw (Float Conv to Int, PPC32 p404)
7900ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      DIP("fctiw%s fr%u,fr%u\n", flag_rC ? ".":"", frD_addr, frB_addr);
7901ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      assign( r_tmp32,
7902ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown              binop(Iop_F64toI32S, rm, mkexpr(frB)) );
7903ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      assign( frD, unop( Iop_ReinterpI64asF64,
7904ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                         unop( Iop_32Uto64, mkexpr(r_tmp32))));
7905ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* FPRF is undefined after fctiw.  Leave unchanged. */
7906ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      set_FPRF = False;
7907ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      break;
7908ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
7909ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   case 0x00F: // fctiwz (Float Conv to Int, Round to Zero, PPC32 p405)
7910ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      DIP("fctiwz%s fr%u,fr%u\n", flag_rC ? ".":"", frD_addr, frB_addr);
7911ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      assign( r_tmp32,
7912ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown              binop(Iop_F64toI32S, mkU32(Irrm_ZERO), mkexpr(frB) ));
7913ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      assign( frD, unop( Iop_ReinterpI64asF64,
7914ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                         unop( Iop_32Uto64, mkexpr(r_tmp32))));
7915ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* FPRF is undefined after fctiwz.  Leave unchanged. */
7916ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      set_FPRF = False;
7917ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      break;
7918ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
7919b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   case 0x08F: case 0x08E: // fctiwu[z]
7920b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      DIP("fctiwu%s%s fr%u,fr%u\n", opc2 == 0x08F ? "z" : "",
7921b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov               flag_rC ? ".":"", frD_addr, frB_addr);
7922b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      assign( r_tmp32,
7923b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov              binop( Iop_F64toI32U,
7924b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                     opc2 == 0x08F ? mkU32( Irrm_ZERO ) : rm,
7925b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                     mkexpr( frB ) ) );
7926b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      assign( frD, unop( Iop_ReinterpI64asF64,
7927b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                         unop( Iop_32Uto64, mkexpr(r_tmp32))));
7928b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      /* FPRF is undefined after fctiwz.  Leave unchanged. */
7929b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      set_FPRF = False;
7930b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      break;
7931b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
7932b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
7933b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   case 0x32E: // fctid (Float Conv to Int DWord, PPC64 p437)
7934b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      DIP("fctid%s fr%u,fr%u\n", flag_rC ? ".":"", frD_addr, frB_addr);
7935b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      assign( r_tmp64,
7936b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov              binop(Iop_F64toI64S, rm, mkexpr(frB)) );
7937b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      assign( frD, unop( Iop_ReinterpI64asF64, mkexpr(r_tmp64)) );
7938ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* FPRF is undefined after fctid.  Leave unchanged. */
7939ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      set_FPRF = False;
7940ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      break;
7941ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
7942ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   case 0x32F: // fctidz (Float Conv to Int DWord, Round to Zero, PPC64 p437)
7943ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      DIP("fctidz%s fr%u,fr%u\n", flag_rC ? ".":"", frD_addr, frB_addr);
7944ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      assign( r_tmp64,
7945ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown              binop(Iop_F64toI64S, mkU32(Irrm_ZERO), mkexpr(frB)) );
7946ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      assign( frD, unop( Iop_ReinterpI64asF64, mkexpr(r_tmp64)) );
7947ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* FPRF is undefined after fctidz.  Leave unchanged. */
7948ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      set_FPRF = False;
7949ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      break;
7950ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
7951b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   case 0x3AE: case 0x3AF: // fctidu[z] (Float Conv to Int DWord Unsigned [Round to Zero])
7952b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   {
7953b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      DIP("fctidu%s%s fr%u,fr%u\n", opc2 == 0x3AE ? "" : "z",
7954b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov               flag_rC ? ".":"", frD_addr, frB_addr);
7955b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      assign( r_tmp64,
7956b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov              binop(Iop_F64toI64U, opc2 == 0x3AE ? rm : mkU32(Irrm_ZERO), mkexpr(frB)) );
7957b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      assign( frD, unop( Iop_ReinterpI64asF64, mkexpr(r_tmp64)) );
7958b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      /* FPRF is undefined after fctidz.  Leave unchanged. */
7959b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      set_FPRF = False;
7960b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      break;
7961b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   }
7962ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   case 0x34E: // fcfid (Float Conv from Int DWord, PPC64 p434)
7963ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      DIP("fcfid%s fr%u,fr%u\n", flag_rC ? ".":"", frD_addr, frB_addr);
7964ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      assign( r_tmp64, unop( Iop_ReinterpF64asI64, mkexpr(frB)) );
7965ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      assign( frD,
7966ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown              binop(Iop_I64StoF64, rm, mkexpr(r_tmp64)) );
7967ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      break;
7968ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
7969b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   case 0x3CE: // fcfidu (Float convert from unsigned DWord)
7970b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      DIP("fcfidu%s fr%u,fr%u\n", flag_rC ? ".":"", frD_addr, frB_addr);
7971b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      assign( r_tmp64, unop( Iop_ReinterpF64asI64, mkexpr(frB)) );
7972b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      assign( frD, binop( Iop_I64UtoF64, rm, mkexpr( r_tmp64 ) ) );
7973b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      break;
7974b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
7975ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   case 0x188: case 0x1A8: case 0x1C8: case 0x1E8: // frin, friz, frip, frim
7976ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      switch(opc2) {
7977ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case 0x188: // frin (Floating Round to Integer Nearest)
7978ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         DIP("frin%s fr%u,fr%u\n", flag_rC ? ".":"", frD_addr, frB_addr);
7979ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         assign( r_tmp64,
7980ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                 binop(Iop_F64toI64S, mkU32(Irrm_NEAREST), mkexpr(frB)) );
7981ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         break;
7982ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case 0x1A8: // friz (Floating Round to Integer Toward Zero)
7983ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         DIP("friz%s fr%u,fr%u\n", flag_rC ? ".":"", frD_addr, frB_addr);
7984ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         assign( r_tmp64,
7985ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                 binop(Iop_F64toI64S, mkU32(Irrm_ZERO), mkexpr(frB)) );
7986ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         break;
7987ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case 0x1C8: // frip (Floating Round to Integer Plus)
7988ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         DIP("frip%s fr%u,fr%u\n", flag_rC ? ".":"", frD_addr, frB_addr);
7989ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         assign( r_tmp64,
7990ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                 binop(Iop_F64toI64S, mkU32(Irrm_PosINF), mkexpr(frB)) );
7991ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         break;
7992ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case 0x1E8: // frim (Floating Round to Integer Minus)
7993ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         DIP("frim%s fr%u,fr%u\n", flag_rC ? ".":"", frD_addr, frB_addr);
7994ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         assign( r_tmp64,
7995ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                 binop(Iop_F64toI64S, mkU32(Irrm_NegINF), mkexpr(frB)) );
7996ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         break;
7997ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
7998ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
7999ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* don't use the rounded integer if frB is outside -9e18..9e18 */
8000ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* F64 has only log10(2**52) significant digits anyway */
8001ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* need to preserve sign of zero */
8002ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /*   frD = (fabs(frB) > 9e18) ? frB :
8003ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               (sign(frB)) ? -fabs((double)r_tmp64) : (double)r_tmp64  */
8004ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      assign(frD, IRExpr_Mux0X( unop(Iop_32to8,
8005ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                     binop(Iop_CmpF64,
8006ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                           IRExpr_Const(IRConst_F64(9e18)),
8007ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                           unop(Iop_AbsF64, mkexpr(frB)))),
8008ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                IRExpr_Mux0X(unop(Iop_32to8,
8009ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                                  binop(Iop_Shr32,
8010ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                                        unop(Iop_64HIto32,
8011ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                                             unop(Iop_ReinterpF64asI64,
8012ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                                                  mkexpr(frB))), mkU8(31))),
8013ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                             binop(Iop_I64StoF64, mkU32(0), mkexpr(r_tmp64) ),
8014ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                             unop(Iop_NegF64,
8015ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                                  unop( Iop_AbsF64,
8016ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                                        binop(Iop_I64StoF64, mkU32(0),
8017ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                                              mkexpr(r_tmp64)) )) ),
8018ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                mkexpr(frB)));
8019ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      break;
8020ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
8021ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   default:
8022ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      vex_printf("dis_fp_round(ppc)(opc2)\n");
8023ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      return False;
8024ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
8025b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy StepanovputFR:
8026ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   putFReg( frD_addr, mkexpr(frD) );
8027ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
8028ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (set_FPRF) {
8029ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      // XXX XXX XXX FIXME
8030ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      // set FPRF from frD
8031ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
8032ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
8033ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (flag_rC && clear_CR1) {
8034ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      putCR321( 1, mkU8(0) );
8035ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      putCR0( 1, mkU8(0) );
8036ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
8037ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
8038ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   return True;
8039ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
8040ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
8041ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*
8042ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  Floating Point Pair Instructions
8043ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown*/
8044ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic Bool dis_fp_pair ( UInt theInstr )
8045ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
8046ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* X-Form/DS-Form */
8047ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   UChar  opc1         = ifieldOPC(theInstr);
8048ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   UChar  frT_hi_addr  = ifieldRegDS(theInstr);
8049ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   UChar  frT_lo_addr  = frT_hi_addr + 1;
8050ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   UChar  rA_addr      = ifieldRegA(theInstr);
8051ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   UChar  rB_addr      = ifieldRegB(theInstr);
8052ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   UInt  uimm16        = ifieldUIMM16(theInstr);
8053ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   Int    simm16       = extend_s_16to32(uimm16);
8054ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   UInt   opc2         = ifieldOPClo10(theInstr);
8055ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   IRType ty           = mode64 ? Ity_I64 : Ity_I32;
8056ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   IRTemp EA_hi        = newTemp(ty);
8057ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   IRTemp EA_lo        = newTemp(ty);
8058ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   IRTemp frT_hi       = newTemp(Ity_F64);
8059ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   IRTemp frT_lo       = newTemp(Ity_F64);
8060ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   UChar b0            = ifieldBIT0(theInstr);
8061ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   Bool is_load        = 0;
8062ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
8063ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if ((frT_hi_addr %2) != 0) {
8064ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      vex_printf("dis_fp_pair(ppc) : odd frT register\n");
8065ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      return False;
8066ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
8067ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
8068ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   switch (opc1) {
8069ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   case 0x1F: // register offset
8070ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      switch(opc2) {
8071ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case 0x317:     // lfdpx (FP Load Double Pair X-form, ISA 2.05  p125)
8072ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         DIP("ldpx fr%u,r%u,r%u\n", frT_hi_addr, rA_addr, rB_addr);
8073ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         is_load = 1;
8074ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         break;
8075ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case 0x397:     // stfdpx (FP STORE Double Pair X-form, ISA 2.05  p125)
8076ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         DIP("stdpx fr%u,r%u,r%u\n", frT_hi_addr, rA_addr, rB_addr);
8077ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         break;
8078ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      default:
8079ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         vex_printf("dis_fp_pair(ppc) : X-form wrong opc2\n");
8080ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return False;
8081ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
8082ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
8083ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (b0 != 0) {
8084ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         vex_printf("dis_fp_pair(ppc)(0x1F,b0)\n");
8085ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return False;
8086ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
8087ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      assign( EA_hi, ea_rAor0_idxd( rA_addr, rB_addr ) );
8088ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      break;
8089ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   case 0x39: // lfdp (FP Load Double Pair DS-form, ISA 2.05  p125)
8090ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      DIP("lfdp fr%u,%d(r%u)\n", frT_hi_addr, simm16, rA_addr);
8091ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      assign( EA_hi, ea_rAor0_simm( rA_addr, simm16  ) );
8092ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      is_load = 1;
8093ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      break;
8094ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   case 0x3d: // stfdp (FP Store Double Pair DS-form, ISA 2.05  p125)
8095ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      DIP("stfdp fr%u,%d(r%u)\n", frT_hi_addr, simm16, rA_addr);
8096ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      assign( EA_hi, ea_rAor0_simm( rA_addr, simm16  ) );
8097ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      break;
8098ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   default:   // immediate offset
8099ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      vex_printf("dis_fp_pair(ppc)(instr)\n");
8100ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      return False;
8101ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
8102ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
8103ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (mode64)
8104ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      assign( EA_lo, binop(Iop_Add64, mkexpr(EA_hi), mkU64(8)) );
8105ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   else
8106ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      assign( EA_lo, binop(Iop_Add32, mkexpr(EA_hi), mkU32(8)) );
8107ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
8108ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   assign( frT_hi, getFReg(frT_hi_addr) );
8109ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   assign( frT_lo, getFReg(frT_lo_addr) );
8110ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
8111ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (is_load) {
8112ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      putFReg( frT_hi_addr, loadBE(Ity_F64, mkexpr(EA_hi)) );
8113ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      putFReg( frT_lo_addr, loadBE(Ity_F64, mkexpr(EA_lo)) );
8114ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   } else {
8115ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      storeBE( mkexpr(EA_hi), mkexpr(frT_hi) );
8116ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      storeBE( mkexpr(EA_lo), mkexpr(frT_lo) );
8117ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
8118ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
8119ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   return True;
8120ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
8121ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
8122ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
8123ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*
8124ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  Floating Point Move Instructions
8125ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown*/
8126ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic Bool dis_fp_move ( UInt theInstr )
8127ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
8128ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* X-Form */
8129ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   UChar opc1     = ifieldOPC(theInstr);
8130ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   UChar frD_addr = ifieldRegDS(theInstr);
8131ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   UChar frA_addr = ifieldRegA(theInstr);
8132ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   UChar frB_addr = ifieldRegB(theInstr);
8133ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   UInt  opc2     = ifieldOPClo10(theInstr);
8134ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   UChar flag_rC  = ifieldBIT0(theInstr);
8135ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
8136ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   IRTemp frD = newTemp(Ity_F64);
8137ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   IRTemp frB = newTemp(Ity_F64);
8138ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   IRTemp itmpB = newTemp(Ity_F64);
8139ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   IRTemp frA;
8140ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   IRTemp signA;
8141ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   IRTemp hiD;
8142ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
8143ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (opc1 != 0x3F || (frA_addr != 0 && opc2 != 0x008)) {
8144ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      vex_printf("dis_fp_move(ppc)(instr)\n");
8145ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      return False;
8146ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
8147ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
8148ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   assign( frB, getFReg(frB_addr));
8149ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
8150ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   switch (opc2) {
8151ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   case 0x008: // fcpsgn (Floating Copy Sign, ISA_V2.05 p126)
8152ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      DIP("fcpsgn%s fr%u,fr%u,fr%u\n", flag_rC ? ".":"", frD_addr, frA_addr,
8153ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown          frB_addr);
8154ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      signA = newTemp(Ity_I32);
8155ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      hiD = newTemp(Ity_I32);
8156ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      itmpB = newTemp(Ity_I64);
8157ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      frA = newTemp(Ity_F64);
8158ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      assign( frA, getFReg(frA_addr) );
8159ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
8160ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* get A's sign bit */
8161ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      assign(signA, binop(Iop_And32,
8162ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                          unop(Iop_64HIto32, unop(Iop_ReinterpF64asI64,
8163ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                                  mkexpr(frA))),
8164ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                          mkU32(0x80000000)) );
8165ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
8166ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      assign( itmpB, unop(Iop_ReinterpF64asI64, mkexpr(frB)) );
8167ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
8168ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* mask off B's sign bit and or in A's sign bit */
8169ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      assign(hiD, binop(Iop_Or32,
8170ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                        binop(Iop_And32,
8171ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                              unop(Iop_64HIto32,
8172ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                   mkexpr(itmpB)),  /* frB's high 32 bits */
8173ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                              mkU32(0x7fffffff)),
8174ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                        mkexpr(signA)) );
8175ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
8176ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* combine hiD/loB into frD */
8177ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      assign( frD, unop(Iop_ReinterpI64asF64,
8178ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                        binop(Iop_32HLto64,
8179ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                              mkexpr(hiD),
8180ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                              unop(Iop_64to32,
8181ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                   mkexpr(itmpB)))) );   /* frB's low 32 bits */
8182ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      break;
8183ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
8184ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   case 0x028: // fneg (Floating Negate, PPC32 p416)
8185ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      DIP("fneg%s fr%u,fr%u\n", flag_rC ? ".":"", frD_addr, frB_addr);
8186ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      assign( frD, unop( Iop_NegF64, mkexpr(frB) ));
8187ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      break;
8188ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
8189ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   case 0x048: // fmr (Floating Move Register, PPC32 p410)
8190ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      DIP("fmr%s fr%u,fr%u\n", flag_rC ? ".":"", frD_addr, frB_addr);
8191ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      assign( frD, mkexpr(frB) );
8192ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      break;
8193ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
8194ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   case 0x088: // fnabs (Floating Negative Absolute Value, PPC32 p415)
8195ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      DIP("fnabs%s fr%u,fr%u\n", flag_rC ? ".":"", frD_addr, frB_addr);
8196ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      assign( frD, unop( Iop_NegF64, unop( Iop_AbsF64, mkexpr(frB) )));
8197ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      break;
8198ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
8199ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   case 0x108: // fabs (Floating Absolute Value, PPC32 p399)
8200ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      DIP("fabs%s fr%u,fr%u\n", flag_rC ? ".":"", frD_addr, frB_addr);
8201ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      assign( frD, unop( Iop_AbsF64, mkexpr(frB) ));
8202ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      break;
8203ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
8204ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   default:
8205ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      vex_printf("dis_fp_move(ppc)(opc2)\n");
8206ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      return False;
8207ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
8208ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
8209ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   putFReg( frD_addr, mkexpr(frD) );
8210ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
8211ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* None of these change FPRF.  cr1 is set in the usual way though,
8212ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if flag_rC is set. */
8213ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
8214ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (flag_rC) {
8215ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      putCR321( 1, mkU8(0) );
8216ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      putCR0( 1, mkU8(0) );
8217ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
8218ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
8219ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   return True;
8220ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
8221ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
8222ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
8223ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
8224ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*
8225ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  Floating Point Status/Control Register Instructions
8226ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown*/
8227ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic Bool dis_fp_scr ( UInt theInstr )
8228ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
8229ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* Many forms - see each switch case */
8230ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   UChar opc1    = ifieldOPC(theInstr);
8231ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   UInt  opc2    = ifieldOPClo10(theInstr);
8232ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   UChar flag_rC = ifieldBIT0(theInstr);
8233ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
8234ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (opc1 != 0x3F) {
8235ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      vex_printf("dis_fp_scr(ppc)(instr)\n");
8236ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      return False;
8237ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
8238ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
8239ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   switch (opc2) {
8240ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   case 0x026: { // mtfsb1 (Move to FPSCR Bit 1, PPC32 p479)
8241ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      // Bit crbD of the FPSCR is set.
8242ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      UChar crbD    = ifieldRegDS(theInstr);
8243ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      UInt  b11to20 = IFIELD(theInstr, 11, 10);
8244ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
8245ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (b11to20 != 0) {
8246ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         vex_printf("dis_fp_scr(ppc)(instr,mtfsb1)\n");
8247ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return False;
8248ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
8249ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      DIP("mtfsb1%s crb%d \n", flag_rC ? ".":"", crbD);
8250ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      putGST_masked( PPC_GST_FPSCR, mkU32(1<<(31-crbD)), 1<<(31-crbD) );
8251ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      break;
8252ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
8253ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
8254ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   case 0x040: { // mcrfs (Move to Condition Register from FPSCR, PPC32 p465)
8255ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      UChar   crfD    = toUChar( IFIELD( theInstr, 23, 3 ) );
8256ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      UChar   b21to22 = toUChar( IFIELD( theInstr, 21, 2 ) );
8257ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      UChar   crfS    = toUChar( IFIELD( theInstr, 18, 3 ) );
8258ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      UChar   b11to17 = toUChar( IFIELD( theInstr, 11, 7 ) );
8259ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      IRTemp  tmp     = newTemp(Ity_I32);
8260ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      IRExpr* fpscr_all;
8261ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (b21to22 != 0 || b11to17 != 0 || flag_rC != 0) {
8262ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         vex_printf("dis_fp_scr(ppc)(instr,mcrfs)\n");
8263ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return False;
8264ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
8265ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      DIP("mcrfs crf%d,crf%d\n", crfD, crfS);
8266ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      vassert(crfD < 8);
8267ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      vassert(crfS < 8);
8268ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      fpscr_all = getGST_masked( PPC_GST_FPSCR, MASK_FPSCR_RN );
8269ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      assign( tmp, binop(Iop_And32,
8270ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                         binop(Iop_Shr32,fpscr_all,mkU8(4 * (7-crfS))),
8271ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                        mkU32(0xF)) );
8272ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      putGST_field( PPC_GST_CR, mkexpr(tmp), crfD );
8273ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      break;
8274ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
8275ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
8276ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   case 0x046: { // mtfsb0 (Move to FPSCR Bit 0, PPC32 p478)
8277ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      // Bit crbD of the FPSCR is cleared.
8278ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      UChar crbD    = ifieldRegDS(theInstr);
8279ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      UInt  b11to20 = IFIELD(theInstr, 11, 10);
8280ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
8281ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (b11to20 != 0) {
8282ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         vex_printf("dis_fp_scr(ppc)(instr,mtfsb0)\n");
8283ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return False;
8284ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
8285ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      DIP("mtfsb0%s crb%d\n", flag_rC ? ".":"", crbD);
8286ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      putGST_masked( PPC_GST_FPSCR, mkU32(0), 1<<(31-crbD) );
8287ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      break;
8288ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
8289ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
8290ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   case 0x086: { // mtfsfi (Move to FPSCR Field Immediate, PPC32 p481)
8291ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      UChar crfD    = toUChar( IFIELD( theInstr, 23, 3 ) );
8292ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      UChar b16to22 = toUChar( IFIELD( theInstr, 16, 7 ) );
8293ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      UChar IMM     = toUChar( IFIELD( theInstr, 12, 4 ) );
8294ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      UChar b11     = toUChar( IFIELD( theInstr, 11, 1 ) );
8295ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
8296ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (b16to22 != 0 || b11 != 0) {
8297ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         vex_printf("dis_fp_scr(ppc)(instr,mtfsfi)\n");
8298ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return False;
8299ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
8300ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      DIP("mtfsfi%s crf%d,%d\n", flag_rC ? ".":"", crfD, IMM);
8301ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      putGST_field( PPC_GST_FPSCR, mkU32(IMM), crfD );
8302ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      break;
8303ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
8304ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
8305ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   case 0x247: { // mffs (Move from FPSCR, PPC32 p468)
8306ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      UChar   frD_addr  = ifieldRegDS(theInstr);
8307ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      UInt    b11to20   = IFIELD(theInstr, 11, 10);
8308ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      IRExpr* fpscr_all = getGST_masked( PPC_GST_FPSCR, MASK_FPSCR_RN );
8309ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
8310ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (b11to20 != 0) {
8311ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         vex_printf("dis_fp_scr(ppc)(instr,mffs)\n");
8312ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return False;
8313ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
8314ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      DIP("mffs%s fr%u\n", flag_rC ? ".":"", frD_addr);
8315ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      putFReg( frD_addr,
8316ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown          unop( Iop_ReinterpI64asF64,
8317ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                unop( Iop_32Uto64, fpscr_all )));
8318ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      break;
8319ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
8320ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
8321ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   case 0x2C7: { // mtfsf (Move to FPSCR Fields, PPC32 p480)
8322ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      UChar b25      = toUChar( IFIELD(theInstr, 25, 1) );
8323ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      UChar FM       = toUChar( IFIELD(theInstr, 17, 8) );
8324ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      UChar frB_addr = ifieldRegB(theInstr);
8325ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      IRTemp frB   = newTemp(Ity_F64);
8326ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      IRTemp rB_32 = newTemp(Ity_I32);
8327ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      Int i, mask;
8328ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
8329ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (b25 == 1) {
8330ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         /* new 64 bit move variant for power 6.  If L field (bit 25) is
8331ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown          * a one do a full 64 bit move.  Note, the FPSCR is not really
8332ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown          * properly modeled.  This instruciton only changes the value of
8333ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown          * the rounding mode.  The HW exception bits do not get set in
8334ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown          * the simulator.  1/12/09
8335ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown          */
8336ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         DIP("mtfsf%s %d,fr%u (L=1)\n", flag_rC ? ".":"", FM, frB_addr);
8337ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         mask = 0xFF;
8338ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
8339ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      } else {
8340ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         DIP("mtfsf%s %d,fr%u\n", flag_rC ? ".":"", FM, frB_addr);
8341ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         // Build 32bit mask from FM:
8342ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         mask = 0;
8343ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         for (i=0; i<8; i++) {
8344ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            if ((FM & (1<<(7-i))) == 1) {
8345ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               mask |= 0xF << (7-i);
8346ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            }
8347ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         }
8348ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
8349ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      assign( frB, getFReg(frB_addr));
8350ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      assign( rB_32, unop( Iop_64to32,
8351ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                           unop( Iop_ReinterpF64asI64, mkexpr(frB) )));
8352ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      putGST_masked( PPC_GST_FPSCR, mkexpr(rB_32), mask );
8353ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      break;
8354ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
8355ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
8356ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   default:
8357ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      vex_printf("dis_fp_scr(ppc)(opc2)\n");
8358ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      return False;
8359ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
8360ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   return True;
8361ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
8362ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
8363ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
8364ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
8365ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*------------------------------------------------------------*/
8366ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*--- AltiVec Instruction Translation                      ---*/
8367ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*------------------------------------------------------------*/
8368ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
8369ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*
8370ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  Altivec Cache Control Instructions (Data Streams)
8371ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown*/
8372ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic Bool dis_av_datastream ( UInt theInstr )
8373ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
8374ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* X-Form */
8375ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   UChar opc1     = ifieldOPC(theInstr);
8376ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   UChar flag_T   = toUChar( IFIELD( theInstr, 25, 1 ) );
8377ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   UChar flag_A   = flag_T;
8378ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   UChar b23to24  = toUChar( IFIELD( theInstr, 23, 2 ) );
8379ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   UChar STRM     = toUChar( IFIELD( theInstr, 21, 2 ) );
8380ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   UChar rA_addr  = ifieldRegA(theInstr);
8381ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   UChar rB_addr  = ifieldRegB(theInstr);
8382ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   UInt  opc2     = ifieldOPClo10(theInstr);
8383ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   UChar b0       = ifieldBIT0(theInstr);
8384ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
8385ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (opc1 != 0x1F || b23to24 != 0 || b0 != 0) {
8386ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      vex_printf("dis_av_datastream(ppc)(instr)\n");
8387ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      return False;
8388ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
8389ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
8390ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   switch (opc2) {
8391ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   case 0x156: // dst (Data Stream Touch, AV p115)
8392ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      DIP("dst%s r%u,r%u,%d\n", flag_T ? "t" : "",
8393ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                rA_addr, rB_addr, STRM);
8394ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      break;
8395ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
8396ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   case 0x176: // dstst (Data Stream Touch for Store, AV p117)
8397ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      DIP("dstst%s r%u,r%u,%d\n", flag_T ? "t" : "",
8398ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                  rA_addr, rB_addr, STRM);
8399ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      break;
8400ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
8401ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   case 0x336: // dss (Data Stream Stop, AV p114)
8402ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (rA_addr != 0 || rB_addr != 0) {
8403ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         vex_printf("dis_av_datastream(ppc)(opc2,dst)\n");
8404ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return False;
8405ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
8406ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (flag_A == 0) {
8407ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         DIP("dss %d\n", STRM);
8408ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      } else {
8409ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         DIP("dssall\n");
8410ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
8411ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      break;
8412ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
8413ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   default:
8414ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      vex_printf("dis_av_datastream(ppc)(opc2)\n");
8415ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      return False;
8416ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
8417ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   return True;
8418ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
8419ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
8420ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*
8421ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  AltiVec Processor Control Instructions
8422ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown*/
8423ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic Bool dis_av_procctl ( UInt theInstr )
8424ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
8425ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* VX-Form */
8426ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   UChar opc1    = ifieldOPC(theInstr);
8427ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   UChar vD_addr = ifieldRegDS(theInstr);
8428ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   UChar vA_addr = ifieldRegA(theInstr);
8429ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   UChar vB_addr = ifieldRegB(theInstr);
8430ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   UInt  opc2    = IFIELD( theInstr, 0, 11 );
8431ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
8432ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (opc1 != 0x4) {
8433ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      vex_printf("dis_av_procctl(ppc)(instr)\n");
8434ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      return False;
8435ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
8436ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
8437ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   switch (opc2) {
8438ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   case 0x604: // mfvscr (Move from VSCR, AV p129)
8439ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (vA_addr != 0 || vB_addr != 0) {
8440ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         vex_printf("dis_av_procctl(ppc)(opc2,dst)\n");
8441ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return False;
8442ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
8443ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      DIP("mfvscr v%d\n", vD_addr);
8444ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      putVReg( vD_addr, unop(Iop_32UtoV128, getGST( PPC_GST_VSCR )) );
8445ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      break;
8446ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
8447ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   case 0x644: { // mtvscr (Move to VSCR, AV p130)
8448ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      IRTemp vB = newTemp(Ity_V128);
8449ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (vD_addr != 0 || vA_addr != 0) {
8450ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         vex_printf("dis_av_procctl(ppc)(opc2,dst)\n");
8451ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return False;
8452ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
8453ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      DIP("mtvscr v%d\n", vB_addr);
8454ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      assign( vB, getVReg(vB_addr));
8455ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      putGST( PPC_GST_VSCR, unop(Iop_V128to32, mkexpr(vB)) );
8456ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      break;
8457ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
8458ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   default:
8459ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      vex_printf("dis_av_procctl(ppc)(opc2)\n");
8460ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      return False;
8461ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
8462ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   return True;
8463ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
8464ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
8465ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*
8466b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov * VSX scalar and vector convert instructions
8467b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov */
8468b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanovstatic Bool
8469b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanovdis_vx_conv ( UInt theInstr, UInt opc2 )
8470b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov{
8471b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   /* XX2-Form */
8472b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   UChar opc1 = ifieldOPC( theInstr );
8473b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   UChar XT = ifieldRegXT( theInstr );
8474b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   UChar XB = ifieldRegXB( theInstr );
8475b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   IRTemp xB, xB2;
8476b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   IRTemp b3, b2, b1, b0;
8477b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   xB = xB2 = IRTemp_INVALID;
8478b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
8479b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   if (opc1 != 0x3C) {
8480b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      vex_printf( "dis_vx_conv(ppc)(instr)\n" );
8481b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      return False;
8482b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   }
8483b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
8484b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   /* Create and assign temps only as needed for the given instruction. */
8485b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   switch (opc2) {
8486b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      // scalar double-precision floating point argument
8487b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      case 0x2B0: case 0x0b0: case 0x290: case 0x212: case 0x090:
8488b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         xB = newTemp(Ity_F64);
8489b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         assign( xB,
8490b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                 unop( Iop_ReinterpI64asF64,
8491b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                       unop( Iop_V128HIto64, getVSReg( XB ) ) ) );
8492b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         break;
8493b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      // vector double-precision floating point arguments
8494b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      case 0x1b0: case 0x312: case 0x390: case 0x190: case 0x3B0:
8495b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
8496b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         xB = newTemp(Ity_F64);
8497b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         xB2 = newTemp(Ity_F64);
8498b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         assign( xB,
8499b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                 unop( Iop_ReinterpI64asF64,
8500b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                       unop( Iop_V128HIto64, getVSReg( XB ) ) ) );
8501b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         assign( xB2,
8502b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                 unop( Iop_ReinterpI64asF64,
8503b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                       unop( Iop_V128to64, getVSReg( XB ) ) ) );
8504b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         break;
8505b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      // vector single precision or [un]signed integer word arguments
8506b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      case 0x130: case 0x392: case 0x330: case 0x310: case 0x110:
8507b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      case 0x1f0: case 0x1d0:
8508b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         b3 = b2 = b1 = b0 = IRTemp_INVALID;
8509b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         breakV128to4x32(getVSReg(XB), &b3, &b2, &b1, &b0);
8510b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         break;
8511b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         // vector [un]signed integer doubleword argument
8512b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      case 0x3f0: case 0x370: case 0x3d0: case 0x350:
8513b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         xB = newTemp(Ity_I64);
8514b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         assign( xB, unop( Iop_V128HIto64, getVSReg( XB ) ) );
8515b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         xB2 = newTemp(Ity_I64);
8516b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         assign( xB2, unop( Iop_V128to64, getVSReg( XB ) ) );
8517b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         break;
8518b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      // scalar [un]signed integer doubleword argument
8519b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      case 0x2F0: case 0x2D0:
8520b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         xB = newTemp(Ity_I64);
8521b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         assign( xB, unop( Iop_V128HIto64, getVSReg( XB ) ) );
8522b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         break;
8523b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      // scalar single precision argument
8524b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      case 0x292: // xscvspdp
8525b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         xB = newTemp(Ity_I32);
8526b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         assign( xB,
8527b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                 unop( Iop_64HIto32, unop( Iop_V128HIto64, getVSReg( XB ) ) ) );
8528b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         break;
8529b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
8530b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      /* Certain instructions have their complete implementation in the main switch statement
8531b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov       * that follows this one; thus we have a "do nothing" case for those instructions here.
8532b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov       */
8533b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      case 0x170: case 0x150:
8534b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         break; // do nothing
8535b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
8536b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      default:
8537b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         vex_printf( "dis_vx_conv(ppc)(opc2)\n" );
8538b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         return False;
8539b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   }
8540b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
8541b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
8542b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   switch (opc2) {
8543b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      case 0x2B0:
8544b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         // xscvdpsxds (VSX Scalar truncate Double-Precision to integer and Convert
8545b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         //             to Signed Integer Doubleword format with Saturate)
8546b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         DIP("xscvdpsxds v%u,v%u\n",  (UInt)XT, (UInt)XB);
8547b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         putVSReg( XT,
8548b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                   binop( Iop_64HLtoV128, binop( Iop_F64toI64S,
8549b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                                                 mkU32( Irrm_ZERO ),
8550b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                                                 mkexpr( xB ) ), mkU64( 0 ) ) );
8551b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         break;
8552b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      case 0x0b0: // xscvdpsxws (VSX Scalar truncate Double-Precision to integer and
8553b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                  //             Convert to Signed Integer Word format with Saturate)
8554b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         DIP("xscvdpsxws v%u,v%u\n",  (UInt)XT, (UInt)XB);
8555b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         putVSReg( XT,
8556b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                   binop( Iop_64HLtoV128,
8557b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                          unop( Iop_32Sto64,
8558b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                                binop( Iop_F64toI32S,
8559b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                                       mkU32( Irrm_ZERO ),
8560b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                                       mkexpr( xB ) ) ),
8561b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                                       mkU64( 0ULL ) ) );
8562b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         break;
8563b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      case 0x290: // xscvdpuxds (VSX Scalar truncate Double-Precision integer and Convert
8564b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                  //             to Unsigned Integer Doubleword format with Saturate)
8565b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         DIP("xscvdpuxds v%u,v%u\n",  (UInt)XT, (UInt)XB);
8566b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         putVSReg( XT,
8567b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                   binop( Iop_64HLtoV128,
8568b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                          binop( Iop_F64toI64U,
8569b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                                 mkU32( Irrm_ZERO ),
8570b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                                 mkexpr( xB ) ),
8571b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                                 mkU64( 0ULL ) ) );
8572b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         break;
8573b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      case 0x2F0:
8574b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         // xscvsxddp (VSX Scalar Convert and round Signed Integer Doubleword to
8575b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         //            Double-Precision format)
8576b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         DIP("xscvsxddp v%u,v%u\n",  (UInt)XT, (UInt)XB);
8577b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         putVSReg( XT,
8578b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                   binop( Iop_64HLtoV128, unop( Iop_ReinterpF64asI64,
8579b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                                                binop( Iop_I64StoF64, get_IR_roundingmode(),
8580b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                                                       mkexpr( xB ) ) ),
8581b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                                                       mkU64( 0 ) ) );
8582b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         break;
8583b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      case 0x2D0:
8584b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         // xscvuxddp (VSX Scalar Convert and round Unsigned Integer Doubleword to
8585b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         //            Double-Precision format)
8586b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         DIP("xscvuxddp v%u,v%u\n",  (UInt)XT, (UInt)XB);
8587b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         putVSReg( XT,
8588b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                   binop( Iop_64HLtoV128, unop( Iop_ReinterpF64asI64,
8589b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                                                binop( Iop_I64UtoF64, get_IR_roundingmode(),
8590b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                                                       mkexpr( xB ) ) ),
8591b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                                                       mkU64( 0 ) ) );
8592b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         break;
8593b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      case 0x1b0: // xvcvdpsxws (VSX Vector truncate Double-Precision to integer and Convert
8594b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                  //             to Signed Integer Word format with Saturate)
8595b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      {
8596b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         IRTemp hiResult_32 = newTemp(Ity_I32);
8597b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         IRTemp loResult_32 = newTemp(Ity_I32);
8598b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         IRExpr* rmZero = mkU32(Irrm_ZERO);
8599b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
8600b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         DIP("xvcvdpsxws v%u,v%u\n",  (UInt)XT, (UInt)XB);
8601b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         assign(hiResult_32, binop(Iop_F64toI32S, rmZero, mkexpr(xB)));
8602b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         assign(loResult_32, binop(Iop_F64toI32S, rmZero, mkexpr(xB2)));
8603b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         putVSReg( XT,
8604b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                   binop( Iop_64HLtoV128,
8605b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                          unop( Iop_32Sto64, mkexpr( hiResult_32 ) ),
8606b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                          unop( Iop_32Sto64, mkexpr( loResult_32 ) ) ) );
8607b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         break;
8608b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      }
8609b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      case 0x130: case 0x110: // xvcvspsxws, xvcvspuxws
8610b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         //  (VSX Vector truncate Single-Precision to integer and
8611b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         //   Convert to [Un]signed Integer Word format with Saturate)
8612b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      {
8613b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         IRExpr * b0_result, * b1_result, * b2_result, * b3_result;
8614b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         IRTemp tempResult = newTemp(Ity_V128);
8615b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         IRTemp res0 = newTemp(Ity_I32);
8616b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         IRTemp res1 = newTemp(Ity_I32);
8617b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         IRTemp res2 = newTemp(Ity_I32);
8618b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         IRTemp res3 = newTemp(Ity_I32);
8619b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         IRTemp hi64 = newTemp(Ity_I64);
8620b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         IRTemp lo64 = newTemp(Ity_I64);
8621b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         Bool un_signed = (opc2 == 0x110);
8622b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         IROp op = un_signed ? Iop_QFtoI32Ux4_RZ : Iop_QFtoI32Sx4_RZ;
8623b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
8624b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         DIP("xvcvsp%sxws v%u,v%u\n", un_signed ? "u" : "s", (UInt)XT, (UInt)XB);
8625b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         /* The xvcvsp{s|u}xws instruction is similar to vct{s|u}xs, except if src is a NaN,
8626b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov          * then result is set to 0x80000000.  */
8627b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         assign(tempResult, unop(op, getVSReg(XB)));
8628b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         assign( hi64, unop(Iop_V128HIto64, mkexpr(tempResult)) );
8629b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         assign( lo64, unop(Iop_V128to64,   mkexpr(tempResult)) );
8630b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         assign( res3, unop(Iop_64HIto32, mkexpr(hi64)) );
8631b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         assign( res2, unop(Iop_64to32,   mkexpr(hi64)) );
8632b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         assign( res1, unop(Iop_64HIto32, mkexpr(lo64)) );
8633b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         assign( res0, unop(Iop_64to32,   mkexpr(lo64)) );
8634b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
8635b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         b3_result = IRExpr_Mux0X(unop(Iop_1Uto8, is_NaN_32(b3)),
8636b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                                  // else: result is from the Iop_QFtoI32{s|u}x4_RZ
8637b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                                  mkexpr(res3),
8638b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                                  // then: result is 0x{8|0}80000000
8639b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                                  mkU32(un_signed ? 0x00000000 : 0x80000000));
8640b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         b2_result = IRExpr_Mux0X(unop(Iop_1Uto8, is_NaN_32(b2)),
8641b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                                  // else: result is from the Iop_QFtoI32{s|u}x4_RZ
8642b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                                  mkexpr(res2),
8643b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                                  // then: result is 0x{8|0}80000000
8644b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                                  mkU32(un_signed ? 0x00000000 : 0x80000000));
8645b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         b1_result = IRExpr_Mux0X(unop(Iop_1Uto8, is_NaN_32(b1)),
8646b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                                  // else: result is from the Iop_QFtoI32{s|u}x4_RZ
8647b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                                  mkexpr(res1),
8648b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                                  // then: result is 0x{8|0}80000000
8649b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                                  mkU32(un_signed ? 0x00000000 : 0x80000000));
8650b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         b0_result = IRExpr_Mux0X(unop(Iop_1Uto8, is_NaN_32(b0)),
8651b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                                  // else: result is from the Iop_QFtoI32{s|u}x4_RZ
8652b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                                  mkexpr(res0),
8653b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                                  // then: result is 0x{8|0}80000000
8654b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                                  mkU32(un_signed ? 0x00000000 : 0x80000000));
8655b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
8656b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         putVSReg( XT,
8657b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                   binop( Iop_64HLtoV128,
8658b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                          binop( Iop_32HLto64, b3_result, b2_result ),
8659b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                          binop( Iop_32HLto64, b1_result, b0_result ) ) );
8660b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         break;
8661b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      }
8662b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      case 0x212: // xscvdpsp (VSX Scalar round Double-Precision to single-precision and
8663b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                  //           Convert to Single-Precision format
8664b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         DIP("xscvdpsp v%u,v%u\n",  (UInt)XT, (UInt)XB);
8665b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         putVSReg( XT,
8666b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                   binop( Iop_64HLtoV128,
8667b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                          binop( Iop_32HLto64,
8668b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                                 unop( Iop_ReinterpF32asI32,
8669b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                                       unop( Iop_TruncF64asF32,
8670b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                                             binop( Iop_RoundF64toF32,
8671b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                                                    get_IR_roundingmode(),
8672b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                                                    mkexpr( xB ) ) ) ),
8673b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                                 mkU32( 0 ) ),
8674b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                          mkU64( 0ULL ) ) );
8675b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         break;
8676b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      case 0x090: // xscvdpuxws (VSX Scalar truncate Double-Precision to integer
8677b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                  //             and Convert to Unsigned Integer Word format with Saturate)
8678b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         DIP("xscvdpuxws v%u,v%u\n",  (UInt)XT, (UInt)XB);
8679b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         putVSReg( XT,
8680b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                   binop( Iop_64HLtoV128,
8681b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                          binop( Iop_32HLto64,
8682b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                                 mkU32( 0 ),
8683b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                                 binop( Iop_F64toI32U,
8684b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                                        mkU32( Irrm_ZERO ),
8685b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                                        mkexpr( xB ) ) ),
8686b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                          mkU64( 0ULL ) ) );
8687b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         break;
8688b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      case 0x292: // xscvspdp (VSX Scalar Convert Single-Precision to Double-Precision format)
8689b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         DIP("xscvspdp v%u,v%u\n",  (UInt)XT, (UInt)XB);
8690b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         putVSReg( XT,
8691b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                   binop( Iop_64HLtoV128,
8692b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                          unop( Iop_ReinterpF64asI64,
8693b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                                unop( Iop_F32toF64,
8694b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                                      unop( Iop_ReinterpI32asF32, mkexpr( xB ) ) ) ),
8695b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                          mkU64( 0ULL ) ) );
8696b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         break;
8697b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      case 0x312: // xvcvdpsp (VSX Vector round Double-Precision to single-precision
8698b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                  //           and Convert to Single-Precision format)
8699b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         DIP("xvcvdpsp v%u,v%u\n",  (UInt)XT, (UInt)XB);
8700b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         putVSReg( XT,
8701b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                   binop( Iop_64HLtoV128,
8702b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                          binop( Iop_32HLto64,
8703b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                                 unop( Iop_ReinterpF32asI32,
8704b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                                       unop( Iop_TruncF64asF32,
8705b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                                             binop( Iop_RoundF64toF32,
8706b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                                                    get_IR_roundingmode(),
8707b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                                                    mkexpr( xB ) ) ) ),
8708b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                                 mkU32( 0 ) ),
8709b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                          binop( Iop_32HLto64,
8710b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                                 unop( Iop_ReinterpF32asI32,
8711b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                                       unop( Iop_TruncF64asF32,
8712b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                                             binop( Iop_RoundF64toF32,
8713b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                                                    get_IR_roundingmode(),
8714b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                                                    mkexpr( xB2 ) ) ) ),
8715b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                                 mkU32( 0 ) ) ) );
8716b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         break;
8717b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      case 0x390: // xvcvdpuxds (VSX Vector truncate Double-Precision to integer
8718b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                  //             and Convert to Unsigned Integer Doubleword format
8719b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                  //             with Saturate)
8720b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         DIP("xvcvdpuxds v%u,v%u\n",  (UInt)XT, (UInt)XB);
8721b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         putVSReg( XT,
8722b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                   binop( Iop_64HLtoV128,
8723b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                          binop( Iop_F64toI64U, mkU32( Irrm_ZERO ), mkexpr( xB ) ),
8724b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                          binop( Iop_F64toI64U, mkU32( Irrm_ZERO ), mkexpr( xB2 ) ) ) );
8725b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         break;
8726b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      case 0x190: // xvcvdpuxws (VSX Vector truncate Double-Precision to integer and
8727b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                  //             Convert to Unsigned Integer Word format with Saturate)
8728b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         DIP("xvcvdpuxws v%u,v%u\n",  (UInt)XT, (UInt)XB);
8729b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         putVSReg( XT,
8730b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                   binop( Iop_64HLtoV128,
8731b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                          binop( Iop_32HLto64,
8732b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                                 binop( Iop_F64toI32U,
8733b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                                        mkU32( Irrm_ZERO ),
8734b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                                        mkexpr( xB ) ),
8735b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                                 mkU32( 0 ) ),
8736b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                          binop( Iop_32HLto64,
8737b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                                 binop( Iop_F64toI32U,
8738b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                                        mkU32( Irrm_ZERO ),
8739b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                                        mkexpr( xB2 ) ),
8740b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                                 mkU32( 0 ) ) ) );
8741b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         break;
8742b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      case 0x392: // xvcvspdp (VSX Vector Convert Single-Precision to Double-Precision format)
8743b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         DIP("xvcvspdp v%u,v%u\n",  (UInt)XT, (UInt)XB);
8744b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         putVSReg( XT,
8745b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                   binop( Iop_64HLtoV128,
8746b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                          unop( Iop_ReinterpF64asI64,
8747b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                                unop( Iop_F32toF64,
8748b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                                      unop( Iop_ReinterpI32asF32, mkexpr( b3 ) ) ) ),
8749b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                          unop( Iop_ReinterpF64asI64,
8750b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                                unop( Iop_F32toF64,
8751b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                                      unop( Iop_ReinterpI32asF32, mkexpr( b1 ) ) ) ) ) );
8752b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         break;
8753b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      case 0x330: // xvcvspsxds (VSX Vector truncate Single-Precision to integer and
8754b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                  //           Convert to Signed Integer Doubleword format with Saturate)
8755b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         DIP("xvcvspsxds v%u,v%u\n",  (UInt)XT, (UInt)XB);
8756b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         putVSReg( XT,
8757b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                   binop( Iop_64HLtoV128,
8758b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                          binop( Iop_F64toI64S,
8759b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                                 mkU32( Irrm_ZERO ),
8760b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                                 unop( Iop_F32toF64,
8761b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                                       unop( Iop_ReinterpI32asF32, mkexpr( b3 ) ) ) ),
8762b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                          binop( Iop_F64toI64S,
8763b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                                 mkU32( Irrm_ZERO ),
8764b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                                 unop( Iop_F32toF64,
8765b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                                       unop( Iop_ReinterpI32asF32, mkexpr( b1 ) ) ) ) ) );
8766b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         break;
8767b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      case 0x310: // xvcvspuxds (VSX Vector truncate Single-Precision to integer and
8768b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                  //            Convert to Unsigned Integer Doubleword format with Saturate)
8769b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         DIP("xvcvspuxds v%u,v%u\n",  (UInt)XT, (UInt)XB);
8770b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         putVSReg( XT,
8771b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                   binop( Iop_64HLtoV128,
8772b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                          binop( Iop_F64toI64U,
8773b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                                 mkU32( Irrm_ZERO ),
8774b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                                 unop( Iop_F32toF64,
8775b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                                       unop( Iop_ReinterpI32asF32, mkexpr( b3 ) ) ) ),
8776b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                          binop( Iop_F64toI64U,
8777b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                                 mkU32( Irrm_ZERO ),
8778b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                                 unop( Iop_F32toF64,
8779b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                                       unop( Iop_ReinterpI32asF32, mkexpr( b1 ) ) ) ) ) );
8780b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         break;
8781b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      case 0x3B0: // xvcvdpsxds (VSX Vector truncate Double-Precision to integer and
8782b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                  //             Convert to Signed Integer Doubleword format with Saturate)
8783b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         DIP("xvcvdpsxds v%u,v%u\n",  (UInt)XT, (UInt)XB);
8784b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         putVSReg( XT,
8785b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                   binop( Iop_64HLtoV128,
8786b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                          binop( Iop_F64toI64S, mkU32( Irrm_ZERO ), mkexpr( xB ) ),
8787b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                          binop( Iop_F64toI64S, mkU32( Irrm_ZERO ), mkexpr( xB2 ) ) ) );
8788b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         break;
8789b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      case 0x3f0: // xvcvsxddp (VSX Vector Convert and round Signed Integer Doubleword
8790b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                  //            to Double-Precision format)
8791b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         DIP("xvcvsxddp v%u,v%u\n",  (UInt)XT, (UInt)XB);
8792b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         putVSReg( XT,
8793b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                   binop( Iop_64HLtoV128,
8794b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                          unop( Iop_ReinterpF64asI64,
8795b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                                binop( Iop_I64StoF64,
8796b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                                       get_IR_roundingmode(),
8797b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                                       mkexpr( xB ) ) ),
8798b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                          unop( Iop_ReinterpF64asI64,
8799b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                                binop( Iop_I64StoF64,
8800b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                                       get_IR_roundingmode(),
8801b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                                       mkexpr( xB2 ) ) ) ) );
8802b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         break;
8803b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      case 0x3d0: // xvcvuxddp (VSX Vector Convert and round Unsigned Integer Doubleword
8804b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                  //            to Double-Precision format)
8805b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         DIP("xvcvuxddp v%u,v%u\n",  (UInt)XT, (UInt)XB);
8806b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         putVSReg( XT,
8807b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                   binop( Iop_64HLtoV128,
8808b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                          unop( Iop_ReinterpF64asI64,
8809b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                                binop( Iop_I64UtoF64,
8810b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                                       get_IR_roundingmode(),
8811b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                                       mkexpr( xB ) ) ),
8812b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                          unop( Iop_ReinterpF64asI64,
8813b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                                binop( Iop_I64UtoF64,
8814b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                                       get_IR_roundingmode(),
8815b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                                       mkexpr( xB2 ) ) ) ) );
8816b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
8817b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         break;
8818b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      case 0x370: // xvcvsxdsp (VSX Vector Convert and round Signed Integer Doubleword
8819b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                  //            to Single-Precision format)
8820b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         DIP("xvcvsxddp v%u,v%u\n",  (UInt)XT, (UInt)XB);
8821b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         putVSReg( XT,
8822b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                   binop( Iop_64HLtoV128,
8823b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                          binop( Iop_32HLto64,
8824b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                                 unop( Iop_ReinterpF32asI32,
8825b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                                       unop( Iop_TruncF64asF32,
8826b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                                             binop( Iop_RoundF64toF32,
8827b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                                                    get_IR_roundingmode(),
8828b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                                                    binop( Iop_I64StoF64,
8829b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                                                           get_IR_roundingmode(),
8830b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                                                           mkexpr( xB ) ) ) ) ),
8831b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                                 mkU32( 0 ) ),
8832b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                          binop( Iop_32HLto64,
8833b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                                 unop( Iop_ReinterpF32asI32,
8834b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                                       unop( Iop_TruncF64asF32,
8835b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                                             binop( Iop_RoundF64toF32,
8836b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                                                    get_IR_roundingmode(),
8837b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                                                    binop( Iop_I64StoF64,
8838b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                                                           get_IR_roundingmode(),
8839b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                                                           mkexpr( xB2 ) ) ) ) ),
8840b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                                 mkU32( 0 ) ) ) );
8841b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         break;
8842b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      case 0x350: // xvcvuxdsp (VSX Vector Convert and round Unsigned Integer Doubleword
8843b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                  //            to Single-Precision format)
8844b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         DIP("xvcvuxddp v%u,v%u\n", (UInt)XT, (UInt)XB);
8845b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         putVSReg( XT,
8846b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                   binop( Iop_64HLtoV128,
8847b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                          binop( Iop_32HLto64,
8848b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                                 unop( Iop_ReinterpF32asI32,
8849b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                                       unop( Iop_TruncF64asF32,
8850b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                                             binop( Iop_RoundF64toF32,
8851b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                                                    get_IR_roundingmode(),
8852b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                                                    binop( Iop_I64UtoF64,
8853b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                                                           get_IR_roundingmode(),
8854b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                                                           mkexpr( xB ) ) ) ) ),
8855b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                                 mkU32( 0 ) ),
8856b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                          binop( Iop_32HLto64,
8857b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                                 unop( Iop_ReinterpF32asI32,
8858b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                                       unop( Iop_TruncF64asF32,
8859b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                                             binop( Iop_RoundF64toF32,
8860b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                                                    get_IR_roundingmode(),
8861b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                                                    binop( Iop_I64UtoF64,
8862b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                                                           get_IR_roundingmode(),
8863b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                                                           mkexpr( xB2 ) ) ) ) ),
8864b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                                 mkU32( 0 ) ) ) );
8865b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         break;
8866b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
8867b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      case 0x1f0: // xvcvsxwdp (VSX Vector Convert Signed Integer Word to Double-Precision format)
8868b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         DIP("xvcvsxwdp v%u,v%u\n",  (UInt)XT, (UInt)XB);
8869b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         putVSReg( XT,
8870b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                   binop( Iop_64HLtoV128,
8871b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                          unop( Iop_ReinterpF64asI64,
8872b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                                binop( Iop_I64StoF64, get_IR_roundingmode(),
8873b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                                       unop( Iop_32Sto64, mkexpr( b3 ) ) ) ),
8874b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                          unop( Iop_ReinterpF64asI64,
8875b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                                binop( Iop_I64StoF64, get_IR_roundingmode(),
8876b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                                       unop( Iop_32Sto64, mkexpr( b1 ) ) ) ) ) );
8877b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         break;
8878b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      case 0x1d0: // xvcvuxwdp (VSX Vector Convert Unsigned Integer Word to Double-Precision format)
8879b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         DIP("xvcvuxwdp v%u,v%u\n",  (UInt)XT, (UInt)XB);
8880b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         putVSReg( XT,
8881b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                   binop( Iop_64HLtoV128,
8882b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                          unop( Iop_ReinterpF64asI64,
8883b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                                binop( Iop_I64UtoF64, get_IR_roundingmode(),
8884b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                                       unop( Iop_32Uto64, mkexpr( b3 ) ) ) ),
8885b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                          unop( Iop_ReinterpF64asI64,
8886b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                                binop( Iop_I64UtoF64, get_IR_roundingmode(),
8887b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                                       unop( Iop_32Uto64, mkexpr( b1 ) ) ) ) ) );
8888b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         break;
8889b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      case 0x170: // xvcvsxwsp (VSX Vector Convert Signed Integer Word to Single-Precision format)
8890b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         DIP("xvcvsxwsp v%u,v%u\n",  (UInt)XT, (UInt)XB);
8891b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         putVSReg( XT, unop( Iop_I32StoFx4, getVSReg( XB ) ) );
8892b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         break;
8893b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      case 0x150: // xvcvuxwsp (VSX Vector Convert Unsigned Integer Word to Single-Precision format)
8894b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         DIP("xvcvuxwsp v%u,v%u\n",  (UInt)XT, (UInt)XB);
8895b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         putVSReg( XT, unop( Iop_I32UtoFx4, getVSReg( XB ) ) );
8896b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         break;
8897b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
8898b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      default:
8899b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         vex_printf( "dis_vx_conv(ppc)(opc2)\n" );
8900b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         return False;
8901b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   }
8902b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   return True;
8903b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov}
8904b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
8905b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov/*
8906b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov * VSX vector Double Precision Floating Point Arithmetic Instructions
8907b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov */
8908b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanovstatic Bool
8909b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanovdis_vxv_dp_arith ( UInt theInstr, UInt opc2 )
8910b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov{
8911b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   /* XX3-Form */
8912b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   UChar opc1 = ifieldOPC( theInstr );
8913b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   UChar XT = ifieldRegXT( theInstr );
8914b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   UChar XA = ifieldRegXA( theInstr );
8915b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   UChar XB = ifieldRegXB( theInstr );
8916b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   IRExpr* rm = get_IR_roundingmode();
8917b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   IRTemp frA = newTemp(Ity_F64);
8918b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   IRTemp frB = newTemp(Ity_F64);
8919b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   IRTemp frA2 = newTemp(Ity_F64);
8920b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   IRTemp frB2 = newTemp(Ity_F64);
8921b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
8922b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   if (opc1 != 0x3C) {
8923b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      vex_printf( "dis_vxv_dp_arith(ppc)(instr)\n" );
8924b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      return False;
8925b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   }
8926b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
8927b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   assign(frA,  unop(Iop_ReinterpI64asF64, unop(Iop_V128HIto64, getVSReg( XA ))));
8928b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   assign(frB,  unop(Iop_ReinterpI64asF64, unop(Iop_V128HIto64, getVSReg( XB ))));
8929b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   assign(frA2, unop(Iop_ReinterpI64asF64, unop(Iop_V128to64, getVSReg( XA ))));
8930b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   assign(frB2, unop(Iop_ReinterpI64asF64, unop(Iop_V128to64, getVSReg( XB ))));
8931b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
8932b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   switch (opc2) {
8933b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      case 0x1E0: // xvdivdp (VSX Vector Divide Double-Precision)
8934b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      case 0x1C0: // xvmuldp (VSX Vector Multiply Double-Precision)
8935b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      case 0x180: // xvadddp (VSX Vector Add Double-Precision)
8936b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      case 0x1A0: // xvsubdp (VSX Vector Subtract Double-Precision)
8937b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      {
8938b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         IROp mOp;
8939b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         Char * oper_name;
8940b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         switch (opc2) {
8941b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov            case 0x1E0:
8942b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov               mOp = Iop_DivF64;
8943b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov               oper_name = "div";
8944b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov               break;
8945b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov            case 0x1C0:
8946b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov               mOp = Iop_MulF64;
8947b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov               oper_name = "mul";
8948b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov               break;
8949b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov            case 0x180:
8950b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov               mOp = Iop_AddF64;
8951b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov               oper_name = "add";
8952b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov               break;
8953b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov            case 0x1A0:
8954b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov               mOp = Iop_SubF64;
8955b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov               oper_name = "sub";
8956b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov               break;
8957b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
8958b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov            default:
8959b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov               vpanic("The impossible happened: dis_vxv_dp_arith(ppc)");
8960b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         }
8961b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         IRTemp hiResult = newTemp(Ity_I64);
8962b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         IRTemp loResult = newTemp(Ity_I64);
8963b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         DIP("xv%sdp v%d,v%d,v%d\n", oper_name, (UInt)XT, (UInt)XA, (UInt)XB);
8964b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
8965b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         assign( hiResult,
8966b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                 unop( Iop_ReinterpF64asI64,
8967b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                       triop( mOp, rm, mkexpr( frA ), mkexpr( frB ) ) ) );
8968b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         assign( loResult,
8969b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                 unop( Iop_ReinterpF64asI64,
8970b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                       triop( mOp, rm, mkexpr( frA2 ), mkexpr( frB2 ) ) ) );
8971b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         putVSReg( XT,
8972b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                   binop( Iop_64HLtoV128, mkexpr( hiResult ), mkexpr( loResult ) ) );
8973b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         break;
8974b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      }
8975b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      case 0x196: // xvsqrtdp
8976b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      {
8977b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         IRTemp hiResult = newTemp(Ity_I64);
8978b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         IRTemp loResult = newTemp(Ity_I64);
8979b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         DIP("xvsqrtdp v%d,v%d\n", (UInt)XT, (UInt)XB);
8980b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
8981b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         assign( hiResult,
8982b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                 unop( Iop_ReinterpF64asI64,
8983b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                       binop( Iop_SqrtF64, rm, mkexpr( frB ) ) ) );
8984b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         assign( loResult,
8985b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                 unop( Iop_ReinterpF64asI64,
8986b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                       binop( Iop_SqrtF64, rm, mkexpr( frB2 ) ) ) );
8987b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         putVSReg( XT,
8988b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                   binop( Iop_64HLtoV128, mkexpr( hiResult ), mkexpr( loResult ) ) );
8989b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         break;
8990b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      }
8991b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      case 0x184: case 0x1A4: // xvmaddadp, xvmaddmdp (VSX Vector Multiply-Add Double-Precision)
8992b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      case 0x1C4: case 0x1E4: // xvmsubadp, xvmsubmdp (VSX Vector Multiply-Subtract Double-Precision)
8993b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      case 0x384: case 0x3A4: // xvnmaddadp, xvnmaddmdp (VSX Vector Negate Multiply-Add Double-Precision)
8994b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      case 0x3C4: case 0x3E4: // xvnmsubadp, xvnmsubmdp (VSX Vector Negate Multiply-Subtract Double-Precision)
8995b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      {
8996b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         /* xvm{add|sub}mdp XT,XA,XB is element-wise equivalent to fm{add|sub} FRT,FRA,FRC,FRB with . . .
8997b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov          *    XT == FRC
8998b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov          *    XA == FRA
8999b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov          *    XB == FRB
9000b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov          *
9001b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov          * and for xvm{add|sub}adp . . .
9002b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov          *    XT == FRB
9003b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov          *    XA == FRA
9004b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov          *    XB == FRC
9005b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov          */
9006b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         Bool negate;
9007b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         IROp mOp = Iop_INVALID;
9008b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         Char * oper_name = NULL;
9009b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         Bool mdp = False;
9010b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
9011b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         switch (opc2) {
9012b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov            case 0x184: case 0x1A4:
9013b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov            case 0x384: case 0x3A4:
9014b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov               mOp = Iop_MAddF64;
9015b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov               oper_name = "add";
9016b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov               mdp = (opc2 & 0x0FF) == 0x0A4;
9017b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov               break;
9018b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
9019b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov            case 0x1C4: case 0x1E4:
9020b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov            case 0x3C4: case 0x3E4:
9021b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov               mOp = Iop_MSubF64;
9022b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov               oper_name = "sub";
9023b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov               mdp = (opc2 & 0x0FF) == 0x0E4;
9024b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov               break;
9025b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
9026b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov            default:
9027b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov               vpanic("The impossible happened: dis_vxv_sp_arith(ppc)");
9028b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         }
9029b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
9030b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         switch (opc2) {
9031b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov            case 0x384: case 0x3A4:
9032b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov            case 0x3C4: case 0x3E4:
9033b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov               negate = True;
9034b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov               break;
9035b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov            default:
9036b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov               negate = False;
9037b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         }
9038b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         IRTemp hiResult = newTemp(Ity_I64);
9039b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         IRTemp loResult = newTemp(Ity_I64);
9040b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         IRTemp frT = newTemp(Ity_F64);
9041b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         IRTemp frT2 = newTemp(Ity_F64);
9042b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         DIP("xv%sm%s%s v%d,v%d,v%d\n", negate ? "n" : "", oper_name, mdp ? "mdp" : "adp",
9043b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov             (UInt)XT, (UInt)XA, (UInt)XB);
9044b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         assign(frT,  unop(Iop_ReinterpI64asF64, unop(Iop_V128HIto64, getVSReg( XT ) ) ) );
9045b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         assign(frT2, unop(Iop_ReinterpI64asF64, unop(Iop_V128to64, getVSReg( XT ) ) ) );
9046b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
9047b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         assign( hiResult,
9048b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                 unop( Iop_ReinterpF64asI64,
9049b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                       qop( mOp,
9050b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                            rm,
9051b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                            mkexpr( frA ),
9052b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                            mkexpr( mdp ? frT : frB ),
9053b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                            mkexpr( mdp ? frB : frT ) ) ) );
9054b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         assign( loResult,
9055b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                 unop( Iop_ReinterpF64asI64,
9056b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                       qop( mOp,
9057b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                            rm,
9058b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                            mkexpr( frA2 ),
9059b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                            mkexpr( mdp ? frT2 : frB2 ),
9060b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                            mkexpr( mdp ? frB2 : frT2 ) ) ) );
9061b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         putVSReg( XT,
9062b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                   binop( Iop_64HLtoV128,
9063b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                          mkexpr( negate ? getNegatedResult( hiResult )
9064b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                                         : hiResult ),
9065b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                          mkexpr( negate ? getNegatedResult( loResult )
9066b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                                         : loResult ) ) );
9067b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         break;
9068b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      }
9069b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      case 0x1D4: // xvtsqrtdp (VSX Vector Test for software Square Root Double-Precision)
9070b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      {
9071b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         IRTemp frBHi_I64 = newTemp(Ity_I64);
9072b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         IRTemp frBLo_I64 = newTemp(Ity_I64);
9073b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         IRTemp flagsHi = newTemp(Ity_I32);
9074b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         IRTemp flagsLo = newTemp(Ity_I32);
9075b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         UChar crfD     = toUChar( IFIELD( theInstr, 23, 3 ) );
9076b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         IRTemp  fe_flagHi, fg_flagHi, fe_flagLo, fg_flagLo;
9077b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         fe_flagHi = fg_flagHi = fe_flagLo = fg_flagLo = IRTemp_INVALID;
9078b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
9079b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         DIP("xvtsqrtdp cr%d,v%d\n", (UInt)crfD, (UInt)XB);
9080b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         assign( frBHi_I64, unop(Iop_V128HIto64, getVSReg( XB )) );
9081b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         assign( frBLo_I64, unop(Iop_V128to64, getVSReg( XB )) );
9082b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         do_fp_tsqrt(frBHi_I64, False /*not single precision*/, &fe_flagHi, &fg_flagHi);
9083b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         do_fp_tsqrt(frBLo_I64, False /*not single precision*/, &fe_flagLo, &fg_flagLo);
9084b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         /* The CR field consists of fl_flag || fg_flag || fe_flag || 0b0
9085b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov          * where fl_flag == 1 on ppc64.
9086b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov          */
9087b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         assign( flagsHi,
9088b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                 binop( Iop_Or32,
9089b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                        binop( Iop_Or32, mkU32( 8 ), // fl_flag
9090b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                               binop( Iop_Shl32, mkexpr(fg_flagHi), mkU8( 2 ) ) ),
9091b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                        binop( Iop_Shl32, mkexpr(fe_flagHi), mkU8( 1 ) ) ) );
9092b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         assign( flagsLo,
9093b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                 binop( Iop_Or32,
9094b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                        binop( Iop_Or32, mkU32( 8 ), // fl_flag
9095b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                               binop( Iop_Shl32, mkexpr(fg_flagLo), mkU8( 2 ) ) ),
9096b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                        binop( Iop_Shl32, mkexpr(fe_flagLo), mkU8( 1 ) ) ) );
9097b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         putGST_field( PPC_GST_CR,
9098b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                       binop( Iop_Or32, mkexpr( flagsHi ), mkexpr( flagsLo ) ),
9099b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                       crfD );
9100b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         break;
9101b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      }
9102b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      case 0x1F4: // xvtdivdp (VSX Vector Test for software Divide Double-Precision)
9103b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      {
9104b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         IRTemp frBHi_I64 = newTemp(Ity_I64);
9105b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         IRTemp frBLo_I64 = newTemp(Ity_I64);
9106b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         IRTemp frAHi_I64 = newTemp(Ity_I64);
9107b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         IRTemp frALo_I64 = newTemp(Ity_I64);
9108b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         IRTemp flagsHi = newTemp(Ity_I32);
9109b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         IRTemp flagsLo = newTemp(Ity_I32);
9110b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         UChar crfD     = toUChar( IFIELD( theInstr, 23, 3 ) );
9111b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         IRTemp  fe_flagHi, fg_flagHi, fe_flagLo, fg_flagLo;
9112b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         fe_flagHi = fg_flagHi = fe_flagLo = fg_flagLo = IRTemp_INVALID;
9113b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
9114b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         DIP("xvtdivdp cr%d,v%d,v%d\n", (UInt)crfD, (UInt)XA, (UInt)XB);
9115b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         assign( frAHi_I64, unop(Iop_V128HIto64, getVSReg( XA )) );
9116b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         assign( frALo_I64, unop(Iop_V128to64, getVSReg( XA )) );
9117b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         assign( frBHi_I64, unop(Iop_V128HIto64, getVSReg( XB )) );
9118b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         assign( frBLo_I64, unop(Iop_V128to64, getVSReg( XB )) );
9119b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
9120b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         _do_fp_tdiv(frAHi_I64, frBHi_I64, False/*dp*/, &fe_flagHi, &fg_flagHi);
9121b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         _do_fp_tdiv(frALo_I64, frBLo_I64, False/*dp*/, &fe_flagLo, &fg_flagLo);
9122b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         /* The CR field consists of fl_flag || fg_flag || fe_flag || 0b0
9123b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov          * where fl_flag == 1 on ppc64.
9124b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov          */
9125b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         assign( flagsHi,
9126b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                 binop( Iop_Or32,
9127b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                        binop( Iop_Or32, mkU32( 8 ), // fl_flag
9128b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                               binop( Iop_Shl32, mkexpr(fg_flagHi), mkU8( 2 ) ) ),
9129b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                        binop( Iop_Shl32, mkexpr(fe_flagHi), mkU8( 1 ) ) ) );
9130b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         assign( flagsLo,
9131b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                 binop( Iop_Or32,
9132b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                        binop( Iop_Or32, mkU32( 8 ), // fl_flag
9133b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                               binop( Iop_Shl32, mkexpr(fg_flagLo), mkU8( 2 ) ) ),
9134b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                        binop( Iop_Shl32, mkexpr(fe_flagLo), mkU8( 1 ) ) ) );
9135b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         putGST_field( PPC_GST_CR,
9136b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                       binop( Iop_Or32, mkexpr( flagsHi ), mkexpr( flagsLo ) ),
9137b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                       crfD );
9138b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         break;
9139b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      }
9140b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
9141b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      default:
9142b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         vex_printf( "dis_vxv_dp_arith(ppc)(opc2)\n" );
9143b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         return False;
9144b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   }
9145b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   return True;
9146b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov}
9147b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
9148b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov/*
9149b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov * VSX vector Single Precision Floating Point Arithmetic Instructions
9150b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov */
9151b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanovstatic Bool
9152b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanovdis_vxv_sp_arith ( UInt theInstr, UInt opc2 )
9153b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov{
9154b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   /* XX3-Form */
9155b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   UChar opc1 = ifieldOPC( theInstr );
9156b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   UChar XT = ifieldRegXT( theInstr );
9157b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   UChar XA = ifieldRegXA( theInstr );
9158b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   UChar XB = ifieldRegXB( theInstr );
9159b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   IRExpr* rm = get_IR_roundingmode();
9160b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   IRTemp a3, a2, a1, a0;
9161b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   IRTemp b3, b2, b1, b0;
9162b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   IRTemp res0 = newTemp(Ity_I32);
9163b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   IRTemp res1 = newTemp(Ity_I32);
9164b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   IRTemp res2 = newTemp(Ity_I32);
9165b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   IRTemp res3 = newTemp(Ity_I32);
9166b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
9167b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   a3 = a2 = a1 = a0 = IRTemp_INVALID;
9168b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   b3 = b2 = b1 = b0 = IRTemp_INVALID;
9169b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
9170b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   if (opc1 != 0x3C) {
9171b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      vex_printf( "dis_vxv_sp_arith(ppc)(instr)\n" );
9172b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      return False;
9173b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   }
9174b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
9175b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   switch (opc2) {
9176b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      case 0x100: // xvaddsp (VSX Vector Add Single-Precision)
9177b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         DIP("xvaddsp v%d,v%d,v%d\n", (UInt)XT, (UInt)XA, (UInt)XB);
9178b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         putVSReg( XT, binop(Iop_Add32Fx4, getVSReg( XA ), getVSReg( XB )) );
9179b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         break;
9180b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
9181b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      case 0x140: // xvmulsp (VSX Vector Multiply Single-Precision)
9182b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         DIP("xvmulsp v%d,v%d,v%d\n", (UInt)XT, (UInt)XA, (UInt)XB);
9183b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         putVSReg( XT, binop(Iop_Mul32Fx4, getVSReg( XA ), getVSReg( XB )) );
9184b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         break;
9185b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
9186b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      case 0x120: // xvsubsp (VSX Vector Subtract Single-Precision)
9187b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         DIP("xvsubsp v%d,v%d,v%d\n", (UInt)XT, (UInt)XA, (UInt)XB);
9188b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         putVSReg( XT, binop(Iop_Sub32Fx4, getVSReg( XA ), getVSReg( XB )) );
9189b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         break;
9190b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
9191b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      case 0x160: // xvdivsp (VSX Vector Divide Single-Precision)
9192b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      {
9193b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         /* Iop_Div32Fx4 is not implemented for ppc64 (in host_ppc_{isel|defs}.c.
9194b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov          * So there are two choices:
9195b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov          *   1. Implement the xvdivsp with a native insn; or
9196b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov          *   2. Extract the 4 single precision floats from each vector
9197b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov          *      register inputs and perform fdivs on each pair
9198b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov          * I will do the latter, due to the general philosophy of
9199b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov          * reusing existing implementations when practical.
9200b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov          */
9201b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         DIP("xvdivsp v%d,v%d,v%d\n", (UInt)XT, (UInt)XA, (UInt)XB);
9202b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         breakV128to4xF64( getVSReg( XA ), &a3, &a2, &a1, &a0 );
9203b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         breakV128to4xF64( getVSReg( XB ), &b3, &b2, &b1, &b0 );
9204b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
9205b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         assign( res0,
9206b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov              unop( Iop_ReinterpF32asI32,
9207b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                    unop( Iop_TruncF64asF32,
9208b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                          triop( Iop_DivF64r32, rm, mkexpr( a0 ), mkexpr( b0 ) ) ) ) );
9209b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         assign( res1,
9210b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                 unop( Iop_ReinterpF32asI32,
9211b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                       unop( Iop_TruncF64asF32,
9212b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                             triop( Iop_DivF64r32, rm, mkexpr( a1 ), mkexpr( b1 ) ) ) ) );
9213b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         assign( res2,
9214b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                 unop( Iop_ReinterpF32asI32,
9215b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                       unop( Iop_TruncF64asF32,
9216b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                             triop( Iop_DivF64r32, rm, mkexpr( a2 ), mkexpr( b2 ) ) ) ) );
9217b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         assign( res3,
9218b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                 unop( Iop_ReinterpF32asI32,
9219b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                       unop( Iop_TruncF64asF32,
9220b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                             triop( Iop_DivF64r32, rm, mkexpr( a3 ), mkexpr( b3 ) ) ) ) );
9221b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
9222b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         putVSReg( XT,
9223b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                   binop( Iop_64HLtoV128,
9224b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                          binop( Iop_32HLto64, mkexpr( res3 ), mkexpr( res2 ) ),
9225b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                          binop( Iop_32HLto64, mkexpr( res1 ), mkexpr( res0 ) ) ) );
9226b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         break;
9227b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      }
9228b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      case 0x116: // xvsqrtsp (VSX Vector Square Root Single-Precision)
9229b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      {
9230b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         DIP("xvsqrtsp v%d,v%d\n", (UInt)XT, (UInt)XB);
9231b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         breakV128to4xF64( getVSReg( XB ), &b3, &b2, &b1, &b0 );
9232b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         /* Note: The native xvsqrtsp insruction does not always give the same precision
9233b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov          * as what we get with Iop_SqrtF64.  But it doesn't seem worthwhile to implement
9234b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov          * an Iop_SqrtF32 that would give us a lower precision result, albeit more true
9235b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov          * to the actual instruction.
9236b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov          */
9237b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
9238b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         assign( res0,
9239b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                 unop( Iop_ReinterpF32asI32,
9240b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                       unop( Iop_TruncF64asF32,
9241b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                             binop(Iop_SqrtF64, rm, mkexpr( b0 ) ) ) ) );
9242b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         assign( res1,
9243b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                 unop( Iop_ReinterpF32asI32,
9244b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                       unop( Iop_TruncF64asF32,
9245b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                             binop(Iop_SqrtF64, rm, mkexpr( b1 ) ) ) ) );
9246b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         assign( res2,
9247b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                 unop( Iop_ReinterpF32asI32,
9248b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                       unop( Iop_TruncF64asF32,
9249b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                             binop(Iop_SqrtF64, rm, mkexpr( b2) ) ) ) );
9250b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         assign( res3,
9251b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                 unop( Iop_ReinterpF32asI32,
9252b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                       unop( Iop_TruncF64asF32,
9253b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                             binop(Iop_SqrtF64, rm, mkexpr( b3 ) ) ) ) );
9254b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
9255b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         putVSReg( XT,
9256b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                   binop( Iop_64HLtoV128,
9257b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                          binop( Iop_32HLto64, mkexpr( res3 ), mkexpr( res2 ) ),
9258b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                          binop( Iop_32HLto64, mkexpr( res1 ), mkexpr( res0 ) ) ) );
9259b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         break;
9260b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      }
9261b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
9262b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      case 0x104: case 0x124: // xvmaddasp, xvmaddmsp (VSX Vector Multiply-Add Single-Precision)
9263b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      case 0x144: case 0x164: // xvmsubasp, xvmsubmsp (VSX Vector Multiply-Subtract Single-Precision)
9264b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      case 0x304: case 0x324: // xvnmaddasp, xvnmaddmsp (VSX Vector Negate Multiply-Add Single-Precision)
9265b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      case 0x344: case 0x364: // xvnmsubasp, xvnmsubmsp (VSX Vector Negate Multiply-Subtract Single-Precision)
9266b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      {
9267b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         IRTemp t3, t2, t1, t0;
9268b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         Bool msp = False;
9269b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         Bool negate;
9270b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         Char * oper_name = NULL;
9271b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         IROp mOp = Iop_INVALID;
9272b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         switch (opc2) {
9273b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov            case 0x104: case 0x124:
9274b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov            case 0x304: case 0x324:
9275b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov               msp = (opc2 & 0x0FF) == 0x024;
9276b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov               mOp = Iop_MAddF64r32;
9277b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov               oper_name = "madd";
9278b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov               break;
9279b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
9280b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov            case 0x144: case 0x164:
9281b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov            case 0x344: case 0x364:
9282b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov               msp = (opc2 & 0x0FF) == 0x064;
9283b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov               mOp = Iop_MSubF64r32;
9284b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov               oper_name = "sub";
9285b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov               break;
9286b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
9287b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov            default:
9288b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov               vpanic("The impossible happened: dis_vxv_sp_arith(ppc)");
9289b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         }
9290b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
9291b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         switch (opc2) {
9292b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov            case 0x304: case 0x324:
9293b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov            case 0x344: case 0x364:
9294b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov               negate = True;
9295b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov               break;
9296b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
9297b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov            default:
9298b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov               negate = False;
9299b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         }
9300b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
9301b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         DIP("xv%sm%s%s v%d,v%d,v%d\n", negate ? "n" : "", oper_name, msp ? "msp" : "asp",
9302b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov             (UInt)XT, (UInt)XA, (UInt)XB);
9303b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
9304b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         t3 = t2 = t1 = t0 = IRTemp_INVALID;
9305b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         breakV128to4xF64( getVSReg( XA ), &a3, &a2, &a1, &a0 );
9306b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         breakV128to4xF64( getVSReg( XB ), &b3, &b2, &b1, &b0 );
9307b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         breakV128to4xF64( getVSReg( XT ), &t3, &t2, &t1, &t0 );
9308b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
9309b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         assign( res0,
9310b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                 unop( Iop_ReinterpF32asI32,
9311b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                       unop( Iop_TruncF64asF32,
9312b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                             qop( mOp,
9313b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                                  rm,
9314b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                                  mkexpr( a0 ),
9315b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                                  mkexpr( msp ? t0 : b0 ),
9316b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                                  mkexpr( msp ? b0 : t0 ) ) ) ) );
9317b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         assign( res1,
9318b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                 unop( Iop_ReinterpF32asI32,
9319b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                       unop( Iop_TruncF64asF32,
9320b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                             qop( mOp,
9321b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                                  rm,
9322b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                                  mkexpr( a1 ),
9323b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                                  mkexpr( msp ? t1 : b1 ),
9324b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                                  mkexpr( msp ? b1 : t1 ) ) ) ) );
9325b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         assign( res2,
9326b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                 unop( Iop_ReinterpF32asI32,
9327b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                       unop( Iop_TruncF64asF32,
9328b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                             qop( mOp,
9329b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                                  rm,
9330b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                                  mkexpr( a2 ),
9331b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                                  mkexpr( msp ? t2 : b2 ),
9332b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                                  mkexpr( msp ? b2 : t2 ) ) ) ) );
9333b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         assign( res3,
9334b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                 unop( Iop_ReinterpF32asI32,
9335b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                       unop( Iop_TruncF64asF32,
9336b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                             qop( mOp,
9337b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                                  rm,
9338b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                                  mkexpr( a3 ),
9339b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                                  mkexpr( msp ? t3 : b3 ),
9340b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                                  mkexpr( msp ? b3 : t3 ) ) ) ) );
9341b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
9342b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         putVSReg( XT,
9343b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                   binop( Iop_64HLtoV128,
9344b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                          binop( Iop_32HLto64, mkexpr( negate ? getNegatedResult_32( res3 ) : res3 ),
9345b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                                 mkexpr( negate ? getNegatedResult_32( res2 ) : res2 ) ),
9346b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                          binop( Iop_32HLto64, mkexpr( negate ? getNegatedResult_32( res1 ) : res1 ),
9347b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                                 mkexpr( negate ? getNegatedResult_32( res0 ) : res0 ) ) ) );
9348b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
9349b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         break;
9350b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      }
9351b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      case 0x154: // xvtsqrtsp (VSX Vector Test for software Square Root Single-Precision)
9352b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      {
9353b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         IRTemp flags0 = newTemp(Ity_I32);
9354b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         IRTemp flags1 = newTemp(Ity_I32);
9355b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         IRTemp flags2 = newTemp(Ity_I32);
9356b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         IRTemp flags3 = newTemp(Ity_I32);
9357b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         UChar crfD     = toUChar( IFIELD( theInstr, 23, 3 ) );
9358b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         IRTemp  fe_flag0, fg_flag0, fe_flag1, fg_flag1;
9359b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         IRTemp  fe_flag2, fg_flag2, fe_flag3, fg_flag3;
9360b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         fe_flag0 = fg_flag0 = fe_flag1 = fg_flag1 = IRTemp_INVALID;
9361b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         fe_flag2 = fg_flag2 = fe_flag3 = fg_flag3 = IRTemp_INVALID;
9362b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         DIP("xvtsqrtsp cr%d,v%d\n", (UInt)crfD, (UInt)XB);
9363b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
9364b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         breakV128to4x32( getVSReg( XB ), &b3, &b2, &b1, &b0 );
9365b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         do_fp_tsqrt(b0, True /* single precision*/, &fe_flag0, &fg_flag0);
9366b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         do_fp_tsqrt(b1, True /* single precision*/, &fe_flag1, &fg_flag1);
9367b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         do_fp_tsqrt(b2, True /* single precision*/, &fe_flag2, &fg_flag2);
9368b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         do_fp_tsqrt(b3, True /* single precision*/, &fe_flag3, &fg_flag3);
9369b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
9370b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         /* The CR field consists of fl_flag || fg_flag || fe_flag || 0b0
9371b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov          * where fl_flag == 1 on ppc64.
9372b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov          */
9373b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         assign( flags0,
9374b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                 binop( Iop_Or32,
9375b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                        binop( Iop_Or32, mkU32( 8 ), // fl_flag
9376b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                               binop( Iop_Shl32, mkexpr(fg_flag0), mkU8( 2 ) ) ),
9377b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                        binop( Iop_Shl32, mkexpr(fe_flag0), mkU8( 1 ) ) ) );
9378b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         assign( flags1,
9379b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                 binop( Iop_Or32,
9380b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                        binop( Iop_Or32, mkU32( 8 ), // fl_flag
9381b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                               binop( Iop_Shl32, mkexpr(fg_flag1), mkU8( 2 ) ) ),
9382b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                        binop( Iop_Shl32, mkexpr(fe_flag1), mkU8( 1 ) ) ) );
9383b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         assign( flags2,
9384b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                 binop( Iop_Or32,
9385b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                        binop( Iop_Or32, mkU32( 8 ), // fl_flag
9386b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                               binop( Iop_Shl32, mkexpr(fg_flag2), mkU8( 2 ) ) ),
9387b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                        binop( Iop_Shl32, mkexpr(fe_flag2), mkU8( 1 ) ) ) );
9388b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         assign( flags3,
9389b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                 binop( Iop_Or32,
9390b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                        binop( Iop_Or32, mkU32( 8 ), // fl_flag
9391b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                               binop( Iop_Shl32, mkexpr(fg_flag3), mkU8( 2 ) ) ),
9392b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                        binop( Iop_Shl32, mkexpr(fe_flag3), mkU8( 1 ) ) ) );
9393b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         putGST_field( PPC_GST_CR,
9394b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                       binop( Iop_Or32,
9395b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                              mkexpr( flags0 ),
9396b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                              binop( Iop_Or32,
9397b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                                     mkexpr( flags1 ),
9398b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                                     binop( Iop_Or32,
9399b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                                            mkexpr( flags2 ),
9400b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                                            mkexpr( flags3 ) ) ) ),
9401b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                       crfD );
9402b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
9403b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         break;
9404b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      }
9405b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      case 0x174: // xvtdivsp (VSX Vector Test for software Divide Single-Precision)
9406b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      {
9407b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         IRTemp flags0 = newTemp(Ity_I32);
9408b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         IRTemp flags1 = newTemp(Ity_I32);
9409b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         IRTemp flags2 = newTemp(Ity_I32);
9410b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         IRTemp flags3 = newTemp(Ity_I32);
9411b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         UChar crfD     = toUChar( IFIELD( theInstr, 23, 3 ) );
9412b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         IRTemp  fe_flag0, fg_flag0, fe_flag1, fg_flag1;
9413b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         IRTemp  fe_flag2, fg_flag2, fe_flag3, fg_flag3;
9414b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         fe_flag0 = fg_flag0 = fe_flag1 = fg_flag1 = IRTemp_INVALID;
9415b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         fe_flag2 = fg_flag2 = fe_flag3 = fg_flag3 = IRTemp_INVALID;
9416b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         DIP("xvtdivsp cr%d,v%d,v%d\n", (UInt)crfD, (UInt)XA, (UInt)XB);
9417b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
9418b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         breakV128to4x32( getVSReg( XA ), &a3, &a2, &a1, &a0 );
9419b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         breakV128to4x32( getVSReg( XB ), &b3, &b2, &b1, &b0 );
9420b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         _do_fp_tdiv(a0, b0, True /* single precision*/, &fe_flag0, &fg_flag0);
9421b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         _do_fp_tdiv(a1, b1, True /* single precision*/, &fe_flag1, &fg_flag1);
9422b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         _do_fp_tdiv(a2, b2, True /* single precision*/, &fe_flag2, &fg_flag2);
9423b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         _do_fp_tdiv(a3, b3, True /* single precision*/, &fe_flag3, &fg_flag3);
9424b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
9425b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         /* The CR field consists of fl_flag || fg_flag || fe_flag || 0b0
9426b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov          * where fl_flag == 1 on ppc64.
9427b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov          */
9428b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         assign( flags0,
9429b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                 binop( Iop_Or32,
9430b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                        binop( Iop_Or32, mkU32( 8 ), // fl_flag
9431b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                               binop( Iop_Shl32, mkexpr(fg_flag0), mkU8( 2 ) ) ),
9432b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                        binop( Iop_Shl32, mkexpr(fe_flag0), mkU8( 1 ) ) ) );
9433b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         assign( flags1,
9434b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                 binop( Iop_Or32,
9435b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                        binop( Iop_Or32, mkU32( 8 ), // fl_flag
9436b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                               binop( Iop_Shl32, mkexpr(fg_flag1), mkU8( 2 ) ) ),
9437b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                        binop( Iop_Shl32, mkexpr(fe_flag1), mkU8( 1 ) ) ) );
9438b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         assign( flags2,
9439b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                 binop( Iop_Or32,
9440b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                        binop( Iop_Or32, mkU32( 8 ), // fl_flag
9441b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                               binop( Iop_Shl32, mkexpr(fg_flag2), mkU8( 2 ) ) ),
9442b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                        binop( Iop_Shl32, mkexpr(fe_flag2), mkU8( 1 ) ) ) );
9443b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         assign( flags3,
9444b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                 binop( Iop_Or32,
9445b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                        binop( Iop_Or32, mkU32( 8 ), // fl_flag
9446b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                               binop( Iop_Shl32, mkexpr(fg_flag3), mkU8( 2 ) ) ),
9447b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                        binop( Iop_Shl32, mkexpr(fe_flag3), mkU8( 1 ) ) ) );
9448b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         putGST_field( PPC_GST_CR,
9449b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                       binop( Iop_Or32,
9450b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                              mkexpr( flags0 ),
9451b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                              binop( Iop_Or32,
9452b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                                     mkexpr( flags1 ),
9453b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                                     binop( Iop_Or32,
9454b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                                            mkexpr( flags2 ),
9455b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                                            mkexpr( flags3 ) ) ) ),
9456b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                       crfD );
9457b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
9458b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         break;
9459b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      }
9460b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
9461b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      default:
9462b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         vex_printf( "dis_vxv_sp_arith(ppc)(opc2)\n" );
9463b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         return False;
9464b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   }
9465b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   return True;
9466b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov}
9467b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
9468b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanovtypedef enum {
9469b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   PPC_CMP_EQ = 2,
9470b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   PPC_CMP_GT = 4,
9471b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   PPC_CMP_GE = 6,
9472b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   PPC_CMP_LT = 8
9473b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov} ppc_cmp_t;
9474b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
9475b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
9476b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov/*
9477b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov  This helper function takes as input the IRExpr returned
9478b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov  from a binop( Iop_CmpF64, fpA, fpB), whose result is returned
9479b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov  in IR form.  This helper function converts it to PPC form.
9480b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
9481b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov  Map compare result from IR to PPC
9482b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
9483b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov  FP cmp result | PPC | IR
9484b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov  --------------------------
9485b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov  UN            | 0x1 | 0x45
9486b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov  EQ            | 0x2 | 0x40
9487b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov  GT            | 0x4 | 0x00
9488b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov  LT            | 0x8 | 0x01
9489b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
9490b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov condcode = Shl(1, (~(ccIR>>5) & 2)
9491b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                    | ((ccIR ^ (ccIR>>6)) & 1)
9492b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov*/
9493b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanovstatic IRTemp
9494b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanovget_fp_cmp_CR_val (IRExpr * ccIR_expr)
9495b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov{
9496b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   IRTemp condcode = newTemp( Ity_I32 );
9497b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   IRTemp ccIR = newTemp( Ity_I32 );
9498b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
9499b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   assign(ccIR, ccIR_expr);
9500b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   assign( condcode,
9501b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov           binop( Iop_Shl32,
9502b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                  mkU32( 1 ),
9503b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                  unop( Iop_32to8,
9504b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                        binop( Iop_Or32,
9505b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                               binop( Iop_And32,
9506b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                                      unop( Iop_Not32,
9507b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                                            binop( Iop_Shr32,
9508b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                                                   mkexpr( ccIR ),
9509b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                                                   mkU8( 5 ) ) ),
9510b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                                      mkU32( 2 ) ),
9511b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                               binop( Iop_And32,
9512b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                                      binop( Iop_Xor32,
9513b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                                             mkexpr( ccIR ),
9514b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                                             binop( Iop_Shr32,
9515b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                                                    mkexpr( ccIR ),
9516b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                                                    mkU8( 6 ) ) ),
9517b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                                      mkU32( 1 ) ) ) ) ) );
9518b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   return condcode;
9519b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov}
9520b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
9521b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov/*
9522b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov * Helper function for get_max_min_fp for ascertaining the max or min between two doubles
9523b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov * following these special rules:
9524b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov *   - The max/min of a QNaN and any value is that value
9525b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov *     (When two QNaNs are being compared, the frA QNaN is the return value.)
9526b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov *   - The max/min of any value and an SNaN is that SNaN converted to a QNaN
9527b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov *     (When two SNaNs are being compared, the frA SNaN is converted to a QNaN.)
9528b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov */
9529b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanovstatic IRExpr * _get_maxmin_fp_NaN(IRTemp frA_I64, IRTemp frB_I64)
9530b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov{
9531b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   IRTemp frA_isNaN = newTemp(Ity_I1);
9532b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   IRTemp frB_isNaN = newTemp(Ity_I1);
9533b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   IRTemp frA_isSNaN = newTemp(Ity_I1);
9534b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   IRTemp frB_isSNaN = newTemp(Ity_I1);
9535b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   IRTemp frA_isQNaN = newTemp(Ity_I1);
9536b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   IRTemp frB_isQNaN = newTemp(Ity_I1);
9537b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
9538b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   assign( frA_isNaN, is_NaN( frA_I64 ) );
9539b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   assign( frB_isNaN, is_NaN( frB_I64 ) );
9540b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   // If operand is a NAN and bit 12 is '0', then it's an SNaN
9541b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   assign( frA_isSNaN,
9542b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov           mkAND1( mkexpr(frA_isNaN),
9543b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                   binop( Iop_CmpEQ32,
9544b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                          binop( Iop_And32,
9545b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                                 unop( Iop_64HIto32, mkexpr( frA_I64 ) ),
9546b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                                 mkU32( 0x00080000 ) ),
9547b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                          mkU32( 0 ) ) ) );
9548b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   assign( frB_isSNaN,
9549b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov           mkAND1( mkexpr(frB_isNaN),
9550b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                   binop( Iop_CmpEQ32,
9551b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                          binop( Iop_And32,
9552b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                                 unop( Iop_64HIto32, mkexpr( frB_I64 ) ),
9553b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                                 mkU32( 0x00080000 ) ),
9554b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                          mkU32( 0 ) ) ) );
9555b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   assign( frA_isQNaN,
9556b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov           mkAND1( mkexpr( frA_isNaN ), unop( Iop_Not1, mkexpr( frA_isSNaN ) ) ) );
9557b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   assign( frB_isQNaN,
9558b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov           mkAND1( mkexpr( frB_isNaN ), unop( Iop_Not1, mkexpr( frB_isSNaN ) ) ) );
9559b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
9560b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   /* Based on the rules specified in the function prologue, the algorithm is as follows:
9561b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov    *  <<<<<<<<<>>>>>>>>>>>>>>>>>>
9562b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov    *   if frA is a SNaN
9563b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov    *     result = frA converted to QNaN
9564b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov    *   else if frB is a SNaN
9565b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov    *     result = frB converted to QNaN
9566b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov    *   else if frB is a QNaN
9567b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov    *     result = frA
9568b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov    *   // One of frA or frB was a NaN in order for this function to be called, so
9569b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov    *   // if we get to this point, we KNOW that frA must be a QNaN.
9570b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov    *   else // frA is a QNaN
9571b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov    *     result = frB
9572b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov    *  <<<<<<<<<>>>>>>>>>>>>>>>>>>
9573b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov    */
9574b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
9575b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov#define SNAN_MASK 0x0008000000000000ULL
9576b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   return
9577b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   IRExpr_Mux0X(unop(Iop_1Uto8, mkexpr(frA_isSNaN)),
9578b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                /* else:  if frB is a SNaN */
9579b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                IRExpr_Mux0X(unop(Iop_1Uto8, mkexpr(frB_isSNaN)),
9580b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                             /* else:  if frB is a QNaN */
9581b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                             IRExpr_Mux0X(unop(Iop_1Uto8, mkexpr(frB_isQNaN)),
9582b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                                          /* else:  frA is a QNaN, so result = frB */
9583b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                                          mkexpr(frB_I64),
9584b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                                          /* then: result = frA */
9585b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                                          mkexpr(frA_I64)),
9586b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                             /* then: result = frB converted to QNaN */
9587b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                             binop(Iop_Or64, mkexpr(frB_I64), mkU64(SNAN_MASK))),
9588b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                /* then: result = frA converted to QNaN */
9589b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                binop(Iop_Or64, mkexpr(frA_I64), mkU64(SNAN_MASK)));
9590b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov}
9591b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
9592b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov/*
9593b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov * Helper function for get_max_min_fp.
9594b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov */
9595b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanovstatic IRExpr * _get_maxmin_fp_cmp(IRTemp src1, IRTemp src2, Bool isMin)
9596b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov{
9597b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   IRTemp src1cmpsrc2 = get_fp_cmp_CR_val( binop( Iop_CmpF64,
9598b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                                                  unop( Iop_ReinterpI64asF64,
9599b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                                                        mkexpr( src1 ) ),
9600b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                                                  unop( Iop_ReinterpI64asF64,
9601b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                                                        mkexpr( src2 ) ) ) );
9602b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
9603b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   return IRExpr_Mux0X( unop( Iop_1Uto8,
9604b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                              binop( Iop_CmpEQ32,
9605b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                                     mkexpr( src1cmpsrc2 ),
9606b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                                     mkU32( isMin ? PPC_CMP_LT : PPC_CMP_GT ) ) ),
9607b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                        /* else: use src2 */
9608b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                        mkexpr( src2 ),
9609b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                        /* then: use src1 */
9610b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                        mkexpr( src1 ) );
9611b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov}
9612b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
9613b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov/*
9614b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov * Helper function for "Maximum/Minimum Double Precision" operations.
9615b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov * Arguments: frA and frb are Ity_I64
9616b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov * Returns Ity_I64 IRExpr that answers the "which is Maxiumum/Minimum" question
9617b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov */
9618b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanovstatic IRExpr * get_max_min_fp(IRTemp frA_I64, IRTemp frB_I64, Bool isMin)
9619b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov{
9620b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   /* There are three special cases where get_fp_cmp_CR_val is not helpful
9621b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov    * for ascertaining the maximum between two doubles:
9622b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov    *   1. The max/min of +0 and -0 is +0.
9623b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov    *   2. The max/min of a QNaN and any value is that value.
9624b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov    *   3. The max/min of any value and an SNaN is that SNaN converted to a QNaN.
9625b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov    * We perform the check for [+/-]0 here in this function and use the
9626b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov    * _get_maxmin_fp_NaN helper for the two NaN cases; otherwise we call _get_maxmin_fp_cmp
9627b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov    * to do the standard comparison function.
9628b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov    */
9629b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   IRTemp anyNaN = newTemp(Ity_I1);
9630b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   IRTemp frA_isZero = newTemp(Ity_I1);
9631b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   IRTemp frB_isZero = newTemp(Ity_I1);
9632b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   assign(frA_isZero, is_Zero(frA_I64, False /*not single precision*/ ));
9633b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   assign(frB_isZero, is_Zero(frB_I64, False /*not single precision*/ ));
9634b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   assign(anyNaN, mkOR1(is_NaN(frA_I64), is_NaN(frB_I64)));
9635b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov#define MINUS_ZERO 0x8000000000000000ULL
9636b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
9637b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   return IRExpr_Mux0X( unop( Iop_1Uto8,
9638b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                              /* If both arguments are zero . . . */
9639b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                              mkAND1( mkexpr( frA_isZero ), mkexpr( frB_isZero ) ) ),
9640b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                        /* else: check if either input is a NaN*/
9641b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                        IRExpr_Mux0X( unop( Iop_1Uto8, mkexpr( anyNaN ) ),
9642b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                                      /* else: use "comparison helper" */
9643b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                                      _get_maxmin_fp_cmp( frB_I64, frA_I64, isMin ),
9644b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                                      /* then: use "NaN helper" */
9645b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                                      _get_maxmin_fp_NaN( frA_I64, frB_I64 ) ),
9646b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                        /* then: if frA is -0 and isMin==True, return -0;
9647b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                         *     else if frA is +0 and isMin==False; return +0;
9648b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                         *     otherwise, simply return frB. */
9649b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                        IRExpr_Mux0X( unop( Iop_1Uto8,
9650b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                                            binop( Iop_CmpEQ32,
9651b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                                                   unop( Iop_64HIto32,
9652b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                                                         mkexpr( frA_I64 ) ),
9653b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                                                   mkU32( isMin ? 0x80000000 : 0 ) ) ),
9654b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                                      mkexpr( frB_I64 ),
9655b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                                      mkU64( isMin ? MINUS_ZERO : 0ULL ) ) );
9656b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov}
9657b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
9658b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov/*
9659b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov * Helper function for vector/scalar double precision fp round to integer instructions.
9660b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov */
9661b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanovstatic IRExpr * _do_vsx_fp_roundToInt(IRTemp frB_I64, UInt opc2, UChar * insn_suffix)
9662b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov{
9663b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
9664b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   /* The same rules apply for x{s|v}rdpi{m|p|c|z} as for floating point round operations (fri{m|n|p|z}). */
9665b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   IRTemp frB = newTemp(Ity_F64);
9666b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   IRTemp frD = newTemp(Ity_F64);
9667b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   IRTemp intermediateResult = newTemp(Ity_I64);
9668b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   IRTemp is_SNAN = newTemp(Ity_I1);
9669b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   IRExpr * hi32;
9670b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   IRExpr * rxpi_rm;
9671b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   switch (opc2 & 0x7F) {
9672b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      case 0x72:
9673b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         insn_suffix = "m";
9674b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         rxpi_rm = mkU32(Irrm_NegINF);
9675b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         break;
9676b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      case 0x52:
9677b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         insn_suffix = "p";
9678b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         rxpi_rm = mkU32(Irrm_PosINF);
9679b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         break;
9680b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      case 0x56:
9681b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         insn_suffix = "c";
9682b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         rxpi_rm = get_IR_roundingmode();
9683b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         break;
9684b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      case 0x32:
9685b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         insn_suffix = "z";
9686b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         rxpi_rm = mkU32(Irrm_ZERO);
9687b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         break;
9688b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      case 0x12:
9689b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         insn_suffix = "";
9690b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         rxpi_rm = mkU32(Irrm_NEAREST);
9691b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         break;
9692b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
9693b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      default: // Impossible to get here
9694b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         vex_printf( "_do_vsx_fp_roundToInt(ppc)(opc2)\n" );
9695b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         return NULL;
9696b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   }
9697b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   assign(frB, unop(Iop_ReinterpI64asF64, mkexpr(frB_I64)));
9698b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   assign( intermediateResult,
9699b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov           binop( Iop_F64toI64S, rxpi_rm,
9700b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                  mkexpr( frB ) ) );
9701b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
9702b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   /* don't use the rounded integer if frB is outside -9e18..9e18 */
9703b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   /* F64 has only log10(2**52) significant digits anyway */
9704b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   /* need to preserve sign of zero */
9705b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   /*   frD = (fabs(frB) > 9e18) ? frB :
9706b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov            (sign(frB)) ? -fabs((double)intermediateResult) : (double)intermediateResult  */
9707b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   assign( frD,
9708b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov           IRExpr_Mux0X( unop( Iop_32to8,
9709b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                               binop( Iop_CmpF64,
9710b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                                      IRExpr_Const( IRConst_F64( 9e18 ) ),
9711b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                                      unop( Iop_AbsF64, mkexpr( frB ) ) ) ),
9712b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                         IRExpr_Mux0X( unop( Iop_32to8,
9713b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                                             binop( Iop_Shr32,
9714b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                                                    unop( Iop_64HIto32,
9715b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                                                          mkexpr( frB_I64 ) ),
9716b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                                                    mkU8( 31 ) ) ),
9717b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                                       binop( Iop_I64StoF64,
9718b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                                              mkU32( 0 ),
9719b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                                              mkexpr( intermediateResult ) ),
9720b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                                       unop( Iop_NegF64,
9721b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                                             unop( Iop_AbsF64,
9722b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                                                   binop( Iop_I64StoF64,
9723b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                                                          mkU32( 0 ),
9724b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                                                          mkexpr( intermediateResult ) ) ) ) ),
9725b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                         mkexpr( frB ) ) );
9726b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
9727b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   /* See Appendix "Floating-Point Round to Integer Model" in ISA doc.
9728b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov    * If frB is a SNAN, then frD <- frB, with bit 12 set to '1'.
9729b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov    */
9730b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov#define SNAN_MASK 0x0008000000000000ULL
9731b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   hi32 = unop( Iop_64HIto32, mkexpr(frB_I64) );
9732b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   assign( is_SNAN,
9733b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov           mkAND1( is_NaN( frB_I64 ),
9734b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                   binop( Iop_CmpEQ32,
9735b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                          binop( Iop_And32, hi32, mkU32( 0x00080000 ) ),
9736b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                          mkU32( 0 ) ) ) );
9737b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
9738b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   return IRExpr_Mux0X( unop( Iop_1Uto8, mkexpr( is_SNAN ) ),
9739b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                        mkexpr( frD ),
9740b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                        unop( Iop_ReinterpI64asF64,
9741b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                              binop( Iop_Xor64,
9742b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                                     mkU64( SNAN_MASK ),
9743b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                                     mkexpr( frB_I64 ) ) ) );
9744b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov}
9745b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
9746b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov/*
9747b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov * Miscellaneous VSX vector instructions
9748b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov */
9749b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanovstatic Bool
9750b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanovdis_vxv_misc ( UInt theInstr, UInt opc2 )
9751b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov{
9752b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   /* XX3-Form */
9753b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   UChar opc1 = ifieldOPC( theInstr );
9754b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   UChar XT = ifieldRegXT( theInstr );
9755b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   UChar XB = ifieldRegXB( theInstr );
9756b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
9757b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   if (opc1 != 0x3C) {
9758b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      vex_printf( "dis_vxv_misc(ppc)(instr)\n" );
9759b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      return False;
9760b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   }
9761b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
9762b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   switch (opc2) {
9763b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      case 0x1B4:  // xvredp (VSX Vector Reciprocal Estimate Double-Precision)
9764b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      case 0x194:  // xvrsqrtedp (VSX Vector Reciprocal Square Root Estimate
9765b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                   //             Double-Precision)
9766b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      {
9767b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         IRExpr* ieee_one = IRExpr_Const(IRConst_F64i(0x3ff0000000000000ULL));
9768b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         IRExpr* rm  = get_IR_roundingmode();
9769b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         IRTemp frB = newTemp(Ity_I64);
9770b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         IRTemp frB2 = newTemp(Ity_I64);
9771b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         Bool redp = opc2 == 0x1B4;
9772b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         IRTemp sqrtHi = newTemp(Ity_F64);
9773b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         IRTemp sqrtLo = newTemp(Ity_F64);
9774b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         assign(frB,  unop(Iop_V128HIto64, getVSReg( XB )));
9775b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         assign(frB2, unop(Iop_V128to64, getVSReg( XB )));
9776b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
9777b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         DIP("%s v%d,v%d\n", redp ? "xvredp" : "xvrsqrtedp", (UInt)XT, (UInt)XB);
9778b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         if (!redp) {
9779b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov            assign( sqrtHi,
9780b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                    binop( Iop_SqrtF64,
9781b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                           rm,
9782b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                           unop( Iop_ReinterpI64asF64, mkexpr( frB ) ) ) );
9783b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov            assign( sqrtLo,
9784b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                    binop( Iop_SqrtF64,
9785b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                           rm,
9786b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                           unop( Iop_ReinterpI64asF64, mkexpr( frB2 ) ) ) );
9787b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         }
9788b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         putVSReg( XT,
9789b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                   binop( Iop_64HLtoV128,
9790b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                          unop( Iop_ReinterpF64asI64,
9791b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                                triop( Iop_DivF64,
9792b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                                       rm,
9793b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                                       ieee_one,
9794b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                                       redp ? unop( Iop_ReinterpI64asF64,
9795b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                                                    mkexpr( frB ) )
9796b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                                            : mkexpr( sqrtHi ) ) ),
9797b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                          unop( Iop_ReinterpF64asI64,
9798b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                                triop( Iop_DivF64,
9799b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                                       rm,
9800b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                                       ieee_one,
9801b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                                       redp ? unop( Iop_ReinterpI64asF64,
9802b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                                                    mkexpr( frB2 ) )
9803b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                                            : mkexpr( sqrtLo ) ) ) ) );
9804b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         break;
9805b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
9806b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      }
9807b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      case 0x134: // xvresp (VSX Vector Reciprocal Estimate Single-Precision)
9808b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      case 0x114: // xvrsqrtesp (VSX Vector Reciprocal Square Root Estimate Single-Precision)
9809b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      {
9810b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         IRTemp b3, b2, b1, b0;
9811b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         IRTemp res0 = newTemp(Ity_I32);
9812b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         IRTemp res1 = newTemp(Ity_I32);
9813b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         IRTemp res2 = newTemp(Ity_I32);
9814b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         IRTemp res3 = newTemp(Ity_I32);
9815b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         IRTemp sqrt3 = newTemp(Ity_F64);
9816b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         IRTemp sqrt2 = newTemp(Ity_F64);
9817b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         IRTemp sqrt1 = newTemp(Ity_F64);
9818b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         IRTemp sqrt0 = newTemp(Ity_F64);
9819b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         IRExpr* rm  = get_IR_roundingmode();
9820b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         Bool resp = opc2 == 0x134;
9821b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
9822b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         IRExpr* ieee_one = IRExpr_Const(IRConst_F64i(0x3ff0000000000000ULL));
9823b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
9824b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         b3 = b2 = b1 = b0 = IRTemp_INVALID;
9825b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         DIP("%s v%d,v%d\n", resp ? "xvresp" : "xvrsqrtesp", (UInt)XT, (UInt)XB);
9826b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         breakV128to4xF64( getVSReg( XB ), &b3, &b2, &b1, &b0 );
9827b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
9828b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         if (!resp) {
9829b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov            assign( sqrt3, binop( Iop_SqrtF64, rm, mkexpr( b3 ) ) );
9830b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov            assign( sqrt2, binop( Iop_SqrtF64, rm, mkexpr( b2 ) ) );
9831b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov            assign( sqrt1, binop( Iop_SqrtF64, rm, mkexpr( b1 ) ) );
9832b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov            assign( sqrt0, binop( Iop_SqrtF64, rm, mkexpr( b0 ) ) );
9833b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         }
9834b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
9835b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         assign( res0,
9836b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                 unop( Iop_ReinterpF32asI32,
9837b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                       unop( Iop_TruncF64asF32,
9838b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                             triop( Iop_DivF64r32,
9839b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                                    rm,
9840b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                                    ieee_one,
9841b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                                    resp ? mkexpr( b0 ) : mkexpr( sqrt0 ) ) ) ) );
9842b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         assign( res1,
9843b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                 unop( Iop_ReinterpF32asI32,
9844b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                       unop( Iop_TruncF64asF32,
9845b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                             triop( Iop_DivF64r32,
9846b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                                    rm,
9847b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                                    ieee_one,
9848b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                                    resp ? mkexpr( b1 ) : mkexpr( sqrt1 ) ) ) ) );
9849b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         assign( res2,
9850b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                 unop( Iop_ReinterpF32asI32,
9851b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                       unop( Iop_TruncF64asF32,
9852b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                             triop( Iop_DivF64r32,
9853b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                                    rm,
9854b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                                    ieee_one,
9855b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                                    resp ? mkexpr( b2 ) : mkexpr( sqrt2 ) ) ) ) );
9856b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         assign( res3,
9857b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                 unop( Iop_ReinterpF32asI32,
9858b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                       unop( Iop_TruncF64asF32,
9859b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                             triop( Iop_DivF64r32,
9860b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                                    rm,
9861b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                                    ieee_one,
9862b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                                    resp ? mkexpr( b3 ) : mkexpr( sqrt3 ) ) ) ) );
9863b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         putVSReg( XT,
9864b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                   binop( Iop_64HLtoV128,
9865b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                          binop( Iop_32HLto64, mkexpr( res3 ), mkexpr( res2 ) ),
9866b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                          binop( Iop_32HLto64, mkexpr( res1 ), mkexpr( res0 ) ) ) );
9867b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         break;
9868b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      }
9869b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      case 0x300: // xvmaxsp (VSX Vector Maximum Single-Precision)
9870b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      case 0x320: // xvminsp (VSX Vector Minimum Single-Precision)
9871b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      {
9872b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         UChar XA = ifieldRegXA( theInstr );
9873b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         IRTemp a3, a2, a1, a0;
9874b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         IRTemp b3, b2, b1, b0;
9875b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         IRTemp res0 = newTemp( Ity_I32 );
9876b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         IRTemp res1 = newTemp( Ity_I32 );
9877b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         IRTemp res2 = newTemp( Ity_I32 );
9878b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         IRTemp res3 = newTemp( Ity_I32 );
9879b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         IRTemp a0_I64 = newTemp( Ity_I64 );
9880b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         IRTemp a1_I64 = newTemp( Ity_I64 );
9881b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         IRTemp a2_I64 = newTemp( Ity_I64 );
9882b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         IRTemp a3_I64 = newTemp( Ity_I64 );
9883b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         IRTemp b0_I64 = newTemp( Ity_I64 );
9884b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         IRTemp b1_I64 = newTemp( Ity_I64 );
9885b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         IRTemp b2_I64 = newTemp( Ity_I64 );
9886b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         IRTemp b3_I64 = newTemp( Ity_I64 );
9887b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
9888b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         Bool isMin = opc2 == 0x320 ? True : False;
9889b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
9890b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         a3 = a2 = a1 = a0 = IRTemp_INVALID;
9891b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         b3 = b2 = b1 = b0 = IRTemp_INVALID;
9892b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         DIP("%s v%d,v%d v%d\n", isMin ? "xvminsp" : "xvmaxsp", (UInt)XT, (UInt)XA, (UInt)XB);
9893b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         breakV128to4xF64( getVSReg( XA ), &a3, &a2, &a1, &a0 );
9894b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         breakV128to4xF64( getVSReg( XB ), &b3, &b2, &b1, &b0 );
9895b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         assign( a0_I64, unop( Iop_ReinterpF64asI64, mkexpr( a0 ) ) );
9896b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         assign( b0_I64, unop( Iop_ReinterpF64asI64, mkexpr( b0 ) ) );
9897b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         assign( a1_I64, unop( Iop_ReinterpF64asI64, mkexpr( a1 ) ) );
9898b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         assign( b1_I64, unop( Iop_ReinterpF64asI64, mkexpr( b1 ) ) );
9899b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         assign( a2_I64, unop( Iop_ReinterpF64asI64, mkexpr( a2 ) ) );
9900b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         assign( b2_I64, unop( Iop_ReinterpF64asI64, mkexpr( b2 ) ) );
9901b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         assign( a3_I64, unop( Iop_ReinterpF64asI64, mkexpr( a3 ) ) );
9902b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         assign( b3_I64, unop( Iop_ReinterpF64asI64, mkexpr( b3 ) ) );
9903b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         assign( res0,
9904b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                 unop( Iop_ReinterpF32asI32,
9905b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                       unop( Iop_TruncF64asF32,
9906b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                             unop( Iop_ReinterpI64asF64,
9907b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                                   get_max_min_fp( a0_I64, b0_I64, isMin ) ) ) ) );
9908b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         assign( res1,
9909b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                 unop( Iop_ReinterpF32asI32,
9910b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                       unop( Iop_TruncF64asF32,
9911b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                             unop( Iop_ReinterpI64asF64,
9912b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                                   get_max_min_fp( a1_I64, b1_I64, isMin ) ) ) ) );
9913b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         assign( res2,
9914b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                 unop( Iop_ReinterpF32asI32,
9915b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                       unop( Iop_TruncF64asF32,
9916b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                             unop( Iop_ReinterpI64asF64,
9917b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                                   get_max_min_fp( a2_I64, b2_I64, isMin ) ) ) ) );
9918b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         assign( res3,
9919b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                 unop( Iop_ReinterpF32asI32,
9920b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                       unop( Iop_TruncF64asF32,
9921b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                             unop( Iop_ReinterpI64asF64,
9922b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                                   get_max_min_fp( a3_I64, b3_I64, isMin ) ) ) ) );
9923b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         putVSReg( XT,
9924b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                   binop( Iop_64HLtoV128,
9925b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                          binop( Iop_32HLto64, mkexpr( res3 ), mkexpr( res2 ) ),
9926b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                          binop( Iop_32HLto64, mkexpr( res1 ), mkexpr( res0 ) ) ) );
9927b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         break;
9928b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      }
9929b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      case 0x380: // xvmaxdp (VSX Vector Maximum Double-Precision)
9930b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      case 0x3A0: // xvmindp (VSX Vector Minimum Double-Precision)
9931b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      {
9932b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         UChar XA = ifieldRegXA( theInstr );
9933b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         IRTemp frA = newTemp(Ity_I64);
9934b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         IRTemp frB = newTemp(Ity_I64);
9935b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         IRTemp frA2 = newTemp(Ity_I64);
9936b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         IRTemp frB2 = newTemp(Ity_I64);
9937b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         Bool isMin = opc2 == 0x3A0 ? True : False;
9938b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
9939b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         assign(frA,  unop(Iop_V128HIto64, getVSReg( XA )));
9940b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         assign(frB,  unop(Iop_V128HIto64, getVSReg( XB )));
9941b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         assign(frA2, unop(Iop_V128to64, getVSReg( XA )));
9942b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         assign(frB2, unop(Iop_V128to64, getVSReg( XB )));
9943b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         DIP("%s v%d,v%d v%d\n", isMin ? "xvmindp" : "xvmaxdp", (UInt)XT, (UInt)XA, (UInt)XB);
9944b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         putVSReg( XT, binop( Iop_64HLtoV128, get_max_min_fp(frA, frB, isMin), get_max_min_fp(frA2, frB2, isMin) ) );
9945b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
9946b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         break;
9947b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      }
9948b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      case 0x3c0: // xvcpsgndp (VSX Vector Copy Sign Double-Precision)
9949b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      {
9950b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         UChar XA = ifieldRegXA( theInstr );
9951b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         IRTemp frA = newTemp(Ity_I64);
9952b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         IRTemp frB = newTemp(Ity_I64);
9953b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         IRTemp frA2 = newTemp(Ity_I64);
9954b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         IRTemp frB2 = newTemp(Ity_I64);
9955b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         assign(frA,  unop(Iop_V128HIto64, getVSReg( XA )));
9956b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         assign(frB,  unop(Iop_V128HIto64, getVSReg( XB )));
9957b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         assign(frA2, unop(Iop_V128to64, getVSReg( XA )));
9958b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         assign(frB2, unop(Iop_V128to64, getVSReg( XB )));
9959b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
9960b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         DIP("xvcpsgndp v%d,v%d,v%d\n", (UInt)XT, (UInt)XA, (UInt)XB);
9961b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         putVSReg( XT,
9962b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                   binop( Iop_64HLtoV128,
9963b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                          binop( Iop_Or64,
9964b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                                 binop( Iop_And64,
9965b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                                        mkexpr( frA ),
9966b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                                        mkU64( SIGN_BIT ) ),
9967b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                                 binop( Iop_And64,
9968b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                                        mkexpr( frB ),
9969b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                                        mkU64( SIGN_MASK ) ) ),
9970b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                          binop( Iop_Or64,
9971b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                                 binop( Iop_And64,
9972b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                                        mkexpr( frA2 ),
9973b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                                        mkU64( SIGN_BIT ) ),
9974b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                                 binop( Iop_And64,
9975b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                                        mkexpr( frB2 ),
9976b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                                        mkU64( SIGN_MASK ) ) ) ) );
9977b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         break;
9978b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      }
9979b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      case 0x340: // xvcpsgnsp
9980b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      {
9981b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         UChar XA = ifieldRegXA( theInstr );
9982b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         IRTemp a3_I64, a2_I64, a1_I64, a0_I64;
9983b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         IRTemp b3_I64, b2_I64, b1_I64, b0_I64;
9984b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         IRTemp resHi = newTemp(Ity_I64);
9985b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         IRTemp resLo = newTemp(Ity_I64);
9986b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
9987b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         a3_I64 = a2_I64 = a1_I64 = a0_I64 = IRTemp_INVALID;
9988b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         b3_I64 = b2_I64 = b1_I64 = b0_I64 = IRTemp_INVALID;
9989b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         DIP("xvcpsgnsp v%d,v%d v%d\n",(UInt)XT, (UInt)XA, (UInt)XB);
9990b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         breakV128to4x64U( getVSReg( XA ), &a3_I64, &a2_I64, &a1_I64, &a0_I64 );
9991b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         breakV128to4x64U( getVSReg( XB ), &b3_I64, &b2_I64, &b1_I64, &b0_I64 );
9992b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
9993b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         assign( resHi,
9994b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                 binop( Iop_32HLto64,
9995b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                        binop( Iop_Or32,
9996b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                               binop( Iop_And32,
9997b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                                      unop(Iop_64to32, mkexpr( a3_I64 ) ),
9998b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                                      mkU32( SIGN_BIT32 ) ),
9999b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                               binop( Iop_And32,
10000b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                                      unop(Iop_64to32, mkexpr( b3_I64 ) ),
10001b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                                      mkU32( SIGN_MASK32) ) ),
10002b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
10003b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                        binop( Iop_Or32,
10004b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                               binop( Iop_And32,
10005b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                                      unop(Iop_64to32, mkexpr( a2_I64 ) ),
10006b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                                      mkU32( SIGN_BIT32 ) ),
10007b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                               binop( Iop_And32,
10008b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                                      unop(Iop_64to32, mkexpr( b2_I64 ) ),
10009b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                                      mkU32( SIGN_MASK32 ) ) ) ) );
10010b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         assign( resLo,
10011b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                 binop( Iop_32HLto64,
10012b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                        binop( Iop_Or32,
10013b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                               binop( Iop_And32,
10014b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                                      unop(Iop_64to32, mkexpr( a1_I64 ) ),
10015b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                                      mkU32( SIGN_BIT32 ) ),
10016b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                               binop( Iop_And32,
10017b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                                      unop(Iop_64to32, mkexpr( b1_I64 ) ),
10018b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                                      mkU32( SIGN_MASK32 ) ) ),
10019b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
10020b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                        binop( Iop_Or32,
10021b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                               binop( Iop_And32,
10022b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                                      unop(Iop_64to32, mkexpr( a0_I64 ) ),
10023b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                                      mkU32( SIGN_BIT32 ) ),
10024b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                               binop( Iop_And32,
10025b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                                      unop(Iop_64to32, mkexpr( b0_I64 ) ),
10026b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                                      mkU32( SIGN_MASK32 ) ) ) ) );
10027b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         putVSReg( XT, binop( Iop_64HLtoV128, mkexpr( resHi ), mkexpr( resLo ) ) );
10028b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         break;
10029b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      }
10030b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      case 0x3B2: // xvabsdp (VSX Vector Absolute Value Double-Precision)
10031b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      case 0x3D2: // xvnabsdp VSX Vector Negative Absolute Value Double-Precision)
10032b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      {
10033b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         IRTemp frB = newTemp(Ity_F64);
10034b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         IRTemp frB2 = newTemp(Ity_F64);
10035b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         IRTemp abs_resultHi = newTemp(Ity_F64);
10036b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         IRTemp abs_resultLo = newTemp(Ity_F64);
10037b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         Bool make_negative = (opc2 == 0x3D2) ? True : False;
10038b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         assign(frB,  unop(Iop_ReinterpI64asF64, unop(Iop_V128HIto64, getVSReg( XB ))));
10039b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         assign(frB2, unop(Iop_ReinterpI64asF64, unop(Iop_V128to64, getVSReg(XB))));
10040b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
10041b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         DIP("xv%sabsdp v%d,v%d\n", make_negative ? "n" : "", (UInt)XT, (UInt)XB);
10042b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         if (make_negative) {
10043b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov            assign(abs_resultHi, unop( Iop_NegF64, unop( Iop_AbsF64, mkexpr( frB ) ) ) );
10044b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov            assign(abs_resultLo, unop( Iop_NegF64, unop( Iop_AbsF64, mkexpr( frB2 ) ) ) );
10045b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
10046b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         } else {
10047b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov            assign(abs_resultHi, unop( Iop_AbsF64, mkexpr( frB ) ) );
10048b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov            assign(abs_resultLo, unop( Iop_AbsF64, mkexpr( frB2 ) ) );
10049b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         }
10050b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         putVSReg( XT, binop( Iop_64HLtoV128,
10051b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                              unop( Iop_ReinterpF64asI64, mkexpr( abs_resultHi ) ),
10052b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                              unop( Iop_ReinterpF64asI64, mkexpr( abs_resultLo ) ) ) );
10053b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         break;
10054b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      }
10055b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      case 0x332: // xvabssp (VSX Vector Absolute Value Single-Precision)
10056b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      case 0x352: // xvnabssp (VSX Vector Negative Absolute Value Single-Precision)
10057b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      {
10058b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         /*
10059b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov          * The Iop_AbsF32 IRop is not implemented for ppc64 since, up until introduction
10060b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov          * of xvabssp, there has not been an abs(sp) type of instruction.  But since emulation
10061b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov          * of this function is so easy using shifts, I choose to emulate this instruction that
10062b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov          * way versus a native instruction method of implementation.
10063b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov          */
10064b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         Bool make_negative = (opc2 == 0x352) ? True : False;
10065b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         IRTemp shiftVector = newTemp(Ity_V128);
10066b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         IRTemp absVal_vector = newTemp(Ity_V128);
10067b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         assign( shiftVector,
10068b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                 binop( Iop_64HLtoV128,
10069b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                        binop( Iop_32HLto64, mkU32( 1 ), mkU32( 1 ) ),
10070b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                        binop( Iop_32HLto64, mkU32( 1 ), mkU32( 1 ) ) ) );
10071b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         assign( absVal_vector,
10072b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                   binop( Iop_Shr32x4,
10073b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                          binop( Iop_Shl32x4,
10074b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                                 getVSReg( XB ),
10075b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                                 mkexpr( shiftVector ) ),
10076b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                          mkexpr( shiftVector ) ) );
10077b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         if (make_negative) {
10078b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov            IRTemp signBit_vector = newTemp(Ity_V128);
10079b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov            assign( signBit_vector,
10080b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                    binop( Iop_64HLtoV128,
10081b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                           binop( Iop_32HLto64,
10082b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                                  mkU32( 0x80000000 ),
10083b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                                  mkU32( 0x80000000 ) ),
10084b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                           binop( Iop_32HLto64,
10085b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                                  mkU32( 0x80000000 ),
10086b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                                  mkU32( 0x80000000 ) ) ) );
10087b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov            putVSReg( XT,
10088b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                      binop( Iop_OrV128,
10089b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                             mkexpr( absVal_vector ),
10090b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                             mkexpr( signBit_vector ) ) );
10091b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         } else {
10092b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov            putVSReg( XT, mkexpr( absVal_vector ) );
10093b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         }
10094b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         break;
10095b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      }
10096b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      case 0x3F2: // xvnegdp (VSX Vector Negate Double-Precision)
10097b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      {
10098b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         IRTemp frB = newTemp(Ity_F64);
10099b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         IRTemp frB2 = newTemp(Ity_F64);
10100b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         assign(frB,  unop(Iop_ReinterpI64asF64, unop(Iop_V128HIto64, getVSReg( XB ))));
10101b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         assign(frB2, unop(Iop_ReinterpI64asF64, unop(Iop_V128to64, getVSReg(XB))));
10102b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         DIP("xvnegdp v%d,v%d\n",  (UInt)XT, (UInt)XB);
10103b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         putVSReg( XT,
10104b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                   binop( Iop_64HLtoV128,
10105b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                          unop( Iop_ReinterpF64asI64,
10106b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                                unop( Iop_NegF64, mkexpr( frB ) ) ),
10107b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                          unop( Iop_ReinterpF64asI64,
10108b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                                unop( Iop_NegF64, mkexpr( frB2 ) ) ) ) );
10109b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         break;
10110b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      }
10111b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      case 0x192: // xvrdpi  (VSX Vector Round to Double-Precision Integer using round toward Nearest Away)
10112b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      case 0x1D6: // xvrdpic (VSX Vector Round to Double-Precision Integer using Current rounding mode)
10113b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      case 0x1F2: // xvrdpim (VSX Vector Round to Double-Precision Integer using round toward -Infinity)
10114b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      case 0x1D2: // xvrdpip (VSX Vector Round to Double-Precision Integer using round toward +Infinity)
10115b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      case 0x1B2: // xvrdpiz (VSX Vector Round to Double-Precision Integer using round toward Zero)
10116b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      {
10117b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         IRTemp frBHi_I64 = newTemp(Ity_I64);
10118b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         IRTemp frBLo_I64 = newTemp(Ity_I64);
10119b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         IRExpr * frD_fp_roundHi = NULL;
10120b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         IRExpr * frD_fp_roundLo = NULL;
10121b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         UChar * insn_suffix = NULL;
10122b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
10123b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         assign( frBHi_I64, unop( Iop_V128HIto64, getVSReg( XB ) ) );
10124b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         frD_fp_roundHi = _do_vsx_fp_roundToInt(frBHi_I64, opc2, insn_suffix);
10125b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         assign( frBLo_I64, unop( Iop_V128to64, getVSReg( XB ) ) );
10126b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         frD_fp_roundLo = _do_vsx_fp_roundToInt(frBLo_I64, opc2, insn_suffix);
10127b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
10128b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         DIP("xvrdpi%s v%d,v%d\n", insn_suffix, (UInt)XT, (UInt)XB);
10129b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         putVSReg( XT,
10130b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                   binop( Iop_64HLtoV128,
10131b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                          unop( Iop_ReinterpF64asI64, frD_fp_roundHi ),
10132b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                          unop( Iop_ReinterpF64asI64, frD_fp_roundLo ) ) );
10133b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         break;
10134b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      }
10135b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      case 0x112: // xvrspi  (VSX Vector Round to Single-Precision Integer using round toward Nearest Away)
10136b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      case 0x156: // xvrspic (VSX Vector Round to SinglePrecision Integer using Current rounding mode)
10137b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      case 0x172: // xvrspim (VSX Vector Round to SinglePrecision Integer using round toward -Infinity)
10138b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      case 0x152: // xvrspip (VSX Vector Round to SinglePrecision Integer using round toward +Infinity)
10139b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      case 0x132: // xvrspiz (VSX Vector Round to SinglePrecision Integer using round toward Zero)
10140b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      {
10141b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         UChar * insn_suffix = NULL;
10142b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         IROp op;
10143b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         if (opc2 != 0x156) {
10144b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov            // Use pre-defined IRop's for vrfi{m|n|p|z}
10145b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov            switch (opc2) {
10146b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov               case 0x112:
10147b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                  insn_suffix = "";
10148b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                  op = Iop_RoundF32x4_RN;
10149b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                  break;
10150b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov               case 0x172:
10151b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                  insn_suffix = "m";
10152b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                  op = Iop_RoundF32x4_RM;
10153b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                  break;
10154b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov               case 0x152:
10155b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                  insn_suffix = "p";
10156b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                  op = Iop_RoundF32x4_RP;
10157b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                  break;
10158b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov               case 0x132:
10159b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                  insn_suffix = "z";
10160b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                  op = Iop_RoundF32x4_RZ;
10161b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                  break;
10162b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
10163b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov               default:
10164b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                  vex_printf( "dis_vxv_misc(ppc)(vrspi<x>)(opc2)\n" );
10165b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                  return False;
10166b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov            }
10167b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov            DIP("xvrspi%s v%d,v%d\n", insn_suffix, (UInt)XT, (UInt)XB);
10168b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov            putVSReg( XT, unop( op, getVSReg(XB) ) );
10169b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         } else {
10170b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov            // Handle xvrspic.  Unfortunately there is no corresponding "vfric" instruction.
10171b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov            IRExpr * frD_fp_roundb3, * frD_fp_roundb2, * frD_fp_roundb1, * frD_fp_roundb0;
10172b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov            IRTemp b3_F64, b2_F64, b1_F64, b0_F64;
10173b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov            IRTemp b3_I64 = newTemp(Ity_I64);
10174b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov            IRTemp b2_I64 = newTemp(Ity_I64);
10175b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov            IRTemp b1_I64 = newTemp(Ity_I64);
10176b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov            IRTemp b0_I64 = newTemp(Ity_I64);
10177b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
10178b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov            b3_F64 = b2_F64 = b1_F64 = b0_F64 = IRTemp_INVALID;
10179b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov            frD_fp_roundb3 = frD_fp_roundb2 = frD_fp_roundb1 = frD_fp_roundb0 = NULL;
10180b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov            breakV128to4xF64( getVSReg(XB), &b3_F64, &b2_F64, &b1_F64, &b0_F64);
10181b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov            assign(b3_I64, unop(Iop_ReinterpF64asI64, mkexpr(b3_F64)));
10182b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov            assign(b2_I64, unop(Iop_ReinterpF64asI64, mkexpr(b2_F64)));
10183b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov            assign(b1_I64, unop(Iop_ReinterpF64asI64, mkexpr(b1_F64)));
10184b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov            assign(b0_I64, unop(Iop_ReinterpF64asI64, mkexpr(b0_F64)));
10185b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov            frD_fp_roundb3 = unop(Iop_TruncF64asF32,
10186b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                                  _do_vsx_fp_roundToInt(b3_I64, opc2, insn_suffix));
10187b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov            frD_fp_roundb2 = unop(Iop_TruncF64asF32,
10188b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                                  _do_vsx_fp_roundToInt(b2_I64, opc2, insn_suffix));
10189b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov            frD_fp_roundb1 = unop(Iop_TruncF64asF32,
10190b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                                  _do_vsx_fp_roundToInt(b1_I64, opc2, insn_suffix));
10191b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov            frD_fp_roundb0 = unop(Iop_TruncF64asF32,
10192b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                                  _do_vsx_fp_roundToInt(b0_I64, opc2, insn_suffix));
10193b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov            DIP("xvrspic v%d,v%d\n", (UInt)XT, (UInt)XB);
10194b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov            putVSReg( XT,
10195b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                      binop( Iop_64HLtoV128,
10196b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                             binop( Iop_32HLto64,
10197b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                                    unop( Iop_ReinterpF32asI32, frD_fp_roundb3 ),
10198b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                                    unop( Iop_ReinterpF32asI32, frD_fp_roundb2 ) ),
10199b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                             binop( Iop_32HLto64,
10200b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                                    unop( Iop_ReinterpF32asI32, frD_fp_roundb1 ),
10201b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                                    unop( Iop_ReinterpF32asI32, frD_fp_roundb0 ) ) ) );
10202b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         }
10203b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         break;
10204b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      }
10205b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
10206b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      default:
10207b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         vex_printf( "dis_vxv_misc(ppc)(opc2)\n" );
10208b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         return False;
10209b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   }
10210b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   return True;
10211b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov}
10212b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
10213b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
10214b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov/*
10215b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov * VSX Scalar Floating Point Arithmetic Instructions
10216b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov */
10217b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanovstatic Bool
10218b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanovdis_vxs_arith ( UInt theInstr, UInt opc2 )
10219b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov{
10220b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   /* XX3-Form */
10221b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   UChar opc1 = ifieldOPC( theInstr );
10222b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   UChar XT = ifieldRegXT( theInstr );
10223b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   UChar XA = ifieldRegXA( theInstr );
10224b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   UChar XB = ifieldRegXB( theInstr );
10225b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   IRExpr* rm = get_IR_roundingmode();
10226b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   IRTemp frA = newTemp(Ity_F64);
10227b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   IRTemp frB = newTemp(Ity_F64);
10228b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
10229b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   if (opc1 != 0x3C) {
10230b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      vex_printf( "dis_vxs_arith(ppc)(instr)\n" );
10231b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      return False;
10232b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   }
10233b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
10234b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   assign(frA, unop(Iop_ReinterpI64asF64, unop(Iop_V128HIto64, getVSReg( XA ))));
10235b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   assign(frB, unop(Iop_ReinterpI64asF64, unop(Iop_V128HIto64, getVSReg( XB ))));
10236b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
10237b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   /* For all the VSX sclar arithmetic instructions, the contents of doubleword element 1
10238b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov    * of VSX[XT] are undefined after the operation; therefore, we can simply set
10239b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov    * element to zero where it makes sense to do so.
10240b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov    */
10241b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   switch (opc2) {
10242b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      case 0x080: // xsadddp (VSX scalar add double-precision)
10243b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         DIP("xsadddp v%d,v%d,v%d\n", (UInt)XT, (UInt)XA, (UInt)XB);
10244b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         putVSReg( XT, binop( Iop_64HLtoV128, unop( Iop_ReinterpF64asI64,
10245b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                                                    triop( Iop_AddF64, rm,
10246b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                                                           mkexpr( frA ),
10247b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                                                           mkexpr( frB ) ) ),
10248b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                              mkU64( 0 ) ) );
10249b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         break;
10250b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      case 0x0E0: // xsdivdp (VSX scalar divide double-precision)
10251b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         DIP("xsdivdp v%d,v%d,v%d\n", (UInt)XT, (UInt)XA, (UInt)XB);
10252b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         putVSReg( XT, binop( Iop_64HLtoV128, unop( Iop_ReinterpF64asI64,
10253b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                                                    triop( Iop_DivF64, rm,
10254b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                                                           mkexpr( frA ),
10255b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                                                           mkexpr( frB ) ) ),
10256b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                              mkU64( 0 ) ) );
10257b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         break;
10258b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      case 0x084: case 0x0A4: // xsmaddadp, xsmaddmdp (VSX scalar multiply-add double-precision)
10259b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      {
10260b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         IRTemp frT = newTemp(Ity_F64);
10261b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         Bool mdp = opc2 == 0x0A4;
10262b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         DIP("xsmadd%sdp v%d,v%d,v%d\n", mdp ? "m" : "a", (UInt)XT, (UInt)XA, (UInt)XB);
10263b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         assign( frT, unop( Iop_ReinterpI64asF64, unop( Iop_V128HIto64,
10264b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                                                        getVSReg( XT ) ) ) );
10265b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         putVSReg( XT, binop( Iop_64HLtoV128, unop( Iop_ReinterpF64asI64,
10266b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                                                    qop( Iop_MAddF64, rm,
10267b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                                                         mkexpr( frA ),
10268b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                                                         mkexpr( mdp ? frT : frB ),
10269b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                                                         mkexpr( mdp ? frB : frT ) ) ),
10270b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                              mkU64( 0 ) ) );
10271b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         break;
10272b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      }
10273b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      case 0x0C4: case 0x0E4: // xsmsubadp, xsmsubmdp (VSX scalar multiply-subtract double-precision)
10274b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      {
10275b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         IRTemp frT = newTemp(Ity_F64);
10276b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         Bool mdp = opc2 == 0x0E4;
10277b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         DIP("xsmsub%sdp v%d,v%d,v%d\n", mdp ? "m" : "a", (UInt)XT, (UInt)XA, (UInt)XB);
10278b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         assign( frT, unop( Iop_ReinterpI64asF64, unop( Iop_V128HIto64,
10279b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                                                        getVSReg( XT ) ) ) );
10280b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         putVSReg( XT, binop( Iop_64HLtoV128, unop( Iop_ReinterpF64asI64,
10281b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                                                    qop( Iop_MSubF64, rm,
10282b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                                                         mkexpr( frA ),
10283b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                                                         mkexpr( mdp ? frT : frB ),
10284b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                                                         mkexpr( mdp ? frB : frT ) ) ),
10285b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                              mkU64( 0 ) ) );
10286b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         break;
10287b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      }
10288b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      case 0x284: case 0x2A4: // xsnmaddadp, xsnmaddmdp (VSX scalar multiply-add double-precision)
10289b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      {
10290b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         /* TODO: mpj -- Naturally, I expected to be able to leverage the implementation
10291b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov          * of fnmadd and use pretty much the same code. However, that code has a bug in the
10292b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov          * way it blindly negates the signbit, even if the floating point result is a NaN.
10293b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov          * So, the TODO is to fix fnmadd (which I'll do in a different patch).
10294b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov          */
10295b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         Bool mdp = opc2 == 0x2A4;
10296b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         IRTemp frT = newTemp(Ity_F64);
10297b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         IRTemp maddResult = newTemp(Ity_I64);
10298b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
10299b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         DIP("xsnmadd%sdp v%d,v%d,v%d\n", mdp ? "m" : "a", (UInt)XT, (UInt)XA, (UInt)XB);
10300b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         assign( frT, unop( Iop_ReinterpI64asF64, unop( Iop_V128HIto64,
10301b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                                                        getVSReg( XT ) ) ) );
10302b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         assign( maddResult, unop( Iop_ReinterpF64asI64, qop( Iop_MAddF64, rm,
10303b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                                                              mkexpr( frA ),
10304b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                                                              mkexpr( mdp ? frT : frB ),
10305b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                                                              mkexpr( mdp ? frB : frT ) ) ) );
10306b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
10307b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         putVSReg( XT, binop( Iop_64HLtoV128, mkexpr( getNegatedResult(maddResult) ),
10308b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                              mkU64( 0 ) ) );
10309b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         break;
10310b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      }
10311b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      case 0x2C4: case 0x2E4: // xsnmsubadp, xsnmsubmdp (VSX Scalar Negative Multiply-Subtract Double-Precision)
10312b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      {
10313b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         IRTemp frT = newTemp(Ity_F64);
10314b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         Bool mdp = opc2 == 0x2E4;
10315b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         IRTemp msubResult = newTemp(Ity_I64);
10316b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
10317b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         DIP("xsnmsub%sdp v%d,v%d,v%d\n", mdp ? "m" : "a", (UInt)XT, (UInt)XA, (UInt)XB);
10318b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         assign( frT, unop( Iop_ReinterpI64asF64, unop( Iop_V128HIto64,
10319b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                                                        getVSReg( XT ) ) ) );
10320b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         assign(msubResult, unop( Iop_ReinterpF64asI64,
10321b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                                      qop( Iop_MSubF64,
10322b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                                           rm,
10323b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                                           mkexpr( frA ),
10324b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                                           mkexpr( mdp ? frT : frB ),
10325b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                                           mkexpr( mdp ? frB : frT ) ) ));
10326b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
10327b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         putVSReg( XT, binop( Iop_64HLtoV128, mkexpr( getNegatedResult(msubResult) ), mkU64( 0 ) ) );
10328b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
10329b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         break;
10330b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      }
10331b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
10332b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      case 0x0C0: // xsmuldp (VSX Scalar Multiply Double-Precision)
10333b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         DIP("xsmuldp v%d,v%d,v%d\n", (UInt)XT, (UInt)XA, (UInt)XB);
10334b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         putVSReg( XT, binop( Iop_64HLtoV128, unop( Iop_ReinterpF64asI64,
10335b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                                                    triop( Iop_MulF64, rm,
10336b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                                                           mkexpr( frA ),
10337b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                                                           mkexpr( frB ) ) ),
10338b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                              mkU64( 0 ) ) );
10339b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         break;
10340b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      case 0x0A0: // xssubdp (VSX Scalar Subtract Double-Precision)
10341b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         DIP("xssubdp v%d,v%d,v%d\n", (UInt)XT, (UInt)XA, (UInt)XB);
10342b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         putVSReg( XT, binop( Iop_64HLtoV128, unop( Iop_ReinterpF64asI64,
10343b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                                                    triop( Iop_SubF64, rm,
10344b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                                                           mkexpr( frA ),
10345b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                                                           mkexpr( frB ) ) ),
10346b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                              mkU64( 0 ) ) );
10347b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         break;
10348b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
10349b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      case 0x096: // xssqrtdp (VSX Scalar Square Root Double-Precision)
10350b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         DIP("xssqrtdp v%d,v%d\n", (UInt)XT, (UInt)XB);
10351b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         putVSReg( XT,  binop( Iop_64HLtoV128, unop( Iop_ReinterpF64asI64,
10352b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                                                     binop( Iop_SqrtF64, rm,
10353b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                                                            mkexpr( frB ) ) ),
10354b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                               mkU64( 0 ) ) );
10355b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         break;
10356b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
10357b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      case 0x0F4: // xstdivdp (VSX Scalar Test for software Divide Double-Precision)
10358b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      {
10359b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         UChar crfD     = toUChar( IFIELD( theInstr, 23, 3 ) );
10360b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         IRTemp frA_I64 = newTemp(Ity_I64);
10361b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         IRTemp frB_I64 = newTemp(Ity_I64);
10362b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         DIP("xstdivdp crf%d,v%d,v%d\n", crfD, (UInt)XA, (UInt)XB);
10363b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         assign( frA_I64, unop( Iop_ReinterpF64asI64, mkexpr( frA ) ) );
10364b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         assign( frB_I64, unop( Iop_ReinterpF64asI64, mkexpr( frB ) ) );
10365b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         putGST_field( PPC_GST_CR, do_fp_tdiv(frA_I64, frB_I64), crfD );
10366b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         break;
10367b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      }
10368b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      case 0x0D4: // xstsqrtdp (VSX Vector Test for software Square Root Double-Precision)
10369b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      {
10370b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         IRTemp frB_I64 = newTemp(Ity_I64);
10371b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         UChar crfD     = toUChar( IFIELD( theInstr, 23, 3 ) );
10372b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         IRTemp flags = newTemp(Ity_I32);
10373b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         IRTemp  fe_flag, fg_flag;
10374b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         fe_flag = fg_flag = IRTemp_INVALID;
10375b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         DIP("xstsqrtdp v%d,v%d\n", (UInt)XT, (UInt)XB);
10376b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         assign( frB_I64, unop(Iop_V128HIto64, getVSReg( XB )) );
10377b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         do_fp_tsqrt(frB_I64, False /*not single precision*/, &fe_flag, &fg_flag);
10378b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         /* The CR field consists of fl_flag || fg_flag || fe_flag || 0b0
10379b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov          * where fl_flag == 1 on ppc64.
10380b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov          */
10381b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         assign( flags,
10382b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                 binop( Iop_Or32,
10383b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                        binop( Iop_Or32, mkU32( 8 ), // fl_flag
10384b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                               binop( Iop_Shl32, mkexpr(fg_flag), mkU8( 2 ) ) ),
10385b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                        binop( Iop_Shl32, mkexpr(fe_flag), mkU8( 1 ) ) ) );
10386b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         putGST_field( PPC_GST_CR, mkexpr(flags), crfD );
10387b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         break;
10388b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      }
10389b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
10390b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      default:
10391b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         vex_printf( "dis_vxs_arith(ppc)(opc2)\n" );
10392b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         return False;
10393b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   }
10394b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
10395b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   return True;
10396b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov}
10397b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
10398b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
10399b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov/*
10400b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov * VSX Floating Point Compare Instructions
10401b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov */
10402b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanovstatic Bool
10403b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanovdis_vx_cmp( UInt theInstr, UInt opc2 )
10404b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov{
10405b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   /* XX3-Form and XX2-Form */
10406b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   UChar opc1 = ifieldOPC( theInstr );
10407b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   UChar crfD     = toUChar( IFIELD( theInstr, 23, 3 ) );
10408b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   IRTemp ccPPC32;
10409b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   UChar XA       = ifieldRegXA ( theInstr );
10410b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   UChar XB       = ifieldRegXB ( theInstr );
10411b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   IRTemp frA     = newTemp(Ity_F64);
10412b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   IRTemp frB     = newTemp(Ity_F64);
10413b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
10414b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   if (opc1 != 0x3C) {
10415b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      vex_printf( "dis_vx_cmp(ppc)(instr)\n" );
10416b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      return False;
10417b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   }
10418b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
10419b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   assign(frA, unop(Iop_ReinterpI64asF64, unop(Iop_V128HIto64, getVSReg( XA ))));
10420b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   assign(frB, unop(Iop_ReinterpI64asF64, unop(Iop_V128HIto64, getVSReg( XB ))));
10421b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   switch (opc2) {
10422b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      case 0x08C: case 0x0AC: // xscmpudp, xscmpodp
10423b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         /* Note: Differences between xscmpudp and xscmpodp are only in
10424b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov          * exception flag settings, which aren't supported anyway. */
10425b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         DIP("xscmp%sdp crf%d,fr%u,fr%u\n", opc2 == 0x08c ? "u" : "o",
10426b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                                           crfD, (UInt)XA, (UInt)XB);
10427b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         ccPPC32 = get_fp_cmp_CR_val( binop(Iop_CmpF64, mkexpr(frA), mkexpr(frB)));
10428b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         putGST_field( PPC_GST_CR, mkexpr(ccPPC32), crfD );
10429b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         break;
10430b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
10431b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      default:
10432b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         vex_printf( "dis_vx_cmp(ppc)(opc2)\n" );
10433b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         return False;
10434b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   }
10435b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   return True;
10436b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov}
10437b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
10438b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanovstatic void
10439b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanovdo_vvec_fp_cmp ( IRTemp vA, IRTemp vB, UChar XT, UChar flag_rC,
10440b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                 ppc_cmp_t cmp_type )
10441b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov{
10442b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   IRTemp frA_hi     = newTemp(Ity_F64);
10443b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   IRTemp frB_hi     = newTemp(Ity_F64);
10444b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   IRTemp frA_lo     = newTemp(Ity_F64);
10445b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   IRTemp frB_lo     = newTemp(Ity_F64);
10446b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   IRTemp ccPPC32    = newTemp(Ity_I32);
10447b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   IRTemp ccIR_hi;
10448b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   IRTemp ccIR_lo;
10449b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
10450b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   IRTemp hiResult = newTemp(Ity_I64);
10451b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   IRTemp loResult = newTemp(Ity_I64);
10452b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   IRTemp hiEQlo = newTemp(Ity_I1);
10453b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   IRTemp all_elem_true = newTemp(Ity_I32);
10454b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   IRTemp all_elem_false = newTemp(Ity_I32);
10455b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
10456b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   assign(frA_hi, unop(Iop_ReinterpI64asF64, unop(Iop_V128HIto64, mkexpr( vA ))));
10457b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   assign(frB_hi, unop(Iop_ReinterpI64asF64, unop(Iop_V128HIto64, mkexpr( vB ))));
10458b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   assign(frA_lo, unop(Iop_ReinterpI64asF64, unop(Iop_V128to64, mkexpr( vA ))));
10459b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   assign(frB_lo, unop(Iop_ReinterpI64asF64, unop(Iop_V128to64, mkexpr( vB ))));
10460b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
10461b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   ccIR_hi = get_fp_cmp_CR_val( binop( Iop_CmpF64,
10462b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                                       mkexpr( frA_hi ),
10463b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                                       mkexpr( frB_hi ) ) );
10464b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   ccIR_lo = get_fp_cmp_CR_val( binop( Iop_CmpF64,
10465b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                                       mkexpr( frA_lo ),
10466b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                                       mkexpr( frB_lo ) ) );
10467b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
10468b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   if (cmp_type != PPC_CMP_GE) {
10469b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      assign( hiResult,
10470b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov              unop( Iop_1Sto64,
10471b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                    binop( Iop_CmpEQ32, mkexpr( ccIR_hi ), mkU32( cmp_type ) ) ) );
10472b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      assign( loResult,
10473b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov              unop( Iop_1Sto64,
10474b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                    binop( Iop_CmpEQ32, mkexpr( ccIR_lo ), mkU32( cmp_type ) ) ) );
10475b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   } else {
10476b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      // For PPC_CMP_GE, one element compare may return "4" (for "greater than") and
10477b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      // the other element compare may return "2" (for "equal to").
10478b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      IRTemp lo_GE = newTemp(Ity_I1);
10479b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      IRTemp hi_GE = newTemp(Ity_I1);
10480b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
10481b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      assign(hi_GE, mkOR1( binop( Iop_CmpEQ32, mkexpr( ccIR_hi ), mkU32( 2 ) ),
10482b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                           binop( Iop_CmpEQ32, mkexpr( ccIR_hi ), mkU32( 4 ) ) ) );
10483b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      assign( hiResult,unop( Iop_1Sto64, mkexpr( hi_GE ) ) );
10484b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
10485b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      assign(lo_GE, mkOR1( binop( Iop_CmpEQ32, mkexpr( ccIR_lo ), mkU32( 2 ) ),
10486b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                           binop( Iop_CmpEQ32, mkexpr( ccIR_lo ), mkU32( 4 ) ) ) );
10487b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      assign( loResult, unop( Iop_1Sto64, mkexpr( lo_GE ) ) );
10488b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   }
10489b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
10490b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   // The [hi/lo]Result will be all 1's or all 0's.  We just look at the lower word.
10491b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   assign( hiEQlo,
10492b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov           binop( Iop_CmpEQ32,
10493b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                  unop( Iop_64to32, mkexpr( hiResult ) ),
10494b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                  unop( Iop_64to32, mkexpr( loResult ) ) ) );
10495b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   putVSReg( XT,
10496b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov             binop( Iop_64HLtoV128, mkexpr( hiResult ), mkexpr( loResult ) ) );
10497b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
10498b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   assign( all_elem_true,
10499b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov           unop( Iop_1Uto32,
10500b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                 mkAND1( mkexpr( hiEQlo ),
10501b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                         binop( Iop_CmpEQ32,
10502b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                                mkU32( 0xffffffff ),
10503b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                                unop( Iop_64to32,
10504b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                                mkexpr( hiResult ) ) ) ) ) );
10505b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
10506b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   assign( all_elem_false,
10507b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov           unop( Iop_1Uto32,
10508b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                 mkAND1( mkexpr( hiEQlo ),
10509b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                         binop( Iop_CmpEQ32,
10510b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                                mkU32( 0 ),
10511b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                                unop( Iop_64to32,
10512b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                                mkexpr( hiResult ) ) ) ) ) );
10513b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   assign( ccPPC32,
10514b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov           binop( Iop_Or32,
10515b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                  binop( Iop_Shl32, mkexpr( all_elem_false ), mkU8( 1 ) ),
10516b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                  binop( Iop_Shl32, mkexpr( all_elem_true ), mkU8( 3 ) ) ) );
10517b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
10518b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   if (flag_rC) {
10519b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      putGST_field( PPC_GST_CR, mkexpr(ccPPC32), 6 );
10520b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   }
10521b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov}
10522b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
10523b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov/*
10524b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov * VSX Vector Compare Instructions
10525b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov */
10526b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanovstatic Bool
10527b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanovdis_vvec_cmp( UInt theInstr, UInt opc2 )
10528b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov{
10529b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   /* XX3-Form */
10530b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   UChar opc1 = ifieldOPC( theInstr );
10531b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   UChar XT = ifieldRegXT ( theInstr );
10532b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   UChar XA = ifieldRegXA ( theInstr );
10533b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   UChar XB = ifieldRegXB ( theInstr );
10534b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   UChar flag_rC  = ifieldBIT10(theInstr);
10535b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   IRTemp vA = newTemp( Ity_V128 );
10536b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   IRTemp vB = newTemp( Ity_V128 );
10537b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
10538b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   if (opc1 != 0x3C) {
10539b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      vex_printf( "dis_vvec_cmp(ppc)(instr)\n" );
10540b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      return False;
10541b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   }
10542b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
10543b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   assign( vA, getVSReg( XA ) );
10544b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   assign( vB, getVSReg( XB ) );
10545b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
10546b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   switch (opc2) {
10547b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      case 0x18C: case 0x38C:  // xvcmpeqdp[.] (VSX Vector Compare Equal To Double-Precision [ & Record ])
10548b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      {
10549b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         DIP("xvcmpeqdp%s crf%d,fr%u,fr%u\n", (flag_rC ? ".":""),
10550b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov             (UInt)XT, (UInt)XA, (UInt)XB);
10551b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         do_vvec_fp_cmp(vA, vB, XT, flag_rC, PPC_CMP_EQ);
10552b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         break;
10553b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      }
10554b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
10555b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      case 0x1CC: case 0x3CC: // xvcmpgedp[.] (VSX Vector Compare Greater Than or Equal To Double-Precision [ & Record ])
10556b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      {
10557b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         DIP("xvcmpgedp%s crf%d,fr%u,fr%u\n", (flag_rC ? ".":""),
10558b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov             (UInt)XT, (UInt)XA, (UInt)XB);
10559b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         do_vvec_fp_cmp(vA, vB, XT, flag_rC, PPC_CMP_GE);
10560b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         break;
10561b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      }
10562b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
10563b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      case 0x1AC: case 0x3AC: // xvcmpgtdp[.] (VSX Vector Compare Greater Than Double-Precision [ & Record ])
10564b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      {
10565b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         DIP("xvcmpgtdp%s crf%d,fr%u,fr%u\n", (flag_rC ? ".":""),
10566b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov             (UInt)XT, (UInt)XA, (UInt)XB);
10567b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         do_vvec_fp_cmp(vA, vB, XT, flag_rC, PPC_CMP_GT);
10568b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         break;
10569b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      }
10570b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
10571b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      case 0x10C: case 0x30C: // xvcmpeqsp[.] (VSX Vector Compare Equal To Single-Precision [ & Record ])
10572b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      {
10573b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         IRTemp vD = newTemp(Ity_V128);
10574b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
10575b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         DIP("xvcmpeqsp%s crf%d,fr%u,fr%u\n", (flag_rC ? ".":""),
10576b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov             (UInt)XT, (UInt)XA, (UInt)XB);
10577b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         assign( vD, binop(Iop_CmpEQ32Fx4, mkexpr(vA), mkexpr(vB)) );
10578b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         putVSReg( XT, mkexpr(vD) );
10579b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         if (flag_rC) {
10580b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov            set_AV_CR6( mkexpr(vD), True );
10581b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         }
10582b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         break;
10583b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      }
10584b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
10585b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      case 0x14C: case 0x34C: // xvcmpgesp[.] (VSX Vector Compare Greater Than or Equal To Single-Precision [ & Record ])
10586b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      {
10587b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         IRTemp vD = newTemp(Ity_V128);
10588b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
10589b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         DIP("xvcmpgesp%s crf%d,fr%u,fr%u\n", (flag_rC ? ".":""),
10590b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov             (UInt)XT, (UInt)XA, (UInt)XB);
10591b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         assign( vD, binop(Iop_CmpGE32Fx4, mkexpr(vA), mkexpr(vB)) );
10592b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         putVSReg( XT, mkexpr(vD) );
10593b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         if (flag_rC) {
10594b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov            set_AV_CR6( mkexpr(vD), True );
10595b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         }
10596b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         break;
10597b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      }
10598b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
10599b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      case 0x12C: case 0x32C: //xvcmpgtsp[.] (VSX Vector Compare Greater Than Single-Precision [ & Record ])
10600b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      {
10601b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         IRTemp vD = newTemp(Ity_V128);
10602b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
10603b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         DIP("xvcmpgtsp%s crf%d,fr%u,fr%u\n", (flag_rC ? ".":""),
10604b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov             (UInt)XT, (UInt)XA, (UInt)XB);
10605b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         assign( vD, binop(Iop_CmpGT32Fx4, mkexpr(vA), mkexpr(vB)) );
10606b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         putVSReg( XT, mkexpr(vD) );
10607b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         if (flag_rC) {
10608b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov            set_AV_CR6( mkexpr(vD), True );
10609b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         }
10610b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         break;
10611b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      }
10612b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
10613b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      default:
10614b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         vex_printf( "dis_vvec_cmp(ppc)(opc2)\n" );
10615b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         return False;
10616b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   }
10617b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   return True;
10618b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov}
10619b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov/*
10620b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov * Miscellaneous VSX Scalar Instructions
10621b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov */
10622b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanovstatic Bool
10623b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanovdis_vxs_misc( UInt theInstr, UInt opc2 )
10624b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov{
10625b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   /* XX3-Form and XX2-Form */
10626b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   UChar opc1 = ifieldOPC( theInstr );
10627b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   UChar XT = ifieldRegXT ( theInstr );
10628b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   UChar XA = ifieldRegXA ( theInstr );
10629b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   UChar XB = ifieldRegXB ( theInstr );
10630b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   IRTemp vA = newTemp( Ity_V128 );
10631b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   IRTemp vB = newTemp( Ity_V128 );
10632b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
10633b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   if (opc1 != 0x3C) {
10634b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      vex_printf( "dis_vxs_misc(ppc)(instr)\n" );
10635b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      return False;
10636b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   }
10637b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
10638b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   assign( vA, getVSReg( XA ) );
10639b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   assign( vB, getVSReg( XB ) );
10640b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
10641b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   /* For all the VSX move instructions, the contents of doubleword element 1
10642b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov    * of VSX[XT] are undefined after the operation; therefore, we can simply
10643b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov    * move the entire array element where it makes sense to do so.
10644b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov    */
10645b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
10646b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   switch (opc2) {
10647b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      case 0x2B2: // xsabsdp (VSX scalar absolute value double-precision
10648b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      {
10649b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         /* Move abs val of dw 0 of VSX[XB] to dw 0 of VSX[XT]. */
10650b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         IRTemp absVal = newTemp(Ity_V128);
10651b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         assign(absVal, binop(Iop_ShrV128, binop(Iop_ShlV128, mkexpr(vB), mkU8(1)), mkU8(1)));
10652b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         DIP("xsabsdp v%d,v%d\n", (UInt)XT, (UInt)XB);
10653b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         putVSReg(XT, mkexpr(absVal));
10654b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         break;
10655b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      }
10656b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      case 0x2C0: // xscpsgndp
10657b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      {
10658b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         /* Scalar copy sign double-precision */
10659b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         IRTemp vecA_signbit = newTemp(Ity_V128);
10660b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         IRTemp vecB_no_signbit = newTemp(Ity_V128);
10661b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         IRTemp vec_result = newTemp(Ity_V128);
10662b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         DIP("xscpsgndp v%d,v%d v%d\n", (UInt)XT, (UInt)XA, (UInt)XB);
10663b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         assign( vecB_no_signbit, binop( Iop_ShrV128, binop( Iop_ShlV128,
10664b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                                                             mkexpr( vB ),
10665b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                                                             mkU8( 1 ) ),
10666b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                                         mkU8( 1 ) ) );
10667b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         assign( vecA_signbit, binop( Iop_ShlV128, binop( Iop_ShrV128,
10668b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                                                          mkexpr( vA ),
10669b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                                                          mkU8( 127 ) ),
10670b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                                      mkU8( 127 ) ) );
10671b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         assign( vec_result, binop( Iop_OrV128, mkexpr(vecA_signbit), mkexpr( vecB_no_signbit ) ) );
10672b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         putVSReg(XT, mkexpr(vec_result));
10673b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         break;
10674b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      }
10675b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      case 0x2D2: // xsnabsdp
10676b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      {
10677b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         /* Scalar negative absolute value double-precision */
10678b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         IRTemp vec_neg_signbit = newTemp(Ity_V128);
10679b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         DIP("xsnabsdp v%d,v%d\n", (UInt)XT, (UInt)XB);
10680b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         assign( vec_neg_signbit, unop( Iop_NotV128, binop( Iop_ShrV128,
10681b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                                                            mkV128( 0xffff ),
10682b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                                                            mkU8( 1 ) ) ) );
10683b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         putVSReg(XT, binop(Iop_OrV128, mkexpr(vec_neg_signbit), mkexpr(vB)));
10684b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         break;
10685b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      }
10686b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      case 0x2F2: // xsnegdp
10687b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      {
10688b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         /* Scalar negate double-precision */
10689b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         IRTemp vecB_no_signbit = newTemp(Ity_V128);
10690b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         IRTemp vecB_signbit_comp = newTemp(Ity_V128);
10691b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         DIP("xsnabsdp v%d,v%d\n", (UInt)XT, (UInt)XB);
10692b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         assign( vecB_no_signbit, binop( Iop_ShrV128, binop( Iop_ShlV128,
10693b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                                                             mkexpr( vB ),
10694b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                                                             mkU8( 1 ) ),
10695b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                                         mkU8( 1 ) ) );
10696b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         assign( vecB_signbit_comp, binop( Iop_ShlV128,
10697b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                                           unop( Iop_NotV128,
10698b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                                                 binop( Iop_ShrV128,
10699b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                                                        mkexpr( vB ),
10700b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                                                        mkU8( 127 ) ) ),
10701b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                                           mkU8( 127 ) ) );
10702b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         putVSReg( XT, binop( Iop_OrV128, mkexpr( vecB_no_signbit ),
10703b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                              mkexpr( vecB_signbit_comp ) ) );
10704b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         break;
10705b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      }
10706b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      case 0x280: // xsmaxdp (VSX Scalar Maximum Double-Precision)
10707b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      case 0x2A0: // xsmindp (VSX Scalar Minimum Double-Precision)
10708b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      {
10709b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         IRTemp frA     = newTemp(Ity_I64);
10710b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         IRTemp frB     = newTemp(Ity_I64);
10711b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         Bool isMin = opc2 == 0x2A0 ? True : False;
10712b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         DIP("%s v%d,v%d v%d\n", isMin ? "xsmaxdp" : "xsmindp", (UInt)XT, (UInt)XA, (UInt)XB);
10713b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
10714b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         assign(frA, unop(Iop_V128HIto64, mkexpr( vA )));
10715b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         assign(frB, unop(Iop_V128HIto64, mkexpr( vB )));
10716b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         putVSReg( XT, binop( Iop_64HLtoV128, get_max_min_fp(frA, frB, isMin), mkU64( 0 ) ) );
10717b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
10718b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         break;
10719b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      }
10720b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      case 0x0F2: // xsrdpim (VSX Scalar Round to Double-Precision Integer using round toward -Infinity)
10721b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      case 0x0D2: // xsrdpip (VSX Scalar Round to Double-Precision Integer using round toward +Infinity)
10722b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      case 0x0D6: // xsrdpic (VSX Scalar Round to Double-Precision Integer using Current rounding mode)
10723b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      case 0x0B2: // xsrdpiz (VSX Scalar Round to Double-Precision Integer using round toward Zero)
10724b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      case 0x092: // xsrdpi  (VSX Scalar Round to Double-Precision Integer using round toward Nearest Away)
10725b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      {
10726b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         IRTemp frB_I64 = newTemp(Ity_I64);
10727b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         IRExpr * frD_fp_round = NULL;
10728b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         UChar * insn_suffix = NULL;
10729b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
10730b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         assign(frB_I64, unop(Iop_V128HIto64, mkexpr( vB )));
10731b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         frD_fp_round = _do_vsx_fp_roundToInt(frB_I64, opc2, insn_suffix);
10732b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
10733b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         DIP("xsrdpi%s v%d,v%d\n", insn_suffix, (UInt)XT, (UInt)XB);
10734b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         putVSReg( XT,
10735b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                   binop( Iop_64HLtoV128,
10736b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                          unop( Iop_ReinterpF64asI64, frD_fp_round),
10737b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                          mkU64( 0 ) ) );
10738b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         break;
10739b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      }
10740b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      case 0x0B4: // xsredp (VSX Scalar Reciprocal Estimate Double-Precision)
10741b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      case 0x094: // xsrsqrtedp (VSX Scalar Reciprocal Square Root Estimate Double-Precision)
10742b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
10743b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      {
10744b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         IRTemp frB = newTemp(Ity_F64);
10745b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         IRTemp sqrt = newTemp(Ity_F64);
10746b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         IRExpr* ieee_one = IRExpr_Const(IRConst_F64i(0x3ff0000000000000ULL));
10747b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         IRExpr* rm  = get_IR_roundingmode();
10748b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         Bool redp = opc2 == 0x0B4;
10749b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         DIP("%s v%d,v%d\n", redp ? "xsredp" : "xsrsqrtedp", (UInt)XT, (UInt)XB);
10750b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         assign( frB,
10751b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                 unop( Iop_ReinterpI64asF64,
10752b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                       unop( Iop_V128HIto64, mkexpr( vB ) ) ) );
10753b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
10754b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         if (!redp)
10755b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov            assign( sqrt,
10756b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                    binop( Iop_SqrtF64,
10757b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                           rm,
10758b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                           mkexpr(frB) ) );
10759b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         putVSReg( XT,
10760b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                      binop( Iop_64HLtoV128,
10761b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                             unop( Iop_ReinterpF64asI64,
10762b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                                   triop( Iop_DivF64,
10763b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                                          rm,
10764b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                                          ieee_one,
10765b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                                          redp ? mkexpr( frB ) : mkexpr( sqrt ) ) ),
10766b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                             mkU64( 0 ) ) );
10767b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         break;
10768b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      }
10769b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
10770b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      default:
10771b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         vex_printf( "dis_vxs_misc(ppc)(opc2)\n" );
10772b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         return False;
10773b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   }
10774b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   return True;
10775b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov}
10776b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
10777b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov/*
10778b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov * VSX Logical Instructions
10779b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov */
10780b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanovstatic Bool
10781b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanovdis_vx_logic ( UInt theInstr, UInt opc2 )
10782b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov{
10783b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   /* XX3-Form */
10784b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   UChar opc1 = ifieldOPC( theInstr );
10785b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   UChar XT = ifieldRegXT ( theInstr );
10786b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   UChar XA = ifieldRegXA ( theInstr );
10787b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   UChar XB = ifieldRegXB ( theInstr );
10788b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   IRTemp vA = newTemp( Ity_V128 );
10789b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   IRTemp vB = newTemp( Ity_V128 );
10790b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
10791b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   if (opc1 != 0x3C) {
10792b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      vex_printf( "dis_vx_logic(ppc)(instr)\n" );
10793b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      return False;
10794b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   }
10795b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
10796b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   assign( vA, getVSReg( XA ) );
10797b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   assign( vB, getVSReg( XB ) );
10798b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
10799b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   switch (opc2) {
10800b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      case 0x268: // xxlxor
10801b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         DIP("xxlxor v%d,v%d,v%d\n", (UInt)XT, (UInt)XA, (UInt)XB);
10802b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         putVSReg( XT, binop( Iop_XorV128, mkexpr( vA ), mkexpr( vB ) ) );
10803b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         break;
10804b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      case 0x248: // xxlor
10805b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         DIP("xxlor v%d,v%d,v%d\n", (UInt)XT, (UInt)XA, (UInt)XB);
10806b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         putVSReg( XT, binop( Iop_OrV128, mkexpr( vA ), mkexpr( vB ) ) );
10807b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         break;
10808b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      case 0x288: // xxlnor
10809b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         DIP("xxlnor v%d,v%d,v%d\n", (UInt)XT, (UInt)XA, (UInt)XB);
10810b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         putVSReg( XT, unop( Iop_NotV128, binop( Iop_OrV128, mkexpr( vA ),
10811b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                                                 mkexpr( vB ) ) ) );
10812b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         break;
10813b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      case 0x208: // xxland
10814b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         DIP("xxland v%d,v%d,v%d\n", (UInt)XT, (UInt)XA, (UInt)XB);
10815b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         putVSReg( XT, binop( Iop_AndV128, mkexpr( vA ), mkexpr( vB ) ) );
10816b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         break;
10817b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      case 0x228: //xxlandc
10818b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         DIP("xxlandc v%d,v%d,v%d\n", (UInt)XT, (UInt)XA, (UInt)XB);
10819b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         putVSReg( XT, binop( Iop_AndV128, mkexpr( vA ), unop( Iop_NotV128,
10820b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                                                               mkexpr( vB ) ) ) );
10821b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         break;
10822b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      default:
10823b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         vex_printf( "dis_vx_logic(ppc)(opc2)\n" );
10824b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         return False;
10825b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   }
10826b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   return True;
10827b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov}
10828b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
10829b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov/*
10830b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov * VSX Load Instructions
10831b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov * NOTE: VSX supports word-aligned storage access.
10832b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov */
10833b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanovstatic Bool
10834b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanovdis_vx_load ( UInt theInstr )
10835b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov{
10836b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   /* XX1-Form */
10837b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   UChar opc1 = ifieldOPC( theInstr );
10838b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   UChar XT = ifieldRegXT ( theInstr );
10839b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   UChar rA_addr = ifieldRegA( theInstr );
10840b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   UChar rB_addr = ifieldRegB( theInstr );
10841b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   UInt opc2 = ifieldOPClo10( theInstr );
10842b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
10843b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   IRType ty = mode64 ? Ity_I64 : Ity_I32;
10844b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   IRTemp EA = newTemp( ty );
10845b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
10846b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   if (opc1 != 0x1F) {
10847b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      vex_printf( "dis_vx_load(ppc)(instr)\n" );
10848b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      return False;
10849b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   }
10850b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
10851b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   assign( EA, ea_rAor0_idxd( rA_addr, rB_addr ) );
10852b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
10853b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   switch (opc2) {
10854b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   case 0x24C: // lxsdx
10855b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   {
10856b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      IRExpr * exp;
10857b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      DIP("lxsdx %d,r%u,r%u\n", (UInt)XT, rA_addr, rB_addr);
10858b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      exp = loadBE( Ity_I64, mkexpr( EA ) );
10859b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      // We need to pass an expression of type Ity_V128 with putVSReg, but the load
10860b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      // we just performed is only a DW.  But since the contents of VSR[XT] element 1
10861b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      // are undefined after this operation, we can just do a splat op.
10862b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      putVSReg( XT, binop( Iop_64HLtoV128, exp, exp ) );
10863b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      break;
10864b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   }
10865b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   case 0x34C: // lxvd2x
10866b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   {
10867b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      IROp addOp = ty == Ity_I64 ? Iop_Add64 : Iop_Add32;
10868b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      IRExpr * high, *low;
10869b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      ULong ea_off = 8;
10870b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      IRExpr* high_addr;
10871b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      DIP("lxvd2x %d,r%u,r%u\n", (UInt)XT, rA_addr, rB_addr);
10872b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      high = loadBE( Ity_I64, mkexpr( EA ) );
10873b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      high_addr = binop( addOp, mkexpr( EA ), ty == Ity_I64 ? mkU64( ea_off )
10874b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov            : mkU32( ea_off ) );
10875b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      low = loadBE( Ity_I64, high_addr );
10876b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      putVSReg( XT, binop( Iop_64HLtoV128, high, low ) );
10877b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      break;
10878b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   }
10879b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   case 0x14C: // lxvdsx
10880b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   {
10881b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      IRTemp data = newTemp(Ity_I64);
10882b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      DIP("lxvdsx %d,r%u,r%u\n", (UInt)XT, rA_addr, rB_addr);
10883b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      assign( data, loadBE( Ity_I64, mkexpr( EA ) ) );
10884b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      putVSReg( XT, binop( Iop_64HLtoV128, mkexpr( data ), mkexpr( data ) ) );
10885b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      break;
10886b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   }
10887b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   case 0x30C:
10888b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   {
10889b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      IRExpr * t3, *t2, *t1, *t0;
10890b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      UInt ea_off = 0;
10891b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      IRExpr* irx_addr;
10892b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
10893b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      DIP("lxvw4x %d,r%u,r%u\n", (UInt)XT, rA_addr, rB_addr);
10894b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      t3 = loadBE( Ity_I32,  mkexpr( EA ) );
10895b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      ea_off += 4;
10896b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      irx_addr = binop( mkSzOp( ty, Iop_Add8 ), mkexpr( EA ),
10897b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                        ty == Ity_I64 ? mkU64( ea_off ) : mkU32( ea_off ) );
10898b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      t2 = loadBE( Ity_I32, irx_addr );
10899b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      ea_off += 4;
10900b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      irx_addr = binop( mkSzOp( ty, Iop_Add8 ), mkexpr( EA ),
10901b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                        ty == Ity_I64 ? mkU64( ea_off ) : mkU32( ea_off ) );
10902b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      t1 = loadBE( Ity_I32, irx_addr );
10903b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      ea_off += 4;
10904b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      irx_addr = binop( mkSzOp( ty, Iop_Add8 ), mkexpr( EA ),
10905b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                        ty == Ity_I64 ? mkU64( ea_off ) : mkU32( ea_off ) );
10906b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      t0 = loadBE( Ity_I32, irx_addr );
10907b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      putVSReg( XT, binop( Iop_64HLtoV128, binop( Iop_32HLto64, t3, t2 ),
10908b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                           binop( Iop_32HLto64, t1, t0 ) ) );
10909b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      break;
10910b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   }
10911b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   default:
10912b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      vex_printf( "dis_vx_load(ppc)(opc2)\n" );
10913b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      return False;
10914b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   }
10915b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   return True;
10916b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov}
10917b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
10918b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov/*
10919b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov * VSX Store Instructions
10920b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov * NOTE: VSX supports word-aligned storage access.
10921b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov */
10922b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanovstatic Bool
10923b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanovdis_vx_store ( UInt theInstr )
10924b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov{
10925b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   /* XX1-Form */
10926b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   UChar opc1 = ifieldOPC( theInstr );
10927b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   UChar XS = ifieldRegXS( theInstr );
10928b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   UChar rA_addr = ifieldRegA( theInstr );
10929b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   UChar rB_addr = ifieldRegB( theInstr );
10930b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   IRTemp vS = newTemp( Ity_V128 );
10931b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   UInt opc2 = ifieldOPClo10( theInstr );
10932b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
10933b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   IRType ty = mode64 ? Ity_I64 : Ity_I32;
10934b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   IRTemp EA = newTemp( ty );
10935b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
10936b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   if (opc1 != 0x1F) {
10937b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      vex_printf( "dis_vx_store(ppc)(instr)\n" );
10938b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      return False;
10939b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   }
10940b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
10941b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   assign( EA, ea_rAor0_idxd( rA_addr, rB_addr ) );
10942b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   assign( vS, getVSReg( XS ) );
10943b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
10944b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   switch (opc2) {
10945b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   case 0x2CC:
10946b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   {
10947b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      IRExpr * high64;
10948b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      DIP("stxsdx %d,r%u,r%u\n", (UInt)XS, rA_addr, rB_addr);
10949b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      high64 = unop( Iop_V128HIto64, mkexpr( vS ) );
10950b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      storeBE( mkexpr( EA ), high64 );
10951b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      break;
10952b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   }
10953b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   case 0x3CC:
10954b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   {
10955b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      IRExpr * high64, *low64;
10956b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      DIP("stxvd2x %d,r%u,r%u\n", (UInt)XS, rA_addr, rB_addr);
10957b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      high64 = unop( Iop_V128HIto64, mkexpr( vS ) );
10958b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      low64 = unop( Iop_V128to64, mkexpr( vS ) );
10959b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      storeBE( mkexpr( EA ), high64 );
10960b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      storeBE( binop( mkSzOp( ty, Iop_Add8 ), mkexpr( EA ), ty == Ity_I64 ? mkU64( 8 )
10961b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov            : mkU32( 8 ) ), low64 );
10962b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      break;
10963b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   }
10964b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   case 0x38C:
10965b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   {
10966b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      UInt ea_off = 0;
10967b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      IRExpr* irx_addr;
10968b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      IRTemp hi64 = newTemp( Ity_I64 );
10969b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      IRTemp lo64 = newTemp( Ity_I64 );
10970b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
10971b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      DIP("stxvw4x %d,r%u,r%u\n", (UInt)XS, rA_addr, rB_addr);
10972b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
10973b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      // This instruction supports word-aligned stores, so EA may not be
10974b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      // quad-word aligned.  Therefore, do 4 individual word-size stores.
10975b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      assign( hi64, unop( Iop_V128HIto64, mkexpr( vS ) ) );
10976b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      assign( lo64, unop( Iop_V128to64, mkexpr( vS ) ) );
10977b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
10978b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      storeBE( mkexpr( EA ), unop( Iop_64HIto32, mkexpr( hi64 ) ) );
10979b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      ea_off += 4;
10980b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      irx_addr = binop( mkSzOp( ty, Iop_Add8 ), mkexpr( EA ),
10981b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                        ty == Ity_I64 ? mkU64( ea_off ) : mkU32( ea_off ) );
10982b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      storeBE( irx_addr, unop( Iop_64to32, mkexpr( hi64 ) ) );
10983b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      ea_off += 4;
10984b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      irx_addr = binop( mkSzOp( ty, Iop_Add8 ), mkexpr( EA ),
10985b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                        ty == Ity_I64 ? mkU64( ea_off ) : mkU32( ea_off ) );
10986b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      storeBE( irx_addr, unop( Iop_64HIto32, mkexpr( lo64 ) ) );
10987b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      ea_off += 4;
10988b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      irx_addr = binop( mkSzOp( ty, Iop_Add8 ), mkexpr( EA ),
10989b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                        ty == Ity_I64 ? mkU64( ea_off ) : mkU32( ea_off ) );
10990b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      storeBE( irx_addr, unop( Iop_64to32, mkexpr( lo64 ) ) );
10991b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
10992b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      break;
10993b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   }
10994b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   default:
10995b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      vex_printf( "dis_vx_store(ppc)(opc2)\n" );
10996b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      return False;
10997b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   }
10998b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   return True;
10999b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov}
11000b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
11001b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov/*
11002b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov * VSX permute and other miscealleous instructions
11003b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov */
11004b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanovstatic Bool
11005b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanovdis_vx_permute_misc( UInt theInstr, UInt opc2 )
11006b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov{
11007b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   /* XX3-Form */
11008b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   UChar opc1 = ifieldOPC( theInstr );
11009b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   UChar XT = ifieldRegXT ( theInstr );
11010b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   UChar XA = ifieldRegXA ( theInstr );
11011b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   UChar XB = ifieldRegXB ( theInstr );
11012b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   IRTemp vT = newTemp( Ity_V128 );
11013b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   IRTemp vA = newTemp( Ity_V128 );
11014b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   IRTemp vB = newTemp( Ity_V128 );
11015b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
11016b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   if (opc1 != 0x3C) {
11017b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      vex_printf( "dis_vx_permute_misc(ppc)(instr)\n" );
11018b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      return False;
11019b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   }
11020b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
11021b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   assign( vA, getVSReg( XA ) );
11022b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   assign( vB, getVSReg( XB ) );
11023b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
11024b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   switch (opc2) {
11025b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      case 0x8: // xxsldwi (VSX Shift Left Double by Word Immediate)
11026b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      {
11027b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         UChar SHW = ifieldSHW ( theInstr );
11028b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         IRTemp result = newTemp(Ity_V128);
11029b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         if ( SHW != 0 ) {
11030b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov             IRTemp hi = newTemp(Ity_V128);
11031b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov             IRTemp lo = newTemp(Ity_V128);
11032b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov             assign( hi, binop(Iop_ShlV128, mkexpr(vA), mkU8(SHW*32)) );
11033b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov             assign( lo, binop(Iop_ShrV128, mkexpr(vB), mkU8(128-SHW*32)) );
11034b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov             assign ( result, binop(Iop_OrV128, mkexpr(hi), mkexpr(lo)) );
11035b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         } else
11036b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov             assign ( result, mkexpr(vA) );
11037b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         DIP("xxsldwi v%d,v%d,v%d,%d\n", (UInt)XT, (UInt)XA, (UInt)XB, (UInt)SHW);
11038b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         putVSReg( XT, mkexpr(result) );
11039b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         break;
11040b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      }
11041b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      case 0x28: // xpermdi (VSX Permute Doubleword Immediate)
11042b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      {
11043b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         UChar DM = ifieldDM ( theInstr );
11044b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         IRTemp hi = newTemp(Ity_I64);
11045b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         IRTemp lo = newTemp(Ity_I64);
11046b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
11047b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         if (DM & 0x2)
11048b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov           assign( hi, unop(Iop_V128to64, mkexpr(vA)) );
11049b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         else
11050b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov           assign( hi, unop(Iop_V128HIto64, mkexpr(vA)) );
11051b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
11052b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         if (DM & 0x1)
11053b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov           assign( lo, unop(Iop_V128to64, mkexpr(vB)) );
11054b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         else
11055b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov           assign( lo, unop(Iop_V128HIto64, mkexpr(vB)) );
11056b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
11057b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         assign( vT, binop(Iop_64HLtoV128, mkexpr(hi), mkexpr(lo)) );
11058b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
11059b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         DIP("xxpermdi v%d,v%d,v%d,0x%x\n", (UInt)XT, (UInt)XA, (UInt)XB, (UInt)DM);
11060b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         putVSReg( XT, mkexpr( vT ) );
11061b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         break;
11062b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      }
11063b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      case 0x48: // xxmrghw (VSX Merge High Word)
11064b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      case 0xc8: // xxmrglw (VSX Merge Low Word)
11065b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      {
11066b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         char type = (opc2 == 0x48) ? 'h' : 'l';
11067b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         IROp word_op = (opc2 == 0x48) ? Iop_V128HIto64 : Iop_V128to64;
11068b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         IRTemp a64 = newTemp(Ity_I64);
11069b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         IRTemp ahi32 = newTemp(Ity_I32);
11070b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         IRTemp alo32 = newTemp(Ity_I32);
11071b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         IRTemp b64 = newTemp(Ity_I64);
11072b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         IRTemp bhi32 = newTemp(Ity_I32);
11073b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         IRTemp blo32 = newTemp(Ity_I32);
11074b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
11075b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         assign( a64, unop(word_op, mkexpr(vA)) );
11076b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         assign( ahi32, unop(Iop_64HIto32, mkexpr(a64)) );
11077b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         assign( alo32, unop(Iop_64to32, mkexpr(a64)) );
11078b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
11079b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         assign( b64, unop(word_op, mkexpr(vB)) );
11080b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         assign( bhi32, unop(Iop_64HIto32, mkexpr(b64)) );
11081b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         assign( blo32, unop(Iop_64to32, mkexpr(b64)) );
11082b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
11083b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         assign( vT, binop(Iop_64HLtoV128,
11084b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                           binop(Iop_32HLto64, mkexpr(ahi32), mkexpr(bhi32)),
11085b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                           binop(Iop_32HLto64, mkexpr(alo32), mkexpr(blo32))) );
11086b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
11087b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         DIP("xxmrg%cw v%d,v%d,v%d\n", type, (UInt)XT, (UInt)XA, (UInt)XB);
11088b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         putVSReg( XT, mkexpr( vT ) );
11089b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         break;
11090b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      }
11091b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      case 0x018: // xxsel (VSX Select)
11092b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      {
11093b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         UChar XC = ifieldRegXC(theInstr);
11094b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         IRTemp vC = newTemp( Ity_V128 );
11095b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         assign( vC, getVSReg( XC ) );
11096b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         DIP("xxsel v%d,v%d,v%d,v%d\n", (UInt)XT, (UInt)XA, (UInt)XB, (UInt)XC);
11097b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         /* vD = (vA & ~vC) | (vB & vC) */
11098b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         putVSReg( XT, binop(Iop_OrV128,
11099b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov            binop(Iop_AndV128, mkexpr(vA), unop(Iop_NotV128, mkexpr(vC))),
11100b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov            binop(Iop_AndV128, mkexpr(vB), mkexpr(vC))) );
11101b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         break;
11102b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      }
11103b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      case 0x148: // xxspltw (VSX Splat Word)
11104b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      {
11105b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         UChar UIM   = ifieldRegA(theInstr) & 3;
11106b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         UChar sh_uim = (3 - (UIM)) * 32;
11107b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         DIP("xxspltw v%d,v%d,%d\n", (UInt)XT, (UInt)XB, UIM);
11108b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         putVSReg( XT,
11109b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                   unop( Iop_Dup32x4,
11110b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                         unop( Iop_V128to32,
11111b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                               binop( Iop_ShrV128, mkexpr( vB ), mkU8( sh_uim ) ) ) ) );
11112b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         break;
11113b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      }
11114b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
11115b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      default:
11116b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         vex_printf( "dis_vx_permute_misc(ppc)(opc2)\n" );
11117b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         return False;
11118b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   }
11119b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   return True;
11120b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov}
11121b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
11122b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov/*
11123ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  AltiVec Load Instructions
11124ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown*/
11125ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic Bool dis_av_load ( VexAbiInfo* vbi, UInt theInstr )
11126ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
11127ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* X-Form */
11128ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   UChar opc1     = ifieldOPC(theInstr);
11129ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   UChar vD_addr  = ifieldRegDS(theInstr);
11130ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   UChar rA_addr  = ifieldRegA(theInstr);
11131ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   UChar rB_addr  = ifieldRegB(theInstr);
11132ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   UInt  opc2     = ifieldOPClo10(theInstr);
11133ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   UChar b0       = ifieldBIT0(theInstr);
11134ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
11135ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   IRType ty         = mode64 ? Ity_I64 : Ity_I32;
11136ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   IRTemp EA         = newTemp(ty);
11137ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   IRTemp EA_align16 = newTemp(ty);
11138ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
11139ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (opc1 != 0x1F || b0 != 0) {
11140ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      vex_printf("dis_av_load(ppc)(instr)\n");
11141ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      return False;
11142ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
11143ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
11144ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   assign( EA, ea_rAor0_idxd(rA_addr, rB_addr) );
11145ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   assign( EA_align16, addr_align( mkexpr(EA), 16 ) );
11146ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
11147ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   switch (opc2) {
11148ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
11149ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   case 0x006: { // lvsl (Load Vector for Shift Left, AV p123)
11150ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      IRDirty* d;
11151ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      UInt vD_off = vectorGuestRegOffset(vD_addr);
11152ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      IRExpr** args = mkIRExprVec_3(
11153ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                         mkU32(vD_off),
11154ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                         binop(Iop_And32, mkNarrowTo32(ty, mkexpr(EA)),
11155ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                          mkU32(0xF)),
11156ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                         mkU32(0)/*left*/ );
11157ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (!mode64) {
11158ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         d = unsafeIRDirty_0_N (
11159ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                        0/*regparms*/,
11160ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                        "ppc32g_dirtyhelper_LVS",
11161ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                        fnptr_to_fnentry(vbi, &ppc32g_dirtyhelper_LVS),
11162ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                        args );
11163ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      } else {
11164ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         d = unsafeIRDirty_0_N (
11165ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                        0/*regparms*/,
11166ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                        "ppc64g_dirtyhelper_LVS",
11167ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                        fnptr_to_fnentry(vbi, &ppc64g_dirtyhelper_LVS),
11168ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                        args );
11169ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
11170ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      DIP("lvsl v%d,r%u,r%u\n", vD_addr, rA_addr, rB_addr);
11171ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* declare guest state effects */
11172ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      d->needsBBP = True;
11173ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      d->nFxState = 1;
11174ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      d->fxState[0].fx     = Ifx_Write;
11175ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      d->fxState[0].offset = vD_off;
11176ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      d->fxState[0].size   = sizeof(U128);
11177ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
11178ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* execute the dirty call, side-effecting guest state */
11179ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      stmt( IRStmt_Dirty(d) );
11180ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      break;
11181ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
11182ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   case 0x026: { // lvsr (Load Vector for Shift Right, AV p125)
11183ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      IRDirty* d;
11184ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      UInt vD_off = vectorGuestRegOffset(vD_addr);
11185ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      IRExpr** args = mkIRExprVec_3(
11186ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                         mkU32(vD_off),
11187ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                         binop(Iop_And32, mkNarrowTo32(ty, mkexpr(EA)),
11188ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                          mkU32(0xF)),
11189ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                         mkU32(1)/*right*/ );
11190ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (!mode64) {
11191ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         d = unsafeIRDirty_0_N (
11192ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                        0/*regparms*/,
11193ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                        "ppc32g_dirtyhelper_LVS",
11194ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                        fnptr_to_fnentry(vbi, &ppc32g_dirtyhelper_LVS),
11195ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                        args );
11196ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      } else {
11197ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         d = unsafeIRDirty_0_N (
11198ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                        0/*regparms*/,
11199ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                        "ppc64g_dirtyhelper_LVS",
11200ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                        fnptr_to_fnentry(vbi, &ppc64g_dirtyhelper_LVS),
11201ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                        args );
11202ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
11203ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      DIP("lvsr v%d,r%u,r%u\n", vD_addr, rA_addr, rB_addr);
11204ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* declare guest state effects */
11205ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      d->needsBBP = True;
11206ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      d->nFxState = 1;
11207ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      d->fxState[0].fx     = Ifx_Write;
11208ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      d->fxState[0].offset = vD_off;
11209ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      d->fxState[0].size   = sizeof(U128);
11210ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
11211ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* execute the dirty call, side-effecting guest state */
11212ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      stmt( IRStmt_Dirty(d) );
11213ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      break;
11214ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
11215ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   case 0x007: // lvebx (Load Vector Element Byte Indexed, AV p119)
11216ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      DIP("lvebx v%d,r%u,r%u\n", vD_addr, rA_addr, rB_addr);
11217ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* loads addressed byte into vector[EA[0:3]
11218ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         since all other destination bytes are undefined,
11219ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         can simply load entire vector from 16-aligned EA */
11220ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      putVReg( vD_addr, loadBE(Ity_V128, mkexpr(EA_align16)) );
11221ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      break;
11222ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
11223ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   case 0x027: // lvehx (Load Vector Element Half Word Indexed, AV p121)
11224ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      DIP("lvehx v%d,r%u,r%u\n", vD_addr, rA_addr, rB_addr);
11225ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* see note for lvebx */
11226ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      putVReg( vD_addr, loadBE(Ity_V128, mkexpr(EA_align16)) );
11227ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      break;
11228ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
11229ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   case 0x047: // lvewx (Load Vector Element Word Indexed, AV p122)
11230ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      DIP("lvewx v%d,r%u,r%u\n", vD_addr, rA_addr, rB_addr);
11231ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* see note for lvebx */
11232ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      putVReg( vD_addr, loadBE(Ity_V128, mkexpr(EA_align16)) );
11233ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      break;
11234ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
11235ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   case 0x067: // lvx (Load Vector Indexed, AV p127)
11236ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      DIP("lvx v%d,r%u,r%u\n", vD_addr, rA_addr, rB_addr);
11237ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      putVReg( vD_addr, loadBE(Ity_V128, mkexpr(EA_align16)) );
11238ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      break;
11239ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
11240ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   case 0x167: // lvxl (Load Vector Indexed LRU, AV p128)
11241ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      DIP("lvxl v%d,r%u,r%u\n", vD_addr, rA_addr, rB_addr);
11242ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      putVReg( vD_addr, loadBE(Ity_V128, mkexpr(EA_align16)) );
11243ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      break;
11244ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
11245ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   default:
11246ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      vex_printf("dis_av_load(ppc)(opc2)\n");
11247ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      return False;
11248ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
11249ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   return True;
11250ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
11251ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
11252ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*
11253ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  AltiVec Store Instructions
11254ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown*/
11255ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic Bool dis_av_store ( UInt theInstr )
11256ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
11257ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* X-Form */
11258ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   UChar opc1     = ifieldOPC(theInstr);
11259ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   UChar vS_addr  = ifieldRegDS(theInstr);
11260ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   UChar rA_addr  = ifieldRegA(theInstr);
11261ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   UChar rB_addr  = ifieldRegB(theInstr);
11262ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   UInt  opc2     = ifieldOPClo10(theInstr);
11263ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   UChar b0       = ifieldBIT0(theInstr);
11264ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
11265ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   IRType ty           = mode64 ? Ity_I64 : Ity_I32;
11266ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   IRTemp EA           = newTemp(ty);
11267ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   IRTemp addr_aligned = newTemp(ty);
11268ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   IRTemp vS           = newTemp(Ity_V128);
11269ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   IRTemp eb           = newTemp(Ity_I8);
11270ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   IRTemp idx          = newTemp(Ity_I8);
11271ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
11272ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (opc1 != 0x1F || b0 != 0) {
11273ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      vex_printf("dis_av_store(ppc)(instr)\n");
11274ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      return False;
11275ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
11276ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
11277ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   assign( vS, getVReg(vS_addr));
11278ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   assign( EA, ea_rAor0_idxd(rA_addr, rB_addr) );
11279ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
11280ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   switch (opc2) {
11281ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   case 0x087: { // stvebx (Store Vector Byte Indexed, AV p131)
11282ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      DIP("stvebx v%d,r%u,r%u\n", vS_addr, rA_addr, rB_addr);
11283ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      assign( eb, binop(Iop_And8, mkU8(0xF),
11284ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                        unop(Iop_32to8,
11285ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                             mkNarrowTo32(ty, mkexpr(EA)) )) );
11286ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      assign( idx, binop(Iop_Shl8,
11287ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                         binop(Iop_Sub8, mkU8(15), mkexpr(eb)),
11288ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                         mkU8(3)) );
11289ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      storeBE( mkexpr(EA),
11290ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               unop(Iop_32to8, unop(Iop_V128to32,
11291ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                    binop(Iop_ShrV128, mkexpr(vS), mkexpr(idx)))) );
11292ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      break;
11293ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
11294ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   case 0x0A7: { // stvehx (Store Vector Half Word Indexed, AV p132)
11295ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      DIP("stvehx v%d,r%u,r%u\n", vS_addr, rA_addr, rB_addr);
11296ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      assign( addr_aligned, addr_align(mkexpr(EA), 2) );
11297ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      assign( eb, binop(Iop_And8, mkU8(0xF),
11298ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                        mkNarrowTo8(ty, mkexpr(addr_aligned) )) );
11299ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      assign( idx, binop(Iop_Shl8,
11300ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                         binop(Iop_Sub8, mkU8(14), mkexpr(eb)),
11301ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                         mkU8(3)) );
11302ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      storeBE( mkexpr(addr_aligned),
11303ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               unop(Iop_32to16, unop(Iop_V128to32,
11304ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                    binop(Iop_ShrV128, mkexpr(vS), mkexpr(idx)))) );
11305ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      break;
11306ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
11307ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   case 0x0C7: { // stvewx (Store Vector Word Indexed, AV p133)
11308ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      DIP("stvewx v%d,r%u,r%u\n", vS_addr, rA_addr, rB_addr);
11309ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      assign( addr_aligned, addr_align(mkexpr(EA), 4) );
11310ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      assign( eb, binop(Iop_And8, mkU8(0xF),
11311ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                        mkNarrowTo8(ty, mkexpr(addr_aligned) )) );
11312ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      assign( idx, binop(Iop_Shl8,
11313ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                         binop(Iop_Sub8, mkU8(12), mkexpr(eb)),
11314ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                         mkU8(3)) );
11315ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      storeBE( mkexpr(addr_aligned),
11316ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               unop(Iop_V128to32,
11317ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                    binop(Iop_ShrV128, mkexpr(vS), mkexpr(idx))) );
11318ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      break;
11319ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
11320ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
11321ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   case 0x0E7: // stvx (Store Vector Indexed, AV p134)
11322ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      DIP("stvx v%d,r%u,r%u\n", vS_addr, rA_addr, rB_addr);
11323ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      storeBE( addr_align( mkexpr(EA), 16 ), mkexpr(vS) );
11324ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      break;
11325ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
11326ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   case 0x1E7: // stvxl (Store Vector Indexed LRU, AV p135)
11327ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      DIP("stvxl v%d,r%u,r%u\n", vS_addr, rA_addr, rB_addr);
11328ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      storeBE( addr_align( mkexpr(EA), 16 ), mkexpr(vS) );
11329ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      break;
11330ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
11331ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   default:
11332ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      vex_printf("dis_av_store(ppc)(opc2)\n");
11333ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      return False;
11334ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
11335ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   return True;
11336ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
11337ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
11338ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*
11339ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  AltiVec Arithmetic Instructions
11340ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown*/
11341ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic Bool dis_av_arith ( UInt theInstr )
11342ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
11343ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* VX-Form */
11344ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   UChar opc1     = ifieldOPC(theInstr);
11345ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   UChar vD_addr  = ifieldRegDS(theInstr);
11346ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   UChar vA_addr  = ifieldRegA(theInstr);
11347ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   UChar vB_addr  = ifieldRegB(theInstr);
11348ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   UInt  opc2     = IFIELD( theInstr, 0, 11 );
11349ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
11350ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   IRTemp vA = newTemp(Ity_V128);
11351ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   IRTemp vB = newTemp(Ity_V128);
11352ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   IRTemp z3 = newTemp(Ity_I64);
11353ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   IRTemp z2 = newTemp(Ity_I64);
11354ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   IRTemp z1 = newTemp(Ity_I64);
11355ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   IRTemp z0 = newTemp(Ity_I64);
11356ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   IRTemp aEvn, aOdd;
11357ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   IRTemp a15, a14, a13, a12, a11, a10, a9, a8;
11358ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   IRTemp a7, a6, a5, a4, a3, a2, a1, a0;
11359ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   IRTemp b3, b2, b1, b0;
11360ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
11361ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   aEvn = aOdd = IRTemp_INVALID;
11362ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   a15 = a14 = a13 = a12 = a11 = a10 = a9 = a8 = IRTemp_INVALID;
11363ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   a7 = a6 = a5 = a4 = a3 = a2 = a1 = a0 = IRTemp_INVALID;
11364ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   b3 = b2 = b1 = b0 = IRTemp_INVALID;
11365ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
11366ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   assign( vA, getVReg(vA_addr));
11367ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   assign( vB, getVReg(vB_addr));
11368ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
11369ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (opc1 != 0x4) {
11370ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      vex_printf("dis_av_arith(ppc)(opc1 != 0x4)\n");
11371ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      return False;
11372ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
11373ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
11374ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   switch (opc2) {
11375ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* Add */
11376ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   case 0x180: { // vaddcuw (Add Carryout Unsigned Word, AV p136)
11377ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      DIP("vaddcuw v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
11378ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* unsigned_ov(x+y) = (y >u not(x)) */
11379ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      putVReg( vD_addr, binop(Iop_ShrN32x4,
11380ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                              binop(Iop_CmpGT32Ux4, mkexpr(vB),
11381ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                    unop(Iop_NotV128, mkexpr(vA))),
11382ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                              mkU8(31)) );
11383ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      break;
11384ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
11385ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   case 0x000: // vaddubm (Add Unsigned Byte Modulo, AV p141)
11386ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      DIP("vaddubm v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
11387ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      putVReg( vD_addr, binop(Iop_Add8x16, mkexpr(vA), mkexpr(vB)) );
11388ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      break;
11389ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
11390ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   case 0x040: // vadduhm (Add Unsigned Half Word Modulo, AV p143)
11391ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      DIP("vadduhm v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
11392ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      putVReg( vD_addr, binop(Iop_Add16x8, mkexpr(vA), mkexpr(vB)) );
11393ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      break;
11394ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
11395ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   case 0x080: // vadduwm (Add Unsigned Word Modulo, AV p145)
11396ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      DIP("vadduwm v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
11397ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      putVReg( vD_addr, binop(Iop_Add32x4, mkexpr(vA), mkexpr(vB)) );
11398ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      break;
11399ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
11400ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   case 0x200: // vaddubs (Add Unsigned Byte Saturate, AV p142)
11401ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      DIP("vaddubs v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
11402ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      putVReg( vD_addr, binop(Iop_QAdd8Ux16, mkexpr(vA), mkexpr(vB)) );
11403ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      // TODO: set VSCR[SAT], perhaps via new primop: Iop_SatOfQAdd8Ux16
11404ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      break;
11405ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
11406ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   case 0x240: // vadduhs (Add Unsigned Half Word Saturate, AV p144)
11407ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      DIP("vadduhs v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
11408ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      putVReg( vD_addr, binop(Iop_QAdd16Ux8, mkexpr(vA), mkexpr(vB)) );
11409ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      // TODO: set VSCR[SAT]
11410ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      break;
11411ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
11412ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   case 0x280: // vadduws (Add Unsigned Word Saturate, AV p146)
11413ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      DIP("vadduws v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
11414ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      putVReg( vD_addr, binop(Iop_QAdd32Ux4, mkexpr(vA), mkexpr(vB)) );
11415ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      // TODO: set VSCR[SAT]
11416ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      break;
11417ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
11418ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   case 0x300: // vaddsbs (Add Signed Byte Saturate, AV p138)
11419ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      DIP("vaddsbs v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
11420ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      putVReg( vD_addr, binop(Iop_QAdd8Sx16, mkexpr(vA), mkexpr(vB)) );
11421ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      // TODO: set VSCR[SAT]
11422ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      break;
11423ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
11424ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   case 0x340: // vaddshs (Add Signed Half Word Saturate, AV p139)
11425ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      DIP("vaddshs v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
11426ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      putVReg( vD_addr, binop(Iop_QAdd16Sx8, mkexpr(vA), mkexpr(vB)) );
11427ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      // TODO: set VSCR[SAT]
11428ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      break;
11429ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
11430ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   case 0x380: // vaddsws (Add Signed Word Saturate, AV p140)
11431ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      DIP("vaddsws v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
11432ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      putVReg( vD_addr, binop(Iop_QAdd32Sx4, mkexpr(vA), mkexpr(vB)) );
11433ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      // TODO: set VSCR[SAT]
11434ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      break;
11435ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
11436ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
11437ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* Subtract */
11438ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   case 0x580: { // vsubcuw (Subtract Carryout Unsigned Word, AV p260)
11439ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      DIP("vsubcuw v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
11440ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* unsigned_ov(x-y) = (y >u x) */
11441ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      putVReg( vD_addr, binop(Iop_ShrN32x4,
11442ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                              unop(Iop_NotV128,
11443ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                   binop(Iop_CmpGT32Ux4, mkexpr(vB),
11444ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                         mkexpr(vA))),
11445ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                              mkU8(31)) );
11446ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      break;
11447ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
11448ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   case 0x400: // vsububm (Subtract Unsigned Byte Modulo, AV p265)
11449ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      DIP("vsububm v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
11450ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      putVReg( vD_addr, binop(Iop_Sub8x16, mkexpr(vA), mkexpr(vB)) );
11451ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      break;
11452ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
11453ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   case 0x440: // vsubuhm (Subtract Unsigned Half Word Modulo, AV p267)
11454ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      DIP("vsubuhm v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
11455ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      putVReg( vD_addr, binop(Iop_Sub16x8, mkexpr(vA), mkexpr(vB)) );
11456ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      break;
11457ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
11458ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   case 0x480: // vsubuwm (Subtract Unsigned Word Modulo, AV p269)
11459ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      DIP("vsubuwm v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
11460ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      putVReg( vD_addr, binop(Iop_Sub32x4, mkexpr(vA), mkexpr(vB)) );
11461ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      break;
11462ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
11463ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   case 0x600: // vsububs (Subtract Unsigned Byte Saturate, AV p266)
11464ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      DIP("vsububs v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
11465ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      putVReg( vD_addr, binop(Iop_QSub8Ux16, mkexpr(vA), mkexpr(vB)) );
11466ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      // TODO: set VSCR[SAT]
11467ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      break;
11468ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
11469ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   case 0x640: // vsubuhs (Subtract Unsigned HWord Saturate, AV p268)
11470ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      DIP("vsubuhs v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
11471ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      putVReg( vD_addr, binop(Iop_QSub16Ux8, mkexpr(vA), mkexpr(vB)) );
11472ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      // TODO: set VSCR[SAT]
11473ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      break;
11474ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
11475ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   case 0x680: // vsubuws (Subtract Unsigned Word Saturate, AV p270)
11476ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      DIP("vsubuws v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
11477ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      putVReg( vD_addr, binop(Iop_QSub32Ux4, mkexpr(vA), mkexpr(vB)) );
11478ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      // TODO: set VSCR[SAT]
11479ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      break;
11480ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
11481ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   case 0x700: // vsubsbs (Subtract Signed Byte Saturate, AV p262)
11482ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      DIP("vsubsbs v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
11483ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      putVReg( vD_addr, binop(Iop_QSub8Sx16, mkexpr(vA), mkexpr(vB)) );
11484ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      // TODO: set VSCR[SAT]
11485ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      break;
11486ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
11487ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   case 0x740: // vsubshs (Subtract Signed Half Word Saturate, AV p263)
11488ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      DIP("vsubshs v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
11489ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      putVReg( vD_addr, binop(Iop_QSub16Sx8, mkexpr(vA), mkexpr(vB)) );
11490ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      // TODO: set VSCR[SAT]
11491ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      break;
11492ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
11493ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   case 0x780: // vsubsws (Subtract Signed Word Saturate, AV p264)
11494ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      DIP("vsubsws v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
11495ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      putVReg( vD_addr, binop(Iop_QSub32Sx4, mkexpr(vA), mkexpr(vB)) );
11496ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      // TODO: set VSCR[SAT]
11497ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      break;
11498ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
11499ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
11500ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* Maximum */
11501ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   case 0x002: // vmaxub (Maximum Unsigned Byte, AV p182)
11502ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      DIP("vmaxub v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
11503ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      putVReg( vD_addr, binop(Iop_Max8Ux16, mkexpr(vA), mkexpr(vB)) );
11504ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      break;
11505ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
11506ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   case 0x042: // vmaxuh (Maximum Unsigned Half Word, AV p183)
11507ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      DIP("vmaxuh v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
11508ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      putVReg( vD_addr, binop(Iop_Max16Ux8, mkexpr(vA), mkexpr(vB)) );
11509ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      break;
11510ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
11511ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   case 0x082: // vmaxuw (Maximum Unsigned Word, AV p184)
11512ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      DIP("vmaxuw v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
11513ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      putVReg( vD_addr, binop(Iop_Max32Ux4, mkexpr(vA), mkexpr(vB)) );
11514ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      break;
11515ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
11516ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   case 0x102: // vmaxsb (Maximum Signed Byte, AV p179)
11517ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      DIP("vmaxsb v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
11518ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      putVReg( vD_addr, binop(Iop_Max8Sx16, mkexpr(vA), mkexpr(vB)) );
11519ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      break;
11520ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
11521ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   case 0x142: // vmaxsh (Maximum Signed Half Word, AV p180)
11522ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      DIP("vmaxsh v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
11523ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      putVReg( vD_addr, binop(Iop_Max16Sx8, mkexpr(vA), mkexpr(vB)) );
11524ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      break;
11525ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
11526ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   case 0x182: // vmaxsw (Maximum Signed Word, AV p181)
11527ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      DIP("vmaxsw v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
11528ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      putVReg( vD_addr, binop(Iop_Max32Sx4, mkexpr(vA), mkexpr(vB)) );
11529ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      break;
11530ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
11531ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
11532ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* Minimum */
11533ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   case 0x202: // vminub (Minimum Unsigned Byte, AV p191)
11534ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      DIP("vminub v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
11535ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      putVReg( vD_addr, binop(Iop_Min8Ux16, mkexpr(vA), mkexpr(vB)) );
11536ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      break;
11537ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
11538ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   case 0x242: // vminuh (Minimum Unsigned Half Word, AV p192)
11539ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      DIP("vminuh v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
11540ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      putVReg( vD_addr, binop(Iop_Min16Ux8, mkexpr(vA), mkexpr(vB)) );
11541ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      break;
11542ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
11543ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   case 0x282: // vminuw (Minimum Unsigned Word, AV p193)
11544ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      DIP("vminuw v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
11545ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      putVReg( vD_addr, binop(Iop_Min32Ux4, mkexpr(vA), mkexpr(vB)) );
11546ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      break;
11547ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
11548ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   case 0x302: // vminsb (Minimum Signed Byte, AV p188)
11549ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      DIP("vminsb v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
11550ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      putVReg( vD_addr, binop(Iop_Min8Sx16, mkexpr(vA), mkexpr(vB)) );
11551ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      break;
11552ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
11553ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   case 0x342: // vminsh (Minimum Signed Half Word, AV p189)
11554ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      DIP("vminsh v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
11555ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      putVReg( vD_addr, binop(Iop_Min16Sx8, mkexpr(vA), mkexpr(vB)) );
11556ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      break;
11557ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
11558ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   case 0x382: // vminsw (Minimum Signed Word, AV p190)
11559ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      DIP("vminsw v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
11560ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      putVReg( vD_addr, binop(Iop_Min32Sx4, mkexpr(vA), mkexpr(vB)) );
11561ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      break;
11562ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
11563ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
11564ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* Average */
11565ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   case 0x402: // vavgub (Average Unsigned Byte, AV p152)
11566ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      DIP("vavgub v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
11567ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      putVReg( vD_addr, binop(Iop_Avg8Ux16, mkexpr(vA), mkexpr(vB)) );
11568ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      break;
11569ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
11570ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   case 0x442: // vavguh (Average Unsigned Half Word, AV p153)
11571ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      DIP("vavguh v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
11572ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      putVReg( vD_addr, binop(Iop_Avg16Ux8, mkexpr(vA), mkexpr(vB)) );
11573ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      break;
11574ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
11575ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   case 0x482: // vavguw (Average Unsigned Word, AV p154)
11576ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      DIP("vavguw v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
11577ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      putVReg( vD_addr, binop(Iop_Avg32Ux4, mkexpr(vA), mkexpr(vB)) );
11578ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      break;
11579ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
11580ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   case 0x502: // vavgsb (Average Signed Byte, AV p149)
11581ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      DIP("vavgsb v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
11582ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      putVReg( vD_addr, binop(Iop_Avg8Sx16, mkexpr(vA), mkexpr(vB)) );
11583ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      break;
11584ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
11585ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   case 0x542: // vavgsh (Average Signed Half Word, AV p150)
11586ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      DIP("vavgsh v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
11587ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      putVReg( vD_addr, binop(Iop_Avg16Sx8, mkexpr(vA), mkexpr(vB)) );
11588ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      break;
11589ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
11590ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   case 0x582: // vavgsw (Average Signed Word, AV p151)
11591ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      DIP("vavgsw v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
11592ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      putVReg( vD_addr, binop(Iop_Avg32Sx4, mkexpr(vA), mkexpr(vB)) );
11593ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      break;
11594ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
11595ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
11596ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* Multiply */
11597ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   case 0x008: // vmuloub (Multiply Odd Unsigned Byte, AV p213)
11598ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      DIP("vmuloub v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
11599ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      putVReg( vD_addr,
11600ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               binop(Iop_MullEven8Ux16, mkexpr(vA), mkexpr(vB)));
11601ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      break;
11602ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
11603ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   case 0x048: // vmulouh (Multiply Odd Unsigned Half Word, AV p214)
11604ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      DIP("vmulouh v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
11605ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      putVReg( vD_addr,
11606ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               binop(Iop_MullEven16Ux8, mkexpr(vA), mkexpr(vB)));
11607ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      break;
11608ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
11609ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   case 0x108: // vmulosb (Multiply Odd Signed Byte, AV p211)
11610ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      DIP("vmulosb v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
11611ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      putVReg( vD_addr,
11612ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               binop(Iop_MullEven8Sx16, mkexpr(vA), mkexpr(vB)));
11613ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      break;
11614ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
11615ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   case 0x148: // vmulosh (Multiply Odd Signed Half Word, AV p212)
11616ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      DIP("vmulosh v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
11617ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      putVReg( vD_addr,
11618ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               binop(Iop_MullEven16Sx8, mkexpr(vA), mkexpr(vB)));
11619ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      break;
11620ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
11621ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   case 0x208: // vmuleub (Multiply Even Unsigned Byte, AV p209)
11622ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      DIP("vmuleub v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
11623ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      putVReg( vD_addr, MK_Iop_MullOdd8Ux16( mkexpr(vA), mkexpr(vB) ));
11624ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      break;
11625ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
11626ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   case 0x248: // vmuleuh (Multiply Even Unsigned Half Word, AV p210)
11627ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      DIP("vmuleuh v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
11628ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      putVReg( vD_addr, MK_Iop_MullOdd16Ux8( mkexpr(vA), mkexpr(vB) ));
11629ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      break;
11630ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
11631ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   case 0x308: // vmulesb (Multiply Even Signed Byte, AV p207)
11632ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      DIP("vmulesb v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
11633ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      putVReg( vD_addr, MK_Iop_MullOdd8Sx16( mkexpr(vA), mkexpr(vB) ));
11634ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      break;
11635ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
11636ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   case 0x348: // vmulesh (Multiply Even Signed Half Word, AV p208)
11637ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      DIP("vmulesh v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
11638ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      putVReg( vD_addr, MK_Iop_MullOdd16Sx8( mkexpr(vA), mkexpr(vB) ));
11639ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      break;
11640ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
11641ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
11642ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* Sum Across Partial */
11643ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   case 0x608: { // vsum4ubs (Sum Partial (1/4) UB Saturate, AV p275)
11644ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      IRTemp aEE, aEO, aOE, aOO;
11645ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      aEE = aEO = aOE = aOO = IRTemp_INVALID;
11646ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      DIP("vsum4ubs v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
11647ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
11648ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* vA: V128_8Ux16 -> 4 x V128_32Ux4, sign-extended */
11649ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      expand8Ux16( mkexpr(vA), &aEvn, &aOdd ); // (15,13...),(14,12...)
11650ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      expand16Ux8( mkexpr(aEvn), &aEE, &aEO ); // (15,11...),(13, 9...)
11651ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      expand16Ux8( mkexpr(aOdd), &aOE, &aOO ); // (14,10...),(12, 8...)
11652ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
11653ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* break V128 to 4xI32's, zero-extending to I64's */
11654ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      breakV128to4x64U( mkexpr(aEE), &a15, &a11, &a7, &a3 );
11655ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      breakV128to4x64U( mkexpr(aOE), &a14, &a10, &a6, &a2 );
11656ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      breakV128to4x64U( mkexpr(aEO), &a13, &a9,  &a5, &a1 );
11657ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      breakV128to4x64U( mkexpr(aOO), &a12, &a8,  &a4, &a0 );
11658ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      breakV128to4x64U( mkexpr(vB),  &b3,  &b2,  &b1, &b0 );
11659ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
11660ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* add lanes */
11661ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      assign( z3, binop(Iop_Add64, mkexpr(b3),
11662ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                     binop(Iop_Add64,
11663ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                        binop(Iop_Add64, mkexpr(a15), mkexpr(a14)),
11664ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                        binop(Iop_Add64, mkexpr(a13), mkexpr(a12)))) );
11665ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      assign( z2, binop(Iop_Add64, mkexpr(b2),
11666ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                     binop(Iop_Add64,
11667ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                         binop(Iop_Add64, mkexpr(a11), mkexpr(a10)),
11668ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                         binop(Iop_Add64, mkexpr(a9), mkexpr(a8)))) );
11669ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      assign( z1, binop(Iop_Add64, mkexpr(b1),
11670ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                     binop(Iop_Add64,
11671ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                         binop(Iop_Add64, mkexpr(a7), mkexpr(a6)),
11672ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                         binop(Iop_Add64, mkexpr(a5), mkexpr(a4)))) );
11673ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      assign( z0, binop(Iop_Add64, mkexpr(b0),
11674ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                     binop(Iop_Add64,
11675ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                         binop(Iop_Add64, mkexpr(a3), mkexpr(a2)),
11676ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                         binop(Iop_Add64, mkexpr(a1), mkexpr(a0)))) );
11677ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
11678ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* saturate-narrow to 32bit, and combine to V128 */
11679ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      putVReg( vD_addr, mkV128from4x64U( mkexpr(z3), mkexpr(z2),
11680ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                         mkexpr(z1), mkexpr(z0)) );
11681ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      break;
11682ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
11683ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   case 0x708: { // vsum4sbs (Sum Partial (1/4) SB Saturate, AV p273)
11684ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      IRTemp aEE, aEO, aOE, aOO;
11685ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      aEE = aEO = aOE = aOO = IRTemp_INVALID;
11686ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      DIP("vsum4sbs v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
11687ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
11688ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* vA: V128_8Sx16 -> 4 x V128_32Sx4, sign-extended */
11689ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      expand8Sx16( mkexpr(vA), &aEvn, &aOdd ); // (15,13...),(14,12...)
11690ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      expand16Sx8( mkexpr(aEvn), &aEE, &aEO ); // (15,11...),(13, 9...)
11691ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      expand16Sx8( mkexpr(aOdd), &aOE, &aOO ); // (14,10...),(12, 8...)
11692ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
11693ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* break V128 to 4xI32's, sign-extending to I64's */
11694ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      breakV128to4x64S( mkexpr(aEE), &a15, &a11, &a7, &a3 );
11695ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      breakV128to4x64S( mkexpr(aOE), &a14, &a10, &a6, &a2 );
11696ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      breakV128to4x64S( mkexpr(aEO), &a13, &a9,  &a5, &a1 );
11697ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      breakV128to4x64S( mkexpr(aOO), &a12, &a8,  &a4, &a0 );
11698ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      breakV128to4x64S( mkexpr(vB),  &b3,  &b2,  &b1, &b0 );
11699ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
11700ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* add lanes */
11701ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      assign( z3, binop(Iop_Add64, mkexpr(b3),
11702ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                     binop(Iop_Add64,
11703ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                        binop(Iop_Add64, mkexpr(a15), mkexpr(a14)),
11704ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                        binop(Iop_Add64, mkexpr(a13), mkexpr(a12)))) );
11705ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      assign( z2, binop(Iop_Add64, mkexpr(b2),
11706ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                     binop(Iop_Add64,
11707ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                        binop(Iop_Add64, mkexpr(a11), mkexpr(a10)),
11708ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                        binop(Iop_Add64, mkexpr(a9), mkexpr(a8)))) );
11709ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      assign( z1, binop(Iop_Add64, mkexpr(b1),
11710ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                     binop(Iop_Add64,
11711ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                        binop(Iop_Add64, mkexpr(a7), mkexpr(a6)),
11712ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                        binop(Iop_Add64, mkexpr(a5), mkexpr(a4)))) );
11713ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      assign( z0, binop(Iop_Add64, mkexpr(b0),
11714ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                     binop(Iop_Add64,
11715ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                        binop(Iop_Add64, mkexpr(a3), mkexpr(a2)),
11716ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                        binop(Iop_Add64, mkexpr(a1), mkexpr(a0)))) );
11717ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
11718ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* saturate-narrow to 32bit, and combine to V128 */
11719ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      putVReg( vD_addr, mkV128from4x64S( mkexpr(z3), mkexpr(z2),
11720ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                         mkexpr(z1), mkexpr(z0)) );
11721ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      break;
11722ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
11723ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   case 0x648: { // vsum4shs (Sum Partial (1/4) SHW Saturate, AV p274)
11724ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      DIP("vsum4shs v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
11725ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
11726ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* vA: V128_16Sx8 -> 2 x V128_32Sx4, sign-extended */
11727ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      expand16Sx8( mkexpr(vA), &aEvn, &aOdd ); // (7,5...),(6,4...)
11728ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
11729ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* break V128 to 4xI32's, sign-extending to I64's */
11730ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      breakV128to4x64S( mkexpr(aEvn), &a7, &a5, &a3, &a1 );
11731ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      breakV128to4x64S( mkexpr(aOdd), &a6, &a4, &a2, &a0 );
11732ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      breakV128to4x64S( mkexpr(vB),   &b3, &b2, &b1, &b0 );
11733ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
11734ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* add lanes */
11735ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      assign( z3, binop(Iop_Add64, mkexpr(b3),
11736ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                        binop(Iop_Add64, mkexpr(a7), mkexpr(a6))));
11737ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      assign( z2, binop(Iop_Add64, mkexpr(b2),
11738ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                        binop(Iop_Add64, mkexpr(a5), mkexpr(a4))));
11739ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      assign( z1, binop(Iop_Add64, mkexpr(b1),
11740ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                        binop(Iop_Add64, mkexpr(a3), mkexpr(a2))));
11741ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      assign( z0, binop(Iop_Add64, mkexpr(b0),
11742ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                        binop(Iop_Add64, mkexpr(a1), mkexpr(a0))));
11743ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
11744ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* saturate-narrow to 32bit, and combine to V128 */
11745ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      putVReg( vD_addr, mkV128from4x64S( mkexpr(z3), mkexpr(z2),
11746ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                         mkexpr(z1), mkexpr(z0)) );
11747ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      break;
11748ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
11749ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   case 0x688: { // vsum2sws (Sum Partial (1/2) SW Saturate, AV p272)
11750ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      DIP("vsum2sws v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
11751ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
11752ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* break V128 to 4xI32's, sign-extending to I64's */
11753ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      breakV128to4x64S( mkexpr(vA), &a3, &a2, &a1, &a0 );
11754ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      breakV128to4x64S( mkexpr(vB), &b3, &b2, &b1, &b0 );
11755ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
11756ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* add lanes */
11757ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      assign( z2, binop(Iop_Add64, mkexpr(b2),
11758ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                        binop(Iop_Add64, mkexpr(a3), mkexpr(a2))) );
11759ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      assign( z0, binop(Iop_Add64, mkexpr(b0),
11760ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                        binop(Iop_Add64, mkexpr(a1), mkexpr(a0))) );
11761ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
11762ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* saturate-narrow to 32bit, and combine to V128 */
11763ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      putVReg( vD_addr, mkV128from4x64S( mkU64(0), mkexpr(z2),
11764ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                         mkU64(0), mkexpr(z0)) );
11765ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      break;
11766ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
11767ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   case 0x788: { // vsumsws  (Sum SW Saturate, AV p271)
11768ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      DIP("vsumsws v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
11769ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
11770ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* break V128 to 4xI32's, sign-extending to I64's */
11771ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      breakV128to4x64S( mkexpr(vA), &a3, &a2, &a1, &a0 );
11772ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      breakV128to4x64S( mkexpr(vB), &b3, &b2, &b1, &b0 );
11773ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
11774ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* add lanes */
11775ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      assign( z0, binop(Iop_Add64, mkexpr(b0),
11776ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                     binop(Iop_Add64,
11777ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                        binop(Iop_Add64, mkexpr(a3), mkexpr(a2)),
11778ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                        binop(Iop_Add64, mkexpr(a1), mkexpr(a0)))) );
11779ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
11780ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* saturate-narrow to 32bit, and combine to V128 */
11781ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      putVReg( vD_addr, mkV128from4x64S( mkU64(0), mkU64(0),
11782ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                         mkU64(0), mkexpr(z0)) );
11783ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      break;
11784ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
11785ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   default:
11786ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      vex_printf("dis_av_arith(ppc)(opc2=0x%x)\n", opc2);
11787ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      return False;
11788ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
11789ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   return True;
11790ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
11791ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
11792ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*
11793ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  AltiVec Logic Instructions
11794ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown*/
11795ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic Bool dis_av_logic ( UInt theInstr )
11796ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
11797ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* VX-Form */
11798ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   UChar opc1    = ifieldOPC(theInstr);
11799ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   UChar vD_addr = ifieldRegDS(theInstr);
11800ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   UChar vA_addr = ifieldRegA(theInstr);
11801ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   UChar vB_addr = ifieldRegB(theInstr);
11802ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   UInt  opc2    = IFIELD( theInstr, 0, 11 );
11803ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
11804ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   IRTemp vA = newTemp(Ity_V128);
11805ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   IRTemp vB = newTemp(Ity_V128);
11806ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   assign( vA, getVReg(vA_addr));
11807ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   assign( vB, getVReg(vB_addr));
11808ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
11809ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (opc1 != 0x4) {
11810ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      vex_printf("dis_av_logic(ppc)(opc1 != 0x4)\n");
11811ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      return False;
11812ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
11813ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
11814ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   switch (opc2) {
11815ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   case 0x404: // vand (And, AV p147)
11816ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      DIP("vand v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
11817ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      putVReg( vD_addr, binop(Iop_AndV128, mkexpr(vA), mkexpr(vB)) );
11818ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      break;
11819ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
11820ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   case 0x444: // vandc (And, AV p148)
11821ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      DIP("vandc v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
11822ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      putVReg( vD_addr, binop(Iop_AndV128, mkexpr(vA),
11823ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                              unop(Iop_NotV128, mkexpr(vB))) );
11824ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      break;
11825ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
11826ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   case 0x484: // vor (Or, AV p217)
11827ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      DIP("vor v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
11828ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      putVReg( vD_addr, binop(Iop_OrV128, mkexpr(vA), mkexpr(vB)) );
11829ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      break;
11830ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
11831ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   case 0x4C4: // vxor (Xor, AV p282)
11832ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      DIP("vxor v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
11833ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      putVReg( vD_addr, binop(Iop_XorV128, mkexpr(vA), mkexpr(vB)) );
11834ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      break;
11835ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
11836ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   case 0x504: // vnor (Nor, AV p216)
11837ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      DIP("vnor v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
11838ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      putVReg( vD_addr,
11839ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         unop(Iop_NotV128, binop(Iop_OrV128, mkexpr(vA), mkexpr(vB))) );
11840ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      break;
11841ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
11842ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   default:
11843ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      vex_printf("dis_av_logic(ppc)(opc2=0x%x)\n", opc2);
11844ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      return False;
11845ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
11846ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   return True;
11847ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
11848ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
11849ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*
11850ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  AltiVec Compare Instructions
11851ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown*/
11852ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic Bool dis_av_cmp ( UInt theInstr )
11853ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
11854ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* VXR-Form */
11855ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   UChar opc1     = ifieldOPC(theInstr);
11856ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   UChar vD_addr  = ifieldRegDS(theInstr);
11857ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   UChar vA_addr  = ifieldRegA(theInstr);
11858ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   UChar vB_addr  = ifieldRegB(theInstr);
11859ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   UChar flag_rC  = ifieldBIT10(theInstr);
11860ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   UInt  opc2     = IFIELD( theInstr, 0, 10 );
11861ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
11862ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   IRTemp vA = newTemp(Ity_V128);
11863ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   IRTemp vB = newTemp(Ity_V128);
11864ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   IRTemp vD = newTemp(Ity_V128);
11865ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   assign( vA, getVReg(vA_addr));
11866ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   assign( vB, getVReg(vB_addr));
11867ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
11868ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (opc1 != 0x4) {
11869ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      vex_printf("dis_av_cmp(ppc)(instr)\n");
11870ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      return False;
11871ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
11872ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
11873ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   switch (opc2) {
11874ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   case 0x006: // vcmpequb (Compare Equal-to Unsigned B, AV p160)
11875ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      DIP("vcmpequb%s v%d,v%d,v%d\n", (flag_rC ? ".":""),
11876ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                      vD_addr, vA_addr, vB_addr);
11877ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      assign( vD, binop(Iop_CmpEQ8x16, mkexpr(vA), mkexpr(vB)) );
11878ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      break;
11879ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
11880ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   case 0x046: // vcmpequh (Compare Equal-to Unsigned HW, AV p161)
11881ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      DIP("vcmpequh%s v%d,v%d,v%d\n", (flag_rC ? ".":""),
11882ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                      vD_addr, vA_addr, vB_addr);
11883ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      assign( vD, binop(Iop_CmpEQ16x8, mkexpr(vA), mkexpr(vB)) );
11884ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      break;
11885ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
11886ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   case 0x086: // vcmpequw (Compare Equal-to Unsigned W, AV p162)
11887ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      DIP("vcmpequw%s v%d,v%d,v%d\n", (flag_rC ? ".":""),
11888ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                      vD_addr, vA_addr, vB_addr);
11889ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      assign( vD, binop(Iop_CmpEQ32x4, mkexpr(vA), mkexpr(vB)) );
11890ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      break;
11891ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
11892ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   case 0x206: // vcmpgtub (Compare Greater-than Unsigned B, AV p168)
11893ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      DIP("vcmpgtub%s v%d,v%d,v%d\n", (flag_rC ? ".":""),
11894ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                      vD_addr, vA_addr, vB_addr);
11895ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      assign( vD, binop(Iop_CmpGT8Ux16, mkexpr(vA), mkexpr(vB)) );
11896ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      break;
11897ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
11898ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   case 0x246: // vcmpgtuh (Compare Greater-than Unsigned HW, AV p169)
11899ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      DIP("vcmpgtuh%s v%d,v%d,v%d\n", (flag_rC ? ".":""),
11900ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                      vD_addr, vA_addr, vB_addr);
11901ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      assign( vD, binop(Iop_CmpGT16Ux8, mkexpr(vA), mkexpr(vB)) );
11902ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      break;
11903ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
11904ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   case 0x286: // vcmpgtuw (Compare Greater-than Unsigned W, AV p170)
11905ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      DIP("vcmpgtuw%s v%d,v%d,v%d\n", (flag_rC ? ".":""),
11906ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                       vD_addr, vA_addr, vB_addr);
11907ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      assign( vD, binop(Iop_CmpGT32Ux4, mkexpr(vA), mkexpr(vB)) );
11908ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      break;
11909ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
11910ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   case 0x306: // vcmpgtsb (Compare Greater-than Signed B, AV p165)
11911ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      DIP("vcmpgtsb%s v%d,v%d,v%d\n", (flag_rC ? ".":""),
11912ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                       vD_addr, vA_addr, vB_addr);
11913ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      assign( vD, binop(Iop_CmpGT8Sx16, mkexpr(vA), mkexpr(vB)) );
11914ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      break;
11915ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
11916ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   case 0x346: // vcmpgtsh (Compare Greater-than Signed HW, AV p166)
11917ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      DIP("vcmpgtsh%s v%d,v%d,v%d\n", (flag_rC ? ".":""),
11918ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                      vD_addr, vA_addr, vB_addr);
11919ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      assign( vD, binop(Iop_CmpGT16Sx8, mkexpr(vA), mkexpr(vB)) );
11920ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      break;
11921ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
11922ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   case 0x386: // vcmpgtsw (Compare Greater-than Signed W, AV p167)
11923ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      DIP("vcmpgtsw%s v%d,v%d,v%d\n", (flag_rC ? ".":""),
11924ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                      vD_addr, vA_addr, vB_addr);
11925ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      assign( vD, binop(Iop_CmpGT32Sx4, mkexpr(vA), mkexpr(vB)) );
11926ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      break;
11927ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
11928ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   default:
11929ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      vex_printf("dis_av_cmp(ppc)(opc2)\n");
11930ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      return False;
11931ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
11932ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
11933ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   putVReg( vD_addr, mkexpr(vD) );
11934ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
11935ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (flag_rC) {
11936ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      set_AV_CR6( mkexpr(vD), True );
11937ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
11938ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   return True;
11939ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
11940ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
11941ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*
11942ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  AltiVec Multiply-Sum Instructions
11943ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown*/
11944ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic Bool dis_av_multarith ( UInt theInstr )
11945ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
11946ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* VA-Form */
11947ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   UChar opc1     = ifieldOPC(theInstr);
11948ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   UChar vD_addr  = ifieldRegDS(theInstr);
11949ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   UChar vA_addr  = ifieldRegA(theInstr);
11950ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   UChar vB_addr  = ifieldRegB(theInstr);
11951ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   UChar vC_addr  = ifieldRegC(theInstr);
11952ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   UChar opc2     = toUChar( IFIELD( theInstr, 0, 6 ) );
11953ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
11954ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   IRTemp vA    = newTemp(Ity_V128);
11955ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   IRTemp vB    = newTemp(Ity_V128);
11956ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   IRTemp vC    = newTemp(Ity_V128);
11957ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   IRTemp zeros = newTemp(Ity_V128);
11958ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   IRTemp aLo   = newTemp(Ity_V128);
11959ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   IRTemp bLo   = newTemp(Ity_V128);
11960ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   IRTemp cLo   = newTemp(Ity_V128);
11961ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   IRTemp zLo   = newTemp(Ity_V128);
11962ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   IRTemp aHi   = newTemp(Ity_V128);
11963ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   IRTemp bHi   = newTemp(Ity_V128);
11964ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   IRTemp cHi   = newTemp(Ity_V128);
11965ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   IRTemp zHi   = newTemp(Ity_V128);
11966ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   IRTemp abEvn = newTemp(Ity_V128);
11967ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   IRTemp abOdd = newTemp(Ity_V128);
11968ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   IRTemp z3    = newTemp(Ity_I64);
11969ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   IRTemp z2    = newTemp(Ity_I64);
11970ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   IRTemp z1    = newTemp(Ity_I64);
11971ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   IRTemp z0    = newTemp(Ity_I64);
11972ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   IRTemp ab7, ab6, ab5, ab4, ab3, ab2, ab1, ab0;
11973ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   IRTemp c3, c2, c1, c0;
11974ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
11975ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   ab7 = ab6 = ab5 = ab4 = ab3 = ab2 = ab1 = ab0 = IRTemp_INVALID;
11976ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   c3 = c2 = c1 = c0 = IRTemp_INVALID;
11977ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
11978ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   assign( vA, getVReg(vA_addr));
11979ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   assign( vB, getVReg(vB_addr));
11980ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   assign( vC, getVReg(vC_addr));
11981ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   assign( zeros, unop(Iop_Dup32x4, mkU32(0)) );
11982ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
11983ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (opc1 != 0x4) {
11984ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      vex_printf("dis_av_multarith(ppc)(instr)\n");
11985ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      return False;
11986ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
11987ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
11988ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   switch (opc2) {
11989ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* Multiply-Add */
11990ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   case 0x20: { // vmhaddshs (Mult Hi, Add Signed HW Saturate, AV p185)
11991ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      IRTemp cSigns = newTemp(Ity_V128);
11992ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      DIP("vmhaddshs v%d,v%d,v%d,v%d\n",
11993ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown          vD_addr, vA_addr, vB_addr, vC_addr);
11994ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      assign(cSigns, binop(Iop_CmpGT16Sx8, mkexpr(zeros), mkexpr(vC)));
11995ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      assign(aLo, binop(Iop_InterleaveLO16x8, mkexpr(zeros), mkexpr(vA)));
11996ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      assign(bLo, binop(Iop_InterleaveLO16x8, mkexpr(zeros), mkexpr(vB)));
11997ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      assign(cLo, binop(Iop_InterleaveLO16x8, mkexpr(cSigns),mkexpr(vC)));
11998ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      assign(aHi, binop(Iop_InterleaveHI16x8, mkexpr(zeros), mkexpr(vA)));
11999ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      assign(bHi, binop(Iop_InterleaveHI16x8, mkexpr(zeros), mkexpr(vB)));
12000ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      assign(cHi, binop(Iop_InterleaveHI16x8, mkexpr(cSigns),mkexpr(vC)));
12001ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
12002ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      assign( zLo, binop(Iop_Add32x4, mkexpr(cLo),
12003ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                         binop(Iop_SarN32x4,
12004ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                               binop(Iop_MullEven16Sx8,
12005ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                     mkexpr(aLo), mkexpr(bLo)),
12006ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                               mkU8(15))) );
12007ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
12008ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      assign( zHi, binop(Iop_Add32x4, mkexpr(cHi),
12009ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                         binop(Iop_SarN32x4,
12010ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                               binop(Iop_MullEven16Sx8,
12011ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                     mkexpr(aHi), mkexpr(bHi)),
12012ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                               mkU8(15))) );
12013ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
12014ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      putVReg( vD_addr,
12015b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov               binop(Iop_QNarrowBin32Sto16Sx8, mkexpr(zHi), mkexpr(zLo)) );
12016ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      break;
12017ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
12018ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   case 0x21: { // vmhraddshs (Mult High Round, Add Signed HW Saturate, AV p186)
12019ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      IRTemp zKonst = newTemp(Ity_V128);
12020ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      IRTemp cSigns = newTemp(Ity_V128);
12021ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      DIP("vmhraddshs v%d,v%d,v%d,v%d\n",
12022ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown          vD_addr, vA_addr, vB_addr, vC_addr);
12023ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      assign(cSigns, binop(Iop_CmpGT16Sx8, mkexpr(zeros), mkexpr(vC)) );
12024ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      assign(aLo, binop(Iop_InterleaveLO16x8, mkexpr(zeros), mkexpr(vA)));
12025ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      assign(bLo, binop(Iop_InterleaveLO16x8, mkexpr(zeros), mkexpr(vB)));
12026ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      assign(cLo, binop(Iop_InterleaveLO16x8, mkexpr(cSigns),mkexpr(vC)));
12027ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      assign(aHi, binop(Iop_InterleaveHI16x8, mkexpr(zeros), mkexpr(vA)));
12028ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      assign(bHi, binop(Iop_InterleaveHI16x8, mkexpr(zeros), mkexpr(vB)));
12029ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      assign(cHi, binop(Iop_InterleaveHI16x8, mkexpr(cSigns),mkexpr(vC)));
12030ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
12031ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* shifting our const avoids store/load version of Dup */
12032ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      assign( zKonst, binop(Iop_ShlN32x4, unop(Iop_Dup32x4, mkU32(0x1)),
12033ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                            mkU8(14)) );
12034ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
12035ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      assign( zLo, binop(Iop_Add32x4, mkexpr(cLo),
12036ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                         binop(Iop_SarN32x4,
12037ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                               binop(Iop_Add32x4, mkexpr(zKonst),
12038ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                     binop(Iop_MullEven16Sx8,
12039ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                           mkexpr(aLo), mkexpr(bLo))),
12040ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                               mkU8(15))) );
12041ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
12042ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      assign( zHi, binop(Iop_Add32x4, mkexpr(cHi),
12043ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                         binop(Iop_SarN32x4,
12044ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                               binop(Iop_Add32x4, mkexpr(zKonst),
12045ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                     binop(Iop_MullEven16Sx8,
12046ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                           mkexpr(aHi), mkexpr(bHi))),
12047ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                               mkU8(15))) );
12048ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
12049b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      putVReg( vD_addr,
12050b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov               binop(Iop_QNarrowBin32Sto16Sx8, mkexpr(zHi), mkexpr(zLo)) );
12051ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      break;
12052ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
12053ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   case 0x22: { // vmladduhm (Mult Low, Add Unsigned HW Modulo, AV p194)
12054ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      DIP("vmladduhm v%d,v%d,v%d,v%d\n",
12055ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown          vD_addr, vA_addr, vB_addr, vC_addr);
12056ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      assign(aLo, binop(Iop_InterleaveLO16x8, mkexpr(zeros), mkexpr(vA)));
12057ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      assign(bLo, binop(Iop_InterleaveLO16x8, mkexpr(zeros), mkexpr(vB)));
12058ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      assign(cLo, binop(Iop_InterleaveLO16x8, mkexpr(zeros), mkexpr(vC)));
12059ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      assign(aHi, binop(Iop_InterleaveHI16x8, mkexpr(zeros), mkexpr(vA)));
12060ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      assign(bHi, binop(Iop_InterleaveHI16x8, mkexpr(zeros), mkexpr(vB)));
12061ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      assign(cHi, binop(Iop_InterleaveHI16x8, mkexpr(zeros), mkexpr(vC)));
12062ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      assign(zLo, binop(Iop_Add32x4,
12063ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                     binop(Iop_MullEven16Ux8, mkexpr(aLo), mkexpr(bLo)),
12064ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                     mkexpr(cLo)) );
12065ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      assign(zHi, binop(Iop_Add32x4,
12066ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                     binop(Iop_MullEven16Ux8, mkexpr(aHi), mkexpr(bHi)),
12067ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                     mkexpr(cHi)));
12068b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      putVReg( vD_addr,
12069b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov               binop(Iop_NarrowBin32to16x8, mkexpr(zHi), mkexpr(zLo)) );
12070ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      break;
12071ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
12072ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
12073ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
12074ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* Multiply-Sum */
12075ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   case 0x24: { // vmsumubm (Multiply Sum Unsigned B Modulo, AV p204)
12076ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      IRTemp abEE, abEO, abOE, abOO;
12077ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      abEE = abEO = abOE = abOO = IRTemp_INVALID;
12078ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      DIP("vmsumubm v%d,v%d,v%d,v%d\n",
12079ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown          vD_addr, vA_addr, vB_addr, vC_addr);
12080ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
12081ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* multiply vA,vB (unsigned, widening) */
12082ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      assign( abEvn, MK_Iop_MullOdd8Ux16( mkexpr(vA), mkexpr(vB) ));
12083ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      assign( abOdd, binop(Iop_MullEven8Ux16, mkexpr(vA), mkexpr(vB)) );
12084ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
12085ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* evn,odd: V128_16Ux8 -> 2 x V128_32Ux4, zero-extended */
12086ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      expand16Ux8( mkexpr(abEvn), &abEE, &abEO );
12087ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      expand16Ux8( mkexpr(abOdd), &abOE, &abOO );
12088ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
12089ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      putVReg( vD_addr,
12090ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         binop(Iop_Add32x4, mkexpr(vC),
12091ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               binop(Iop_Add32x4,
12092ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                     binop(Iop_Add32x4, mkexpr(abEE), mkexpr(abEO)),
12093ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                     binop(Iop_Add32x4, mkexpr(abOE), mkexpr(abOO)))) );
12094ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      break;
12095ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
12096ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   case 0x25: { // vmsummbm (Multiply Sum Mixed-Sign B Modulo, AV p201)
12097ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      IRTemp aEvn, aOdd, bEvn, bOdd;
12098ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      IRTemp abEE = newTemp(Ity_V128);
12099ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      IRTemp abEO = newTemp(Ity_V128);
12100ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      IRTemp abOE = newTemp(Ity_V128);
12101ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      IRTemp abOO = newTemp(Ity_V128);
12102ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      aEvn = aOdd = bEvn = bOdd = IRTemp_INVALID;
12103ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      DIP("vmsummbm v%d,v%d,v%d,v%d\n",
12104ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown          vD_addr, vA_addr, vB_addr, vC_addr);
12105ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
12106ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* sign-extend vA, zero-extend vB, for mixed-sign multiply
12107ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         (separating out adjacent lanes to different vectors) */
12108ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      expand8Sx16( mkexpr(vA), &aEvn, &aOdd );
12109ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      expand8Ux16( mkexpr(vB), &bEvn, &bOdd );
12110ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
12111ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* multiply vA, vB, again separating adjacent lanes */
12112ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      assign( abEE, MK_Iop_MullOdd16Sx8( mkexpr(aEvn), mkexpr(bEvn) ));
12113ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      assign( abEO, binop(Iop_MullEven16Sx8, mkexpr(aEvn), mkexpr(bEvn)) );
12114ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      assign( abOE, MK_Iop_MullOdd16Sx8( mkexpr(aOdd), mkexpr(bOdd) ));
12115ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      assign( abOO, binop(Iop_MullEven16Sx8, mkexpr(aOdd), mkexpr(bOdd)) );
12116ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
12117ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* add results together, + vC */
12118ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      putVReg( vD_addr,
12119ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         binop(Iop_QAdd32Sx4, mkexpr(vC),
12120ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               binop(Iop_QAdd32Sx4,
12121ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                     binop(Iop_QAdd32Sx4, mkexpr(abEE), mkexpr(abEO)),
12122ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                     binop(Iop_QAdd32Sx4, mkexpr(abOE), mkexpr(abOO)))) );
12123ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      break;
12124ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
12125ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   case 0x26: { // vmsumuhm (Multiply Sum Unsigned HW Modulo, AV p205)
12126ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      DIP("vmsumuhm v%d,v%d,v%d,v%d\n",
12127ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown          vD_addr, vA_addr, vB_addr, vC_addr);
12128ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      assign( abEvn, MK_Iop_MullOdd16Ux8( mkexpr(vA), mkexpr(vB) ));
12129ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      assign( abOdd, binop(Iop_MullEven16Ux8, mkexpr(vA), mkexpr(vB)) );
12130ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      putVReg( vD_addr,
12131ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         binop(Iop_Add32x4, mkexpr(vC),
12132ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               binop(Iop_Add32x4, mkexpr(abEvn), mkexpr(abOdd))) );
12133ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      break;
12134ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
12135ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   case 0x27: { // vmsumuhs (Multiply Sum Unsigned HW Saturate, AV p206)
12136ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      DIP("vmsumuhs v%d,v%d,v%d,v%d\n",
12137ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown          vD_addr, vA_addr, vB_addr, vC_addr);
12138ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* widening multiply, separating lanes */
12139ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      assign( abEvn, MK_Iop_MullOdd16Ux8(mkexpr(vA), mkexpr(vB) ));
12140ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      assign( abOdd, binop(Iop_MullEven16Ux8, mkexpr(vA), mkexpr(vB)) );
12141ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
12142ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* break V128 to 4xI32's, zero-extending to I64's */
12143ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      breakV128to4x64U( mkexpr(abEvn), &ab7, &ab5, &ab3, &ab1 );
12144ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      breakV128to4x64U( mkexpr(abOdd), &ab6, &ab4, &ab2, &ab0 );
12145ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      breakV128to4x64U( mkexpr(vC),    &c3,  &c2,  &c1,  &c0  );
12146ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
12147ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* add lanes */
12148ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      assign( z3, binop(Iop_Add64, mkexpr(c3),
12149ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                        binop(Iop_Add64, mkexpr(ab7), mkexpr(ab6))));
12150ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      assign( z2, binop(Iop_Add64, mkexpr(c2),
12151ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                        binop(Iop_Add64, mkexpr(ab5), mkexpr(ab4))));
12152ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      assign( z1, binop(Iop_Add64, mkexpr(c1),
12153ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                        binop(Iop_Add64, mkexpr(ab3), mkexpr(ab2))));
12154ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      assign( z0, binop(Iop_Add64, mkexpr(c0),
12155ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                        binop(Iop_Add64, mkexpr(ab1), mkexpr(ab0))));
12156ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
12157ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* saturate-narrow to 32bit, and combine to V128 */
12158ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      putVReg( vD_addr, mkV128from4x64U( mkexpr(z3), mkexpr(z2),
12159ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                         mkexpr(z1), mkexpr(z0)) );
12160ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
12161ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      break;
12162ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
12163ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   case 0x28: { // vmsumshm (Multiply Sum Signed HW Modulo, AV p202)
12164ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      DIP("vmsumshm v%d,v%d,v%d,v%d\n",
12165ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown          vD_addr, vA_addr, vB_addr, vC_addr);
12166ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      assign( abEvn, MK_Iop_MullOdd16Sx8( mkexpr(vA), mkexpr(vB) ));
12167ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      assign( abOdd, binop(Iop_MullEven16Sx8, mkexpr(vA), mkexpr(vB)) );
12168ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      putVReg( vD_addr,
12169ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         binop(Iop_Add32x4, mkexpr(vC),
12170ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               binop(Iop_Add32x4, mkexpr(abOdd), mkexpr(abEvn))) );
12171ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      break;
12172ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
12173ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   case 0x29: { // vmsumshs (Multiply Sum Signed HW Saturate, AV p203)
12174ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      DIP("vmsumshs v%d,v%d,v%d,v%d\n",
12175ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown          vD_addr, vA_addr, vB_addr, vC_addr);
12176ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* widening multiply, separating lanes */
12177ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      assign( abEvn, MK_Iop_MullOdd16Sx8( mkexpr(vA), mkexpr(vB) ));
12178ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      assign( abOdd, binop(Iop_MullEven16Sx8, mkexpr(vA), mkexpr(vB)) );
12179ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
12180ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* break V128 to 4xI32's, sign-extending to I64's */
12181ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      breakV128to4x64S( mkexpr(abEvn), &ab7, &ab5, &ab3, &ab1 );
12182ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      breakV128to4x64S( mkexpr(abOdd), &ab6, &ab4, &ab2, &ab0 );
12183ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      breakV128to4x64S( mkexpr(vC),    &c3,  &c2,  &c1,  &c0  );
12184ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
12185ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* add lanes */
12186ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      assign( z3, binop(Iop_Add64, mkexpr(c3),
12187ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                        binop(Iop_Add64, mkexpr(ab7), mkexpr(ab6))));
12188ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      assign( z2, binop(Iop_Add64, mkexpr(c2),
12189ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                        binop(Iop_Add64, mkexpr(ab5), mkexpr(ab4))));
12190ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      assign( z1, binop(Iop_Add64, mkexpr(c1),
12191ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                        binop(Iop_Add64, mkexpr(ab3), mkexpr(ab2))));
12192ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      assign( z0, binop(Iop_Add64, mkexpr(c0),
12193ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                        binop(Iop_Add64, mkexpr(ab1), mkexpr(ab0))));
12194ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
12195ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* saturate-narrow to 32bit, and combine to V128 */
12196ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      putVReg( vD_addr, mkV128from4x64S( mkexpr(z3), mkexpr(z2),
12197ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                         mkexpr(z1), mkexpr(z0)) );
12198ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      break;
12199ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
12200ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   default:
12201ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      vex_printf("dis_av_multarith(ppc)(opc2)\n");
12202ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      return False;
12203ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
12204ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   return True;
12205ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
12206ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
12207ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*
12208ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  AltiVec Shift/Rotate Instructions
12209ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown*/
12210ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic Bool dis_av_shift ( UInt theInstr )
12211ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
12212ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* VX-Form */
12213ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   UChar opc1    = ifieldOPC(theInstr);
12214ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   UChar vD_addr = ifieldRegDS(theInstr);
12215ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   UChar vA_addr = ifieldRegA(theInstr);
12216ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   UChar vB_addr = ifieldRegB(theInstr);
12217ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   UInt  opc2    = IFIELD( theInstr, 0, 11 );
12218ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
12219ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   IRTemp vA = newTemp(Ity_V128);
12220ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   IRTemp vB = newTemp(Ity_V128);
12221ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   assign( vA, getVReg(vA_addr));
12222ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   assign( vB, getVReg(vB_addr));
12223ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
12224ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (opc1 != 0x4){
12225ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      vex_printf("dis_av_shift(ppc)(instr)\n");
12226ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      return False;
12227ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
12228ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
12229ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   switch (opc2) {
12230ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* Rotate */
12231ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   case 0x004: // vrlb (Rotate Left Integer B, AV p234)
12232ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      DIP("vrlb v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
12233ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      putVReg( vD_addr, binop(Iop_Rol8x16, mkexpr(vA), mkexpr(vB)) );
12234ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      break;
12235ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
12236ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   case 0x044: // vrlh (Rotate Left Integer HW, AV p235)
12237ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      DIP("vrlh v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
12238ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      putVReg( vD_addr, binop(Iop_Rol16x8, mkexpr(vA), mkexpr(vB)) );
12239ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      break;
12240ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
12241ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   case 0x084: // vrlw (Rotate Left Integer W, AV p236)
12242ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      DIP("vrlw v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
12243ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      putVReg( vD_addr, binop(Iop_Rol32x4, mkexpr(vA), mkexpr(vB)) );
12244ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      break;
12245ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
12246ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
12247ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* Shift Left */
12248ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   case 0x104: // vslb (Shift Left Integer B, AV p240)
12249ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      DIP("vslb v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
12250ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      putVReg( vD_addr, binop(Iop_Shl8x16, mkexpr(vA), mkexpr(vB)) );
12251ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      break;
12252ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
12253ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   case 0x144: // vslh (Shift Left Integer HW, AV p242)
12254ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      DIP("vslh v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
12255ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      putVReg( vD_addr, binop(Iop_Shl16x8, mkexpr(vA), mkexpr(vB)) );
12256ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      break;
12257ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
12258ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   case 0x184: // vslw (Shift Left Integer W, AV p244)
12259ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      DIP("vslw v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
12260ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      putVReg( vD_addr, binop(Iop_Shl32x4, mkexpr(vA), mkexpr(vB)) );
12261ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      break;
12262ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
12263ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   case 0x1C4: { // vsl (Shift Left, AV p239)
12264ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      IRTemp sh = newTemp(Ity_I8);
12265ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      DIP("vsl v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
12266ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      assign( sh, binop(Iop_And8, mkU8(0x7),
12267ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                        unop(Iop_32to8,
12268ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                             unop(Iop_V128to32, mkexpr(vB)))) );
12269ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      putVReg( vD_addr,
12270ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               binop(Iop_ShlV128, mkexpr(vA), mkexpr(sh)) );
12271ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      break;
12272ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
12273ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   case 0x40C: { // vslo (Shift Left by Octet, AV p243)
12274ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      IRTemp sh = newTemp(Ity_I8);
12275ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      DIP("vslo v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
12276ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      assign( sh, binop(Iop_And8, mkU8(0x78),
12277ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                        unop(Iop_32to8,
12278ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                             unop(Iop_V128to32, mkexpr(vB)))) );
12279ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      putVReg( vD_addr,
12280ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               binop(Iop_ShlV128, mkexpr(vA), mkexpr(sh)) );
12281ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      break;
12282ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
12283ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
12284ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
12285ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* Shift Right */
12286ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   case 0x204: // vsrb (Shift Right B, AV p256)
12287ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      DIP("vsrb v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
12288ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      putVReg( vD_addr, binop(Iop_Shr8x16, mkexpr(vA), mkexpr(vB)) );
12289ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      break;
12290ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
12291ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   case 0x244: // vsrh (Shift Right HW, AV p257)
12292ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      DIP("vsrh v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
12293ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      putVReg( vD_addr, binop(Iop_Shr16x8, mkexpr(vA), mkexpr(vB)) );
12294ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      break;
12295ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
12296ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   case 0x284: // vsrw (Shift Right W, AV p259)
12297ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      DIP("vsrw v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
12298ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      putVReg( vD_addr, binop(Iop_Shr32x4, mkexpr(vA), mkexpr(vB)) );
12299ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      break;
12300ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
12301ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   case 0x2C4: { // vsr (Shift Right, AV p251)
12302ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      IRTemp sh = newTemp(Ity_I8);
12303ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      DIP("vsr v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
12304ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      assign( sh, binop(Iop_And8, mkU8(0x7),
12305ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                        unop(Iop_32to8,
12306ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                             unop(Iop_V128to32, mkexpr(vB)))) );
12307ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      putVReg( vD_addr,
12308ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               binop(Iop_ShrV128, mkexpr(vA), mkexpr(sh)) );
12309ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      break;
12310ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
12311ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   case 0x304: // vsrab (Shift Right Alg B, AV p253)
12312ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      DIP("vsrab v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
12313ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      putVReg( vD_addr, binop(Iop_Sar8x16, mkexpr(vA), mkexpr(vB)) );
12314ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      break;
12315ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
12316ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   case 0x344: // vsrah (Shift Right Alg HW, AV p254)
12317ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      DIP("vsrah v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
12318ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      putVReg( vD_addr, binop(Iop_Sar16x8, mkexpr(vA), mkexpr(vB)) );
12319ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      break;
12320ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
12321ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   case 0x384: // vsraw (Shift Right Alg W, AV p255)
12322ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      DIP("vsraw v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
12323ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      putVReg( vD_addr, binop(Iop_Sar32x4, mkexpr(vA), mkexpr(vB)) );
12324ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      break;
12325ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
12326ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   case 0x44C: { // vsro (Shift Right by Octet, AV p258)
12327ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      IRTemp sh = newTemp(Ity_I8);
12328ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      DIP("vsro v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
12329ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      assign( sh, binop(Iop_And8, mkU8(0x78),
12330ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                        unop(Iop_32to8,
12331ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                             unop(Iop_V128to32, mkexpr(vB)))) );
12332ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      putVReg( vD_addr,
12333ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               binop(Iop_ShrV128, mkexpr(vA), mkexpr(sh)) );
12334ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      break;
12335ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
12336ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
12337ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   default:
12338ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      vex_printf("dis_av_shift(ppc)(opc2)\n");
12339ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      return False;
12340ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
12341ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   return True;
12342ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
12343ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
12344ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*
12345ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  AltiVec Permute Instructions
12346ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown*/
12347ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic Bool dis_av_permute ( UInt theInstr )
12348ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
12349ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* VA-Form, VX-Form */
12350ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   UChar opc1      = ifieldOPC(theInstr);
12351ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   UChar vD_addr   = ifieldRegDS(theInstr);
12352ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   UChar vA_addr   = ifieldRegA(theInstr);
12353ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   UChar UIMM_5    = vA_addr;
12354ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   UChar vB_addr   = ifieldRegB(theInstr);
12355ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   UChar vC_addr   = ifieldRegC(theInstr);
12356ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   UChar b10       = ifieldBIT10(theInstr);
12357ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   UChar SHB_uimm4 = toUChar( IFIELD( theInstr, 6, 4 ) );
12358ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   UInt  opc2      = toUChar( IFIELD( theInstr, 0, 6 ) );
12359ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
12360ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   UChar SIMM_8 = extend_s_5to8(UIMM_5);
12361ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
12362ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   IRTemp vA = newTemp(Ity_V128);
12363ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   IRTemp vB = newTemp(Ity_V128);
12364ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   IRTemp vC = newTemp(Ity_V128);
12365ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   assign( vA, getVReg(vA_addr));
12366ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   assign( vB, getVReg(vB_addr));
12367ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   assign( vC, getVReg(vC_addr));
12368ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
12369ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (opc1 != 0x4) {
12370ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      vex_printf("dis_av_permute(ppc)(instr)\n");
12371ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      return False;
12372ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
12373ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
12374ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   switch (opc2) {
12375ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   case 0x2A: // vsel (Conditional Select, AV p238)
12376ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      DIP("vsel v%d,v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr, vC_addr);
12377ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* vD = (vA & ~vC) | (vB & vC) */
12378ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      putVReg( vD_addr, binop(Iop_OrV128,
12379ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         binop(Iop_AndV128, mkexpr(vA), unop(Iop_NotV128, mkexpr(vC))),
12380ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         binop(Iop_AndV128, mkexpr(vB), mkexpr(vC))) );
12381ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      return True;
12382ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
12383ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   case 0x2B: { // vperm (Permute, AV p218)
12384ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* limited to two args for IR, so have to play games... */
12385ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      IRTemp a_perm  = newTemp(Ity_V128);
12386ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      IRTemp b_perm  = newTemp(Ity_V128);
12387ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      IRTemp mask    = newTemp(Ity_V128);
12388ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      IRTemp vC_andF = newTemp(Ity_V128);
12389ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      DIP("vperm v%d,v%d,v%d,v%d\n",
12390ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown          vD_addr, vA_addr, vB_addr, vC_addr);
12391ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* Limit the Perm8x16 steering values to 0 .. 15 as that is what
12392ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         IR specifies, and also to hide irrelevant bits from
12393ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         memcheck */
12394ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      assign( vC_andF,
12395ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown              binop(Iop_AndV128, mkexpr(vC),
12396ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                 unop(Iop_Dup8x16, mkU8(0xF))) );
12397ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      assign( a_perm,
12398ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown              binop(Iop_Perm8x16, mkexpr(vA), mkexpr(vC_andF)) );
12399ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      assign( b_perm,
12400ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown              binop(Iop_Perm8x16, mkexpr(vB), mkexpr(vC_andF)) );
12401ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      // mask[i8] = (vC[i8]_4 == 1) ? 0xFF : 0x0
12402ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      assign( mask, binop(Iop_SarN8x16,
12403ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                          binop(Iop_ShlN8x16, mkexpr(vC), mkU8(3)),
12404ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                          mkU8(7)) );
12405ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      // dst = (a & ~mask) | (b & mask)
12406ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      putVReg( vD_addr, binop(Iop_OrV128,
12407ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                              binop(Iop_AndV128, mkexpr(a_perm),
12408ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                    unop(Iop_NotV128, mkexpr(mask))),
12409ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                              binop(Iop_AndV128, mkexpr(b_perm),
12410ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                    mkexpr(mask))) );
12411ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      return True;
12412ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
12413ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   case 0x2C: // vsldoi (Shift Left Double by Octet Imm, AV p241)
12414ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (b10 != 0) {
12415ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         vex_printf("dis_av_permute(ppc)(vsldoi)\n");
12416ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return False;
12417ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
12418ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      DIP("vsldoi v%d,v%d,v%d,%d\n",
12419ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown          vD_addr, vA_addr, vB_addr, SHB_uimm4);
12420ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (SHB_uimm4 == 0)
12421ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         putVReg( vD_addr, mkexpr(vA) );
12422ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      else
12423ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         putVReg( vD_addr,
12424ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            binop(Iop_OrV128,
12425ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  binop(Iop_ShlV128, mkexpr(vA), mkU8(SHB_uimm4*8)),
12426ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  binop(Iop_ShrV128, mkexpr(vB), mkU8((16-SHB_uimm4)*8))) );
12427ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      return True;
12428ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
12429ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   default:
12430ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     break; // Fall through...
12431ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
12432ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
12433ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   opc2 = IFIELD( theInstr, 0, 11 );
12434ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   switch (opc2) {
12435ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
12436ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* Merge */
12437ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   case 0x00C: // vmrghb (Merge High B, AV p195)
12438ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      DIP("vmrghb v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
12439ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      putVReg( vD_addr,
12440ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               binop(Iop_InterleaveHI8x16, mkexpr(vA), mkexpr(vB)) );
12441ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      break;
12442ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
12443ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   case 0x04C: // vmrghh (Merge High HW, AV p196)
12444ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      DIP("vmrghh v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
12445ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      putVReg( vD_addr,
12446ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               binop(Iop_InterleaveHI16x8, mkexpr(vA), mkexpr(vB)) );
12447ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      break;
12448ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
12449ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   case 0x08C: // vmrghw (Merge High W, AV p197)
12450ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      DIP("vmrghw v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
12451ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      putVReg( vD_addr,
12452ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               binop(Iop_InterleaveHI32x4, mkexpr(vA), mkexpr(vB)) );
12453ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      break;
12454ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
12455ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   case 0x10C: // vmrglb (Merge Low B, AV p198)
12456ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      DIP("vmrglb v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
12457ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      putVReg( vD_addr,
12458ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               binop(Iop_InterleaveLO8x16, mkexpr(vA), mkexpr(vB)) );
12459ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      break;
12460ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
12461ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   case 0x14C: // vmrglh (Merge Low HW, AV p199)
12462ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      DIP("vmrglh v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
12463ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      putVReg( vD_addr,
12464ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               binop(Iop_InterleaveLO16x8, mkexpr(vA), mkexpr(vB)) );
12465ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      break;
12466ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
12467ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   case 0x18C: // vmrglw (Merge Low W, AV p200)
12468ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      DIP("vmrglw v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
12469ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      putVReg( vD_addr,
12470ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               binop(Iop_InterleaveLO32x4, mkexpr(vA), mkexpr(vB)) );
12471ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      break;
12472ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
12473ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
12474ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* Splat */
12475ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   case 0x20C: { // vspltb (Splat Byte, AV p245)
12476ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* vD = Dup8x16( vB[UIMM_5] ) */
12477ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      UChar sh_uimm = (15 - (UIMM_5 & 15)) * 8;
12478ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      DIP("vspltb v%d,v%d,%d\n", vD_addr, vB_addr, UIMM_5);
12479ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      putVReg( vD_addr, unop(Iop_Dup8x16,
12480ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown           unop(Iop_32to8, unop(Iop_V128to32,
12481ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                binop(Iop_ShrV128, mkexpr(vB), mkU8(sh_uimm))))) );
12482ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      break;
12483ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
12484ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   case 0x24C: { // vsplth (Splat Half Word, AV p246)
12485ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      UChar sh_uimm = (7 - (UIMM_5 & 7)) * 16;
12486ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      DIP("vsplth v%d,v%d,%d\n", vD_addr, vB_addr, UIMM_5);
12487ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      putVReg( vD_addr, unop(Iop_Dup16x8,
12488ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown           unop(Iop_32to16, unop(Iop_V128to32,
12489ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                binop(Iop_ShrV128, mkexpr(vB), mkU8(sh_uimm))))) );
12490ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      break;
12491ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
12492ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   case 0x28C: { // vspltw (Splat Word, AV p250)
12493ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* vD = Dup32x4( vB[UIMM_5] ) */
12494ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      UChar sh_uimm = (3 - (UIMM_5 & 3)) * 32;
12495ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      DIP("vspltw v%d,v%d,%d\n", vD_addr, vB_addr, UIMM_5);
12496ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      putVReg( vD_addr, unop(Iop_Dup32x4,
12497ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         unop(Iop_V128to32,
12498ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown              binop(Iop_ShrV128, mkexpr(vB), mkU8(sh_uimm)))) );
12499ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      break;
12500ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
12501ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   case 0x30C: // vspltisb (Splat Immediate Signed B, AV p247)
12502ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      DIP("vspltisb v%d,%d\n", vD_addr, (Char)SIMM_8);
12503ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      putVReg( vD_addr, unop(Iop_Dup8x16, mkU8(SIMM_8)) );
12504ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      break;
12505ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
12506ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   case 0x34C: // vspltish (Splat Immediate Signed HW, AV p248)
12507ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      DIP("vspltish v%d,%d\n", vD_addr, (Char)SIMM_8);
12508ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      putVReg( vD_addr,
12509ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               unop(Iop_Dup16x8, mkU16(extend_s_8to32(SIMM_8))) );
12510ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      break;
12511ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
12512ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   case 0x38C: // vspltisw (Splat Immediate Signed W, AV p249)
12513ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      DIP("vspltisw v%d,%d\n", vD_addr, (Char)SIMM_8);
12514ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      putVReg( vD_addr,
12515ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               unop(Iop_Dup32x4, mkU32(extend_s_8to32(SIMM_8))) );
12516ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      break;
12517ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
12518ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   default:
12519ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      vex_printf("dis_av_permute(ppc)(opc2)\n");
12520ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      return False;
12521ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
12522ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   return True;
12523ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
12524ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
12525ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*
12526ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  AltiVec Pack/Unpack Instructions
12527ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown*/
12528ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic Bool dis_av_pack ( UInt theInstr )
12529ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
12530ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* VX-Form */
12531ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   UChar opc1     = ifieldOPC(theInstr);
12532ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   UChar vD_addr  = ifieldRegDS(theInstr);
12533ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   UChar vA_addr  = ifieldRegA(theInstr);
12534ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   UChar vB_addr  = ifieldRegB(theInstr);
12535ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   UInt  opc2     = IFIELD( theInstr, 0, 11 );
12536ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
12537ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   IRTemp signs = IRTemp_INVALID;
12538ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   IRTemp zeros = IRTemp_INVALID;
12539ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   IRTemp vA    = newTemp(Ity_V128);
12540ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   IRTemp vB    = newTemp(Ity_V128);
12541ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   assign( vA, getVReg(vA_addr));
12542ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   assign( vB, getVReg(vB_addr));
12543ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
12544ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (opc1 != 0x4) {
12545ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      vex_printf("dis_av_pack(ppc)(instr)\n");
12546ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      return False;
12547ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
12548ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
12549ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   switch (opc2) {
12550ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* Packing */
12551ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   case 0x00E: // vpkuhum (Pack Unsigned HW Unsigned Modulo, AV p224)
12552ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      DIP("vpkuhum v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
12553b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      putVReg( vD_addr,
12554b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov               binop(Iop_NarrowBin16to8x16, mkexpr(vA), mkexpr(vB)) );
12555ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      return True;
12556ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
12557ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   case 0x04E: // vpkuwum (Pack Unsigned W Unsigned Modulo, AV p226)
12558ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      DIP("vpkuwum v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
12559b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      putVReg( vD_addr,
12560b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov               binop(Iop_NarrowBin32to16x8, mkexpr(vA), mkexpr(vB)) );
12561ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      return True;
12562ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
12563ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   case 0x08E: // vpkuhus (Pack Unsigned HW Unsigned Saturate, AV p225)
12564ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      DIP("vpkuhus v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
12565ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      putVReg( vD_addr,
12566b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov               binop(Iop_QNarrowBin16Uto8Ux16, mkexpr(vA), mkexpr(vB)) );
12567ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      // TODO: set VSCR[SAT]
12568ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      return True;
12569ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
12570ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   case 0x0CE: // vpkuwus (Pack Unsigned W Unsigned Saturate, AV p227)
12571ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      DIP("vpkuwus v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
12572ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      putVReg( vD_addr,
12573b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov               binop(Iop_QNarrowBin32Uto16Ux8, mkexpr(vA), mkexpr(vB)) );
12574ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      // TODO: set VSCR[SAT]
12575ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      return True;
12576ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
12577ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   case 0x10E: { // vpkshus (Pack Signed HW Unsigned Saturate, AV p221)
12578ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      // This insn does a signed->unsigned saturating conversion.
12579ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      // Conversion done here, then uses unsigned->unsigned vpk insn:
12580ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      //  => UnsignedSaturatingNarrow( x & ~ (x >>s 15) )
12581ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      IRTemp vA_tmp = newTemp(Ity_V128);
12582ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      IRTemp vB_tmp = newTemp(Ity_V128);
12583ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      DIP("vpkshus v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
12584ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      assign( vA_tmp, binop(Iop_AndV128, mkexpr(vA),
12585ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                            unop(Iop_NotV128,
12586ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                 binop(Iop_SarN16x8,
12587ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                       mkexpr(vA), mkU8(15)))) );
12588ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      assign( vB_tmp, binop(Iop_AndV128, mkexpr(vB),
12589ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                            unop(Iop_NotV128,
12590ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                 binop(Iop_SarN16x8,
12591ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                       mkexpr(vB), mkU8(15)))) );
12592b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      putVReg( vD_addr, binop(Iop_QNarrowBin16Uto8Ux16,
12593ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                              mkexpr(vA_tmp), mkexpr(vB_tmp)) );
12594ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      // TODO: set VSCR[SAT]
12595ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      return True;
12596ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
12597ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   case 0x14E: { // vpkswus (Pack Signed W Unsigned Saturate, AV p223)
12598ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      // This insn does a signed->unsigned saturating conversion.
12599ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      // Conversion done here, then uses unsigned->unsigned vpk insn:
12600ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      //  => UnsignedSaturatingNarrow( x & ~ (x >>s 31) )
12601ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      IRTemp vA_tmp = newTemp(Ity_V128);
12602ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      IRTemp vB_tmp = newTemp(Ity_V128);
12603ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      DIP("vpkswus v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
12604ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      assign( vA_tmp, binop(Iop_AndV128, mkexpr(vA),
12605ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                            unop(Iop_NotV128,
12606ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                 binop(Iop_SarN32x4,
12607ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                       mkexpr(vA), mkU8(31)))) );
12608ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      assign( vB_tmp, binop(Iop_AndV128, mkexpr(vB),
12609ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                            unop(Iop_NotV128,
12610ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                 binop(Iop_SarN32x4,
12611ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                       mkexpr(vB), mkU8(31)))) );
12612b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      putVReg( vD_addr, binop(Iop_QNarrowBin32Uto16Ux8,
12613ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                              mkexpr(vA_tmp), mkexpr(vB_tmp)) );
12614ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      // TODO: set VSCR[SAT]
12615ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      return True;
12616ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
12617ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   case 0x18E: // vpkshss (Pack Signed HW Signed Saturate, AV p220)
12618ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      DIP("vpkshss v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
12619ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      putVReg( vD_addr,
12620b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov               binop(Iop_QNarrowBin16Sto8Sx16, mkexpr(vA), mkexpr(vB)) );
12621ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      // TODO: set VSCR[SAT]
12622ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      return True;
12623ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
12624ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   case 0x1CE: // vpkswss (Pack Signed W Signed Saturate, AV p222)
12625ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      DIP("vpkswss v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
12626ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      putVReg( vD_addr,
12627b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov               binop(Iop_QNarrowBin32Sto16Sx8, mkexpr(vA), mkexpr(vB)) );
12628ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      // TODO: set VSCR[SAT]
12629ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      return True;
12630ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
12631ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   case 0x30E: { // vpkpx (Pack Pixel, AV p219)
12632ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* CAB: Worth a new primop? */
12633ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* Using shifts to compact pixel elements, then packing them */
12634ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      IRTemp a1 = newTemp(Ity_V128);
12635ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      IRTemp a2 = newTemp(Ity_V128);
12636ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      IRTemp a3 = newTemp(Ity_V128);
12637ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      IRTemp a_tmp = newTemp(Ity_V128);
12638ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      IRTemp b1 = newTemp(Ity_V128);
12639ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      IRTemp b2 = newTemp(Ity_V128);
12640ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      IRTemp b3 = newTemp(Ity_V128);
12641ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      IRTemp b_tmp = newTemp(Ity_V128);
12642ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      DIP("vpkpx v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
12643ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      assign( a1, binop(Iop_ShlN16x8,
12644ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                        binop(Iop_ShrN32x4, mkexpr(vA), mkU8(19)),
12645ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                        mkU8(10)) );
12646ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      assign( a2, binop(Iop_ShlN16x8,
12647ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                        binop(Iop_ShrN16x8, mkexpr(vA), mkU8(11)),
12648ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                        mkU8(5)) );
12649ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      assign( a3,  binop(Iop_ShrN16x8,
12650ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                         binop(Iop_ShlN16x8, mkexpr(vA), mkU8(8)),
12651ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                         mkU8(11)) );
12652ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      assign( a_tmp, binop(Iop_OrV128, mkexpr(a1),
12653ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                           binop(Iop_OrV128, mkexpr(a2), mkexpr(a3))) );
12654ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
12655ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      assign( b1, binop(Iop_ShlN16x8,
12656ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                        binop(Iop_ShrN32x4, mkexpr(vB), mkU8(19)),
12657ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                        mkU8(10)) );
12658ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      assign( b2, binop(Iop_ShlN16x8,
12659ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                        binop(Iop_ShrN16x8, mkexpr(vB), mkU8(11)),
12660ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                        mkU8(5)) );
12661ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      assign( b3,  binop(Iop_ShrN16x8,
12662ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                         binop(Iop_ShlN16x8, mkexpr(vB), mkU8(8)),
12663ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                         mkU8(11)) );
12664ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      assign( b_tmp, binop(Iop_OrV128, mkexpr(b1),
12665ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                           binop(Iop_OrV128, mkexpr(b2), mkexpr(b3))) );
12666ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
12667b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      putVReg( vD_addr, binop(Iop_NarrowBin32to16x8,
12668ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                              mkexpr(a_tmp), mkexpr(b_tmp)) );
12669ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      return True;
12670ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
12671ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
12672ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   default:
12673ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      break; // Fall through...
12674ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
12675ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
12676ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
12677ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (vA_addr != 0) {
12678ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      vex_printf("dis_av_pack(ppc)(vA_addr)\n");
12679ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      return False;
12680ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
12681ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
12682ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   signs = newTemp(Ity_V128);
12683ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   zeros = newTemp(Ity_V128);
12684ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   assign( zeros, unop(Iop_Dup32x4, mkU32(0)) );
12685ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
12686ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   switch (opc2) {
12687ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* Unpacking */
12688ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   case 0x20E: { // vupkhsb (Unpack High Signed B, AV p277)
12689ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      DIP("vupkhsb v%d,v%d\n", vD_addr, vB_addr);
12690ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      assign( signs, binop(Iop_CmpGT8Sx16, mkexpr(zeros), mkexpr(vB)) );
12691ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      putVReg( vD_addr,
12692ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               binop(Iop_InterleaveHI8x16, mkexpr(signs), mkexpr(vB)) );
12693ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      break;
12694ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
12695ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   case 0x24E: { // vupkhsh (Unpack High Signed HW, AV p278)
12696ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      DIP("vupkhsh v%d,v%d\n", vD_addr, vB_addr);
12697ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      assign( signs, binop(Iop_CmpGT16Sx8, mkexpr(zeros), mkexpr(vB)) );
12698ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      putVReg( vD_addr,
12699ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               binop(Iop_InterleaveHI16x8, mkexpr(signs), mkexpr(vB)) );
12700ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      break;
12701ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
12702ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   case 0x28E: { // vupklsb (Unpack Low Signed B, AV p280)
12703ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      DIP("vupklsb v%d,v%d\n", vD_addr, vB_addr);
12704ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      assign( signs, binop(Iop_CmpGT8Sx16, mkexpr(zeros), mkexpr(vB)) );
12705ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      putVReg( vD_addr,
12706ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               binop(Iop_InterleaveLO8x16, mkexpr(signs), mkexpr(vB)) );
12707ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      break;
12708ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
12709ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   case 0x2CE: { // vupklsh (Unpack Low Signed HW, AV p281)
12710ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      DIP("vupklsh v%d,v%d\n", vD_addr, vB_addr);
12711ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      assign( signs, binop(Iop_CmpGT16Sx8, mkexpr(zeros), mkexpr(vB)) );
12712ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      putVReg( vD_addr,
12713ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               binop(Iop_InterleaveLO16x8, mkexpr(signs), mkexpr(vB)) );
12714ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      break;
12715ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
12716ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   case 0x34E: { // vupkhpx (Unpack High Pixel16, AV p276)
12717ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* CAB: Worth a new primop? */
12718ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* Using shifts to isolate pixel elements, then expanding them */
12719ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      IRTemp z0  = newTemp(Ity_V128);
12720ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      IRTemp z1  = newTemp(Ity_V128);
12721ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      IRTemp z01 = newTemp(Ity_V128);
12722ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      IRTemp z2  = newTemp(Ity_V128);
12723ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      IRTemp z3  = newTemp(Ity_V128);
12724ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      IRTemp z23 = newTemp(Ity_V128);
12725ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      DIP("vupkhpx v%d,v%d\n", vD_addr, vB_addr);
12726ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      assign( z0,  binop(Iop_ShlN16x8,
12727ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                         binop(Iop_SarN16x8, mkexpr(vB), mkU8(15)),
12728ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                         mkU8(8)) );
12729ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      assign( z1,  binop(Iop_ShrN16x8,
12730ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                         binop(Iop_ShlN16x8, mkexpr(vB), mkU8(1)),
12731ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                         mkU8(11)) );
12732ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      assign( z01, binop(Iop_InterleaveHI16x8, mkexpr(zeros),
12733ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                         binop(Iop_OrV128, mkexpr(z0), mkexpr(z1))) );
12734ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      assign( z2,  binop(Iop_ShrN16x8,
12735ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                         binop(Iop_ShlN16x8,
12736ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                               binop(Iop_ShrN16x8, mkexpr(vB), mkU8(5)),
12737ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                               mkU8(11)),
12738ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                         mkU8(3)) );
12739ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      assign( z3,  binop(Iop_ShrN16x8,
12740ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                         binop(Iop_ShlN16x8, mkexpr(vB), mkU8(11)),
12741ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                         mkU8(11)) );
12742ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      assign( z23, binop(Iop_InterleaveHI16x8, mkexpr(zeros),
12743ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                         binop(Iop_OrV128, mkexpr(z2), mkexpr(z3))) );
12744ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      putVReg( vD_addr,
12745ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               binop(Iop_OrV128,
12746ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                     binop(Iop_ShlN32x4, mkexpr(z01), mkU8(16)),
12747ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                     mkexpr(z23)) );
12748ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      break;
12749ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
12750ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   case 0x3CE: { // vupklpx (Unpack Low Pixel16, AV p279)
12751ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* identical to vupkhpx, except interleaving LO */
12752ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      IRTemp z0  = newTemp(Ity_V128);
12753ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      IRTemp z1  = newTemp(Ity_V128);
12754ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      IRTemp z01 = newTemp(Ity_V128);
12755ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      IRTemp z2  = newTemp(Ity_V128);
12756ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      IRTemp z3  = newTemp(Ity_V128);
12757ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      IRTemp z23 = newTemp(Ity_V128);
12758ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      DIP("vupklpx v%d,v%d\n", vD_addr, vB_addr);
12759ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      assign( z0,  binop(Iop_ShlN16x8,
12760ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                         binop(Iop_SarN16x8, mkexpr(vB), mkU8(15)),
12761ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                         mkU8(8)) );
12762ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      assign( z1,  binop(Iop_ShrN16x8,
12763ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                         binop(Iop_ShlN16x8, mkexpr(vB), mkU8(1)),
12764ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                         mkU8(11)) );
12765ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      assign( z01, binop(Iop_InterleaveLO16x8, mkexpr(zeros),
12766ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                         binop(Iop_OrV128, mkexpr(z0), mkexpr(z1))) );
12767ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      assign( z2,  binop(Iop_ShrN16x8,
12768ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                         binop(Iop_ShlN16x8,
12769ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                               binop(Iop_ShrN16x8, mkexpr(vB), mkU8(5)),
12770ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                               mkU8(11)),
12771ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                         mkU8(3)) );
12772ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      assign( z3,  binop(Iop_ShrN16x8,
12773ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                         binop(Iop_ShlN16x8, mkexpr(vB), mkU8(11)),
12774ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                         mkU8(11)) );
12775ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      assign( z23, binop(Iop_InterleaveLO16x8, mkexpr(zeros),
12776ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                         binop(Iop_OrV128, mkexpr(z2), mkexpr(z3))) );
12777ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      putVReg( vD_addr,
12778ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               binop(Iop_OrV128,
12779ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                     binop(Iop_ShlN32x4, mkexpr(z01), mkU8(16)),
12780ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                     mkexpr(z23)) );
12781ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      break;
12782ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
12783ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   default:
12784ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      vex_printf("dis_av_pack(ppc)(opc2)\n");
12785ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      return False;
12786ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
12787ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   return True;
12788ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
12789ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
12790ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
12791ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*
12792ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  AltiVec Floating Point Arithmetic Instructions
12793ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown*/
12794ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic Bool dis_av_fp_arith ( UInt theInstr )
12795ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
12796ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* VA-Form */
12797ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   UChar opc1     = ifieldOPC(theInstr);
12798ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   UChar vD_addr  = ifieldRegDS(theInstr);
12799ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   UChar vA_addr  = ifieldRegA(theInstr);
12800ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   UChar vB_addr  = ifieldRegB(theInstr);
12801ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   UChar vC_addr  = ifieldRegC(theInstr);
12802ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   UInt  opc2=0;
12803ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
12804ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   IRTemp vA = newTemp(Ity_V128);
12805ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   IRTemp vB = newTemp(Ity_V128);
12806ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   IRTemp vC = newTemp(Ity_V128);
12807ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   assign( vA, getVReg(vA_addr));
12808ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   assign( vB, getVReg(vB_addr));
12809ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   assign( vC, getVReg(vC_addr));
12810ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
12811ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (opc1 != 0x4) {
12812ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      vex_printf("dis_av_fp_arith(ppc)(instr)\n");
12813ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      return False;
12814ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
12815ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
12816ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   opc2 = IFIELD( theInstr, 0, 6 );
12817ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   switch (opc2) {
12818ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   case 0x2E: // vmaddfp (Multiply Add FP, AV p177)
12819ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      DIP("vmaddfp v%d,v%d,v%d,v%d\n",
12820ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown          vD_addr, vA_addr, vC_addr, vB_addr);
12821ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      putVReg( vD_addr,
12822ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               binop(Iop_Add32Fx4, mkexpr(vB),
12823ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                     binop(Iop_Mul32Fx4, mkexpr(vA), mkexpr(vC))) );
12824ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      return True;
12825ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
12826ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   case 0x2F: { // vnmsubfp (Negative Multiply-Subtract FP, AV p215)
12827ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      DIP("vnmsubfp v%d,v%d,v%d,v%d\n",
12828ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown          vD_addr, vA_addr, vC_addr, vB_addr);
12829ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      putVReg( vD_addr,
12830ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               binop(Iop_Sub32Fx4,
12831ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                     mkexpr(vB),
12832ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                     binop(Iop_Mul32Fx4, mkexpr(vA), mkexpr(vC))) );
12833ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      return True;
12834ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
12835ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
12836ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   default:
12837ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     break; // Fall through...
12838ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
12839ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
12840ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   opc2 = IFIELD( theInstr, 0, 11 );
12841ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   switch (opc2) {
12842ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   case 0x00A: // vaddfp (Add FP, AV p137)
12843ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      DIP("vaddfp v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
12844ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      putVReg( vD_addr, binop(Iop_Add32Fx4, mkexpr(vA), mkexpr(vB)) );
12845ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      return True;
12846ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
12847ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  case 0x04A: // vsubfp (Subtract FP, AV p261)
12848ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      DIP("vsubfp v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
12849ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      putVReg( vD_addr, binop(Iop_Sub32Fx4, mkexpr(vA), mkexpr(vB)) );
12850ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      return True;
12851ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
12852ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   case 0x40A: // vmaxfp (Maximum FP, AV p178)
12853ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      DIP("vmaxfp v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
12854ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      putVReg( vD_addr, binop(Iop_Max32Fx4, mkexpr(vA), mkexpr(vB)) );
12855ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      return True;
12856ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
12857ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   case 0x44A: // vminfp (Minimum FP, AV p187)
12858ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      DIP("vminfp v%d,v%d,v%d\n", vD_addr, vA_addr, vB_addr);
12859ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      putVReg( vD_addr, binop(Iop_Min32Fx4, mkexpr(vA), mkexpr(vB)) );
12860ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      return True;
12861ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
12862ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   default:
12863ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      break; // Fall through...
12864ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
12865ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
12866ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
12867ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (vA_addr != 0) {
12868ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      vex_printf("dis_av_fp_arith(ppc)(vA_addr)\n");
12869ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      return False;
12870ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
12871ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
12872ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   switch (opc2) {
12873ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   case 0x10A: // vrefp (Reciprocal Esimate FP, AV p228)
12874ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      DIP("vrefp v%d,v%d\n", vD_addr, vB_addr);
12875ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      putVReg( vD_addr, unop(Iop_Recip32Fx4, mkexpr(vB)) );
12876ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      return True;
12877ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
12878ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   case 0x14A: // vrsqrtefp (Reciprocal Sqrt Estimate FP, AV p237)
12879ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      DIP("vrsqrtefp v%d,v%d\n", vD_addr, vB_addr);
12880ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      putVReg( vD_addr, unop(Iop_RSqrt32Fx4, mkexpr(vB)) );
12881ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      return True;
12882ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
12883ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   case 0x18A: // vexptefp (2 Raised to the Exp Est FP, AV p173)
12884ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      DIP("vexptefp v%d,v%d\n", vD_addr, vB_addr);
12885ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      DIP(" => not implemented\n");
12886ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      return False;
12887ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
12888ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   case 0x1CA: // vlogefp (Log2 Estimate FP, AV p175)
12889ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      DIP("vlogefp v%d,v%d\n", vD_addr, vB_addr);
12890ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      DIP(" => not implemented\n");
12891ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      return False;
12892ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
12893ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   default:
12894ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      vex_printf("dis_av_fp_arith(ppc)(opc2=0x%x)\n",opc2);
12895ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      return False;
12896ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
12897ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   return True;
12898ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
12899ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
12900ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*
12901ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  AltiVec Floating Point Compare Instructions
12902ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown*/
12903ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic Bool dis_av_fp_cmp ( UInt theInstr )
12904ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
12905ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* VXR-Form */
12906ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   UChar opc1     = ifieldOPC(theInstr);
12907ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   UChar vD_addr  = ifieldRegDS(theInstr);
12908ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   UChar vA_addr  = ifieldRegA(theInstr);
12909ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   UChar vB_addr  = ifieldRegB(theInstr);
12910ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   UChar flag_rC  = ifieldBIT10(theInstr);
12911ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   UInt  opc2     = IFIELD( theInstr, 0, 10 );
12912ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
12913ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   Bool cmp_bounds = False;
12914ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
12915ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   IRTemp vA = newTemp(Ity_V128);
12916ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   IRTemp vB = newTemp(Ity_V128);
12917ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   IRTemp vD = newTemp(Ity_V128);
12918ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   assign( vA, getVReg(vA_addr));
12919ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   assign( vB, getVReg(vB_addr));
12920ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
12921ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (opc1 != 0x4) {
12922ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      vex_printf("dis_av_fp_cmp(ppc)(instr)\n");
12923ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      return False;
12924ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
12925ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
12926ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   switch (opc2) {
12927ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   case 0x0C6: // vcmpeqfp (Compare Equal-to FP, AV p159)
12928ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      DIP("vcmpeqfp%s v%d,v%d,v%d\n", (flag_rC ? ".":""),
12929ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                      vD_addr, vA_addr, vB_addr);
12930ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      assign( vD, binop(Iop_CmpEQ32Fx4, mkexpr(vA), mkexpr(vB)) );
12931ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      break;
12932ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
12933ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   case 0x1C6: // vcmpgefp (Compare Greater-than-or-Equal-to, AV p163)
12934ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      DIP("vcmpgefp%s v%d,v%d,v%d\n", (flag_rC ? ".":""),
12935ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                      vD_addr, vA_addr, vB_addr);
12936ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      assign( vD, binop(Iop_CmpGE32Fx4, mkexpr(vA), mkexpr(vB)) );
12937ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      break;
12938ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
12939ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   case 0x2C6: // vcmpgtfp (Compare Greater-than FP, AV p164)
12940ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      DIP("vcmpgtfp%s v%d,v%d,v%d\n", (flag_rC ? ".":""),
12941ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                      vD_addr, vA_addr, vB_addr);
12942ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      assign( vD, binop(Iop_CmpGT32Fx4, mkexpr(vA), mkexpr(vB)) );
12943ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      break;
12944ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
12945ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   case 0x3C6: { // vcmpbfp (Compare Bounds FP, AV p157)
12946ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      IRTemp gt      = newTemp(Ity_V128);
12947ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      IRTemp lt      = newTemp(Ity_V128);
12948ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      IRTemp zeros   = newTemp(Ity_V128);
12949ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      DIP("vcmpbfp%s v%d,v%d,v%d\n", (flag_rC ? ".":""),
12950ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                     vD_addr, vA_addr, vB_addr);
12951ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      cmp_bounds = True;
12952ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      assign( zeros,   unop(Iop_Dup32x4, mkU32(0)) );
12953ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
12954ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* Note: making use of fact that the ppc backend for compare insns
12955ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return zero'd lanes if either of the corresponding arg lanes is
12956ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         a nan.
12957ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
12958ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         Perhaps better to have an irop Iop_isNan32Fx4, but then we'd
12959ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         need this for the other compares too (vcmpeqfp etc)...
12960ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         Better still, tighten down the spec for compare irops.
12961ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown       */
12962ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      assign( gt, unop(Iop_NotV128,
12963ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                       binop(Iop_CmpLE32Fx4, mkexpr(vA), mkexpr(vB))) );
12964ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      assign( lt, unop(Iop_NotV128,
12965ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                       binop(Iop_CmpGE32Fx4, mkexpr(vA),
12966ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                             binop(Iop_Sub32Fx4, mkexpr(zeros),
12967ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                                 mkexpr(vB)))) );
12968ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
12969ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      // finally, just shift gt,lt to correct position
12970ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      assign( vD, binop(Iop_ShlN32x4,
12971ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                        binop(Iop_OrV128,
12972ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                              binop(Iop_AndV128, mkexpr(gt),
12973ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                    unop(Iop_Dup32x4, mkU32(0x2))),
12974ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                              binop(Iop_AndV128, mkexpr(lt),
12975ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                    unop(Iop_Dup32x4, mkU32(0x1)))),
12976ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                        mkU8(30)) );
12977ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      break;
12978ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
12979ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
12980ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   default:
12981ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      vex_printf("dis_av_fp_cmp(ppc)(opc2)\n");
12982ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      return False;
12983ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
12984ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
12985ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   putVReg( vD_addr, mkexpr(vD) );
12986ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
12987ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (flag_rC) {
12988ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      set_AV_CR6( mkexpr(vD), !cmp_bounds );
12989ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
12990ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   return True;
12991ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
12992ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
12993ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*
12994ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  AltiVec Floating Point Convert/Round Instructions
12995ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown*/
12996ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic Bool dis_av_fp_convert ( UInt theInstr )
12997ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
12998ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* VX-Form */
12999ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   UChar opc1     = ifieldOPC(theInstr);
13000ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   UChar vD_addr  = ifieldRegDS(theInstr);
13001ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   UChar UIMM_5   = ifieldRegA(theInstr);
13002ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   UChar vB_addr  = ifieldRegB(theInstr);
13003ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   UInt  opc2     = IFIELD( theInstr, 0, 11 );
13004ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
13005ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   IRTemp vB        = newTemp(Ity_V128);
13006ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   IRTemp vScale    = newTemp(Ity_V128);
13007ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   IRTemp vInvScale = newTemp(Ity_V128);
13008ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
13009ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   float scale, inv_scale;
13010ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
13011ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   assign( vB, getVReg(vB_addr));
13012ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
13013ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* scale = 2^UIMM, cast to float, reinterpreted as uint */
13014ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   scale = (float)( (unsigned int) 1<<UIMM_5 );
13015ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   assign( vScale, unop(Iop_Dup32x4, mkU32( float_to_bits(scale) )) );
13016ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   inv_scale = 1/scale;
13017ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   assign( vInvScale,
13018ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown           unop(Iop_Dup32x4, mkU32( float_to_bits(inv_scale) )) );
13019ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
13020ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (opc1 != 0x4) {
13021ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      vex_printf("dis_av_fp_convert(ppc)(instr)\n");
13022ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      return False;
13023ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
13024ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
13025ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   switch (opc2) {
13026ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   case 0x30A: // vcfux (Convert from Unsigned Fixed-Point W, AV p156)
13027ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      DIP("vcfux v%d,v%d,%d\n", vD_addr, vB_addr, UIMM_5);
13028ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      putVReg( vD_addr, binop(Iop_Mul32Fx4,
13029ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                              unop(Iop_I32UtoFx4, mkexpr(vB)),
13030ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                              mkexpr(vInvScale)) );
13031ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      return True;
13032ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
13033ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   case 0x34A: // vcfsx (Convert from Signed Fixed-Point W, AV p155)
13034ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      DIP("vcfsx v%d,v%d,%d\n", vD_addr, vB_addr, UIMM_5);
13035ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
13036ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      putVReg( vD_addr, binop(Iop_Mul32Fx4,
13037ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                              unop(Iop_I32StoFx4, mkexpr(vB)),
13038ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                              mkexpr(vInvScale)) );
13039ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      return True;
13040ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
13041ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   case 0x38A: // vctuxs (Convert to Unsigned Fixed-Point W Saturate, AV p172)
13042ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      DIP("vctuxs v%d,v%d,%d\n", vD_addr, vB_addr, UIMM_5);
13043ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      putVReg( vD_addr,
13044ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               unop(Iop_QFtoI32Ux4_RZ,
13045ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                    binop(Iop_Mul32Fx4, mkexpr(vB), mkexpr(vScale))) );
13046ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      return True;
13047ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
13048ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   case 0x3CA: // vctsxs (Convert to Signed Fixed-Point W Saturate, AV p171)
13049ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      DIP("vctsxs v%d,v%d,%d\n", vD_addr, vB_addr, UIMM_5);
13050ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      putVReg( vD_addr,
13051ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               unop(Iop_QFtoI32Sx4_RZ,
13052ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                     binop(Iop_Mul32Fx4, mkexpr(vB), mkexpr(vScale))) );
13053ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      return True;
13054ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
13055ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   default:
13056ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     break;    // Fall through...
13057ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
13058ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
13059ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (UIMM_5 != 0) {
13060ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      vex_printf("dis_av_fp_convert(ppc)(UIMM_5)\n");
13061ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      return False;
13062ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
13063ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
13064ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   switch (opc2) {
13065ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   case 0x20A: // vrfin (Round to FP Integer Nearest, AV p231)
13066ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      DIP("vrfin v%d,v%d\n", vD_addr, vB_addr);
13067ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      putVReg( vD_addr, unop(Iop_RoundF32x4_RN, mkexpr(vB)) );
13068ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      break;
13069ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
13070ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   case 0x24A: // vrfiz (Round to FP Integer toward zero, AV p233)
13071ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      DIP("vrfiz v%d,v%d\n", vD_addr, vB_addr);
13072ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      putVReg( vD_addr, unop(Iop_RoundF32x4_RZ, mkexpr(vB)) );
13073ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      break;
13074ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
13075ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   case 0x28A: // vrfip (Round to FP Integer toward +inf, AV p232)
13076ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      DIP("vrfip v%d,v%d\n", vD_addr, vB_addr);
13077ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      putVReg( vD_addr, unop(Iop_RoundF32x4_RP, mkexpr(vB)) );
13078ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      break;
13079ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
13080ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   case 0x2CA: // vrfim (Round to FP Integer toward -inf, AV p230)
13081ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      DIP("vrfim v%d,v%d\n", vD_addr, vB_addr);
13082ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      putVReg( vD_addr, unop(Iop_RoundF32x4_RM, mkexpr(vB)) );
13083ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      break;
13084ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
13085ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   default:
13086ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      vex_printf("dis_av_fp_convert(ppc)(opc2)\n");
13087ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      return False;
13088ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
13089ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   return True;
13090ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
13091ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
13092ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
13093b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov/* The 0x3C primary opcode (VSX category) uses several different forms of
13094b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov * extended opcodes:
13095b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov *   o XX2-form:
13096b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov *      - [10:2] (IBM notation [21:29])
13097b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov *   o XX3-form variants:
13098b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov *       - variant 1: [10:3] (IBM notation [21:28])
13099b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov *       - variant 2: [9:3] (IBM notation [22:28])
13100b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov *       - variant 3: [7:3] (IBM notation [24:28])
13101b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov *   o XX-4 form:
13102b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov *      - [10:6] (IBM notation [21:25])
13103b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov *
13104b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov * The XX2-form needs bit 0 masked from the standard extended opcode
13105b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov * as returned by ifieldOPClo10; the XX3-form needs bits 0 and 1 masked;
13106b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov * and the XX4-form needs bits 0, 1, and 2 masked.  Additionally, the
13107b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov * XX4 and XX3 (variants 2 and 3) forms need certain bits masked on the
13108b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov * front end since their encoding does not begin at bit 21 like the standard
13109b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov * format.
13110b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov *
13111b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov * The get_VSX60_opc2() function uses the vsx_insn array below to obtain the
13112b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov * secondary opcode for such VSX instructions.
13113b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov *
13114b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov*/
13115b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
13116b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
13117b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanovstruct vsx_insn {
13118b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   UInt opcode;
13119b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   Char * name;
13120b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov};
13121b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
13122b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov//  ATTENTION:  Keep this array sorted on the opcocde!!!
13123b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanovstatic struct vsx_insn vsx_all[] = {
13124b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      { 0x8, "xxsldwi" },
13125b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      { 0x18, "xxsel" },
13126b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      { 0x28, "xxpermdi" },
13127b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      { 0x48, "xxmrghw" },
13128b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      { 0x80, "xsadddp" },
13129b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      { 0x84, "xsmaddadp" },
13130b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      { 0x8c, "xscmpudp" },
13131b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      { 0x90, "xscvdpuxws" },
13132b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      { 0x92, "xsrdpi" },
13133b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      { 0x94, "xsrsqrtedp" },
13134b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      { 0x96, "xssqrtdp" },
13135b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      { 0xa0, "xssubdp" },
13136b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      { 0xa4, "xsmaddmdp" },
13137b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      { 0xac, "xscmpodp" },
13138b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      { 0xb0, "xscvdpsxws" },
13139b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      { 0xb2, "xsrdpiz" },
13140b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      { 0xb4, "xsredp" },
13141b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      { 0xc0, "xsmuldp" },
13142b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      { 0xc4, "xsmsubadp" },
13143b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      { 0xc8, "xxmrglw" },
13144b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      { 0xd2, "xsrdpip" },
13145b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      { 0xd4, "xstsqrtdp" },
13146b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      { 0xd6, "xsrdpic" },
13147b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      { 0xe0, "xsdivdp" },
13148b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      { 0xe4, "xsmsubmdp" },
13149b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      { 0xf2, "xsrdpim" },
13150b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      { 0xf4, "xstdivdp" },
13151b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      { 0x100, "xvaddsp" },
13152b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      { 0x104, "xvmaddasp" },
13153b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      { 0x10c, "xvcmpeqsp" },
13154b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      { 0x110, "xvcvspuxws" },
13155b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      { 0x112, "xvrspi" },
13156b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      { 0x114, "xvrsqrtesp" },
13157b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      { 0x116, "xvsqrtsp" },
13158b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      { 0x120, "xvsubsp" },
13159b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      { 0x124, "xvmaddmsp" },
13160b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      { 0x12c, "xvcmpgtsp" },
13161b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      { 0x130, "xvcvspsxws" },
13162b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      { 0x132, "xvrspiz" },
13163b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      { 0x134, "xvresp" },
13164b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      { 0x140, "xvmulsp" },
13165b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      { 0x144, "xvmsubasp" },
13166b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      { 0x148, "xxspltw" },
13167b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      { 0x14c, "xvcmpgesp" },
13168b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      { 0x150, "xvcvuxwsp" },
13169b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      { 0x152, "xvrspip" },
13170b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      { 0x154, "xvtsqrtsp" },
13171b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      { 0x156, "xvrspic" },
13172b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      { 0x160, "xvdivsp" },
13173b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      { 0x164, "xvmsubmsp" },
13174b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      { 0x170, "xvcvsxwsp" },
13175b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      { 0x172, "xvrspim" },
13176b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      { 0x174, "xvtdivsp" },
13177b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      { 0x180, "xvadddp" },
13178b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      { 0x184, "xvmaddadp" },
13179b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      { 0x18c, "xvcmpeqdp" },
13180b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      { 0x190, "xvcvdpuxws" },
13181b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      { 0x192, "xvrdpi" },
13182b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      { 0x194, "xvrsqrtedp" },
13183b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      { 0x196, "xvsqrtdp" },
13184b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      { 0x1a0, "xvsubdp" },
13185b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      { 0x1a4, "xvmaddmdp" },
13186b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      { 0x1ac, "xvcmpgtdp" },
13187b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      { 0x1b0, "xvcvdpsxws" },
13188b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      { 0x1b2, "xvrdpiz" },
13189b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      { 0x1b4, "xvredp" },
13190b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      { 0x1c0, "xvmuldp" },
13191b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      { 0x1c4, "xvmsubadp" },
13192b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      { 0x1cc, "xvcmpgedp" },
13193b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      { 0x1d0, "xvcvuxwdp" },
13194b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      { 0x1d2, "xvrdpip" },
13195b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      { 0x1d4, "xvtsqrtdp" },
13196b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      { 0x1d6, "xvrdpic" },
13197b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      { 0x1e0, "xvdivdp" },
13198b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      { 0x1e4, "xvmsubmdp" },
13199b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      { 0x1f0, "xvcvsxwdp" },
13200b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      { 0x1f2, "xvrdpim" },
13201b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      { 0x1f4, "xvtdivdp" },
13202b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      { 0x208, "xxland" },
13203b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      { 0x212, "xscvdpsp" },
13204b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      { 0x228, "xxlandc" },
13205b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      { 0x248 , "xxlor" },
13206b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      { 0x268, "xxlxor" },
13207b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      { 0x280, "xsmaxdp" },
13208b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      { 0x284, "xsnmaddadp" },
13209b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      { 0x288, "xxlnor" },
13210b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      { 0x290, "xscvdpuxds" },
13211b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      { 0x292, "xscvspdp" },
13212b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      { 0x2a0, "xsmindp" },
13213b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      { 0x2a4, "xsnmaddmdp" },
13214b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      { 0x2b0, "xscvdpsxds" },
13215b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      { 0x2b2, "xsabsdp" },
13216b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      { 0x2c0, "xscpsgndp" },
13217b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      { 0x2c4, "xsnmsubadp" },
13218b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      { 0x2d0, "xscvuxddp" },
13219b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      { 0x2d2, "xsnabsdp" },
13220b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      { 0x2e4, "xsnmsubmdp" },
13221b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      { 0x2f0, "xscvsxddp" },
13222b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      { 0x2f2, "xsnegdp" },
13223b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      { 0x300, "xvmaxsp" },
13224b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      { 0x304, "xvnmaddasp" },
13225b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      { 0x30c, "xvcmpeqsp." },
13226b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      { 0x310, "xvcvspuxds" },
13227b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      { 0x312, "xvcvdpsp" },
13228b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      { 0x320, "xvminsp" },
13229b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      { 0x324, "xvnmaddmsp" },
13230b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      { 0x32c, "xvcmpgtsp." },
13231b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      { 0x330, "xvcvspsxds" },
13232b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      { 0x332, "xvabssp" },
13233b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      { 0x340, "xvcpsgnsp" },
13234b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      { 0x344, "xvnmsubasp" },
13235b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      { 0x34c, "xvcmpgesp." },
13236b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      { 0x350, "xvcvuxdsp" },
13237b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      { 0x352, "xvnabssp" },
13238b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      { 0x364, "xvnmsubmsp" },
13239b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      { 0x370, "xvcvsxdsp" },
13240b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      { 0x372, "xvnegsp" },
13241b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      { 0x380, "xvmaxdp" },
13242b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      { 0x384, "xvnmaddadp" },
13243b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      { 0x38c, "xvcmpeqdp." },
13244b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      { 0x390, "xvcvdpuxds" },
13245b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      { 0x392, "xvcvspdp" },
13246b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      { 0x3a0, "xvmindp" },
13247b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      { 0x3a4, "xvnmaddmdp" },
13248b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      { 0x3ac, "xvcmpgtdp." },
13249b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      { 0x3b0, "xvcvdpsxds" },
13250b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      { 0x3b2, "xvabsdp" },
13251b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      { 0x3c0, "xvcpsgndp" },
13252b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      { 0x3c4, "xvnmsubadp" },
13253b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      { 0x3cc, "xvcmpgedp." },
13254b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      { 0x3d0, "xvcvuxddp" },
13255b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      { 0x3d2, "xvnabsdp" },
13256b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      { 0x3e4, "xvnmsubmdp" },
13257b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      { 0x3f0, "xvcvsxddp" },
13258b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      { 0x3f2, "xvnegdp" }
13259b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov};
13260b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov#define VSX_ALL_LEN 135
13261b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
13262b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov// ATTENTION: This search function assumes vsx_all array is sorted.
13263b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanovstatic Int findVSXextOpCode(UInt opcode)
13264b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov{
13265b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   Int low, mid, high;
13266b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   low = 0;
13267b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   high = VSX_ALL_LEN - 1;
13268b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   while (low <= high) {
13269b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      mid = (low + high)/2;
13270b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      if (opcode < vsx_all[mid].opcode)
13271b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         high = mid - 1;
13272b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      else if (opcode > vsx_all[mid].opcode)
13273b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         low = mid + 1;
13274b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      else
13275b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         return mid;
13276b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   }
13277b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   return -1;
13278b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov}
13279b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
13280b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
13281b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov/* The full 10-bit extended opcode retrieved via ifieldOPClo10 is
13282b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov * passed, and we then try to match it up with one of the VSX forms
13283b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov * below.
13284b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov */
13285b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanovstatic UInt get_VSX60_opc2(UInt opc2_full)
13286b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov{
13287b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov#define XX2_MASK 0x000003FE
13288b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov#define XX3_1_MASK 0x000003FC
13289b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov#define XX3_2_MASK 0x000001FC
13290b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov#define XX3_3_MASK 0x0000007C
13291b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov#define XX4_MASK 0x00000018
13292b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   Int ret;
13293b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   UInt vsxExtOpcode = 0;
132948f943afc22a6a683b78271836c8ddc462b4824a9Evgeniy Stepanov
13295b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   if (( ret = findVSXextOpCode(opc2_full & XX2_MASK)) >= 0)
13296b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      vsxExtOpcode = vsx_all[ret].opcode;
13297b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   else if (( ret = findVSXextOpCode(opc2_full & XX3_1_MASK)) >= 0)
13298b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      vsxExtOpcode = vsx_all[ret].opcode;
13299b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   else if (( ret = findVSXextOpCode(opc2_full & XX3_2_MASK)) >= 0)
13300b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      vsxExtOpcode = vsx_all[ret].opcode;
13301b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   else if (( ret = findVSXextOpCode(opc2_full & XX3_3_MASK)) >= 0)
13302b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      vsxExtOpcode = vsx_all[ret].opcode;
13303b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   else if (( ret = findVSXextOpCode(opc2_full & XX4_MASK)) >= 0)
13304b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      vsxExtOpcode = vsx_all[ret].opcode;
133058f943afc22a6a683b78271836c8ddc462b4824a9Evgeniy Stepanov
13306b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   return vsxExtOpcode;
13307b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov}
13308ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
13309ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*------------------------------------------------------------*/
13310ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*--- Disassemble a single instruction                     ---*/
13311ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*------------------------------------------------------------*/
13312ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
13313ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* Disassemble a single instruction into IR.  The instruction
13314ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   is located in host memory at &guest_code[delta]. */
13315ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
13316ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic
13317ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownDisResult disInstr_PPC_WRK (
13318ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown             Bool         put_IP,
13319ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown             Bool         (*resteerOkFn) ( /*opaque*/void*, Addr64 ),
13320ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown             Bool         resteerCisOk,
13321ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown             void*        callback_opaque,
13322ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown             Long         delta64,
13323ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown             VexArchInfo* archinfo,
13324ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown             VexAbiInfo*  abiinfo
13325ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown          )
13326ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
13327ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   UChar     opc1;
13328ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   UInt      opc2;
13329ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   DisResult dres;
13330ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   UInt      theInstr;
13331ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   IRType    ty = mode64 ? Ity_I64 : Ity_I32;
13332ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   Bool      allow_F  = False;
13333ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   Bool      allow_V  = False;
13334ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   Bool      allow_FX = False;
13335ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   Bool      allow_GX = False;
13336b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   Bool      allow_VX = False;  // Equates to "supports Power ISA 2.06
13337ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   UInt      hwcaps = archinfo->hwcaps;
13338ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   Long      delta;
13339ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
13340ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* What insn variants are we supporting today? */
13341ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (mode64) {
13342ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      allow_F  = True;
13343ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      allow_V  = (0 != (hwcaps & VEX_HWCAPS_PPC64_V));
13344ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      allow_FX = (0 != (hwcaps & VEX_HWCAPS_PPC64_FX));
13345ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      allow_GX = (0 != (hwcaps & VEX_HWCAPS_PPC64_GX));
13346b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      allow_VX = (0 != (hwcaps & VEX_HWCAPS_PPC64_VX));
13347ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   } else {
13348ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      allow_F  = (0 != (hwcaps & VEX_HWCAPS_PPC32_F));
13349ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      allow_V  = (0 != (hwcaps & VEX_HWCAPS_PPC32_V));
13350ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      allow_FX = (0 != (hwcaps & VEX_HWCAPS_PPC32_FX));
13351ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      allow_GX = (0 != (hwcaps & VEX_HWCAPS_PPC32_GX));
13352b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      allow_VX = (0 != (hwcaps & VEX_HWCAPS_PPC32_VX));
13353ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
13354ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
13355ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* The running delta */
13356ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   delta = (Long)mkSzAddr(ty, (ULong)delta64);
13357ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
13358ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* Set result defaults. */
13359ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   dres.whatNext   = Dis_Continue;
13360ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   dres.len        = 0;
13361ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   dres.continueAt = 0;
13362ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
13363ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* At least this is simple on PPC32: insns are all 4 bytes long, and
13364ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      4-aligned.  So just fish the whole thing out of memory right now
13365ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      and have done. */
13366ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   theInstr = getUIntBigendianly( (UChar*)(&guest_code[delta]) );
13367ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
13368ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (0) vex_printf("insn: 0x%x\n", theInstr);
13369ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
13370ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   DIP("\t0x%llx:  ", (ULong)guest_CIA_curr_instr);
13371ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
13372ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* We may be asked to update the guest CIA before going further. */
13373ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (put_IP)
13374ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      putGST( PPC_GST_CIA, mkSzImm(ty, guest_CIA_curr_instr) );
13375ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
13376ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* Spot "Special" instructions (see comment at top of file). */
13377ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   {
13378ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      UChar* code = (UChar*)(guest_code + delta);
13379ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* Spot the 16-byte preamble:
13380ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         32-bit mode:
13381ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            54001800  rlwinm 0,0,3,0,0
13382ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            54006800  rlwinm 0,0,13,0,0
13383ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            5400E800  rlwinm 0,0,29,0,0
13384ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            54009800  rlwinm 0,0,19,0,0
13385ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         64-bit mode:
13386ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            78001800  rotldi 0,0,3
13387ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            78006800  rotldi 0,0,13
13388ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            7800E802  rotldi 0,0,61
13389ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            78009802  rotldi 0,0,51
13390ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      */
13391ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      UInt word1 = mode64 ? 0x78001800 : 0x54001800;
13392ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      UInt word2 = mode64 ? 0x78006800 : 0x54006800;
13393ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      UInt word3 = mode64 ? 0x7800E802 : 0x5400E800;
13394ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      UInt word4 = mode64 ? 0x78009802 : 0x54009800;
13395ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (getUIntBigendianly(code+ 0) == word1 &&
13396ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown          getUIntBigendianly(code+ 4) == word2 &&
13397ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown          getUIntBigendianly(code+ 8) == word3 &&
13398ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown          getUIntBigendianly(code+12) == word4) {
13399ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         /* Got a "Special" instruction preamble.  Which one is it? */
13400ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         if (getUIntBigendianly(code+16) == 0x7C210B78 /* or 1,1,1 */) {
13401ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            /* %R3 = client_request ( %R4 ) */
13402ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            DIP("r3 = client_request ( %%r4 )\n");
13403ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            delta += 20;
13404ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            irsb->next     = mkSzImm( ty, guest_CIA_bbstart + delta );
13405ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            irsb->jumpkind = Ijk_ClientReq;
13406ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            dres.whatNext  = Dis_StopHere;
13407ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            goto decode_success;
13408ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         }
13409ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         else
13410ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         if (getUIntBigendianly(code+16) == 0x7C421378 /* or 2,2,2 */) {
13411ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            /* %R3 = guest_NRADDR */
13412ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            DIP("r3 = guest_NRADDR\n");
13413ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            delta += 20;
13414ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            dres.len = 20;
13415ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            putIReg(3, IRExpr_Get( OFFB_NRADDR, ty ));
13416ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            goto decode_success;
13417ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         }
13418ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         else
13419ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         if (getUIntBigendianly(code+16) == 0x7C631B78 /* or 3,3,3 */) {
13420ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            /*  branch-and-link-to-noredir %R11 */
13421ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            DIP("branch-and-link-to-noredir r11\n");
13422ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            delta += 20;
13423ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            putGST( PPC_GST_LR, mkSzImm(ty, guest_CIA_bbstart + (Long)delta) );
13424ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            irsb->next     = getIReg(11);
13425ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            irsb->jumpkind = Ijk_NoRedir;
13426ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            dres.whatNext  = Dis_StopHere;
13427ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            goto decode_success;
13428ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         }
13429ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         else
13430ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         if (getUIntBigendianly(code+16) == 0x7C842378 /* or 4,4,4 */) {
13431ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            /* %R3 = guest_NRADDR_GPR2 */
13432ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            DIP("r3 = guest_NRADDR_GPR2\n");
13433ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            delta += 20;
13434ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            dres.len = 20;
13435ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            putIReg(3, IRExpr_Get( OFFB_NRADDR_GPR2, ty ));
13436ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            goto decode_success;
13437ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         }
13438ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         /* We don't know what it is.  Set opc1/opc2 so decode_failure
13439ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            can print the insn following the Special-insn preamble. */
13440ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         theInstr = getUIntBigendianly(code+16);
13441ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         opc1     = ifieldOPC(theInstr);
13442ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         opc2     = ifieldOPClo10(theInstr);
13443ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         goto decode_failure;
13444ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         /*NOTREACHED*/
13445ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
13446ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
13447ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
13448ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   opc1 = ifieldOPC(theInstr);
13449ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   opc2 = ifieldOPClo10(theInstr);
13450ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
13451ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   // Note: all 'reserved' bits must be cleared, else invalid
13452ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   switch (opc1) {
13453ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
13454ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* Integer Arithmetic Instructions */
13455ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   case 0x0C: case 0x0D: case 0x0E:  // addic, addic., addi
13456ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   case 0x0F: case 0x07: case 0x08:  // addis, mulli,  subfic
13457ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (dis_int_arith( theInstr )) goto decode_success;
13458ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      goto decode_failure;
13459ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
13460ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* Integer Compare Instructions */
13461ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   case 0x0B: case 0x0A: // cmpi, cmpli
13462ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (dis_int_cmp( theInstr )) goto decode_success;
13463ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      goto decode_failure;
13464ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
13465ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* Integer Logical Instructions */
13466ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   case 0x1C: case 0x1D: case 0x18: // andi., andis., ori
13467ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   case 0x19: case 0x1A: case 0x1B: // oris,  xori,   xoris
13468ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (dis_int_logic( theInstr )) goto decode_success;
13469ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      goto decode_failure;
13470ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
13471ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* Integer Rotate Instructions */
13472ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   case 0x14: case 0x15:  case 0x17: // rlwimi, rlwinm, rlwnm
13473ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (dis_int_rot( theInstr )) goto decode_success;
13474ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      goto decode_failure;
13475ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
13476ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* 64bit Integer Rotate Instructions */
13477ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   case 0x1E: // rldcl, rldcr, rldic, rldicl, rldicr, rldimi
13478ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (dis_int_rot( theInstr )) goto decode_success;
13479ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      goto decode_failure;
13480ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
13481ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* Integer Load Instructions */
13482ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   case 0x22: case 0x23: case 0x2A: // lbz,  lbzu, lha
13483ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   case 0x2B: case 0x28: case 0x29: // lhau, lhz,  lhzu
13484ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   case 0x20: case 0x21:            // lwz,  lwzu
13485ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (dis_int_load( theInstr )) goto decode_success;
13486ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      goto decode_failure;
13487ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
13488ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* Integer Store Instructions */
13489ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   case 0x26: case 0x27: case 0x2C: // stb,  stbu, sth
13490ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   case 0x2D: case 0x24: case 0x25: // sthu, stw,  stwu
13491ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (dis_int_store( theInstr, abiinfo )) goto decode_success;
13492ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      goto decode_failure;
13493ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
13494ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* Integer Load and Store Multiple Instructions */
13495ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   case 0x2E: case 0x2F: // lmw, stmw
13496ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (dis_int_ldst_mult( theInstr )) goto decode_success;
13497ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      goto decode_failure;
13498ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
13499ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* Branch Instructions */
13500ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   case 0x12: case 0x10: // b, bc
13501ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (dis_branch(theInstr, abiinfo, &dres,
13502ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                               resteerOkFn, callback_opaque))
13503ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         goto decode_success;
13504ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      goto decode_failure;
13505ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
13506ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* System Linkage Instructions */
13507ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   case 0x11: // sc
13508ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (dis_syslink(theInstr, abiinfo, &dres)) goto decode_success;
13509ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      goto decode_failure;
13510ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
13511ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* Trap Instructions */
13512ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   case 0x02: case 0x03: // tdi, twi
13513ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (dis_trapi(theInstr, &dres)) goto decode_success;
13514ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      goto decode_failure;
13515ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
13516ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* Floating Point Load Instructions */
13517ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   case 0x30: case 0x31: case 0x32: // lfs, lfsu, lfd
13518ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   case 0x33:                       // lfdu
13519ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (!allow_F) goto decode_noF;
13520ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (dis_fp_load( theInstr )) goto decode_success;
13521ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      goto decode_failure;
13522ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
13523ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* Floating Point Store Instructions */
13524ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   case 0x34: case 0x35: case 0x36: // stfsx, stfsux, stfdx
13525ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   case 0x37:                       // stfdux
13526ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (!allow_F) goto decode_noF;
13527ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (dis_fp_store( theInstr )) goto decode_success;
13528ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      goto decode_failure;
13529ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
13530ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* Floating Point Load Double Pair Instructions */
13531ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   case 0x39: case 0x3D:
13532ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (!allow_F) goto decode_noF;
13533ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (dis_fp_pair( theInstr )) goto decode_success;
13534ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      goto decode_failure;
13535ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
13536ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* 64bit Integer Loads */
13537ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   case 0x3A:  // ld, ldu, lwa
13538ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (!mode64) goto decode_failure;
13539ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (dis_int_load( theInstr )) goto decode_success;
13540ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      goto decode_failure;
13541ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
13542ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   case 0x3B:
13543ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (!allow_F) goto decode_noF;
13544b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      opc2 = ifieldOPClo10(theInstr);
13545b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      switch (opc2) {
13546b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         case 0x3CE: // fcfidus (implemented as native insn)
13547b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov            if (!allow_VX)
13548b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov               goto decode_noVX;
13549b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov            if (dis_fp_round( theInstr ))
13550b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov               goto decode_success;
13551b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov            goto decode_failure;
13552b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         case 0x34E: // fcfids
13553b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov            if (dis_fp_round( theInstr ))
13554b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov               goto decode_success;
13555b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov            goto decode_failure;
13556b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      }
13557b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
13558ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      opc2 = IFIELD(theInstr, 1, 5);
13559ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      switch (opc2) {
13560ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* Floating Point Arith Instructions */
13561ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case 0x12: case 0x14: case 0x15: // fdivs,  fsubs, fadds
13562ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case 0x19:                       // fmuls
13563ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         if (dis_fp_arith(theInstr)) goto decode_success;
13564ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         goto decode_failure;
13565ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case 0x16:                       // fsqrts
13566ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         if (!allow_FX) goto decode_noFX;
13567ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         if (dis_fp_arith(theInstr)) goto decode_success;
13568ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         goto decode_failure;
13569ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case 0x18:                       // fres
13570ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         if (!allow_GX) goto decode_noGX;
13571ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         if (dis_fp_arith(theInstr)) goto decode_success;
13572ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         goto decode_failure;
13573ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
13574ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* Floating Point Mult-Add Instructions */
13575ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case 0x1C: case 0x1D: case 0x1E: // fmsubs, fmadds, fnmsubs
13576ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case 0x1F:                       // fnmadds
13577ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         if (dis_fp_multadd(theInstr)) goto decode_success;
13578ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         goto decode_failure;
13579ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
13580ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case 0x1A:                       // frsqrtes
13581ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         if (!allow_GX) goto decode_noGX;
13582ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         if (dis_fp_arith(theInstr)) goto decode_success;
13583ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         goto decode_failure;
13584b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
13585ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      default:
13586ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         goto decode_failure;
13587ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
13588ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      break;
13589ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
13590b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   case 0x3C: // VSX instructions (except load/store)
13591b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   {
13592b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      UInt vsxOpc2 = get_VSX60_opc2(opc2);
13593b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      /* The vsxOpc2 returned is the "normalized" value, representing the
13594b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov       * instructions secondary opcode as taken from the standard secondary
13595b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov       * opcode field [21:30] (IBM notatition), even if the actual field
13596b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov       * is non-standard.  These normalized values are given in the opcode
13597b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov       * appendices of the ISA 2.06 document.
13598b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov       */
13599b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      if (vsxOpc2 == 0)
13600b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         goto decode_failure;
13601b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
13602b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      switch (vsxOpc2) {
13603b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         case 0x8: case 0x28: case 0x48: case 0xc8: // xxsldwi, xxpermdi, xxmrghw, xxmrglw
13604b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         case 0x018: case 0x148: // xxsel, xxspltw
13605b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov            if (dis_vx_permute_misc(theInstr, vsxOpc2)) goto decode_success;
13606b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov            goto decode_failure;
13607b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         case 0x268: case 0x248: case 0x288: case 0x208: case 0x228: // xxlxor, xxlor, xxlnor, xxland, xxlandc
13608b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov            if (dis_vx_logic(theInstr, vsxOpc2)) goto decode_success;
13609b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov            goto decode_failure;
13610b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         case 0x2B2: case 0x2C0: // xsabsdp, xscpsgndp
13611b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         case 0x2D2: case 0x2F2: // xsnabsdp, xsnegdp
13612b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         case 0x280: case 0x2A0: // xsmaxdp, xsmindp
13613b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         case 0x0F2: case 0x0D2: // xsrdpim, xsrdpip
13614b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         case 0x0B4: case 0x094: // xsredp, xsrsqrtedp
13615b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         case 0x0D6: case 0x0B2: // xsrdpic, xsrdpiz
13616b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         case 0x092: // xsrdpi
13617b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov            if (dis_vxs_misc(theInstr, vsxOpc2)) goto decode_success;
13618b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov            goto decode_failure;
13619b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         case 0x08C: case 0x0AC: // xscmpudp, xscmpodp
13620b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov            if (dis_vx_cmp(theInstr, vsxOpc2)) goto decode_success;
13621b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov            goto decode_failure;
13622b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         case 0x080: case 0x0E0: // xsadddp, xsdivdp
13623b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         case 0x084: case 0x0A4: // xsmaddadp, xsmaddmdp
13624b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         case 0x0C4: case 0x0E4: // xsmsubadp, xsmsubmdp
13625b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         case 0x284: case 0x2A4: // xsnmaddadp, xsnmaddmdp
13626b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         case 0x2C4: case 0x2E4: // xsnmsubadp, xsnmsubmdp
13627b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         case 0x0C0: case 0x0A0: // xsmuldp, xssubdp
13628b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         case 0x096: case 0x0F4: // xssqrtdp, xstdivdp
13629b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         case 0x0D4: // xstsqrtdp
13630b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov            if (dis_vxs_arith(theInstr, vsxOpc2)) goto decode_success;
13631b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov            goto decode_failure;
13632b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         case 0x180: // xvadddp
13633b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         case 0x1E0: // xvdivdp
13634b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         case 0x1C0: // xvmuldp
13635b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         case 0x1A0: // xvsubdp
13636b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         case 0x184: case 0x1A4: // xvmaddadp, xvmaddmdp
13637b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         case 0x1C4: case 0x1E4: // xvmsubadp, xvmsubmdp
13638b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         case 0x384: case 0x3A4: // xvnmaddadp, xvnmaddmdp
13639b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         case 0x3C4: case 0x3E4: // xvnmsubadp, xvnmsubmdp
13640b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         case 0x1D4: case 0x1F4: // xvtsqrtdp, xvtdivdp
13641b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         case 0x196: // xvsqrtdp
13642b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov            if (dis_vxv_dp_arith(theInstr, vsxOpc2)) goto decode_success;
13643b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov            goto decode_failure;
13644b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         case 0x100: // xvaddsp
13645b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         case 0x160: // xvdivsp
13646b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         case 0x140: // xvmulsp
13647b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         case 0x120: // xvsubsp
13648b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         case 0x104: case 0x124: // xvmaddasp, xvmaddmsp
13649b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         case 0x144: case 0x164: // xvmsubasp, xvmsubmsp
13650b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         case 0x304: case 0x324: // xvnmaddasp, xvnmaddmsp
13651b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         case 0x344: case 0x364: // xvnmsubasp, xvnmsubmsp
13652b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         case 0x154: case 0x174: // xvtsqrtsp, xvtdivsp
13653b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         case 0x116: // xvsqrtsp
13654b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov            if (dis_vxv_sp_arith(theInstr, vsxOpc2)) goto decode_success;
13655b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov            goto decode_failure;
13656b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
13657b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         case 0x2B0: case 0x2F0: case 0x2D0: // xscvdpsxds, xscvsxddp, xscvuxddp
13658b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         case 0x1b0: case 0x130: // xvcvdpsxws, xvcvspsxws
13659b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         case 0x0b0: case 0x290: // xscvdpsxws, xscvdpuxds
13660b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         case 0x212: case 0x090: // xscvdpsp, xscvdpuxws
13661b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         case 0x292: case 0x312: // xscvspdp, xvcvdpsp
13662b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         case 0x390: case 0x190: // xvcvdpuxds, xvcvdpuxws
13663b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         case 0x3B0: case 0x310: // xvcvdpsxds, xvcvspuxds
13664b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         case 0x392: case 0x330: // xvcvspdp, xvcvspsxds
13665b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         case 0x110: case 0x3f0: // xvcvspuxws, xvcvsxddp
13666b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         case 0x370: case 0x1f0: // xvcvsxdsp, xvcvsxwdp
13667b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         case 0x170: case 0x150: // xvcvsxwsp, xvcvuxwsp
13668b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         case 0x3d0: case 0x350: // xvcvuxddp, xvcvuxdsp
13669b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         case 0x1d0: // xvcvuxwdp
13670b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov            if (dis_vx_conv(theInstr, vsxOpc2)) goto decode_success;
13671b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov            goto decode_failure;
13672b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
13673b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         case 0x18C: case 0x38C: // xvcmpeqdp[.]
13674b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         case 0x10C: case 0x30C: // xvcmpeqsp[.]
13675b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         case 0x14C: case 0x34C: // xvcmpgesp[.]
13676b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         case 0x12C: case 0x32C: // xvcmpgtsp[.]
13677b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         case 0x1CC: case 0x3CC: // xvcmpgedp[.]
13678b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         case 0x1AC: case 0x3AC: // xvcmpgtdp[.]
13679b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov             if (dis_vvec_cmp(theInstr, vsxOpc2)) goto decode_success;
13680b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov             goto decode_failure;
13681b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
13682b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         case 0x134:  // xvresp
13683b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         case 0x1B4:  // xvredp
13684b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         case 0x194: case 0x114: // xvrsqrtedp, xvrsqrtesp
13685b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         case 0x380: case 0x3A0: // xvmaxdp, xvmindp
13686b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         case 0x300: case 0x320: // xvmaxsp, xvminsp
13687b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         case 0x3C0: case 0x340: // xvcpsgndp, xvcpsgnsp
13688b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         case 0x3B2: case 0x332: // xvabsdp, xvabssp
13689b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         case 0x3D2: case 0x352: // xvnabsdp, xvnabssp
13690b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         case 0x192: case 0x1D6: // xvrdpi, xvrdpic
13691b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         case 0x1F2: case 0x1D2: // xvrdpim, xvrdpip
13692b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         case 0x1B2: case 0x3F2: // xvrdpiz, xvnegdp
13693b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         case 0x112: case 0x156: // xvrspi, xvrspic
13694b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         case 0x172: case 0x152: // xvrspim, xvrspip
13695b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         case 0x132: // xvrspiz
13696b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov            if (dis_vxv_misc(theInstr, vsxOpc2)) goto decode_success;
13697b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov            goto decode_failure;
13698b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
13699b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         default:
13700b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov            goto decode_failure;
13701b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      }
13702b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      break;
13703b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   }
13704b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
13705ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* 64bit Integer Stores */
13706ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   case 0x3E:  // std, stdu
13707ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (!mode64) goto decode_failure;
13708ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (dis_int_store( theInstr, abiinfo )) goto decode_success;
13709ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      goto decode_failure;
13710ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
13711ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   case 0x3F:
13712ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (!allow_F) goto decode_noF;
13713ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* Instrs using opc[1:5] never overlap instrs using opc[1:10],
13714ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         so we can simply fall through the first switch statement */
13715ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
13716ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      opc2 = IFIELD(theInstr, 1, 5);
13717ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      switch (opc2) {
13718ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* Floating Point Arith Instructions */
13719ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case 0x12: case 0x14: case 0x15: // fdiv, fsub, fadd
13720ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case 0x19:                       // fmul
13721ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         if (dis_fp_arith(theInstr)) goto decode_success;
13722ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         goto decode_failure;
13723ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case 0x16:                       // fsqrt
13724ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         if (!allow_FX) goto decode_noFX;
13725ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         if (dis_fp_arith(theInstr)) goto decode_success;
13726ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         goto decode_failure;
13727ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case 0x17: case 0x1A:            // fsel, frsqrte
13728ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         if (!allow_GX) goto decode_noGX;
13729ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         if (dis_fp_arith(theInstr)) goto decode_success;
13730ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         goto decode_failure;
13731ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
13732ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* Floating Point Mult-Add Instructions */
13733ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case 0x1C: case 0x1D: case 0x1E: // fmsub, fmadd, fnmsub
13734ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case 0x1F:                       // fnmadd
13735ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         if (dis_fp_multadd(theInstr)) goto decode_success;
13736ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         goto decode_failure;
13737ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
13738ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case 0x18:                       // fre
13739ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         if (!allow_GX) goto decode_noGX;
13740ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         if (dis_fp_arith(theInstr)) goto decode_success;
13741ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         goto decode_failure;
13742ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
13743ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      default:
13744ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         break; // Fall through
13745ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
13746ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
13747ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      opc2 = IFIELD(theInstr, 1, 10);
13748ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      switch (opc2) {
13749ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* Floating Point Compare Instructions */
13750ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case 0x000: // fcmpu
13751ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case 0x020: // fcmpo
13752ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         if (dis_fp_cmp(theInstr)) goto decode_success;
13753ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         goto decode_failure;
13754ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
13755b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      case 0x080: // ftdiv
13756b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      case 0x0A0: // ftsqrt
13757b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         if (dis_fp_tests(theInstr)) goto decode_success;
13758b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         goto decode_failure;
13759b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
13760ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* Floating Point Rounding/Conversion Instructions */
13761ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case 0x00C: // frsp
13762ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case 0x00E: // fctiw
13763ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case 0x00F: // fctiwz
13764ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case 0x32E: // fctid
13765ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case 0x32F: // fctidz
13766ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case 0x34E: // fcfid
13767ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         if (dis_fp_round(theInstr)) goto decode_success;
13768ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         goto decode_failure;
13769b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      case 0x3CE: case 0x3AE: case 0x3AF: // fcfidu, fctidu[z] (implemented as native insns)
13770b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      case 0x08F: case 0x08E: // fctiwu[z] (implemented as native insns)
13771b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         if (!allow_VX) goto decode_noVX;
13772b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         if (dis_fp_round(theInstr)) goto decode_success;
13773b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         goto decode_failure;
13774ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
13775ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* Power6 rounding stuff */
13776ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case 0x1E8: // frim
13777ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case 0x1C8: // frip
13778ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case 0x188: // frin
13779ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case 0x1A8: // friz
13780ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         /* A hack to check for P6 capability . . . */
13781ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         if ((allow_F && allow_V && allow_FX && allow_GX) &&
13782ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown             (dis_fp_round(theInstr)))
13783ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            goto decode_success;
13784ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         goto decode_failure;
13785ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
13786ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* Floating Point Move Instructions */
13787ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case 0x008: // fcpsgn
13788ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case 0x028: // fneg
13789ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case 0x048: // fmr
13790ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case 0x088: // fnabs
13791ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case 0x108: // fabs
13792ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         if (dis_fp_move( theInstr )) goto decode_success;
13793ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         goto decode_failure;
13794ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
13795ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* Floating Point Status/Control Register Instructions */
13796ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case 0x026: // mtfsb1
13797ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case 0x040: // mcrfs
13798ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case 0x046: // mtfsb0
13799ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case 0x086: // mtfsfi
13800ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case 0x247: // mffs
13801ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case 0x2C7: // mtfsf
13802ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         if (dis_fp_scr( theInstr )) goto decode_success;
13803ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         goto decode_failure;
13804ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
13805ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      default:
13806ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         goto decode_failure;
13807ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
13808ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      break;
13809ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
13810ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   case 0x13:
13811ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      switch (opc2) {
13812ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
13813ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* Condition Register Logical Instructions */
13814ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case 0x101: case 0x081: case 0x121: // crand,  crandc, creqv
13815ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case 0x0E1: case 0x021: case 0x1C1: // crnand, crnor,  cror
13816ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case 0x1A1: case 0x0C1: case 0x000: // crorc,  crxor,  mcrf
13817ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         if (dis_cond_logic( theInstr )) goto decode_success;
13818ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         goto decode_failure;
13819ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
13820ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* Branch Instructions */
13821ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case 0x210: case 0x010: // bcctr, bclr
13822ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         if (dis_branch(theInstr, abiinfo, &dres,
13823ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                  resteerOkFn, callback_opaque))
13824ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            goto decode_success;
13825ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         goto decode_failure;
13826ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
13827ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* Memory Synchronization Instructions */
13828ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case 0x096: // isync
13829ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         if (dis_memsync( theInstr )) goto decode_success;
13830ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         goto decode_failure;
13831ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
13832ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      default:
13833ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         goto decode_failure;
13834ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
13835ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      break;
13836ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
13837ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
13838ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   case 0x1F:
13839ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
13840ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* For arith instns, bit10 is the OE flag (overflow enable) */
13841ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
13842ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      opc2 = IFIELD(theInstr, 1, 9);
13843ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      switch (opc2) {
13844ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* Integer Arithmetic Instructions */
13845ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case 0x10A: case 0x00A: case 0x08A: // add,   addc,  adde
13846ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case 0x0EA: case 0x0CA: case 0x1EB: // addme, addze, divw
13847ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case 0x1CB: case 0x04B: case 0x00B: // divwu, mulhw, mulhwu
13848ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case 0x0EB: case 0x068: case 0x028: // mullw, neg,   subf
13849ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case 0x008: case 0x088: case 0x0E8: // subfc, subfe, subfme
13850b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      case 0x0C8: // subfze
13851b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         if (dis_int_arith( theInstr )) goto decode_success;
13852b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         goto decode_failure;
13853b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
13854b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      case 0x18B: // divweu (implemented as native insn)
13855b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      case 0x1AB: // divwe (implemented as native insn)
13856b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         if (!allow_VX) goto decode_noVX;
13857ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         if (dis_int_arith( theInstr )) goto decode_success;
13858ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         goto decode_failure;
13859ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
13860ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* 64bit Integer Arithmetic */
13861ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case 0x009: case 0x049: case 0x0E9: // mulhdu, mulhd, mulld
13862b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      case 0x1C9: case 0x1E9: // divdu, divd
13863b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         if (!mode64) goto decode_failure;
13864b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         if (dis_int_arith( theInstr )) goto decode_success;
13865b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         goto decode_failure;
13866b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
13867b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      case 0x1A9: //  divde (implemented as native insn)
13868b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      case 0x189: //  divdeuo (implemented as native insn)
13869b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         if (!allow_VX) goto decode_noVX;
13870ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         if (!mode64) goto decode_failure;
13871ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         if (dis_int_arith( theInstr )) goto decode_success;
13872ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         goto decode_failure;
13873ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
13874ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case 0x1FC:                         // cmpb
13875ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         if (dis_int_logic( theInstr )) goto decode_success;
13876ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         goto decode_failure;
13877ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
13878ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      default:
13879ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         break;  // Fall through...
13880ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
13881ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
13882ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* All remaining opcodes use full 10 bits. */
13883ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
13884ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      opc2 = IFIELD(theInstr, 1, 10);
13885ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      switch (opc2) {
13886ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* Integer Compare Instructions  */
13887ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case 0x000: case 0x020: // cmp, cmpl
13888ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         if (dis_int_cmp( theInstr )) goto decode_success;
13889ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         goto decode_failure;
13890ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
13891ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* Integer Logical Instructions */
13892ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case 0x01C: case 0x03C: case 0x01A: // and,  andc,  cntlzw
13893ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case 0x11C: case 0x3BA: case 0x39A: // eqv,  extsb, extsh
13894ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case 0x1DC: case 0x07C: case 0x1BC: // nand, nor,   or
13895ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case 0x19C: case 0x13C:             // orc,  xor
13896ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case 0x2DF: case 0x25F:            // mftgpr, mffgpr
13897ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         if (dis_int_logic( theInstr )) goto decode_success;
13898ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         goto decode_failure;
13899ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
13900ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* 64bit Integer Logical Instructions */
13901ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case 0x3DA: case 0x03A: // extsw, cntlzd
13902ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         if (!mode64) goto decode_failure;
13903ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         if (dis_int_logic( theInstr )) goto decode_success;
13904ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         goto decode_failure;
13905ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
13906ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         /* 64bit Integer Parity Instructions */
13907ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case 0xba: case 0x9a: // prtyd, prtyw
13908ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         if (dis_int_parity( theInstr )) goto decode_success;
13909ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         goto decode_failure;
13910ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
13911ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* Integer Shift Instructions */
13912ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case 0x018: case 0x318: case 0x338: // slw, sraw, srawi
13913ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case 0x218:                         // srw
13914ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         if (dis_int_shift( theInstr )) goto decode_success;
13915ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         goto decode_failure;
13916ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
13917ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* 64bit Integer Shift Instructions */
13918ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case 0x01B: case 0x31A: // sld, srad
13919ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case 0x33A: case 0x33B: // sradi
13920ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case 0x21B:             // srd
13921ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         if (!mode64) goto decode_failure;
13922ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         if (dis_int_shift( theInstr )) goto decode_success;
13923ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         goto decode_failure;
13924ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
13925ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* Integer Load Instructions */
13926ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case 0x057: case 0x077: case 0x157: // lbzx,  lbzux, lhax
13927ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case 0x177: case 0x117: case 0x137: // lhaux, lhzx,  lhzux
13928ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case 0x017: case 0x037:             // lwzx,  lwzux
13929ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         if (dis_int_load( theInstr )) goto decode_success;
13930ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         goto decode_failure;
13931ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
13932ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* 64bit Integer Load Instructions */
13933ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case 0x035: case 0x015:             // ldux,  ldx
13934ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case 0x175: case 0x155:             // lwaux, lwax
13935ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         if (!mode64) goto decode_failure;
13936ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         if (dis_int_load( theInstr )) goto decode_success;
13937ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         goto decode_failure;
13938ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
13939ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* Integer Store Instructions */
13940ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case 0x0F7: case 0x0D7: case 0x1B7: // stbux, stbx,  sthux
13941ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case 0x197: case 0x0B7: case 0x097: // sthx,  stwux, stwx
13942ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         if (dis_int_store( theInstr, abiinfo )) goto decode_success;
13943ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         goto decode_failure;
13944ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
13945ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* 64bit Integer Store Instructions */
13946ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case 0x0B5: case 0x095: // stdux, stdx
13947ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         if (!mode64) goto decode_failure;
13948ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         if (dis_int_store( theInstr, abiinfo )) goto decode_success;
13949ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         goto decode_failure;
13950ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
13951ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* Integer Load and Store with Byte Reverse Instructions */
13952ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case 0x316: case 0x216: case 0x396: // lhbrx, lwbrx, sthbrx
13953b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      case 0x296: case 0x214:             // stwbrx, ldbrx
13954b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      case 0x294:                         // stdbrx
13955ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         if (dis_int_ldst_rev( theInstr )) goto decode_success;
13956ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         goto decode_failure;
13957ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
13958ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* Integer Load and Store String Instructions */
13959ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case 0x255: case 0x215: case 0x2D5: // lswi, lswx, stswi
13960ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case 0x295: {                       // stswx
13961ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         Bool stopHere = False;
13962ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         Bool ok = dis_int_ldst_str( theInstr, &stopHere );
13963ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         if (!ok) goto decode_failure;
13964ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         if (stopHere) {
13965ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            irsb->next     = mkSzImm(ty, nextInsnAddr());
13966ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            irsb->jumpkind = Ijk_Boring;
13967ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            dres.whatNext  = Dis_StopHere;
13968ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         }
13969ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         goto decode_success;
13970ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
13971ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
13972ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* Memory Synchronization Instructions */
13973ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case 0x356: case 0x014: case 0x096: // eieio, lwarx, stwcx.
13974ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case 0x256:                         // sync
13975ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         if (dis_memsync( theInstr )) goto decode_success;
13976ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         goto decode_failure;
13977ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
13978ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* 64bit Memory Synchronization Instructions */
13979ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case 0x054: case 0x0D6: // ldarx, stdcx.
13980ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         if (!mode64) goto decode_failure;
13981ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         if (dis_memsync( theInstr )) goto decode_success;
13982ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         goto decode_failure;
13983ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
13984ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* Processor Control Instructions */
13985ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case 0x200: case 0x013: case 0x153: // mcrxr, mfcr,  mfspr
13986ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case 0x173: case 0x090: case 0x1D3: // mftb,  mtcrf, mtspr
13987ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         if (dis_proc_ctl( abiinfo, theInstr )) goto decode_success;
13988ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         goto decode_failure;
13989ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
13990ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* Cache Management Instructions */
13991ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case 0x2F6: case 0x056: case 0x036: // dcba, dcbf,   dcbst
13992ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case 0x116: case 0x0F6: case 0x3F6: // dcbt, dcbtst, dcbz
13993ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case 0x3D6:                         // icbi
13994ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         if (dis_cache_manage( theInstr, &dres, archinfo ))
13995ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            goto decode_success;
13996ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         goto decode_failure;
13997ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
13998ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//zz       /* External Control Instructions */
13999ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//zz       case 0x136: case 0x1B6: // eciwx, ecowx
14000ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//zz          DIP("external control op => not implemented\n");
14001ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//zz          goto decode_failure;
14002ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
14003ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* Trap Instructions */
14004ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case 0x004: case 0x044:             // tw,   td
14005ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         if (dis_trap(theInstr, &dres)) goto decode_success;
14006ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         goto decode_failure;
14007ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
14008ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* Floating Point Load Instructions */
14009ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case 0x217: case 0x237: case 0x257: // lfsx, lfsux, lfdx
14010ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case 0x277:                         // lfdux
14011ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         if (!allow_F) goto decode_noF;
14012ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         if (dis_fp_load( theInstr )) goto decode_success;
14013ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         goto decode_failure;
14014ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
14015ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* Floating Point Store Instructions */
14016ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case 0x297: case 0x2B7: case 0x2D7: // stfs,  stfsu, stfd
14017ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case 0x2F7:                         // stfdu, stfiwx
14018ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         if (!allow_F) goto decode_noF;
14019ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         if (dis_fp_store( theInstr )) goto decode_success;
14020ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         goto decode_failure;
14021ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case 0x3D7:                         // stfiwx
14022ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         if (!allow_F) goto decode_noF;
14023ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         if (!allow_GX) goto decode_noGX;
14024ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         if (dis_fp_store( theInstr )) goto decode_success;
14025ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         goto decode_failure;
14026ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
14027ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         /* Floating Point Double Pair Indexed Instructions */
14028ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case 0x317: // lfdpx (Power6)
14029ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case 0x397: // stfdpx (Power6)
14030ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         if (!allow_F) goto decode_noF;
14031ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         if (dis_fp_pair(theInstr)) goto decode_success;
14032ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         goto decode_failure;
14033ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
14034ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case 0x357:                         // lfiwax
14035ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         if (!allow_F) goto decode_noF;
14036ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         if (dis_fp_load( theInstr )) goto decode_success;
14037ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         goto decode_failure;
14038ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
14039b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      case 0x377:                         // lfiwzx
14040b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         if (!allow_F) goto decode_noF;
14041b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         if (dis_fp_load( theInstr )) goto decode_success;
14042b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         goto decode_failure;
14043b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
14044ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* AltiVec instructions */
14045ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
14046ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* AV Cache Control - Data streams */
14047ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case 0x156: case 0x176: case 0x336: // dst, dstst, dss
14048ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         if (!allow_V) goto decode_noV;
14049ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         if (dis_av_datastream( theInstr )) goto decode_success;
14050ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         goto decode_failure;
14051ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
14052ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* AV Load */
14053ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case 0x006: case 0x026:             // lvsl, lvsr
14054ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case 0x007: case 0x027: case 0x047: // lvebx, lvehx, lvewx
14055ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case 0x067: case 0x167:             // lvx, lvxl
14056ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         if (!allow_V) goto decode_noV;
14057ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         if (dis_av_load( abiinfo, theInstr )) goto decode_success;
14058ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         goto decode_failure;
14059ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
14060ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* AV Store */
14061ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case 0x087: case 0x0A7: case 0x0C7: // stvebx, stvehx, stvewx
14062ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case 0x0E7: case 0x1E7:             // stvx, stvxl
14063ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         if (!allow_V) goto decode_noV;
14064ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         if (dis_av_store( theInstr )) goto decode_success;
14065ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         goto decode_failure;
14066ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
14067b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      /* VSX Load */
14068b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      case 0x24C: // lxsdx
14069b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      case 0x34C: // lxvd2x
14070b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      case 0x14C: // lxvdsx
14071b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      case 0x30C: // lxvw4x
14072b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov    	  if (dis_vx_load( theInstr )) goto decode_success;
14073b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov          goto decode_failure;
14074b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
14075b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      /* VSX Store */
14076b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      case 0x2CC: // stxsdx
14077b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      case 0x3CC: // stxvd2x
14078b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      case 0x38C: // stxvw4x
14079b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov    	  if (dis_vx_store( theInstr )) goto decode_success;
14080b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov    	  goto decode_failure;
14081b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
14082b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      /* Miscellaneous ISA 2.06 instructions */
14083b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      case 0x1FA: // popcntd
14084b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      case 0x17A: // popcntw
14085b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov    	  if (dis_int_logic( theInstr )) goto decode_success;
14086b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov    	  goto decode_failure;
14087b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
14088b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      case 0x0FC: // bpermd
14089b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         if (dis_int_logic( theInstr )) goto decode_success;
14090b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov         goto decode_failure;
14091b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
14092ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      default:
14093ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         /* Deal with some other cases that we would otherwise have
14094ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            punted on. */
14095ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         /* --- ISEL (PowerISA_V2.05.pdf, p74) --- */
14096ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         /* only decode this insn when reserved bit 0 (31 in IBM's
14097ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            notation) is zero */
14098ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         if (IFIELD(theInstr, 0, 6) == (15<<1)) {
14099ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            UInt rT = ifieldRegDS( theInstr );
14100ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            UInt rA = ifieldRegA( theInstr );
14101ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            UInt rB = ifieldRegB( theInstr );
14102ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            UInt bi = ifieldRegC( theInstr );
14103ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            putIReg(
14104ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               rT,
14105ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               IRExpr_Mux0X( unop(Iop_32to8,getCRbit( bi )),
14106ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                             getIReg(rB),
14107ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                             rA == 0 ? (mode64 ? mkU64(0) : mkU32(0))
14108ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                     : getIReg(rA) )
14109ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            );
14110ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            DIP("isel r%u,r%u,r%u,crb%u\n", rT,rA,rB,bi);
14111ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            goto decode_success;
14112ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         }
14113ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         goto decode_failure;
14114ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
14115ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      break;
14116ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
14117ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
14118ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   case 0x04:
14119ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* AltiVec instructions */
14120ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
14121ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      opc2 = IFIELD(theInstr, 0, 6);
14122ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      switch (opc2) {
14123ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* AV Mult-Add, Mult-Sum */
14124ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case 0x20: case 0x21: case 0x22: // vmhaddshs, vmhraddshs, vmladduhm
14125ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case 0x24: case 0x25: case 0x26: // vmsumubm, vmsummbm, vmsumuhm
14126ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case 0x27: case 0x28: case 0x29: // vmsumuhs, vmsumshm, vmsumshs
14127ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         if (!allow_V) goto decode_noV;
14128ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         if (dis_av_multarith( theInstr )) goto decode_success;
14129ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         goto decode_failure;
14130ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
14131ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* AV Permutations */
14132ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case 0x2A:                       // vsel
14133ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case 0x2B:                       // vperm
14134ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case 0x2C:                       // vsldoi
14135ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         if (!allow_V) goto decode_noV;
14136ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         if (dis_av_permute( theInstr )) goto decode_success;
14137ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         goto decode_failure;
14138ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
14139ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* AV Floating Point Mult-Add/Sub */
14140ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case 0x2E: case 0x2F:            // vmaddfp, vnmsubfp
14141ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         if (!allow_V) goto decode_noV;
14142ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         if (dis_av_fp_arith( theInstr )) goto decode_success;
14143ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         goto decode_failure;
14144ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
14145ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      default:
14146ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         break;  // Fall through...
14147ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
14148ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
14149ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      opc2 = IFIELD(theInstr, 0, 11);
14150ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      switch (opc2) {
14151ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* AV Arithmetic */
14152ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case 0x180:                         // vaddcuw
14153ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case 0x000: case 0x040: case 0x080: // vaddubm, vadduhm, vadduwm
14154ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case 0x200: case 0x240: case 0x280: // vaddubs, vadduhs, vadduws
14155ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case 0x300: case 0x340: case 0x380: // vaddsbs, vaddshs, vaddsws
14156ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case 0x580:                         // vsubcuw
14157ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case 0x400: case 0x440: case 0x480: // vsububm, vsubuhm, vsubuwm
14158ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case 0x600: case 0x640: case 0x680: // vsububs, vsubuhs, vsubuws
14159ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case 0x700: case 0x740: case 0x780: // vsubsbs, vsubshs, vsubsws
14160ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case 0x402: case 0x442: case 0x482: // vavgub, vavguh, vavguw
14161ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case 0x502: case 0x542: case 0x582: // vavgsb, vavgsh, vavgsw
14162ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case 0x002: case 0x042: case 0x082: // vmaxub, vmaxuh, vmaxuw
14163ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case 0x102: case 0x142: case 0x182: // vmaxsb, vmaxsh, vmaxsw
14164ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case 0x202: case 0x242: case 0x282: // vminub, vminuh, vminuw
14165ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case 0x302: case 0x342: case 0x382: // vminsb, vminsh, vminsw
14166ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case 0x008: case 0x048:             // vmuloub, vmulouh
14167ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case 0x108: case 0x148:             // vmulosb, vmulosh
14168ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case 0x208: case 0x248:             // vmuleub, vmuleuh
14169ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case 0x308: case 0x348:             // vmulesb, vmulesh
14170ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case 0x608: case 0x708: case 0x648: // vsum4ubs, vsum4sbs, vsum4shs
14171ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case 0x688: case 0x788:             // vsum2sws, vsumsws
14172ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         if (!allow_V) goto decode_noV;
14173ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         if (dis_av_arith( theInstr )) goto decode_success;
14174ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         goto decode_failure;
14175ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
14176ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* AV Rotate, Shift */
14177ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case 0x004: case 0x044: case 0x084: // vrlb, vrlh, vrlw
14178ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case 0x104: case 0x144: case 0x184: // vslb, vslh, vslw
14179ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case 0x204: case 0x244: case 0x284: // vsrb, vsrh, vsrw
14180ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case 0x304: case 0x344: case 0x384: // vsrab, vsrah, vsraw
14181ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case 0x1C4: case 0x2C4:             // vsl, vsr
14182ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case 0x40C: case 0x44C:             // vslo, vsro
14183ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         if (!allow_V) goto decode_noV;
14184ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         if (dis_av_shift( theInstr )) goto decode_success;
14185ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         goto decode_failure;
14186ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
14187ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* AV Logic */
14188ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case 0x404: case 0x444: case 0x484: // vand, vandc, vor
14189ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case 0x4C4: case 0x504:             // vxor, vnor
14190ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         if (!allow_V) goto decode_noV;
14191ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         if (dis_av_logic( theInstr )) goto decode_success;
14192ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         goto decode_failure;
14193ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
14194ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* AV Processor Control */
14195ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case 0x604: case 0x644:             // mfvscr, mtvscr
14196ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         if (!allow_V) goto decode_noV;
14197ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         if (dis_av_procctl( theInstr )) goto decode_success;
14198ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         goto decode_failure;
14199ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
14200ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* AV Floating Point Arithmetic */
14201ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case 0x00A: case 0x04A:             // vaddfp, vsubfp
14202ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case 0x10A: case 0x14A: case 0x18A: // vrefp, vrsqrtefp, vexptefp
14203ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case 0x1CA:                         // vlogefp
14204ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case 0x40A: case 0x44A:             // vmaxfp, vminfp
14205ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         if (!allow_V) goto decode_noV;
14206ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         if (dis_av_fp_arith( theInstr )) goto decode_success;
14207ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         goto decode_failure;
14208ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
14209ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* AV Floating Point Round/Convert */
14210ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case 0x20A: case 0x24A: case 0x28A: // vrfin, vrfiz, vrfip
14211ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case 0x2CA:                         // vrfim
14212ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case 0x30A: case 0x34A: case 0x38A: // vcfux, vcfsx, vctuxs
14213ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case 0x3CA:                         // vctsxs
14214ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         if (!allow_V) goto decode_noV;
14215ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         if (dis_av_fp_convert( theInstr )) goto decode_success;
14216ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         goto decode_failure;
14217ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
14218ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* AV Merge, Splat */
14219ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case 0x00C: case 0x04C: case 0x08C: // vmrghb, vmrghh, vmrghw
14220ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case 0x10C: case 0x14C: case 0x18C: // vmrglb, vmrglh, vmrglw
14221ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case 0x20C: case 0x24C: case 0x28C: // vspltb, vsplth, vspltw
14222ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case 0x30C: case 0x34C: case 0x38C: // vspltisb, vspltish, vspltisw
14223ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         if (!allow_V) goto decode_noV;
14224ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         if (dis_av_permute( theInstr )) goto decode_success;
14225ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         goto decode_failure;
14226ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
14227ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* AV Pack, Unpack */
14228ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case 0x00E: case 0x04E: case 0x08E: // vpkuhum, vpkuwum, vpkuhus
14229ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case 0x0CE:                         // vpkuwus
14230ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case 0x10E: case 0x14E: case 0x18E: // vpkshus, vpkswus, vpkshss
14231ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case 0x1CE:                         // vpkswss
14232ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case 0x20E: case 0x24E: case 0x28E: // vupkhsb, vupkhsh, vupklsb
14233ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case 0x2CE:                         // vupklsh
14234ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case 0x30E: case 0x34E: case 0x3CE: // vpkpx, vupkhpx, vupklpx
14235ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         if (!allow_V) goto decode_noV;
14236ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         if (dis_av_pack( theInstr )) goto decode_success;
14237ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         goto decode_failure;
14238ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
14239ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      default:
14240ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         break;  // Fall through...
14241ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
14242ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
14243ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      opc2 = IFIELD(theInstr, 0, 10);
14244ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      switch (opc2) {
14245ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
14246ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* AV Compare */
14247ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case 0x006: case 0x046: case 0x086: // vcmpequb, vcmpequh, vcmpequw
14248ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case 0x206: case 0x246: case 0x286: // vcmpgtub, vcmpgtuh, vcmpgtuw
14249ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case 0x306: case 0x346: case 0x386: // vcmpgtsb, vcmpgtsh, vcmpgtsw
14250ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         if (!allow_V) goto decode_noV;
14251ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         if (dis_av_cmp( theInstr )) goto decode_success;
14252ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         goto decode_failure;
14253ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
14254ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* AV Floating Point Compare */
14255ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case 0x0C6: case 0x1C6: case 0x2C6: // vcmpeqfp, vcmpgefp, vcmpgtfp
14256ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case 0x3C6:                         // vcmpbfp
14257ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         if (!allow_V) goto decode_noV;
14258ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         if (dis_av_fp_cmp( theInstr )) goto decode_success;
14259ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         goto decode_failure;
14260ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
14261ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      default:
14262ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         goto decode_failure;
14263ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
14264ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      break;
14265ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
14266ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   default:
14267ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      goto decode_failure;
14268ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
14269ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   decode_noF:
14270ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      vassert(!allow_F);
14271ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      vex_printf("disInstr(ppc): declined to decode an FP insn.\n");
14272ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      goto decode_failure;
14273ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   decode_noV:
14274ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      vassert(!allow_V);
14275ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      vex_printf("disInstr(ppc): declined to decode an AltiVec insn.\n");
14276ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      goto decode_failure;
14277b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   decode_noVX:
14278b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      vassert(!allow_VX);
14279b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      vex_printf("disInstr(ppc): declined to decode a Power ISA 2.06 insn.\n");
14280b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov      goto decode_failure;
14281ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   decode_noFX:
14282ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      vassert(!allow_FX);
14283ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      vex_printf("disInstr(ppc): "
14284ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                 "declined to decode a GeneralPurpose-Optional insn.\n");
14285ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      goto decode_failure;
14286ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   decode_noGX:
14287ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      vassert(!allow_GX);
14288ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      vex_printf("disInstr(ppc): "
14289ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                 "declined to decode a Graphics-Optional insn.\n");
14290ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      goto decode_failure;
14291ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
14292ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   decode_failure:
14293ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* All decode failures end up here. */
14294ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   opc2 = (theInstr) & 0x7FF;
14295ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   vex_printf("disInstr(ppc): unhandled instruction: "
14296ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown              "0x%x\n", theInstr);
14297ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   vex_printf("                 primary %d(0x%x), secondary %u(0x%x)\n",
14298ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown              opc1, opc1, opc2, opc2);
14299ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
14300ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* Tell the dispatcher that this insn cannot be decoded, and so has
14301ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      not been executed, and (is currently) the next to be executed.
14302ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      CIA should be up-to-date since it made so at the start of each
14303ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      insn, but nevertheless be paranoid and update it again right
14304ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      now. */
14305ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   putGST( PPC_GST_CIA, mkSzImm(ty, guest_CIA_curr_instr) );
14306ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   irsb->next     = mkSzImm(ty, guest_CIA_curr_instr);
14307ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   irsb->jumpkind = Ijk_NoDecode;
14308ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   dres.whatNext  = Dis_StopHere;
14309ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   dres.len       = 0;
14310ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   return dres;
14311ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
14312ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   } /* switch (opc) for the main (primary) opcode switch. */
14313ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
14314ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  decode_success:
14315ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* All decode successes end up here. */
14316ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   DIP("\n");
14317ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
14318ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (dres.len == 0) {
14319ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      dres.len = 4;
14320ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   } else {
14321ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      vassert(dres.len == 20);
14322ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
14323ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   return dres;
14324ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
14325ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
14326ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#undef DIP
14327ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#undef DIS
14328ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
14329ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
14330ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*------------------------------------------------------------*/
14331ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*--- Top-level fn                                         ---*/
14332ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*------------------------------------------------------------*/
14333ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
14334ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* Disassemble a single instruction into IR.  The instruction
14335ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   is located in host memory at &guest_code[delta]. */
14336ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
14337ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownDisResult disInstr_PPC ( IRSB*        irsb_IN,
14338ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                         Bool         put_IP,
14339ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                         Bool         (*resteerOkFn) ( void*, Addr64 ),
14340ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                         Bool         resteerCisOk,
14341ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                         void*        callback_opaque,
14342ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                         UChar*       guest_code_IN,
14343ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                         Long         delta,
14344ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                         Addr64       guest_IP,
14345ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                         VexArch      guest_arch,
14346ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                         VexArchInfo* archinfo,
14347ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                         VexAbiInfo*  abiinfo,
14348ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                         Bool         host_bigendian_IN )
14349ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
14350ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   IRType     ty;
14351ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   DisResult  dres;
14352ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   UInt       mask32, mask64;
14353ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   UInt hwcaps_guest = archinfo->hwcaps;
14354ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
14355ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   vassert(guest_arch == VexArchPPC32 || guest_arch == VexArchPPC64);
14356ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
14357ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* global -- ick */
14358ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   mode64 = guest_arch == VexArchPPC64;
14359ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   ty = mode64 ? Ity_I64 : Ity_I32;
14360ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
14361ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* do some sanity checks */
14362ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   mask32 = VEX_HWCAPS_PPC32_F | VEX_HWCAPS_PPC32_V
14363b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov            | VEX_HWCAPS_PPC32_FX | VEX_HWCAPS_PPC32_GX | VEX_HWCAPS_PPC32_VX;
14364ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
14365b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   mask64 = VEX_HWCAPS_PPC64_V | VEX_HWCAPS_PPC64_FX
14366b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov		   | VEX_HWCAPS_PPC64_GX | VEX_HWCAPS_PPC64_VX;
14367ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
14368ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (mode64) {
14369ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      vassert((hwcaps_guest & mask32) == 0);
14370ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   } else {
14371ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      vassert((hwcaps_guest & mask64) == 0);
14372ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
14373ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
14374ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* Set globals (see top of this file) */
14375ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   guest_code           = guest_code_IN;
14376ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   irsb                 = irsb_IN;
14377ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   host_is_bigendian    = host_bigendian_IN;
14378ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
14379ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   guest_CIA_curr_instr = mkSzAddr(ty, guest_IP);
14380ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   guest_CIA_bbstart    = mkSzAddr(ty, guest_IP - delta);
14381ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
14382ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   dres = disInstr_PPC_WRK ( put_IP,
14383ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                             resteerOkFn, resteerCisOk, callback_opaque,
14384ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                             delta, archinfo, abiinfo );
14385ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
14386ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   return dres;
14387ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
14388ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
14389ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
14390ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*------------------------------------------------------------*/
14391ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*--- Unused stuff                                         ---*/
14392ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*------------------------------------------------------------*/
14393ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
14394ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown///* A potentially more memcheck-friendly implementation of Clz32, with
14395ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//   the boundary case Clz32(0) = 32, which is what ppc requires. */
14396ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//
14397ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//static IRExpr* /* :: Ity_I32 */ verbose_Clz32 ( IRTemp arg )
14398ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//{
14399ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//   /* Welcome ... to SSA R Us. */
14400ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//   IRTemp n1  = newTemp(Ity_I32);
14401ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//   IRTemp n2  = newTemp(Ity_I32);
14402ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//   IRTemp n3  = newTemp(Ity_I32);
14403ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//   IRTemp n4  = newTemp(Ity_I32);
14404ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//   IRTemp n5  = newTemp(Ity_I32);
14405ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//   IRTemp n6  = newTemp(Ity_I32);
14406ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//   IRTemp n7  = newTemp(Ity_I32);
14407ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//   IRTemp n8  = newTemp(Ity_I32);
14408ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//   IRTemp n9  = newTemp(Ity_I32);
14409ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//   IRTemp n10 = newTemp(Ity_I32);
14410ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//   IRTemp n11 = newTemp(Ity_I32);
14411ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//   IRTemp n12 = newTemp(Ity_I32);
14412ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//
14413ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//   /* First, propagate the most significant 1-bit into all lower
14414ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//      positions in the word. */
14415ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//   /* unsigned int clz ( unsigned int n )
14416ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//      {
14417ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//         n |= (n >> 1);
14418ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//         n |= (n >> 2);
14419ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//         n |= (n >> 4);
14420ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//         n |= (n >> 8);
14421ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//         n |= (n >> 16);
14422ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//         return bitcount(~n);
14423ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//      }
14424ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//   */
14425ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//   assign(n1, mkexpr(arg));
14426ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//   assign(n2, binop(Iop_Or32, mkexpr(n1), binop(Iop_Shr32, mkexpr(n1), mkU8(1))));
14427ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//   assign(n3, binop(Iop_Or32, mkexpr(n2), binop(Iop_Shr32, mkexpr(n2), mkU8(2))));
14428ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//   assign(n4, binop(Iop_Or32, mkexpr(n3), binop(Iop_Shr32, mkexpr(n3), mkU8(4))));
14429ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//   assign(n5, binop(Iop_Or32, mkexpr(n4), binop(Iop_Shr32, mkexpr(n4), mkU8(8))));
14430ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//   assign(n6, binop(Iop_Or32, mkexpr(n5), binop(Iop_Shr32, mkexpr(n5), mkU8(16))));
14431ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//   /* This gives a word of the form 0---01---1.  Now invert it, giving
14432ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//      a word of the form 1---10---0, then do a population-count idiom
14433ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//      (to count the 1s, which is the number of leading zeroes, or 32
14434ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//      if the original word was 0. */
14435ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//   assign(n7, unop(Iop_Not32, mkexpr(n6)));
14436ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//
14437ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//   /* unsigned int bitcount ( unsigned int n )
14438ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//      {
14439ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//         n = n - ((n >> 1) & 0x55555555);
14440ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//         n = (n & 0x33333333) + ((n >> 2) & 0x33333333);
14441ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//         n = (n + (n >> 4)) & 0x0F0F0F0F;
14442ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//         n = n + (n >> 8);
14443ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//         n = (n + (n >> 16)) & 0x3F;
14444ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//         return n;
14445ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//      }
14446ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//   */
14447ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//   assign(n8,
14448ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//          binop(Iop_Sub32,
14449ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//                mkexpr(n7),
14450ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//                binop(Iop_And32,
14451ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//                      binop(Iop_Shr32, mkexpr(n7), mkU8(1)),
14452ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//                      mkU32(0x55555555))));
14453ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//   assign(n9,
14454ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//          binop(Iop_Add32,
14455ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//                binop(Iop_And32, mkexpr(n8), mkU32(0x33333333)),
14456ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//                binop(Iop_And32,
14457ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//                      binop(Iop_Shr32, mkexpr(n8), mkU8(2)),
14458ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//                      mkU32(0x33333333))));
14459ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//   assign(n10,
14460ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//          binop(Iop_And32,
14461ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//                binop(Iop_Add32,
14462ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//                      mkexpr(n9),
14463ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//                      binop(Iop_Shr32, mkexpr(n9), mkU8(4))),
14464ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//                mkU32(0x0F0F0F0F)));
14465ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//   assign(n11,
14466ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//          binop(Iop_Add32,
14467ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//                mkexpr(n10),
14468ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//                binop(Iop_Shr32, mkexpr(n10), mkU8(8))));
14469ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//   assign(n12,
14470ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//          binop(Iop_Add32,
14471ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//                mkexpr(n11),
14472ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//                binop(Iop_Shr32, mkexpr(n11), mkU8(16))));
14473ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//   return
14474ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//      binop(Iop_And32, mkexpr(n12), mkU32(0x3F));
14475ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//}
14476ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
14477ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*--------------------------------------------------------------------*/
14478ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*--- end                                         guest_ppc_toIR.c ---*/
14479ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*--------------------------------------------------------------------*/
14480