blob: 2a4e9b164e8963a6dccad615eda326f053943c92 [file] [log] [blame]
cerionbcf8c3e2005-02-04 16:17:07 +00001
2/*---------------------------------------------------------------*/
sewardj752f9062010-05-03 21:38:49 +00003/*--- begin host_ppc_defs.c ---*/
cerionbcf8c3e2005-02-04 16:17:07 +00004/*---------------------------------------------------------------*/
5
6/*
sewardj752f9062010-05-03 21:38:49 +00007 This file is part of Valgrind, a dynamic binary instrumentation
8 framework.
cerionbcf8c3e2005-02-04 16:17:07 +00009
sewardj89ae8472013-10-18 14:12:58 +000010 Copyright (C) 2004-2013 OpenWorks LLP
sewardj752f9062010-05-03 21:38:49 +000011 info@open-works.net
cerionbcf8c3e2005-02-04 16:17:07 +000012
sewardj752f9062010-05-03 21:38:49 +000013 This program is free software; you can redistribute it and/or
14 modify it under the terms of the GNU General Public License as
15 published by the Free Software Foundation; either version 2 of the
16 License, or (at your option) any later version.
cerionbcf8c3e2005-02-04 16:17:07 +000017
sewardj752f9062010-05-03 21:38:49 +000018 This program is distributed in the hope that it will be useful, but
19 WITHOUT ANY WARRANTY; without even the implied warranty of
20 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
21 General Public License for more details.
22
23 You should have received a copy of the GNU General Public License
24 along with this program; if not, write to the Free Software
25 Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
sewardj7bd6ffe2005-08-03 16:07:36 +000026 02110-1301, USA.
27
sewardj752f9062010-05-03 21:38:49 +000028 The GNU General Public License is contained in the file COPYING.
cerionbcf8c3e2005-02-04 16:17:07 +000029
30 Neither the names of the U.S. Department of Energy nor the
31 University of California nor the names of its contributors may be
32 used to endorse or promote products derived from this software
33 without prior written permission.
cerionbcf8c3e2005-02-04 16:17:07 +000034*/
35
36#include "libvex_basictypes.h"
37#include "libvex.h"
38#include "libvex_trc_values.h"
39
sewardjcef7d3e2009-07-02 12:21:59 +000040#include "main_util.h"
41#include "host_generic_regs.h"
42#include "host_ppc_defs.h"
cerionbcf8c3e2005-02-04 16:17:07 +000043
44
45/* --------- Registers. --------- */
46
cerion5b2325f2005-12-23 00:55:09 +000047void ppHRegPPC ( HReg reg )
cerioncd304492005-02-08 19:40:24 +000048{
49 Int r;
florian55085f82012-11-21 00:36:55 +000050 static const HChar* ireg32_names[32]
cerion5b2325f2005-12-23 00:55:09 +000051 = { "%r0", "%r1", "%r2", "%r3",
52 "%r4", "%r5", "%r6", "%r7",
53 "%r8", "%r9", "%r10", "%r11",
54 "%r12", "%r13", "%r14", "%r15",
55 "%r16", "%r17", "%r18", "%r19",
56 "%r20", "%r21", "%r22", "%r23",
57 "%r24", "%r25", "%r26", "%r27",
58 "%r28", "%r29", "%r30", "%r31" };
cerioncd304492005-02-08 19:40:24 +000059 /* Be generic for all virtual regs. */
60 if (hregIsVirtual(reg)) {
61 ppHReg(reg);
62 return;
63 }
64 /* But specific for real regs. */
65 switch (hregClass(reg)) {
cerionf0de28c2005-12-13 20:21:11 +000066 case HRcInt64:
67 r = hregNumber(reg);
68 vassert(r >= 0 && r < 32);
69 vex_printf("%s", ireg32_names[r]);
70 return;
cerionb85e8bb2005-02-16 08:54:33 +000071 case HRcInt32:
72 r = hregNumber(reg);
73 vassert(r >= 0 && r < 32);
74 vex_printf("%s", ireg32_names[r]);
75 return;
76 case HRcFlt64:
77 r = hregNumber(reg);
cerion094d1392005-06-20 13:45:57 +000078 vassert(r >= 0 && r < 32);
79 vex_printf("%%fr%d", r);
cerionb85e8bb2005-02-16 08:54:33 +000080 return;
cerionc3d8bdc2005-06-28 18:06:23 +000081 case HRcVec128:
82 r = hregNumber(reg);
83 vassert(r >= 0 && r < 32);
84 vex_printf("%%v%d", r);
85 return;
cerionb85e8bb2005-02-16 08:54:33 +000086 default:
cerion5b2325f2005-12-23 00:55:09 +000087 vpanic("ppHRegPPC");
cerioncd304492005-02-08 19:40:24 +000088 }
cerionbcf8c3e2005-02-04 16:17:07 +000089}
90
cerionf0de28c2005-12-13 20:21:11 +000091
92#define MkHRegGPR(_n, _mode64) \
93 mkHReg(_n, _mode64 ? HRcInt64 : HRcInt32, False)
94
95HReg hregPPC_GPR0 ( Bool mode64 ) { return MkHRegGPR( 0, mode64); }
96HReg hregPPC_GPR1 ( Bool mode64 ) { return MkHRegGPR( 1, mode64); }
97HReg hregPPC_GPR2 ( Bool mode64 ) { return MkHRegGPR( 2, mode64); }
98HReg hregPPC_GPR3 ( Bool mode64 ) { return MkHRegGPR( 3, mode64); }
99HReg hregPPC_GPR4 ( Bool mode64 ) { return MkHRegGPR( 4, mode64); }
100HReg hregPPC_GPR5 ( Bool mode64 ) { return MkHRegGPR( 5, mode64); }
101HReg hregPPC_GPR6 ( Bool mode64 ) { return MkHRegGPR( 6, mode64); }
102HReg hregPPC_GPR7 ( Bool mode64 ) { return MkHRegGPR( 7, mode64); }
103HReg hregPPC_GPR8 ( Bool mode64 ) { return MkHRegGPR( 8, mode64); }
104HReg hregPPC_GPR9 ( Bool mode64 ) { return MkHRegGPR( 9, mode64); }
105HReg hregPPC_GPR10 ( Bool mode64 ) { return MkHRegGPR(10, mode64); }
106HReg hregPPC_GPR11 ( Bool mode64 ) { return MkHRegGPR(11, mode64); }
107HReg hregPPC_GPR12 ( Bool mode64 ) { return MkHRegGPR(12, mode64); }
108HReg hregPPC_GPR13 ( Bool mode64 ) { return MkHRegGPR(13, mode64); }
109HReg hregPPC_GPR14 ( Bool mode64 ) { return MkHRegGPR(14, mode64); }
110HReg hregPPC_GPR15 ( Bool mode64 ) { return MkHRegGPR(15, mode64); }
111HReg hregPPC_GPR16 ( Bool mode64 ) { return MkHRegGPR(16, mode64); }
112HReg hregPPC_GPR17 ( Bool mode64 ) { return MkHRegGPR(17, mode64); }
113HReg hregPPC_GPR18 ( Bool mode64 ) { return MkHRegGPR(18, mode64); }
114HReg hregPPC_GPR19 ( Bool mode64 ) { return MkHRegGPR(19, mode64); }
115HReg hregPPC_GPR20 ( Bool mode64 ) { return MkHRegGPR(20, mode64); }
116HReg hregPPC_GPR21 ( Bool mode64 ) { return MkHRegGPR(21, mode64); }
117HReg hregPPC_GPR22 ( Bool mode64 ) { return MkHRegGPR(22, mode64); }
118HReg hregPPC_GPR23 ( Bool mode64 ) { return MkHRegGPR(23, mode64); }
119HReg hregPPC_GPR24 ( Bool mode64 ) { return MkHRegGPR(24, mode64); }
120HReg hregPPC_GPR25 ( Bool mode64 ) { return MkHRegGPR(25, mode64); }
121HReg hregPPC_GPR26 ( Bool mode64 ) { return MkHRegGPR(26, mode64); }
122HReg hregPPC_GPR27 ( Bool mode64 ) { return MkHRegGPR(27, mode64); }
123HReg hregPPC_GPR28 ( Bool mode64 ) { return MkHRegGPR(28, mode64); }
124HReg hregPPC_GPR29 ( Bool mode64 ) { return MkHRegGPR(29, mode64); }
125HReg hregPPC_GPR30 ( Bool mode64 ) { return MkHRegGPR(30, mode64); }
126HReg hregPPC_GPR31 ( Bool mode64 ) { return MkHRegGPR(31, mode64); }
127
128#undef MK_INT_HREG
cerioncd304492005-02-08 19:40:24 +0000129
cerion5b2325f2005-12-23 00:55:09 +0000130HReg hregPPC_FPR0 ( void ) { return mkHReg( 0, HRcFlt64, False); }
131HReg hregPPC_FPR1 ( void ) { return mkHReg( 1, HRcFlt64, False); }
132HReg hregPPC_FPR2 ( void ) { return mkHReg( 2, HRcFlt64, False); }
133HReg hregPPC_FPR3 ( void ) { return mkHReg( 3, HRcFlt64, False); }
134HReg hregPPC_FPR4 ( void ) { return mkHReg( 4, HRcFlt64, False); }
135HReg hregPPC_FPR5 ( void ) { return mkHReg( 5, HRcFlt64, False); }
136HReg hregPPC_FPR6 ( void ) { return mkHReg( 6, HRcFlt64, False); }
137HReg hregPPC_FPR7 ( void ) { return mkHReg( 7, HRcFlt64, False); }
138HReg hregPPC_FPR8 ( void ) { return mkHReg( 8, HRcFlt64, False); }
139HReg hregPPC_FPR9 ( void ) { return mkHReg( 9, HRcFlt64, False); }
140HReg hregPPC_FPR10 ( void ) { return mkHReg(10, HRcFlt64, False); }
141HReg hregPPC_FPR11 ( void ) { return mkHReg(11, HRcFlt64, False); }
142HReg hregPPC_FPR12 ( void ) { return mkHReg(12, HRcFlt64, False); }
143HReg hregPPC_FPR13 ( void ) { return mkHReg(13, HRcFlt64, False); }
144HReg hregPPC_FPR14 ( void ) { return mkHReg(14, HRcFlt64, False); }
145HReg hregPPC_FPR15 ( void ) { return mkHReg(15, HRcFlt64, False); }
146HReg hregPPC_FPR16 ( void ) { return mkHReg(16, HRcFlt64, False); }
147HReg hregPPC_FPR17 ( void ) { return mkHReg(17, HRcFlt64, False); }
148HReg hregPPC_FPR18 ( void ) { return mkHReg(18, HRcFlt64, False); }
149HReg hregPPC_FPR19 ( void ) { return mkHReg(19, HRcFlt64, False); }
150HReg hregPPC_FPR20 ( void ) { return mkHReg(20, HRcFlt64, False); }
151HReg hregPPC_FPR21 ( void ) { return mkHReg(21, HRcFlt64, False); }
152HReg hregPPC_FPR22 ( void ) { return mkHReg(22, HRcFlt64, False); }
153HReg hregPPC_FPR23 ( void ) { return mkHReg(23, HRcFlt64, False); }
154HReg hregPPC_FPR24 ( void ) { return mkHReg(24, HRcFlt64, False); }
155HReg hregPPC_FPR25 ( void ) { return mkHReg(25, HRcFlt64, False); }
156HReg hregPPC_FPR26 ( void ) { return mkHReg(26, HRcFlt64, False); }
157HReg hregPPC_FPR27 ( void ) { return mkHReg(27, HRcFlt64, False); }
158HReg hregPPC_FPR28 ( void ) { return mkHReg(28, HRcFlt64, False); }
159HReg hregPPC_FPR29 ( void ) { return mkHReg(29, HRcFlt64, False); }
160HReg hregPPC_FPR30 ( void ) { return mkHReg(30, HRcFlt64, False); }
161HReg hregPPC_FPR31 ( void ) { return mkHReg(31, HRcFlt64, False); }
cerionbcf8c3e2005-02-04 16:17:07 +0000162
cerion5b2325f2005-12-23 00:55:09 +0000163HReg hregPPC_VR0 ( void ) { return mkHReg( 0, HRcVec128, False); }
164HReg hregPPC_VR1 ( void ) { return mkHReg( 1, HRcVec128, False); }
165HReg hregPPC_VR2 ( void ) { return mkHReg( 2, HRcVec128, False); }
166HReg hregPPC_VR3 ( void ) { return mkHReg( 3, HRcVec128, False); }
167HReg hregPPC_VR4 ( void ) { return mkHReg( 4, HRcVec128, False); }
168HReg hregPPC_VR5 ( void ) { return mkHReg( 5, HRcVec128, False); }
169HReg hregPPC_VR6 ( void ) { return mkHReg( 6, HRcVec128, False); }
170HReg hregPPC_VR7 ( void ) { return mkHReg( 7, HRcVec128, False); }
171HReg hregPPC_VR8 ( void ) { return mkHReg( 8, HRcVec128, False); }
172HReg hregPPC_VR9 ( void ) { return mkHReg( 9, HRcVec128, False); }
173HReg hregPPC_VR10 ( void ) { return mkHReg(10, HRcVec128, False); }
174HReg hregPPC_VR11 ( void ) { return mkHReg(11, HRcVec128, False); }
175HReg hregPPC_VR12 ( void ) { return mkHReg(12, HRcVec128, False); }
176HReg hregPPC_VR13 ( void ) { return mkHReg(13, HRcVec128, False); }
177HReg hregPPC_VR14 ( void ) { return mkHReg(14, HRcVec128, False); }
178HReg hregPPC_VR15 ( void ) { return mkHReg(15, HRcVec128, False); }
179HReg hregPPC_VR16 ( void ) { return mkHReg(16, HRcVec128, False); }
180HReg hregPPC_VR17 ( void ) { return mkHReg(17, HRcVec128, False); }
181HReg hregPPC_VR18 ( void ) { return mkHReg(18, HRcVec128, False); }
182HReg hregPPC_VR19 ( void ) { return mkHReg(19, HRcVec128, False); }
183HReg hregPPC_VR20 ( void ) { return mkHReg(20, HRcVec128, False); }
184HReg hregPPC_VR21 ( void ) { return mkHReg(21, HRcVec128, False); }
185HReg hregPPC_VR22 ( void ) { return mkHReg(22, HRcVec128, False); }
186HReg hregPPC_VR23 ( void ) { return mkHReg(23, HRcVec128, False); }
187HReg hregPPC_VR24 ( void ) { return mkHReg(24, HRcVec128, False); }
188HReg hregPPC_VR25 ( void ) { return mkHReg(25, HRcVec128, False); }
189HReg hregPPC_VR26 ( void ) { return mkHReg(26, HRcVec128, False); }
190HReg hregPPC_VR27 ( void ) { return mkHReg(27, HRcVec128, False); }
191HReg hregPPC_VR28 ( void ) { return mkHReg(28, HRcVec128, False); }
192HReg hregPPC_VR29 ( void ) { return mkHReg(29, HRcVec128, False); }
193HReg hregPPC_VR30 ( void ) { return mkHReg(30, HRcVec128, False); }
194HReg hregPPC_VR31 ( void ) { return mkHReg(31, HRcVec128, False); }
cerionc3d8bdc2005-06-28 18:06:23 +0000195
cerion5b2325f2005-12-23 00:55:09 +0000196void getAllocableRegs_PPC ( Int* nregs, HReg** arr, Bool mode64 )
cerioncd304492005-02-08 19:40:24 +0000197{
cerionc3d8bdc2005-06-28 18:06:23 +0000198 UInt i=0;
cerionf0de28c2005-12-13 20:21:11 +0000199 if (mode64)
sewardjf7745052005-12-16 01:06:42 +0000200 *nregs = (32-9) + (32-24) + (32-24);
cerionf0de28c2005-12-13 20:21:11 +0000201 else
sewardjf7745052005-12-16 01:06:42 +0000202 *nregs = (32-7) + (32-24) + (32-24);
cerioncd304492005-02-08 19:40:24 +0000203 *arr = LibVEX_Alloc(*nregs * sizeof(HReg));
cerion5b2325f2005-12-23 00:55:09 +0000204 // GPR0 = scratch reg where poss. - some ops interpret as value zero
cerion2c49e032005-02-09 17:29:49 +0000205 // GPR1 = stack pointer
206 // GPR2 = TOC pointer
cerionf0de28c2005-12-13 20:21:11 +0000207 (*arr)[i++] = hregPPC_GPR3(mode64);
208 (*arr)[i++] = hregPPC_GPR4(mode64);
209 (*arr)[i++] = hregPPC_GPR5(mode64);
210 (*arr)[i++] = hregPPC_GPR6(mode64);
211 (*arr)[i++] = hregPPC_GPR7(mode64);
212 (*arr)[i++] = hregPPC_GPR8(mode64);
213 (*arr)[i++] = hregPPC_GPR9(mode64);
214 (*arr)[i++] = hregPPC_GPR10(mode64);
215 if (!mode64) {
216 /* in mode64:
217 r11 used for calls by ptr / env ptr for some langs
218 r12 used for exception handling and global linkage code */
219 (*arr)[i++] = hregPPC_GPR11(mode64);
220 (*arr)[i++] = hregPPC_GPR12(mode64);
221 }
cerion2c49e032005-02-09 17:29:49 +0000222 // GPR13 = thread specific pointer
sewardjf7745052005-12-16 01:06:42 +0000223 // GPR14 and above are callee save. Yay.
cerionf0de28c2005-12-13 20:21:11 +0000224 (*arr)[i++] = hregPPC_GPR14(mode64);
225 (*arr)[i++] = hregPPC_GPR15(mode64);
226 (*arr)[i++] = hregPPC_GPR16(mode64);
227 (*arr)[i++] = hregPPC_GPR17(mode64);
228 (*arr)[i++] = hregPPC_GPR18(mode64);
229 (*arr)[i++] = hregPPC_GPR19(mode64);
230 (*arr)[i++] = hregPPC_GPR20(mode64);
231 (*arr)[i++] = hregPPC_GPR21(mode64);
232 (*arr)[i++] = hregPPC_GPR22(mode64);
233 (*arr)[i++] = hregPPC_GPR23(mode64);
234 (*arr)[i++] = hregPPC_GPR24(mode64);
235 (*arr)[i++] = hregPPC_GPR25(mode64);
236 (*arr)[i++] = hregPPC_GPR26(mode64);
237 (*arr)[i++] = hregPPC_GPR27(mode64);
238 (*arr)[i++] = hregPPC_GPR28(mode64);
sewardjf7745052005-12-16 01:06:42 +0000239 // GPR29 is reserved for the dispatcher
sewardjb8a8dba2005-12-15 21:33:50 +0000240 // GPR30 is reserved as AltiVec spill reg temporary
241 // GPR31 is reserved for the GuestStatePtr
cerioncd304492005-02-08 19:40:24 +0000242
sewardjb8a8dba2005-12-15 21:33:50 +0000243 /* Don't waste the reg-allocs's time trawling through zillions of
244 FP registers - they mostly will never be used. We'll tolerate
245 the occasional extra spill instead. */
sewardjcb1f68e2005-12-30 03:39:14 +0000246 /* For both ppc32-linux and ppc64-linux, f14-f31 are callee save.
247 So use them. */
248 (*arr)[i++] = hregPPC_FPR14();
249 (*arr)[i++] = hregPPC_FPR15();
250 (*arr)[i++] = hregPPC_FPR16();
251 (*arr)[i++] = hregPPC_FPR17();
252 (*arr)[i++] = hregPPC_FPR18();
253 (*arr)[i++] = hregPPC_FPR19();
254 (*arr)[i++] = hregPPC_FPR20();
255 (*arr)[i++] = hregPPC_FPR21();
sewardjb8a8dba2005-12-15 21:33:50 +0000256
257 /* Same deal re Altivec */
sewardjcb1f68e2005-12-30 03:39:14 +0000258 /* For both ppc32-linux and ppc64-linux, v20-v31 are callee save.
259 So use them. */
sewardjf7745052005-12-16 01:06:42 +0000260 /* NB, vr29 is used as a scratch temporary -- do not allocate */
sewardjcb1f68e2005-12-30 03:39:14 +0000261 (*arr)[i++] = hregPPC_VR20();
262 (*arr)[i++] = hregPPC_VR21();
263 (*arr)[i++] = hregPPC_VR22();
264 (*arr)[i++] = hregPPC_VR23();
265 (*arr)[i++] = hregPPC_VR24();
266 (*arr)[i++] = hregPPC_VR25();
267 (*arr)[i++] = hregPPC_VR26();
268 (*arr)[i++] = hregPPC_VR27();
sewardjb8a8dba2005-12-15 21:33:50 +0000269
cerion01713102005-06-29 19:05:08 +0000270 vassert(i == *nregs);
cerion2c49e032005-02-09 17:29:49 +0000271}
272
273
274/* --------- Condition codes, Intel encoding. --------- */
275
florian55085f82012-11-21 00:36:55 +0000276const HChar* showPPCCondCode ( PPCCondCode cond )
cerion2c49e032005-02-09 17:29:49 +0000277{
cerionab9132d2005-02-15 15:46:59 +0000278 if (cond.test == Pct_ALWAYS) return "always";
279
280 switch (cond.flag) {
cerion5b2325f2005-12-23 00:55:09 +0000281 case Pcf_7SO:
282 return (cond.test == Pct_TRUE) ? "cr7.so=1" : "cr7.so=0";
283 case Pcf_7EQ:
284 return (cond.test == Pct_TRUE) ? "cr7.eq=1" : "cr7.eq=0";
285 case Pcf_7GT:
286 return (cond.test == Pct_TRUE) ? "cr7.gt=1" : "cr7.gt=0";
287 case Pcf_7LT:
288 return (cond.test == Pct_TRUE) ? "cr7.lt=1" : "cr7.lt=0";
sewardj7e308072011-05-04 09:50:48 +0000289 case Pcf_NONE:
290 return "no-flag";
cerion5b2325f2005-12-23 00:55:09 +0000291 default: vpanic("ppPPCCondCode");
cerion2c49e032005-02-09 17:29:49 +0000292 }
cerionbcf8c3e2005-02-04 16:17:07 +0000293}
294
cerioned623db2005-06-20 12:42:04 +0000295/* construct condition code */
cerion5b2325f2005-12-23 00:55:09 +0000296PPCCondCode mk_PPCCondCode ( PPCCondTest test, PPCCondFlag flag )
cerion7cf8e4e2005-02-16 16:08:17 +0000297{
cerion5b2325f2005-12-23 00:55:09 +0000298 PPCCondCode cc;
cerion7cf8e4e2005-02-16 16:08:17 +0000299 cc.flag = flag;
300 cc.test = test;
sewardj7e308072011-05-04 09:50:48 +0000301 if (test == Pct_ALWAYS) {
302 vassert(flag == Pcf_NONE);
303 } else {
304 vassert(flag != Pcf_NONE);
305 }
cerion7cf8e4e2005-02-16 16:08:17 +0000306 return cc;
307}
308
309/* false->true, true->false */
cerion5b2325f2005-12-23 00:55:09 +0000310PPCCondTest invertCondTest ( PPCCondTest ct )
cerion33aa6da2005-02-16 10:25:26 +0000311{
312 vassert(ct != Pct_ALWAYS);
313 return (ct == Pct_TRUE) ? Pct_FALSE : Pct_TRUE;
314}
315
316
cerioncd304492005-02-08 19:40:24 +0000317/* --------- PPCAMode: memory address expressions. --------- */
318
cerion5b2325f2005-12-23 00:55:09 +0000319PPCAMode* PPCAMode_IR ( Int idx, HReg base ) {
320 PPCAMode* am = LibVEX_Alloc(sizeof(PPCAMode));
sewardja5f957d2005-07-02 01:29:32 +0000321 vassert(idx >= -0x8000 && idx < 0x8000);
cerioncd304492005-02-08 19:40:24 +0000322 am->tag = Pam_IR;
323 am->Pam.IR.base = base;
324 am->Pam.IR.index = idx;
325 return am;
326}
cerion5b2325f2005-12-23 00:55:09 +0000327PPCAMode* PPCAMode_RR ( HReg idx, HReg base ) {
328 PPCAMode* am = LibVEX_Alloc(sizeof(PPCAMode));
cerioncd304492005-02-08 19:40:24 +0000329 am->tag = Pam_RR;
330 am->Pam.RR.base = base;
331 am->Pam.RR.index = idx;
332 return am;
333}
334
cerion5b2325f2005-12-23 00:55:09 +0000335PPCAMode* dopyPPCAMode ( PPCAMode* am ) {
cerioncd304492005-02-08 19:40:24 +0000336 switch (am->tag) {
cerionb85e8bb2005-02-16 08:54:33 +0000337 case Pam_IR:
cerion5b2325f2005-12-23 00:55:09 +0000338 return PPCAMode_IR( am->Pam.IR.index, am->Pam.IR.base );
cerionb85e8bb2005-02-16 08:54:33 +0000339 case Pam_RR:
cerion5b2325f2005-12-23 00:55:09 +0000340 return PPCAMode_RR( am->Pam.RR.index, am->Pam.RR.base );
cerionb85e8bb2005-02-16 08:54:33 +0000341 default:
cerion5b2325f2005-12-23 00:55:09 +0000342 vpanic("dopyPPCAMode");
cerioncd304492005-02-08 19:40:24 +0000343 }
344}
345
cerion5b2325f2005-12-23 00:55:09 +0000346void ppPPCAMode ( PPCAMode* am ) {
cerioncd304492005-02-08 19:40:24 +0000347 switch (am->tag) {
cerionb85e8bb2005-02-16 08:54:33 +0000348 case Pam_IR:
349 if (am->Pam.IR.index == 0)
cerionf9d6e222005-02-23 18:21:31 +0000350 vex_printf("0(");
cerionb85e8bb2005-02-16 08:54:33 +0000351 else
sewardja5f957d2005-07-02 01:29:32 +0000352 vex_printf("%d(", (Int)am->Pam.IR.index);
cerion5b2325f2005-12-23 00:55:09 +0000353 ppHRegPPC(am->Pam.IR.base);
cerionb85e8bb2005-02-16 08:54:33 +0000354 vex_printf(")");
355 return;
356 case Pam_RR:
cerion5b2325f2005-12-23 00:55:09 +0000357 ppHRegPPC(am->Pam.RR.base);
cerionb85e8bb2005-02-16 08:54:33 +0000358 vex_printf(",");
cerion5b2325f2005-12-23 00:55:09 +0000359 ppHRegPPC(am->Pam.RR.index);
cerionb85e8bb2005-02-16 08:54:33 +0000360 return;
361 default:
cerion5b2325f2005-12-23 00:55:09 +0000362 vpanic("ppPPCAMode");
cerioncd304492005-02-08 19:40:24 +0000363 }
364}
365
cerion5b2325f2005-12-23 00:55:09 +0000366static void addRegUsage_PPCAMode ( HRegUsage* u, PPCAMode* am ) {
cerioncd304492005-02-08 19:40:24 +0000367 switch (am->tag) {
cerionb85e8bb2005-02-16 08:54:33 +0000368 case Pam_IR:
369 addHRegUse(u, HRmRead, am->Pam.IR.base);
370 return;
371 case Pam_RR:
372 addHRegUse(u, HRmRead, am->Pam.RR.base);
373 addHRegUse(u, HRmRead, am->Pam.RR.index);
374 return;
375 default:
cerion5b2325f2005-12-23 00:55:09 +0000376 vpanic("addRegUsage_PPCAMode");
cerioncd304492005-02-08 19:40:24 +0000377 }
378}
cerioncd304492005-02-08 19:40:24 +0000379
cerion5b2325f2005-12-23 00:55:09 +0000380static void mapRegs_PPCAMode ( HRegRemap* m, PPCAMode* am ) {
cerioncd304492005-02-08 19:40:24 +0000381 switch (am->tag) {
cerionb85e8bb2005-02-16 08:54:33 +0000382 case Pam_IR:
383 am->Pam.IR.base = lookupHRegRemap(m, am->Pam.IR.base);
384 return;
385 case Pam_RR:
386 am->Pam.RR.base = lookupHRegRemap(m, am->Pam.RR.base);
387 am->Pam.RR.index = lookupHRegRemap(m, am->Pam.RR.index);
388 return;
389 default:
cerion5b2325f2005-12-23 00:55:09 +0000390 vpanic("mapRegs_PPCAMode");
cerioncd304492005-02-08 19:40:24 +0000391 }
392}
cerioncd304492005-02-08 19:40:24 +0000393
sewardjb51f0f42005-07-18 11:38:02 +0000394/* --------- Operand, which can be a reg or a u16/s16. --------- */
395
cerion5b2325f2005-12-23 00:55:09 +0000396PPCRH* PPCRH_Imm ( Bool syned, UShort imm16 ) {
397 PPCRH* op = LibVEX_Alloc(sizeof(PPCRH));
sewardjb51f0f42005-07-18 11:38:02 +0000398 op->tag = Prh_Imm;
399 op->Prh.Imm.syned = syned;
400 op->Prh.Imm.imm16 = imm16;
401 /* If this is a signed value, ensure it's not -32768, so that we
402 are guaranteed always to be able to negate if needed. */
403 if (syned)
404 vassert(imm16 != 0x8000);
405 vassert(syned == True || syned == False);
406 return op;
407}
cerion5b2325f2005-12-23 00:55:09 +0000408PPCRH* PPCRH_Reg ( HReg reg ) {
409 PPCRH* op = LibVEX_Alloc(sizeof(PPCRH));
sewardjb51f0f42005-07-18 11:38:02 +0000410 op->tag = Prh_Reg;
411 op->Prh.Reg.reg = reg;
412 return op;
413}
414
cerion5b2325f2005-12-23 00:55:09 +0000415void ppPPCRH ( PPCRH* op ) {
sewardjb51f0f42005-07-18 11:38:02 +0000416 switch (op->tag) {
417 case Prh_Imm:
418 if (op->Prh.Imm.syned)
419 vex_printf("%d", (Int)(Short)op->Prh.Imm.imm16);
420 else
sewardjc7cd2142005-09-09 22:31:49 +0000421 vex_printf("%u", (UInt)(UShort)op->Prh.Imm.imm16);
sewardjb51f0f42005-07-18 11:38:02 +0000422 return;
423 case Prh_Reg:
cerion5b2325f2005-12-23 00:55:09 +0000424 ppHRegPPC(op->Prh.Reg.reg);
sewardjb51f0f42005-07-18 11:38:02 +0000425 return;
426 default:
cerion5b2325f2005-12-23 00:55:09 +0000427 vpanic("ppPPCRH");
sewardjb51f0f42005-07-18 11:38:02 +0000428 }
429}
430
cerion5b2325f2005-12-23 00:55:09 +0000431/* An PPCRH can only be used in a "read" context (what would it mean
sewardjb51f0f42005-07-18 11:38:02 +0000432 to write or modify a literal?) and so we enumerate its registers
433 accordingly. */
cerion5b2325f2005-12-23 00:55:09 +0000434static void addRegUsage_PPCRH ( HRegUsage* u, PPCRH* op ) {
sewardjb51f0f42005-07-18 11:38:02 +0000435 switch (op->tag) {
436 case Prh_Imm:
437 return;
438 case Prh_Reg:
439 addHRegUse(u, HRmRead, op->Prh.Reg.reg);
440 return;
441 default:
cerion5b2325f2005-12-23 00:55:09 +0000442 vpanic("addRegUsage_PPCRH");
sewardjb51f0f42005-07-18 11:38:02 +0000443 }
444}
445
cerion5b2325f2005-12-23 00:55:09 +0000446static void mapRegs_PPCRH ( HRegRemap* m, PPCRH* op ) {
sewardjb51f0f42005-07-18 11:38:02 +0000447 switch (op->tag) {
448 case Prh_Imm:
449 return;
450 case Prh_Reg:
451 op->Prh.Reg.reg = lookupHRegRemap(m, op->Prh.Reg.reg);
452 return;
453 default:
cerion5b2325f2005-12-23 00:55:09 +0000454 vpanic("mapRegs_PPCRH");
sewardjb51f0f42005-07-18 11:38:02 +0000455 }
456}
457
458
cerionf0de28c2005-12-13 20:21:11 +0000459/* --------- Operand, which can be a reg or a u32/64. --------- */
cerioncd304492005-02-08 19:40:24 +0000460
cerion5b2325f2005-12-23 00:55:09 +0000461PPCRI* PPCRI_Imm ( ULong imm64 ) {
462 PPCRI* op = LibVEX_Alloc(sizeof(PPCRI));
cerionf0de28c2005-12-13 20:21:11 +0000463 op->tag = Pri_Imm;
464 op->Pri.Imm = imm64;
cerioncd304492005-02-08 19:40:24 +0000465 return op;
466}
cerion5b2325f2005-12-23 00:55:09 +0000467PPCRI* PPCRI_Reg ( HReg reg ) {
468 PPCRI* op = LibVEX_Alloc(sizeof(PPCRI));
cerionf0de28c2005-12-13 20:21:11 +0000469 op->tag = Pri_Reg;
470 op->Pri.Reg = reg;
cerioncd304492005-02-08 19:40:24 +0000471 return op;
472}
473
cerion5b2325f2005-12-23 00:55:09 +0000474void ppPPCRI ( PPCRI* dst ) {
sewardjb51f0f42005-07-18 11:38:02 +0000475 switch (dst->tag) {
476 case Pri_Imm:
cerionf0de28c2005-12-13 20:21:11 +0000477 vex_printf("0x%llx", dst->Pri.Imm);
sewardjb51f0f42005-07-18 11:38:02 +0000478 break;
479 case Pri_Reg:
cerion5b2325f2005-12-23 00:55:09 +0000480 ppHRegPPC(dst->Pri.Reg);
sewardjb51f0f42005-07-18 11:38:02 +0000481 break;
482 default:
cerion5b2325f2005-12-23 00:55:09 +0000483 vpanic("ppPPCRI");
cerioncd304492005-02-08 19:40:24 +0000484 }
485}
486
cerion5b2325f2005-12-23 00:55:09 +0000487/* An PPCRI can only be used in a "read" context (what would it
sewardjb51f0f42005-07-18 11:38:02 +0000488 mean to write or modify a literal?) and so we enumerate its
489 registers accordingly. */
cerion5b2325f2005-12-23 00:55:09 +0000490static void addRegUsage_PPCRI ( HRegUsage* u, PPCRI* dst ) {
sewardjb51f0f42005-07-18 11:38:02 +0000491 switch (dst->tag) {
492 case Pri_Imm:
493 return;
494 case Pri_Reg:
495 addHRegUse(u, HRmRead, dst->Pri.Reg);
496 return;
497 default:
cerion5b2325f2005-12-23 00:55:09 +0000498 vpanic("addRegUsage_PPCRI");
cerioncd304492005-02-08 19:40:24 +0000499 }
500}
501
cerion5b2325f2005-12-23 00:55:09 +0000502static void mapRegs_PPCRI ( HRegRemap* m, PPCRI* dst ) {
sewardjb51f0f42005-07-18 11:38:02 +0000503 switch (dst->tag) {
504 case Pri_Imm:
505 return;
506 case Pri_Reg:
507 dst->Pri.Reg = lookupHRegRemap(m, dst->Pri.Reg);
508 return;
509 default:
cerion5b2325f2005-12-23 00:55:09 +0000510 vpanic("mapRegs_PPCRI");
cerioncd304492005-02-08 19:40:24 +0000511 }
512}
513
sewardjb51f0f42005-07-18 11:38:02 +0000514
cerion27b3d7e2005-09-14 20:35:47 +0000515/* --------- Operand, which can be a vector reg or a simm5. --------- */
516
cerion5b2325f2005-12-23 00:55:09 +0000517PPCVI5s* PPCVI5s_Imm ( Char simm5 ) {
518 PPCVI5s* op = LibVEX_Alloc(sizeof(PPCVI5s));
cerion27b3d7e2005-09-14 20:35:47 +0000519 op->tag = Pvi_Imm;
520 op->Pvi.Imm5s = simm5;
521 vassert(simm5 >= -16 && simm5 <= 15);
522 return op;
523}
cerion5b2325f2005-12-23 00:55:09 +0000524PPCVI5s* PPCVI5s_Reg ( HReg reg ) {
525 PPCVI5s* op = LibVEX_Alloc(sizeof(PPCVI5s));
526 op->tag = Pvi_Reg;
527 op->Pvi.Reg = reg;
cerion27b3d7e2005-09-14 20:35:47 +0000528 vassert(hregClass(reg) == HRcVec128);
529 return op;
530}
531
cerion5b2325f2005-12-23 00:55:09 +0000532void ppPPCVI5s ( PPCVI5s* src ) {
cerion27b3d7e2005-09-14 20:35:47 +0000533 switch (src->tag) {
534 case Pvi_Imm:
535 vex_printf("%d", (Int)src->Pvi.Imm5s);
536 break;
537 case Pvi_Reg:
cerion5b2325f2005-12-23 00:55:09 +0000538 ppHRegPPC(src->Pvi.Reg);
cerion27b3d7e2005-09-14 20:35:47 +0000539 break;
540 default:
cerion5b2325f2005-12-23 00:55:09 +0000541 vpanic("ppPPCVI5s");
cerion27b3d7e2005-09-14 20:35:47 +0000542 }
543}
544
cerion5b2325f2005-12-23 00:55:09 +0000545/* An PPCVI5s can only be used in a "read" context (what would it
cerion27b3d7e2005-09-14 20:35:47 +0000546 mean to write or modify a literal?) and so we enumerate its
547 registers accordingly. */
cerion5b2325f2005-12-23 00:55:09 +0000548static void addRegUsage_PPCVI5s ( HRegUsage* u, PPCVI5s* dst ) {
cerion27b3d7e2005-09-14 20:35:47 +0000549 switch (dst->tag) {
550 case Pvi_Imm:
551 return;
552 case Pvi_Reg:
553 addHRegUse(u, HRmRead, dst->Pvi.Reg);
554 return;
555 default:
cerion5b2325f2005-12-23 00:55:09 +0000556 vpanic("addRegUsage_PPCVI5s");
cerion27b3d7e2005-09-14 20:35:47 +0000557 }
558}
559
cerion5b2325f2005-12-23 00:55:09 +0000560static void mapRegs_PPCVI5s ( HRegRemap* m, PPCVI5s* dst ) {
cerion27b3d7e2005-09-14 20:35:47 +0000561 switch (dst->tag) {
562 case Pvi_Imm:
563 return;
564 case Pvi_Reg:
565 dst->Pvi.Reg = lookupHRegRemap(m, dst->Pvi.Reg);
566 return;
567 default:
cerion5b2325f2005-12-23 00:55:09 +0000568 vpanic("mapRegs_PPCVI5s");
cerion27b3d7e2005-09-14 20:35:47 +0000569 }
570}
571
572
cerioncd304492005-02-08 19:40:24 +0000573/* --------- Instructions. --------- */
574
florian55085f82012-11-21 00:36:55 +0000575const HChar* showPPCUnaryOp ( PPCUnaryOp op ) {
cerion2c49e032005-02-09 17:29:49 +0000576 switch (op) {
cerion5b2325f2005-12-23 00:55:09 +0000577 case Pun_NOT: return "not";
578 case Pun_NEG: return "neg";
cerion07b07a92005-12-22 14:32:35 +0000579 case Pun_CLZ32: return "cntlzw";
580 case Pun_CLZ64: return "cntlzd";
sewardj7fd5bb02006-01-26 02:24:17 +0000581 case Pun_EXTSW: return "extsw";
cerion5b2325f2005-12-23 00:55:09 +0000582 default: vpanic("showPPCUnaryOp");
cerion2c49e032005-02-09 17:29:49 +0000583 }
584}
cerioncd304492005-02-08 19:40:24 +0000585
florian55085f82012-11-21 00:36:55 +0000586const HChar* showPPCAluOp ( PPCAluOp op, Bool immR ) {
cerioncd304492005-02-08 19:40:24 +0000587 switch (op) {
sewardjb51f0f42005-07-18 11:38:02 +0000588 case Palu_ADD: return immR ? "addi" : "add";
589 case Palu_SUB: return immR ? "subi" : "sub";
590 case Palu_AND: return immR ? "andi." : "and";
591 case Palu_OR: return immR ? "ori" : "or";
592 case Palu_XOR: return immR ? "xori" : "xor";
cerion5b2325f2005-12-23 00:55:09 +0000593 default: vpanic("showPPCAluOp");
cerionab9132d2005-02-15 15:46:59 +0000594 }
595}
596
florian55085f82012-11-21 00:36:55 +0000597const HChar* showPPCShftOp ( PPCShftOp op, Bool immR, Bool sz32 ) {
cerionbb01b7c2005-12-16 13:40:18 +0000598 switch (op) {
599 case Pshft_SHL: return sz32 ? (immR ? "slwi" : "slw") :
600 (immR ? "sldi" : "sld");
601 case Pshft_SHR: return sz32 ? (immR ? "srwi" : "srw") :
602 (immR ? "srdi" : "srd");
603 case Pshft_SAR: return sz32 ? (immR ? "srawi" : "sraw") :
604 (immR ? "sradi" : "srad");
cerion5b2325f2005-12-23 00:55:09 +0000605 default: vpanic("showPPCShftOp");
cerionbb01b7c2005-12-16 13:40:18 +0000606 }
607}
608
florian55085f82012-11-21 00:36:55 +0000609const HChar* showPPCFpOp ( PPCFpOp op ) {
cerion094d1392005-06-20 13:45:57 +0000610 switch (op) {
sewardjb183b852006-02-03 16:08:03 +0000611 case Pfp_ADDD: return "fadd";
612 case Pfp_SUBD: return "fsub";
613 case Pfp_MULD: return "fmul";
614 case Pfp_DIVD: return "fdiv";
sewardj40c80262006-02-08 19:30:46 +0000615 case Pfp_MADDD: return "fmadd";
616 case Pfp_MSUBD: return "fmsub";
617 case Pfp_MADDS: return "fmadds";
618 case Pfp_MSUBS: return "fmsubs";
sewardjb183b852006-02-03 16:08:03 +0000619 case Pfp_ADDS: return "fadds";
620 case Pfp_SUBS: return "fsubs";
621 case Pfp_MULS: return "fmuls";
622 case Pfp_DIVS: return "fdivs";
cerion094d1392005-06-20 13:45:57 +0000623 case Pfp_SQRT: return "fsqrt";
624 case Pfp_ABS: return "fabs";
625 case Pfp_NEG: return "fneg";
626 case Pfp_MOV: return "fmr";
sewardjbaf971a2006-01-27 15:09:35 +0000627 case Pfp_RES: return "fres";
628 case Pfp_RSQRTE: return "frsqrte";
sewardj0f1ef862008-08-08 08:37:06 +0000629 case Pfp_FRIM: return "frim";
630 case Pfp_FRIN: return "frin";
631 case Pfp_FRIP: return "frip";
632 case Pfp_FRIZ: return "friz";
sewardjc6bbd472012-04-02 10:20:48 +0000633 case Pfp_DFPADD: return "dadd";
634 case Pfp_DFPADDQ: return "daddq";
635 case Pfp_DFPSUB: return "dsub";
636 case Pfp_DFPSUBQ: return "dsubq";
637 case Pfp_DFPMUL: return "dmul";
638 case Pfp_DFPMULQ: return "dmulq";
639 case Pfp_DFPDIV: return "ddivd";
640 case Pfp_DFPDIVQ: return "ddivq";
sewardj26217b02012-04-12 17:19:48 +0000641 case Pfp_DCTDP: return "dctdp";
642 case Pfp_DRSP: return "drsp";
643 case Pfp_DCTFIX: return "dctfix";
644 case Pfp_DCFFIX: return "dcffix";
645 case Pfp_DCTQPQ: return "dctqpq";
646 case Pfp_DCFFIXQ: return "dcffixq";
sewardjcdc376d2012-04-23 11:21:12 +0000647 case Pfp_DQUA: return "dqua";
648 case Pfp_DQUAQ: return "dquaq";
649 case Pfp_DXEX: return "dxex";
650 case Pfp_DXEXQ: return "dxexq";
651 case Pfp_DIEX: return "diex";
652 case Pfp_DIEXQ: return "diexq";
653 case Pfp_RRDTR: return "rrdtr";
cerion5b2325f2005-12-23 00:55:09 +0000654 default: vpanic("showPPCFpOp");
cerion094d1392005-06-20 13:45:57 +0000655 }
656}
cerioncd304492005-02-08 19:40:24 +0000657
florian55085f82012-11-21 00:36:55 +0000658const HChar* showPPCAvOp ( PPCAvOp op ) {
cerionc3d8bdc2005-06-28 18:06:23 +0000659 switch (op) {
cerion6b6f59e2005-06-28 20:59:18 +0000660
661 /* Unary */
662 case Pav_MOV: return "vmr"; /* Mov */
cerionc3d8bdc2005-06-28 18:06:23 +0000663
cerion6b6f59e2005-06-28 20:59:18 +0000664 case Pav_AND: return "vand"; /* Bitwise */
cerionc3d8bdc2005-06-28 18:06:23 +0000665 case Pav_OR: return "vor";
666 case Pav_XOR: return "vxor";
667 case Pav_NOT: return "vnot";
668
cerion6b6f59e2005-06-28 20:59:18 +0000669 case Pav_UNPCKH8S: return "vupkhsb"; /* Unpack */
cerionc3d8bdc2005-06-28 18:06:23 +0000670 case Pav_UNPCKH16S: return "vupkhsh";
671 case Pav_UNPCKL8S: return "vupklsb";
672 case Pav_UNPCKL16S: return "vupklsh";
673 case Pav_UNPCKHPIX: return "vupkhpx";
674 case Pav_UNPCKLPIX: return "vupklpx";
cerion6b6f59e2005-06-28 20:59:18 +0000675
676 /* Integer binary */
carll0c74bb52013-08-12 18:01:40 +0000677 case Pav_ADDU: return "vaddu_m"; // b,h,w,dw
carll48ae46b2013-10-01 15:45:54 +0000678 case Pav_QADDU: return "vaddu_s"; // b,h,w,dw
679 case Pav_QADDS: return "vadds_s"; // b,h,w,dw
cerionc3d8bdc2005-06-28 18:06:23 +0000680
carll48ae46b2013-10-01 15:45:54 +0000681 case Pav_SUBU: return "vsubu_m"; // b,h,w,dw
682 case Pav_QSUBU: return "vsubu_s"; // b,h,w,dw
683 case Pav_QSUBS: return "vsubs_s"; // b,h,w,dw
cerion6b6f59e2005-06-28 20:59:18 +0000684
carll48ae46b2013-10-01 15:45:54 +0000685 case Pav_MULU: return "vmulu"; // w
686 case Pav_OMULU: return "vmulou"; // b,h,w
687 case Pav_OMULS: return "vmulos"; // b,h,w
688 case Pav_EMULU: return "vmuleu"; // b,h,w
689 case Pav_EMULS: return "vmules"; // b,h,w
cerion6b6f59e2005-06-28 20:59:18 +0000690
691 case Pav_AVGU: return "vavgu"; // b,h,w
692 case Pav_AVGS: return "vavgs"; // b,h,w
693
694 case Pav_MAXU: return "vmaxu"; // b,h,w
695 case Pav_MAXS: return "vmaxs"; // b,h,w
696
697 case Pav_MINU: return "vminu"; // b,h,w
698 case Pav_MINS: return "vmins"; // b,h,w
699
700 /* Compare (always affects CR field 6) */
701 case Pav_CMPEQU: return "vcmpequ"; // b,h,w
702 case Pav_CMPGTU: return "vcmpgtu"; // b,h,w
703 case Pav_CMPGTS: return "vcmpgts"; // b,h,w
704
705 /* Shift */
carll48ae46b2013-10-01 15:45:54 +0000706 case Pav_SHL: return "vsl"; // ' ',b,h,w,dw
707 case Pav_SHR: return "vsr"; // ' ',b,h,w,dw
708 case Pav_SAR: return "vsra"; // b,h,w,dw
709 case Pav_ROTL: return "vrl"; // b,h,w,dw
cerion6b6f59e2005-06-28 20:59:18 +0000710
711 /* Pack */
carll0c74bb52013-08-12 18:01:40 +0000712 case Pav_PACKUU: return "vpku_um"; // h,w,dw
cerionf34ccc42005-09-16 08:55:50 +0000713 case Pav_QPACKUU: return "vpku_us"; // h,w
714 case Pav_QPACKSU: return "vpks_us"; // h,w
715 case Pav_QPACKSS: return "vpks_ss"; // h,w
cerion6b6f59e2005-06-28 20:59:18 +0000716 case Pav_PACKPXL: return "vpkpx";
717
cerionc3d8bdc2005-06-28 18:06:23 +0000718 /* Merge */
cerion6b6f59e2005-06-28 20:59:18 +0000719 case Pav_MRGHI: return "vmrgh"; // b,h,w
720 case Pav_MRGLO: return "vmrgl"; // b,h,w
721
carll48ae46b2013-10-01 15:45:54 +0000722 /* Concatenation */
723 case Pav_CATODD: return "vmrgow"; // w
724 case Pav_CATEVEN: return "vmrgew"; // w
725
carll7deaf952013-10-15 18:11:20 +0000726 /* SHA */
727 case Pav_SHA256: return "vshasigmaw"; // w
728 case Pav_SHA512: return "vshasigmaw"; // dw
729
730 /* BCD */
731 case Pav_BCDAdd: return "bcdadd."; // qw
732 case Pav_BCDSub: return "bcdsub."; // qw
733
734 /* Polynomial arith */
735 case Pav_POLYMULADD: return "vpmsum"; // b, h, w, d
736
737 /* Cipher */
738 case Pav_CIPHERV128: case Pav_CIPHERLV128:
739 case Pav_NCIPHERV128: case Pav_NCIPHERLV128:
740 case Pav_CIPHERSUBV128: return "v_cipher_"; // qw
741
742 /* zero count */
743 case Pav_ZEROCNTBYTE: case Pav_ZEROCNTWORD:
744 case Pav_ZEROCNTHALF: case Pav_ZEROCNTDBL:
745 return "vclz_"; // b, h, w, d
746
carll60c6bac2013-10-18 01:19:06 +0000747 /* vector gather (byte-by-byte bit matrix transpose) */
748 case Pav_BITMTXXPOSE:
749 return "vgbbd";
750
cerion5b2325f2005-12-23 00:55:09 +0000751 default: vpanic("showPPCAvOp");
cerion8ea0d3e2005-11-14 00:44:47 +0000752 }
753}
754
florian55085f82012-11-21 00:36:55 +0000755const HChar* showPPCAvFpOp ( PPCAvFpOp op ) {
cerion8ea0d3e2005-11-14 00:44:47 +0000756 switch (op) {
cerion6b6f59e2005-06-28 20:59:18 +0000757 /* Floating Point Binary */
cerion8ea0d3e2005-11-14 00:44:47 +0000758 case Pavfp_ADDF: return "vaddfp";
759 case Pavfp_SUBF: return "vsubfp";
760 case Pavfp_MULF: return "vmaddfp";
761 case Pavfp_MAXF: return "vmaxfp";
762 case Pavfp_MINF: return "vminfp";
763 case Pavfp_CMPEQF: return "vcmpeqfp";
764 case Pavfp_CMPGTF: return "vcmpgtfp";
765 case Pavfp_CMPGEF: return "vcmpgefp";
cerionc3d8bdc2005-06-28 18:06:23 +0000766
cerion8ea0d3e2005-11-14 00:44:47 +0000767 /* Floating Point Unary */
768 case Pavfp_RCPF: return "vrefp";
769 case Pavfp_RSQRTF: return "vrsqrtefp";
ceriond963eb42005-11-16 18:02:58 +0000770 case Pavfp_CVTU2F: return "vcfux";
771 case Pavfp_CVTS2F: return "vcfsx";
772 case Pavfp_QCVTF2U: return "vctuxs";
773 case Pavfp_QCVTF2S: return "vctsxs";
774 case Pavfp_ROUNDM: return "vrfim";
775 case Pavfp_ROUNDP: return "vrfip";
776 case Pavfp_ROUNDN: return "vrfin";
777 case Pavfp_ROUNDZ: return "vrfiz";
cerion8ea0d3e2005-11-14 00:44:47 +0000778
cerion5b2325f2005-12-23 00:55:09 +0000779 default: vpanic("showPPCAvFpOp");
cerionc3d8bdc2005-06-28 18:06:23 +0000780 }
781}
782
cerion5b2325f2005-12-23 00:55:09 +0000783PPCInstr* PPCInstr_LI ( HReg dst, ULong imm64, Bool mode64 )
sewardjb51f0f42005-07-18 11:38:02 +0000784{
cerion5b2325f2005-12-23 00:55:09 +0000785 PPCInstr* i = LibVEX_Alloc(sizeof(PPCInstr));
cerionf0de28c2005-12-13 20:21:11 +0000786 i->tag = Pin_LI;
787 i->Pin.LI.dst = dst;
788 i->Pin.LI.imm64 = imm64;
789 if (!mode64)
790 vassert( (Long)imm64 == (Long)(Int)(UInt)imm64 );
sewardjb51f0f42005-07-18 11:38:02 +0000791 return i;
792}
cerion5b2325f2005-12-23 00:55:09 +0000793PPCInstr* PPCInstr_Alu ( PPCAluOp op, HReg dst,
794 HReg srcL, PPCRH* srcR ) {
795 PPCInstr* i = LibVEX_Alloc(sizeof(PPCInstr));
cerionf0de28c2005-12-13 20:21:11 +0000796 i->tag = Pin_Alu;
797 i->Pin.Alu.op = op;
798 i->Pin.Alu.dst = dst;
799 i->Pin.Alu.srcL = srcL;
800 i->Pin.Alu.srcR = srcR;
cerioncd304492005-02-08 19:40:24 +0000801 return i;
802}
cerion5b2325f2005-12-23 00:55:09 +0000803PPCInstr* PPCInstr_Shft ( PPCShftOp op, Bool sz32,
804 HReg dst, HReg srcL, PPCRH* srcR ) {
805 PPCInstr* i = LibVEX_Alloc(sizeof(PPCInstr));
cerionbb01b7c2005-12-16 13:40:18 +0000806 i->tag = Pin_Shft;
807 i->Pin.Shft.op = op;
808 i->Pin.Shft.sz32 = sz32;
809 i->Pin.Shft.dst = dst;
810 i->Pin.Shft.srcL = srcL;
811 i->Pin.Shft.srcR = srcR;
812 return i;
813}
cerion5b2325f2005-12-23 00:55:09 +0000814PPCInstr* PPCInstr_AddSubC ( Bool isAdd, Bool setC,
815 HReg dst, HReg srcL, HReg srcR ) {
816 PPCInstr* i = LibVEX_Alloc(sizeof(PPCInstr));
817 i->tag = Pin_AddSubC;
818 i->Pin.AddSubC.isAdd = isAdd;
819 i->Pin.AddSubC.setC = setC;
820 i->Pin.AddSubC.dst = dst;
821 i->Pin.AddSubC.srcL = srcL;
822 i->Pin.AddSubC.srcR = srcR;
cerion4a49b032005-11-08 16:23:07 +0000823 return i;
824}
cerion5b2325f2005-12-23 00:55:09 +0000825PPCInstr* PPCInstr_Cmp ( Bool syned, Bool sz32,
826 UInt crfD, HReg srcL, PPCRH* srcR ) {
827 PPCInstr* i = LibVEX_Alloc(sizeof(PPCInstr));
cerionf0de28c2005-12-13 20:21:11 +0000828 i->tag = Pin_Cmp;
829 i->Pin.Cmp.syned = syned;
cerionbb01b7c2005-12-16 13:40:18 +0000830 i->Pin.Cmp.sz32 = sz32;
cerionf0de28c2005-12-13 20:21:11 +0000831 i->Pin.Cmp.crfD = crfD;
832 i->Pin.Cmp.srcL = srcL;
833 i->Pin.Cmp.srcR = srcR;
cerion2c49e032005-02-09 17:29:49 +0000834 return i;
835}
cerion5b2325f2005-12-23 00:55:09 +0000836PPCInstr* PPCInstr_Unary ( PPCUnaryOp op, HReg dst, HReg src ) {
837 PPCInstr* i = LibVEX_Alloc(sizeof(PPCInstr));
838 i->tag = Pin_Unary;
839 i->Pin.Unary.op = op;
840 i->Pin.Unary.dst = dst;
841 i->Pin.Unary.src = src;
cerion2c49e032005-02-09 17:29:49 +0000842 return i;
843}
cerion5b2325f2005-12-23 00:55:09 +0000844PPCInstr* PPCInstr_MulL ( Bool syned, Bool hi, Bool sz32,
845 HReg dst, HReg srcL, HReg srcR ) {
846 PPCInstr* i = LibVEX_Alloc(sizeof(PPCInstr));
cerion92f5dc72005-02-10 16:11:35 +0000847 i->tag = Pin_MulL;
848 i->Pin.MulL.syned = syned;
cerionf0de28c2005-12-13 20:21:11 +0000849 i->Pin.MulL.hi = hi;
cerionbb01b7c2005-12-16 13:40:18 +0000850 i->Pin.MulL.sz32 = sz32;
cerionc0e707e2005-02-10 22:35:34 +0000851 i->Pin.MulL.dst = dst;
ceriona2f75882005-03-15 16:33:38 +0000852 i->Pin.MulL.srcL = srcL;
853 i->Pin.MulL.srcR = srcR;
cerionf0de28c2005-12-13 20:21:11 +0000854 /* if doing the low word, the signedness is irrelevant, but tie it
sewardjb51f0f42005-07-18 11:38:02 +0000855 down anyway. */
cerionf0de28c2005-12-13 20:21:11 +0000856 if (!hi) vassert(!syned);
cerion92f5dc72005-02-10 16:11:35 +0000857 return i;
858}
sewardj4aa412a2011-07-24 14:13:21 +0000859PPCInstr* PPCInstr_Div ( Bool extended, Bool syned, Bool sz32,
cerion5b2325f2005-12-23 00:55:09 +0000860 HReg dst, HReg srcL, HReg srcR ) {
861 PPCInstr* i = LibVEX_Alloc(sizeof(PPCInstr));
862 i->tag = Pin_Div;
sewardj4aa412a2011-07-24 14:13:21 +0000863 i->Pin.Div.extended = extended;
cerion5b2325f2005-12-23 00:55:09 +0000864 i->Pin.Div.syned = syned;
865 i->Pin.Div.sz32 = sz32;
866 i->Pin.Div.dst = dst;
867 i->Pin.Div.srcL = srcL;
868 i->Pin.Div.srcR = srcR;
cerionc0e707e2005-02-10 22:35:34 +0000869 return i;
870}
cerion5b2325f2005-12-23 00:55:09 +0000871PPCInstr* PPCInstr_Call ( PPCCondCode cond,
sewardjcfe046e2013-01-17 14:23:53 +0000872 Addr64 target, UInt argiregs, RetLoc rloc ) {
sewardj6a64a9f2005-08-21 00:48:37 +0000873 UInt mask;
cerion5b2325f2005-12-23 00:55:09 +0000874 PPCInstr* i = LibVEX_Alloc(sizeof(PPCInstr));
cerion2c49e032005-02-09 17:29:49 +0000875 i->tag = Pin_Call;
876 i->Pin.Call.cond = cond;
877 i->Pin.Call.target = target;
sewardj6a64a9f2005-08-21 00:48:37 +0000878 i->Pin.Call.argiregs = argiregs;
sewardjcfe046e2013-01-17 14:23:53 +0000879 i->Pin.Call.rloc = rloc;
sewardj6a64a9f2005-08-21 00:48:37 +0000880 /* Only r3 .. r10 inclusive may be used as arg regs. Hence: */
881 mask = (1<<3)|(1<<4)|(1<<5)|(1<<6)|(1<<7)|(1<<8)|(1<<9)|(1<<10);
882 vassert(0 == (argiregs & ~mask));
sewardj74142b82013-08-08 10:28:59 +0000883 vassert(is_sane_RetLoc(rloc));
cerion2c49e032005-02-09 17:29:49 +0000884 return i;
885}
sewardj3dee8492012-04-20 00:13:28 +0000886PPCInstr* PPCInstr_XDirect ( Addr64 dstGA, PPCAMode* amCIA,
887 PPCCondCode cond, Bool toFastEP ) {
888 PPCInstr* i = LibVEX_Alloc(sizeof(PPCInstr));
889 i->tag = Pin_XDirect;
890 i->Pin.XDirect.dstGA = dstGA;
891 i->Pin.XDirect.amCIA = amCIA;
892 i->Pin.XDirect.cond = cond;
893 i->Pin.XDirect.toFastEP = toFastEP;
894 return i;
895}
896PPCInstr* PPCInstr_XIndir ( HReg dstGA, PPCAMode* amCIA,
897 PPCCondCode cond ) {
898 PPCInstr* i = LibVEX_Alloc(sizeof(PPCInstr));
899 i->tag = Pin_XIndir;
900 i->Pin.XIndir.dstGA = dstGA;
901 i->Pin.XIndir.amCIA = amCIA;
902 i->Pin.XIndir.cond = cond;
903 return i;
904}
905PPCInstr* PPCInstr_XAssisted ( HReg dstGA, PPCAMode* amCIA,
906 PPCCondCode cond, IRJumpKind jk ) {
907 PPCInstr* i = LibVEX_Alloc(sizeof(PPCInstr));
908 i->tag = Pin_XAssisted;
909 i->Pin.XAssisted.dstGA = dstGA;
910 i->Pin.XAssisted.amCIA = amCIA;
911 i->Pin.XAssisted.cond = cond;
912 i->Pin.XAssisted.jk = jk;
cerion2c49e032005-02-09 17:29:49 +0000913 return i;
914}
cerion5b2325f2005-12-23 00:55:09 +0000915PPCInstr* PPCInstr_CMov ( PPCCondCode cond,
916 HReg dst, PPCRI* src ) {
sewardje9d8a262009-07-01 08:06:34 +0000917 PPCInstr* i = LibVEX_Alloc(sizeof(PPCInstr));
cerionf0de28c2005-12-13 20:21:11 +0000918 i->tag = Pin_CMov;
919 i->Pin.CMov.cond = cond;
920 i->Pin.CMov.src = src;
921 i->Pin.CMov.dst = dst;
cerionab9132d2005-02-15 15:46:59 +0000922 vassert(cond.test != Pct_ALWAYS);
cerionb536af92005-02-10 15:03:19 +0000923 return i;
924}
sewardj7fd5bb02006-01-26 02:24:17 +0000925PPCInstr* PPCInstr_Load ( UChar sz,
cerion5b2325f2005-12-23 00:55:09 +0000926 HReg dst, PPCAMode* src, Bool mode64 ) {
927 PPCInstr* i = LibVEX_Alloc(sizeof(PPCInstr));
cerion7cf8e4e2005-02-16 16:08:17 +0000928 i->tag = Pin_Load;
929 i->Pin.Load.sz = sz;
cerion7cf8e4e2005-02-16 16:08:17 +0000930 i->Pin.Load.src = src;
931 i->Pin.Load.dst = dst;
cerionf0de28c2005-12-13 20:21:11 +0000932 vassert(sz == 1 || sz == 2 || sz == 4 || sz == 8);
933 if (sz == 8) vassert(mode64);
cerioncd304492005-02-08 19:40:24 +0000934 return i;
935}
sewardje9d8a262009-07-01 08:06:34 +0000936PPCInstr* PPCInstr_LoadL ( UChar sz,
937 HReg dst, HReg src, Bool mode64 )
938{
939 PPCInstr* i = LibVEX_Alloc(sizeof(PPCInstr));
940 i->tag = Pin_LoadL;
941 i->Pin.LoadL.sz = sz;
942 i->Pin.LoadL.src = src;
943 i->Pin.LoadL.dst = dst;
944 vassert(sz == 4 || sz == 8);
945 if (sz == 8) vassert(mode64);
946 return i;
947}
cerion5b2325f2005-12-23 00:55:09 +0000948PPCInstr* PPCInstr_Store ( UChar sz, PPCAMode* dst, HReg src,
949 Bool mode64 ) {
950 PPCInstr* i = LibVEX_Alloc(sizeof(PPCInstr));
cerioncd304492005-02-08 19:40:24 +0000951 i->tag = Pin_Store;
952 i->Pin.Store.sz = sz;
953 i->Pin.Store.src = src;
954 i->Pin.Store.dst = dst;
cerionf0de28c2005-12-13 20:21:11 +0000955 vassert(sz == 1 || sz == 2 || sz == 4 || sz == 8);
956 if (sz == 8) vassert(mode64);
cerioncd304492005-02-08 19:40:24 +0000957 return i;
958}
sewardje9d8a262009-07-01 08:06:34 +0000959PPCInstr* PPCInstr_StoreC ( UChar sz, HReg dst, HReg src, Bool mode64 ) {
960 PPCInstr* i = LibVEX_Alloc(sizeof(PPCInstr));
961 i->tag = Pin_StoreC;
962 i->Pin.StoreC.sz = sz;
963 i->Pin.StoreC.src = src;
964 i->Pin.StoreC.dst = dst;
965 vassert(sz == 4 || sz == 8);
966 if (sz == 8) vassert(mode64);
967 return i;
968}
cerion5b2325f2005-12-23 00:55:09 +0000969PPCInstr* PPCInstr_Set ( PPCCondCode cond, HReg dst ) {
970 PPCInstr* i = LibVEX_Alloc(sizeof(PPCInstr));
971 i->tag = Pin_Set;
972 i->Pin.Set.cond = cond;
973 i->Pin.Set.dst = dst;
cerionb536af92005-02-10 15:03:19 +0000974 return i;
975}
cerion5b2325f2005-12-23 00:55:09 +0000976PPCInstr* PPCInstr_MfCR ( HReg dst )
sewardjb51f0f42005-07-18 11:38:02 +0000977{
cerion5b2325f2005-12-23 00:55:09 +0000978 PPCInstr* i = LibVEX_Alloc(sizeof(PPCInstr));
979 i->tag = Pin_MfCR;
980 i->Pin.MfCR.dst = dst;
sewardjb51f0f42005-07-18 11:38:02 +0000981 return i;
982}
cerion5b2325f2005-12-23 00:55:09 +0000983PPCInstr* PPCInstr_MFence ( void )
cerion92f5dc72005-02-10 16:11:35 +0000984{
cerion5b2325f2005-12-23 00:55:09 +0000985 PPCInstr* i = LibVEX_Alloc(sizeof(PPCInstr));
986 i->tag = Pin_MFence;
cerion92f5dc72005-02-10 16:11:35 +0000987 return i;
988}
cerioncd304492005-02-08 19:40:24 +0000989
cerion5b2325f2005-12-23 00:55:09 +0000990PPCInstr* PPCInstr_FpUnary ( PPCFpOp op, HReg dst, HReg src ) {
991 PPCInstr* i = LibVEX_Alloc(sizeof(PPCInstr));
cerion094d1392005-06-20 13:45:57 +0000992 i->tag = Pin_FpUnary;
993 i->Pin.FpUnary.op = op;
994 i->Pin.FpUnary.dst = dst;
995 i->Pin.FpUnary.src = src;
996 return i;
997}
cerion5b2325f2005-12-23 00:55:09 +0000998PPCInstr* PPCInstr_FpBinary ( PPCFpOp op, HReg dst,
999 HReg srcL, HReg srcR ) {
1000 PPCInstr* i = LibVEX_Alloc(sizeof(PPCInstr));
cerion094d1392005-06-20 13:45:57 +00001001 i->tag = Pin_FpBinary;
1002 i->Pin.FpBinary.op = op;
1003 i->Pin.FpBinary.dst = dst;
1004 i->Pin.FpBinary.srcL = srcL;
1005 i->Pin.FpBinary.srcR = srcR;
1006 return i;
1007}
sewardj40c80262006-02-08 19:30:46 +00001008PPCInstr* PPCInstr_FpMulAcc ( PPCFpOp op, HReg dst, HReg srcML,
1009 HReg srcMR, HReg srcAcc )
1010{
1011 PPCInstr* i = LibVEX_Alloc(sizeof(PPCInstr));
1012 i->tag = Pin_FpMulAcc;
1013 i->Pin.FpMulAcc.op = op;
1014 i->Pin.FpMulAcc.dst = dst;
1015 i->Pin.FpMulAcc.srcML = srcML;
1016 i->Pin.FpMulAcc.srcMR = srcMR;
1017 i->Pin.FpMulAcc.srcAcc = srcAcc;
1018 return i;
1019}
cerion5b2325f2005-12-23 00:55:09 +00001020PPCInstr* PPCInstr_FpLdSt ( Bool isLoad, UChar sz,
1021 HReg reg, PPCAMode* addr ) {
1022 PPCInstr* i = LibVEX_Alloc(sizeof(PPCInstr));
cerion094d1392005-06-20 13:45:57 +00001023 i->tag = Pin_FpLdSt;
1024 i->Pin.FpLdSt.isLoad = isLoad;
1025 i->Pin.FpLdSt.sz = sz;
1026 i->Pin.FpLdSt.reg = reg;
1027 i->Pin.FpLdSt.addr = addr;
1028 vassert(sz == 4 || sz == 8);
1029 return i;
1030}
sewardj92923de2006-01-25 21:29:48 +00001031PPCInstr* PPCInstr_FpSTFIW ( HReg addr, HReg data )
1032{
1033 PPCInstr* i = LibVEX_Alloc(sizeof(PPCInstr));
1034 i->tag = Pin_FpSTFIW;
1035 i->Pin.FpSTFIW.addr = addr;
1036 i->Pin.FpSTFIW.data = data;
cerion094d1392005-06-20 13:45:57 +00001037 return i;
1038}
sewardj92923de2006-01-25 21:29:48 +00001039PPCInstr* PPCInstr_FpRSP ( HReg dst, HReg src ) {
1040 PPCInstr* i = LibVEX_Alloc(sizeof(PPCInstr));
1041 i->tag = Pin_FpRSP;
1042 i->Pin.FpRSP.dst = dst;
1043 i->Pin.FpRSP.src = src;
cerion094d1392005-06-20 13:45:57 +00001044 return i;
1045}
sewardjc6bbd472012-04-02 10:20:48 +00001046PPCInstr* PPCInstr_Dfp64Unary(PPCFpOp op, HReg dst, HReg src) {
1047 PPCInstr* i = LibVEX_Alloc( sizeof(PPCInstr) );
1048 i->tag = Pin_Dfp64Unary;
1049 i->Pin.Dfp64Unary.op = op;
1050 i->Pin.Dfp64Unary.dst = dst;
1051 i->Pin.Dfp64Unary.src = src;
1052 return i;
1053}
1054PPCInstr* PPCInstr_Dfp64Binary(PPCFpOp op, HReg dst, HReg srcL, HReg srcR) {
1055 PPCInstr* i = LibVEX_Alloc( sizeof(PPCInstr) );
1056 i->tag = Pin_Dfp64Binary;
1057 i->Pin.Dfp64Binary.op = op;
1058 i->Pin.Dfp64Binary.dst = dst;
1059 i->Pin.Dfp64Binary.srcL = srcL;
1060 i->Pin.Dfp64Binary.srcR = srcR;
1061 return i;
1062}
sewardj26217b02012-04-12 17:19:48 +00001063PPCInstr* PPCInstr_DfpShift ( PPCFpOp op, HReg dst, HReg src, PPCRI* shift ) {
1064 PPCInstr* i = LibVEX_Alloc(sizeof(PPCInstr));
1065 i->tag = Pin_DfpShift;
1066 i->Pin.DfpShift.op = op;
1067 i->Pin.DfpShift.shift = shift;
1068 i->Pin.DfpShift.src = src;
1069 i->Pin.DfpShift.dst = dst;
1070 return i;
1071}
1072PPCInstr* PPCInstr_Dfp128Unary(PPCFpOp op, HReg dst_hi, HReg dst_lo,
1073 HReg src_hi, HReg src_lo) {
1074 PPCInstr* i = LibVEX_Alloc( sizeof(PPCInstr) );
1075 i->tag = Pin_Dfp128Unary;
1076 i->Pin.Dfp128Unary.op = op;
1077 i->Pin.Dfp128Unary.dst_hi = dst_hi;
1078 i->Pin.Dfp128Unary.dst_lo = dst_lo;
1079 i->Pin.Dfp128Unary.src_hi = src_hi;
1080 i->Pin.Dfp128Unary.src_lo = src_lo;
1081 return i;
1082}
sewardjc6bbd472012-04-02 10:20:48 +00001083PPCInstr* PPCInstr_Dfp128Binary(PPCFpOp op, HReg dst_hi, HReg dst_lo,
1084 HReg srcR_hi, HReg srcR_lo) {
1085 /* dst is used to pass the srcL argument and return the result */
1086 PPCInstr* i = LibVEX_Alloc( sizeof(PPCInstr) );
1087 i->tag = Pin_Dfp128Binary;
1088 i->Pin.Dfp128Binary.op = op;
1089 i->Pin.Dfp128Binary.dst_hi = dst_hi;
1090 i->Pin.Dfp128Binary.dst_lo = dst_lo;
1091 i->Pin.Dfp128Binary.srcR_hi = srcR_hi;
1092 i->Pin.Dfp128Binary.srcR_lo = srcR_lo;
1093 return i;
1094}
sewardj26217b02012-04-12 17:19:48 +00001095PPCInstr* PPCInstr_DfpShift128 ( PPCFpOp op, HReg dst_hi, HReg dst_lo,
1096 HReg src_hi, HReg src_lo,
1097 PPCRI* shift ) {
1098 PPCInstr* i = LibVEX_Alloc(sizeof(PPCInstr));
1099 i->tag = Pin_DfpShift128;
1100 i->Pin.DfpShift128.op = op;
1101 i->Pin.DfpShift128.shift = shift;
1102 i->Pin.DfpShift128.src_hi = src_hi;
1103 i->Pin.DfpShift128.src_lo = src_lo;
1104 i->Pin.DfpShift128.dst_hi = dst_hi;
1105 i->Pin.DfpShift128.dst_lo = dst_lo;
1106 return i;
1107}
sewardjcdc376d2012-04-23 11:21:12 +00001108PPCInstr* PPCInstr_DfpRound ( HReg dst, HReg src, PPCRI* r_rmc ) {
1109 PPCInstr* i = LibVEX_Alloc(sizeof(PPCInstr));
1110 i->tag = Pin_DfpRound;
1111 i->Pin.DfpRound.dst = dst;
1112 i->Pin.DfpRound.src = src;
1113 i->Pin.DfpRound.r_rmc = r_rmc;
1114 return i;
1115}
1116PPCInstr* PPCInstr_DfpRound128 ( HReg dst_hi, HReg dst_lo, HReg src_hi,
1117 HReg src_lo, PPCRI* r_rmc ) {
1118 PPCInstr* i = LibVEX_Alloc(sizeof(PPCInstr));
1119 i->tag = Pin_DfpRound128;
1120 i->Pin.DfpRound128.dst_hi = dst_hi;
1121 i->Pin.DfpRound128.dst_lo = dst_lo;
1122 i->Pin.DfpRound128.src_hi = src_hi;
1123 i->Pin.DfpRound128.src_lo = src_lo;
1124 i->Pin.DfpRound128.r_rmc = r_rmc;
1125 return i;
1126}
floriana7b0d102012-06-15 20:55:43 +00001127PPCInstr* PPCInstr_DfpQuantize ( PPCFpOp op, HReg dst, HReg srcL, HReg srcR,
sewardjcdc376d2012-04-23 11:21:12 +00001128 PPCRI* rmc ) {
1129 PPCInstr* i = LibVEX_Alloc(sizeof(PPCInstr));
1130 i->tag = Pin_DfpQuantize;
1131 i->Pin.DfpQuantize.op = op;
1132 i->Pin.DfpQuantize.dst = dst;
1133 i->Pin.DfpQuantize.srcL = srcL;
1134 i->Pin.DfpQuantize.srcR = srcR;
1135 i->Pin.DfpQuantize.rmc = rmc;
1136 return i;
1137}
floriana7b0d102012-06-15 20:55:43 +00001138PPCInstr* PPCInstr_DfpQuantize128 ( PPCFpOp op, HReg dst_hi, HReg dst_lo,
sewardjcdc376d2012-04-23 11:21:12 +00001139 HReg src_hi, HReg src_lo, PPCRI* rmc ) {
1140 /* dst is used to pass left operand in and return result */
1141 PPCInstr* i = LibVEX_Alloc(sizeof(PPCInstr));
1142 i->tag = Pin_DfpQuantize128;
1143 i->Pin.DfpQuantize128.op = op;
1144 i->Pin.DfpQuantize128.dst_hi = dst_hi;
1145 i->Pin.DfpQuantize128.dst_lo = dst_lo;
1146 i->Pin.DfpQuantize128.src_hi = src_hi;
1147 i->Pin.DfpQuantize128.src_lo = src_lo;
1148 i->Pin.DfpQuantize128.rmc = rmc;
1149 return i;
1150}
sewardj26217b02012-04-12 17:19:48 +00001151PPCInstr* PPCInstr_DfpD128toD64 ( PPCFpOp op, HReg dst,
1152 HReg src_hi, HReg src_lo ) {
1153 PPCInstr* i = LibVEX_Alloc(sizeof(PPCInstr));
1154 i->tag = Pin_DfpD128toD64;
1155 i->Pin.DfpD128toD64.op = op;
1156 i->Pin.DfpD128toD64.src_hi = src_hi;
1157 i->Pin.DfpD128toD64.src_lo = src_lo;
1158 i->Pin.DfpD128toD64.dst = dst;
1159 return i;
1160}
sewardj26217b02012-04-12 17:19:48 +00001161PPCInstr* PPCInstr_DfpI64StoD128 ( PPCFpOp op, HReg dst_hi,
1162 HReg dst_lo, HReg src ) {
1163 PPCInstr* i = LibVEX_Alloc(sizeof(PPCInstr));
1164 i->tag = Pin_DfpI64StoD128;
1165 i->Pin.DfpI64StoD128.op = op;
1166 i->Pin.DfpI64StoD128.src = src;
1167 i->Pin.DfpI64StoD128.dst_hi = dst_hi;
1168 i->Pin.DfpI64StoD128.dst_lo = dst_lo;
1169 return i;
1170}
sewardjcdc376d2012-04-23 11:21:12 +00001171PPCInstr* PPCInstr_ExtractExpD128 ( PPCFpOp op, HReg dst,
1172 HReg src_hi, HReg src_lo ) {
1173 /* dst is used to pass the srcL argument */
1174 PPCInstr* i = LibVEX_Alloc(sizeof(PPCInstr));
1175 i->tag = Pin_ExtractExpD128;
1176 i->Pin.ExtractExpD128.op = op;
1177 i->Pin.ExtractExpD128.dst = dst;
1178 i->Pin.ExtractExpD128.src_hi = src_hi;
1179 i->Pin.ExtractExpD128.src_lo = src_lo;
1180 return i;
1181}
1182PPCInstr* PPCInstr_InsertExpD128 ( PPCFpOp op, HReg dst_hi, HReg dst_lo,
1183 HReg srcL, HReg srcR_hi, HReg srcR_lo ) {
1184 /* dst is used to pass the srcL argument */
1185 PPCInstr* i = LibVEX_Alloc(sizeof(PPCInstr));
1186 i->tag = Pin_InsertExpD128;
1187 i->Pin.InsertExpD128.op = op;
1188 i->Pin.InsertExpD128.dst_hi = dst_hi;
1189 i->Pin.InsertExpD128.dst_lo = dst_lo;
1190 i->Pin.InsertExpD128.srcL = srcL;
1191 i->Pin.InsertExpD128.srcR_hi = srcR_hi;
1192 i->Pin.InsertExpD128.srcR_lo = srcR_lo;
1193 return i;
1194}
1195PPCInstr* PPCInstr_Dfp64Cmp (/* UInt crfD,*/ HReg dst, HReg srcL, HReg srcR ) {
1196 PPCInstr* i = LibVEX_Alloc(sizeof(PPCInstr));
1197 i->tag = Pin_Dfp64Cmp;
1198 i->Pin.Dfp64Cmp.dst = dst;
1199 i->Pin.Dfp64Cmp.srcL = srcL;
1200 i->Pin.Dfp64Cmp.srcR = srcR;
1201 return i;
1202}
1203PPCInstr* PPCInstr_Dfp128Cmp ( HReg dst, HReg srcL_hi, HReg srcL_lo,
1204 HReg srcR_hi, HReg srcR_lo ) {
1205 PPCInstr* i = LibVEX_Alloc(sizeof(PPCInstr));
1206 i->tag = Pin_Dfp128Cmp;
1207 i->Pin.Dfp128Cmp.dst = dst;
1208 i->Pin.Dfp128Cmp.srcL_hi = srcL_hi;
1209 i->Pin.Dfp128Cmp.srcL_lo = srcL_lo;
1210 i->Pin.Dfp128Cmp.srcR_hi = srcR_hi;
1211 i->Pin.Dfp128Cmp.srcR_lo = srcR_lo;
1212 return i;
1213}
sewardj3dee8492012-04-20 00:13:28 +00001214PPCInstr* PPCInstr_EvCheck ( PPCAMode* amCounter,
1215 PPCAMode* amFailAddr ) {
1216 PPCInstr* i = LibVEX_Alloc(sizeof(PPCInstr));
1217 i->tag = Pin_EvCheck;
1218 i->Pin.EvCheck.amCounter = amCounter;
1219 i->Pin.EvCheck.amFailAddr = amFailAddr;
1220 return i;
1221}
1222PPCInstr* PPCInstr_ProfInc ( void ) {
1223 PPCInstr* i = LibVEX_Alloc(sizeof(PPCInstr));
1224 i->tag = Pin_ProfInc;
1225 return i;
1226}
1227
sewardj7d810d72011-05-08 22:05:10 +00001228/*
1229Valid combo | fromI | int32 | syned | flt64 |
1230--------------------------------------------
1231 | n n n n |
1232--------------------------------------------
1233 F64->I64U | n n n y |
1234--------------------------------------------
1235 | n n y n |
1236--------------------------------------------
1237 F64->I64S | n n y y |
1238--------------------------------------------
1239 | n y n n |
1240--------------------------------------------
1241 F64->I32U | n y n y |
1242--------------------------------------------
1243 | n y y n |
1244--------------------------------------------
1245 F64->I32S | n y y y |
1246--------------------------------------------
1247 I64U->F32 | y n n n |
1248--------------------------------------------
1249 I64U->F64 | y n n y |
1250--------------------------------------------
1251 | y n y n |
1252--------------------------------------------
1253 I64S->F64 | y n y y |
1254--------------------------------------------
1255 | y y n n |
1256--------------------------------------------
1257 | y y n y |
1258--------------------------------------------
1259 | y y y n |
1260--------------------------------------------
1261 | y y y y |
1262--------------------------------------------
1263*/
sewardj66d5ef22011-04-15 11:55:00 +00001264PPCInstr* PPCInstr_FpCftI ( Bool fromI, Bool int32, Bool syned,
sewardj7d810d72011-05-08 22:05:10 +00001265 Bool flt64, HReg dst, HReg src ) {
1266 Bool tmp = fromI | int32 | syned | flt64;
1267 vassert(tmp == True || tmp == False); // iow, no high bits set
1268 UShort conversion = 0;
1269 conversion = (fromI << 3) | (int32 << 2) | (syned << 1) | flt64;
1270 switch (conversion) {
1271 // Supported conversion operations
1272 case 1: case 3: case 5: case 7:
1273 case 8: case 9: case 11:
1274 break;
1275 default:
1276 vpanic("PPCInstr_FpCftI(ppc_host)");
1277 }
sewardj92923de2006-01-25 21:29:48 +00001278 PPCInstr* i = LibVEX_Alloc(sizeof(PPCInstr));
1279 i->tag = Pin_FpCftI;
1280 i->Pin.FpCftI.fromI = fromI;
1281 i->Pin.FpCftI.int32 = int32;
sewardj66d5ef22011-04-15 11:55:00 +00001282 i->Pin.FpCftI.syned = syned;
sewardj7d810d72011-05-08 22:05:10 +00001283 i->Pin.FpCftI.flt64 = flt64;
sewardj92923de2006-01-25 21:29:48 +00001284 i->Pin.FpCftI.dst = dst;
1285 i->Pin.FpCftI.src = src;
cerion07b07a92005-12-22 14:32:35 +00001286 return i;
1287}
cerion5b2325f2005-12-23 00:55:09 +00001288PPCInstr* PPCInstr_FpCMov ( PPCCondCode cond, HReg dst, HReg src ) {
1289 PPCInstr* i = LibVEX_Alloc(sizeof(PPCInstr));
cerion094d1392005-06-20 13:45:57 +00001290 i->tag = Pin_FpCMov;
1291 i->Pin.FpCMov.cond = cond;
1292 i->Pin.FpCMov.dst = dst;
1293 i->Pin.FpCMov.src = src;
1294 vassert(cond.test != Pct_ALWAYS);
1295 return i;
1296}
sewardjc6bbd472012-04-02 10:20:48 +00001297PPCInstr* PPCInstr_FpLdFPSCR ( HReg src, Bool dfp_rm ) {
cerion5b2325f2005-12-23 00:55:09 +00001298 PPCInstr* i = LibVEX_Alloc(sizeof(PPCInstr));
cerion094d1392005-06-20 13:45:57 +00001299 i->tag = Pin_FpLdFPSCR;
1300 i->Pin.FpLdFPSCR.src = src;
sewardjc6bbd472012-04-02 10:20:48 +00001301 i->Pin.FpLdFPSCR.dfp_rm = dfp_rm ? 1 : 0;
cerion094d1392005-06-20 13:45:57 +00001302 return i;
1303}
cerion5b2325f2005-12-23 00:55:09 +00001304PPCInstr* PPCInstr_FpCmp ( HReg dst, HReg srcL, HReg srcR ) {
1305 PPCInstr* i = LibVEX_Alloc(sizeof(PPCInstr));
cerion094d1392005-06-20 13:45:57 +00001306 i->tag = Pin_FpCmp;
1307 i->Pin.FpCmp.dst = dst;
1308 i->Pin.FpCmp.srcL = srcL;
1309 i->Pin.FpCmp.srcR = srcR;
1310 return i;
1311}
cerionbcf8c3e2005-02-04 16:17:07 +00001312
cerion7f000af2005-02-22 20:36:49 +00001313/* Read/Write Link Register */
cerion5b2325f2005-12-23 00:55:09 +00001314PPCInstr* PPCInstr_RdWrLR ( Bool wrLR, HReg gpr ) {
1315 PPCInstr* i = LibVEX_Alloc(sizeof(PPCInstr));
cerion7f000af2005-02-22 20:36:49 +00001316 i->tag = Pin_RdWrLR;
1317 i->Pin.RdWrLR.wrLR = wrLR;
1318 i->Pin.RdWrLR.gpr = gpr;
1319 return i;
1320}
1321
cerionc3d8bdc2005-06-28 18:06:23 +00001322/* AltiVec */
cerion5b2325f2005-12-23 00:55:09 +00001323PPCInstr* PPCInstr_AvLdSt ( Bool isLoad, UChar sz,
1324 HReg reg, PPCAMode* addr ) {
1325 PPCInstr* i = LibVEX_Alloc(sizeof(PPCInstr));
cerionc3d8bdc2005-06-28 18:06:23 +00001326 i->tag = Pin_AvLdSt;
1327 i->Pin.AvLdSt.isLoad = isLoad;
1328 i->Pin.AvLdSt.sz = sz;
1329 i->Pin.AvLdSt.reg = reg;
1330 i->Pin.AvLdSt.addr = addr;
1331 return i;
1332}
cerion5b2325f2005-12-23 00:55:09 +00001333PPCInstr* PPCInstr_AvUnary ( PPCAvOp op, HReg dst, HReg src ) {
1334 PPCInstr* i = LibVEX_Alloc(sizeof(PPCInstr));
cerion8ea0d3e2005-11-14 00:44:47 +00001335 i->tag = Pin_AvUnary;
cerionc3d8bdc2005-06-28 18:06:23 +00001336 i->Pin.AvUnary.op = op;
1337 i->Pin.AvUnary.dst = dst;
1338 i->Pin.AvUnary.src = src;
1339 return i;
1340}
cerion5b2325f2005-12-23 00:55:09 +00001341PPCInstr* PPCInstr_AvBinary ( PPCAvOp op, HReg dst,
1342 HReg srcL, HReg srcR ) {
1343 PPCInstr* i = LibVEX_Alloc(sizeof(PPCInstr));
cerionc3d8bdc2005-06-28 18:06:23 +00001344 i->tag = Pin_AvBinary;
1345 i->Pin.AvBinary.op = op;
1346 i->Pin.AvBinary.dst = dst;
1347 i->Pin.AvBinary.srcL = srcL;
1348 i->Pin.AvBinary.srcR = srcR;
1349 return i;
1350}
cerion5b2325f2005-12-23 00:55:09 +00001351PPCInstr* PPCInstr_AvBin8x16 ( PPCAvOp op, HReg dst,
1352 HReg srcL, HReg srcR ) {
1353 PPCInstr* i = LibVEX_Alloc(sizeof(PPCInstr));
1354 i->tag = Pin_AvBin8x16;
cerion6b6f59e2005-06-28 20:59:18 +00001355 i->Pin.AvBin8x16.op = op;
1356 i->Pin.AvBin8x16.dst = dst;
1357 i->Pin.AvBin8x16.srcL = srcL;
1358 i->Pin.AvBin8x16.srcR = srcR;
1359 return i;
1360}
cerion5b2325f2005-12-23 00:55:09 +00001361PPCInstr* PPCInstr_AvBin16x8 ( PPCAvOp op, HReg dst,
1362 HReg srcL, HReg srcR ) {
1363 PPCInstr* i = LibVEX_Alloc(sizeof(PPCInstr));
1364 i->tag = Pin_AvBin16x8;
cerion6b6f59e2005-06-28 20:59:18 +00001365 i->Pin.AvBin16x8.op = op;
1366 i->Pin.AvBin16x8.dst = dst;
1367 i->Pin.AvBin16x8.srcL = srcL;
1368 i->Pin.AvBin16x8.srcR = srcR;
1369 return i;
1370}
cerion5b2325f2005-12-23 00:55:09 +00001371PPCInstr* PPCInstr_AvBin32x4 ( PPCAvOp op, HReg dst,
1372 HReg srcL, HReg srcR ) {
1373 PPCInstr* i = LibVEX_Alloc(sizeof(PPCInstr));
1374 i->tag = Pin_AvBin32x4;
cerion6b6f59e2005-06-28 20:59:18 +00001375 i->Pin.AvBin32x4.op = op;
1376 i->Pin.AvBin32x4.dst = dst;
1377 i->Pin.AvBin32x4.srcL = srcL;
1378 i->Pin.AvBin32x4.srcR = srcR;
1379 return i;
1380}
carll0c74bb52013-08-12 18:01:40 +00001381PPCInstr* PPCInstr_AvBin64x2 ( PPCAvOp op, HReg dst,
1382 HReg srcL, HReg srcR ) {
1383 PPCInstr* i = LibVEX_Alloc(sizeof(PPCInstr));
1384 i->tag = Pin_AvBin64x2;
1385 i->Pin.AvBin64x2.op = op;
1386 i->Pin.AvBin64x2.dst = dst;
1387 i->Pin.AvBin64x2.srcL = srcL;
1388 i->Pin.AvBin64x2.srcR = srcR;
1389 return i;
1390}
1391
sewardje522d4b2011-04-26 21:36:09 +00001392PPCInstr* PPCInstr_AvBin32Fx4 ( PPCAvFpOp op, HReg dst,
cerion5b2325f2005-12-23 00:55:09 +00001393 HReg srcL, HReg srcR ) {
1394 PPCInstr* i = LibVEX_Alloc(sizeof(PPCInstr));
cerion6b6f59e2005-06-28 20:59:18 +00001395 i->tag = Pin_AvBin32Fx4;
1396 i->Pin.AvBin32Fx4.op = op;
1397 i->Pin.AvBin32Fx4.dst = dst;
1398 i->Pin.AvBin32Fx4.srcL = srcL;
1399 i->Pin.AvBin32Fx4.srcR = srcR;
1400 return i;
1401}
sewardje522d4b2011-04-26 21:36:09 +00001402PPCInstr* PPCInstr_AvUn32Fx4 ( PPCAvFpOp op, HReg dst, HReg src ) {
cerion5b2325f2005-12-23 00:55:09 +00001403 PPCInstr* i = LibVEX_Alloc(sizeof(PPCInstr));
cerion8ea0d3e2005-11-14 00:44:47 +00001404 i->tag = Pin_AvUn32Fx4;
1405 i->Pin.AvUn32Fx4.op = op;
1406 i->Pin.AvUn32Fx4.dst = dst;
1407 i->Pin.AvUn32Fx4.src = src;
1408 return i;
1409}
cerion5b2325f2005-12-23 00:55:09 +00001410PPCInstr* PPCInstr_AvPerm ( HReg dst, HReg srcL, HReg srcR, HReg ctl ) {
1411 PPCInstr* i = LibVEX_Alloc(sizeof(PPCInstr));
cerionc3d8bdc2005-06-28 18:06:23 +00001412 i->tag = Pin_AvPerm;
cerionc3d8bdc2005-06-28 18:06:23 +00001413 i->Pin.AvPerm.dst = dst;
1414 i->Pin.AvPerm.srcL = srcL;
1415 i->Pin.AvPerm.srcR = srcR;
cerion92d9d872005-09-15 21:58:50 +00001416 i->Pin.AvPerm.ctl = ctl;
cerionc3d8bdc2005-06-28 18:06:23 +00001417 return i;
1418}
carll48ae46b2013-10-01 15:45:54 +00001419
cerion5b2325f2005-12-23 00:55:09 +00001420PPCInstr* PPCInstr_AvSel ( HReg ctl, HReg dst, HReg srcL, HReg srcR ) {
1421 PPCInstr* i = LibVEX_Alloc(sizeof(PPCInstr));
cerionc3d8bdc2005-06-28 18:06:23 +00001422 i->tag = Pin_AvSel;
1423 i->Pin.AvSel.ctl = ctl;
1424 i->Pin.AvSel.dst = dst;
1425 i->Pin.AvSel.srcL = srcL;
1426 i->Pin.AvSel.srcR = srcR;
1427 return i;
1428}
carll9877fe52014-10-07 17:49:14 +00001429PPCInstr* PPCInstr_AvSh ( Bool shLeft, HReg dst, PPCAMode* addr ) {
carll99de41e2014-10-07 18:20:39 +00001430 PPCInstr* i = LibVEX_Alloc(sizeof(PPCInstr));
carll9877fe52014-10-07 17:49:14 +00001431 i->tag = Pin_AvSh;
1432 i->Pin.AvSh.shLeft = shLeft;
1433 i->Pin.AvSh.dst = dst;
1434 i->Pin.AvSh.addr = addr;
1435 return i;
1436}
cerion5b2325f2005-12-23 00:55:09 +00001437PPCInstr* PPCInstr_AvShlDbl ( UChar shift, HReg dst,
1438 HReg srcL, HReg srcR ) {
1439 PPCInstr* i = LibVEX_Alloc(sizeof(PPCInstr));
cerionc3d8bdc2005-06-28 18:06:23 +00001440 i->tag = Pin_AvShlDbl;
1441 i->Pin.AvShlDbl.shift = shift;
1442 i->Pin.AvShlDbl.dst = dst;
1443 i->Pin.AvShlDbl.srcL = srcL;
1444 i->Pin.AvShlDbl.srcR = srcR;
1445 return i;
1446}
cerion5b2325f2005-12-23 00:55:09 +00001447PPCInstr* PPCInstr_AvSplat ( UChar sz, HReg dst, PPCVI5s* src ) {
1448 PPCInstr* i = LibVEX_Alloc(sizeof(PPCInstr));
cerionc3d8bdc2005-06-28 18:06:23 +00001449 i->tag = Pin_AvSplat;
1450 i->Pin.AvSplat.sz = sz;
1451 i->Pin.AvSplat.dst = dst;
1452 i->Pin.AvSplat.src = src;
1453 return i;
1454}
cerion5b2325f2005-12-23 00:55:09 +00001455PPCInstr* PPCInstr_AvCMov ( PPCCondCode cond, HReg dst, HReg src ) {
1456 PPCInstr* i = LibVEX_Alloc(sizeof(PPCInstr));
cerion6b6f59e2005-06-28 20:59:18 +00001457 i->tag = Pin_AvCMov;
1458 i->Pin.AvCMov.cond = cond;
1459 i->Pin.AvCMov.dst = dst;
1460 i->Pin.AvCMov.src = src;
1461 vassert(cond.test != Pct_ALWAYS);
1462 return i;
1463}
cerion5b2325f2005-12-23 00:55:09 +00001464PPCInstr* PPCInstr_AvLdVSCR ( HReg src ) {
1465 PPCInstr* i = LibVEX_Alloc(sizeof(PPCInstr));
cerionc3d8bdc2005-06-28 18:06:23 +00001466 i->tag = Pin_AvLdVSCR;
1467 i->Pin.AvLdVSCR.src = src;
1468 return i;
1469}
carll7deaf952013-10-15 18:11:20 +00001470PPCInstr* PPCInstr_AvCipherV128Unary ( PPCAvOp op, HReg dst, HReg src ) {
1471 PPCInstr* i = LibVEX_Alloc(sizeof(PPCInstr));
1472 i->tag = Pin_AvCipherV128Unary;
1473 i->Pin.AvCipherV128Unary.op = op;
1474 i->Pin.AvCipherV128Unary.dst = dst;
1475 i->Pin.AvCipherV128Unary.src = src;
1476 return i;
1477}
1478PPCInstr* PPCInstr_AvCipherV128Binary ( PPCAvOp op, HReg dst,
1479 HReg srcL, HReg srcR ) {
1480 PPCInstr* i = LibVEX_Alloc(sizeof(PPCInstr));
1481 i->tag = Pin_AvCipherV128Binary;
1482 i->Pin.AvCipherV128Binary.op = op;
1483 i->Pin.AvCipherV128Binary.dst = dst;
1484 i->Pin.AvCipherV128Binary.srcL = srcL;
1485 i->Pin.AvCipherV128Binary.srcR = srcR;
1486 return i;
1487}
1488PPCInstr* PPCInstr_AvHashV128Binary ( PPCAvOp op, HReg dst,
1489 HReg src, PPCRI* s_field ) {
1490 PPCInstr* i = LibVEX_Alloc(sizeof(PPCInstr));
1491 i->tag = Pin_AvHashV128Binary;
1492 i->Pin.AvHashV128Binary.op = op;
1493 i->Pin.AvHashV128Binary.dst = dst;
1494 i->Pin.AvHashV128Binary.src = src;
1495 i->Pin.AvHashV128Binary.s_field = s_field;
1496 return i;
1497}
1498PPCInstr* PPCInstr_AvBCDV128Trinary ( PPCAvOp op, HReg dst,
1499 HReg src1, HReg src2, PPCRI* ps ) {
1500 PPCInstr* i = LibVEX_Alloc(sizeof(PPCInstr));
1501 i->tag = Pin_AvBCDV128Trinary;
1502 i->Pin.AvBCDV128Trinary.op = op;
1503 i->Pin.AvBCDV128Trinary.dst = dst;
1504 i->Pin.AvBCDV128Trinary.src1 = src1;
1505 i->Pin.AvBCDV128Trinary.src2 = src2;
1506 i->Pin.AvBCDV128Trinary.ps = ps;
1507 return i;
1508}
cerionc3d8bdc2005-06-28 18:06:23 +00001509
cerion9e263e32005-03-03 17:21:51 +00001510
1511/* Pretty Print instructions */
cerionf0de28c2005-12-13 20:21:11 +00001512static void ppLoadImm ( HReg dst, ULong imm, Bool mode64 ) {
cerionf0de28c2005-12-13 20:21:11 +00001513 vex_printf("li_word ");
cerion5b2325f2005-12-23 00:55:09 +00001514 ppHRegPPC(dst);
cerionf0de28c2005-12-13 20:21:11 +00001515 if (!mode64) {
cerionf0de28c2005-12-13 20:21:11 +00001516 vex_printf(",0x%08x", (UInt)imm);
1517 } else {
1518 vex_printf(",0x%016llx", imm);
1519 }
cerion9e263e32005-03-03 17:21:51 +00001520}
1521
1522static void ppMovReg ( HReg dst, HReg src ) {
1523 if (hregNumber(dst) != hregNumber(src)) {
1524 vex_printf("mr ");
cerion5b2325f2005-12-23 00:55:09 +00001525 ppHRegPPC(dst);
cerion9e263e32005-03-03 17:21:51 +00001526 vex_printf(",");
cerion5b2325f2005-12-23 00:55:09 +00001527 ppHRegPPC(src);
cerion9e263e32005-03-03 17:21:51 +00001528 }
1529}
1530
floriand8c64e02014-10-08 08:54:44 +00001531void ppPPCInstr ( const PPCInstr* i, Bool mode64 )
cerionbcf8c3e2005-02-04 16:17:07 +00001532{
1533 switch (i->tag) {
cerionf0de28c2005-12-13 20:21:11 +00001534 case Pin_LI:
1535 ppLoadImm(i->Pin.LI.dst, i->Pin.LI.imm64, mode64);
sewardjb51f0f42005-07-18 11:38:02 +00001536 break;
cerionf0de28c2005-12-13 20:21:11 +00001537 case Pin_Alu: {
cerion5b2325f2005-12-23 00:55:09 +00001538 HReg r_srcL = i->Pin.Alu.srcL;
1539 PPCRH* rh_srcR = i->Pin.Alu.srcR;
sewardjb51f0f42005-07-18 11:38:02 +00001540 /* special-case "mr" */
cerionf0de28c2005-12-13 20:21:11 +00001541 if (i->Pin.Alu.op == Palu_OR && // or Rd,Rs,Rs == mr Rd,Rs
1542 rh_srcR->tag == Prh_Reg &&
florian79efdc62013-02-11 00:47:35 +00001543 sameHReg(rh_srcR->Prh.Reg.reg, r_srcL)) {
cerionb85e8bb2005-02-16 08:54:33 +00001544 vex_printf("mr ");
cerion5b2325f2005-12-23 00:55:09 +00001545 ppHRegPPC(i->Pin.Alu.dst);
cerioncd304492005-02-08 19:40:24 +00001546 vex_printf(",");
cerion5b2325f2005-12-23 00:55:09 +00001547 ppHRegPPC(r_srcL);
cerionbb01b7c2005-12-16 13:40:18 +00001548 return;
1549 }
1550 /* special-case "li" */
1551 if (i->Pin.Alu.op == Palu_ADD && // addi Rd,0,imm == li Rd,imm
1552 rh_srcR->tag == Prh_Imm &&
1553 hregNumber(r_srcL) == 0) {
1554 vex_printf("li ");
cerion5b2325f2005-12-23 00:55:09 +00001555 ppHRegPPC(i->Pin.Alu.dst);
cerionb8c3b7f2005-03-01 20:27:49 +00001556 vex_printf(",");
cerion5b2325f2005-12-23 00:55:09 +00001557 ppPPCRH(rh_srcR);
cerionbb01b7c2005-12-16 13:40:18 +00001558 return;
cerionb8c3b7f2005-03-01 20:27:49 +00001559 }
cerionbb01b7c2005-12-16 13:40:18 +00001560 /* generic */
cerion5b2325f2005-12-23 00:55:09 +00001561 vex_printf("%s ", showPPCAluOp(i->Pin.Alu.op,
1562 toBool(rh_srcR->tag == Prh_Imm)));
1563 ppHRegPPC(i->Pin.Alu.dst);
cerionbb01b7c2005-12-16 13:40:18 +00001564 vex_printf(",");
cerion5b2325f2005-12-23 00:55:09 +00001565 ppHRegPPC(r_srcL);
cerionbb01b7c2005-12-16 13:40:18 +00001566 vex_printf(",");
cerion5b2325f2005-12-23 00:55:09 +00001567 ppPPCRH(rh_srcR);
cerionbb01b7c2005-12-16 13:40:18 +00001568 return;
1569 }
1570 case Pin_Shft: {
cerion5b2325f2005-12-23 00:55:09 +00001571 HReg r_srcL = i->Pin.Shft.srcL;
1572 PPCRH* rh_srcR = i->Pin.Shft.srcR;
1573 vex_printf("%s ", showPPCShftOp(i->Pin.Shft.op,
1574 toBool(rh_srcR->tag == Prh_Imm),
1575 i->Pin.Shft.sz32));
1576 ppHRegPPC(i->Pin.Shft.dst);
cerionbb01b7c2005-12-16 13:40:18 +00001577 vex_printf(",");
cerion5b2325f2005-12-23 00:55:09 +00001578 ppHRegPPC(r_srcL);
cerionbb01b7c2005-12-16 13:40:18 +00001579 vex_printf(",");
cerion5b2325f2005-12-23 00:55:09 +00001580 ppPPCRH(rh_srcR);
cerionb85e8bb2005-02-16 08:54:33 +00001581 return;
cerionf0de28c2005-12-13 20:21:11 +00001582 }
cerion5b2325f2005-12-23 00:55:09 +00001583 case Pin_AddSubC:
cerion4a49b032005-11-08 16:23:07 +00001584 vex_printf("%s%s ",
cerion5b2325f2005-12-23 00:55:09 +00001585 i->Pin.AddSubC.isAdd ? "add" : "sub",
1586 i->Pin.AddSubC.setC ? "c" : "e");
1587 ppHRegPPC(i->Pin.AddSubC.dst);
cerion4a49b032005-11-08 16:23:07 +00001588 vex_printf(",");
cerion5b2325f2005-12-23 00:55:09 +00001589 ppHRegPPC(i->Pin.AddSubC.srcL);
cerion4a49b032005-11-08 16:23:07 +00001590 vex_printf(",");
cerion5b2325f2005-12-23 00:55:09 +00001591 ppHRegPPC(i->Pin.AddSubC.srcR);
cerion4a49b032005-11-08 16:23:07 +00001592 return;
cerionf0de28c2005-12-13 20:21:11 +00001593 case Pin_Cmp:
cerionbb01b7c2005-12-16 13:40:18 +00001594 vex_printf("%s%c%s %%cr%u,",
cerionf0de28c2005-12-13 20:21:11 +00001595 i->Pin.Cmp.syned ? "cmp" : "cmpl",
cerionbb01b7c2005-12-16 13:40:18 +00001596 i->Pin.Cmp.sz32 ? 'w' : 'd',
cerionf0de28c2005-12-13 20:21:11 +00001597 i->Pin.Cmp.srcR->tag == Prh_Imm ? "i" : "",
1598 i->Pin.Cmp.crfD);
cerion5b2325f2005-12-23 00:55:09 +00001599 ppHRegPPC(i->Pin.Cmp.srcL);
cerionb85e8bb2005-02-16 08:54:33 +00001600 vex_printf(",");
cerion5b2325f2005-12-23 00:55:09 +00001601 ppPPCRH(i->Pin.Cmp.srcR);
cerionb85e8bb2005-02-16 08:54:33 +00001602 return;
cerionf0de28c2005-12-13 20:21:11 +00001603 case Pin_Unary:
cerion5b2325f2005-12-23 00:55:09 +00001604 vex_printf("%s ", showPPCUnaryOp(i->Pin.Unary.op));
1605 ppHRegPPC(i->Pin.Unary.dst);
cerionb85e8bb2005-02-16 08:54:33 +00001606 vex_printf(",");
cerion5b2325f2005-12-23 00:55:09 +00001607 ppHRegPPC(i->Pin.Unary.src);
cerionb85e8bb2005-02-16 08:54:33 +00001608 return;
1609 case Pin_MulL:
cerionbb01b7c2005-12-16 13:40:18 +00001610 vex_printf("mul%c%c%s ",
1611 i->Pin.MulL.hi ? 'h' : 'l',
1612 i->Pin.MulL.sz32 ? 'w' : 'd',
cerionf0de28c2005-12-13 20:21:11 +00001613 i->Pin.MulL.hi ? (i->Pin.MulL.syned ? "s" : "u") : "");
cerion5b2325f2005-12-23 00:55:09 +00001614 ppHRegPPC(i->Pin.MulL.dst);
cerionb85e8bb2005-02-16 08:54:33 +00001615 vex_printf(",");
cerion5b2325f2005-12-23 00:55:09 +00001616 ppHRegPPC(i->Pin.MulL.srcL);
cerionb85e8bb2005-02-16 08:54:33 +00001617 vex_printf(",");
cerion5b2325f2005-12-23 00:55:09 +00001618 ppHRegPPC(i->Pin.MulL.srcR);
cerionb85e8bb2005-02-16 08:54:33 +00001619 return;
1620 case Pin_Div:
sewardj4aa412a2011-07-24 14:13:21 +00001621 vex_printf("div%c%s%s ",
cerionbb01b7c2005-12-16 13:40:18 +00001622 i->Pin.Div.sz32 ? 'w' : 'd',
sewardj4aa412a2011-07-24 14:13:21 +00001623 i->Pin.Div.extended ? "e" : "",
cerionb85e8bb2005-02-16 08:54:33 +00001624 i->Pin.Div.syned ? "" : "u");
cerion5b2325f2005-12-23 00:55:09 +00001625 ppHRegPPC(i->Pin.Div.dst);
cerionb85e8bb2005-02-16 08:54:33 +00001626 vex_printf(",");
cerion5b2325f2005-12-23 00:55:09 +00001627 ppHRegPPC(i->Pin.Div.srcL);
cerionb85e8bb2005-02-16 08:54:33 +00001628 vex_printf(",");
cerion5b2325f2005-12-23 00:55:09 +00001629 ppHRegPPC(i->Pin.Div.srcR);
cerionb85e8bb2005-02-16 08:54:33 +00001630 return;
sewardj6a64a9f2005-08-21 00:48:37 +00001631 case Pin_Call: {
1632 Int n;
cerion8c51ed42005-02-22 11:16:54 +00001633 vex_printf("call: ");
1634 if (i->Pin.Call.cond.test != Pct_ALWAYS) {
cerion5b2325f2005-12-23 00:55:09 +00001635 vex_printf("if (%s) ", showPPCCondCode(i->Pin.Call.cond));
cerion8c51ed42005-02-22 11:16:54 +00001636 }
1637 vex_printf("{ ");
cerionf0de28c2005-12-13 20:21:11 +00001638 ppLoadImm(hregPPC_GPR10(mode64), i->Pin.Call.target, mode64);
1639 vex_printf(" ; mtctr r10 ; bctrl [");
sewardj6a64a9f2005-08-21 00:48:37 +00001640 for (n = 0; n < 32; n++) {
1641 if (i->Pin.Call.argiregs & (1<<n)) {
1642 vex_printf("r%d", n);
1643 if ((i->Pin.Call.argiregs >> n) > 1)
1644 vex_printf(",");
1645 }
1646 }
sewardjcfe046e2013-01-17 14:23:53 +00001647 vex_printf(",");
1648 ppRetLoc(i->Pin.Call.rloc);
sewardj6a64a9f2005-08-21 00:48:37 +00001649 vex_printf("] }");
cerionb85e8bb2005-02-16 08:54:33 +00001650 break;
sewardj6a64a9f2005-08-21 00:48:37 +00001651 }
sewardj3dee8492012-04-20 00:13:28 +00001652 case Pin_XDirect:
1653 vex_printf("(xDirect) ");
1654 vex_printf("if (%s) { ",
1655 showPPCCondCode(i->Pin.XDirect.cond));
1656 if (mode64) {
1657 vex_printf("imm64 r30,0x%llx; ", i->Pin.XDirect.dstGA);
1658 vex_printf("std r30,");
cerione97e1062005-02-21 15:09:19 +00001659 } else {
sewardj3dee8492012-04-20 00:13:28 +00001660 vex_printf("imm32 r30,0x%llx; ", i->Pin.XDirect.dstGA);
1661 vex_printf("stw r30,");
cerione97e1062005-02-21 15:09:19 +00001662 }
sewardj3dee8492012-04-20 00:13:28 +00001663 ppPPCAMode(i->Pin.XDirect.amCIA);
1664 vex_printf("; ");
1665 if (mode64) {
1666 vex_printf("imm64-fixed5 r30,$disp_cp_chain_me_to_%sEP; ",
1667 i->Pin.XDirect.toFastEP ? "fast" : "slow");
1668 } else {
1669 vex_printf("imm32-fixed2 r30,$disp_cp_chain_me_to_%sEP; ",
1670 i->Pin.XDirect.toFastEP ? "fast" : "slow");
1671 }
1672 vex_printf("mtctr r30; bctrl }");
1673 return;
1674 case Pin_XIndir:
1675 vex_printf("(xIndir) ");
1676 vex_printf("if (%s) { ",
1677 showPPCCondCode(i->Pin.XIndir.cond));
1678 vex_printf("%s ", mode64 ? "std" : "stw");
1679 ppHRegPPC(i->Pin.XIndir.dstGA);
1680 vex_printf(",");
1681 ppPPCAMode(i->Pin.XIndir.amCIA);
1682 vex_printf("; ");
1683 vex_printf("imm%s r30,$disp_cp_xindir; ", mode64 ? "64" : "32");
1684 vex_printf("mtctr r30; bctr }");
1685 return;
1686 case Pin_XAssisted:
1687 vex_printf("(xAssisted) ");
1688 vex_printf("if (%s) { ",
1689 showPPCCondCode(i->Pin.XAssisted.cond));
1690 vex_printf("%s ", mode64 ? "std" : "stw");
1691 ppHRegPPC(i->Pin.XAssisted.dstGA);
1692 vex_printf(",");
1693 ppPPCAMode(i->Pin.XAssisted.amCIA);
1694 vex_printf("; ");
1695 vex_printf("li r31,$IRJumpKind_to_TRCVAL(%d); ",
1696 (Int)i->Pin.XAssisted.jk);
1697 vex_printf("imm%s r30,$disp_cp_xindir; ", mode64 ? "64" : "32");
1698 vex_printf("mtctr r30; bctr }");
cerionb85e8bb2005-02-16 08:54:33 +00001699 return;
cerionf0de28c2005-12-13 20:21:11 +00001700 case Pin_CMov:
cerion5b2325f2005-12-23 00:55:09 +00001701 vex_printf("cmov (%s) ", showPPCCondCode(i->Pin.CMov.cond));
1702 ppHRegPPC(i->Pin.CMov.dst);
cerionb85e8bb2005-02-16 08:54:33 +00001703 vex_printf(",");
cerion5b2325f2005-12-23 00:55:09 +00001704 ppPPCRI(i->Pin.CMov.src);
cerion8c51ed42005-02-22 11:16:54 +00001705 vex_printf(": ");
cerionf0de28c2005-12-13 20:21:11 +00001706 if (i->Pin.CMov.cond.test != Pct_ALWAYS) {
cerion5b2325f2005-12-23 00:55:09 +00001707 vex_printf("if (%s) ", showPPCCondCode(i->Pin.CMov.cond));
cerion8c51ed42005-02-22 11:16:54 +00001708 }
1709 vex_printf("{ ");
cerionf0de28c2005-12-13 20:21:11 +00001710 if (i->Pin.CMov.src->tag == Pri_Imm) {
1711 ppLoadImm(i->Pin.CMov.dst, i->Pin.CMov.src->Pri.Imm, mode64);
cerion8c51ed42005-02-22 11:16:54 +00001712 } else {
cerionf0de28c2005-12-13 20:21:11 +00001713 ppMovReg(i->Pin.CMov.dst, i->Pin.CMov.src->Pri.Reg);
cerion8c51ed42005-02-22 11:16:54 +00001714 }
1715 vex_printf(" }");
cerionb85e8bb2005-02-16 08:54:33 +00001716 return;
cerion7cf8e4e2005-02-16 16:08:17 +00001717 case Pin_Load: {
sewardj428fabd2005-03-21 03:11:17 +00001718 Bool idxd = toBool(i->Pin.Load.src->tag == Pam_RR);
cerionf0de28c2005-12-13 20:21:11 +00001719 UChar sz = i->Pin.Load.sz;
florian5df8ab02012-10-13 19:34:19 +00001720 HChar c_sz = sz==1 ? 'b' : sz==2 ? 'h' : sz==4 ? 'w' : 'd';
sewardj34085e32007-03-09 18:07:00 +00001721 vex_printf("l%c%s%s ", c_sz, sz==8 ? "" : "z", idxd ? "x" : "" );
cerion5b2325f2005-12-23 00:55:09 +00001722 ppHRegPPC(i->Pin.Load.dst);
cerionb85e8bb2005-02-16 08:54:33 +00001723 vex_printf(",");
cerion5b2325f2005-12-23 00:55:09 +00001724 ppPPCAMode(i->Pin.Load.src);
cerionb85e8bb2005-02-16 08:54:33 +00001725 return;
1726 }
sewardje9d8a262009-07-01 08:06:34 +00001727 case Pin_LoadL:
1728 vex_printf("l%carx ", i->Pin.LoadL.sz==4 ? 'w' : 'd');
1729 ppHRegPPC(i->Pin.LoadL.dst);
1730 vex_printf(",%%r0,");
1731 ppHRegPPC(i->Pin.LoadL.src);
1732 return;
cerionb85e8bb2005-02-16 08:54:33 +00001733 case Pin_Store: {
1734 UChar sz = i->Pin.Store.sz;
sewardj428fabd2005-03-21 03:11:17 +00001735 Bool idxd = toBool(i->Pin.Store.dst->tag == Pam_RR);
florian5df8ab02012-10-13 19:34:19 +00001736 HChar c_sz = sz==1 ? 'b' : sz==2 ? 'h' : sz==4 ? 'w' : /*8*/ 'd';
cerionf0de28c2005-12-13 20:21:11 +00001737 vex_printf("st%c%s ", c_sz, idxd ? "x" : "" );
cerion5b2325f2005-12-23 00:55:09 +00001738 ppHRegPPC(i->Pin.Store.src);
cerionb85e8bb2005-02-16 08:54:33 +00001739 vex_printf(",");
cerion5b2325f2005-12-23 00:55:09 +00001740 ppPPCAMode(i->Pin.Store.dst);
cerionb85e8bb2005-02-16 08:54:33 +00001741 return;
1742 }
sewardje9d8a262009-07-01 08:06:34 +00001743 case Pin_StoreC:
1744 vex_printf("st%ccx. ", i->Pin.StoreC.sz==4 ? 'w' : 'd');
1745 ppHRegPPC(i->Pin.StoreC.src);
1746 vex_printf(",%%r0,");
1747 ppHRegPPC(i->Pin.StoreC.dst);
1748 return;
cerion5b2325f2005-12-23 00:55:09 +00001749 case Pin_Set: {
1750 PPCCondCode cc = i->Pin.Set.cond;
1751 vex_printf("set (%s),", showPPCCondCode(cc));
1752 ppHRegPPC(i->Pin.Set.dst);
cerionf9d6e222005-02-23 18:21:31 +00001753 if (cc.test == Pct_ALWAYS) {
1754 vex_printf(": { li ");
cerion5b2325f2005-12-23 00:55:09 +00001755 ppHRegPPC(i->Pin.Set.dst);
cerionf9d6e222005-02-23 18:21:31 +00001756 vex_printf(",1 }");
1757 } else {
1758 vex_printf(": { mfcr r0 ; rlwinm ");
cerion5b2325f2005-12-23 00:55:09 +00001759 ppHRegPPC(i->Pin.Set.dst);
sewardj428fabd2005-03-21 03:11:17 +00001760 vex_printf(",r0,%u,31,31", cc.flag+1);
cerionf9d6e222005-02-23 18:21:31 +00001761 if (cc.test == Pct_FALSE) {
1762 vex_printf("; xori ");
cerion5b2325f2005-12-23 00:55:09 +00001763 ppHRegPPC(i->Pin.Set.dst);
cerionf9d6e222005-02-23 18:21:31 +00001764 vex_printf(",");
cerion5b2325f2005-12-23 00:55:09 +00001765 ppHRegPPC(i->Pin.Set.dst);
sewardjf7745052005-12-16 01:06:42 +00001766 vex_printf(",1");
cerionf9d6e222005-02-23 18:21:31 +00001767 }
1768 vex_printf(" }");
1769 }
cerionb85e8bb2005-02-16 08:54:33 +00001770 return;
cerionf9d6e222005-02-23 18:21:31 +00001771 }
sewardjb51f0f42005-07-18 11:38:02 +00001772 case Pin_MfCR:
1773 vex_printf("mfcr ");
cerion5b2325f2005-12-23 00:55:09 +00001774 ppHRegPPC(i->Pin.MfCR.dst);
sewardjb51f0f42005-07-18 11:38:02 +00001775 break;
cerionb85e8bb2005-02-16 08:54:33 +00001776 case Pin_MFence:
cerion98411db2005-02-16 14:14:49 +00001777 vex_printf("mfence (=sync)");
cerionb85e8bb2005-02-16 08:54:33 +00001778 return;
cerion094d1392005-06-20 13:45:57 +00001779
1780 case Pin_FpUnary:
cerion5b2325f2005-12-23 00:55:09 +00001781 vex_printf("%s ", showPPCFpOp(i->Pin.FpUnary.op));
1782 ppHRegPPC(i->Pin.FpUnary.dst);
cerion094d1392005-06-20 13:45:57 +00001783 vex_printf(",");
cerion5b2325f2005-12-23 00:55:09 +00001784 ppHRegPPC(i->Pin.FpUnary.src);
cerion094d1392005-06-20 13:45:57 +00001785 return;
1786 case Pin_FpBinary:
cerion5b2325f2005-12-23 00:55:09 +00001787 vex_printf("%s ", showPPCFpOp(i->Pin.FpBinary.op));
1788 ppHRegPPC(i->Pin.FpBinary.dst);
cerion094d1392005-06-20 13:45:57 +00001789 vex_printf(",");
cerion5b2325f2005-12-23 00:55:09 +00001790 ppHRegPPC(i->Pin.FpBinary.srcL);
cerion094d1392005-06-20 13:45:57 +00001791 vex_printf(",");
cerion5b2325f2005-12-23 00:55:09 +00001792 ppHRegPPC(i->Pin.FpBinary.srcR);
cerion094d1392005-06-20 13:45:57 +00001793 return;
sewardj40c80262006-02-08 19:30:46 +00001794 case Pin_FpMulAcc:
1795 vex_printf("%s ", showPPCFpOp(i->Pin.FpMulAcc.op));
1796 ppHRegPPC(i->Pin.FpMulAcc.dst);
1797 vex_printf(",");
1798 ppHRegPPC(i->Pin.FpMulAcc.srcML);
1799 vex_printf(",");
1800 ppHRegPPC(i->Pin.FpMulAcc.srcMR);
1801 vex_printf(",");
1802 ppHRegPPC(i->Pin.FpMulAcc.srcAcc);
1803 return;
cerion094d1392005-06-20 13:45:57 +00001804 case Pin_FpLdSt: {
1805 UChar sz = i->Pin.FpLdSt.sz;
1806 Bool idxd = toBool(i->Pin.FpLdSt.addr->tag == Pam_RR);
1807 if (i->Pin.FpLdSt.isLoad) {
1808 vex_printf("lf%c%s ",
1809 (sz==4 ? 's' : 'd'),
1810 idxd ? "x" : "" );
cerion5b2325f2005-12-23 00:55:09 +00001811 ppHRegPPC(i->Pin.FpLdSt.reg);
cerion094d1392005-06-20 13:45:57 +00001812 vex_printf(",");
cerion5b2325f2005-12-23 00:55:09 +00001813 ppPPCAMode(i->Pin.FpLdSt.addr);
cerion094d1392005-06-20 13:45:57 +00001814 } else {
1815 vex_printf("stf%c%s ",
1816 (sz==4 ? 's' : 'd'),
1817 idxd ? "x" : "" );
cerion5b2325f2005-12-23 00:55:09 +00001818 ppHRegPPC(i->Pin.FpLdSt.reg);
cerion094d1392005-06-20 13:45:57 +00001819 vex_printf(",");
cerion5b2325f2005-12-23 00:55:09 +00001820 ppPPCAMode(i->Pin.FpLdSt.addr);
cerion094d1392005-06-20 13:45:57 +00001821 }
1822 return;
1823 }
sewardj92923de2006-01-25 21:29:48 +00001824 case Pin_FpSTFIW:
1825 vex_printf("stfiwz ");
1826 ppHRegPPC(i->Pin.FpSTFIW.data);
1827 vex_printf(",0(");
1828 ppHRegPPC(i->Pin.FpSTFIW.addr);
1829 vex_printf(")");
1830 return;
1831 case Pin_FpRSP:
cerion094d1392005-06-20 13:45:57 +00001832 vex_printf("frsp ");
sewardj92923de2006-01-25 21:29:48 +00001833 ppHRegPPC(i->Pin.FpRSP.dst);
cerion094d1392005-06-20 13:45:57 +00001834 vex_printf(",");
sewardj92923de2006-01-25 21:29:48 +00001835 ppHRegPPC(i->Pin.FpRSP.src);
cerion094d1392005-06-20 13:45:57 +00001836 return;
sewardj92923de2006-01-25 21:29:48 +00001837 case Pin_FpCftI: {
florian55085f82012-11-21 00:36:55 +00001838 const HChar* str = "fc?????";
sewardj4aa412a2011-07-24 14:13:21 +00001839 /* Note that "fcfids" is missing from below. That instruction would
1840 * satisfy the predicate:
1841 * (i->Pin.FpCftI.fromI == True && i->Pin.FpCftI.int32 == False)
1842 * which would go into a final "else" clause to make this if-else
1843 * block balanced. But we're able to implement fcfids by leveraging
1844 * the fcfid implementation, so it wasn't necessary to include it here.
1845 */
sewardj92923de2006-01-25 21:29:48 +00001846 if (i->Pin.FpCftI.fromI == False && i->Pin.FpCftI.int32 == False)
sewardj66d5ef22011-04-15 11:55:00 +00001847 if (i->Pin.FpCftI.syned == True)
sewardj4aa412a2011-07-24 14:13:21 +00001848 str = "fctid";
sewardj66d5ef22011-04-15 11:55:00 +00001849 else
sewardj4aa412a2011-07-24 14:13:21 +00001850 str = "fctidu";
1851 else if (i->Pin.FpCftI.fromI == False && i->Pin.FpCftI.int32 == True)
1852 if (i->Pin.FpCftI.syned == True)
1853 str = "fctiw";
1854 else
1855 str = "fctiwu";
1856 else if (i->Pin.FpCftI.fromI == True && i->Pin.FpCftI.int32 == False) {
1857 if (i->Pin.FpCftI.syned == True) {
1858 str = "fcfid";
1859 } else {
1860 if (i->Pin.FpCftI.flt64 == True)
1861 str = "fcfidu";
1862 else
1863 str = "fcfidus";
1864 }
sewardj66d5ef22011-04-15 11:55:00 +00001865 }
sewardj92923de2006-01-25 21:29:48 +00001866 vex_printf("%s ", str);
1867 ppHRegPPC(i->Pin.FpCftI.dst);
1868 vex_printf(",");
1869 ppHRegPPC(i->Pin.FpCftI.src);
cerion094d1392005-06-20 13:45:57 +00001870 return;
sewardj92923de2006-01-25 21:29:48 +00001871 }
cerion094d1392005-06-20 13:45:57 +00001872 case Pin_FpCMov:
cerion5b2325f2005-12-23 00:55:09 +00001873 vex_printf("fpcmov (%s) ", showPPCCondCode(i->Pin.FpCMov.cond));
1874 ppHRegPPC(i->Pin.FpCMov.dst);
cerion094d1392005-06-20 13:45:57 +00001875 vex_printf(",");
cerion5b2325f2005-12-23 00:55:09 +00001876 ppHRegPPC(i->Pin.FpCMov.src);
cerion094d1392005-06-20 13:45:57 +00001877 vex_printf(": ");
1878 vex_printf("if (fr_dst != fr_src) { ");
1879 if (i->Pin.FpCMov.cond.test != Pct_ALWAYS) {
cerion5b2325f2005-12-23 00:55:09 +00001880 vex_printf("if (%s) { ", showPPCCondCode(i->Pin.FpCMov.cond));
cerion094d1392005-06-20 13:45:57 +00001881 }
1882 vex_printf("fmr ");
cerion5b2325f2005-12-23 00:55:09 +00001883 ppHRegPPC(i->Pin.FpCMov.dst);
cerion094d1392005-06-20 13:45:57 +00001884 vex_printf(",");
cerion5b2325f2005-12-23 00:55:09 +00001885 ppHRegPPC(i->Pin.FpCMov.src);
cerion094d1392005-06-20 13:45:57 +00001886 if (i->Pin.FpCMov.cond.test != Pct_ALWAYS)
1887 vex_printf(" }");
1888 vex_printf(" }");
1889 return;
1890 case Pin_FpLdFPSCR:
1891 vex_printf("mtfsf 0xFF,");
cerion5b2325f2005-12-23 00:55:09 +00001892 ppHRegPPC(i->Pin.FpLdFPSCR.src);
sewardjc6bbd472012-04-02 10:20:48 +00001893 vex_printf(",0, %s", i->Pin.FpLdFPSCR.dfp_rm ? "1" : "0");
cerion094d1392005-06-20 13:45:57 +00001894 return;
1895 case Pin_FpCmp:
sewardjb51f0f42005-07-18 11:38:02 +00001896 vex_printf("fcmpo %%cr1,");
cerion5b2325f2005-12-23 00:55:09 +00001897 ppHRegPPC(i->Pin.FpCmp.srcL);
cerion094d1392005-06-20 13:45:57 +00001898 vex_printf(",");
cerion5b2325f2005-12-23 00:55:09 +00001899 ppHRegPPC(i->Pin.FpCmp.srcR);
cerion094d1392005-06-20 13:45:57 +00001900 vex_printf("; mfcr ");
cerion5b2325f2005-12-23 00:55:09 +00001901 ppHRegPPC(i->Pin.FpCmp.dst);
cerion094d1392005-06-20 13:45:57 +00001902 vex_printf("; rlwinm ");
cerion5b2325f2005-12-23 00:55:09 +00001903 ppHRegPPC(i->Pin.FpCmp.dst);
cerion094d1392005-06-20 13:45:57 +00001904 vex_printf(",");
cerion5b2325f2005-12-23 00:55:09 +00001905 ppHRegPPC(i->Pin.FpCmp.dst);
cerion094d1392005-06-20 13:45:57 +00001906 vex_printf(",8,28,31");
1907 return;
cerionbcf8c3e2005-02-04 16:17:07 +00001908
cerion7f000af2005-02-22 20:36:49 +00001909 case Pin_RdWrLR:
1910 vex_printf("%s ", i->Pin.RdWrLR.wrLR ? "mtlr" : "mflr");
cerion5b2325f2005-12-23 00:55:09 +00001911 ppHRegPPC(i->Pin.RdWrLR.gpr);
cerion7f000af2005-02-22 20:36:49 +00001912 return;
1913
cerionc3d8bdc2005-06-28 18:06:23 +00001914 case Pin_AvLdSt: {
sewardj197bd172005-10-12 11:34:33 +00001915 UChar sz = i->Pin.AvLdSt.sz;
florian55085f82012-11-21 00:36:55 +00001916 const HChar* str_size;
cerionc3d8bdc2005-06-28 18:06:23 +00001917 if (i->Pin.AvLdSt.addr->tag == Pam_IR) {
cerionf0de28c2005-12-13 20:21:11 +00001918 ppLoadImm(hregPPC_GPR30(mode64),
floriane6be61f2013-02-01 16:11:51 +00001919 i->Pin.AvLdSt.addr->Pam.IR.index, mode64);
cerion01713102005-06-29 19:05:08 +00001920 vex_printf(" ; ");
cerionc3d8bdc2005-06-28 18:06:23 +00001921 }
sewardj197bd172005-10-12 11:34:33 +00001922 str_size = sz==1 ? "eb" : sz==2 ? "eh" : sz==4 ? "ew" : "";
cerion01713102005-06-29 19:05:08 +00001923 if (i->Pin.AvLdSt.isLoad)
cerion225a0342005-09-12 20:49:09 +00001924 vex_printf("lv%sx ", str_size);
cerion01713102005-06-29 19:05:08 +00001925 else
cerion225a0342005-09-12 20:49:09 +00001926 vex_printf("stv%sx ", str_size);
cerion5b2325f2005-12-23 00:55:09 +00001927 ppHRegPPC(i->Pin.AvLdSt.reg);
cerion01713102005-06-29 19:05:08 +00001928 vex_printf(",");
1929 if (i->Pin.AvLdSt.addr->tag == Pam_IR)
1930 vex_printf("%%r30");
1931 else
cerion5b2325f2005-12-23 00:55:09 +00001932 ppHRegPPC(i->Pin.AvLdSt.addr->Pam.RR.index);
cerion01713102005-06-29 19:05:08 +00001933 vex_printf(",");
cerion5b2325f2005-12-23 00:55:09 +00001934 ppHRegPPC(i->Pin.AvLdSt.addr->Pam.RR.base);
cerionc3d8bdc2005-06-28 18:06:23 +00001935 return;
1936 }
1937 case Pin_AvUnary:
cerion5b2325f2005-12-23 00:55:09 +00001938 vex_printf("%s ", showPPCAvOp(i->Pin.AvUnary.op));
1939 ppHRegPPC(i->Pin.AvUnary.dst);
cerionc3d8bdc2005-06-28 18:06:23 +00001940 vex_printf(",");
cerion5b2325f2005-12-23 00:55:09 +00001941 ppHRegPPC(i->Pin.AvUnary.src);
cerionc3d8bdc2005-06-28 18:06:23 +00001942 return;
1943 case Pin_AvBinary:
cerion5b2325f2005-12-23 00:55:09 +00001944 vex_printf("%s ", showPPCAvOp(i->Pin.AvBinary.op));
1945 ppHRegPPC(i->Pin.AvBinary.dst);
cerionc3d8bdc2005-06-28 18:06:23 +00001946 vex_printf(",");
cerion5b2325f2005-12-23 00:55:09 +00001947 ppHRegPPC(i->Pin.AvBinary.srcL);
cerionc3d8bdc2005-06-28 18:06:23 +00001948 vex_printf(",");
cerion5b2325f2005-12-23 00:55:09 +00001949 ppHRegPPC(i->Pin.AvBinary.srcR);
cerionc3d8bdc2005-06-28 18:06:23 +00001950 return;
cerion6b6f59e2005-06-28 20:59:18 +00001951 case Pin_AvBin8x16:
cerion5b2325f2005-12-23 00:55:09 +00001952 vex_printf("%s(b) ", showPPCAvOp(i->Pin.AvBin8x16.op));
1953 ppHRegPPC(i->Pin.AvBin8x16.dst);
cerion6b6f59e2005-06-28 20:59:18 +00001954 vex_printf(",");
cerion5b2325f2005-12-23 00:55:09 +00001955 ppHRegPPC(i->Pin.AvBin8x16.srcL);
cerion6b6f59e2005-06-28 20:59:18 +00001956 vex_printf(",");
cerion5b2325f2005-12-23 00:55:09 +00001957 ppHRegPPC(i->Pin.AvBin8x16.srcR);
cerion6b6f59e2005-06-28 20:59:18 +00001958 return;
1959 case Pin_AvBin16x8:
cerion5b2325f2005-12-23 00:55:09 +00001960 vex_printf("%s(h) ", showPPCAvOp(i->Pin.AvBin16x8.op));
1961 ppHRegPPC(i->Pin.AvBin16x8.dst);
cerion6b6f59e2005-06-28 20:59:18 +00001962 vex_printf(",");
cerion5b2325f2005-12-23 00:55:09 +00001963 ppHRegPPC(i->Pin.AvBin16x8.srcL);
cerion6b6f59e2005-06-28 20:59:18 +00001964 vex_printf(",");
cerion5b2325f2005-12-23 00:55:09 +00001965 ppHRegPPC(i->Pin.AvBin16x8.srcR);
cerion6b6f59e2005-06-28 20:59:18 +00001966 return;
1967 case Pin_AvBin32x4:
cerion5b2325f2005-12-23 00:55:09 +00001968 vex_printf("%s(w) ", showPPCAvOp(i->Pin.AvBin32x4.op));
1969 ppHRegPPC(i->Pin.AvBin32x4.dst);
cerion6b6f59e2005-06-28 20:59:18 +00001970 vex_printf(",");
cerion5b2325f2005-12-23 00:55:09 +00001971 ppHRegPPC(i->Pin.AvBin32x4.srcL);
cerion6b6f59e2005-06-28 20:59:18 +00001972 vex_printf(",");
cerion5b2325f2005-12-23 00:55:09 +00001973 ppHRegPPC(i->Pin.AvBin32x4.srcR);
cerion6b6f59e2005-06-28 20:59:18 +00001974 return;
carll0c74bb52013-08-12 18:01:40 +00001975 case Pin_AvBin64x2:
1976 vex_printf("%s(w) ", showPPCAvOp(i->Pin.AvBin64x2.op));
1977 ppHRegPPC(i->Pin.AvBin64x2.dst);
1978 vex_printf(",");
1979 ppHRegPPC(i->Pin.AvBin64x2.srcL);
1980 vex_printf(",");
1981 ppHRegPPC(i->Pin.AvBin64x2.srcR);
1982 return;
cerion6b6f59e2005-06-28 20:59:18 +00001983 case Pin_AvBin32Fx4:
cerion5b2325f2005-12-23 00:55:09 +00001984 vex_printf("%s ", showPPCAvFpOp(i->Pin.AvBin32Fx4.op));
1985 ppHRegPPC(i->Pin.AvBin32Fx4.dst);
cerion6b6f59e2005-06-28 20:59:18 +00001986 vex_printf(",");
cerion5b2325f2005-12-23 00:55:09 +00001987 ppHRegPPC(i->Pin.AvBin32Fx4.srcL);
cerion6b6f59e2005-06-28 20:59:18 +00001988 vex_printf(",");
cerion5b2325f2005-12-23 00:55:09 +00001989 ppHRegPPC(i->Pin.AvBin32Fx4.srcR);
cerion6b6f59e2005-06-28 20:59:18 +00001990 return;
cerion8ea0d3e2005-11-14 00:44:47 +00001991 case Pin_AvUn32Fx4:
cerion5b2325f2005-12-23 00:55:09 +00001992 vex_printf("%s ", showPPCAvFpOp(i->Pin.AvUn32Fx4.op));
1993 ppHRegPPC(i->Pin.AvUn32Fx4.dst);
cerion8ea0d3e2005-11-14 00:44:47 +00001994 vex_printf(",");
cerion5b2325f2005-12-23 00:55:09 +00001995 ppHRegPPC(i->Pin.AvUn32Fx4.src);
cerion8ea0d3e2005-11-14 00:44:47 +00001996 return;
cerionc3d8bdc2005-06-28 18:06:23 +00001997 case Pin_AvPerm:
1998 vex_printf("vperm ");
cerion5b2325f2005-12-23 00:55:09 +00001999 ppHRegPPC(i->Pin.AvPerm.dst);
cerionc3d8bdc2005-06-28 18:06:23 +00002000 vex_printf(",");
cerion5b2325f2005-12-23 00:55:09 +00002001 ppHRegPPC(i->Pin.AvPerm.srcL);
cerionc3d8bdc2005-06-28 18:06:23 +00002002 vex_printf(",");
cerion5b2325f2005-12-23 00:55:09 +00002003 ppHRegPPC(i->Pin.AvPerm.srcR);
cerionc3d8bdc2005-06-28 18:06:23 +00002004 vex_printf(",");
cerion5b2325f2005-12-23 00:55:09 +00002005 ppHRegPPC(i->Pin.AvPerm.ctl);
cerionc3d8bdc2005-06-28 18:06:23 +00002006 return;
2007
2008 case Pin_AvSel:
2009 vex_printf("vsel ");
cerion5b2325f2005-12-23 00:55:09 +00002010 ppHRegPPC(i->Pin.AvSel.dst);
cerionc3d8bdc2005-06-28 18:06:23 +00002011 vex_printf(",");
cerion5b2325f2005-12-23 00:55:09 +00002012 ppHRegPPC(i->Pin.AvSel.srcL);
cerionc3d8bdc2005-06-28 18:06:23 +00002013 vex_printf(",");
cerion5b2325f2005-12-23 00:55:09 +00002014 ppHRegPPC(i->Pin.AvSel.srcR);
cerionc3d8bdc2005-06-28 18:06:23 +00002015 vex_printf(",");
cerion5b2325f2005-12-23 00:55:09 +00002016 ppHRegPPC(i->Pin.AvSel.ctl);
cerionc3d8bdc2005-06-28 18:06:23 +00002017 return;
2018
carll9877fe52014-10-07 17:49:14 +00002019 case Pin_AvSh:
2020 /* This only generates the following instructions with RA
2021 * register number set to 0.
2022 */
2023 if (i->Pin.AvSh.addr->tag == Pam_IR) {
2024 ppLoadImm(hregPPC_GPR30(mode64),
2025 i->Pin.AvSh.addr->Pam.IR.index, mode64);
2026 vex_printf(" ; ");
2027 }
2028
2029 if (i->Pin.AvSh.shLeft)
2030 vex_printf("lvsl ");
2031 else
2032 vex_printf("lvsr ");
2033
2034 ppHRegPPC(i->Pin.AvSh.dst);
2035 if (i->Pin.AvSh.addr->tag == Pam_IR)
2036 vex_printf("%%r30");
2037 else
2038 ppHRegPPC(i->Pin.AvSh.addr->Pam.RR.index);
2039 vex_printf(",");
2040 ppHRegPPC(i->Pin.AvSh.addr->Pam.RR.base);
2041 return;
2042
cerionc3d8bdc2005-06-28 18:06:23 +00002043 case Pin_AvShlDbl:
2044 vex_printf("vsldoi ");
cerion5b2325f2005-12-23 00:55:09 +00002045 ppHRegPPC(i->Pin.AvShlDbl.dst);
cerionc3d8bdc2005-06-28 18:06:23 +00002046 vex_printf(",");
cerion5b2325f2005-12-23 00:55:09 +00002047 ppHRegPPC(i->Pin.AvShlDbl.srcL);
cerionc3d8bdc2005-06-28 18:06:23 +00002048 vex_printf(",");
cerion5b2325f2005-12-23 00:55:09 +00002049 ppHRegPPC(i->Pin.AvShlDbl.srcR);
sewardjdb36c0f2005-07-03 00:05:31 +00002050 vex_printf(",%d", i->Pin.AvShlDbl.shift);
cerionc3d8bdc2005-06-28 18:06:23 +00002051 return;
2052
2053 case Pin_AvSplat: {
cerion27b3d7e2005-09-14 20:35:47 +00002054 UChar sz = i->Pin.AvSplat.sz;
florian5df8ab02012-10-13 19:34:19 +00002055 HChar ch_sz = toUChar( (sz == 8) ? 'b' : (sz == 16) ? 'h' : 'w' );
cerionc3d8bdc2005-06-28 18:06:23 +00002056 vex_printf("vsplt%s%c ",
cerion27b3d7e2005-09-14 20:35:47 +00002057 i->Pin.AvSplat.src->tag == Pvi_Imm ? "is" : "", ch_sz);
cerion5b2325f2005-12-23 00:55:09 +00002058 ppHRegPPC(i->Pin.AvSplat.dst);
cerionc3d8bdc2005-06-28 18:06:23 +00002059 vex_printf(",");
cerion5b2325f2005-12-23 00:55:09 +00002060 ppPPCVI5s(i->Pin.AvSplat.src);
cerion27b3d7e2005-09-14 20:35:47 +00002061 if (i->Pin.AvSplat.src->tag == Pvi_Reg)
sewardj62d05432005-10-29 22:30:47 +00002062 vex_printf(", %d", (128/sz)-1); /* louis lane */
cerionc3d8bdc2005-06-28 18:06:23 +00002063 return;
2064 }
2065
cerion6b6f59e2005-06-28 20:59:18 +00002066 case Pin_AvCMov:
cerion5b2325f2005-12-23 00:55:09 +00002067 vex_printf("avcmov (%s) ", showPPCCondCode(i->Pin.AvCMov.cond));
2068 ppHRegPPC(i->Pin.AvCMov.dst);
cerion6b6f59e2005-06-28 20:59:18 +00002069 vex_printf(",");
cerion5b2325f2005-12-23 00:55:09 +00002070 ppHRegPPC(i->Pin.AvCMov.src);
cerion6b6f59e2005-06-28 20:59:18 +00002071 vex_printf(": ");
2072 vex_printf("if (v_dst != v_src) { ");
2073 if (i->Pin.AvCMov.cond.test != Pct_ALWAYS) {
cerion5b2325f2005-12-23 00:55:09 +00002074 vex_printf("if (%s) { ", showPPCCondCode(i->Pin.AvCMov.cond));
cerion6b6f59e2005-06-28 20:59:18 +00002075 }
2076 vex_printf("vmr ");
cerion5b2325f2005-12-23 00:55:09 +00002077 ppHRegPPC(i->Pin.AvCMov.dst);
cerion6b6f59e2005-06-28 20:59:18 +00002078 vex_printf(",");
cerion5b2325f2005-12-23 00:55:09 +00002079 ppHRegPPC(i->Pin.AvCMov.src);
cerion6b6f59e2005-06-28 20:59:18 +00002080 if (i->Pin.FpCMov.cond.test != Pct_ALWAYS)
2081 vex_printf(" }");
2082 vex_printf(" }");
2083 return;
2084
cerionc3d8bdc2005-06-28 18:06:23 +00002085 case Pin_AvLdVSCR:
2086 vex_printf("mtvscr ");
cerion5b2325f2005-12-23 00:55:09 +00002087 ppHRegPPC(i->Pin.AvLdVSCR.src);
cerionc3d8bdc2005-06-28 18:06:23 +00002088 return;
2089
carll7deaf952013-10-15 18:11:20 +00002090 case Pin_AvCipherV128Unary:
2091 vex_printf("%s(w) ", showPPCAvOp(i->Pin.AvCipherV128Unary.op));
2092 ppHRegPPC(i->Pin.AvCipherV128Unary.dst);
2093 vex_printf(",");
2094 ppHRegPPC(i->Pin.AvCipherV128Unary.src);
2095 return;
2096
2097 case Pin_AvCipherV128Binary:
2098 vex_printf("%s(w) ", showPPCAvOp(i->Pin.AvCipherV128Binary.op));
2099 ppHRegPPC(i->Pin.AvCipherV128Binary.dst);
2100 vex_printf(",");
2101 ppHRegPPC(i->Pin.AvCipherV128Binary.srcL);
2102 vex_printf(",");
2103 ppHRegPPC(i->Pin.AvCipherV128Binary.srcR);
2104 return;
2105
2106 case Pin_AvHashV128Binary:
2107 vex_printf("%s(w) ", showPPCAvOp(i->Pin.AvHashV128Binary.op));
2108 ppHRegPPC(i->Pin.AvHashV128Binary.dst);
2109 vex_printf(",");
2110 ppHRegPPC(i->Pin.AvHashV128Binary.src);
2111 vex_printf(",");
2112 ppPPCRI(i->Pin.AvHashV128Binary.s_field);
2113 return;
2114
2115 case Pin_AvBCDV128Trinary:
2116 vex_printf("%s(w) ", showPPCAvOp(i->Pin.AvBCDV128Trinary.op));
2117 ppHRegPPC(i->Pin.AvBCDV128Trinary.dst);
2118 vex_printf(",");
2119 ppHRegPPC(i->Pin.AvBCDV128Trinary.src1);
2120 vex_printf(",");
2121 ppHRegPPC(i->Pin.AvBCDV128Trinary.src2);
2122 vex_printf(",");
2123 ppPPCRI(i->Pin.AvBCDV128Trinary.ps);
2124 return;
2125
sewardjc6bbd472012-04-02 10:20:48 +00002126 case Pin_Dfp64Unary:
2127 vex_printf("%s ", showPPCFpOp(i->Pin.Dfp64Unary.op));
2128 ppHRegPPC(i->Pin.Dfp64Unary.dst);
2129 vex_printf(",");
2130 ppHRegPPC(i->Pin.Dfp64Unary.src);
2131 return;
2132
2133 case Pin_Dfp64Binary:
2134 vex_printf("%s ", showPPCFpOp(i->Pin.Dfp64Binary.op));
2135 ppHRegPPC(i->Pin.Dfp64Binary.dst);
2136 vex_printf(",");
2137 ppHRegPPC(i->Pin.Dfp64Binary.srcL);
2138 vex_printf(",");
2139 ppHRegPPC(i->Pin.Dfp64Binary.srcR);
2140 return;
2141
sewardj26217b02012-04-12 17:19:48 +00002142 case Pin_DfpShift:
2143 vex_printf("%s ", showPPCFpOp(i->Pin.DfpShift.op));
2144 ppHRegPPC(i->Pin.DfpShift.dst);
2145 vex_printf(",");
2146 ppHRegPPC(i->Pin.DfpShift.src);
2147 vex_printf(",");
2148 ppPPCRI(i->Pin.DfpShift.shift);
2149 return;
2150
2151 case Pin_Dfp128Unary:
2152 vex_printf("%s ", showPPCFpOp(i->Pin.Dfp128Unary.op));
2153 ppHRegPPC(i->Pin.Dfp128Unary.dst_hi);
2154 vex_printf(",");
2155 ppHRegPPC(i->Pin.Dfp128Unary.src_hi);
2156 return;
2157
sewardjc6bbd472012-04-02 10:20:48 +00002158 case Pin_Dfp128Binary:
2159 vex_printf("%s ", showPPCFpOp(i->Pin.Dfp128Binary.op));
2160 ppHRegPPC(i->Pin.Dfp128Binary.dst_hi);
2161 vex_printf(",");
2162 ppHRegPPC(i->Pin.Dfp128Binary.srcR_hi);
2163 return;
2164
sewardj26217b02012-04-12 17:19:48 +00002165 case Pin_DfpShift128:
2166 vex_printf("%s ", showPPCFpOp(i->Pin.DfpShift128.op));
2167 ppHRegPPC(i->Pin.DfpShift128.dst_hi);
2168 vex_printf(",");
2169 ppHRegPPC(i->Pin.DfpShift128.src_hi);
2170 vex_printf(",");
2171 ppPPCRI(i->Pin.DfpShift128.shift);
2172 return;
2173
sewardjcdc376d2012-04-23 11:21:12 +00002174 case Pin_DfpRound:
2175 vex_printf("drintx ");
2176 ppHRegPPC(i->Pin.DfpRound.dst);
2177 vex_printf(",");
2178 ppHRegPPC(i->Pin.DfpRound.src);
2179 vex_printf(",");
2180 ppPPCRI(i->Pin.DfpRound.r_rmc); /* R in bit 3 and RMC in bits 2:0 */
2181 return;
2182
2183 case Pin_DfpRound128:
2184 vex_printf("drintxq ");
2185 ppHRegPPC(i->Pin.DfpRound128.dst_hi);
2186 vex_printf(",");
2187 ppHRegPPC(i->Pin.DfpRound128.src_hi);
2188 vex_printf(",");
2189 ppPPCRI(i->Pin.DfpRound128.r_rmc); /* R in bit 3 and RMC in bits 2:0 */
2190 return;
2191
2192 case Pin_DfpQuantize:
2193 vex_printf("%s ", showPPCFpOp(i->Pin.DfpQuantize.op));
2194 ppHRegPPC(i->Pin.DfpQuantize.dst);
2195 vex_printf(",");
2196 ppHRegPPC(i->Pin.DfpQuantize.srcL);
2197 vex_printf(",");
2198 ppHRegPPC(i->Pin.DfpQuantize.srcR);
2199 vex_printf(",");
2200 ppPPCRI(i->Pin.DfpQuantize.rmc);
2201 return;
2202
2203 case Pin_DfpQuantize128:
2204 /* Dst is used to pass in left source and return result */
2205 vex_printf("dquaq ");
2206 ppHRegPPC(i->Pin.DfpQuantize128.dst_hi);
2207 vex_printf(",");
2208 ppHRegPPC(i->Pin.DfpQuantize128.dst_hi);
2209 vex_printf(",");
2210 ppHRegPPC(i->Pin.DfpQuantize128.src_hi);
2211 vex_printf(",");
2212 ppPPCRI(i->Pin.DfpQuantize128.rmc);
2213 return;
2214
sewardj26217b02012-04-12 17:19:48 +00002215 case Pin_DfpD128toD64:
2216 vex_printf("%s ", showPPCFpOp(i->Pin.DfpD128toD64.op));
2217 ppHRegPPC(i->Pin.DfpD128toD64.dst);
2218 vex_printf(",");
2219 ppHRegPPC(i->Pin.DfpD128toD64.src_hi);
2220 vex_printf(",");
2221 return;
2222
2223 case Pin_DfpI64StoD128:
2224 vex_printf("%s ", showPPCFpOp(i->Pin.DfpI64StoD128.op));
2225 ppHRegPPC(i->Pin.DfpI64StoD128.dst_hi);
2226 vex_printf(",");
2227 ppHRegPPC(i->Pin.DfpI64StoD128.src);
2228 vex_printf(",");
2229 return;
sewardjcdc376d2012-04-23 11:21:12 +00002230 case Pin_ExtractExpD128:
2231 vex_printf("dxexq ");
2232 ppHRegPPC(i->Pin.ExtractExpD128.dst);
2233 vex_printf(",");
2234 ppHRegPPC(i->Pin.ExtractExpD128.src_hi);
2235 return;
2236 case Pin_InsertExpD128:
2237 vex_printf("diexq ");
2238 ppHRegPPC(i->Pin.InsertExpD128.dst_hi);
2239 vex_printf(",");
2240 ppHRegPPC(i->Pin.InsertExpD128.srcL);
2241 vex_printf(",");
2242 ppHRegPPC(i->Pin.InsertExpD128.srcR_hi);
2243 return;
2244 case Pin_Dfp64Cmp:
2245 vex_printf("dcmpo %%cr1,");
2246 ppHRegPPC(i->Pin.Dfp64Cmp.srcL);
2247 vex_printf(",");
2248 ppHRegPPC(i->Pin.Dfp64Cmp.srcR);
2249 vex_printf("; mfcr ");
2250 ppHRegPPC(i->Pin.Dfp64Cmp.dst);
2251 vex_printf("; rlwinm ");
2252 ppHRegPPC(i->Pin.Dfp64Cmp.dst);
2253 vex_printf(",");
2254 ppHRegPPC(i->Pin.Dfp64Cmp.dst);
2255 vex_printf(",8,28,31");
2256 return;
2257 case Pin_Dfp128Cmp:
2258 vex_printf("dcmpoq %%cr1,");
2259 ppHRegPPC(i->Pin.Dfp128Cmp.srcL_hi);
2260 vex_printf(",");
2261 ppHRegPPC(i->Pin.Dfp128Cmp.srcR_hi);
2262 vex_printf("; mfcr ");
2263 ppHRegPPC(i->Pin.Dfp128Cmp.dst);
2264 vex_printf("; rlwinm ");
2265 ppHRegPPC(i->Pin.Dfp128Cmp.dst);
2266 vex_printf(",");
2267 ppHRegPPC(i->Pin.Dfp128Cmp.dst);
2268 vex_printf(",8,28,31");
2269 return;
sewardj3dee8492012-04-20 00:13:28 +00002270 case Pin_EvCheck:
2271 /* Note that the counter dec is 32 bit even in 64-bit mode. */
2272 vex_printf("(evCheck) ");
2273 vex_printf("lwz r30,");
2274 ppPPCAMode(i->Pin.EvCheck.amCounter);
2275 vex_printf("; addic. r30,r30,-1; ");
2276 vex_printf("stw r30,");
2277 ppPPCAMode(i->Pin.EvCheck.amCounter);
2278 vex_printf("; bge nofail; lwz r30,");
2279 ppPPCAMode(i->Pin.EvCheck.amFailAddr);
2280 vex_printf("; mtctr r30; bctr; nofail:");
2281 return;
sewardj3dee8492012-04-20 00:13:28 +00002282 case Pin_ProfInc:
2283 if (mode64) {
sewardjf252de52012-04-20 10:42:24 +00002284 vex_printf("(profInc) imm64-fixed5 r30,$NotKnownYet; ");
sewardj3dee8492012-04-20 00:13:28 +00002285 vex_printf("ld r29,(r30); addi r29,r29,1; std r29,(r30)");
2286 } else {
sewardjf252de52012-04-20 10:42:24 +00002287 vex_printf("(profInc) imm32-fixed2 r30,$NotKnownYet; ");
sewardj3dee8492012-04-20 00:13:28 +00002288 vex_printf("lwz r29,4(r30); addic. r29,r29,1; stw r29,4(r30)");
2289 vex_printf("lwz r29,0(r30); addze r29,r29; stw r29,0(r30)");
2290 }
2291 break;
cerionb85e8bb2005-02-16 08:54:33 +00002292 default:
cerion5b2325f2005-12-23 00:55:09 +00002293 vex_printf("\nppPPCInstr: No such tag(%d)\n", (Int)i->tag);
2294 vpanic("ppPPCInstr");
cerionbcf8c3e2005-02-04 16:17:07 +00002295 }
2296}
2297
2298/* --------- Helpers for register allocation. --------- */
2299
floriand8c64e02014-10-08 08:54:44 +00002300void getRegUsage_PPCInstr ( HRegUsage* u, const PPCInstr* i, Bool mode64 )
cerionbcf8c3e2005-02-04 16:17:07 +00002301{
cerionbcf8c3e2005-02-04 16:17:07 +00002302 initHRegUsage(u);
2303 switch (i->tag) {
cerionf0de28c2005-12-13 20:21:11 +00002304 case Pin_LI:
2305 addHRegUse(u, HRmWrite, i->Pin.LI.dst);
sewardjb51f0f42005-07-18 11:38:02 +00002306 break;
cerionf0de28c2005-12-13 20:21:11 +00002307 case Pin_Alu:
cerion5b2325f2005-12-23 00:55:09 +00002308 addHRegUse(u, HRmRead, i->Pin.Alu.srcL);
2309 addRegUsage_PPCRH(u, i->Pin.Alu.srcR);
cerionf0de28c2005-12-13 20:21:11 +00002310 addHRegUse(u, HRmWrite, i->Pin.Alu.dst);
cerionb85e8bb2005-02-16 08:54:33 +00002311 return;
cerionbb01b7c2005-12-16 13:40:18 +00002312 case Pin_Shft:
2313 addHRegUse(u, HRmRead, i->Pin.Shft.srcL);
cerion5b2325f2005-12-23 00:55:09 +00002314 addRegUsage_PPCRH(u, i->Pin.Shft.srcR);
cerionbb01b7c2005-12-16 13:40:18 +00002315 addHRegUse(u, HRmWrite, i->Pin.Shft.dst);
2316 return;
cerion5b2325f2005-12-23 00:55:09 +00002317 case Pin_AddSubC:
2318 addHRegUse(u, HRmWrite, i->Pin.AddSubC.dst);
2319 addHRegUse(u, HRmRead, i->Pin.AddSubC.srcL);
2320 addHRegUse(u, HRmRead, i->Pin.AddSubC.srcR);
cerion4a49b032005-11-08 16:23:07 +00002321 return;
cerionf0de28c2005-12-13 20:21:11 +00002322 case Pin_Cmp:
2323 addHRegUse(u, HRmRead, i->Pin.Cmp.srcL);
cerion5b2325f2005-12-23 00:55:09 +00002324 addRegUsage_PPCRH(u, i->Pin.Cmp.srcR);
cerionb85e8bb2005-02-16 08:54:33 +00002325 return;
cerionf0de28c2005-12-13 20:21:11 +00002326 case Pin_Unary:
cerion5b2325f2005-12-23 00:55:09 +00002327 addHRegUse(u, HRmWrite, i->Pin.Unary.dst);
2328 addHRegUse(u, HRmRead, i->Pin.Unary.src);
cerionb85e8bb2005-02-16 08:54:33 +00002329 return;
2330 case Pin_MulL:
2331 addHRegUse(u, HRmWrite, i->Pin.MulL.dst);
cerion5b2325f2005-12-23 00:55:09 +00002332 addHRegUse(u, HRmRead, i->Pin.MulL.srcL);
2333 addHRegUse(u, HRmRead, i->Pin.MulL.srcR);
cerionb85e8bb2005-02-16 08:54:33 +00002334 return;
2335 case Pin_Div:
2336 addHRegUse(u, HRmWrite, i->Pin.Div.dst);
cerion5b2325f2005-12-23 00:55:09 +00002337 addHRegUse(u, HRmRead, i->Pin.Div.srcL);
2338 addHRegUse(u, HRmRead, i->Pin.Div.srcR);
cerionb85e8bb2005-02-16 08:54:33 +00002339 return;
cerionf0de28c2005-12-13 20:21:11 +00002340 case Pin_Call: {
2341 UInt argir;
cerionb85e8bb2005-02-16 08:54:33 +00002342 /* This is a bit subtle. */
2343 /* First off, claim it trashes all the caller-saved regs
2344 which fall within the register allocator's jurisdiction.
cerionf0de28c2005-12-13 20:21:11 +00002345 These I believe to be:
2346 mode32: r3 to r12
2347 mode64: r3 to r10
cerionb85e8bb2005-02-16 08:54:33 +00002348 */
sewardjcb1f68e2005-12-30 03:39:14 +00002349 /* XXXXXXXXXXXXXXXXX BUG! This doesn't say anything about the FP
2350 or Altivec registers. We get away with this ONLY because
2351 getAllocatableRegs_PPC gives the allocator callee-saved fp
2352 and Altivec regs, and no caller-save ones. */
cerionf0de28c2005-12-13 20:21:11 +00002353 addHRegUse(u, HRmWrite, hregPPC_GPR3(mode64));
2354 addHRegUse(u, HRmWrite, hregPPC_GPR4(mode64));
2355 addHRegUse(u, HRmWrite, hregPPC_GPR5(mode64));
2356 addHRegUse(u, HRmWrite, hregPPC_GPR6(mode64));
2357 addHRegUse(u, HRmWrite, hregPPC_GPR7(mode64));
2358 addHRegUse(u, HRmWrite, hregPPC_GPR8(mode64));
2359 addHRegUse(u, HRmWrite, hregPPC_GPR9(mode64));
2360 addHRegUse(u, HRmWrite, hregPPC_GPR10(mode64));
2361 if (!mode64) {
2362 addHRegUse(u, HRmWrite, hregPPC_GPR11(mode64));
2363 addHRegUse(u, HRmWrite, hregPPC_GPR12(mode64));
2364 }
2365
cerionb85e8bb2005-02-16 08:54:33 +00002366 /* Now we have to state any parameter-carrying registers
sewardj6a64a9f2005-08-21 00:48:37 +00002367 which might be read. This depends on the argiregs field. */
cerionf0de28c2005-12-13 20:21:11 +00002368 argir = i->Pin.Call.argiregs;
2369 if (argir &(1<<10)) addHRegUse(u, HRmRead, hregPPC_GPR10(mode64));
2370 if (argir & (1<<9)) addHRegUse(u, HRmRead, hregPPC_GPR9(mode64));
2371 if (argir & (1<<8)) addHRegUse(u, HRmRead, hregPPC_GPR8(mode64));
2372 if (argir & (1<<7)) addHRegUse(u, HRmRead, hregPPC_GPR7(mode64));
2373 if (argir & (1<<6)) addHRegUse(u, HRmRead, hregPPC_GPR6(mode64));
2374 if (argir & (1<<5)) addHRegUse(u, HRmRead, hregPPC_GPR5(mode64));
2375 if (argir & (1<<4)) addHRegUse(u, HRmRead, hregPPC_GPR4(mode64));
2376 if (argir & (1<<3)) addHRegUse(u, HRmRead, hregPPC_GPR3(mode64));
sewardj6a64a9f2005-08-21 00:48:37 +00002377
cerionf0de28c2005-12-13 20:21:11 +00002378 vassert(0 == (argir & ~((1<<3)|(1<<4)|(1<<5)|(1<<6)
2379 |(1<<7)|(1<<8)|(1<<9)|(1<<10))));
sewardj6a64a9f2005-08-21 00:48:37 +00002380
cerionb85e8bb2005-02-16 08:54:33 +00002381 /* Finally, there is the issue that the insn trashes a
2382 register because the literal target address has to be
cerionf0de28c2005-12-13 20:21:11 +00002383 loaded into a register. %r10 seems a suitable victim.
sewardje9d8a262009-07-01 08:06:34 +00002384 (Can't use %r0, as some insns interpret it as value zero). */
cerionf0de28c2005-12-13 20:21:11 +00002385 addHRegUse(u, HRmWrite, hregPPC_GPR10(mode64));
2386 /* Upshot of this is that the assembler really must use %r10,
ceriona56e9cc2005-02-16 18:08:25 +00002387 and no other, as a destination temporary. */
cerionb85e8bb2005-02-16 08:54:33 +00002388 return;
cerionf0de28c2005-12-13 20:21:11 +00002389 }
sewardj3dee8492012-04-20 00:13:28 +00002390 /* XDirect/XIndir/XAssisted are also a bit subtle. They
2391 conditionally exit the block. Hence we only need to list (1)
2392 the registers that they read, and (2) the registers that they
2393 write in the case where the block is not exited. (2) is empty,
2394 hence only (1) is relevant here. */
2395 case Pin_XDirect:
2396 addRegUsage_PPCAMode(u, i->Pin.XDirect.amCIA);
2397 return;
2398 case Pin_XIndir:
2399 addHRegUse(u, HRmRead, i->Pin.XIndir.dstGA);
2400 addRegUsage_PPCAMode(u, i->Pin.XIndir.amCIA);
2401 return;
2402 case Pin_XAssisted:
2403 addHRegUse(u, HRmRead, i->Pin.XAssisted.dstGA);
2404 addRegUsage_PPCAMode(u, i->Pin.XAssisted.amCIA);
cerionb85e8bb2005-02-16 08:54:33 +00002405 return;
cerionf0de28c2005-12-13 20:21:11 +00002406 case Pin_CMov:
cerion5b2325f2005-12-23 00:55:09 +00002407 addRegUsage_PPCRI(u, i->Pin.CMov.src);
cerionf0de28c2005-12-13 20:21:11 +00002408 addHRegUse(u, HRmWrite, i->Pin.CMov.dst);
cerionb85e8bb2005-02-16 08:54:33 +00002409 return;
cerion7cf8e4e2005-02-16 16:08:17 +00002410 case Pin_Load:
cerion5b2325f2005-12-23 00:55:09 +00002411 addRegUsage_PPCAMode(u, i->Pin.Load.src);
cerion7cf8e4e2005-02-16 16:08:17 +00002412 addHRegUse(u, HRmWrite, i->Pin.Load.dst);
cerionb85e8bb2005-02-16 08:54:33 +00002413 return;
sewardje9d8a262009-07-01 08:06:34 +00002414 case Pin_LoadL:
2415 addHRegUse(u, HRmRead, i->Pin.LoadL.src);
2416 addHRegUse(u, HRmWrite, i->Pin.LoadL.dst);
2417 return;
cerionb85e8bb2005-02-16 08:54:33 +00002418 case Pin_Store:
cerion5b2325f2005-12-23 00:55:09 +00002419 addHRegUse(u, HRmRead, i->Pin.Store.src);
2420 addRegUsage_PPCAMode(u, i->Pin.Store.dst);
cerionb85e8bb2005-02-16 08:54:33 +00002421 return;
sewardje9d8a262009-07-01 08:06:34 +00002422 case Pin_StoreC:
2423 addHRegUse(u, HRmRead, i->Pin.StoreC.src);
2424 addHRegUse(u, HRmRead, i->Pin.StoreC.dst);
2425 return;
cerion5b2325f2005-12-23 00:55:09 +00002426 case Pin_Set:
2427 addHRegUse(u, HRmWrite, i->Pin.Set.dst);
cerionb85e8bb2005-02-16 08:54:33 +00002428 return;
sewardjb51f0f42005-07-18 11:38:02 +00002429 case Pin_MfCR:
2430 addHRegUse(u, HRmWrite, i->Pin.MfCR.dst);
2431 return;
cerionb85e8bb2005-02-16 08:54:33 +00002432 case Pin_MFence:
2433 return;
cerion094d1392005-06-20 13:45:57 +00002434
2435 case Pin_FpUnary:
2436 addHRegUse(u, HRmWrite, i->Pin.FpUnary.dst);
2437 addHRegUse(u, HRmRead, i->Pin.FpUnary.src);
2438 return;
2439 case Pin_FpBinary:
2440 addHRegUse(u, HRmWrite, i->Pin.FpBinary.dst);
2441 addHRegUse(u, HRmRead, i->Pin.FpBinary.srcL);
2442 addHRegUse(u, HRmRead, i->Pin.FpBinary.srcR);
2443 return;
sewardj40c80262006-02-08 19:30:46 +00002444 case Pin_FpMulAcc:
2445 addHRegUse(u, HRmWrite, i->Pin.FpMulAcc.dst);
2446 addHRegUse(u, HRmRead, i->Pin.FpMulAcc.srcML);
2447 addHRegUse(u, HRmRead, i->Pin.FpMulAcc.srcMR);
2448 addHRegUse(u, HRmRead, i->Pin.FpMulAcc.srcAcc);
2449 return;
cerion094d1392005-06-20 13:45:57 +00002450 case Pin_FpLdSt:
2451 addHRegUse(u, (i->Pin.FpLdSt.isLoad ? HRmWrite : HRmRead),
2452 i->Pin.FpLdSt.reg);
cerion5b2325f2005-12-23 00:55:09 +00002453 addRegUsage_PPCAMode(u, i->Pin.FpLdSt.addr);
cerion094d1392005-06-20 13:45:57 +00002454 return;
sewardj92923de2006-01-25 21:29:48 +00002455 case Pin_FpSTFIW:
2456 addHRegUse(u, HRmRead, i->Pin.FpSTFIW.addr);
2457 addHRegUse(u, HRmRead, i->Pin.FpSTFIW.data);
cerion094d1392005-06-20 13:45:57 +00002458 return;
sewardj92923de2006-01-25 21:29:48 +00002459 case Pin_FpRSP:
2460 addHRegUse(u, HRmWrite, i->Pin.FpRSP.dst);
2461 addHRegUse(u, HRmRead, i->Pin.FpRSP.src);
cerion094d1392005-06-20 13:45:57 +00002462 return;
sewardj92923de2006-01-25 21:29:48 +00002463 case Pin_FpCftI:
2464 addHRegUse(u, HRmWrite, i->Pin.FpCftI.dst);
2465 addHRegUse(u, HRmRead, i->Pin.FpCftI.src);
cerion07b07a92005-12-22 14:32:35 +00002466 return;
cerion094d1392005-06-20 13:45:57 +00002467 case Pin_FpCMov:
2468 addHRegUse(u, HRmModify, i->Pin.FpCMov.dst);
cerion5b2325f2005-12-23 00:55:09 +00002469 addHRegUse(u, HRmRead, i->Pin.FpCMov.src);
cerion094d1392005-06-20 13:45:57 +00002470 return;
2471 case Pin_FpLdFPSCR:
2472 addHRegUse(u, HRmRead, i->Pin.FpLdFPSCR.src);
2473 return;
2474 case Pin_FpCmp:
2475 addHRegUse(u, HRmWrite, i->Pin.FpCmp.dst);
cerion5b2325f2005-12-23 00:55:09 +00002476 addHRegUse(u, HRmRead, i->Pin.FpCmp.srcL);
2477 addHRegUse(u, HRmRead, i->Pin.FpCmp.srcR);
cerion094d1392005-06-20 13:45:57 +00002478 return;
cerion7f000af2005-02-22 20:36:49 +00002479
2480 case Pin_RdWrLR:
2481 addHRegUse(u, (i->Pin.RdWrLR.wrLR ? HRmRead : HRmWrite),
2482 i->Pin.RdWrLR.gpr);
2483 return;
2484
cerionc3d8bdc2005-06-28 18:06:23 +00002485 case Pin_AvLdSt:
2486 addHRegUse(u, (i->Pin.AvLdSt.isLoad ? HRmWrite : HRmRead),
2487 i->Pin.AvLdSt.reg);
2488 if (i->Pin.AvLdSt.addr->tag == Pam_IR)
cerionf0de28c2005-12-13 20:21:11 +00002489 addHRegUse(u, HRmWrite, hregPPC_GPR30(mode64));
cerion5b2325f2005-12-23 00:55:09 +00002490 addRegUsage_PPCAMode(u, i->Pin.AvLdSt.addr);
cerionc3d8bdc2005-06-28 18:06:23 +00002491 return;
2492 case Pin_AvUnary:
2493 addHRegUse(u, HRmWrite, i->Pin.AvUnary.dst);
2494 addHRegUse(u, HRmRead, i->Pin.AvUnary.src);
2495 return;
2496 case Pin_AvBinary:
sewardjdc1f9132005-10-22 12:49:49 +00002497 if (i->Pin.AvBinary.op == Pav_XOR
florian79efdc62013-02-11 00:47:35 +00002498 && sameHReg(i->Pin.AvBinary.dst, i->Pin.AvBinary.srcL)
2499 && sameHReg(i->Pin.AvBinary.dst, i->Pin.AvBinary.srcR)) {
sewardjdc1f9132005-10-22 12:49:49 +00002500 /* reg-alloc needs to understand 'xor r,r,r' as a write of r */
2501 /* (as opposed to a rite of passage :-) */
2502 addHRegUse(u, HRmWrite, i->Pin.AvBinary.dst);
2503 } else {
2504 addHRegUse(u, HRmWrite, i->Pin.AvBinary.dst);
2505 addHRegUse(u, HRmRead, i->Pin.AvBinary.srcL);
2506 addHRegUse(u, HRmRead, i->Pin.AvBinary.srcR);
2507 }
cerionc3d8bdc2005-06-28 18:06:23 +00002508 return;
cerion6b6f59e2005-06-28 20:59:18 +00002509 case Pin_AvBin8x16:
2510 addHRegUse(u, HRmWrite, i->Pin.AvBin8x16.dst);
2511 addHRegUse(u, HRmRead, i->Pin.AvBin8x16.srcL);
2512 addHRegUse(u, HRmRead, i->Pin.AvBin8x16.srcR);
2513 return;
2514 case Pin_AvBin16x8:
2515 addHRegUse(u, HRmWrite, i->Pin.AvBin16x8.dst);
2516 addHRegUse(u, HRmRead, i->Pin.AvBin16x8.srcL);
2517 addHRegUse(u, HRmRead, i->Pin.AvBin16x8.srcR);
2518 return;
2519 case Pin_AvBin32x4:
2520 addHRegUse(u, HRmWrite, i->Pin.AvBin32x4.dst);
2521 addHRegUse(u, HRmRead, i->Pin.AvBin32x4.srcL);
2522 addHRegUse(u, HRmRead, i->Pin.AvBin32x4.srcR);
cerion6b6f59e2005-06-28 20:59:18 +00002523 return;
carll0c74bb52013-08-12 18:01:40 +00002524 case Pin_AvBin64x2:
2525 addHRegUse(u, HRmWrite, i->Pin.AvBin64x2.dst);
2526 addHRegUse(u, HRmRead, i->Pin.AvBin64x2.srcL);
2527 addHRegUse(u, HRmRead, i->Pin.AvBin64x2.srcR);
2528 return;
cerion6b6f59e2005-06-28 20:59:18 +00002529 case Pin_AvBin32Fx4:
2530 addHRegUse(u, HRmWrite, i->Pin.AvBin32Fx4.dst);
2531 addHRegUse(u, HRmRead, i->Pin.AvBin32Fx4.srcL);
2532 addHRegUse(u, HRmRead, i->Pin.AvBin32Fx4.srcR);
cerion8ea0d3e2005-11-14 00:44:47 +00002533 if (i->Pin.AvBin32Fx4.op == Pavfp_MULF)
cerion5b2325f2005-12-23 00:55:09 +00002534 addHRegUse(u, HRmWrite, hregPPC_VR29());
cerion8ea0d3e2005-11-14 00:44:47 +00002535 return;
2536 case Pin_AvUn32Fx4:
2537 addHRegUse(u, HRmWrite, i->Pin.AvUn32Fx4.dst);
2538 addHRegUse(u, HRmRead, i->Pin.AvUn32Fx4.src);
cerion6b6f59e2005-06-28 20:59:18 +00002539 return;
cerionc3d8bdc2005-06-28 18:06:23 +00002540 case Pin_AvPerm:
2541 addHRegUse(u, HRmWrite, i->Pin.AvPerm.dst);
cerionc3d8bdc2005-06-28 18:06:23 +00002542 addHRegUse(u, HRmRead, i->Pin.AvPerm.srcL);
2543 addHRegUse(u, HRmRead, i->Pin.AvPerm.srcR);
cerion92d9d872005-09-15 21:58:50 +00002544 addHRegUse(u, HRmRead, i->Pin.AvPerm.ctl);
cerionc3d8bdc2005-06-28 18:06:23 +00002545 return;
2546 case Pin_AvSel:
2547 addHRegUse(u, HRmWrite, i->Pin.AvSel.dst);
2548 addHRegUse(u, HRmRead, i->Pin.AvSel.ctl);
2549 addHRegUse(u, HRmRead, i->Pin.AvSel.srcL);
2550 addHRegUse(u, HRmRead, i->Pin.AvSel.srcR);
2551 return;
carll9877fe52014-10-07 17:49:14 +00002552 case Pin_AvSh:
2553 addHRegUse(u, HRmWrite, i->Pin.AvSh.dst);
2554 if (i->Pin.AvSh.addr->tag == Pam_IR)
2555 addHRegUse(u, HRmWrite, hregPPC_GPR30(mode64));
2556 addRegUsage_PPCAMode(u, i->Pin.AvSh.addr);
2557 return;
cerionc3d8bdc2005-06-28 18:06:23 +00002558 case Pin_AvShlDbl:
2559 addHRegUse(u, HRmWrite, i->Pin.AvShlDbl.dst);
2560 addHRegUse(u, HRmRead, i->Pin.AvShlDbl.srcL);
2561 addHRegUse(u, HRmRead, i->Pin.AvShlDbl.srcR);
2562 return;
2563 case Pin_AvSplat:
cerion5b2325f2005-12-23 00:55:09 +00002564 addHRegUse(u, HRmWrite, i->Pin.AvSplat.dst);
2565 addRegUsage_PPCVI5s(u, i->Pin.AvSplat.src);
cerionc3d8bdc2005-06-28 18:06:23 +00002566 return;
cerion6b6f59e2005-06-28 20:59:18 +00002567 case Pin_AvCMov:
2568 addHRegUse(u, HRmModify, i->Pin.AvCMov.dst);
cerion5b2325f2005-12-23 00:55:09 +00002569 addHRegUse(u, HRmRead, i->Pin.AvCMov.src);
cerion6b6f59e2005-06-28 20:59:18 +00002570 return;
cerionc3d8bdc2005-06-28 18:06:23 +00002571 case Pin_AvLdVSCR:
2572 addHRegUse(u, HRmRead, i->Pin.AvLdVSCR.src);
2573 return;
carll7deaf952013-10-15 18:11:20 +00002574 case Pin_AvCipherV128Unary:
2575 addHRegUse(u, HRmWrite, i->Pin.AvCipherV128Unary.dst);
2576 addHRegUse(u, HRmRead, i->Pin.AvCipherV128Unary.src);
2577 return;
2578 case Pin_AvCipherV128Binary:
2579 addHRegUse(u, HRmWrite, i->Pin.AvCipherV128Binary.dst);
2580 addHRegUse(u, HRmRead, i->Pin.AvCipherV128Binary.srcL);
2581 addHRegUse(u, HRmRead, i->Pin.AvCipherV128Binary.srcR);
2582 return;
2583 case Pin_AvHashV128Binary:
2584 addHRegUse(u, HRmWrite, i->Pin.AvHashV128Binary.dst);
2585 addHRegUse(u, HRmRead, i->Pin.AvHashV128Binary.src);
2586 addRegUsage_PPCRI(u, i->Pin.AvHashV128Binary.s_field);
2587 return;
2588 case Pin_AvBCDV128Trinary:
2589 addHRegUse(u, HRmWrite, i->Pin.AvBCDV128Trinary.dst);
2590 addHRegUse(u, HRmRead, i->Pin.AvBCDV128Trinary.src1);
2591 addHRegUse(u, HRmRead, i->Pin.AvBCDV128Trinary.src2);
2592 addRegUsage_PPCRI(u, i->Pin.AvBCDV128Trinary.ps);
2593 return;
sewardjc6bbd472012-04-02 10:20:48 +00002594 case Pin_Dfp64Unary:
2595 addHRegUse(u, HRmWrite, i->Pin.Dfp64Unary.dst);
2596 addHRegUse(u, HRmRead, i->Pin.Dfp64Unary.src);
2597 return;
2598 case Pin_Dfp64Binary:
2599 addHRegUse(u, HRmWrite, i->Pin.Dfp64Binary.dst);
2600 addHRegUse(u, HRmRead, i->Pin.Dfp64Binary.srcL);
2601 addHRegUse(u, HRmRead, i->Pin.Dfp64Binary.srcR);
2602 return;
sewardj26217b02012-04-12 17:19:48 +00002603 case Pin_DfpShift:
2604 addRegUsage_PPCRI(u, i->Pin.DfpShift.shift);
2605 addHRegUse(u, HRmWrite, i->Pin.DfpShift.src);
2606 addHRegUse(u, HRmWrite, i->Pin.DfpShift.dst);
2607 return;
2608 case Pin_Dfp128Unary:
2609 addHRegUse(u, HRmWrite, i->Pin.Dfp128Unary.dst_hi);
2610 addHRegUse(u, HRmWrite, i->Pin.Dfp128Unary.dst_lo);
2611 addHRegUse(u, HRmRead, i->Pin.Dfp128Unary.src_hi);
2612 addHRegUse(u, HRmRead, i->Pin.Dfp128Unary.src_lo);
2613 return;
sewardjc6bbd472012-04-02 10:20:48 +00002614 case Pin_Dfp128Binary:
2615 addHRegUse(u, HRmWrite, i->Pin.Dfp128Binary.dst_hi);
2616 addHRegUse(u, HRmWrite, i->Pin.Dfp128Binary.dst_lo);
2617 addHRegUse(u, HRmRead, i->Pin.Dfp128Binary.srcR_hi);
2618 addHRegUse(u, HRmRead, i->Pin.Dfp128Binary.srcR_lo);
2619 return;
sewardjcdc376d2012-04-23 11:21:12 +00002620 case Pin_DfpRound:
2621 addHRegUse(u, HRmWrite, i->Pin.DfpRound.dst);
2622 addHRegUse(u, HRmRead, i->Pin.DfpRound.src);
2623 return;
2624 case Pin_DfpRound128:
2625 addHRegUse(u, HRmWrite, i->Pin.DfpRound128.dst_hi);
2626 addHRegUse(u, HRmWrite, i->Pin.DfpRound128.dst_lo);
2627 addHRegUse(u, HRmRead, i->Pin.DfpRound128.src_hi);
2628 addHRegUse(u, HRmRead, i->Pin.DfpRound128.src_lo);
2629 return;
2630 case Pin_DfpQuantize:
2631 addRegUsage_PPCRI(u, i->Pin.DfpQuantize.rmc);
2632 addHRegUse(u, HRmWrite, i->Pin.DfpQuantize.dst);
2633 addHRegUse(u, HRmRead, i->Pin.DfpQuantize.srcL);
2634 addHRegUse(u, HRmRead, i->Pin.DfpQuantize.srcR);
2635 return;
2636 case Pin_DfpQuantize128:
2637 addHRegUse(u, HRmWrite, i->Pin.DfpQuantize128.dst_hi);
2638 addHRegUse(u, HRmWrite, i->Pin.DfpQuantize128.dst_lo);
2639 addHRegUse(u, HRmRead, i->Pin.DfpQuantize128.src_hi);
2640 addHRegUse(u, HRmRead, i->Pin.DfpQuantize128.src_lo);
2641 return;
sewardj26217b02012-04-12 17:19:48 +00002642 case Pin_DfpShift128:
2643 addRegUsage_PPCRI(u, i->Pin.DfpShift128.shift);
2644 addHRegUse(u, HRmWrite, i->Pin.DfpShift128.src_hi);
2645 addHRegUse(u, HRmWrite, i->Pin.DfpShift128.src_lo);
2646 addHRegUse(u, HRmWrite, i->Pin.DfpShift128.dst_hi);
2647 addHRegUse(u, HRmWrite, i->Pin.DfpShift128.dst_lo);
2648 return;
2649 case Pin_DfpD128toD64:
2650 addHRegUse(u, HRmWrite, i->Pin.DfpD128toD64.src_hi);
2651 addHRegUse(u, HRmWrite, i->Pin.DfpD128toD64.src_lo);
2652 addHRegUse(u, HRmWrite, i->Pin.DfpD128toD64.dst);
2653 return;
2654 case Pin_DfpI64StoD128:
2655 addHRegUse(u, HRmWrite, i->Pin.DfpI64StoD128.src);
2656 addHRegUse(u, HRmWrite, i->Pin.DfpI64StoD128.dst_hi);
2657 addHRegUse(u, HRmWrite, i->Pin.DfpI64StoD128.dst_lo);
2658 return;
sewardjcdc376d2012-04-23 11:21:12 +00002659 case Pin_ExtractExpD128:
2660 addHRegUse(u, HRmWrite, i->Pin.ExtractExpD128.dst);
2661 addHRegUse(u, HRmRead, i->Pin.ExtractExpD128.src_hi);
2662 addHRegUse(u, HRmRead, i->Pin.ExtractExpD128.src_lo);
2663 return;
2664 case Pin_InsertExpD128:
2665 addHRegUse(u, HRmWrite, i->Pin.InsertExpD128.dst_hi);
2666 addHRegUse(u, HRmWrite, i->Pin.InsertExpD128.dst_lo);
2667 addHRegUse(u, HRmRead, i->Pin.InsertExpD128.srcL);
2668 addHRegUse(u, HRmRead, i->Pin.InsertExpD128.srcR_hi);
2669 addHRegUse(u, HRmRead, i->Pin.InsertExpD128.srcR_lo);
2670 return;
2671 case Pin_Dfp64Cmp:
2672 addHRegUse(u, HRmWrite, i->Pin.Dfp64Cmp.dst);
2673 addHRegUse(u, HRmRead, i->Pin.Dfp64Cmp.srcL);
2674 addHRegUse(u, HRmRead, i->Pin.Dfp64Cmp.srcR);
2675 return;
2676 case Pin_Dfp128Cmp:
2677 addHRegUse(u, HRmWrite, i->Pin.Dfp128Cmp.dst);
2678 addHRegUse(u, HRmRead, i->Pin.Dfp128Cmp.srcL_hi);
2679 addHRegUse(u, HRmRead, i->Pin.Dfp128Cmp.srcL_lo);
2680 addHRegUse(u, HRmRead, i->Pin.Dfp128Cmp.srcR_hi);
2681 addHRegUse(u, HRmRead, i->Pin.Dfp128Cmp.srcR_lo);
2682 return;
sewardj3dee8492012-04-20 00:13:28 +00002683 case Pin_EvCheck:
2684 /* We expect both amodes only to mention the GSP (r31), so this
2685 is in fact pointless, since GSP isn't allocatable, but
2686 anyway.. */
2687 addRegUsage_PPCAMode(u, i->Pin.EvCheck.amCounter);
2688 addRegUsage_PPCAMode(u, i->Pin.EvCheck.amFailAddr);
2689 addHRegUse(u, HRmWrite, hregPPC_GPR30(mode64)); /* also unavail to RA */
2690 return;
2691 case Pin_ProfInc:
2692 addHRegUse(u, HRmWrite, hregPPC_GPR29(mode64));
2693 addHRegUse(u, HRmWrite, hregPPC_GPR30(mode64));
2694 return;
cerionb85e8bb2005-02-16 08:54:33 +00002695 default:
cerion5b2325f2005-12-23 00:55:09 +00002696 ppPPCInstr(i, mode64);
2697 vpanic("getRegUsage_PPCInstr");
cerionbcf8c3e2005-02-04 16:17:07 +00002698 }
2699}
2700
cerioncd304492005-02-08 19:40:24 +00002701/* local helper */
cerion92b64362005-12-13 12:02:26 +00002702static void mapReg( HRegRemap* m, HReg* r )
cerioncd304492005-02-08 19:40:24 +00002703{
2704 *r = lookupHRegRemap(m, *r);
2705}
cerionbcf8c3e2005-02-04 16:17:07 +00002706
cerion5b2325f2005-12-23 00:55:09 +00002707void mapRegs_PPCInstr ( HRegRemap* m, PPCInstr* i, Bool mode64 )
cerionbcf8c3e2005-02-04 16:17:07 +00002708{
2709 switch (i->tag) {
cerionf0de28c2005-12-13 20:21:11 +00002710 case Pin_LI:
2711 mapReg(m, &i->Pin.LI.dst);
sewardjb51f0f42005-07-18 11:38:02 +00002712 return;
cerionf0de28c2005-12-13 20:21:11 +00002713 case Pin_Alu:
2714 mapReg(m, &i->Pin.Alu.dst);
2715 mapReg(m, &i->Pin.Alu.srcL);
cerion5b2325f2005-12-23 00:55:09 +00002716 mapRegs_PPCRH(m, i->Pin.Alu.srcR);
cerionb85e8bb2005-02-16 08:54:33 +00002717 return;
cerionbb01b7c2005-12-16 13:40:18 +00002718 case Pin_Shft:
2719 mapReg(m, &i->Pin.Shft.dst);
2720 mapReg(m, &i->Pin.Shft.srcL);
cerion5b2325f2005-12-23 00:55:09 +00002721 mapRegs_PPCRH(m, i->Pin.Shft.srcR);
cerionbb01b7c2005-12-16 13:40:18 +00002722 return;
cerion5b2325f2005-12-23 00:55:09 +00002723 case Pin_AddSubC:
2724 mapReg(m, &i->Pin.AddSubC.dst);
2725 mapReg(m, &i->Pin.AddSubC.srcL);
2726 mapReg(m, &i->Pin.AddSubC.srcR);
cerion4a49b032005-11-08 16:23:07 +00002727 return;
cerionf0de28c2005-12-13 20:21:11 +00002728 case Pin_Cmp:
2729 mapReg(m, &i->Pin.Cmp.srcL);
cerion5b2325f2005-12-23 00:55:09 +00002730 mapRegs_PPCRH(m, i->Pin.Cmp.srcR);
cerionb85e8bb2005-02-16 08:54:33 +00002731 return;
cerionf0de28c2005-12-13 20:21:11 +00002732 case Pin_Unary:
cerion5b2325f2005-12-23 00:55:09 +00002733 mapReg(m, &i->Pin.Unary.dst);
2734 mapReg(m, &i->Pin.Unary.src);
cerionb85e8bb2005-02-16 08:54:33 +00002735 return;
2736 case Pin_MulL:
2737 mapReg(m, &i->Pin.MulL.dst);
ceriona2f75882005-03-15 16:33:38 +00002738 mapReg(m, &i->Pin.MulL.srcL);
sewardjb51f0f42005-07-18 11:38:02 +00002739 mapReg(m, &i->Pin.MulL.srcR);
cerionb85e8bb2005-02-16 08:54:33 +00002740 return;
2741 case Pin_Div:
2742 mapReg(m, &i->Pin.Div.dst);
ceriona2f75882005-03-15 16:33:38 +00002743 mapReg(m, &i->Pin.Div.srcL);
2744 mapReg(m, &i->Pin.Div.srcR);
cerionb85e8bb2005-02-16 08:54:33 +00002745 return;
cerionb85e8bb2005-02-16 08:54:33 +00002746 case Pin_Call:
2747 return;
sewardj3dee8492012-04-20 00:13:28 +00002748 case Pin_XDirect:
2749 mapRegs_PPCAMode(m, i->Pin.XDirect.amCIA);
2750 return;
2751 case Pin_XIndir:
2752 mapReg(m, &i->Pin.XIndir.dstGA);
2753 mapRegs_PPCAMode(m, i->Pin.XIndir.amCIA);
2754 return;
2755 case Pin_XAssisted:
2756 mapReg(m, &i->Pin.XAssisted.dstGA);
2757 mapRegs_PPCAMode(m, i->Pin.XAssisted.amCIA);
cerionb85e8bb2005-02-16 08:54:33 +00002758 return;
cerionf0de28c2005-12-13 20:21:11 +00002759 case Pin_CMov:
cerion5b2325f2005-12-23 00:55:09 +00002760 mapRegs_PPCRI(m, i->Pin.CMov.src);
cerionf0de28c2005-12-13 20:21:11 +00002761 mapReg(m, &i->Pin.CMov.dst);
cerionb85e8bb2005-02-16 08:54:33 +00002762 return;
cerion7cf8e4e2005-02-16 16:08:17 +00002763 case Pin_Load:
cerion5b2325f2005-12-23 00:55:09 +00002764 mapRegs_PPCAMode(m, i->Pin.Load.src);
cerion7cf8e4e2005-02-16 16:08:17 +00002765 mapReg(m, &i->Pin.Load.dst);
cerionb85e8bb2005-02-16 08:54:33 +00002766 return;
sewardje9d8a262009-07-01 08:06:34 +00002767 case Pin_LoadL:
2768 mapReg(m, &i->Pin.LoadL.src);
2769 mapReg(m, &i->Pin.LoadL.dst);
2770 return;
cerionb85e8bb2005-02-16 08:54:33 +00002771 case Pin_Store:
2772 mapReg(m, &i->Pin.Store.src);
cerion5b2325f2005-12-23 00:55:09 +00002773 mapRegs_PPCAMode(m, i->Pin.Store.dst);
cerionb85e8bb2005-02-16 08:54:33 +00002774 return;
sewardje9d8a262009-07-01 08:06:34 +00002775 case Pin_StoreC:
2776 mapReg(m, &i->Pin.StoreC.src);
2777 mapReg(m, &i->Pin.StoreC.dst);
2778 return;
cerion5b2325f2005-12-23 00:55:09 +00002779 case Pin_Set:
2780 mapReg(m, &i->Pin.Set.dst);
cerionb85e8bb2005-02-16 08:54:33 +00002781 return;
sewardjb51f0f42005-07-18 11:38:02 +00002782 case Pin_MfCR:
2783 mapReg(m, &i->Pin.MfCR.dst);
2784 return;
cerionb85e8bb2005-02-16 08:54:33 +00002785 case Pin_MFence:
2786 return;
cerion094d1392005-06-20 13:45:57 +00002787 case Pin_FpUnary:
sewardjb51f0f42005-07-18 11:38:02 +00002788 mapReg(m, &i->Pin.FpUnary.dst);
2789 mapReg(m, &i->Pin.FpUnary.src);
2790 return;
2791 case Pin_FpBinary:
2792 mapReg(m, &i->Pin.FpBinary.dst);
2793 mapReg(m, &i->Pin.FpBinary.srcL);
2794 mapReg(m, &i->Pin.FpBinary.srcR);
2795 return;
sewardj40c80262006-02-08 19:30:46 +00002796 case Pin_FpMulAcc:
2797 mapReg(m, &i->Pin.FpMulAcc.dst);
2798 mapReg(m, &i->Pin.FpMulAcc.srcML);
2799 mapReg(m, &i->Pin.FpMulAcc.srcMR);
2800 mapReg(m, &i->Pin.FpMulAcc.srcAcc);
2801 return;
sewardjb51f0f42005-07-18 11:38:02 +00002802 case Pin_FpLdSt:
2803 mapReg(m, &i->Pin.FpLdSt.reg);
cerion5b2325f2005-12-23 00:55:09 +00002804 mapRegs_PPCAMode(m, i->Pin.FpLdSt.addr);
sewardjb51f0f42005-07-18 11:38:02 +00002805 return;
sewardj92923de2006-01-25 21:29:48 +00002806 case Pin_FpSTFIW:
2807 mapReg(m, &i->Pin.FpSTFIW.addr);
2808 mapReg(m, &i->Pin.FpSTFIW.data);
sewardjb51f0f42005-07-18 11:38:02 +00002809 return;
sewardj92923de2006-01-25 21:29:48 +00002810 case Pin_FpRSP:
2811 mapReg(m, &i->Pin.FpRSP.dst);
2812 mapReg(m, &i->Pin.FpRSP.src);
sewardjb51f0f42005-07-18 11:38:02 +00002813 return;
sewardj92923de2006-01-25 21:29:48 +00002814 case Pin_FpCftI:
2815 mapReg(m, &i->Pin.FpCftI.dst);
2816 mapReg(m, &i->Pin.FpCftI.src);
cerion07b07a92005-12-22 14:32:35 +00002817 return;
sewardjb51f0f42005-07-18 11:38:02 +00002818 case Pin_FpCMov:
2819 mapReg(m, &i->Pin.FpCMov.dst);
2820 mapReg(m, &i->Pin.FpCMov.src);
2821 return;
2822 case Pin_FpLdFPSCR:
2823 mapReg(m, &i->Pin.FpLdFPSCR.src);
2824 return;
2825 case Pin_FpCmp:
2826 mapReg(m, &i->Pin.FpCmp.dst);
2827 mapReg(m, &i->Pin.FpCmp.srcL);
2828 mapReg(m, &i->Pin.FpCmp.srcR);
2829 return;
cerion7f000af2005-02-22 20:36:49 +00002830 case Pin_RdWrLR:
2831 mapReg(m, &i->Pin.RdWrLR.gpr);
2832 return;
cerionc3d8bdc2005-06-28 18:06:23 +00002833 case Pin_AvLdSt:
2834 mapReg(m, &i->Pin.AvLdSt.reg);
cerion5b2325f2005-12-23 00:55:09 +00002835 mapRegs_PPCAMode(m, i->Pin.AvLdSt.addr);
cerionc3d8bdc2005-06-28 18:06:23 +00002836 return;
2837 case Pin_AvUnary:
2838 mapReg(m, &i->Pin.AvUnary.dst);
2839 mapReg(m, &i->Pin.AvUnary.src);
2840 return;
2841 case Pin_AvBinary:
2842 mapReg(m, &i->Pin.AvBinary.dst);
2843 mapReg(m, &i->Pin.AvBinary.srcL);
2844 mapReg(m, &i->Pin.AvBinary.srcR);
2845 return;
cerion6b6f59e2005-06-28 20:59:18 +00002846 case Pin_AvBin8x16:
2847 mapReg(m, &i->Pin.AvBin8x16.dst);
2848 mapReg(m, &i->Pin.AvBin8x16.srcL);
2849 mapReg(m, &i->Pin.AvBin8x16.srcR);
2850 return;
2851 case Pin_AvBin16x8:
2852 mapReg(m, &i->Pin.AvBin16x8.dst);
2853 mapReg(m, &i->Pin.AvBin16x8.srcL);
2854 mapReg(m, &i->Pin.AvBin16x8.srcR);
2855 return;
2856 case Pin_AvBin32x4:
2857 mapReg(m, &i->Pin.AvBin32x4.dst);
2858 mapReg(m, &i->Pin.AvBin32x4.srcL);
2859 mapReg(m, &i->Pin.AvBin32x4.srcR);
2860 return;
carll0c74bb52013-08-12 18:01:40 +00002861 case Pin_AvBin64x2:
2862 mapReg(m, &i->Pin.AvBin64x2.dst);
2863 mapReg(m, &i->Pin.AvBin64x2.srcL);
2864 mapReg(m, &i->Pin.AvBin64x2.srcR);
2865 return;
cerion6b6f59e2005-06-28 20:59:18 +00002866 case Pin_AvBin32Fx4:
2867 mapReg(m, &i->Pin.AvBin32Fx4.dst);
2868 mapReg(m, &i->Pin.AvBin32Fx4.srcL);
2869 mapReg(m, &i->Pin.AvBin32Fx4.srcR);
2870 return;
cerion8ea0d3e2005-11-14 00:44:47 +00002871 case Pin_AvUn32Fx4:
2872 mapReg(m, &i->Pin.AvUn32Fx4.dst);
2873 mapReg(m, &i->Pin.AvUn32Fx4.src);
2874 return;
cerionc3d8bdc2005-06-28 18:06:23 +00002875 case Pin_AvPerm:
2876 mapReg(m, &i->Pin.AvPerm.dst);
2877 mapReg(m, &i->Pin.AvPerm.srcL);
2878 mapReg(m, &i->Pin.AvPerm.srcR);
2879 mapReg(m, &i->Pin.AvPerm.ctl);
2880 return;
2881 case Pin_AvSel:
2882 mapReg(m, &i->Pin.AvSel.dst);
2883 mapReg(m, &i->Pin.AvSel.srcL);
2884 mapReg(m, &i->Pin.AvSel.srcR);
2885 mapReg(m, &i->Pin.AvSel.ctl);
2886 return;
carll9877fe52014-10-07 17:49:14 +00002887 case Pin_AvSh:
2888 mapReg(m, &i->Pin.AvSh.dst);
2889 mapRegs_PPCAMode(m, i->Pin.AvSh.addr);
2890 return;
cerionc3d8bdc2005-06-28 18:06:23 +00002891 case Pin_AvShlDbl:
2892 mapReg(m, &i->Pin.AvShlDbl.dst);
2893 mapReg(m, &i->Pin.AvShlDbl.srcL);
2894 mapReg(m, &i->Pin.AvShlDbl.srcR);
2895 return;
2896 case Pin_AvSplat:
2897 mapReg(m, &i->Pin.AvSplat.dst);
cerion5b2325f2005-12-23 00:55:09 +00002898 mapRegs_PPCVI5s(m, i->Pin.AvSplat.src);
cerionc3d8bdc2005-06-28 18:06:23 +00002899 return;
cerion6b6f59e2005-06-28 20:59:18 +00002900 case Pin_AvCMov:
2901 mapReg(m, &i->Pin.AvCMov.dst);
2902 mapReg(m, &i->Pin.AvCMov.src);
2903 return;
cerionc3d8bdc2005-06-28 18:06:23 +00002904 case Pin_AvLdVSCR:
2905 mapReg(m, &i->Pin.AvLdVSCR.src);
2906 return;
carll7deaf952013-10-15 18:11:20 +00002907 case Pin_AvCipherV128Unary:
2908 mapReg(m, &i->Pin.AvCipherV128Unary.dst);
2909 mapReg(m, &i->Pin.AvCipherV128Unary.src);
2910 return;
2911 case Pin_AvCipherV128Binary:
2912 mapReg(m, &i->Pin.AvCipherV128Binary.dst);
2913 mapReg(m, &i->Pin.AvCipherV128Binary.srcL);
2914 mapReg(m, &i->Pin.AvCipherV128Binary.srcR);
2915 return;
2916 case Pin_AvHashV128Binary:
2917 mapRegs_PPCRI(m, i->Pin.AvHashV128Binary.s_field);
2918 mapReg(m, &i->Pin.AvHashV128Binary.dst);
2919 mapReg(m, &i->Pin.AvHashV128Binary.src);
2920 return;
2921 case Pin_AvBCDV128Trinary:
2922 mapReg(m, &i->Pin.AvBCDV128Trinary.dst);
2923 mapReg(m, &i->Pin.AvBCDV128Trinary.src1);
2924 mapReg(m, &i->Pin.AvBCDV128Trinary.src2);
2925 mapRegs_PPCRI(m, i->Pin.AvBCDV128Trinary.ps);
2926 return;
sewardjc6bbd472012-04-02 10:20:48 +00002927 case Pin_Dfp64Unary:
2928 mapReg(m, &i->Pin.Dfp64Unary.dst);
2929 mapReg(m, &i->Pin.Dfp64Unary.src);
2930 return;
2931 case Pin_Dfp64Binary:
2932 mapReg(m, &i->Pin.Dfp64Binary.dst);
2933 mapReg(m, &i->Pin.Dfp64Binary.srcL);
2934 mapReg(m, &i->Pin.Dfp64Binary.srcR);
2935 return;
sewardj26217b02012-04-12 17:19:48 +00002936 case Pin_DfpShift:
2937 mapRegs_PPCRI(m, i->Pin.DfpShift.shift);
2938 mapReg(m, &i->Pin.DfpShift.src);
2939 mapReg(m, &i->Pin.DfpShift.dst);
2940 return;
2941 case Pin_Dfp128Unary:
2942 mapReg(m, &i->Pin.Dfp128Unary.dst_hi);
2943 mapReg(m, &i->Pin.Dfp128Unary.dst_lo);
2944 mapReg(m, &i->Pin.Dfp128Unary.src_hi);
2945 mapReg(m, &i->Pin.Dfp128Unary.src_lo);
2946 return;
sewardjc6bbd472012-04-02 10:20:48 +00002947 case Pin_Dfp128Binary:
2948 mapReg(m, &i->Pin.Dfp128Binary.dst_hi);
2949 mapReg(m, &i->Pin.Dfp128Binary.dst_lo);
2950 mapReg(m, &i->Pin.Dfp128Binary.srcR_hi);
2951 mapReg(m, &i->Pin.Dfp128Binary.srcR_lo);
2952 return;
sewardj26217b02012-04-12 17:19:48 +00002953 case Pin_DfpShift128:
2954 mapRegs_PPCRI(m, i->Pin.DfpShift128.shift);
2955 mapReg(m, &i->Pin.DfpShift128.src_hi);
2956 mapReg(m, &i->Pin.DfpShift128.src_lo);
2957 mapReg(m, &i->Pin.DfpShift128.dst_hi);
2958 mapReg(m, &i->Pin.DfpShift128.dst_lo);
2959 return;
sewardjcdc376d2012-04-23 11:21:12 +00002960 case Pin_DfpRound:
2961 mapReg(m, &i->Pin.DfpRound.dst);
2962 mapReg(m, &i->Pin.DfpRound.src);
2963 return;
2964 case Pin_DfpRound128:
2965 mapReg(m, &i->Pin.DfpRound128.dst_hi);
2966 mapReg(m, &i->Pin.DfpRound128.dst_lo);
2967 mapReg(m, &i->Pin.DfpRound128.src_hi);
2968 mapReg(m, &i->Pin.DfpRound128.src_lo);
2969 return;
2970 case Pin_DfpQuantize:
2971 mapRegs_PPCRI(m, i->Pin.DfpQuantize.rmc);
2972 mapReg(m, &i->Pin.DfpQuantize.dst);
2973 mapReg(m, &i->Pin.DfpQuantize.srcL);
2974 mapReg(m, &i->Pin.DfpQuantize.srcR);
2975 return;
2976 case Pin_DfpQuantize128:
2977 mapRegs_PPCRI(m, i->Pin.DfpQuantize128.rmc);
2978 mapReg(m, &i->Pin.DfpQuantize128.dst_hi);
2979 mapReg(m, &i->Pin.DfpQuantize128.dst_lo);
2980 mapReg(m, &i->Pin.DfpQuantize128.src_hi);
2981 mapReg(m, &i->Pin.DfpQuantize128.src_lo);
floriana7b0d102012-06-15 20:55:43 +00002982 return;
sewardj26217b02012-04-12 17:19:48 +00002983 case Pin_DfpD128toD64:
2984 mapReg(m, &i->Pin.DfpD128toD64.src_hi);
2985 mapReg(m, &i->Pin.DfpD128toD64.src_lo);
2986 mapReg(m, &i->Pin.DfpD128toD64.dst);
2987 return;
2988 case Pin_DfpI64StoD128:
2989 mapReg(m, &i->Pin.DfpI64StoD128.src);
2990 mapReg(m, &i->Pin.DfpI64StoD128.dst_hi);
2991 mapReg(m, &i->Pin.DfpI64StoD128.dst_lo);
2992 return;
sewardjcdc376d2012-04-23 11:21:12 +00002993 case Pin_ExtractExpD128:
2994 mapReg(m, &i->Pin.ExtractExpD128.dst);
2995 mapReg(m, &i->Pin.ExtractExpD128.src_hi);
2996 mapReg(m, &i->Pin.ExtractExpD128.src_lo);
2997 return;
2998 case Pin_InsertExpD128:
2999 mapReg(m, &i->Pin.InsertExpD128.dst_hi);
3000 mapReg(m, &i->Pin.InsertExpD128.dst_lo);
3001 mapReg(m, &i->Pin.InsertExpD128.srcL);
3002 mapReg(m, &i->Pin.InsertExpD128.srcR_hi);
3003 mapReg(m, &i->Pin.InsertExpD128.srcR_lo);
3004 return;
3005 case Pin_Dfp64Cmp:
3006 mapReg(m, &i->Pin.Dfp64Cmp.dst);
3007 mapReg(m, &i->Pin.Dfp64Cmp.srcL);
3008 mapReg(m, &i->Pin.Dfp64Cmp.srcR);
3009 return;
3010 case Pin_Dfp128Cmp:
3011 mapReg(m, &i->Pin.Dfp128Cmp.dst);
3012 mapReg(m, &i->Pin.Dfp128Cmp.srcL_hi);
3013 mapReg(m, &i->Pin.Dfp128Cmp.srcL_lo);
3014 mapReg(m, &i->Pin.Dfp128Cmp.srcR_hi);
3015 mapReg(m, &i->Pin.Dfp128Cmp.srcR_lo);
3016 return;
sewardj3dee8492012-04-20 00:13:28 +00003017 case Pin_EvCheck:
3018 /* We expect both amodes only to mention the GSP (r31), so this
3019 is in fact pointless, since GSP isn't allocatable, but
3020 anyway.. */
3021 mapRegs_PPCAMode(m, i->Pin.EvCheck.amCounter);
3022 mapRegs_PPCAMode(m, i->Pin.EvCheck.amFailAddr);
3023 return;
3024 case Pin_ProfInc:
3025 /* hardwires r29 and r30 -- nothing to modify. */
3026 return;
cerionb85e8bb2005-02-16 08:54:33 +00003027 default:
cerion5b2325f2005-12-23 00:55:09 +00003028 ppPPCInstr(i, mode64);
3029 vpanic("mapRegs_PPCInstr");
cerionbcf8c3e2005-02-04 16:17:07 +00003030 }
3031}
3032
3033/* Figure out if i represents a reg-reg move, and if so assign the
3034 source and destination to *src and *dst. If in doubt say No. Used
3035 by the register allocator to do move coalescing.
3036*/
floriand8c64e02014-10-08 08:54:44 +00003037Bool isMove_PPCInstr ( const PPCInstr* i, HReg* src, HReg* dst )
cerionbcf8c3e2005-02-04 16:17:07 +00003038{
cerionab9132d2005-02-15 15:46:59 +00003039 /* Moves between integer regs */
cerionf0de28c2005-12-13 20:21:11 +00003040 if (i->tag == Pin_Alu) {
cerionab9132d2005-02-15 15:46:59 +00003041 // or Rd,Rs,Rs == mr Rd,Rs
cerionf0de28c2005-12-13 20:21:11 +00003042 if (i->Pin.Alu.op != Palu_OR)
cerionab9132d2005-02-15 15:46:59 +00003043 return False;
cerionf0de28c2005-12-13 20:21:11 +00003044 if (i->Pin.Alu.srcR->tag != Prh_Reg)
cerionab9132d2005-02-15 15:46:59 +00003045 return False;
florian79efdc62013-02-11 00:47:35 +00003046 if (! sameHReg(i->Pin.Alu.srcR->Prh.Reg.reg, i->Pin.Alu.srcL))
cerionb85e8bb2005-02-16 08:54:33 +00003047 return False;
cerionf0de28c2005-12-13 20:21:11 +00003048 *src = i->Pin.Alu.srcL;
3049 *dst = i->Pin.Alu.dst;
cerionab9132d2005-02-15 15:46:59 +00003050 return True;
3051 }
cerion094d1392005-06-20 13:45:57 +00003052 /* Moves between FP regs */
3053 if (i->tag == Pin_FpUnary) {
3054 if (i->Pin.FpUnary.op != Pfp_MOV)
3055 return False;
3056 *src = i->Pin.FpUnary.src;
3057 *dst = i->Pin.FpUnary.dst;
3058 return True;
3059 }
cerionbcf8c3e2005-02-04 16:17:07 +00003060 return False;
3061}
3062
3063
cerion75949202005-12-24 13:14:11 +00003064/* Generate ppc spill/reload instructions under the direction of the
cerionbcf8c3e2005-02-04 16:17:07 +00003065 register allocator. Note it's critical these don't write the
3066 condition codes. */
sewardj2a0cc852010-01-02 13:23:54 +00003067
3068void genSpill_PPC ( /*OUT*/HInstr** i1, /*OUT*/HInstr** i2,
3069 HReg rreg, Int offsetB, Bool mode64 )
cerione13bb312005-02-10 19:51:03 +00003070{
cerion5b2325f2005-12-23 00:55:09 +00003071 PPCAMode* am;
cerione13bb312005-02-10 19:51:03 +00003072 vassert(!hregIsVirtual(rreg));
sewardj2a0cc852010-01-02 13:23:54 +00003073 *i1 = *i2 = NULL;
cerion5b2325f2005-12-23 00:55:09 +00003074 am = PPCAMode_IR( offsetB, GuestStatePtr(mode64) );
cerione13bb312005-02-10 19:51:03 +00003075 switch (hregClass(rreg)) {
sewardj2a0cc852010-01-02 13:23:54 +00003076 case HRcInt64:
3077 vassert(mode64);
3078 *i1 = PPCInstr_Store( 8, am, rreg, mode64 );
3079 return;
3080 case HRcInt32:
3081 vassert(!mode64);
3082 *i1 = PPCInstr_Store( 4, am, rreg, mode64 );
3083 return;
3084 case HRcFlt64:
3085 *i1 = PPCInstr_FpLdSt ( False/*store*/, 8, rreg, am );
3086 return;
3087 case HRcVec128:
3088 // XXX: GPR30 used as spill register to kludge AltiVec
3089 // AMode_IR
3090 *i1 = PPCInstr_AvLdSt ( False/*store*/, 16, rreg, am );
3091 return;
3092 default:
3093 ppHRegClass(hregClass(rreg));
3094 vpanic("genSpill_PPC: unimplemented regclass");
cerione13bb312005-02-10 19:51:03 +00003095 }
cerionbcf8c3e2005-02-04 16:17:07 +00003096}
3097
sewardj2a0cc852010-01-02 13:23:54 +00003098void genReload_PPC ( /*OUT*/HInstr** i1, /*OUT*/HInstr** i2,
3099 HReg rreg, Int offsetB, Bool mode64 )
cerione13bb312005-02-10 19:51:03 +00003100{
cerion5b2325f2005-12-23 00:55:09 +00003101 PPCAMode* am;
cerione13bb312005-02-10 19:51:03 +00003102 vassert(!hregIsVirtual(rreg));
sewardj2a0cc852010-01-02 13:23:54 +00003103 *i1 = *i2 = NULL;
cerion5b2325f2005-12-23 00:55:09 +00003104 am = PPCAMode_IR( offsetB, GuestStatePtr(mode64) );
cerione13bb312005-02-10 19:51:03 +00003105 switch (hregClass(rreg)) {
sewardj2a0cc852010-01-02 13:23:54 +00003106 case HRcInt64:
3107 vassert(mode64);
3108 *i1 = PPCInstr_Load( 8, rreg, am, mode64 );
3109 return;
3110 case HRcInt32:
3111 vassert(!mode64);
3112 *i1 = PPCInstr_Load( 4, rreg, am, mode64 );
3113 return;
3114 case HRcFlt64:
3115 *i1 = PPCInstr_FpLdSt ( True/*load*/, 8, rreg, am );
3116 return;
3117 case HRcVec128:
3118 // XXX: GPR30 used as spill register to kludge AltiVec AMode_IR
3119 *i1 = PPCInstr_AvLdSt ( True/*load*/, 16, rreg, am );
3120 return;
3121 default:
3122 ppHRegClass(hregClass(rreg));
3123 vpanic("genReload_PPC: unimplemented regclass");
cerione13bb312005-02-10 19:51:03 +00003124 }
cerionbcf8c3e2005-02-04 16:17:07 +00003125}
3126
3127
cerion75949202005-12-24 13:14:11 +00003128/* --------- The ppc assembler (bleh.) --------- */
cerioncd304492005-02-08 19:40:24 +00003129
cerionf0de28c2005-12-13 20:21:11 +00003130static UInt iregNo ( HReg r, Bool mode64 )
cerioncd304492005-02-08 19:40:24 +00003131{
3132 UInt n;
cerionf0de28c2005-12-13 20:21:11 +00003133 vassert(hregClass(r) == mode64 ? HRcInt64 : HRcInt32);
cerioncd304492005-02-08 19:40:24 +00003134 vassert(!hregIsVirtual(r));
3135 n = hregNumber(r);
3136 vassert(n <= 32);
3137 return n;
3138}
cerioncd304492005-02-08 19:40:24 +00003139
cerion094d1392005-06-20 13:45:57 +00003140static UInt fregNo ( HReg fr )
3141{
3142 UInt n;
3143 vassert(hregClass(fr) == HRcFlt64);
3144 vassert(!hregIsVirtual(fr));
3145 n = hregNumber(fr);
3146 vassert(n <= 32);
3147 return n;
3148}
cerioncd304492005-02-08 19:40:24 +00003149
cerionc3d8bdc2005-06-28 18:06:23 +00003150static UInt vregNo ( HReg v )
3151{
3152 UInt n;
3153 vassert(hregClass(v) == HRcVec128);
3154 vassert(!hregIsVirtual(v));
3155 n = hregNumber(v);
3156 vassert(n <= 32);
3157 return n;
3158}
3159
carll1f5fe1f2014-08-07 23:25:23 +00003160/* Emit an instruction ppc-endianly */
3161static UChar* emit32 ( UChar* p, UInt w32, VexEndness endness_host )
ceriond5e38382005-02-11 13:38:15 +00003162{
carll1f5fe1f2014-08-07 23:25:23 +00003163 if (endness_host == VexEndnessBE) {
3164 *p++ = toUChar((w32 >> 24) & 0x000000FF);
3165 *p++ = toUChar((w32 >> 16) & 0x000000FF);
3166 *p++ = toUChar((w32 >> 8) & 0x000000FF);
3167 *p++ = toUChar((w32) & 0x000000FF);
3168 } else {
3169 *p++ = toUChar((w32) & 0x000000FF);
3170 *p++ = toUChar((w32 >> 8) & 0x000000FF);
3171 *p++ = toUChar((w32 >> 16) & 0x000000FF);
3172 *p++ = toUChar((w32 >> 24) & 0x000000FF);
3173 }
ceriond5e38382005-02-11 13:38:15 +00003174 return p;
3175}
cerioncd304492005-02-08 19:40:24 +00003176
carll1f5fe1f2014-08-07 23:25:23 +00003177/* Fetch an instruction ppc-endianly */
3178static UInt fetch32 ( UChar* p, VexEndness endness_host )
sewardj3dee8492012-04-20 00:13:28 +00003179{
3180 UInt w32 = 0;
carll1f5fe1f2014-08-07 23:25:23 +00003181 if (endness_host == VexEndnessBE) {
3182 w32 |= ((0xFF & (UInt)p[0]) << 24);
3183 w32 |= ((0xFF & (UInt)p[1]) << 16);
3184 w32 |= ((0xFF & (UInt)p[2]) << 8);
3185 w32 |= ((0xFF & (UInt)p[3]) << 0);
3186 } else {
3187 w32 |= ((0xFF & (UInt)p[3]) << 24);
3188 w32 |= ((0xFF & (UInt)p[2]) << 16);
3189 w32 |= ((0xFF & (UInt)p[1]) << 8);
3190 w32 |= ((0xFF & (UInt)p[0]) << 0);
3191 }
sewardj3dee8492012-04-20 00:13:28 +00003192 return w32;
3193}
3194
cerion75949202005-12-24 13:14:11 +00003195/* The following mkForm[...] functions refer to ppc instruction forms
cerion094d1392005-06-20 13:45:57 +00003196 as per PPC32 p576
3197 */
cerioned623db2005-06-20 12:42:04 +00003198
cerion5b2325f2005-12-23 00:55:09 +00003199static UChar* mkFormD ( UChar* p, UInt opc1,
carll1f5fe1f2014-08-07 23:25:23 +00003200 UInt r1, UInt r2, UInt imm, VexEndness endness_host )
ceriond5e38382005-02-11 13:38:15 +00003201{
sewardj9a036bf2005-03-14 18:19:08 +00003202 UInt theInstr;
ceriona2f75882005-03-15 16:33:38 +00003203 vassert(opc1 < 0x40);
cerionf0de28c2005-12-13 20:21:11 +00003204 vassert(r1 < 0x20);
3205 vassert(r2 < 0x20);
cerion35663a72005-03-01 09:11:49 +00003206 imm = imm & 0xFFFF;
ceriona2f75882005-03-15 16:33:38 +00003207 theInstr = ((opc1<<26) | (r1<<21) | (r2<<16) | (imm));
carll1f5fe1f2014-08-07 23:25:23 +00003208 return emit32(p, theInstr, endness_host);
ceriond5e38382005-02-11 13:38:15 +00003209}
3210
cerionf0de28c2005-12-13 20:21:11 +00003211static UChar* mkFormMD ( UChar* p, UInt opc1, UInt r1, UInt r2,
carll1f5fe1f2014-08-07 23:25:23 +00003212 UInt imm1, UInt imm2, UInt opc2,
3213 VexEndness endness_host )
cerionf0de28c2005-12-13 20:21:11 +00003214{
3215 UInt theInstr;
3216 vassert(opc1 < 0x40);
3217 vassert(r1 < 0x20);
3218 vassert(r2 < 0x20);
3219 vassert(imm1 < 0x40);
3220 vassert(imm2 < 0x40);
3221 vassert(opc2 < 0x08);
3222 imm2 = ((imm2 & 0x1F) << 1) | (imm2 >> 5);
3223 theInstr = ((opc1<<26) | (r1<<21) | (r2<<16) |
cerion5b2325f2005-12-23 00:55:09 +00003224 ((imm1 & 0x1F)<<11) | (imm2<<5) |
3225 (opc2<<2) | ((imm1 >> 5)<<1));
carll1f5fe1f2014-08-07 23:25:23 +00003226 return emit32(p, theInstr, endness_host);
cerionf0de28c2005-12-13 20:21:11 +00003227}
3228
ceriona2f75882005-03-15 16:33:38 +00003229static UChar* mkFormX ( UChar* p, UInt opc1, UInt r1, UInt r2,
carll1f5fe1f2014-08-07 23:25:23 +00003230 UInt r3, UInt opc2, UInt b0, VexEndness endness_host )
ceriond5e38382005-02-11 13:38:15 +00003231{
sewardj9a036bf2005-03-14 18:19:08 +00003232 UInt theInstr;
ceriona2f75882005-03-15 16:33:38 +00003233 vassert(opc1 < 0x40);
cerionf0de28c2005-12-13 20:21:11 +00003234 vassert(r1 < 0x20);
3235 vassert(r2 < 0x20);
3236 vassert(r3 < 0x20);
ceriona2f75882005-03-15 16:33:38 +00003237 vassert(opc2 < 0x400);
cerionf0de28c2005-12-13 20:21:11 +00003238 vassert(b0 < 0x2);
cerion5b2325f2005-12-23 00:55:09 +00003239 theInstr = ((opc1<<26) | (r1<<21) | (r2<<16) |
3240 (r3<<11) | (opc2<<1) | (b0));
carll1f5fe1f2014-08-07 23:25:23 +00003241 return emit32(p, theInstr, endness_host);
ceriond5e38382005-02-11 13:38:15 +00003242}
3243
ceriona2f75882005-03-15 16:33:38 +00003244static UChar* mkFormXO ( UChar* p, UInt opc1, UInt r1, UInt r2,
carll1f5fe1f2014-08-07 23:25:23 +00003245 UInt r3, UInt b10, UInt opc2, UInt b0,
3246 VexEndness endness_host )
cerionab9132d2005-02-15 15:46:59 +00003247{
sewardj9a036bf2005-03-14 18:19:08 +00003248 UInt theInstr;
ceriona2f75882005-03-15 16:33:38 +00003249 vassert(opc1 < 0x40);
cerionf0de28c2005-12-13 20:21:11 +00003250 vassert(r1 < 0x20);
3251 vassert(r2 < 0x20);
3252 vassert(r3 < 0x20);
3253 vassert(b10 < 0x2);
ceriona2f75882005-03-15 16:33:38 +00003254 vassert(opc2 < 0x200);
cerionf0de28c2005-12-13 20:21:11 +00003255 vassert(b0 < 0x2);
ceriona2f75882005-03-15 16:33:38 +00003256 theInstr = ((opc1<<26) | (r1<<21) | (r2<<16) |
3257 (r3<<11) | (b10 << 10) | (opc2<<1) | (b0));
carll1f5fe1f2014-08-07 23:25:23 +00003258 return emit32(p, theInstr, endness_host);
cerionab9132d2005-02-15 15:46:59 +00003259}
ceriond5e38382005-02-11 13:38:15 +00003260
ceriona2f75882005-03-15 16:33:38 +00003261static UChar* mkFormXL ( UChar* p, UInt opc1, UInt f1, UInt f2,
carll1f5fe1f2014-08-07 23:25:23 +00003262 UInt f3, UInt opc2, UInt b0, VexEndness endness_host )
cerion33aa6da2005-02-16 10:25:26 +00003263{
sewardj9a036bf2005-03-14 18:19:08 +00003264 UInt theInstr;
ceriona2f75882005-03-15 16:33:38 +00003265 vassert(opc1 < 0x40);
cerionf0de28c2005-12-13 20:21:11 +00003266 vassert(f1 < 0x20);
3267 vassert(f2 < 0x20);
3268 vassert(f3 < 0x20);
ceriona2f75882005-03-15 16:33:38 +00003269 vassert(opc2 < 0x400);
cerionf0de28c2005-12-13 20:21:11 +00003270 vassert(b0 < 0x2);
cerion5b2325f2005-12-23 00:55:09 +00003271 theInstr = ((opc1<<26) | (f1<<21) | (f2<<16) |
3272 (f3<<11) | (opc2<<1) | (b0));
carll1f5fe1f2014-08-07 23:25:23 +00003273 return emit32(p, theInstr, endness_host);
cerion33aa6da2005-02-16 10:25:26 +00003274}
3275
3276// Note: for split field ops, give mnemonic arg
carll1f5fe1f2014-08-07 23:25:23 +00003277static UChar* mkFormXFX ( UChar* p, UInt r1, UInt f2, UInt opc2,
3278 VexEndness endness_host )
cerion33aa6da2005-02-16 10:25:26 +00003279{
sewardj9a036bf2005-03-14 18:19:08 +00003280 UInt theInstr;
cerionf0de28c2005-12-13 20:21:11 +00003281 vassert(r1 < 0x20);
3282 vassert(f2 < 0x20);
ceriona2f75882005-03-15 16:33:38 +00003283 vassert(opc2 < 0x400);
3284 switch (opc2) {
cerion33aa6da2005-02-16 10:25:26 +00003285 case 144: // mtcrf
3286 vassert(f2 < 0x100);
3287 f2 = f2 << 1;
3288 break;
3289 case 339: // mfspr
3290 case 371: // mftb
3291 case 467: // mtspr
3292 vassert(f2 < 0x400);
cerion5b2325f2005-12-23 00:55:09 +00003293 // re-arrange split field
3294 f2 = ((f2>>5) & 0x1F) | ((f2 & 0x1F)<<5);
cerion33aa6da2005-02-16 10:25:26 +00003295 break;
cerion5b2325f2005-12-23 00:55:09 +00003296 default: vpanic("mkFormXFX(ppch)");
cerion33aa6da2005-02-16 10:25:26 +00003297 }
ceriona2f75882005-03-15 16:33:38 +00003298 theInstr = ((31<<26) | (r1<<21) | (f2<<11) | (opc2<<1));
carll1f5fe1f2014-08-07 23:25:23 +00003299 return emit32(p, theInstr, endness_host);
cerion33aa6da2005-02-16 10:25:26 +00003300}
3301
cerion094d1392005-06-20 13:45:57 +00003302// Only used by mtfsf
carll1f5fe1f2014-08-07 23:25:23 +00003303static UChar* mkFormXFL ( UChar* p, UInt FM, UInt freg, UInt dfp_rm,
3304 VexEndness endness_host )
cerion094d1392005-06-20 13:45:57 +00003305{
3306 UInt theInstr;
3307 vassert(FM < 0x100);
3308 vassert(freg < 0x20);
sewardjc6bbd472012-04-02 10:20:48 +00003309 theInstr = ((63<<26) | (FM<<17) | (dfp_rm<<16) | (freg<<11) | (711<<1));
carll1f5fe1f2014-08-07 23:25:23 +00003310 return emit32(p, theInstr, endness_host);
cerion094d1392005-06-20 13:45:57 +00003311}
3312
cerionf0de28c2005-12-13 20:21:11 +00003313static UChar* mkFormXS ( UChar* p, UInt opc1, UInt r1, UInt r2,
carll1f5fe1f2014-08-07 23:25:23 +00003314 UInt imm, UInt opc2, UInt b0,
3315 VexEndness endness_host )
cerionf0de28c2005-12-13 20:21:11 +00003316{
3317 UInt theInstr;
3318 vassert(opc1 < 0x40);
3319 vassert(r1 < 0x20);
3320 vassert(r2 < 0x20);
3321 vassert(imm < 0x40);
3322 vassert(opc2 < 0x400);
3323 vassert(b0 < 0x2);
3324 theInstr = ((opc1<<26) | (r1<<21) | (r2<<16) |
3325 ((imm & 0x1F)<<11) | (opc2<<2) | ((imm>>5)<<1) | (b0));
carll1f5fe1f2014-08-07 23:25:23 +00003326 return emit32(p, theInstr, endness_host);
cerionf0de28c2005-12-13 20:21:11 +00003327}
3328
3329
cerion33aa6da2005-02-16 10:25:26 +00003330#if 0
3331// 'b'
carll1f5fe1f2014-08-07 23:25:23 +00003332static UChar* mkFormI ( UChar* p, UInt LI, UInt AA, UInt LK,
3333 VexEndness endness_host )
cerion33aa6da2005-02-16 10:25:26 +00003334{
sewardj9a036bf2005-03-14 18:19:08 +00003335 UInt theInstr;
cerion33aa6da2005-02-16 10:25:26 +00003336 vassert(LI < 0x1000000);
3337 vassert(AA < 0x2);
3338 vassert(LK < 0x2);
sewardj9a036bf2005-03-14 18:19:08 +00003339 theInstr = ((18<<26) | (LI<<2) | (AA<<1) | (LK));
carll1f5fe1f2014-08-07 23:25:23 +00003340 return emit32(p, theInstr, endness_host);
cerion33aa6da2005-02-16 10:25:26 +00003341}
3342#endif
3343
3344// 'bc'
3345static UChar* mkFormB ( UChar* p, UInt BO, UInt BI,
carll1f5fe1f2014-08-07 23:25:23 +00003346 UInt BD, UInt AA, UInt LK, VexEndness endness_host )
cerion33aa6da2005-02-16 10:25:26 +00003347{
sewardj9a036bf2005-03-14 18:19:08 +00003348 UInt theInstr;
cerion33aa6da2005-02-16 10:25:26 +00003349 vassert(BO < 0x20);
3350 vassert(BI < 0x20);
3351 vassert(BD < 0x4000);
3352 vassert(AA < 0x2);
3353 vassert(LK < 0x2);
cerion5b2325f2005-12-23 00:55:09 +00003354 theInstr = ((16<<26) | (BO<<21) | (BI<<16) |
3355 (BD<<2) | (AA<<1) | (LK));
carll1f5fe1f2014-08-07 23:25:23 +00003356 return emit32(p, theInstr, endness_host);
cerion33aa6da2005-02-16 10:25:26 +00003357}
3358
cerion33aa6da2005-02-16 10:25:26 +00003359// rotates
ceriona2f75882005-03-15 16:33:38 +00003360static UChar* mkFormM ( UChar* p, UInt opc1, UInt r1, UInt r2,
carll1f5fe1f2014-08-07 23:25:23 +00003361 UInt f3, UInt MB, UInt ME, UInt Rc,
3362 VexEndness endness_host )
cerion33aa6da2005-02-16 10:25:26 +00003363{
sewardj9a036bf2005-03-14 18:19:08 +00003364 UInt theInstr;
ceriona2f75882005-03-15 16:33:38 +00003365 vassert(opc1 < 0x40);
cerionf0de28c2005-12-13 20:21:11 +00003366 vassert(r1 < 0x20);
3367 vassert(r2 < 0x20);
3368 vassert(f3 < 0x20);
3369 vassert(MB < 0x20);
3370 vassert(ME < 0x20);
3371 vassert(Rc < 0x2);
ceriona2f75882005-03-15 16:33:38 +00003372 theInstr = ((opc1<<26) | (r1<<21) | (r2<<16) |
sewardj9a036bf2005-03-14 18:19:08 +00003373 (f3<<11) | (MB<<6) | (ME<<1) | (Rc));
carll1f5fe1f2014-08-07 23:25:23 +00003374 return emit32(p, theInstr, endness_host);
cerion33aa6da2005-02-16 10:25:26 +00003375}
cerion33aa6da2005-02-16 10:25:26 +00003376
cerion094d1392005-06-20 13:45:57 +00003377static UChar* mkFormA ( UChar* p, UInt opc1, UInt r1, UInt r2,
carll1f5fe1f2014-08-07 23:25:23 +00003378 UInt r3, UInt r4, UInt opc2, UInt b0,
3379 VexEndness endness_host )
cerion094d1392005-06-20 13:45:57 +00003380{
3381 UInt theInstr;
3382 vassert(opc1 < 0x40);
3383 vassert(r1 < 0x20);
3384 vassert(r2 < 0x20);
3385 vassert(r3 < 0x20);
3386 vassert(r4 < 0x20);
3387 vassert(opc2 < 0x20);
3388 vassert(b0 < 0x2 );
3389 theInstr = ((opc1<<26) | (r1<<21) | (r2<<16) | (r3<<11) |
3390 (r4<<6) | (opc2<<1) | (b0));
carll1f5fe1f2014-08-07 23:25:23 +00003391 return emit32(p, theInstr, endness_host);
cerion094d1392005-06-20 13:45:57 +00003392}
3393
sewardj26217b02012-04-12 17:19:48 +00003394static UChar* mkFormZ22 ( UChar* p, UInt opc1, UInt r1, UInt r2,
carll1f5fe1f2014-08-07 23:25:23 +00003395 UInt constant, UInt opc2, UInt b0,
3396 VexEndness endness_host)
sewardj26217b02012-04-12 17:19:48 +00003397{
3398 UInt theInstr;
3399 vassert(opc1 < 0x40);
3400 vassert(r1 < 0x20);
3401 vassert(r2 < 0x20);
3402 vassert(constant < 0x40); /* 6 bit constant */
3403 vassert(opc2 < 0x200); /* 9 bit field */
3404 vassert(b0 < 0x2);
3405 theInstr = ((opc1<<26) | (r1<<21) | (r2<<16) |
3406 (constant<<10) | (opc2<<1) | (b0));
carll1f5fe1f2014-08-07 23:25:23 +00003407 return emit32(p, theInstr, endness_host);
sewardj26217b02012-04-12 17:19:48 +00003408}
3409
sewardjcdc376d2012-04-23 11:21:12 +00003410static UChar* mkFormZ23 ( UChar* p, UInt opc1, UInt r1, UInt r2,
carll1f5fe1f2014-08-07 23:25:23 +00003411 UInt r3, UInt rmc, UInt opc2, UInt b0,
3412 VexEndness endness_host)
sewardjcdc376d2012-04-23 11:21:12 +00003413{
3414 UInt theInstr;
3415 vassert(opc1 < 0x40);
3416 vassert(r1 < 0x20);
3417 vassert(r2 < 0x20);
3418 vassert(r3 < 0x20);
3419 vassert(rmc < 0x4);
3420 vassert(opc2 < 0x100);
3421 vassert(b0 < 0x2);
3422 theInstr = ((opc1<<26) | (r1<<21) | (r2<<16) |
3423 (r3<<11) | (rmc<<9) | (opc2<<1) | (b0));
carll1f5fe1f2014-08-07 23:25:23 +00003424 return emit32(p, theInstr, endness_host);
sewardjcdc376d2012-04-23 11:21:12 +00003425}
3426
cerionf0de28c2005-12-13 20:21:11 +00003427static UChar* doAMode_IR ( UChar* p, UInt opc1, UInt rSD,
carll1f5fe1f2014-08-07 23:25:23 +00003428 PPCAMode* am, Bool mode64, VexEndness endness_host )
ceriond5e38382005-02-11 13:38:15 +00003429{
cerioned623db2005-06-20 12:42:04 +00003430 UInt rA, idx;
ceriond5e38382005-02-11 13:38:15 +00003431 vassert(am->tag == Pam_IR);
ceriona2f75882005-03-15 16:33:38 +00003432 vassert(am->Pam.IR.index < 0x10000);
3433
cerionf0de28c2005-12-13 20:21:11 +00003434 rA = iregNo(am->Pam.IR.base, mode64);
sewardj9a036bf2005-03-14 18:19:08 +00003435 idx = am->Pam.IR.index;
ceriona2f75882005-03-15 16:33:38 +00003436
cerionf0de28c2005-12-13 20:21:11 +00003437 if (opc1 == 58 || opc1 == 62) { // ld/std: mode64 only
3438 vassert(mode64);
sewardj34085e32007-03-09 18:07:00 +00003439 /* stay sane with DS form: lowest 2 bits must be 00. This
3440 should be guaranteed to us by iselWordExpr_AMode. */
3441 vassert(0 == (idx & 3));
cerionf0de28c2005-12-13 20:21:11 +00003442 }
carll1f5fe1f2014-08-07 23:25:23 +00003443 p = mkFormD(p, opc1, rSD, rA, idx, endness_host);
ceriond5e38382005-02-11 13:38:15 +00003444 return p;
3445}
3446
ceriona2f75882005-03-15 16:33:38 +00003447static UChar* doAMode_RR ( UChar* p, UInt opc1, UInt opc2,
carll1f5fe1f2014-08-07 23:25:23 +00003448 UInt rSD, PPCAMode* am, Bool mode64,
3449 VexEndness endness_host )
ceriond5e38382005-02-11 13:38:15 +00003450{
cerioned623db2005-06-20 12:42:04 +00003451 UInt rA, rB;
ceriond5e38382005-02-11 13:38:15 +00003452 vassert(am->tag == Pam_RR);
ceriona2f75882005-03-15 16:33:38 +00003453
cerionf0de28c2005-12-13 20:21:11 +00003454 rA = iregNo(am->Pam.RR.base, mode64);
3455 rB = iregNo(am->Pam.RR.index, mode64);
ceriona2f75882005-03-15 16:33:38 +00003456
carll1f5fe1f2014-08-07 23:25:23 +00003457 p = mkFormX(p, opc1, rSD, rA, rB, opc2, 0, endness_host);
ceriond5e38382005-02-11 13:38:15 +00003458 return p;
3459}
3460
cerionf0de28c2005-12-13 20:21:11 +00003461
cerione97e1062005-02-21 15:09:19 +00003462/* Load imm to r_dst */
carll1f5fe1f2014-08-07 23:25:23 +00003463static UChar* mkLoadImm ( UChar* p, UInt r_dst, ULong imm, Bool mode64,
3464 VexEndness endness_host )
cerione97e1062005-02-21 15:09:19 +00003465{
3466 vassert(r_dst < 0x20);
3467
sewardjafd16392006-05-06 14:40:40 +00003468 if (!mode64) {
3469 /* In 32-bit mode, make sure the top 32 bits of imm are a sign
3470 extension of the bottom 32 bits, so that the range tests
3471 below work correctly. */
3472 UInt u32 = (UInt)imm;
3473 Int s32 = (Int)u32;
3474 Long s64 = (Long)s32;
3475 imm = (ULong)s64;
3476 }
3477
cerion5b2325f2005-12-23 00:55:09 +00003478 if (imm >= 0xFFFFFFFFFFFF8000ULL || imm < 0x8000) {
cerionf0de28c2005-12-13 20:21:11 +00003479 // sign-extendable from 16 bits
3480
cerione97e1062005-02-21 15:09:19 +00003481 // addi r_dst,0,imm => li r_dst,imm
carll1f5fe1f2014-08-07 23:25:23 +00003482 p = mkFormD(p, 14, r_dst, 0, imm & 0xFFFF, endness_host);
cerione97e1062005-02-21 15:09:19 +00003483 } else {
cerion5b2325f2005-12-23 00:55:09 +00003484 if (imm >= 0xFFFFFFFF80000000ULL || imm < 0x80000000ULL) {
cerionf0de28c2005-12-13 20:21:11 +00003485 // sign-extendable from 32 bits
3486
3487 // addis r_dst,r0,(imm>>16) => lis r_dst, (imm>>16)
carll1f5fe1f2014-08-07 23:25:23 +00003488 p = mkFormD(p, 15, r_dst, 0, (imm>>16) & 0xFFFF, endness_host);
cerionf0de28c2005-12-13 20:21:11 +00003489 // ori r_dst, r_dst, (imm & 0xFFFF)
carll1f5fe1f2014-08-07 23:25:23 +00003490 p = mkFormD(p, 24, r_dst, r_dst, imm & 0xFFFF, endness_host);
cerionf0de28c2005-12-13 20:21:11 +00003491 } else {
3492 // full 64bit immediate load: 5 (five!) insns.
3493 vassert(mode64);
3494
3495 // load high word
sewardjaca070a2006-10-17 00:28:22 +00003496
cerionf0de28c2005-12-13 20:21:11 +00003497 // lis r_dst, (imm>>48) & 0xFFFF
carll1f5fe1f2014-08-07 23:25:23 +00003498 p = mkFormD(p, 15, r_dst, 0, (imm>>48) & 0xFFFF, endness_host);
sewardjaca070a2006-10-17 00:28:22 +00003499
cerionf0de28c2005-12-13 20:21:11 +00003500 // ori r_dst, r_dst, (imm>>32) & 0xFFFF
sewardjaca070a2006-10-17 00:28:22 +00003501 if ((imm>>32) & 0xFFFF)
carll1f5fe1f2014-08-07 23:25:23 +00003502 p = mkFormD(p, 24, r_dst, r_dst, (imm>>32) & 0xFFFF, endness_host);
cerionf0de28c2005-12-13 20:21:11 +00003503
3504 // shift r_dst low word to high word => rldicr
carll1f5fe1f2014-08-07 23:25:23 +00003505 p = mkFormMD(p, 30, r_dst, r_dst, 32, 31, 1, endness_host);
cerionf0de28c2005-12-13 20:21:11 +00003506
3507 // load low word
sewardjaca070a2006-10-17 00:28:22 +00003508
cerionf0de28c2005-12-13 20:21:11 +00003509 // oris r_dst, r_dst, (imm>>16) & 0xFFFF
sewardjaca070a2006-10-17 00:28:22 +00003510 if ((imm>>16) & 0xFFFF)
carll1f5fe1f2014-08-07 23:25:23 +00003511 p = mkFormD(p, 25, r_dst, r_dst, (imm>>16) & 0xFFFF, endness_host);
sewardjaca070a2006-10-17 00:28:22 +00003512
cerionf0de28c2005-12-13 20:21:11 +00003513 // ori r_dst, r_dst, (imm) & 0xFFFF
sewardjaca070a2006-10-17 00:28:22 +00003514 if (imm & 0xFFFF)
carll1f5fe1f2014-08-07 23:25:23 +00003515 p = mkFormD(p, 24, r_dst, r_dst, imm & 0xFFFF, endness_host);
cerionf0de28c2005-12-13 20:21:11 +00003516 }
cerione97e1062005-02-21 15:09:19 +00003517 }
3518 return p;
3519}
3520
sewardj3dee8492012-04-20 00:13:28 +00003521/* A simplified version of mkLoadImm that always generates 2 or 5
3522 instructions (32 or 64 bits respectively) even if it could generate
3523 fewer. This is needed for generating fixed sized patchable
3524 sequences. */
3525static UChar* mkLoadImm_EXACTLY2or5 ( UChar* p,
carll1f5fe1f2014-08-07 23:25:23 +00003526 UInt r_dst, ULong imm, Bool mode64,
3527 VexEndness endness_host )
sewardj3dee8492012-04-20 00:13:28 +00003528{
3529 vassert(r_dst < 0x20);
3530
3531 if (!mode64) {
3532 /* In 32-bit mode, make sure the top 32 bits of imm are a sign
3533 extension of the bottom 32 bits. (Probably unnecessary.) */
3534 UInt u32 = (UInt)imm;
3535 Int s32 = (Int)u32;
3536 Long s64 = (Long)s32;
3537 imm = (ULong)s64;
3538 }
3539
3540 if (!mode64) {
3541 // addis r_dst,r0,(imm>>16) => lis r_dst, (imm>>16)
carll1f5fe1f2014-08-07 23:25:23 +00003542 p = mkFormD(p, 15, r_dst, 0, (imm>>16) & 0xFFFF, endness_host);
sewardj3dee8492012-04-20 00:13:28 +00003543 // ori r_dst, r_dst, (imm & 0xFFFF)
carll1f5fe1f2014-08-07 23:25:23 +00003544 p = mkFormD(p, 24, r_dst, r_dst, imm & 0xFFFF, endness_host);
sewardj3dee8492012-04-20 00:13:28 +00003545
3546 } else {
3547 // full 64bit immediate load: 5 (five!) insns.
3548
3549 // load high word
3550 // lis r_dst, (imm>>48) & 0xFFFF
carll1f5fe1f2014-08-07 23:25:23 +00003551 p = mkFormD(p, 15, r_dst, 0, (imm>>48) & 0xFFFF, endness_host);
sewardj3dee8492012-04-20 00:13:28 +00003552
3553 // ori r_dst, r_dst, (imm>>32) & 0xFFFF
carll1f5fe1f2014-08-07 23:25:23 +00003554 p = mkFormD(p, 24, r_dst, r_dst, (imm>>32) & 0xFFFF, endness_host);
sewardj3dee8492012-04-20 00:13:28 +00003555
3556 // shift r_dst low word to high word => rldicr
carll1f5fe1f2014-08-07 23:25:23 +00003557 p = mkFormMD(p, 30, r_dst, r_dst, 32, 31, 1, endness_host);
sewardj3dee8492012-04-20 00:13:28 +00003558
3559 // load low word
3560 // oris r_dst, r_dst, (imm>>16) & 0xFFFF
carll1f5fe1f2014-08-07 23:25:23 +00003561 p = mkFormD(p, 25, r_dst, r_dst, (imm>>16) & 0xFFFF, endness_host);
sewardj3dee8492012-04-20 00:13:28 +00003562
3563 // ori r_dst, r_dst, (imm) & 0xFFFF
carll1f5fe1f2014-08-07 23:25:23 +00003564 p = mkFormD(p, 24, r_dst, r_dst, imm & 0xFFFF, endness_host);
sewardj3dee8492012-04-20 00:13:28 +00003565 }
3566 return p;
3567}
3568
3569/* Checks whether the sequence of bytes at p was indeed created
3570 by mkLoadImm_EXACTLY2or5 with the given parameters. */
3571static Bool isLoadImm_EXACTLY2or5 ( UChar* p_to_check,
carll1f5fe1f2014-08-07 23:25:23 +00003572 UInt r_dst, ULong imm, Bool mode64,
3573 VexEndness endness_host )
sewardj3dee8492012-04-20 00:13:28 +00003574{
3575 vassert(r_dst < 0x20);
3576
3577 if (!mode64) {
3578 /* In 32-bit mode, make sure the top 32 bits of imm are a sign
3579 extension of the bottom 32 bits. (Probably unnecessary.) */
3580 UInt u32 = (UInt)imm;
3581 Int s32 = (Int)u32;
3582 Long s64 = (Long)s32;
3583 imm = (ULong)s64;
3584 }
3585
3586 if (!mode64) {
3587 UInt expect[2] = { 0, 0 };
3588 UChar* p = (UChar*)&expect[0];
3589 // addis r_dst,r0,(imm>>16) => lis r_dst, (imm>>16)
carll1f5fe1f2014-08-07 23:25:23 +00003590 p = mkFormD(p, 15, r_dst, 0, (imm>>16) & 0xFFFF, endness_host);
sewardj3dee8492012-04-20 00:13:28 +00003591 // ori r_dst, r_dst, (imm & 0xFFFF)
carll1f5fe1f2014-08-07 23:25:23 +00003592 p = mkFormD(p, 24, r_dst, r_dst, imm & 0xFFFF, endness_host);
sewardj3dee8492012-04-20 00:13:28 +00003593 vassert(p == (UChar*)&expect[2]);
3594
carll1f5fe1f2014-08-07 23:25:23 +00003595 return fetch32(p_to_check + 0, endness_host) == expect[0]
3596 && fetch32(p_to_check + 4, endness_host) == expect[1];
sewardj3dee8492012-04-20 00:13:28 +00003597
3598 } else {
3599 UInt expect[5] = { 0, 0, 0, 0, 0 };
3600 UChar* p = (UChar*)&expect[0];
3601 // full 64bit immediate load: 5 (five!) insns.
3602
3603 // load high word
3604 // lis r_dst, (imm>>48) & 0xFFFF
carll1f5fe1f2014-08-07 23:25:23 +00003605 p = mkFormD(p, 15, r_dst, 0, (imm>>48) & 0xFFFF, endness_host);
sewardj3dee8492012-04-20 00:13:28 +00003606
3607 // ori r_dst, r_dst, (imm>>32) & 0xFFFF
carll1f5fe1f2014-08-07 23:25:23 +00003608 p = mkFormD(p, 24, r_dst, r_dst, (imm>>32) & 0xFFFF, endness_host);
sewardj3dee8492012-04-20 00:13:28 +00003609
3610 // shift r_dst low word to high word => rldicr
carll1f5fe1f2014-08-07 23:25:23 +00003611 p = mkFormMD(p, 30, r_dst, r_dst, 32, 31, 1, endness_host);
sewardj3dee8492012-04-20 00:13:28 +00003612
3613 // load low word
3614 // oris r_dst, r_dst, (imm>>16) & 0xFFFF
carll1f5fe1f2014-08-07 23:25:23 +00003615 p = mkFormD(p, 25, r_dst, r_dst, (imm>>16) & 0xFFFF, endness_host);
sewardj3dee8492012-04-20 00:13:28 +00003616
3617 // ori r_dst, r_dst, (imm) & 0xFFFF
carll1f5fe1f2014-08-07 23:25:23 +00003618 p = mkFormD(p, 24, r_dst, r_dst, imm & 0xFFFF, endness_host);
sewardj3dee8492012-04-20 00:13:28 +00003619
3620 vassert(p == (UChar*)&expect[5]);
3621
carll1f5fe1f2014-08-07 23:25:23 +00003622 return fetch32(p_to_check + 0, endness_host) == expect[0]
3623 && fetch32(p_to_check + 4, endness_host) == expect[1]
3624 && fetch32(p_to_check + 8, endness_host) == expect[2]
3625 && fetch32(p_to_check + 12, endness_host) == expect[3]
3626 && fetch32(p_to_check + 16, endness_host) == expect[4];
sewardj3dee8492012-04-20 00:13:28 +00003627 }
3628}
3629
3630
3631/* Generate a machine-word sized load or store. Simplified version of
3632 the Pin_Load and Pin_Store cases below. */
3633static UChar* do_load_or_store_machine_word (
3634 UChar* p, Bool isLoad,
carll1f5fe1f2014-08-07 23:25:23 +00003635 UInt reg, PPCAMode* am, Bool mode64, VexEndness endness_host )
sewardj3dee8492012-04-20 00:13:28 +00003636{
3637 if (isLoad) {
3638 UInt opc1, sz = mode64 ? 8 : 4;
3639 switch (am->tag) {
3640 case Pam_IR:
3641 if (mode64) {
3642 vassert(0 == (am->Pam.IR.index & 3));
3643 }
3644 switch (sz) {
3645 case 4: opc1 = 32; vassert(!mode64); break;
3646 case 8: opc1 = 58; vassert(mode64); break;
3647 default: vassert(0);
3648 }
carll1f5fe1f2014-08-07 23:25:23 +00003649 p = doAMode_IR(p, opc1, reg, am, mode64, endness_host);
sewardj3dee8492012-04-20 00:13:28 +00003650 break;
3651 case Pam_RR:
3652 /* we could handle this case, but we don't expect to ever
3653 need to. */
3654 vassert(0);
3655 default:
3656 vassert(0);
3657 }
3658 } else /*store*/ {
3659 UInt opc1, sz = mode64 ? 8 : 4;
3660 switch (am->tag) {
3661 case Pam_IR:
3662 if (mode64) {
3663 vassert(0 == (am->Pam.IR.index & 3));
3664 }
3665 switch (sz) {
3666 case 4: opc1 = 36; vassert(!mode64); break;
3667 case 8: opc1 = 62; vassert(mode64); break;
3668 default: vassert(0);
3669 }
carll1f5fe1f2014-08-07 23:25:23 +00003670 p = doAMode_IR(p, opc1, reg, am, mode64, endness_host);
sewardj3dee8492012-04-20 00:13:28 +00003671 break;
3672 case Pam_RR:
3673 /* we could handle this case, but we don't expect to ever
3674 need to. */
3675 vassert(0);
3676 default:
3677 vassert(0);
3678 }
3679 }
3680 return p;
3681}
3682
3683/* Generate a 32-bit sized load or store. Simplified version of
3684 do_load_or_store_machine_word above. */
3685static UChar* do_load_or_store_word32 (
3686 UChar* p, Bool isLoad,
carll1f5fe1f2014-08-07 23:25:23 +00003687 UInt reg, PPCAMode* am, Bool mode64, VexEndness endness_host )
sewardj3dee8492012-04-20 00:13:28 +00003688{
3689 if (isLoad) {
3690 UInt opc1;
3691 switch (am->tag) {
3692 case Pam_IR:
3693 if (mode64) {
3694 vassert(0 == (am->Pam.IR.index & 3));
3695 }
3696 opc1 = 32;
carll1f5fe1f2014-08-07 23:25:23 +00003697 p = doAMode_IR(p, opc1, reg, am, mode64, endness_host);
sewardj3dee8492012-04-20 00:13:28 +00003698 break;
3699 case Pam_RR:
3700 /* we could handle this case, but we don't expect to ever
3701 need to. */
3702 vassert(0);
3703 default:
3704 vassert(0);
3705 }
3706 } else /*store*/ {
3707 UInt opc1;
3708 switch (am->tag) {
3709 case Pam_IR:
3710 if (mode64) {
3711 vassert(0 == (am->Pam.IR.index & 3));
3712 }
3713 opc1 = 36;
carll1f5fe1f2014-08-07 23:25:23 +00003714 p = doAMode_IR(p, opc1, reg, am, mode64, endness_host);
sewardj3dee8492012-04-20 00:13:28 +00003715 break;
3716 case Pam_RR:
3717 /* we could handle this case, but we don't expect to ever
3718 need to. */
3719 vassert(0);
3720 default:
3721 vassert(0);
3722 }
3723 }
3724 return p;
3725}
3726
cerione97e1062005-02-21 15:09:19 +00003727/* Move r_dst to r_src */
carll1f5fe1f2014-08-07 23:25:23 +00003728static UChar* mkMoveReg ( UChar* p, UInt r_dst, UInt r_src,
3729 VexEndness endness_host )
cerione97e1062005-02-21 15:09:19 +00003730{
3731 vassert(r_dst < 0x20);
3732 vassert(r_src < 0x20);
3733
3734 if (r_dst != r_src) {
3735 /* or r_dst, r_src, r_src */
carll1f5fe1f2014-08-07 23:25:23 +00003736 p = mkFormX(p, 31, r_src, r_dst, r_src, 444, 0, endness_host );
cerione97e1062005-02-21 15:09:19 +00003737 }
3738 return p;
3739}
3740
cerionc3d8bdc2005-06-28 18:06:23 +00003741static UChar* mkFormVX ( UChar* p, UInt opc1, UInt r1, UInt r2,
carll1f5fe1f2014-08-07 23:25:23 +00003742 UInt r3, UInt opc2, VexEndness endness_host )
cerionc3d8bdc2005-06-28 18:06:23 +00003743{
3744 UInt theInstr;
3745 vassert(opc1 < 0x40);
3746 vassert(r1 < 0x20);
3747 vassert(r2 < 0x20);
3748 vassert(r3 < 0x20);
3749 vassert(opc2 < 0x800);
cerion6b6f59e2005-06-28 20:59:18 +00003750 theInstr = ((opc1<<26) | (r1<<21) | (r2<<16) | (r3<<11) | opc2);
carll1f5fe1f2014-08-07 23:25:23 +00003751 return emit32(p, theInstr, endness_host);
cerion6b6f59e2005-06-28 20:59:18 +00003752}
3753
carll9877fe52014-10-07 17:49:14 +00003754static UChar* mkFormVXI ( UChar* p, UInt opc1, UInt r1, UInt r2,
3755 UInt r3, UInt opc2, VexEndness endness_host )
3756{
3757 UInt theInstr;
3758 vassert(opc1 < 0x40);
3759 vassert(r1 < 0x20);
3760 vassert(r2 < 0x20);
3761 vassert(r3 < 0x20);
3762 vassert(opc2 < 0x27);
3763 theInstr = ((opc1<<26) | (r1<<21) | (r2<<16) | (r3<<11) | opc2<<1);
3764 return emit32(p, theInstr, endness_host);
3765}
3766
cerion8ea0d3e2005-11-14 00:44:47 +00003767static UChar* mkFormVXR ( UChar* p, UInt opc1, UInt r1, UInt r2,
carll1f5fe1f2014-08-07 23:25:23 +00003768 UInt r3, UInt Rc, UInt opc2,
3769 VexEndness endness_host )
cerion6b6f59e2005-06-28 20:59:18 +00003770{
3771 UInt theInstr;
3772 vassert(opc1 < 0x40);
3773 vassert(r1 < 0x20);
3774 vassert(r2 < 0x20);
3775 vassert(r3 < 0x20);
3776 vassert(Rc < 0x2);
3777 vassert(opc2 < 0x400);
cerion5b2325f2005-12-23 00:55:09 +00003778 theInstr = ((opc1<<26) | (r1<<21) | (r2<<16) |
3779 (r3<<11) | (Rc<<10) | opc2);
carll1f5fe1f2014-08-07 23:25:23 +00003780 return emit32(p, theInstr, endness_host);
cerionc3d8bdc2005-06-28 18:06:23 +00003781}
3782
3783static UChar* mkFormVA ( UChar* p, UInt opc1, UInt r1, UInt r2,
carll1f5fe1f2014-08-07 23:25:23 +00003784 UInt r3, UInt r4, UInt opc2, VexEndness endness_host )
cerionc3d8bdc2005-06-28 18:06:23 +00003785{
3786 UInt theInstr;
3787 vassert(opc1 < 0x40);
3788 vassert(r1 < 0x20);
3789 vassert(r2 < 0x20);
3790 vassert(r3 < 0x20);
3791 vassert(r4 < 0x20);
3792 vassert(opc2 < 0x40);
cerion5b2325f2005-12-23 00:55:09 +00003793 theInstr = ((opc1<<26) | (r1<<21) | (r2<<16) |
3794 (r3<<11) | (r4<<6) | opc2);
carll1f5fe1f2014-08-07 23:25:23 +00003795 return emit32(p, theInstr, endness_host);
cerionc3d8bdc2005-06-28 18:06:23 +00003796}
3797
3798
ceriond5e38382005-02-11 13:38:15 +00003799
cerionbcf8c3e2005-02-04 16:17:07 +00003800/* Emit an instruction into buf and return the number of bytes used.
3801 Note that buf is not the insn's final place, and therefore it is
sewardj3dee8492012-04-20 00:13:28 +00003802 imperative to emit position-independent code. If the emitted
3803 instruction was a profiler inc, set *is_profInc to True, else leave
3804 it unchanged.
sewardjb8a8dba2005-12-15 21:33:50 +00003805*/
sewardj3dee8492012-04-20 00:13:28 +00003806Int emit_PPCInstr ( /*MB_MOD*/Bool* is_profInc,
floriand8c64e02014-10-08 08:54:44 +00003807 UChar* buf, Int nbuf, const PPCInstr* i,
sewardj9b769162014-07-24 12:42:03 +00003808 Bool mode64, VexEndness endness_host,
florian8462d112014-09-24 15:18:09 +00003809 const void* disp_cp_chain_me_to_slowEP,
3810 const void* disp_cp_chain_me_to_fastEP,
3811 const void* disp_cp_xindir,
3812 const void* disp_cp_xassisted)
cerionbcf8c3e2005-02-04 16:17:07 +00003813{
cerionbcf8c3e2005-02-04 16:17:07 +00003814 UChar* p = &buf[0];
cerion7cf8e4e2005-02-16 16:08:17 +00003815 vassert(nbuf >= 32);
cerion2c49e032005-02-09 17:29:49 +00003816
sewardj7fd5bb02006-01-26 02:24:17 +00003817 if (0) {
3818 vex_printf("asm ");ppPPCInstr(i, mode64); vex_printf("\n");
3819 }
cerionbcf8c3e2005-02-04 16:17:07 +00003820
3821 switch (i->tag) {
3822
cerionf0de28c2005-12-13 20:21:11 +00003823 case Pin_LI:
3824 p = mkLoadImm(p, iregNo(i->Pin.LI.dst, mode64),
carll1f5fe1f2014-08-07 23:25:23 +00003825 i->Pin.LI.imm64, mode64, endness_host);
sewardjb51f0f42005-07-18 11:38:02 +00003826 goto done;
3827
cerionf0de28c2005-12-13 20:21:11 +00003828 case Pin_Alu: {
cerion5b2325f2005-12-23 00:55:09 +00003829 PPCRH* srcR = i->Pin.Alu.srcR;
3830 Bool immR = toBool(srcR->tag == Prh_Imm);
3831 UInt r_dst = iregNo(i->Pin.Alu.dst, mode64);
3832 UInt r_srcL = iregNo(i->Pin.Alu.srcL, mode64);
3833 UInt r_srcR = immR ? (-1)/*bogus*/ :
3834 iregNo(srcR->Prh.Reg.reg, mode64);
cerion2c49e032005-02-09 17:29:49 +00003835
cerionf0de28c2005-12-13 20:21:11 +00003836 switch (i->Pin.Alu.op) {
sewardjb51f0f42005-07-18 11:38:02 +00003837 case Palu_ADD:
3838 if (immR) {
3839 /* addi (PPC32 p350) */
3840 vassert(srcR->Prh.Imm.syned);
3841 vassert(srcR->Prh.Imm.imm16 != 0x8000);
carll1f5fe1f2014-08-07 23:25:23 +00003842 p = mkFormD(p, 14, r_dst, r_srcL, srcR->Prh.Imm.imm16, endness_host);
cerion9e263e32005-03-03 17:21:51 +00003843 } else {
sewardjb51f0f42005-07-18 11:38:02 +00003844 /* add (PPC32 p347) */
carll1f5fe1f2014-08-07 23:25:23 +00003845 p = mkFormXO(p, 31, r_dst, r_srcL, r_srcR, 0, 266, 0, endness_host);
cerionab9132d2005-02-15 15:46:59 +00003846 }
sewardjb51f0f42005-07-18 11:38:02 +00003847 break;
cerionab9132d2005-02-15 15:46:59 +00003848
sewardjb51f0f42005-07-18 11:38:02 +00003849 case Palu_SUB:
3850 if (immR) {
3851 /* addi (PPC32 p350), but with negated imm */
3852 vassert(srcR->Prh.Imm.syned);
3853 vassert(srcR->Prh.Imm.imm16 != 0x8000);
carll1f5fe1f2014-08-07 23:25:23 +00003854 p = mkFormD(p, 14, r_dst, r_srcL, (- srcR->Prh.Imm.imm16),
3855 endness_host);
cerion9e263e32005-03-03 17:21:51 +00003856 } else {
sewardjb51f0f42005-07-18 11:38:02 +00003857 /* subf (PPC32 p537), with args the "wrong" way round */
carll1f5fe1f2014-08-07 23:25:23 +00003858 p = mkFormXO(p, 31, r_dst, r_srcR, r_srcL, 0, 40, 0, endness_host);
cerionab9132d2005-02-15 15:46:59 +00003859 }
cerion5e2527e2005-02-25 16:39:58 +00003860 break;
cerion5e2527e2005-02-25 16:39:58 +00003861
sewardjb51f0f42005-07-18 11:38:02 +00003862 case Palu_AND:
3863 if (immR) {
3864 /* andi. (PPC32 p358) */
3865 vassert(!srcR->Prh.Imm.syned);
carll1f5fe1f2014-08-07 23:25:23 +00003866 p = mkFormD(p, 28, r_srcL, r_dst, srcR->Prh.Imm.imm16, endness_host);
sewardjb51f0f42005-07-18 11:38:02 +00003867 } else {
3868 /* and (PPC32 p356) */
carll1f5fe1f2014-08-07 23:25:23 +00003869 p = mkFormX(p, 31, r_srcL, r_dst, r_srcR, 28, 0, endness_host);
cerion9e263e32005-03-03 17:21:51 +00003870 }
cerionb85e8bb2005-02-16 08:54:33 +00003871 break;
cerion9e263e32005-03-03 17:21:51 +00003872
sewardjb51f0f42005-07-18 11:38:02 +00003873 case Palu_OR:
3874 if (immR) {
3875 /* ori (PPC32 p497) */
3876 vassert(!srcR->Prh.Imm.syned);
carll1f5fe1f2014-08-07 23:25:23 +00003877 p = mkFormD(p, 24, r_srcL, r_dst, srcR->Prh.Imm.imm16, endness_host);
sewardjb51f0f42005-07-18 11:38:02 +00003878 } else {
3879 /* or (PPC32 p495) */
carll1f5fe1f2014-08-07 23:25:23 +00003880 p = mkFormX(p, 31, r_srcL, r_dst, r_srcR, 444, 0, endness_host);
sewardjb51f0f42005-07-18 11:38:02 +00003881 }
3882 break;
3883
3884 case Palu_XOR:
3885 if (immR) {
3886 /* xori (PPC32 p550) */
3887 vassert(!srcR->Prh.Imm.syned);
carll1f5fe1f2014-08-07 23:25:23 +00003888 p = mkFormD(p, 26, r_srcL, r_dst, srcR->Prh.Imm.imm16, endness_host);
sewardjb51f0f42005-07-18 11:38:02 +00003889 } else {
3890 /* xor (PPC32 p549) */
carll1f5fe1f2014-08-07 23:25:23 +00003891 p = mkFormX(p, 31, r_srcL, r_dst, r_srcR, 316, 0, endness_host);
sewardjb51f0f42005-07-18 11:38:02 +00003892 }
3893 break;
3894
cerionbb01b7c2005-12-16 13:40:18 +00003895 default:
3896 goto bad;
3897 }
3898 goto done;
3899 }
3900
3901 case Pin_Shft: {
cerion5b2325f2005-12-23 00:55:09 +00003902 PPCRH* srcR = i->Pin.Shft.srcR;
3903 Bool sz32 = i->Pin.Shft.sz32;
3904 Bool immR = toBool(srcR->tag == Prh_Imm);
3905 UInt r_dst = iregNo(i->Pin.Shft.dst, mode64);
3906 UInt r_srcL = iregNo(i->Pin.Shft.srcL, mode64);
3907 UInt r_srcR = immR ? (-1)/*bogus*/ :
3908 iregNo(srcR->Prh.Reg.reg, mode64);
cerionbb01b7c2005-12-16 13:40:18 +00003909 if (!mode64)
3910 vassert(sz32);
3911
3912 switch (i->Pin.Shft.op) {
3913 case Pshft_SHL:
3914 if (sz32) {
cerionf0de28c2005-12-13 20:21:11 +00003915 if (immR) {
3916 /* rd = rs << n, 1 <= n <= 31
3917 is
3918 rlwinm rd,rs,n,0,31-n (PPC32 p501)
3919 */
3920 UInt n = srcR->Prh.Imm.imm16;
3921 vassert(!srcR->Prh.Imm.syned);
3922 vassert(n > 0 && n < 32);
carll1f5fe1f2014-08-07 23:25:23 +00003923 p = mkFormM(p, 21, r_srcL, r_dst, n, 0, 31-n, 0, endness_host);
cerionf0de28c2005-12-13 20:21:11 +00003924 } else {
3925 /* slw (PPC32 p505) */
carll1f5fe1f2014-08-07 23:25:23 +00003926 p = mkFormX(p, 31, r_srcL, r_dst, r_srcR, 24, 0, endness_host);
cerionf0de28c2005-12-13 20:21:11 +00003927 }
sewardjb51f0f42005-07-18 11:38:02 +00003928 } else {
cerionf0de28c2005-12-13 20:21:11 +00003929 if (immR) {
3930 /* rd = rs << n, 1 <= n <= 63
3931 is
3932 rldicr rd,rs,n,63-n (PPC64 p559)
3933 */
3934 UInt n = srcR->Prh.Imm.imm16;
3935 vassert(!srcR->Prh.Imm.syned);
3936 vassert(n > 0 && n < 64);
carll1f5fe1f2014-08-07 23:25:23 +00003937 p = mkFormMD(p, 30, r_srcL, r_dst, n, 63-n, 1, endness_host);
cerionf0de28c2005-12-13 20:21:11 +00003938 } else {
3939 /* sld (PPC64 p568) */
carll1f5fe1f2014-08-07 23:25:23 +00003940 p = mkFormX(p, 31, r_srcL, r_dst, r_srcR, 27, 0, endness_host);
cerionf0de28c2005-12-13 20:21:11 +00003941 }
sewardjb51f0f42005-07-18 11:38:02 +00003942 }
3943 break;
3944
cerionbb01b7c2005-12-16 13:40:18 +00003945 case Pshft_SHR:
3946 if (sz32) {
3947 if (immR) {
cerionf0de28c2005-12-13 20:21:11 +00003948 /* rd = rs >>u n, 1 <= n <= 31
3949 is
3950 rlwinm rd,rs,32-n,n,31 (PPC32 p501)
3951 */
3952 UInt n = srcR->Prh.Imm.imm16;
3953 vassert(!srcR->Prh.Imm.syned);
3954 vassert(n > 0 && n < 32);
carll1f5fe1f2014-08-07 23:25:23 +00003955 p = mkFormM(p, 21, r_srcL, r_dst, 32-n, n, 31, 0, endness_host);
cerionf0de28c2005-12-13 20:21:11 +00003956 } else {
3957 /* srw (PPC32 p508) */
carll1f5fe1f2014-08-07 23:25:23 +00003958 p = mkFormX(p, 31, r_srcL, r_dst, r_srcR, 536, 0, endness_host);
cerionf0de28c2005-12-13 20:21:11 +00003959 }
sewardjb51f0f42005-07-18 11:38:02 +00003960 } else {
cerionf0de28c2005-12-13 20:21:11 +00003961 if (immR) {
3962 /* rd = rs >>u n, 1 <= n <= 63
3963 is
3964 rldicl rd,rs,64-n,n (PPC64 p558)
3965 */
3966 UInt n = srcR->Prh.Imm.imm16;
3967 vassert(!srcR->Prh.Imm.syned);
3968 vassert(n > 0 && n < 64);
carll1f5fe1f2014-08-07 23:25:23 +00003969 p = mkFormMD(p, 30, r_srcL, r_dst, 64-n, n, 0, endness_host);
cerionf0de28c2005-12-13 20:21:11 +00003970 } else {
3971 /* srd (PPC64 p574) */
carll1f5fe1f2014-08-07 23:25:23 +00003972 p = mkFormX(p, 31, r_srcL, r_dst, r_srcR, 539, 0, endness_host);
cerionf0de28c2005-12-13 20:21:11 +00003973 }
sewardjb51f0f42005-07-18 11:38:02 +00003974 }
3975 break;
3976
cerionbb01b7c2005-12-16 13:40:18 +00003977 case Pshft_SAR:
3978 if (sz32) {
cerionf0de28c2005-12-13 20:21:11 +00003979 if (immR) {
3980 /* srawi (PPC32 p507) */
3981 UInt n = srcR->Prh.Imm.imm16;
3982 vassert(!srcR->Prh.Imm.syned);
sewardjeb17e492007-08-25 23:07:44 +00003983 /* In 64-bit mode, we allow right shifts by zero bits
3984 as that is a handy way to sign extend the lower 32
3985 bits into the upper 32 bits. */
3986 if (mode64)
3987 vassert(n >= 0 && n < 32);
3988 else
3989 vassert(n > 0 && n < 32);
carll1f5fe1f2014-08-07 23:25:23 +00003990 p = mkFormX(p, 31, r_srcL, r_dst, n, 824, 0, endness_host);
cerionf0de28c2005-12-13 20:21:11 +00003991 } else {
3992 /* sraw (PPC32 p506) */
carll1f5fe1f2014-08-07 23:25:23 +00003993 p = mkFormX(p, 31, r_srcL, r_dst, r_srcR, 792, 0, endness_host);
cerionf0de28c2005-12-13 20:21:11 +00003994 }
sewardjb51f0f42005-07-18 11:38:02 +00003995 } else {
cerionf0de28c2005-12-13 20:21:11 +00003996 if (immR) {
3997 /* sradi (PPC64 p571) */
3998 UInt n = srcR->Prh.Imm.imm16;
3999 vassert(!srcR->Prh.Imm.syned);
4000 vassert(n > 0 && n < 64);
carll1f5fe1f2014-08-07 23:25:23 +00004001 p = mkFormXS(p, 31, r_srcL, r_dst, n, 413, 0, endness_host);
cerionf0de28c2005-12-13 20:21:11 +00004002 } else {
4003 /* srad (PPC32 p570) */
carll1f5fe1f2014-08-07 23:25:23 +00004004 p = mkFormX(p, 31, r_srcL, r_dst, r_srcR, 794, 0, endness_host);
cerionf0de28c2005-12-13 20:21:11 +00004005 }
sewardjb51f0f42005-07-18 11:38:02 +00004006 }
cerionb85e8bb2005-02-16 08:54:33 +00004007 break;
cerion9e263e32005-03-03 17:21:51 +00004008
cerionab9132d2005-02-15 15:46:59 +00004009 default:
4010 goto bad;
4011 }
cerionb85e8bb2005-02-16 08:54:33 +00004012 goto done;
cerionab9132d2005-02-15 15:46:59 +00004013 }
cerion2c49e032005-02-09 17:29:49 +00004014
cerion5b2325f2005-12-23 00:55:09 +00004015 case Pin_AddSubC: {
4016 Bool isAdd = i->Pin.AddSubC.isAdd;
4017 Bool setC = i->Pin.AddSubC.setC;
4018 UInt r_srcL = iregNo(i->Pin.AddSubC.srcL, mode64);
4019 UInt r_srcR = iregNo(i->Pin.AddSubC.srcR, mode64);
4020 UInt r_dst = iregNo(i->Pin.AddSubC.dst, mode64);
cerion4a49b032005-11-08 16:23:07 +00004021
4022 if (isAdd) {
4023 if (setC) /* addc (PPC32 p348) */
carll1f5fe1f2014-08-07 23:25:23 +00004024 p = mkFormXO(p, 31, r_dst, r_srcL, r_srcR, 0, 10, 0, endness_host);
cerion4a49b032005-11-08 16:23:07 +00004025 else /* adde (PPC32 p349) */
carll1f5fe1f2014-08-07 23:25:23 +00004026 p = mkFormXO(p, 31, r_dst, r_srcL, r_srcR, 0, 138, 0, endness_host);
cerion4a49b032005-11-08 16:23:07 +00004027 } else {
4028 /* subfX, with args the "wrong" way round */
4029 if (setC) /* subfc (PPC32 p538) */
carll1f5fe1f2014-08-07 23:25:23 +00004030 p = mkFormXO(p, 31, r_dst, r_srcR, r_srcL, 0, 8, 0, endness_host);
cerion4a49b032005-11-08 16:23:07 +00004031 else /* subfe (PPC32 p539) */
carll1f5fe1f2014-08-07 23:25:23 +00004032 p = mkFormXO(p, 31, r_dst, r_srcR, r_srcL, 0, 136, 0, endness_host);
cerion4a49b032005-11-08 16:23:07 +00004033 }
4034 goto done;
4035 }
4036
cerionf0de28c2005-12-13 20:21:11 +00004037 case Pin_Cmp: {
4038 Bool syned = i->Pin.Cmp.syned;
cerionbb01b7c2005-12-16 13:40:18 +00004039 Bool sz32 = i->Pin.Cmp.sz32;
cerionf0de28c2005-12-13 20:21:11 +00004040 UInt fld1 = i->Pin.Cmp.crfD << 2;
4041 UInt r_srcL = iregNo(i->Pin.Cmp.srcL, mode64);
ceriona2f75882005-03-15 16:33:38 +00004042 UInt r_srcR, imm_srcR;
cerion5b2325f2005-12-23 00:55:09 +00004043 PPCRH* srcR = i->Pin.Cmp.srcR;
cerionab9132d2005-02-15 15:46:59 +00004044
cerionbb01b7c2005-12-16 13:40:18 +00004045 if (!mode64) // cmp double word invalid for mode32
4046 vassert(sz32);
4047 else if (!sz32) // mode64 && cmp64: set L=1
4048 fld1 |= 1;
4049
sewardjb51f0f42005-07-18 11:38:02 +00004050 switch (srcR->tag) {
4051 case Prh_Imm:
cerionbb01b7c2005-12-16 13:40:18 +00004052 vassert(syned == srcR->Prh.Imm.syned);
sewardjb51f0f42005-07-18 11:38:02 +00004053 imm_srcR = srcR->Prh.Imm.imm16;
cerionbb01b7c2005-12-16 13:40:18 +00004054 if (syned) { // cmpw/di (signed) (PPC32 p368)
sewardjb51f0f42005-07-18 11:38:02 +00004055 vassert(imm_srcR != 0x8000);
carll1f5fe1f2014-08-07 23:25:23 +00004056 p = mkFormD(p, 11, fld1, r_srcL, imm_srcR, endness_host);
cerionbb01b7c2005-12-16 13:40:18 +00004057 } else { // cmplw/di (unsigned) (PPC32 p370)
carll1f5fe1f2014-08-07 23:25:23 +00004058 p = mkFormD(p, 10, fld1, r_srcL, imm_srcR, endness_host);
sewardjb51f0f42005-07-18 11:38:02 +00004059 }
cerion98411db2005-02-16 14:14:49 +00004060 break;
sewardjb51f0f42005-07-18 11:38:02 +00004061 case Prh_Reg:
cerionf0de28c2005-12-13 20:21:11 +00004062 r_srcR = iregNo(srcR->Prh.Reg.reg, mode64);
cerionbb01b7c2005-12-16 13:40:18 +00004063 if (syned) // cmpwi (signed) (PPC32 p367)
carll1f5fe1f2014-08-07 23:25:23 +00004064 p = mkFormX(p, 31, fld1, r_srcL, r_srcR, 0, 0, endness_host);
cerionbb01b7c2005-12-16 13:40:18 +00004065 else // cmplwi (unsigned) (PPC32 p379)
carll1f5fe1f2014-08-07 23:25:23 +00004066 p = mkFormX(p, 31, fld1, r_srcL, r_srcR, 32, 0, endness_host);
cerion98411db2005-02-16 14:14:49 +00004067 break;
sewardjb51f0f42005-07-18 11:38:02 +00004068 default:
4069 goto bad;
cerion98411db2005-02-16 14:14:49 +00004070 }
4071 goto done;
4072 }
cerionb536af92005-02-10 15:03:19 +00004073
cerionf0de28c2005-12-13 20:21:11 +00004074 case Pin_Unary: {
cerion5b2325f2005-12-23 00:55:09 +00004075 UInt r_dst = iregNo(i->Pin.Unary.dst, mode64);
4076 UInt r_src = iregNo(i->Pin.Unary.src, mode64);
cerion98411db2005-02-16 14:14:49 +00004077
cerion5b2325f2005-12-23 00:55:09 +00004078 switch (i->Pin.Unary.op) {
cerion98411db2005-02-16 14:14:49 +00004079 case Pun_NOT: // nor r_dst,r_src,r_src
carll1f5fe1f2014-08-07 23:25:23 +00004080 p = mkFormX(p, 31, r_src, r_dst, r_src, 124, 0, endness_host);
cerion98411db2005-02-16 14:14:49 +00004081 break;
4082 case Pun_NEG: // neg r_dst,r_src
carll1f5fe1f2014-08-07 23:25:23 +00004083 p = mkFormXO(p, 31, r_dst, r_src, 0, 0, 104, 0, endness_host);
cerion98411db2005-02-16 14:14:49 +00004084 break;
cerion07b07a92005-12-22 14:32:35 +00004085 case Pun_CLZ32: // cntlzw r_dst, r_src
carll1f5fe1f2014-08-07 23:25:23 +00004086 p = mkFormX(p, 31, r_src, r_dst, 0, 26, 0, endness_host);
cerion98411db2005-02-16 14:14:49 +00004087 break;
cerion07b07a92005-12-22 14:32:35 +00004088 case Pun_CLZ64: // cntlzd r_dst, r_src
sewardj7fd5bb02006-01-26 02:24:17 +00004089 vassert(mode64);
carll1f5fe1f2014-08-07 23:25:23 +00004090 p = mkFormX(p, 31, r_src, r_dst, 0, 58, 0, endness_host);
cerion07b07a92005-12-22 14:32:35 +00004091 break;
sewardj7fd5bb02006-01-26 02:24:17 +00004092 case Pun_EXTSW: // extsw r_dst, r_src
4093 vassert(mode64);
carll1f5fe1f2014-08-07 23:25:23 +00004094 p = mkFormX(p, 31, r_src, r_dst, 0, 986, 0, endness_host);
sewardj7fd5bb02006-01-26 02:24:17 +00004095 break;
cerion98411db2005-02-16 14:14:49 +00004096 default: goto bad;
4097 }
4098 goto done;
4099 }
4100
4101 case Pin_MulL: {
4102 Bool syned = i->Pin.MulL.syned;
cerionbb01b7c2005-12-16 13:40:18 +00004103 Bool sz32 = i->Pin.MulL.sz32;
cerionf0de28c2005-12-13 20:21:11 +00004104 UInt r_dst = iregNo(i->Pin.MulL.dst, mode64);
4105 UInt r_srcL = iregNo(i->Pin.MulL.srcL, mode64);
4106 UInt r_srcR = iregNo(i->Pin.MulL.srcR, mode64);
cerionbb01b7c2005-12-16 13:40:18 +00004107
4108 if (!mode64)
4109 vassert(sz32);
cerion98411db2005-02-16 14:14:49 +00004110
cerionf0de28c2005-12-13 20:21:11 +00004111 if (i->Pin.MulL.hi) {
sewardjb51f0f42005-07-18 11:38:02 +00004112 // mul hi words, must consider sign
cerionbb01b7c2005-12-16 13:40:18 +00004113 if (sz32) {
4114 if (syned) // mulhw r_dst,r_srcL,r_srcR
carll1f5fe1f2014-08-07 23:25:23 +00004115 p = mkFormXO(p, 31, r_dst, r_srcL, r_srcR, 0, 75, 0,
4116 endness_host);
cerionbb01b7c2005-12-16 13:40:18 +00004117 else // mulhwu r_dst,r_srcL,r_srcR
carll1f5fe1f2014-08-07 23:25:23 +00004118 p = mkFormXO(p, 31, r_dst, r_srcL, r_srcR, 0, 11, 0,
4119 endness_host);
cerionbb01b7c2005-12-16 13:40:18 +00004120 } else {
4121 if (syned) // mulhd r_dst,r_srcL,r_srcR
carll1f5fe1f2014-08-07 23:25:23 +00004122 p = mkFormXO(p, 31, r_dst, r_srcL, r_srcR, 0, 73, 0,
4123 endness_host);
cerionbb01b7c2005-12-16 13:40:18 +00004124 else // mulhdu r_dst,r_srcL,r_srcR
carll1f5fe1f2014-08-07 23:25:23 +00004125 p = mkFormXO(p, 31, r_dst, r_srcL, r_srcR, 0, 9, 0, endness_host);
cerion98411db2005-02-16 14:14:49 +00004126 }
sewardjb51f0f42005-07-18 11:38:02 +00004127 } else {
4128 // mul low word, sign is irrelevant
4129 vassert(!i->Pin.MulL.syned);
cerionbb01b7c2005-12-16 13:40:18 +00004130 if (sz32) // mullw r_dst,r_srcL,r_srcR
carll1f5fe1f2014-08-07 23:25:23 +00004131 p = mkFormXO(p, 31, r_dst, r_srcL, r_srcR, 0, 235, 0, endness_host);
cerionbb01b7c2005-12-16 13:40:18 +00004132 else // mulld r_dst,r_srcL,r_srcR
carll1f5fe1f2014-08-07 23:25:23 +00004133 p = mkFormXO(p, 31, r_dst, r_srcL, r_srcR, 0, 233, 0, endness_host);
cerion98411db2005-02-16 14:14:49 +00004134 }
4135 goto done;
4136 }
cerion2c49e032005-02-09 17:29:49 +00004137
cerionfd0b87f2005-02-16 14:43:14 +00004138 case Pin_Div: {
cerionf0de28c2005-12-13 20:21:11 +00004139 Bool syned = i->Pin.Div.syned;
cerionbb01b7c2005-12-16 13:40:18 +00004140 Bool sz32 = i->Pin.Div.sz32;
cerionf0de28c2005-12-13 20:21:11 +00004141 UInt r_dst = iregNo(i->Pin.Div.dst, mode64);
4142 UInt r_srcL = iregNo(i->Pin.Div.srcL, mode64);
4143 UInt r_srcR = iregNo(i->Pin.Div.srcR, mode64);
cerionfd0b87f2005-02-16 14:43:14 +00004144
cerionbb01b7c2005-12-16 13:40:18 +00004145 if (!mode64)
4146 vassert(sz32);
4147
sewardj4aa412a2011-07-24 14:13:21 +00004148 if (i->Pin.Div.extended) {
4149 if (sz32) {
4150 if (syned)
4151 // divwe r_dst,r_srcL,r_srcR
carll1f5fe1f2014-08-07 23:25:23 +00004152 p = mkFormXO(p, 31, r_dst, r_srcL, r_srcR, 0, 427, 0,
4153 endness_host);
sewardj4aa412a2011-07-24 14:13:21 +00004154 else
4155 // divweu r_dst,r_srcL,r_srcR
carll1f5fe1f2014-08-07 23:25:23 +00004156 p = mkFormXO(p, 31, r_dst, r_srcL, r_srcR, 0, 395, 0,
4157 endness_host);
sewardj4aa412a2011-07-24 14:13:21 +00004158 } else {
sewardje71e56a2011-09-05 12:11:06 +00004159 if (syned)
4160 // divde r_dst,r_srcL,r_srcR
carll1f5fe1f2014-08-07 23:25:23 +00004161 p = mkFormXO(p, 31, r_dst, r_srcL, r_srcR, 0, 425, 0,
4162 endness_host);
sewardje71e56a2011-09-05 12:11:06 +00004163 else
4164 // divdeu r_dst,r_srcL,r_srcR
carll1f5fe1f2014-08-07 23:25:23 +00004165 p = mkFormXO(p, 31, r_dst, r_srcL, r_srcR, 0, 393, 0,
4166 endness_host);
sewardj4aa412a2011-07-24 14:13:21 +00004167 }
4168 } else if (sz32) {
cerionbb01b7c2005-12-16 13:40:18 +00004169 if (syned) // divw r_dst,r_srcL,r_srcR
carll1f5fe1f2014-08-07 23:25:23 +00004170 p = mkFormXO(p, 31, r_dst, r_srcL, r_srcR, 0, 491, 0, endness_host);
cerionbb01b7c2005-12-16 13:40:18 +00004171 else // divwu r_dst,r_srcL,r_srcR
carll1f5fe1f2014-08-07 23:25:23 +00004172 p = mkFormXO(p, 31, r_dst, r_srcL, r_srcR, 0, 459, 0, endness_host);
cerionbb01b7c2005-12-16 13:40:18 +00004173 } else {
4174 if (syned) // divd r_dst,r_srcL,r_srcR
carll1f5fe1f2014-08-07 23:25:23 +00004175 p = mkFormXO(p, 31, r_dst, r_srcL, r_srcR, 0, 489, 0, endness_host);
cerionbb01b7c2005-12-16 13:40:18 +00004176 else // divdu r_dst,r_srcL,r_srcR
carll1f5fe1f2014-08-07 23:25:23 +00004177 p = mkFormXO(p, 31, r_dst, r_srcL, r_srcR, 0, 457, 0, endness_host);
cerionfd0b87f2005-02-16 14:43:14 +00004178 }
4179 goto done;
4180 }
cerion2c49e032005-02-09 17:29:49 +00004181
cerion33aa6da2005-02-16 10:25:26 +00004182 case Pin_Call: {
sewardjcfe046e2013-01-17 14:23:53 +00004183 if (i->Pin.Call.cond.test != Pct_ALWAYS
sewardj74142b82013-08-08 10:28:59 +00004184 && i->Pin.Call.rloc.pri != RLPri_None) {
sewardjcfe046e2013-01-17 14:23:53 +00004185 /* The call might not happen (it isn't unconditional) and it
4186 returns a result. In this case we will need to generate a
4187 control flow diamond to put 0x555..555 in the return
4188 register(s) in the case where the call doesn't happen. If
4189 this ever becomes necessary, maybe copy code from the ARM
4190 equivalent. Until that day, just give up. */
4191 goto bad;
4192 }
cerion5b2325f2005-12-23 00:55:09 +00004193 PPCCondCode cond = i->Pin.Call.cond;
4194 UInt r_dst = 10;
ceriona56e9cc2005-02-16 18:08:25 +00004195 /* As per detailed comment for Pin_Call in
cerion5b2325f2005-12-23 00:55:09 +00004196 getRegUsage_PPCInstr above, %r10 is used as an address temp */
ceriona56e9cc2005-02-16 18:08:25 +00004197
cerioned623db2005-06-20 12:42:04 +00004198 /* jump over the following insns if condition does not hold */
sewardj3dee8492012-04-20 00:13:28 +00004199 UChar* ptmp = NULL;
cerione97e1062005-02-21 15:09:19 +00004200 if (cond.test != Pct_ALWAYS) {
cerion9762bbf2005-06-23 08:44:52 +00004201 /* jmp fwds if !condition */
4202 /* don't know how many bytes to jump over yet...
4203 make space for a jump instruction and fill in later. */
4204 ptmp = p; /* fill in this bit later */
cerion5b2325f2005-12-23 00:55:09 +00004205 p += 4; // p += 4
cerionab9132d2005-02-15 15:46:59 +00004206 }
4207
cerion5b2325f2005-12-23 00:55:09 +00004208 /* load target to r_dst */ // p += 4|8|20
carll1f5fe1f2014-08-07 23:25:23 +00004209 p = mkLoadImm(p, r_dst, i->Pin.Call.target, mode64, endness_host);
cerionab9132d2005-02-15 15:46:59 +00004210
ceriona56e9cc2005-02-16 18:08:25 +00004211 /* mtspr 9,r_dst => move r_dst to count register */
carll1f5fe1f2014-08-07 23:25:23 +00004212 p = mkFormXFX(p, r_dst, 9, 467, endness_host); // p += 4
cerion33aa6da2005-02-16 10:25:26 +00004213
cerion8c51ed42005-02-22 11:16:54 +00004214 /* bctrl => branch to count register (and save to lr) */
carll1f5fe1f2014-08-07 23:25:23 +00004215 p = mkFormXL(p, 19, Pct_ALWAYS, 0, 0, 528, 1, endness_host); // p += 4
cerion9762bbf2005-06-23 08:44:52 +00004216
4217 /* Fix up the conditional jump, if there was one. */
4218 if (cond.test != Pct_ALWAYS) {
4219 Int delta = p - ptmp;
cerionf0de28c2005-12-13 20:21:11 +00004220 vassert(delta >= 16 && delta <= 32);
cerion9762bbf2005-06-23 08:44:52 +00004221 /* bc !ct,cf,delta */
cerion5b2325f2005-12-23 00:55:09 +00004222 mkFormB(ptmp, invertCondTest(cond.test),
carll1f5fe1f2014-08-07 23:25:23 +00004223 cond.flag, (delta>>2), 0, 0, endness_host);
cerion9762bbf2005-06-23 08:44:52 +00004224 }
cerion33aa6da2005-02-16 10:25:26 +00004225 goto done;
4226 }
4227
sewardj3dee8492012-04-20 00:13:28 +00004228 case Pin_XDirect: {
4229 /* NB: what goes on here has to be very closely coordinated
4230 with the chainXDirect_PPC and unchainXDirect_PPC below. */
4231 /* We're generating chain-me requests here, so we need to be
4232 sure this is actually allowed -- no-redir translations
4233 can't use chain-me's. Hence: */
4234 vassert(disp_cp_chain_me_to_slowEP != NULL);
4235 vassert(disp_cp_chain_me_to_fastEP != NULL);
sewardjb8a8dba2005-12-15 21:33:50 +00004236
sewardj3dee8492012-04-20 00:13:28 +00004237 /* First off, if this is conditional, create a conditional jump
4238 over the rest of it. Or at least, leave a space for it that
4239 we will shortly fill in. */
4240 UChar* ptmp = NULL;
4241 if (i->Pin.XDirect.cond.test != Pct_ALWAYS) {
4242 vassert(i->Pin.XDirect.cond.flag != Pcf_NONE);
4243 ptmp = p;
cerione97e1062005-02-21 15:09:19 +00004244 p += 4;
cerion33aa6da2005-02-16 10:25:26 +00004245 } else {
sewardj3dee8492012-04-20 00:13:28 +00004246 vassert(i->Pin.XDirect.cond.flag == Pcf_NONE);
cerion33aa6da2005-02-16 10:25:26 +00004247 }
sewardj3dee8492012-04-20 00:13:28 +00004248
4249 /* Update the guest CIA. */
4250 /* imm32/64 r30, dstGA */
4251 if (!mode64) vassert(0 == (((ULong)i->Pin.XDirect.dstGA) >> 32));
carll1f5fe1f2014-08-07 23:25:23 +00004252 p = mkLoadImm(p, /*r*/30, (ULong)i->Pin.XDirect.dstGA, mode64,
4253 endness_host);
sewardj3dee8492012-04-20 00:13:28 +00004254 /* stw/std r30, amCIA */
4255 p = do_load_or_store_machine_word(
4256 p, False/*!isLoad*/,
carll1f5fe1f2014-08-07 23:25:23 +00004257 /*r*/30, i->Pin.XDirect.amCIA, mode64, endness_host
sewardj3dee8492012-04-20 00:13:28 +00004258 );
4259
4260 /* --- FIRST PATCHABLE BYTE follows --- */
4261 /* VG_(disp_cp_chain_me_to_{slowEP,fastEP}) (where we're calling
4262 to) backs up the return address, so as to find the address of
4263 the first patchable byte. So: don't change the number of
4264 instructions (32-bit: 4, 64-bit: 7) below. */
4265 /* imm32/64-fixed r30, VG_(disp_cp_chain_me_to_{slowEP,fastEP} */
florian8462d112014-09-24 15:18:09 +00004266 const void* disp_cp_chain_me
sewardj3dee8492012-04-20 00:13:28 +00004267 = i->Pin.XDirect.toFastEP ? disp_cp_chain_me_to_fastEP
4268 : disp_cp_chain_me_to_slowEP;
4269 p = mkLoadImm_EXACTLY2or5(
carll1f5fe1f2014-08-07 23:25:23 +00004270 p, /*r*/30, Ptr_to_ULong(disp_cp_chain_me), mode64, endness_host);
sewardj3dee8492012-04-20 00:13:28 +00004271 /* mtctr r30 */
carll1f5fe1f2014-08-07 23:25:23 +00004272 p = mkFormXFX(p, /*r*/30, 9, 467, endness_host);
sewardj3dee8492012-04-20 00:13:28 +00004273 /* bctrl */
carll1f5fe1f2014-08-07 23:25:23 +00004274 p = mkFormXL(p, 19, Pct_ALWAYS, 0, 0, 528, 1, endness_host);
sewardj3dee8492012-04-20 00:13:28 +00004275 /* --- END of PATCHABLE BYTES --- */
cerion7cf8e4e2005-02-16 16:08:17 +00004276
4277 /* Fix up the conditional jump, if there was one. */
sewardj3dee8492012-04-20 00:13:28 +00004278 if (i->Pin.XDirect.cond.test != Pct_ALWAYS) {
cerion7cf8e4e2005-02-16 16:08:17 +00004279 Int delta = p - ptmp;
sewardj9e1cf152012-04-20 02:18:31 +00004280 vassert(delta >= 16 && delta <= 64 && 0 == (delta & 3));
cerione97e1062005-02-21 15:09:19 +00004281 /* bc !ct,cf,delta */
sewardj3dee8492012-04-20 00:13:28 +00004282 mkFormB(ptmp, invertCondTest(i->Pin.XDirect.cond.test),
carll1f5fe1f2014-08-07 23:25:23 +00004283 i->Pin.XDirect.cond.flag, (delta>>2), 0, 0, endness_host);
sewardj3dee8492012-04-20 00:13:28 +00004284 }
4285 goto done;
4286 }
4287
4288 case Pin_XIndir: {
4289 /* We're generating transfers that could lead indirectly to a
4290 chain-me, so we need to be sure this is actually allowed --
4291 no-redir translations are not allowed to reach normal
4292 translations without going through the scheduler. That means
4293 no XDirects or XIndirs out from no-redir translations.
4294 Hence: */
4295 vassert(disp_cp_xindir != NULL);
4296
4297 /* First off, if this is conditional, create a conditional jump
4298 over the rest of it. Or at least, leave a space for it that
4299 we will shortly fill in. */
4300 UChar* ptmp = NULL;
4301 if (i->Pin.XIndir.cond.test != Pct_ALWAYS) {
4302 vassert(i->Pin.XIndir.cond.flag != Pcf_NONE);
4303 ptmp = p;
4304 p += 4;
4305 } else {
4306 vassert(i->Pin.XIndir.cond.flag == Pcf_NONE);
4307 }
4308
4309 /* Update the guest CIA. */
4310 /* stw/std r-dstGA, amCIA */
4311 p = do_load_or_store_machine_word(
4312 p, False/*!isLoad*/,
4313 iregNo(i->Pin.XIndir.dstGA, mode64),
carll1f5fe1f2014-08-07 23:25:23 +00004314 i->Pin.XIndir.amCIA, mode64, endness_host
sewardj3dee8492012-04-20 00:13:28 +00004315 );
4316
4317 /* imm32/64 r30, VG_(disp_cp_xindir) */
carll1f5fe1f2014-08-07 23:25:23 +00004318 p = mkLoadImm(p, /*r*/30, (ULong)Ptr_to_ULong(disp_cp_xindir), mode64,
4319 endness_host);
sewardj3dee8492012-04-20 00:13:28 +00004320 /* mtctr r30 */
carll1f5fe1f2014-08-07 23:25:23 +00004321 p = mkFormXFX(p, /*r*/30, 9, 467, endness_host);
sewardj3dee8492012-04-20 00:13:28 +00004322 /* bctr */
carll1f5fe1f2014-08-07 23:25:23 +00004323 p = mkFormXL(p, 19, Pct_ALWAYS, 0, 0, 528, 0, endness_host);
sewardj3dee8492012-04-20 00:13:28 +00004324
4325 /* Fix up the conditional jump, if there was one. */
4326 if (i->Pin.XIndir.cond.test != Pct_ALWAYS) {
4327 Int delta = p - ptmp;
4328 vassert(delta >= 16 && delta <= 32 && 0 == (delta & 3));
4329 /* bc !ct,cf,delta */
4330 mkFormB(ptmp, invertCondTest(i->Pin.XIndir.cond.test),
carll1f5fe1f2014-08-07 23:25:23 +00004331 i->Pin.XIndir.cond.flag, (delta>>2), 0, 0, endness_host);
sewardj3dee8492012-04-20 00:13:28 +00004332 }
4333 goto done;
4334 }
4335
4336 case Pin_XAssisted: {
4337 /* First off, if this is conditional, create a conditional jump
4338 over the rest of it. Or at least, leave a space for it that
4339 we will shortly fill in. */
4340 UChar* ptmp = NULL;
4341 if (i->Pin.XAssisted.cond.test != Pct_ALWAYS) {
4342 vassert(i->Pin.XAssisted.cond.flag != Pcf_NONE);
4343 ptmp = p;
4344 p += 4;
4345 } else {
4346 vassert(i->Pin.XAssisted.cond.flag == Pcf_NONE);
4347 }
4348
4349 /* Update the guest CIA. */
4350 /* stw/std r-dstGA, amCIA */
4351 p = do_load_or_store_machine_word(
4352 p, False/*!isLoad*/,
4353 iregNo(i->Pin.XIndir.dstGA, mode64),
carll1f5fe1f2014-08-07 23:25:23 +00004354 i->Pin.XIndir.amCIA, mode64, endness_host
sewardj3dee8492012-04-20 00:13:28 +00004355 );
4356
4357 /* imm32/64 r31, $magic_number */
4358 UInt trcval = 0;
4359 switch (i->Pin.XAssisted.jk) {
4360 case Ijk_ClientReq: trcval = VEX_TRC_JMP_CLIENTREQ; break;
4361 case Ijk_Sys_syscall: trcval = VEX_TRC_JMP_SYS_SYSCALL; break;
4362 //case Ijk_Sys_int128: trcval = VEX_TRC_JMP_SYS_INT128; break;
4363 //case Ijk_Yield: trcval = VEX_TRC_JMP_YIELD; break;
4364 case Ijk_EmWarn: trcval = VEX_TRC_JMP_EMWARN; break;
sewardjf252de52012-04-20 10:42:24 +00004365 case Ijk_EmFail: trcval = VEX_TRC_JMP_EMFAIL; break;
sewardj3dee8492012-04-20 00:13:28 +00004366 //case Ijk_MapFail: trcval = VEX_TRC_JMP_MAPFAIL; break;
4367 case Ijk_NoDecode: trcval = VEX_TRC_JMP_NODECODE; break;
sewardj05f5e012014-05-04 10:52:11 +00004368 case Ijk_InvalICache: trcval = VEX_TRC_JMP_INVALICACHE; break;
sewardj3dee8492012-04-20 00:13:28 +00004369 case Ijk_NoRedir: trcval = VEX_TRC_JMP_NOREDIR; break;
4370 case Ijk_SigTRAP: trcval = VEX_TRC_JMP_SIGTRAP; break;
4371 //case Ijk_SigSEGV: trcval = VEX_TRC_JMP_SIGSEGV; break;
4372 case Ijk_SigBUS: trcval = VEX_TRC_JMP_SIGBUS; break;
4373 case Ijk_Boring: trcval = VEX_TRC_JMP_BORING; break;
4374 /* We don't expect to see the following being assisted. */
4375 //case Ijk_Ret:
4376 //case Ijk_Call:
4377 /* fallthrough */
4378 default:
4379 ppIRJumpKind(i->Pin.XAssisted.jk);
4380 vpanic("emit_ARMInstr.Pin_XAssisted: unexpected jump kind");
4381 }
4382 vassert(trcval != 0);
carll1f5fe1f2014-08-07 23:25:23 +00004383 p = mkLoadImm(p, /*r*/31, trcval, mode64, endness_host);
sewardj3dee8492012-04-20 00:13:28 +00004384
4385 /* imm32/64 r30, VG_(disp_cp_xassisted) */
4386 p = mkLoadImm(p, /*r*/30,
carll1f5fe1f2014-08-07 23:25:23 +00004387 (ULong)Ptr_to_ULong(disp_cp_xassisted), mode64,
4388 endness_host);
sewardj3dee8492012-04-20 00:13:28 +00004389 /* mtctr r30 */
carll1f5fe1f2014-08-07 23:25:23 +00004390 p = mkFormXFX(p, /*r*/30, 9, 467, endness_host);
sewardj3dee8492012-04-20 00:13:28 +00004391 /* bctr */
carll1f5fe1f2014-08-07 23:25:23 +00004392 p = mkFormXL(p, 19, Pct_ALWAYS, 0, 0, 528, 0, endness_host);
sewardj3dee8492012-04-20 00:13:28 +00004393
4394 /* Fix up the conditional jump, if there was one. */
4395 if (i->Pin.XAssisted.cond.test != Pct_ALWAYS) {
4396 Int delta = p - ptmp;
4397 vassert(delta >= 16 && delta <= 32 && 0 == (delta & 3));
4398 /* bc !ct,cf,delta */
4399 mkFormB(ptmp, invertCondTest(i->Pin.XAssisted.cond.test),
carll1f5fe1f2014-08-07 23:25:23 +00004400 i->Pin.XAssisted.cond.flag, (delta>>2), 0, 0, endness_host);
cerion7cf8e4e2005-02-16 16:08:17 +00004401 }
cerion33aa6da2005-02-16 10:25:26 +00004402 goto done;
4403 }
cerionb536af92005-02-10 15:03:19 +00004404
cerionf0de28c2005-12-13 20:21:11 +00004405 case Pin_CMov: {
cerion5b2325f2005-12-23 00:55:09 +00004406 UInt r_dst, r_src;
cerionf0de28c2005-12-13 20:21:11 +00004407 ULong imm_src;
cerion5b2325f2005-12-23 00:55:09 +00004408 PPCCondCode cond;
cerionf0de28c2005-12-13 20:21:11 +00004409 vassert(i->Pin.CMov.cond.test != Pct_ALWAYS);
ceriona2f75882005-03-15 16:33:38 +00004410
cerionf0de28c2005-12-13 20:21:11 +00004411 r_dst = iregNo(i->Pin.CMov.dst, mode64);
4412 cond = i->Pin.CMov.cond;
cerion98411db2005-02-16 14:14:49 +00004413
cerione97e1062005-02-21 15:09:19 +00004414 /* branch (if cond fails) over move instrs */
sewardj3dee8492012-04-20 00:13:28 +00004415 UChar* ptmp = NULL;
cerione97e1062005-02-21 15:09:19 +00004416 if (cond.test != Pct_ALWAYS) {
4417 /* don't know how many bytes to jump over yet...
4418 make space for a jump instruction and fill in later. */
4419 ptmp = p; /* fill in this bit later */
4420 p += 4;
4421 }
cerion98411db2005-02-16 14:14:49 +00004422
4423 // cond true: move src => dst
cerionf0de28c2005-12-13 20:21:11 +00004424 switch (i->Pin.CMov.src->tag) {
cerion98411db2005-02-16 14:14:49 +00004425 case Pri_Imm:
cerionf0de28c2005-12-13 20:21:11 +00004426 imm_src = i->Pin.CMov.src->Pri.Imm;
carll1f5fe1f2014-08-07 23:25:23 +00004427 p = mkLoadImm(p, r_dst, imm_src, mode64, endness_host); // p += 4|8|20
cerion98411db2005-02-16 14:14:49 +00004428 break;
4429 case Pri_Reg:
cerionf0de28c2005-12-13 20:21:11 +00004430 r_src = iregNo(i->Pin.CMov.src->Pri.Reg, mode64);
carll1f5fe1f2014-08-07 23:25:23 +00004431 p = mkMoveReg(p, r_dst, r_src, endness_host); // p += 4
cerion98411db2005-02-16 14:14:49 +00004432 break;
4433 default: goto bad;
4434 }
cerione97e1062005-02-21 15:09:19 +00004435
4436 /* Fix up the conditional jump, if there was one. */
4437 if (cond.test != Pct_ALWAYS) {
4438 Int delta = p - ptmp;
cerionf0de28c2005-12-13 20:21:11 +00004439 vassert(delta >= 8 && delta <= 24);
cerione97e1062005-02-21 15:09:19 +00004440 /* bc !ct,cf,delta */
cerion5b2325f2005-12-23 00:55:09 +00004441 mkFormB(ptmp, invertCondTest(cond.test),
carll1f5fe1f2014-08-07 23:25:23 +00004442 cond.flag, (delta>>2), 0, 0, endness_host);
cerione97e1062005-02-21 15:09:19 +00004443 }
cerion98411db2005-02-16 14:14:49 +00004444 goto done;
4445 }
cerionb536af92005-02-10 15:03:19 +00004446
cerion7cf8e4e2005-02-16 16:08:17 +00004447 case Pin_Load: {
cerion5b2325f2005-12-23 00:55:09 +00004448 PPCAMode* am_addr = i->Pin.Load.src;
cerionf0de28c2005-12-13 20:21:11 +00004449 UInt r_dst = iregNo(i->Pin.Load.dst, mode64);
ceriona2f75882005-03-15 16:33:38 +00004450 UInt opc1, opc2, sz = i->Pin.Load.sz;
cerionf0de28c2005-12-13 20:21:11 +00004451 switch (am_addr->tag) {
ceriond5e38382005-02-11 13:38:15 +00004452 case Pam_IR:
sewardj34085e32007-03-09 18:07:00 +00004453 if (mode64 && (sz == 4 || sz == 8)) {
4454 /* should be guaranteed to us by iselWordExpr_AMode */
4455 vassert(0 == (am_addr->Pam.IR.index & 3));
4456 }
cerionf0de28c2005-12-13 20:21:11 +00004457 switch(sz) {
sewardj7fd5bb02006-01-26 02:24:17 +00004458 case 1: opc1 = 34; break;
4459 case 2: opc1 = 40; break;
4460 case 4: opc1 = 32; break;
4461 case 8: opc1 = 58; vassert(mode64); break;
4462 default: goto bad;
cerionab9132d2005-02-15 15:46:59 +00004463 }
carll1f5fe1f2014-08-07 23:25:23 +00004464 p = doAMode_IR(p, opc1, r_dst, am_addr, mode64, endness_host);
cerionab9132d2005-02-15 15:46:59 +00004465 goto done;
ceriond5e38382005-02-11 13:38:15 +00004466 case Pam_RR:
cerionf0de28c2005-12-13 20:21:11 +00004467 switch(sz) {
sewardj7fd5bb02006-01-26 02:24:17 +00004468 case 1: opc2 = 87; break;
4469 case 2: opc2 = 279; break;
4470 case 4: opc2 = 23; break;
4471 case 8: opc2 = 21; vassert(mode64); break;
4472 default: goto bad;
cerionab9132d2005-02-15 15:46:59 +00004473 }
carll1f5fe1f2014-08-07 23:25:23 +00004474 p = doAMode_RR(p, 31, opc2, r_dst, am_addr, mode64, endness_host);
cerionab9132d2005-02-15 15:46:59 +00004475 goto done;
ceriond5e38382005-02-11 13:38:15 +00004476 default:
cerionab9132d2005-02-15 15:46:59 +00004477 goto bad;
ceriond5e38382005-02-11 13:38:15 +00004478 }
4479 }
cerionb536af92005-02-10 15:03:19 +00004480
sewardje9d8a262009-07-01 08:06:34 +00004481 case Pin_LoadL: {
4482 if (i->Pin.LoadL.sz == 4) {
4483 p = mkFormX(p, 31, iregNo(i->Pin.LoadL.dst, mode64),
carll1f5fe1f2014-08-07 23:25:23 +00004484 0, iregNo(i->Pin.LoadL.src, mode64), 20, 0, endness_host);
sewardje9d8a262009-07-01 08:06:34 +00004485 goto done;
4486 }
4487 if (i->Pin.LoadL.sz == 8 && mode64) {
4488 p = mkFormX(p, 31, iregNo(i->Pin.LoadL.dst, mode64),
carll1f5fe1f2014-08-07 23:25:23 +00004489 0, iregNo(i->Pin.LoadL.src, mode64), 84, 0, endness_host);
sewardje9d8a262009-07-01 08:06:34 +00004490 goto done;
4491 }
4492 goto bad;
4493 }
4494
cerion5b2325f2005-12-23 00:55:09 +00004495 case Pin_Set: {
cerionab9132d2005-02-15 15:46:59 +00004496 /* Make the destination register be 1 or 0, depending on whether
cerion9e263e32005-03-03 17:21:51 +00004497 the relevant condition holds. */
cerion5b2325f2005-12-23 00:55:09 +00004498 UInt r_dst = iregNo(i->Pin.Set.dst, mode64);
4499 PPCCondCode cond = i->Pin.Set.cond;
4500 UInt rot_imm, r_tmp;
cerion98411db2005-02-16 14:14:49 +00004501
4502 if (cond.test == Pct_ALWAYS) {
cerion9e263e32005-03-03 17:21:51 +00004503 // Just load 1 to dst => li dst,1
carll1f5fe1f2014-08-07 23:25:23 +00004504 p = mkFormD(p, 14, r_dst, 0, 1, endness_host);
cerionab9132d2005-02-15 15:46:59 +00004505 } else {
sewardj7e308072011-05-04 09:50:48 +00004506 vassert(cond.flag != Pcf_NONE);
cerion7cf8e4e2005-02-16 16:08:17 +00004507 rot_imm = 1 + cond.flag;
cerion5b2325f2005-12-23 00:55:09 +00004508 r_tmp = 0; // Not set in getAllocable, so no need to declare.
cerion98411db2005-02-16 14:14:49 +00004509
4510 // r_tmp = CR => mfcr r_tmp
carll1f5fe1f2014-08-07 23:25:23 +00004511 p = mkFormX(p, 31, r_tmp, 0, 0, 19, 0, endness_host);
cerion98411db2005-02-16 14:14:49 +00004512
4513 // r_dst = flag (rotate left and mask)
cerion7cf8e4e2005-02-16 16:08:17 +00004514 // => rlwinm r_dst,r_tmp,rot_imm,31,31
carll1f5fe1f2014-08-07 23:25:23 +00004515 p = mkFormM(p, 21, r_tmp, r_dst, rot_imm, 31, 31, 0, endness_host);
cerion98411db2005-02-16 14:14:49 +00004516
4517 if (cond.test == Pct_FALSE) {
ceriona2f75882005-03-15 16:33:38 +00004518 // flip bit => xori r_dst,r_dst,1
carll1f5fe1f2014-08-07 23:25:23 +00004519 p = mkFormD(p, 26, r_dst, r_dst, 1, endness_host);
cerionab9132d2005-02-15 15:46:59 +00004520 }
4521 }
4522 goto done;
cerionab9132d2005-02-15 15:46:59 +00004523 }
cerionb536af92005-02-10 15:03:19 +00004524
sewardjb51f0f42005-07-18 11:38:02 +00004525 case Pin_MfCR:
4526 // mfcr dst
carll1f5fe1f2014-08-07 23:25:23 +00004527 p = mkFormX(p, 31, iregNo(i->Pin.MfCR.dst, mode64), 0, 0, 19, 0,
4528 endness_host);
sewardjb51f0f42005-07-18 11:38:02 +00004529 goto done;
4530
cerion98411db2005-02-16 14:14:49 +00004531 case Pin_MFence: {
carll1f5fe1f2014-08-07 23:25:23 +00004532 p = mkFormX(p, 31, 0, 0, 0, 598, 0, endness_host); // sync, PPC32 p616
sewardje9d8a262009-07-01 08:06:34 +00004533 // CAB: Should this be isync?
4534 // p = mkFormXL(p, 19, 0, 0, 0, 150, 0); // isync, PPC32 p467
cerion98411db2005-02-16 14:14:49 +00004535 goto done;
4536 }
cerionb536af92005-02-10 15:03:19 +00004537
ceriond5e38382005-02-11 13:38:15 +00004538 case Pin_Store: {
cerion5b2325f2005-12-23 00:55:09 +00004539 PPCAMode* am_addr = i->Pin.Store.dst;
cerionf0de28c2005-12-13 20:21:11 +00004540 UInt r_src = iregNo(i->Pin.Store.src, mode64);
ceriona2f75882005-03-15 16:33:38 +00004541 UInt opc1, opc2, sz = i->Pin.Store.sz;
ceriond5e38382005-02-11 13:38:15 +00004542 switch (i->Pin.Store.dst->tag) {
4543 case Pam_IR:
sewardj34085e32007-03-09 18:07:00 +00004544 if (mode64 && (sz == 4 || sz == 8)) {
4545 /* should be guaranteed to us by iselWordExpr_AMode */
4546 vassert(0 == (am_addr->Pam.IR.index & 3));
4547 }
cerionf0de28c2005-12-13 20:21:11 +00004548 switch(sz) {
4549 case 1: opc1 = 38; break;
4550 case 2: opc1 = 44; break;
4551 case 4: opc1 = 36; break;
4552 case 8: vassert(mode64);
4553 opc1 = 62; break;
4554 default:
4555 goto bad;
4556 }
carll1f5fe1f2014-08-07 23:25:23 +00004557 p = doAMode_IR(p, opc1, r_src, am_addr, mode64, endness_host);
cerionab9132d2005-02-15 15:46:59 +00004558 goto done;
ceriond5e38382005-02-11 13:38:15 +00004559 case Pam_RR:
cerionf0de28c2005-12-13 20:21:11 +00004560 switch(sz) {
4561 case 1: opc2 = 215; break;
4562 case 2: opc2 = 407; break;
4563 case 4: opc2 = 151; break;
4564 case 8: vassert(mode64);
4565 opc2 = 149; break;
4566 default:
4567 goto bad;
4568 }
carll1f5fe1f2014-08-07 23:25:23 +00004569 p = doAMode_RR(p, 31, opc2, r_src, am_addr, mode64, endness_host);
cerionab9132d2005-02-15 15:46:59 +00004570 goto done;
ceriond5e38382005-02-11 13:38:15 +00004571 default:
cerionab9132d2005-02-15 15:46:59 +00004572 goto bad;
ceriond5e38382005-02-11 13:38:15 +00004573 }
4574 goto done;
4575 }
cerionb536af92005-02-10 15:03:19 +00004576
sewardje9d8a262009-07-01 08:06:34 +00004577 case Pin_StoreC: {
4578 if (i->Pin.StoreC.sz == 4) {
4579 p = mkFormX(p, 31, iregNo(i->Pin.StoreC.src, mode64),
carll1f5fe1f2014-08-07 23:25:23 +00004580 0, iregNo(i->Pin.StoreC.dst, mode64), 150, 1, endness_host);
sewardje9d8a262009-07-01 08:06:34 +00004581 goto done;
4582 }
4583 if (i->Pin.StoreC.sz == 8 && mode64) {
4584 p = mkFormX(p, 31, iregNo(i->Pin.StoreC.src, mode64),
carll1f5fe1f2014-08-07 23:25:23 +00004585 0, iregNo(i->Pin.StoreC.dst, mode64), 214, 1, endness_host);
sewardje9d8a262009-07-01 08:06:34 +00004586 goto done;
4587 }
4588 goto bad;
4589 }
4590
cerion094d1392005-06-20 13:45:57 +00004591 case Pin_FpUnary: {
4592 UInt fr_dst = fregNo(i->Pin.FpUnary.dst);
4593 UInt fr_src = fregNo(i->Pin.FpUnary.src);
4594 switch (i->Pin.FpUnary.op) {
sewardjbaf971a2006-01-27 15:09:35 +00004595 case Pfp_RSQRTE: // frsqrtre, PPC32 p424
carll1f5fe1f2014-08-07 23:25:23 +00004596 p = mkFormA( p, 63, fr_dst, 0, fr_src, 0, 26, 0, endness_host );
sewardjbaf971a2006-01-27 15:09:35 +00004597 break;
4598 case Pfp_RES: // fres, PPC32 p421
carll1f5fe1f2014-08-07 23:25:23 +00004599 p = mkFormA( p, 59, fr_dst, 0, fr_src, 0, 24, 0, endness_host );
sewardjbaf971a2006-01-27 15:09:35 +00004600 break;
cerion094d1392005-06-20 13:45:57 +00004601 case Pfp_SQRT: // fsqrt, PPC32 p427
carll1f5fe1f2014-08-07 23:25:23 +00004602 p = mkFormA( p, 63, fr_dst, 0, fr_src, 0, 22, 0, endness_host );
cerion094d1392005-06-20 13:45:57 +00004603 break;
4604 case Pfp_ABS: // fabs, PPC32 p399
carll1f5fe1f2014-08-07 23:25:23 +00004605 p = mkFormX(p, 63, fr_dst, 0, fr_src, 264, 0, endness_host);
cerion094d1392005-06-20 13:45:57 +00004606 break;
4607 case Pfp_NEG: // fneg, PPC32 p416
carll1f5fe1f2014-08-07 23:25:23 +00004608 p = mkFormX(p, 63, fr_dst, 0, fr_src, 40, 0, endness_host);
cerion094d1392005-06-20 13:45:57 +00004609 break;
4610 case Pfp_MOV: // fmr, PPC32 p410
carll1f5fe1f2014-08-07 23:25:23 +00004611 p = mkFormX(p, 63, fr_dst, 0, fr_src, 72, 0, endness_host);
cerion094d1392005-06-20 13:45:57 +00004612 break;
sewardj0f1ef862008-08-08 08:37:06 +00004613 case Pfp_FRIM: // frim, PPC ISA 2.05 p137
carll1f5fe1f2014-08-07 23:25:23 +00004614 p = mkFormX(p, 63, fr_dst, 0, fr_src, 488, 0, endness_host);
sewardj0f1ef862008-08-08 08:37:06 +00004615 break;
4616 case Pfp_FRIP: // frip, PPC ISA 2.05 p137
carll1f5fe1f2014-08-07 23:25:23 +00004617 p = mkFormX(p, 63, fr_dst, 0, fr_src, 456, 0, endness_host);
sewardj0f1ef862008-08-08 08:37:06 +00004618 break;
4619 case Pfp_FRIN: // frin, PPC ISA 2.05 p137
carll1f5fe1f2014-08-07 23:25:23 +00004620 p = mkFormX(p, 63, fr_dst, 0, fr_src, 392, 0, endness_host);
sewardj0f1ef862008-08-08 08:37:06 +00004621 break;
4622 case Pfp_FRIZ: // friz, PPC ISA 2.05 p137
carll1f5fe1f2014-08-07 23:25:23 +00004623 p = mkFormX(p, 63, fr_dst, 0, fr_src, 424, 0, endness_host);
sewardj0f1ef862008-08-08 08:37:06 +00004624 break;
cerion094d1392005-06-20 13:45:57 +00004625 default:
4626 goto bad;
4627 }
4628 goto done;
4629 }
4630
4631 case Pin_FpBinary: {
4632 UInt fr_dst = fregNo(i->Pin.FpBinary.dst);
4633 UInt fr_srcL = fregNo(i->Pin.FpBinary.srcL);
4634 UInt fr_srcR = fregNo(i->Pin.FpBinary.srcR);
4635 switch (i->Pin.FpBinary.op) {
sewardjb183b852006-02-03 16:08:03 +00004636 case Pfp_ADDD: // fadd, PPC32 p400
carll1f5fe1f2014-08-07 23:25:23 +00004637 p = mkFormA( p, 63, fr_dst, fr_srcL, fr_srcR, 0, 21, 0, endness_host );
cerion094d1392005-06-20 13:45:57 +00004638 break;
sewardjb183b852006-02-03 16:08:03 +00004639 case Pfp_ADDS: // fadds, PPC32 p401
carll1f5fe1f2014-08-07 23:25:23 +00004640 p = mkFormA( p, 59, fr_dst, fr_srcL, fr_srcR, 0, 21, 0, endness_host );
sewardjb183b852006-02-03 16:08:03 +00004641 break;
4642 case Pfp_SUBD: // fsub, PPC32 p429
carll1f5fe1f2014-08-07 23:25:23 +00004643 p = mkFormA( p, 63, fr_dst, fr_srcL, fr_srcR, 0, 20, 0, endness_host );
cerion094d1392005-06-20 13:45:57 +00004644 break;
sewardjb183b852006-02-03 16:08:03 +00004645 case Pfp_SUBS: // fsubs, PPC32 p430
carll1f5fe1f2014-08-07 23:25:23 +00004646 p = mkFormA( p, 59, fr_dst, fr_srcL, fr_srcR, 0, 20, 0, endness_host );
sewardjb183b852006-02-03 16:08:03 +00004647 break;
4648 case Pfp_MULD: // fmul, PPC32 p413
carll1f5fe1f2014-08-07 23:25:23 +00004649 p = mkFormA( p, 63, fr_dst, fr_srcL, 0, fr_srcR, 25, 0, endness_host );
cerion094d1392005-06-20 13:45:57 +00004650 break;
sewardjb183b852006-02-03 16:08:03 +00004651 case Pfp_MULS: // fmuls, PPC32 p414
carll1f5fe1f2014-08-07 23:25:23 +00004652 p = mkFormA( p, 59, fr_dst, fr_srcL, 0, fr_srcR, 25, 0, endness_host );
sewardjb183b852006-02-03 16:08:03 +00004653 break;
4654 case Pfp_DIVD: // fdiv, PPC32 p406
carll1f5fe1f2014-08-07 23:25:23 +00004655 p = mkFormA( p, 63, fr_dst, fr_srcL, fr_srcR, 0, 18, 0, endness_host );
cerion094d1392005-06-20 13:45:57 +00004656 break;
sewardjb183b852006-02-03 16:08:03 +00004657 case Pfp_DIVS: // fdivs, PPC32 p407
carll1f5fe1f2014-08-07 23:25:23 +00004658 p = mkFormA( p, 59, fr_dst, fr_srcL, fr_srcR, 0, 18, 0, endness_host );
sewardjb183b852006-02-03 16:08:03 +00004659 break;
cerion094d1392005-06-20 13:45:57 +00004660 default:
4661 goto bad;
4662 }
4663 goto done;
4664 }
4665
sewardj40c80262006-02-08 19:30:46 +00004666 case Pin_FpMulAcc: {
4667 UInt fr_dst = fregNo(i->Pin.FpMulAcc.dst);
4668 UInt fr_srcML = fregNo(i->Pin.FpMulAcc.srcML);
4669 UInt fr_srcMR = fregNo(i->Pin.FpMulAcc.srcMR);
4670 UInt fr_srcAcc = fregNo(i->Pin.FpMulAcc.srcAcc);
4671 switch (i->Pin.FpMulAcc.op) {
4672 case Pfp_MADDD: // fmadd, PPC32 p408
carll1f5fe1f2014-08-07 23:25:23 +00004673 p = mkFormA( p, 63, fr_dst, fr_srcML, fr_srcAcc, fr_srcMR, 29, 0,
4674 endness_host );
sewardj40c80262006-02-08 19:30:46 +00004675 break;
4676 case Pfp_MADDS: // fmadds, PPC32 p409
carll1f5fe1f2014-08-07 23:25:23 +00004677 p = mkFormA( p, 59, fr_dst, fr_srcML, fr_srcAcc, fr_srcMR, 29, 0,
4678 endness_host );
sewardj40c80262006-02-08 19:30:46 +00004679 break;
4680 case Pfp_MSUBD: // fmsub, PPC32 p411
carll1f5fe1f2014-08-07 23:25:23 +00004681 p = mkFormA( p, 63, fr_dst, fr_srcML, fr_srcAcc, fr_srcMR, 28, 0,
4682 endness_host );
sewardj40c80262006-02-08 19:30:46 +00004683 break;
4684 case Pfp_MSUBS: // fmsubs, PPC32 p412
carll1f5fe1f2014-08-07 23:25:23 +00004685 p = mkFormA( p, 59, fr_dst, fr_srcML, fr_srcAcc, fr_srcMR, 28, 0,
4686 endness_host );
sewardj40c80262006-02-08 19:30:46 +00004687 break;
4688 default:
4689 goto bad;
4690 }
4691 goto done;
4692 }
4693
cerion094d1392005-06-20 13:45:57 +00004694 case Pin_FpLdSt: {
cerion5b2325f2005-12-23 00:55:09 +00004695 PPCAMode* am_addr = i->Pin.FpLdSt.addr;
cerion094d1392005-06-20 13:45:57 +00004696 UInt f_reg = fregNo(i->Pin.FpLdSt.reg);
4697 Bool idxd = toBool(i->Pin.FpLdSt.addr->tag == Pam_RR);
4698 UChar sz = i->Pin.FpLdSt.sz;
cerionf0de28c2005-12-13 20:21:11 +00004699 UInt opc;
cerion094d1392005-06-20 13:45:57 +00004700 vassert(sz == 4 || sz == 8);
4701
4702 if (i->Pin.FpLdSt.isLoad) { // Load from memory
4703 if (idxd) { // lf[s|d]x, PPC32 p444|440
cerionf0de28c2005-12-13 20:21:11 +00004704 opc = (sz == 4) ? 535 : 599;
carll1f5fe1f2014-08-07 23:25:23 +00004705 p = doAMode_RR(p, 31, opc, f_reg, am_addr, mode64, endness_host);
cerion094d1392005-06-20 13:45:57 +00004706 } else { // lf[s|d], PPC32 p441|437
cerionf0de28c2005-12-13 20:21:11 +00004707 opc = (sz == 4) ? 48 : 50;
carll1f5fe1f2014-08-07 23:25:23 +00004708 p = doAMode_IR(p, opc, f_reg, am_addr, mode64, endness_host);
cerion094d1392005-06-20 13:45:57 +00004709 }
4710 } else { // Store to memory
4711 if (idxd) { // stf[s|d]x, PPC32 p521|516
cerionf0de28c2005-12-13 20:21:11 +00004712 opc = (sz == 4) ? 663 : 727;
carll1f5fe1f2014-08-07 23:25:23 +00004713 p = doAMode_RR(p, 31, opc, f_reg, am_addr, mode64, endness_host);
cerion094d1392005-06-20 13:45:57 +00004714 } else { // stf[s|d], PPC32 p518|513
cerionf0de28c2005-12-13 20:21:11 +00004715 opc = (sz == 4) ? 52 : 54;
carll1f5fe1f2014-08-07 23:25:23 +00004716 p = doAMode_IR(p, opc, f_reg, am_addr, mode64, endness_host);
cerion094d1392005-06-20 13:45:57 +00004717 }
4718 }
4719 goto done;
4720 }
4721
sewardj92923de2006-01-25 21:29:48 +00004722 case Pin_FpSTFIW: {
4723 UInt ir_addr = iregNo(i->Pin.FpSTFIW.addr, mode64);
4724 UInt fr_data = fregNo(i->Pin.FpSTFIW.data);
4725 // stfiwx (store fp64[lo32] as int32), PPC32 p517
4726 // Use rA==0, so that EA == rB == ir_addr
carll1f5fe1f2014-08-07 23:25:23 +00004727 p = mkFormX(p, 31, fr_data, 0/*rA=0*/, ir_addr, 983, 0, endness_host);
sewardj92923de2006-01-25 21:29:48 +00004728 goto done;
4729 }
4730
4731 case Pin_FpRSP: {
4732 UInt fr_dst = fregNo(i->Pin.FpRSP.dst);
4733 UInt fr_src = fregNo(i->Pin.FpRSP.src);
cerion094d1392005-06-20 13:45:57 +00004734 // frsp, PPC32 p423
carll1f5fe1f2014-08-07 23:25:23 +00004735 p = mkFormX(p, 63, fr_dst, 0, fr_src, 12, 0, endness_host);
cerion094d1392005-06-20 13:45:57 +00004736 goto done;
4737 }
4738
sewardj92923de2006-01-25 21:29:48 +00004739 case Pin_FpCftI: {
4740 UInt fr_dst = fregNo(i->Pin.FpCftI.dst);
4741 UInt fr_src = fregNo(i->Pin.FpCftI.src);
4742 if (i->Pin.FpCftI.fromI == False && i->Pin.FpCftI.int32 == True) {
sewardj4aa412a2011-07-24 14:13:21 +00004743 if (i->Pin.FpCftI.syned == True) {
4744 // fctiw (conv f64 to i32), PPC32 p404
carll1f5fe1f2014-08-07 23:25:23 +00004745 p = mkFormX(p, 63, fr_dst, 0, fr_src, 14, 0, endness_host);
sewardj4aa412a2011-07-24 14:13:21 +00004746 goto done;
4747 } else {
4748 // fctiwu (conv f64 to u32)
carll1f5fe1f2014-08-07 23:25:23 +00004749 p = mkFormX(p, 63, fr_dst, 0, fr_src, 142, 0, endness_host);
sewardj4aa412a2011-07-24 14:13:21 +00004750 goto done;
4751 }
sewardj92923de2006-01-25 21:29:48 +00004752 }
sewardj7fd5bb02006-01-26 02:24:17 +00004753 if (i->Pin.FpCftI.fromI == False && i->Pin.FpCftI.int32 == False) {
sewardj4aa412a2011-07-24 14:13:21 +00004754 if (i->Pin.FpCftI.syned == True) {
4755 // fctid (conv f64 to i64), PPC64 p437
carll1f5fe1f2014-08-07 23:25:23 +00004756 p = mkFormX(p, 63, fr_dst, 0, fr_src, 814, 0, endness_host);
sewardj4aa412a2011-07-24 14:13:21 +00004757 goto done;
4758 } else {
4759 // fctidu (conv f64 to u64)
carll1f5fe1f2014-08-07 23:25:23 +00004760 p = mkFormX(p, 63, fr_dst, 0, fr_src, 942, 0, endness_host);
sewardj4aa412a2011-07-24 14:13:21 +00004761 goto done;
4762 }
sewardj7fd5bb02006-01-26 02:24:17 +00004763 }
4764 if (i->Pin.FpCftI.fromI == True && i->Pin.FpCftI.int32 == False) {
sewardj66d5ef22011-04-15 11:55:00 +00004765 if (i->Pin.FpCftI.syned == True) {
4766 // fcfid (conv i64 to f64), PPC64 p434
carll1f5fe1f2014-08-07 23:25:23 +00004767 p = mkFormX(p, 63, fr_dst, 0, fr_src, 846, 0, endness_host);
sewardj66d5ef22011-04-15 11:55:00 +00004768 goto done;
sewardj7d810d72011-05-08 22:05:10 +00004769 } else if (i->Pin.FpCftI.flt64 == True) {
sewardj66d5ef22011-04-15 11:55:00 +00004770 // fcfidu (conv u64 to f64)
carll1f5fe1f2014-08-07 23:25:23 +00004771 p = mkFormX(p, 63, fr_dst, 0, fr_src, 974, 0, endness_host);
sewardj66d5ef22011-04-15 11:55:00 +00004772 goto done;
4773 } else {
4774 // fcfidus (conv u64 to f32)
carll1f5fe1f2014-08-07 23:25:23 +00004775 p = mkFormX(p, 59, fr_dst, 0, fr_src, 974, 0, endness_host);
sewardj66d5ef22011-04-15 11:55:00 +00004776 goto done;
4777 }
sewardj7fd5bb02006-01-26 02:24:17 +00004778 }
sewardj92923de2006-01-25 21:29:48 +00004779 goto bad;
cerion094d1392005-06-20 13:45:57 +00004780 }
4781
4782 case Pin_FpCMov: {
cerion5b2325f2005-12-23 00:55:09 +00004783 UInt fr_dst = fregNo(i->Pin.FpCMov.dst);
4784 UInt fr_src = fregNo(i->Pin.FpCMov.src);
4785 PPCCondCode cc = i->Pin.FpCMov.cond;
cerion094d1392005-06-20 13:45:57 +00004786
4787 if (fr_dst == fr_src) goto done;
4788
4789 vassert(cc.test != Pct_ALWAYS);
4790
4791 /* jmp fwds if !condition */
4792 if (cc.test != Pct_ALWAYS) {
4793 /* bc !ct,cf,n_bytes>>2 */
carll1f5fe1f2014-08-07 23:25:23 +00004794 p = mkFormB(p, invertCondTest(cc.test), cc.flag, 8>>2, 0, 0,
4795 endness_host);
cerion094d1392005-06-20 13:45:57 +00004796 }
4797
4798 // fmr, PPC32 p410
carll1f5fe1f2014-08-07 23:25:23 +00004799 p = mkFormX(p, 63, fr_dst, 0, fr_src, 72, 0, endness_host);
cerion094d1392005-06-20 13:45:57 +00004800 goto done;
4801 }
4802
4803 case Pin_FpLdFPSCR: {
4804 UInt fr_src = fregNo(i->Pin.FpLdFPSCR.src);
carll1f5fe1f2014-08-07 23:25:23 +00004805 p = mkFormXFL(p, 0xFF, fr_src, i->Pin.FpLdFPSCR.dfp_rm, endness_host); // mtfsf, PPC32 p480
cerion094d1392005-06-20 13:45:57 +00004806 goto done;
4807 }
4808
4809 case Pin_FpCmp: {
sewardjb51f0f42005-07-18 11:38:02 +00004810 UChar crfD = 1;
cerionf0de28c2005-12-13 20:21:11 +00004811 UInt r_dst = iregNo(i->Pin.FpCmp.dst, mode64);
sewardjb51f0f42005-07-18 11:38:02 +00004812 UInt fr_srcL = fregNo(i->Pin.FpCmp.srcL);
4813 UInt fr_srcR = fregNo(i->Pin.FpCmp.srcR);
cerion094d1392005-06-20 13:45:57 +00004814 vassert(crfD < 8);
4815 // fcmpo, PPC32 p402
carll1f5fe1f2014-08-07 23:25:23 +00004816 p = mkFormX(p, 63, crfD<<2, fr_srcL, fr_srcR, 32, 0, endness_host);
cerion094d1392005-06-20 13:45:57 +00004817
4818 // mfcr (mv CR to r_dst), PPC32 p467
carll1f5fe1f2014-08-07 23:25:23 +00004819 p = mkFormX(p, 31, r_dst, 0, 0, 19, 0, endness_host);
cerion094d1392005-06-20 13:45:57 +00004820
4821 // rlwinm r_dst,r_dst,8,28,31, PPC32 p501
sewardjb51f0f42005-07-18 11:38:02 +00004822 // => rotate field 1 to bottomw of word, masking out upper 28
carll1f5fe1f2014-08-07 23:25:23 +00004823 p = mkFormM(p, 21, r_dst, r_dst, 8, 28, 31, 0, endness_host);
cerion094d1392005-06-20 13:45:57 +00004824 goto done;
4825 }
cerionbcf8c3e2005-02-04 16:17:07 +00004826
cerion7f000af2005-02-22 20:36:49 +00004827 case Pin_RdWrLR: {
cerionf0de28c2005-12-13 20:21:11 +00004828 UInt reg = iregNo(i->Pin.RdWrLR.gpr, mode64);
cerion7f000af2005-02-22 20:36:49 +00004829 /* wrLR==True ? mtlr r4 : mflr r4 */
carll1f5fe1f2014-08-07 23:25:23 +00004830 p = mkFormXFX(p, reg, 8, (i->Pin.RdWrLR.wrLR==True) ? 467 : 339,
4831 endness_host);
cerion7f000af2005-02-22 20:36:49 +00004832 goto done;
4833 }
4834
cerionc3d8bdc2005-06-28 18:06:23 +00004835
4836 /* AltiVec */
4837 case Pin_AvLdSt: {
4838 UInt opc2, v_reg, r_idx, r_base;
4839 UChar sz = i->Pin.AvLdSt.sz;
4840 Bool idxd = toBool(i->Pin.AvLdSt.addr->tag == Pam_RR);
cerion225a0342005-09-12 20:49:09 +00004841 vassert(sz == 1 || sz == 2 || sz == 4 || sz == 16);
cerionc3d8bdc2005-06-28 18:06:23 +00004842
4843 v_reg = vregNo(i->Pin.AvLdSt.reg);
cerionf0de28c2005-12-13 20:21:11 +00004844 r_base = iregNo(i->Pin.AvLdSt.addr->Pam.RR.base, mode64);
cerionc3d8bdc2005-06-28 18:06:23 +00004845
4846 // Only have AltiVec AMode_RR: kludge AMode_IR
4847 if (!idxd) {
4848 r_idx = 30; // XXX: Using r30 as temp
cerion5b2325f2005-12-23 00:55:09 +00004849 p = mkLoadImm(p, r_idx,
carll1f5fe1f2014-08-07 23:25:23 +00004850 i->Pin.AvLdSt.addr->Pam.IR.index, mode64, endness_host);
cerionc3d8bdc2005-06-28 18:06:23 +00004851 } else {
cerionf0de28c2005-12-13 20:21:11 +00004852 r_idx = iregNo(i->Pin.AvLdSt.addr->Pam.RR.index, mode64);
cerionc3d8bdc2005-06-28 18:06:23 +00004853 }
4854
cerion225a0342005-09-12 20:49:09 +00004855 if (i->Pin.FpLdSt.isLoad) { // Load from memory (1,2,4,16)
cerion5b2325f2005-12-23 00:55:09 +00004856 opc2 = (sz==1) ? 7 : (sz==2) ? 39 : (sz==4) ? 71 : 103;
carll1f5fe1f2014-08-07 23:25:23 +00004857 p = mkFormX(p, 31, v_reg, r_idx, r_base, opc2, 0, endness_host);
cerion225a0342005-09-12 20:49:09 +00004858 } else { // Store to memory (1,2,4,16)
cerion5b2325f2005-12-23 00:55:09 +00004859 opc2 = (sz==1) ? 135 : (sz==2) ? 167 : (sz==4) ? 199 : 231;
carll1f5fe1f2014-08-07 23:25:23 +00004860 p = mkFormX(p, 31, v_reg, r_idx, r_base, opc2, 0, endness_host);
cerionc3d8bdc2005-06-28 18:06:23 +00004861 }
4862 goto done;
4863 }
4864
4865 case Pin_AvUnary: {
4866 UInt v_dst = vregNo(i->Pin.AvUnary.dst);
4867 UInt v_src = vregNo(i->Pin.AvUnary.src);
4868 UInt opc2;
4869 switch (i->Pin.AvUnary.op) {
4870 case Pav_MOV: opc2 = 1156; break; // vor vD,vS,vS
4871 case Pav_NOT: opc2 = 1284; break; // vnor vD,vS,vS
4872 case Pav_UNPCKH8S: opc2 = 526; break; // vupkhsb
4873 case Pav_UNPCKH16S: opc2 = 590; break; // vupkhsh
4874 case Pav_UNPCKL8S: opc2 = 654; break; // vupklsb
4875 case Pav_UNPCKL16S: opc2 = 718; break; // vupklsh
4876 case Pav_UNPCKHPIX: opc2 = 846; break; // vupkhpx
4877 case Pav_UNPCKLPIX: opc2 = 974; break; // vupklpx
carll7deaf952013-10-15 18:11:20 +00004878
4879 case Pav_ZEROCNTBYTE: opc2 = 1794; break; // vclzb
4880 case Pav_ZEROCNTHALF: opc2 = 1858; break; // vclzh
4881 case Pav_ZEROCNTWORD: opc2 = 1922; break; // vclzw
4882 case Pav_ZEROCNTDBL: opc2 = 1986; break; // vclzd
carll60c6bac2013-10-18 01:19:06 +00004883 case Pav_BITMTXXPOSE: opc2 = 1292; break; // vgbbd
cerionc3d8bdc2005-06-28 18:06:23 +00004884 default:
4885 goto bad;
4886 }
4887 switch (i->Pin.AvUnary.op) {
4888 case Pav_MOV:
4889 case Pav_NOT:
carll1f5fe1f2014-08-07 23:25:23 +00004890 p = mkFormVX( p, 4, v_dst, v_src, v_src, opc2, endness_host );
cerionc3d8bdc2005-06-28 18:06:23 +00004891 break;
4892 default:
carll1f5fe1f2014-08-07 23:25:23 +00004893 p = mkFormVX( p, 4, v_dst, 0, v_src, opc2, endness_host );
cerion8ea0d3e2005-11-14 00:44:47 +00004894 break;
cerionc3d8bdc2005-06-28 18:06:23 +00004895 }
4896 goto done;
4897 }
4898
4899 case Pin_AvBinary: {
4900 UInt v_dst = vregNo(i->Pin.AvBinary.dst);
4901 UInt v_srcL = vregNo(i->Pin.AvBinary.srcL);
4902 UInt v_srcR = vregNo(i->Pin.AvBinary.srcR);
4903 UInt opc2;
cerion27b3d7e2005-09-14 20:35:47 +00004904 if (i->Pin.AvBinary.op == Pav_SHL) {
carll1f5fe1f2014-08-07 23:25:23 +00004905 p = mkFormVX( p, 4, v_dst, v_srcL, v_srcR, 1036, endness_host ); // vslo
4906 p = mkFormVX( p, 4, v_dst, v_dst, v_srcR, 452, endness_host ); // vsl
cerion27b3d7e2005-09-14 20:35:47 +00004907 goto done;
4908 }
4909 if (i->Pin.AvBinary.op == Pav_SHR) {
carll1f5fe1f2014-08-07 23:25:23 +00004910 p = mkFormVX( p, 4, v_dst, v_srcL, v_srcR, 1100, endness_host ); // vsro
4911 p = mkFormVX( p, 4, v_dst, v_dst, v_srcR, 708, endness_host ); // vsr
cerion27b3d7e2005-09-14 20:35:47 +00004912 goto done;
4913 }
cerionc3d8bdc2005-06-28 18:06:23 +00004914 switch (i->Pin.AvBinary.op) {
4915 /* Bitwise */
cerion225a0342005-09-12 20:49:09 +00004916 case Pav_AND: opc2 = 1028; break; // vand
cerionc3d8bdc2005-06-28 18:06:23 +00004917 case Pav_OR: opc2 = 1156; break; // vor
cerion225a0342005-09-12 20:49:09 +00004918 case Pav_XOR: opc2 = 1220; break; // vxor
cerionc3d8bdc2005-06-28 18:06:23 +00004919 default:
4920 goto bad;
4921 }
carll1f5fe1f2014-08-07 23:25:23 +00004922 p = mkFormVX( p, 4, v_dst, v_srcL, v_srcR, opc2, endness_host );
cerionc3d8bdc2005-06-28 18:06:23 +00004923 goto done;
4924 }
4925
cerion6b6f59e2005-06-28 20:59:18 +00004926 case Pin_AvBin8x16: {
4927 UInt v_dst = vregNo(i->Pin.AvBin8x16.dst);
4928 UInt v_srcL = vregNo(i->Pin.AvBin8x16.srcL);
4929 UInt v_srcR = vregNo(i->Pin.AvBin8x16.srcR);
4930 UInt opc2;
4931 switch (i->Pin.AvBin8x16.op) {
4932
cerionf34ccc42005-09-16 08:55:50 +00004933 case Pav_ADDU: opc2 = 0; break; // vaddubm
4934 case Pav_QADDU: opc2 = 512; break; // vaddubs
4935 case Pav_QADDS: opc2 = 768; break; // vaddsbs
cerion6b6f59e2005-06-28 20:59:18 +00004936
cerionf34ccc42005-09-16 08:55:50 +00004937 case Pav_SUBU: opc2 = 1024; break; // vsububm
4938 case Pav_QSUBU: opc2 = 1536; break; // vsububs
4939 case Pav_QSUBS: opc2 = 1792; break; // vsubsbs
cerion6b6f59e2005-06-28 20:59:18 +00004940
cerion1ac656a2005-11-04 19:44:48 +00004941 case Pav_OMULU: opc2 = 8; break; // vmuloub
4942 case Pav_OMULS: opc2 = 264; break; // vmulosb
4943 case Pav_EMULU: opc2 = 520; break; // vmuleub
4944 case Pav_EMULS: opc2 = 776; break; // vmulesb
4945
cerion6b6f59e2005-06-28 20:59:18 +00004946 case Pav_AVGU: opc2 = 1026; break; // vavgub
4947 case Pav_AVGS: opc2 = 1282; break; // vavgsb
4948 case Pav_MAXU: opc2 = 2; break; // vmaxub
4949 case Pav_MAXS: opc2 = 258; break; // vmaxsb
4950 case Pav_MINU: opc2 = 514; break; // vminub
4951 case Pav_MINS: opc2 = 770; break; // vminsb
4952
4953 case Pav_CMPEQU: opc2 = 6; break; // vcmpequb
4954 case Pav_CMPGTU: opc2 = 518; break; // vcmpgtub
4955 case Pav_CMPGTS: opc2 = 774; break; // vcmpgtsb
4956
4957 case Pav_SHL: opc2 = 260; break; // vslb
4958 case Pav_SHR: opc2 = 516; break; // vsrb
4959 case Pav_SAR: opc2 = 772; break; // vsrab
4960 case Pav_ROTL: opc2 = 4; break; // vrlb
4961
4962 case Pav_MRGHI: opc2 = 12; break; // vmrghb
4963 case Pav_MRGLO: opc2 = 268; break; // vmrglb
4964
carll7deaf952013-10-15 18:11:20 +00004965 case Pav_POLYMULADD: opc2 = 1032; break; // vpmsumb
4966
cerion6b6f59e2005-06-28 20:59:18 +00004967 default:
4968 goto bad;
4969 }
carll1f5fe1f2014-08-07 23:25:23 +00004970 p = mkFormVX( p, 4, v_dst, v_srcL, v_srcR, opc2, endness_host );
cerion6b6f59e2005-06-28 20:59:18 +00004971 goto done;
4972 }
4973
4974 case Pin_AvBin16x8: {
4975 UInt v_dst = vregNo(i->Pin.AvBin16x8.dst);
4976 UInt v_srcL = vregNo(i->Pin.AvBin16x8.srcL);
4977 UInt v_srcR = vregNo(i->Pin.AvBin16x8.srcR);
4978 UInt opc2;
4979 switch (i->Pin.AvBin16x8.op) {
4980
cerionf34ccc42005-09-16 08:55:50 +00004981 case Pav_ADDU: opc2 = 64; break; // vadduhm
4982 case Pav_QADDU: opc2 = 576; break; // vadduhs
4983 case Pav_QADDS: opc2 = 832; break; // vaddshs
cerion6b6f59e2005-06-28 20:59:18 +00004984
cerionf34ccc42005-09-16 08:55:50 +00004985 case Pav_SUBU: opc2 = 1088; break; // vsubuhm
4986 case Pav_QSUBU: opc2 = 1600; break; // vsubuhs
4987 case Pav_QSUBS: opc2 = 1856; break; // vsubshs
cerion6b6f59e2005-06-28 20:59:18 +00004988
cerion1ac656a2005-11-04 19:44:48 +00004989 case Pav_OMULU: opc2 = 72; break; // vmulouh
4990 case Pav_OMULS: opc2 = 328; break; // vmulosh
4991 case Pav_EMULU: opc2 = 584; break; // vmuleuh
4992 case Pav_EMULS: opc2 = 840; break; // vmulesh
cerion6b6f59e2005-06-28 20:59:18 +00004993
4994 case Pav_AVGU: opc2 = 1090; break; // vavguh
4995 case Pav_AVGS: opc2 = 1346; break; // vavgsh
4996 case Pav_MAXU: opc2 = 66; break; // vmaxuh
4997 case Pav_MAXS: opc2 = 322; break; // vmaxsh
4998 case Pav_MINS: opc2 = 834; break; // vminsh
4999 case Pav_MINU: opc2 = 578; break; // vminuh
5000
5001 case Pav_CMPEQU: opc2 = 70; break; // vcmpequh
5002 case Pav_CMPGTU: opc2 = 582; break; // vcmpgtuh
5003 case Pav_CMPGTS: opc2 = 838; break; // vcmpgtsh
5004
5005 case Pav_SHL: opc2 = 324; break; // vslh
5006 case Pav_SHR: opc2 = 580; break; // vsrh
5007 case Pav_SAR: opc2 = 836; break; // vsrah
5008 case Pav_ROTL: opc2 = 68; break; // vrlh
5009
cerionf34ccc42005-09-16 08:55:50 +00005010 case Pav_PACKUU: opc2 = 14; break; // vpkuhum
5011 case Pav_QPACKUU: opc2 = 142; break; // vpkuhus
5012 case Pav_QPACKSU: opc2 = 270; break; // vpkshus
5013 case Pav_QPACKSS: opc2 = 398; break; // vpkshss
5014 case Pav_PACKPXL: opc2 = 782; break; // vpkpx
cerion6b6f59e2005-06-28 20:59:18 +00005015
5016 case Pav_MRGHI: opc2 = 76; break; // vmrghh
5017 case Pav_MRGLO: opc2 = 332; break; // vmrglh
5018
carll7deaf952013-10-15 18:11:20 +00005019 case Pav_POLYMULADD: opc2 = 1224; break; // vpmsumh
5020
cerion6b6f59e2005-06-28 20:59:18 +00005021 default:
5022 goto bad;
5023 }
carll1f5fe1f2014-08-07 23:25:23 +00005024 p = mkFormVX( p, 4, v_dst, v_srcL, v_srcR, opc2, endness_host );
cerion6b6f59e2005-06-28 20:59:18 +00005025 goto done;
5026 }
5027
5028 case Pin_AvBin32x4: {
5029 UInt v_dst = vregNo(i->Pin.AvBin32x4.dst);
5030 UInt v_srcL = vregNo(i->Pin.AvBin32x4.srcL);
5031 UInt v_srcR = vregNo(i->Pin.AvBin32x4.srcR);
5032 UInt opc2;
5033 switch (i->Pin.AvBin32x4.op) {
5034
cerionf34ccc42005-09-16 08:55:50 +00005035 case Pav_ADDU: opc2 = 128; break; // vadduwm
5036 case Pav_QADDU: opc2 = 640; break; // vadduws
5037 case Pav_QADDS: opc2 = 896; break; // vaddsws
cerion6b6f59e2005-06-28 20:59:18 +00005038
cerionf34ccc42005-09-16 08:55:50 +00005039 case Pav_SUBU: opc2 = 1152; break; // vsubuwm
5040 case Pav_QSUBU: opc2 = 1664; break; // vsubuws
5041 case Pav_QSUBS: opc2 = 1920; break; // vsubsws
cerion6b6f59e2005-06-28 20:59:18 +00005042
carll48ae46b2013-10-01 15:45:54 +00005043 case Pav_MULU: opc2 = 137; break; // vmuluwm
5044 case Pav_OMULU: opc2 = 136; break; // vmulouw
5045 case Pav_OMULS: opc2 = 392; break; // vmulosw
5046 case Pav_EMULU: opc2 = 648; break; // vmuleuw
5047 case Pav_EMULS: opc2 = 904; break; // vmulesw
5048
cerion6b6f59e2005-06-28 20:59:18 +00005049 case Pav_AVGU: opc2 = 1154; break; // vavguw
5050 case Pav_AVGS: opc2 = 1410; break; // vavgsw
5051
5052 case Pav_MAXU: opc2 = 130; break; // vmaxuw
5053 case Pav_MAXS: opc2 = 386; break; // vmaxsw
5054
5055 case Pav_MINS: opc2 = 898; break; // vminsw
5056 case Pav_MINU: opc2 = 642; break; // vminuw
5057
5058 case Pav_CMPEQU: opc2 = 134; break; // vcmpequw
5059 case Pav_CMPGTS: opc2 = 902; break; // vcmpgtsw
5060 case Pav_CMPGTU: opc2 = 646; break; // vcmpgtuw
5061
5062 case Pav_SHL: opc2 = 388; break; // vslw
5063 case Pav_SHR: opc2 = 644; break; // vsrw
5064 case Pav_SAR: opc2 = 900; break; // vsraw
5065 case Pav_ROTL: opc2 = 132; break; // vrlw
5066
cerionf34ccc42005-09-16 08:55:50 +00005067 case Pav_PACKUU: opc2 = 78; break; // vpkuwum
5068 case Pav_QPACKUU: opc2 = 206; break; // vpkuwus
5069 case Pav_QPACKSU: opc2 = 334; break; // vpkswus
5070 case Pav_QPACKSS: opc2 = 462; break; // vpkswss
cerion6b6f59e2005-06-28 20:59:18 +00005071
5072 case Pav_MRGHI: opc2 = 140; break; // vmrghw
5073 case Pav_MRGLO: opc2 = 396; break; // vmrglw
5074
carll48ae46b2013-10-01 15:45:54 +00005075 case Pav_CATODD: opc2 = 1676; break; // vmrgow
5076 case Pav_CATEVEN: opc2 = 1932; break; // vmrgew
5077
carll7deaf952013-10-15 18:11:20 +00005078 case Pav_POLYMULADD: opc2 = 1160; break; // vpmsumw
5079
cerion6b6f59e2005-06-28 20:59:18 +00005080 default:
5081 goto bad;
5082 }
carll1f5fe1f2014-08-07 23:25:23 +00005083 p = mkFormVX( p, 4, v_dst, v_srcL, v_srcR, opc2, endness_host );
cerion6b6f59e2005-06-28 20:59:18 +00005084 goto done;
5085 }
5086
carll0c74bb52013-08-12 18:01:40 +00005087 case Pin_AvBin64x2: {
5088 UInt v_dst = vregNo(i->Pin.AvBin64x2.dst);
5089 UInt v_srcL = vregNo(i->Pin.AvBin64x2.srcL);
5090 UInt v_srcR = vregNo(i->Pin.AvBin64x2.srcR);
5091 UInt opc2;
5092 switch (i->Pin.AvBin64x2.op) {
carll48ae46b2013-10-01 15:45:54 +00005093 case Pav_ADDU: opc2 = 192; break; // vaddudm vector double add
5094 case Pav_SUBU: opc2 = 1216; break; // vsubudm vector double add
5095 case Pav_MAXU: opc2 = 194; break; // vmaxud vector double max
5096 case Pav_MAXS: opc2 = 450; break; // vmaxsd vector double max
5097 case Pav_MINU: opc2 = 706; break; // vminud vector double min
5098 case Pav_MINS: opc2 = 962; break; // vminsd vector double min
5099 case Pav_CMPEQU: opc2 = 199; break; // vcmpequd vector double compare
5100 case Pav_CMPGTU: opc2 = 711; break; // vcmpgtud vector double compare
5101 case Pav_CMPGTS: opc2 = 967; break; // vcmpgtsd vector double compare
5102 case Pav_SHL: opc2 = 1476; break; // vsld
5103 case Pav_SHR: opc2 = 1732; break; // vsrd
5104 case Pav_SAR: opc2 = 964; break; // vsrad
5105 case Pav_ROTL: opc2 = 196; break; // vrld
5106 case Pav_PACKUU: opc2 = 1102; break; // vpkudum
5107 case Pav_QPACKUU: opc2 = 1230; break; // vpkudus, vpksdus (emulated)
5108 case Pav_QPACKSS: opc2 = 1486; break; // vpksdsm
5109 case Pav_MRGHI: opc2 = 1614; break; // vmrghw
5110 case Pav_MRGLO: opc2 = 1742; break; // vmrglw
carll7deaf952013-10-15 18:11:20 +00005111 case Pav_POLYMULADD: opc2 = 1096; break; // vpmsumd
carll48ae46b2013-10-01 15:45:54 +00005112 default:
5113 goto bad;
carll0c74bb52013-08-12 18:01:40 +00005114 }
carll1f5fe1f2014-08-07 23:25:23 +00005115 p = mkFormVX( p, 4, v_dst, v_srcL, v_srcR, opc2, endness_host );
carll0c74bb52013-08-12 18:01:40 +00005116 goto done;
5117 }
carll7deaf952013-10-15 18:11:20 +00005118 case Pin_AvCipherV128Unary: {
5119 UInt v_dst = vregNo(i->Pin.AvCipherV128Unary.dst);
5120 UInt v_src = vregNo(i->Pin.AvCipherV128Unary.src);
5121 UInt opc2;
5122 switch (i->Pin.AvCipherV128Unary.op) {
5123 case Pav_CIPHERSUBV128: opc2 = 1480; break; // vsbox
5124 default:
5125 goto bad;
5126 }
carll1f5fe1f2014-08-07 23:25:23 +00005127 p = mkFormVX( p, 4, v_dst, v_src, 0, opc2, endness_host );
carll7deaf952013-10-15 18:11:20 +00005128 goto done;
5129 }
5130 case Pin_AvCipherV128Binary: {
5131 UInt v_dst = vregNo(i->Pin.AvCipherV128Binary.dst);
5132 UInt v_srcL = vregNo(i->Pin.AvCipherV128Binary.srcL);
5133 UInt v_srcR = vregNo(i->Pin.AvCipherV128Binary.srcR);
5134 UInt opc2;
5135 switch (i->Pin.AvCipherV128Binary.op) {
5136 case Pav_CIPHERV128: opc2 = 1288; break; // vcipher
5137 case Pav_CIPHERLV128: opc2 = 1289; break; // vcipherlast
5138 case Pav_NCIPHERV128: opc2 = 1352; break; // vncipher
5139 case Pav_NCIPHERLV128: opc2 = 1353; break; // vncipherlast
5140 default:
5141 goto bad;
5142 }
carll1f5fe1f2014-08-07 23:25:23 +00005143 p = mkFormVX( p, 4, v_dst, v_srcL, v_srcR, opc2, endness_host );
carll7deaf952013-10-15 18:11:20 +00005144 goto done;
5145 }
5146 case Pin_AvHashV128Binary: {
5147 UInt v_dst = vregNo(i->Pin.AvHashV128Binary.dst);
5148 UInt v_src = vregNo(i->Pin.AvHashV128Binary.src);
5149 PPCRI* s_field = i->Pin.AvHashV128Binary.s_field;
5150 UInt opc2;
5151 switch (i->Pin.AvHashV128Binary.op) {
5152 case Pav_SHA256: opc2 = 1666; break; // vshasigmaw
5153 case Pav_SHA512: opc2 = 1730; break; // vshasigmad
5154 default:
5155 goto bad;
5156 }
carll1f5fe1f2014-08-07 23:25:23 +00005157 p = mkFormVX( p, 4, v_dst, v_src, s_field->Pri.Imm, opc2, endness_host );
carll7deaf952013-10-15 18:11:20 +00005158 goto done;
5159 }
5160 case Pin_AvBCDV128Trinary: {
5161 UInt v_dst = vregNo(i->Pin.AvBCDV128Trinary.dst);
5162 UInt v_src1 = vregNo(i->Pin.AvBCDV128Trinary.src1);
5163 UInt v_src2 = vregNo(i->Pin.AvBCDV128Trinary.src2);
5164 PPCRI* ps = i->Pin.AvBCDV128Trinary.ps;
5165 UInt opc2;
5166 switch (i->Pin.AvBCDV128Trinary.op) {
5167 case Pav_BCDAdd: opc2 = 1; break; // bcdadd
5168 case Pav_BCDSub: opc2 = 65; break; // bcdsub
5169 default:
5170 goto bad;
5171 }
5172 p = mkFormVXR( p, 4, v_dst, v_src1, v_src2,
carll1f5fe1f2014-08-07 23:25:23 +00005173 0x1, (ps->Pri.Imm << 9) | opc2, endness_host );
carll7deaf952013-10-15 18:11:20 +00005174 goto done;
5175 }
cerion6b6f59e2005-06-28 20:59:18 +00005176 case Pin_AvBin32Fx4: {
5177 UInt v_dst = vregNo(i->Pin.AvBin32Fx4.dst);
5178 UInt v_srcL = vregNo(i->Pin.AvBin32Fx4.srcL);
5179 UInt v_srcR = vregNo(i->Pin.AvBin32Fx4.srcR);
5180 switch (i->Pin.AvBin32Fx4.op) {
5181
cerion8ea0d3e2005-11-14 00:44:47 +00005182 case Pavfp_ADDF:
carll1f5fe1f2014-08-07 23:25:23 +00005183 p = mkFormVX( p, 4, v_dst, v_srcL, v_srcR, 10, endness_host ); // vaddfp
cerion6b6f59e2005-06-28 20:59:18 +00005184 break;
cerion8ea0d3e2005-11-14 00:44:47 +00005185 case Pavfp_SUBF:
carll1f5fe1f2014-08-07 23:25:23 +00005186 p = mkFormVX( p, 4, v_dst, v_srcL, v_srcR, 74, endness_host ); // vsubfp
cerion6b6f59e2005-06-28 20:59:18 +00005187 break;
cerion8ea0d3e2005-11-14 00:44:47 +00005188 case Pavfp_MAXF:
carll1f5fe1f2014-08-07 23:25:23 +00005189 p = mkFormVX( p, 4, v_dst, v_srcL, v_srcR, 1034, endness_host ); // vmaxfp
cerion6b6f59e2005-06-28 20:59:18 +00005190 break;
cerion8ea0d3e2005-11-14 00:44:47 +00005191 case Pavfp_MINF:
carll1f5fe1f2014-08-07 23:25:23 +00005192 p = mkFormVX( p, 4, v_dst, v_srcL, v_srcR, 1098, endness_host ); // vminfp
cerion6b6f59e2005-06-28 20:59:18 +00005193 break;
5194
cerion8ea0d3e2005-11-14 00:44:47 +00005195 case Pavfp_MULF: {
cerion6b6f59e2005-06-28 20:59:18 +00005196 /* Make a vmulfp from a vmaddfp:
5197 load -0.0 (0x8000_0000) to each 32-bit word of vB
5198 this makes the add a noop.
5199 */
sewardjf7745052005-12-16 01:06:42 +00005200 UInt vB = 29; // XXX: Using v29 for temp do not change
5201 // without also changing
cerion5b2325f2005-12-23 00:55:09 +00005202 // getRegUsage_PPCInstr
cerion8ea0d3e2005-11-14 00:44:47 +00005203 UInt konst = 0x1F;
cerion6b6f59e2005-06-28 20:59:18 +00005204
ceriond963eb42005-11-16 18:02:58 +00005205 // Better way to load -0.0 (0x80000000) ?
cerion6b6f59e2005-06-28 20:59:18 +00005206 // vspltisw vB,0x1F (0x1F => each word of vB)
carll1f5fe1f2014-08-07 23:25:23 +00005207 p = mkFormVX( p, 4, vB, konst, 0, 908, endness_host );
cerion6b6f59e2005-06-28 20:59:18 +00005208
cerion5b2325f2005-12-23 00:55:09 +00005209 // vslw vB,vB,vB (each word of vB = (0x1F << 0x1F) = 0x80000000
carll1f5fe1f2014-08-07 23:25:23 +00005210 p = mkFormVX( p, 4, vB, vB, vB, 388, endness_host );
cerion6b6f59e2005-06-28 20:59:18 +00005211
5212 // Finally, do the multiply:
carll1f5fe1f2014-08-07 23:25:23 +00005213 p = mkFormVA( p, 4, v_dst, v_srcL, vB, v_srcR, 46, endness_host );
cerion36991ef2005-09-15 12:42:16 +00005214 break;
cerion6b6f59e2005-06-28 20:59:18 +00005215 }
cerion5b2325f2005-12-23 00:55:09 +00005216 case Pavfp_CMPEQF: // vcmpeqfp
carll1f5fe1f2014-08-07 23:25:23 +00005217 p = mkFormVXR( p, 4, v_dst, v_srcL, v_srcR, 0, 198, endness_host);
cerion36991ef2005-09-15 12:42:16 +00005218 break;
cerion5b2325f2005-12-23 00:55:09 +00005219 case Pavfp_CMPGTF: // vcmpgtfp
carll1f5fe1f2014-08-07 23:25:23 +00005220 p = mkFormVXR( p, 4, v_dst, v_srcL, v_srcR, 0, 710, endness_host );
cerion36991ef2005-09-15 12:42:16 +00005221 break;
cerion5b2325f2005-12-23 00:55:09 +00005222 case Pavfp_CMPGEF: // vcmpgefp
carll1f5fe1f2014-08-07 23:25:23 +00005223 p = mkFormVXR( p, 4, v_dst, v_srcL, v_srcR, 0, 454, endness_host );
cerion36991ef2005-09-15 12:42:16 +00005224 break;
cerion6b6f59e2005-06-28 20:59:18 +00005225
5226 default:
5227 goto bad;
5228 }
5229 goto done;
5230 }
5231
cerion8ea0d3e2005-11-14 00:44:47 +00005232 case Pin_AvUn32Fx4: {
5233 UInt v_dst = vregNo(i->Pin.AvUn32Fx4.dst);
5234 UInt v_src = vregNo(i->Pin.AvUn32Fx4.src);
5235 UInt opc2;
5236 switch (i->Pin.AvUn32Fx4.op) {
ceriond963eb42005-11-16 18:02:58 +00005237 case Pavfp_RCPF: opc2 = 266; break; // vrefp
5238 case Pavfp_RSQRTF: opc2 = 330; break; // vrsqrtefp
5239 case Pavfp_CVTU2F: opc2 = 778; break; // vcfux
5240 case Pavfp_CVTS2F: opc2 = 842; break; // vcfsx
5241 case Pavfp_QCVTF2U: opc2 = 906; break; // vctuxs
5242 case Pavfp_QCVTF2S: opc2 = 970; break; // vctsxs
5243 case Pavfp_ROUNDM: opc2 = 714; break; // vrfim
5244 case Pavfp_ROUNDP: opc2 = 650; break; // vrfip
5245 case Pavfp_ROUNDN: opc2 = 522; break; // vrfin
5246 case Pavfp_ROUNDZ: opc2 = 586; break; // vrfiz
cerion8ea0d3e2005-11-14 00:44:47 +00005247 default:
5248 goto bad;
5249 }
carll1f5fe1f2014-08-07 23:25:23 +00005250 p = mkFormVX( p, 4, v_dst, 0, v_src, opc2, endness_host );
cerion8ea0d3e2005-11-14 00:44:47 +00005251 goto done;
5252 }
5253
cerionc3d8bdc2005-06-28 18:06:23 +00005254 case Pin_AvPerm: { // vperm
cerionc3d8bdc2005-06-28 18:06:23 +00005255 UInt v_dst = vregNo(i->Pin.AvPerm.dst);
5256 UInt v_srcL = vregNo(i->Pin.AvPerm.srcL);
5257 UInt v_srcR = vregNo(i->Pin.AvPerm.srcR);
cerion92d9d872005-09-15 21:58:50 +00005258 UInt v_ctl = vregNo(i->Pin.AvPerm.ctl);
carll1f5fe1f2014-08-07 23:25:23 +00005259 p = mkFormVA( p, 4, v_dst, v_srcL, v_srcR, v_ctl, 43, endness_host );
cerionc3d8bdc2005-06-28 18:06:23 +00005260 goto done;
5261 }
5262
5263 case Pin_AvSel: { // vsel
5264 UInt v_ctl = vregNo(i->Pin.AvSel.ctl);
5265 UInt v_dst = vregNo(i->Pin.AvSel.dst);
5266 UInt v_srcL = vregNo(i->Pin.AvSel.srcL);
5267 UInt v_srcR = vregNo(i->Pin.AvSel.srcR);
carll1f5fe1f2014-08-07 23:25:23 +00005268 p = mkFormVA( p, 4, v_dst, v_srcL, v_srcR, v_ctl, 42, endness_host );
cerionc3d8bdc2005-06-28 18:06:23 +00005269 goto done;
5270 }
5271
carll9877fe52014-10-07 17:49:14 +00005272 case Pin_AvSh: { // vsl or vsr
5273 UInt v_dst = vregNo(i->Pin.AvSh.dst);
5274 Bool idxd = toBool(i->Pin.AvSh.addr->tag == Pam_RR);
5275 UInt r_idx, r_base;
5276
5277 r_base = iregNo(i->Pin.AvSh.addr->Pam.RR.base, mode64);
5278
5279 if (!idxd) {
carll99de41e2014-10-07 18:20:39 +00005280 r_idx = 30; // XXX: Using r30 as temp
carll9877fe52014-10-07 17:49:14 +00005281 p = mkLoadImm(p, r_idx,
5282 i->Pin.AvSh.addr->Pam.IR.index, mode64, endness_host);
5283 } else {
5284 r_idx = iregNo(i->Pin.AvSh.addr->Pam.RR.index, mode64);
5285 }
5286
5287 if (i->Pin.AvSh.shLeft)
5288 //vsl VRT,RA,RB
5289 p = mkFormVXI( p, 31, v_dst, r_idx, r_base, 6, endness_host );
5290 else
5291 //vsr VRT,RA,RB
5292 p = mkFormVXI( p, 31, v_dst, r_idx, r_base, 38, endness_host );
5293 goto done;
5294 }
5295
cerionc3d8bdc2005-06-28 18:06:23 +00005296 case Pin_AvShlDbl: { // vsldoi
5297 UInt shift = i->Pin.AvShlDbl.shift;
5298 UInt v_dst = vregNo(i->Pin.AvShlDbl.dst);
5299 UInt v_srcL = vregNo(i->Pin.AvShlDbl.srcL);
5300 UInt v_srcR = vregNo(i->Pin.AvShlDbl.srcR);
5301 vassert(shift <= 0xF);
carll1f5fe1f2014-08-07 23:25:23 +00005302 p = mkFormVA( p, 4, v_dst, v_srcL, v_srcR, shift, 44, endness_host );
cerionc3d8bdc2005-06-28 18:06:23 +00005303 goto done;
5304 }
5305
5306 case Pin_AvSplat: { // vsplt(is)(b,h,w)
5307 UInt v_dst = vregNo(i->Pin.AvShlDbl.dst);
5308 UChar sz = i->Pin.AvSplat.sz;
cerion27b3d7e2005-09-14 20:35:47 +00005309 UInt v_src, opc2;
cerionc3d8bdc2005-06-28 18:06:23 +00005310 vassert(sz == 8 || sz == 16 || sz == 32);
5311
cerion27b3d7e2005-09-14 20:35:47 +00005312 if (i->Pin.AvSplat.src->tag == Pvi_Imm) {
sewardj197bd172005-10-12 11:34:33 +00005313 Char simm5;
cerion6b6f59e2005-06-28 20:59:18 +00005314 opc2 = (sz == 8) ? 780 : (sz == 16) ? 844 : 908; // 8,16,32
cerion27b3d7e2005-09-14 20:35:47 +00005315 /* expects 5-bit-signed-imm */
sewardj197bd172005-10-12 11:34:33 +00005316 simm5 = i->Pin.AvSplat.src->Pvi.Imm5s;
cerion27b3d7e2005-09-14 20:35:47 +00005317 vassert(simm5 >= -16 && simm5 <= 15);
ceriond3e52412005-09-14 21:15:40 +00005318 simm5 = simm5 & 0x1F;
carll1f5fe1f2014-08-07 23:25:23 +00005319 p = mkFormVX( p, 4, v_dst, (UInt)simm5, 0, opc2, endness_host );
cerion27b3d7e2005-09-14 20:35:47 +00005320 }
5321 else { // Pri_Reg
sewardj197bd172005-10-12 11:34:33 +00005322 UInt lowest_lane;
cerionc3d8bdc2005-06-28 18:06:23 +00005323 opc2 = (sz == 8) ? 524 : (sz == 16) ? 588 : 652; // 8,16,32
cerion27b3d7e2005-09-14 20:35:47 +00005324 vassert(hregClass(i->Pin.AvSplat.src->Pvi.Reg) == HRcVec128);
5325 v_src = vregNo(i->Pin.AvSplat.src->Pvi.Reg);
sewardj197bd172005-10-12 11:34:33 +00005326 lowest_lane = (128/sz)-1;
carll1f5fe1f2014-08-07 23:25:23 +00005327 p = mkFormVX( p, 4, v_dst, lowest_lane, v_src, opc2, endness_host );
cerionc3d8bdc2005-06-28 18:06:23 +00005328 }
5329 goto done;
5330 }
5331
cerion6b6f59e2005-06-28 20:59:18 +00005332 case Pin_AvCMov: {
cerion5b2325f2005-12-23 00:55:09 +00005333 UInt v_dst = vregNo(i->Pin.AvCMov.dst);
5334 UInt v_src = vregNo(i->Pin.AvCMov.src);
5335 PPCCondCode cc = i->Pin.AvCMov.cond;
cerion6b6f59e2005-06-28 20:59:18 +00005336
5337 if (v_dst == v_src) goto done;
5338
5339 vassert(cc.test != Pct_ALWAYS);
5340
5341 /* jmp fwds 2 insns if !condition */
5342 if (cc.test != Pct_ALWAYS) {
5343 /* bc !ct,cf,n_bytes>>2 */
carll1f5fe1f2014-08-07 23:25:23 +00005344 p = mkFormB(p, invertCondTest(cc.test), cc.flag, 8>>2, 0, 0,
5345 endness_host);
cerion6b6f59e2005-06-28 20:59:18 +00005346 }
5347 /* vmr */
carll1f5fe1f2014-08-07 23:25:23 +00005348 p = mkFormVX( p, 4, v_dst, v_src, v_src, 1156, endness_host );
cerion6b6f59e2005-06-28 20:59:18 +00005349 goto done;
5350 }
5351
cerionc3d8bdc2005-06-28 18:06:23 +00005352 case Pin_AvLdVSCR: { // mtvscr
5353 UInt v_src = vregNo(i->Pin.AvLdVSCR.src);
carll1f5fe1f2014-08-07 23:25:23 +00005354 p = mkFormVX( p, 4, 0, 0, v_src, 1604, endness_host );
cerionc3d8bdc2005-06-28 18:06:23 +00005355 goto done;
5356 }
5357
sewardjc6bbd472012-04-02 10:20:48 +00005358 case Pin_Dfp64Unary: {
5359 UInt fr_dst = fregNo( i->Pin.FpUnary.dst );
5360 UInt fr_src = fregNo( i->Pin.FpUnary.src );
5361
5362 switch (i->Pin.Dfp64Unary.op) {
5363 case Pfp_MOV: // fmr, PPC32 p410
carll1f5fe1f2014-08-07 23:25:23 +00005364 p = mkFormX( p, 63, fr_dst, 0, fr_src, 72, 0, endness_host );
sewardjc6bbd472012-04-02 10:20:48 +00005365 break;
sewardj26217b02012-04-12 17:19:48 +00005366 case Pfp_DCTDP: // D32 to D64
carll1f5fe1f2014-08-07 23:25:23 +00005367 p = mkFormX( p, 59, fr_dst, 0, fr_src, 258, 0, endness_host );
sewardj26217b02012-04-12 17:19:48 +00005368 break;
5369 case Pfp_DRSP: // D64 to D32
carll1f5fe1f2014-08-07 23:25:23 +00005370 p = mkFormX( p, 59, fr_dst, 0, fr_src, 770, 0, endness_host );
sewardj26217b02012-04-12 17:19:48 +00005371 break;
5372 case Pfp_DCFFIX: // I64 to D64 conversion
5373 /* ONLY WORKS ON POWER7 */
carll1f5fe1f2014-08-07 23:25:23 +00005374 p = mkFormX( p, 59, fr_dst, 0, fr_src, 802, 0, endness_host );
sewardj26217b02012-04-12 17:19:48 +00005375 break;
5376 case Pfp_DCTFIX: // D64 to I64 conversion
carll1f5fe1f2014-08-07 23:25:23 +00005377 p = mkFormX( p, 59, fr_dst, 0, fr_src, 290, 0, endness_host );
sewardj26217b02012-04-12 17:19:48 +00005378 break;
sewardjcdc376d2012-04-23 11:21:12 +00005379 case Pfp_DXEX: // Extract exponent
carll1f5fe1f2014-08-07 23:25:23 +00005380 p = mkFormX( p, 59, fr_dst, 0, fr_src, 354, 0, endness_host );
sewardjcdc376d2012-04-23 11:21:12 +00005381 break;
sewardjc6bbd472012-04-02 10:20:48 +00005382 default:
5383 goto bad;
5384 }
5385 goto done;
5386 }
5387
5388 case Pin_Dfp64Binary: {
5389 UInt fr_dst = fregNo( i->Pin.Dfp64Binary.dst );
5390 UInt fr_srcL = fregNo( i->Pin.Dfp64Binary.srcL );
5391 UInt fr_srcR = fregNo( i->Pin.Dfp64Binary.srcR );
5392 switch (i->Pin.Dfp64Binary.op) {
5393 case Pfp_DFPADD: /* dadd, dfp add, use default RM from reg ignore mode
5394 * from the Iop instruction. */
carll1f5fe1f2014-08-07 23:25:23 +00005395 p = mkFormX( p, 59, fr_dst, fr_srcL, fr_srcR, 2, 0, endness_host );
sewardjc6bbd472012-04-02 10:20:48 +00005396 break;
5397 case Pfp_DFPSUB: /* dsub, dfp subtract, use default RM from reg ignore
5398 * mode from the Iop instruction. */
carll1f5fe1f2014-08-07 23:25:23 +00005399 p = mkFormX( p, 59, fr_dst, fr_srcL, fr_srcR, 514, 0, endness_host );
sewardjc6bbd472012-04-02 10:20:48 +00005400 break;
5401 case Pfp_DFPMUL: /* dmul, dfp multipy, use default RM from reg ignore
5402 * mode from the Iop instruction. */
carll1f5fe1f2014-08-07 23:25:23 +00005403 p = mkFormX( p, 59, fr_dst, fr_srcL, fr_srcR, 34, 0, endness_host );
sewardjc6bbd472012-04-02 10:20:48 +00005404 break;
5405 case Pfp_DFPDIV: /* ddiv, dfp divide, use default RM from reg ignore
5406 * mode from the Iop instruction. */
carll1f5fe1f2014-08-07 23:25:23 +00005407 p = mkFormX( p, 59, fr_dst, fr_srcL, fr_srcR, 546, 0, endness_host );
sewardjc6bbd472012-04-02 10:20:48 +00005408 break;
sewardjcdc376d2012-04-23 11:21:12 +00005409 case Pfp_DIEX: /* diex, insert exponent */
carll1f5fe1f2014-08-07 23:25:23 +00005410 p = mkFormX( p, 59, fr_dst, fr_srcL, fr_srcR, 866, 0, endness_host );
sewardjcdc376d2012-04-23 11:21:12 +00005411 break;
sewardjc6bbd472012-04-02 10:20:48 +00005412 default:
5413 goto bad;
5414 }
5415 goto done;
5416 }
5417
sewardj26217b02012-04-12 17:19:48 +00005418 case Pin_DfpShift: {
5419 UInt fr_src = fregNo(i->Pin.DfpShift.src);
5420 UInt fr_dst = fregNo(i->Pin.DfpShift.dst);
5421 UInt shift;
5422
5423 shift = i->Pin.DfpShift.shift->Pri.Imm;
5424
5425 switch (i->Pin.DfpShift.op) {
5426 case Pfp_DSCLI: /* dscli, DFP shift left by fr_srcR */
carll1f5fe1f2014-08-07 23:25:23 +00005427 p = mkFormZ22( p, 59, fr_dst, fr_src, shift, 66, 0, endness_host );
sewardj26217b02012-04-12 17:19:48 +00005428 break;
5429 case Pfp_DSCRI: /* dscri, DFP shift right by fr_srcR */
carll1f5fe1f2014-08-07 23:25:23 +00005430 p = mkFormZ22( p, 59, fr_dst, fr_src, shift, 98, 0, endness_host );
sewardj26217b02012-04-12 17:19:48 +00005431 break;
5432 default:
5433 vex_printf("ERROR: emit_PPCInstr default case\n");
5434 goto bad;
5435 }
5436 goto done;
5437 }
5438
sewardjcdc376d2012-04-23 11:21:12 +00005439 case Pin_ExtractExpD128: {
5440 UInt fr_dst = fregNo(i->Pin.ExtractExpD128.dst);
5441 UInt fr_srcHi = fregNo(i->Pin.ExtractExpD128.src_hi);
5442 UInt fr_srcLo = fregNo(i->Pin.ExtractExpD128.src_lo);
5443
5444 switch (i->Pin.ExtractExpD128.op) {
5445 case Pfp_DXEXQ:
5446 /* Setup the upper and lower registers of the source operand
5447 * register pair.
5448 */
carll1f5fe1f2014-08-07 23:25:23 +00005449 p = mkFormX( p, 63, 12, 0, fr_srcHi, 72, 0, endness_host );
5450 p = mkFormX( p, 63, 13, 0, fr_srcLo, 72, 0, endness_host );
5451 p = mkFormX( p, 63, 10, 0, 12, 354, 0, endness_host );
sewardjcdc376d2012-04-23 11:21:12 +00005452
5453 /* The instruction will put the 64-bit result in
5454 * register 10.
5455 */
carll1f5fe1f2014-08-07 23:25:23 +00005456 p = mkFormX(p, 63, fr_dst, 0, 10, 72, 0, endness_host);
sewardjcdc376d2012-04-23 11:21:12 +00005457 break;
5458 default:
5459 vex_printf("Error: emit_PPCInstr case Pin_DfpExtractExp, case inst Default\n");
5460 goto bad;
5461 }
5462 goto done;
5463 }
sewardj26217b02012-04-12 17:19:48 +00005464 case Pin_Dfp128Unary: {
5465 UInt fr_dstHi = fregNo(i->Pin.Dfp128Unary.dst_hi);
5466 UInt fr_dstLo = fregNo(i->Pin.Dfp128Unary.dst_lo);
5467 UInt fr_srcLo = fregNo(i->Pin.Dfp128Unary.src_lo);
5468
5469 /* Do instruction with 128-bit source operands in registers (10,11)
5470 * and (12,13).
5471 */
5472 switch (i->Pin.Dfp128Unary.op) {
5473 case Pfp_DCTQPQ: // D64 to D128, srcLo holds 64 bit operand
carll1f5fe1f2014-08-07 23:25:23 +00005474 p = mkFormX( p, 63, 12, 0, fr_srcLo, 72, 0, endness_host );
sewardj26217b02012-04-12 17:19:48 +00005475
carll1f5fe1f2014-08-07 23:25:23 +00005476 p = mkFormX( p, 63, 10, 0, 12, 258, 0, endness_host );
sewardj26217b02012-04-12 17:19:48 +00005477
5478 /* The instruction will put the 128-bit result in
5479 * registers (10,11). Note, the operand in the instruction only
5480 * reference the first of the two registers in the pair.
5481 */
carll1f5fe1f2014-08-07 23:25:23 +00005482 p = mkFormX(p, 63, fr_dstHi, 0, 10, 72, 0, endness_host);
5483 p = mkFormX(p, 63, fr_dstLo, 0, 11, 72, 0, endness_host);
sewardj26217b02012-04-12 17:19:48 +00005484 break;
5485 default:
5486 vex_printf("Error: emit_PPCInstr case Pin_Dfp128Unary, case inst Default\
5487\n");
5488 goto bad;
5489 }
5490 goto done;
5491 }
5492
sewardjc6bbd472012-04-02 10:20:48 +00005493 case Pin_Dfp128Binary: {
5494 /* dst is used to supply the left source operand and return
5495 * the result.
5496 */
5497 UInt fr_dstHi = fregNo( i->Pin.Dfp128Binary.dst_hi );
5498 UInt fr_dstLo = fregNo( i->Pin.Dfp128Binary.dst_lo );
5499 UInt fr_srcRHi = fregNo( i->Pin.Dfp128Binary.srcR_hi );
5500 UInt fr_srcRLo = fregNo( i->Pin.Dfp128Binary.srcR_lo );
5501
5502 /* Setup the upper and lower registers of the source operand
5503 * register pair.
5504 */
carll1f5fe1f2014-08-07 23:25:23 +00005505 p = mkFormX( p, 63, 10, 0, fr_dstHi, 72, 0, endness_host );
5506 p = mkFormX( p, 63, 11, 0, fr_dstLo, 72, 0, endness_host );
5507 p = mkFormX( p, 63, 12, 0, fr_srcRHi, 72, 0, endness_host );
5508 p = mkFormX( p, 63, 13, 0, fr_srcRLo, 72, 0, endness_host );
sewardjc6bbd472012-04-02 10:20:48 +00005509
5510 /* Do instruction with 128-bit source operands in registers (10,11)
5511 * and (12,13).
5512 */
5513 switch (i->Pin.Dfp128Binary.op) {
5514 case Pfp_DFPADDQ:
carll1f5fe1f2014-08-07 23:25:23 +00005515 p = mkFormX( p, 63, 10, 10, 12, 2, 0, endness_host );
sewardjc6bbd472012-04-02 10:20:48 +00005516 break;
5517 case Pfp_DFPSUBQ:
carll1f5fe1f2014-08-07 23:25:23 +00005518 p = mkFormX( p, 63, 10, 10, 12, 514, 0, endness_host );
sewardjc6bbd472012-04-02 10:20:48 +00005519 break;
5520 case Pfp_DFPMULQ:
carll1f5fe1f2014-08-07 23:25:23 +00005521 p = mkFormX( p, 63, 10, 10, 12, 34, 0, endness_host );
sewardjc6bbd472012-04-02 10:20:48 +00005522 break;
5523 case Pfp_DFPDIVQ:
carll1f5fe1f2014-08-07 23:25:23 +00005524 p = mkFormX( p, 63, 10, 10, 12, 546, 0, endness_host );
sewardjc6bbd472012-04-02 10:20:48 +00005525 break;
5526 default:
5527 goto bad;
5528 }
5529
5530 /* The instruction will put the 128-bit result in
5531 * registers (10,11). Note, the operand in the instruction only
5532 * reference the first of the two registers in the pair.
5533 */
carll1f5fe1f2014-08-07 23:25:23 +00005534 p = mkFormX(p, 63, fr_dstHi, 0, 10, 72, 0, endness_host);
5535 p = mkFormX(p, 63, fr_dstLo, 0, 11, 72, 0, endness_host);
sewardjc6bbd472012-04-02 10:20:48 +00005536 goto done;
5537 }
5538
sewardj26217b02012-04-12 17:19:48 +00005539 case Pin_DfpShift128: {
5540 UInt fr_src_hi = fregNo(i->Pin.DfpShift128.src_hi);
5541 UInt fr_src_lo = fregNo(i->Pin.DfpShift128.src_lo);
5542 UInt fr_dst_hi = fregNo(i->Pin.DfpShift128.dst_hi);
5543 UInt fr_dst_lo = fregNo(i->Pin.DfpShift128.dst_lo);
5544 UInt shift;
5545
5546 shift = i->Pin.DfpShift128.shift->Pri.Imm;
5547
5548 /* setup source operand in register 12, 13 pair */
carll1f5fe1f2014-08-07 23:25:23 +00005549 p = mkFormX(p, 63, 12, 0, fr_src_hi, 72, 0, endness_host);
5550 p = mkFormX(p, 63, 13, 0, fr_src_lo, 72, 0, endness_host);
sewardj26217b02012-04-12 17:19:48 +00005551
5552 /* execute instruction putting result in register 10, 11 pair */
5553 switch (i->Pin.DfpShift128.op) {
5554 case Pfp_DSCLIQ: /* dscliq, DFP shift left, fr_srcR is the integer
5555 * shift amount.
5556 */
carll1f5fe1f2014-08-07 23:25:23 +00005557 p = mkFormZ22( p, 63, 10, 12, shift, 66, 0, endness_host );
sewardj26217b02012-04-12 17:19:48 +00005558 break;
5559 case Pfp_DSCRIQ: /* dscriq, DFP shift right, fr_srcR is the integer
5560 * shift amount.
5561 */
carll1f5fe1f2014-08-07 23:25:23 +00005562 p = mkFormZ22( p, 63, 10, 12, shift, 98, 0, endness_host );
sewardj26217b02012-04-12 17:19:48 +00005563 break;
5564 default:
5565 vex_printf("ERROR: emit_PPCInstr quad default case %d \n",
5566 i->Pin.DfpShift128.op);
5567 goto bad;
5568 }
5569
5570 /* The instruction put the 128-bit result in registers (10,11).
5571 * Note, the operand in the instruction only reference the first of
5572 * the two registers in the pair.
5573 */
carll1f5fe1f2014-08-07 23:25:23 +00005574 p = mkFormX(p, 63, fr_dst_hi, 0, 10, 72, 0, endness_host);
5575 p = mkFormX(p, 63, fr_dst_lo, 0, 11, 72, 0, endness_host);
sewardj26217b02012-04-12 17:19:48 +00005576 goto done;
5577 }
5578
sewardjcdc376d2012-04-23 11:21:12 +00005579 case Pin_DfpRound: {
5580 UInt fr_dst = fregNo(i->Pin.DfpRound.dst);
5581 UInt fr_src = fregNo(i->Pin.DfpRound.src);
5582 UInt r_rmc, r, rmc;
5583
5584 r_rmc = i->Pin.DfpRound.r_rmc->Pri.Imm;
5585 r = (r_rmc & 0x8) >> 3;
5586 rmc = r_rmc & 0x3;
5587
5588 // drintx
carll1f5fe1f2014-08-07 23:25:23 +00005589 p = mkFormZ23(p, 59, fr_dst, r, fr_src, rmc, 99, 0, endness_host);
sewardjcdc376d2012-04-23 11:21:12 +00005590 goto done;
5591 }
5592
5593 case Pin_DfpRound128: {
5594 UInt fr_dstHi = fregNo(i->Pin.DfpRound128.dst_hi);
5595 UInt fr_dstLo = fregNo(i->Pin.DfpRound128.dst_lo);
5596 UInt fr_srcHi = fregNo(i->Pin.DfpRound128.src_hi);
5597 UInt fr_srcLo = fregNo(i->Pin.DfpRound128.src_lo);
5598 UInt r_rmc, r, rmc;
5599
5600 r_rmc = i->Pin.DfpRound128.r_rmc->Pri.Imm;
5601 r = (r_rmc & 0x8) >> 3;
5602 rmc = r_rmc & 0x3;
5603
5604 /* Setup the upper and lower registers of the source operand
5605 * register pair.
5606 */
carll1f5fe1f2014-08-07 23:25:23 +00005607 p = mkFormX(p, 63, 12, 0, fr_srcHi, 72, 0, endness_host);
5608 p = mkFormX(p, 63, 13, 0, fr_srcLo, 72, 0, endness_host);
sewardjcdc376d2012-04-23 11:21:12 +00005609
5610 /* Do drintx instruction with 128-bit source operands in
5611 * registers (12,13).
5612 */
carll1f5fe1f2014-08-07 23:25:23 +00005613 p = mkFormZ23(p, 63, 10, r, 12, rmc, 99, 0, endness_host);
sewardjcdc376d2012-04-23 11:21:12 +00005614
5615 /* The instruction will put the 128-bit result in
5616 * registers (10,11). Note, the operand in the instruction only
5617 * reference the first of the two registers in the pair.
5618 */
carll1f5fe1f2014-08-07 23:25:23 +00005619 p = mkFormX(p, 63, fr_dstHi, 0, 10, 72, 0, endness_host);
5620 p = mkFormX(p, 63, fr_dstLo, 0, 11, 72, 0, endness_host);
sewardjcdc376d2012-04-23 11:21:12 +00005621 goto done;
5622 }
5623
5624 case Pin_DfpQuantize: {
5625 UInt fr_dst = fregNo(i->Pin.DfpQuantize.dst);
5626 UInt fr_srcL = fregNo(i->Pin.DfpQuantize.srcL);
5627 UInt fr_srcR = fregNo(i->Pin.DfpQuantize.srcR);
5628 UInt rmc;
5629
5630 rmc = i->Pin.DfpQuantize.rmc->Pri.Imm;
5631
5632 switch (i->Pin.DfpQuantize.op) {
5633 case Pfp_DQUA:
carll1f5fe1f2014-08-07 23:25:23 +00005634 p = mkFormZ23(p, 59, fr_dst, fr_srcL, fr_srcR, rmc, 3, 0, endness_host);
sewardjcdc376d2012-04-23 11:21:12 +00005635 break;
5636 case Pfp_RRDTR:
carll1f5fe1f2014-08-07 23:25:23 +00005637 p = mkFormZ23(p, 59, fr_dst, fr_srcL, fr_srcR, rmc, 35, 0, endness_host);
sewardjcdc376d2012-04-23 11:21:12 +00005638 break;
5639 default:
5640 break;
5641 }
5642 goto done;
5643 }
5644
5645 case Pin_DfpQuantize128: {
5646 UInt fr_dst_hi = fregNo(i->Pin.DfpQuantize128.dst_hi);
5647 UInt fr_dst_lo = fregNo(i->Pin.DfpQuantize128.dst_lo);
5648 UInt fr_src_hi = fregNo(i->Pin.DfpQuantize128.src_hi);
5649 UInt fr_src_lo = fregNo(i->Pin.DfpQuantize128.src_lo);
5650 UInt rmc;
5651
5652 rmc = i->Pin.DfpQuantize128.rmc->Pri.Imm;
5653 /* Setup the upper and lower registers of the source operand
5654 * register pairs. Note, left source operand passed in via the
5655 * dst register pair.
5656 */
carll1f5fe1f2014-08-07 23:25:23 +00005657 p = mkFormX(p, 63, 10, 0, fr_dst_hi, 72, 0, endness_host);
5658 p = mkFormX(p, 63, 11, 0, fr_dst_lo, 72, 0, endness_host);
5659 p = mkFormX(p, 63, 12, 0, fr_src_hi, 72, 0, endness_host);
5660 p = mkFormX(p, 63, 13, 0, fr_src_lo, 72, 0, endness_host);
sewardjcdc376d2012-04-23 11:21:12 +00005661
5662 /* Do dquaq instruction with 128-bit source operands in
5663 * registers (12,13).
5664 */
5665 switch (i->Pin.DfpQuantize128.op) {
5666 case Pfp_DQUAQ:
carll1f5fe1f2014-08-07 23:25:23 +00005667 p = mkFormZ23(p, 63, 10, 10, 12, rmc, 3, 0, endness_host);
sewardjcdc376d2012-04-23 11:21:12 +00005668 break;
5669 case Pfp_DRRNDQ:
carll1f5fe1f2014-08-07 23:25:23 +00005670 p = mkFormZ23(p, 63, 10, 10, 12, rmc, 35, 0, endness_host);
sewardjcdc376d2012-04-23 11:21:12 +00005671 break;
5672 default:
5673 vpanic("Pin_DfpQuantize128: default case, couldn't find inst to issue \n");
5674 break;
5675 }
5676
5677 /* The instruction will put the 128-bit result in
5678 * registers (10,11). Note, the operand in the instruction only
5679 * reference the first of the two registers in the pair.
5680 */
carll1f5fe1f2014-08-07 23:25:23 +00005681 p = mkFormX(p, 63, fr_dst_hi, 0, 10, 72, 0, endness_host);
5682 p = mkFormX(p, 63, fr_dst_lo, 0, 11, 72, 0, endness_host);
sewardjcdc376d2012-04-23 11:21:12 +00005683 goto done;
5684 }
5685
sewardj26217b02012-04-12 17:19:48 +00005686 case Pin_DfpD128toD64: {
5687 UInt fr_dst = fregNo( i->Pin.DfpD128toD64.dst );
5688 UInt fr_srcHi = fregNo( i->Pin.DfpD128toD64.src_hi );
5689 UInt fr_srcLo = fregNo( i->Pin.DfpD128toD64.src_lo );
5690
5691 /* Setup the upper and lower registers of the source operand
5692 * register pair.
5693 */
carll1f5fe1f2014-08-07 23:25:23 +00005694 p = mkFormX( p, 63, 10, 0, fr_dst, 72, 0, endness_host );
5695 p = mkFormX( p, 63, 12, 0, fr_srcHi, 72, 0, endness_host );
5696 p = mkFormX( p, 63, 13, 0, fr_srcLo, 72, 0, endness_host );
sewardj26217b02012-04-12 17:19:48 +00005697
5698 /* Do instruction with 128-bit source operands in registers (10,11) */
5699 switch (i->Pin.Dfp128Binary.op) {
5700 case Pfp_DRDPQ:
carll1f5fe1f2014-08-07 23:25:23 +00005701 p = mkFormX( p, 63, 10, 0, 12, 770, 0, endness_host );
sewardj26217b02012-04-12 17:19:48 +00005702 break;
5703 case Pfp_DCTFIXQ:
carll1f5fe1f2014-08-07 23:25:23 +00005704 p = mkFormX( p, 63, 10, 0, 12, 290, 0, endness_host );
sewardj26217b02012-04-12 17:19:48 +00005705 break;
5706 default:
5707 goto bad;
5708 }
5709
5710 /* The instruction will put the 64-bit result in registers 10. */
carll1f5fe1f2014-08-07 23:25:23 +00005711 p = mkFormX(p, 63, fr_dst, 0, 10, 72, 0, endness_host);
sewardj26217b02012-04-12 17:19:48 +00005712 goto done;
5713 }
sewardjdb014092012-04-20 23:58:17 +00005714
sewardj26217b02012-04-12 17:19:48 +00005715 case Pin_DfpI64StoD128: {
5716 UInt fr_dstHi = fregNo( i->Pin.DfpI64StoD128.dst_hi );
5717 UInt fr_dstLo = fregNo( i->Pin.DfpI64StoD128.dst_lo );
5718 UInt fr_src = fregNo( i->Pin.DfpI64StoD128.src );
5719
5720 switch (i->Pin.Dfp128Binary.op) {
5721 case Pfp_DCFFIXQ:
carll1f5fe1f2014-08-07 23:25:23 +00005722 p = mkFormX( p, 63, 10, 11, fr_src, 802, 0, endness_host );
sewardj26217b02012-04-12 17:19:48 +00005723 break;
5724 default:
5725 goto bad;
5726 }
5727
5728 /* The instruction will put the 64-bit result in registers 10, 11. */
carll1f5fe1f2014-08-07 23:25:23 +00005729 p = mkFormX(p, 63, fr_dstHi, 0, 10, 72, 0, endness_host);
5730 p = mkFormX(p, 63, fr_dstLo, 0, 11, 72, 0, endness_host);
sewardj26217b02012-04-12 17:19:48 +00005731 goto done;
5732 }
sewardjdb014092012-04-20 23:58:17 +00005733
sewardjcdc376d2012-04-23 11:21:12 +00005734 case Pin_InsertExpD128: {
5735 UInt fr_dstHi = fregNo(i->Pin.InsertExpD128.dst_hi);
5736 UInt fr_dstLo = fregNo(i->Pin.InsertExpD128.dst_lo);
5737 UInt fr_srcL = fregNo(i->Pin.InsertExpD128.srcL);
5738 UInt fr_srcRHi = fregNo(i->Pin.InsertExpD128.srcR_hi);
5739 UInt fr_srcRLo = fregNo(i->Pin.InsertExpD128.srcR_lo);
5740
5741 /* The left operand is a single F64 value, the right is an F128
5742 * register pair.
5743 */
carll1f5fe1f2014-08-07 23:25:23 +00005744 p = mkFormX(p, 63, 10, 0, fr_srcL, 72, 0, endness_host);
5745 p = mkFormX(p, 63, 12, 0, fr_srcRHi, 72, 0, endness_host);
5746 p = mkFormX(p, 63, 13, 0, fr_srcRLo, 72, 0, endness_host);
5747 p = mkFormX(p, 63, 10, 10, 12, 866, 0, endness_host );
sewardjcdc376d2012-04-23 11:21:12 +00005748
5749 /* The instruction will put the 128-bit result into
5750 * registers (10,11). Note, the operand in the instruction only
5751 * reference the first of the two registers in the pair.
5752 */
carll1f5fe1f2014-08-07 23:25:23 +00005753 p = mkFormX(p, 63, fr_dstHi, 0, 10, 72, 0, endness_host);
5754 p = mkFormX(p, 63, fr_dstLo, 0, 11, 72, 0, endness_host);
sewardjcdc376d2012-04-23 11:21:12 +00005755 goto done;
5756 }
5757
5758 case Pin_Dfp64Cmp:{
5759 UChar crfD = 1;
5760 UInt r_dst = iregNo(i->Pin.Dfp64Cmp.dst, mode64);
5761 UInt fr_srcL = fregNo(i->Pin.Dfp64Cmp.srcL);
5762 UInt fr_srcR = fregNo(i->Pin.Dfp64Cmp.srcR);
5763 vassert(crfD < 8);
5764 // dcmpo, dcmpu
carll1f5fe1f2014-08-07 23:25:23 +00005765 p = mkFormX(p, 59, crfD<<2, fr_srcL, fr_srcR, 130, 0, endness_host);
sewardjcdc376d2012-04-23 11:21:12 +00005766
5767 // mfcr (mv CR to r_dst)
carll1f5fe1f2014-08-07 23:25:23 +00005768 p = mkFormX(p, 31, r_dst, 0, 0, 19, 0, endness_host);
sewardjcdc376d2012-04-23 11:21:12 +00005769
5770 // rlwinm r_dst,r_dst,8,28,31
5771 // => rotate field 1 to bottomw of word, masking out upper 28
carll1f5fe1f2014-08-07 23:25:23 +00005772 p = mkFormM(p, 21, r_dst, r_dst, 8, 28, 31, 0, endness_host);
sewardjcdc376d2012-04-23 11:21:12 +00005773 goto done;
5774 }
5775
5776 case Pin_Dfp128Cmp: {
5777 UChar crfD = 1;
5778 UInt r_dst = iregNo(i->Pin.Dfp128Cmp.dst, mode64);
5779 UInt fr_srcL_hi = fregNo(i->Pin.Dfp128Cmp.srcL_hi);
5780 UInt fr_srcL_lo = fregNo(i->Pin.Dfp128Cmp.srcL_lo);
5781 UInt fr_srcR_hi = fregNo(i->Pin.Dfp128Cmp.srcR_hi);
5782 UInt fr_srcR_lo = fregNo(i->Pin.Dfp128Cmp.srcR_lo);
5783 vassert(crfD < 8);
5784 // dcmpoq, dcmpuq
5785 /* Setup the upper and lower registers of the source operand
5786 * register pair.
5787 */
carll1f5fe1f2014-08-07 23:25:23 +00005788 p = mkFormX(p, 63, 10, 0, fr_srcL_hi, 72, 0, endness_host);
5789 p = mkFormX(p, 63, 11, 0, fr_srcL_lo, 72, 0, endness_host);
5790 p = mkFormX(p, 63, 12, 0, fr_srcR_hi, 72, 0, endness_host);
5791 p = mkFormX(p, 63, 13, 0, fr_srcR_lo, 72, 0, endness_host);
sewardjcdc376d2012-04-23 11:21:12 +00005792
carll1f5fe1f2014-08-07 23:25:23 +00005793 p = mkFormX(p, 63, crfD<<2, 10, 12, 130, 0, endness_host);
sewardjcdc376d2012-04-23 11:21:12 +00005794
5795 // mfcr (mv CR to r_dst)
carll1f5fe1f2014-08-07 23:25:23 +00005796 p = mkFormX(p, 31, r_dst, 0, 0, 19, 0, endness_host);
sewardjcdc376d2012-04-23 11:21:12 +00005797
5798 // rlwinm r_dst,r_dst,8,28,31
5799 // => rotate field 1 to bottomw of word, masking out upper 28
carll1f5fe1f2014-08-07 23:25:23 +00005800 p = mkFormM(p, 21, r_dst, r_dst, 8, 28, 31, 0, endness_host);
sewardjcdc376d2012-04-23 11:21:12 +00005801 goto done;
5802 }
5803
sewardj3dee8492012-04-20 00:13:28 +00005804 case Pin_EvCheck: {
5805 /* This requires a 32-bit dec/test in both 32- and 64-bit
5806 modes. */
5807 /* We generate:
5808 lwz r30, amCounter
5809 addic. r30, r30, -1
5810 stw r30, amCounter
5811 bge nofail
5812 lwz/ld r30, amFailAddr
5813 mtctr r30
5814 bctr
5815 nofail:
5816 */
5817 UChar* p0 = p;
5818 /* lwz r30, amCounter */
5819 p = do_load_or_store_word32(p, True/*isLoad*/, /*r*/30,
carll1f5fe1f2014-08-07 23:25:23 +00005820 i->Pin.EvCheck.amCounter, mode64,
5821 endness_host);
sewardj3dee8492012-04-20 00:13:28 +00005822 /* addic. r30,r30,-1 */
carll1f5fe1f2014-08-07 23:25:23 +00005823 p = emit32(p, 0x37DEFFFF, endness_host);
sewardj3dee8492012-04-20 00:13:28 +00005824 /* stw r30, amCounter */
5825 p = do_load_or_store_word32(p, False/*!isLoad*/, /*r*/30,
carll1f5fe1f2014-08-07 23:25:23 +00005826 i->Pin.EvCheck.amCounter, mode64,
5827 endness_host);
sewardj3dee8492012-04-20 00:13:28 +00005828 /* bge nofail */
carll1f5fe1f2014-08-07 23:25:23 +00005829 p = emit32(p, 0x40800010, endness_host);
sewardj3dee8492012-04-20 00:13:28 +00005830 /* lwz/ld r30, amFailAddr */
5831 p = do_load_or_store_machine_word(p, True/*isLoad*/, /*r*/30,
carll1f5fe1f2014-08-07 23:25:23 +00005832 i->Pin.EvCheck.amFailAddr, mode64,
5833 endness_host);
sewardj3dee8492012-04-20 00:13:28 +00005834 /* mtctr r30 */
carll1f5fe1f2014-08-07 23:25:23 +00005835 p = mkFormXFX(p, /*r*/30, 9, 467, endness_host);
sewardj3dee8492012-04-20 00:13:28 +00005836 /* bctr */
carll1f5fe1f2014-08-07 23:25:23 +00005837 p = mkFormXL(p, 19, Pct_ALWAYS, 0, 0, 528, 0, endness_host);
sewardj3dee8492012-04-20 00:13:28 +00005838 /* nofail: */
5839
5840 /* Crosscheck */
sewardj9b769162014-07-24 12:42:03 +00005841 vassert(evCheckSzB_PPC(endness_host) == (UChar*)p - (UChar*)p0);
sewardj3dee8492012-04-20 00:13:28 +00005842 goto done;
5843 }
5844
5845 case Pin_ProfInc: {
5846 /* We generate:
5847 (ctrP is unknown now, so use 0x65556555(65556555) in the
5848 expectation that a later call to LibVEX_patchProfCtr
5849 will be used to fill in the immediate fields once the
5850 right value is known.)
5851 32-bit:
5852 imm32-exactly r30, 0x65556555
5853 lwz r29, 4(r30)
5854 addic. r29, r29, 1
5855 stw r29, 4(r30)
5856 lwz r29, 0(r30)
5857 addze r29, r29
5858 stw r29, 0(r30)
5859 64-bit:
5860 imm64-exactly r30, 0x6555655565556555
5861 ld r29, 0(r30)
sewardjf252de52012-04-20 10:42:24 +00005862 addi r29, r29, 1
sewardj3dee8492012-04-20 00:13:28 +00005863 std r29, 0(r30)
5864 */
5865 if (mode64) {
5866 p = mkLoadImm_EXACTLY2or5(
carll1f5fe1f2014-08-07 23:25:23 +00005867 p, /*r*/30, 0x6555655565556555ULL, True/*mode64*/, endness_host);
5868 p = emit32(p, 0xEBBE0000, endness_host);
5869 p = emit32(p, 0x3BBD0001, endness_host);
5870 p = emit32(p, 0xFBBE0000, endness_host);
sewardj3dee8492012-04-20 00:13:28 +00005871 } else {
5872 p = mkLoadImm_EXACTLY2or5(
carll1f5fe1f2014-08-07 23:25:23 +00005873 p, /*r*/30, 0x65556555ULL, False/*!mode64*/, endness_host);
5874 p = emit32(p, 0x83BE0004, endness_host);
5875 p = emit32(p, 0x37BD0001, endness_host);
5876 p = emit32(p, 0x93BE0004, endness_host);
5877 p = emit32(p, 0x83BE0000, endness_host);
5878 p = emit32(p, 0x7FBD0194, endness_host);
5879 p = emit32(p, 0x93BE0000, endness_host);
sewardj3dee8492012-04-20 00:13:28 +00005880 }
5881 /* Tell the caller .. */
5882 vassert(!(*is_profInc));
5883 *is_profInc = True;
5884 goto done;
5885 }
5886
cerionbcf8c3e2005-02-04 16:17:07 +00005887 default:
5888 goto bad;
5889 }
5890
5891 bad:
cerionab9132d2005-02-15 15:46:59 +00005892 vex_printf("\n=> ");
cerion5b2325f2005-12-23 00:55:09 +00005893 ppPPCInstr(i, mode64);
5894 vpanic("emit_PPCInstr");
cerionbcf8c3e2005-02-04 16:17:07 +00005895 /*NOTREACHED*/
5896
cerionbcf8c3e2005-02-04 16:17:07 +00005897 done:
sewardj9e1cf152012-04-20 02:18:31 +00005898 vassert(p - &buf[0] <= 64);
cerionbcf8c3e2005-02-04 16:17:07 +00005899 return p - &buf[0];
cerionbcf8c3e2005-02-04 16:17:07 +00005900}
5901
sewardj3dee8492012-04-20 00:13:28 +00005902
5903/* How big is an event check? See case for Pin_EvCheck in
5904 emit_PPCInstr just above. That crosschecks what this returns, so
5905 we can tell if we're inconsistent. */
sewardj9b769162014-07-24 12:42:03 +00005906Int evCheckSzB_PPC ( VexEndness endness_host )
sewardj3dee8492012-04-20 00:13:28 +00005907{
5908 return 28;
5909}
5910
5911
5912/* NB: what goes on here has to be very closely coordinated with the
5913 emitInstr case for XDirect, above. */
sewardj9b769162014-07-24 12:42:03 +00005914VexInvalRange chainXDirect_PPC ( VexEndness endness_host,
5915 void* place_to_chain,
florian7d6f81d2014-09-22 21:43:37 +00005916 const void* disp_cp_chain_me_EXPECTED,
5917 const void* place_to_jump_to,
sewardj3dee8492012-04-20 00:13:28 +00005918 Bool mode64 )
5919{
sewardj9b769162014-07-24 12:42:03 +00005920 if (mode64) {
carll1f5fe1f2014-08-07 23:25:23 +00005921 vassert((endness_host == VexEndnessBE) ||
5922 (endness_host == VexEndnessLE));
sewardj9b769162014-07-24 12:42:03 +00005923 } else {
5924 vassert(endness_host == VexEndnessBE);
5925 }
5926
sewardj3dee8492012-04-20 00:13:28 +00005927 /* What we're expecting to see is:
5928 imm32/64-fixed r30, disp_cp_chain_me_to_EXPECTED
5929 mtctr r30
5930 bctrl
5931 viz
5932 <8 or 20 bytes generated by mkLoadImm_EXACTLY2or5>
5933 7F C9 03 A6
5934 4E 80 04 21
5935 */
5936 UChar* p = (UChar*)place_to_chain;
5937 vassert(0 == (3 & (HWord)p));
5938 vassert(isLoadImm_EXACTLY2or5(p, /*r*/30,
5939 Ptr_to_ULong(disp_cp_chain_me_EXPECTED),
carll1f5fe1f2014-08-07 23:25:23 +00005940 mode64, endness_host));
5941 vassert(fetch32(p + (mode64 ? 20 : 8) + 0, endness_host) == 0x7FC903A6);
5942 vassert(fetch32(p + (mode64 ? 20 : 8) + 4, endness_host) == 0x4E800421);
sewardj3dee8492012-04-20 00:13:28 +00005943 /* And what we want to change it to is:
5944 imm32/64-fixed r30, place_to_jump_to
5945 mtctr r30
5946 bctr
5947 viz
5948 <8 or 20 bytes generated by mkLoadImm_EXACTLY2or5>
5949 7F C9 03 A6
5950 4E 80 04 20
5951 The replacement has the same length as the original.
5952 */
5953 p = mkLoadImm_EXACTLY2or5(p, /*r*/30,
carll1f5fe1f2014-08-07 23:25:23 +00005954 Ptr_to_ULong(place_to_jump_to), mode64,
5955 endness_host);
5956 p = emit32(p, 0x7FC903A6, endness_host);
5957 p = emit32(p, 0x4E800420, endness_host);
sewardj3dee8492012-04-20 00:13:28 +00005958
5959 Int len = p - (UChar*)place_to_chain;
5960 vassert(len == (mode64 ? 28 : 16)); /* stay sane */
5961 VexInvalRange vir = {(HWord)place_to_chain, len};
5962 return vir;
5963}
5964
5965
5966/* NB: what goes on here has to be very closely coordinated with the
5967 emitInstr case for XDirect, above. */
sewardj9b769162014-07-24 12:42:03 +00005968VexInvalRange unchainXDirect_PPC ( VexEndness endness_host,
5969 void* place_to_unchain,
florian7d6f81d2014-09-22 21:43:37 +00005970 const void* place_to_jump_to_EXPECTED,
5971 const void* disp_cp_chain_me,
sewardj3dee8492012-04-20 00:13:28 +00005972 Bool mode64 )
5973{
sewardj9b769162014-07-24 12:42:03 +00005974 if (mode64) {
carll1f5fe1f2014-08-07 23:25:23 +00005975 vassert((endness_host == VexEndnessBE) ||
5976 (endness_host == VexEndnessLE));
sewardj9b769162014-07-24 12:42:03 +00005977 } else {
5978 vassert(endness_host == VexEndnessBE);
5979 }
5980
sewardj3dee8492012-04-20 00:13:28 +00005981 /* What we're expecting to see is:
5982 imm32/64-fixed r30, place_to_jump_to_EXPECTED
5983 mtctr r30
5984 bctr
5985 viz
5986 <8 or 20 bytes generated by mkLoadImm_EXACTLY2or5>
5987 7F C9 03 A6
5988 4E 80 04 20
5989 */
5990 UChar* p = (UChar*)place_to_unchain;
5991 vassert(0 == (3 & (HWord)p));
5992 vassert(isLoadImm_EXACTLY2or5(p, /*r*/30,
5993 Ptr_to_ULong(place_to_jump_to_EXPECTED),
carll1f5fe1f2014-08-07 23:25:23 +00005994 mode64, endness_host));
5995 vassert(fetch32(p + (mode64 ? 20 : 8) + 0, endness_host) == 0x7FC903A6);
5996 vassert(fetch32(p + (mode64 ? 20 : 8) + 4, endness_host) == 0x4E800420);
sewardj3dee8492012-04-20 00:13:28 +00005997 /* And what we want to change it to is:
5998 imm32/64-fixed r30, disp_cp_chain_me
5999 mtctr r30
6000 bctrl
6001 viz
6002 <8 or 20 bytes generated by mkLoadImm_EXACTLY2or5>
6003 7F C9 03 A6
6004 4E 80 04 21
6005 The replacement has the same length as the original.
6006 */
6007 p = mkLoadImm_EXACTLY2or5(p, /*r*/30,
carll1f5fe1f2014-08-07 23:25:23 +00006008 Ptr_to_ULong(disp_cp_chain_me), mode64,
6009 endness_host);
6010 p = emit32(p, 0x7FC903A6, endness_host);
6011 p = emit32(p, 0x4E800421, endness_host);
sewardj3dee8492012-04-20 00:13:28 +00006012
6013 Int len = p - (UChar*)place_to_unchain;
6014 vassert(len == (mode64 ? 28 : 16)); /* stay sane */
6015 VexInvalRange vir = {(HWord)place_to_unchain, len};
6016 return vir;
6017}
6018
6019
6020/* Patch the counter address into a profile inc point, as previously
6021 created by the Pin_ProfInc case for emit_PPCInstr. */
sewardj9b769162014-07-24 12:42:03 +00006022VexInvalRange patchProfInc_PPC ( VexEndness endness_host,
6023 void* place_to_patch,
florian7d6f81d2014-09-22 21:43:37 +00006024 const ULong* location_of_counter,
sewardj3dee8492012-04-20 00:13:28 +00006025 Bool mode64 )
6026{
sewardj9b769162014-07-24 12:42:03 +00006027 if (mode64) {
carll1f5fe1f2014-08-07 23:25:23 +00006028 vassert((endness_host == VexEndnessBE) ||
6029 (endness_host == VexEndnessLE));
sewardj9b769162014-07-24 12:42:03 +00006030 } else {
6031 vassert(endness_host == VexEndnessBE);
6032 }
6033
sewardj3dee8492012-04-20 00:13:28 +00006034 UChar* p = (UChar*)place_to_patch;
6035 vassert(0 == (3 & (HWord)p));
6036
6037 Int len = 0;
6038 if (mode64) {
6039 vassert(isLoadImm_EXACTLY2or5(p, /*r*/30,
carll1f5fe1f2014-08-07 23:25:23 +00006040 0x6555655565556555ULL, True/*mode64*/,
6041 endness_host));
6042 vassert(fetch32(p + 20, endness_host) == 0xEBBE0000);
6043 vassert(fetch32(p + 24, endness_host) == 0x3BBD0001);
6044 vassert(fetch32(p + 28, endness_host) == 0xFBBE0000);
sewardj3dee8492012-04-20 00:13:28 +00006045 p = mkLoadImm_EXACTLY2or5(p, /*r*/30,
6046 Ptr_to_ULong(location_of_counter),
carll1f5fe1f2014-08-07 23:25:23 +00006047 True/*mode64*/, endness_host);
sewardj3dee8492012-04-20 00:13:28 +00006048 len = p - (UChar*)place_to_patch;
6049 vassert(len == 20);
6050 } else {
6051 vassert(isLoadImm_EXACTLY2or5(p, /*r*/30,
carll1f5fe1f2014-08-07 23:25:23 +00006052 0x65556555ULL, False/*!mode64*/,
6053 endness_host));
6054 vassert(fetch32(p + 8, endness_host) == 0x83BE0004);
6055 vassert(fetch32(p + 12, endness_host) == 0x37BD0001);
6056 vassert(fetch32(p + 16, endness_host) == 0x93BE0004);
6057 vassert(fetch32(p + 20, endness_host) == 0x83BE0000);
6058 vassert(fetch32(p + 24, endness_host) == 0x7FBD0194);
6059 vassert(fetch32(p + 28, endness_host) == 0x93BE0000);
sewardj3dee8492012-04-20 00:13:28 +00006060 p = mkLoadImm_EXACTLY2or5(p, /*r*/30,
6061 Ptr_to_ULong(location_of_counter),
carll1f5fe1f2014-08-07 23:25:23 +00006062 False/*!mode64*/, endness_host);
sewardj3dee8492012-04-20 00:13:28 +00006063 len = p - (UChar*)place_to_patch;
6064 vassert(len == 8);
6065 }
6066 VexInvalRange vir = {(HWord)place_to_patch, len};
6067 return vir;
6068}
6069
6070
cerionbcf8c3e2005-02-04 16:17:07 +00006071/*---------------------------------------------------------------*/
sewardjcef7d3e2009-07-02 12:21:59 +00006072/*--- end host_ppc_defs.c ---*/
cerionbcf8c3e2005-02-04 16:17:07 +00006073/*---------------------------------------------------------------*/