blob: 7cc7312cfeb4abeb677a6146209d7942f4abd364 [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
sewardj25e54732012-08-05 15:36:51 +000010 Copyright (C) 2004-2012 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 */
cerionf34ccc42005-09-16 08:55:50 +0000677 case Pav_ADDU: return "vaddu_m"; // b,h,w
678 case Pav_QADDU: return "vaddu_s"; // b,h,w
679 case Pav_QADDS: return "vadds_s"; // b,h,w
cerionc3d8bdc2005-06-28 18:06:23 +0000680
cerionf34ccc42005-09-16 08:55:50 +0000681 case Pav_SUBU: return "vsubu_m"; // b,h,w
682 case Pav_QSUBU: return "vsubu_s"; // b,h,w
683 case Pav_QSUBS: return "vsubs_s"; // b,h,w
cerion6b6f59e2005-06-28 20:59:18 +0000684
685 case Pav_OMULU: return "vmulou"; // b,h
686 case Pav_OMULS: return "vmulos"; // b,h
687 case Pav_EMULU: return "vmuleu"; // b,h
688 case Pav_EMULS: return "vmules"; // b,h
689
690 case Pav_AVGU: return "vavgu"; // b,h,w
691 case Pav_AVGS: return "vavgs"; // b,h,w
692
693 case Pav_MAXU: return "vmaxu"; // b,h,w
694 case Pav_MAXS: return "vmaxs"; // b,h,w
695
696 case Pav_MINU: return "vminu"; // b,h,w
697 case Pav_MINS: return "vmins"; // b,h,w
698
699 /* Compare (always affects CR field 6) */
700 case Pav_CMPEQU: return "vcmpequ"; // b,h,w
701 case Pav_CMPGTU: return "vcmpgtu"; // b,h,w
702 case Pav_CMPGTS: return "vcmpgts"; // b,h,w
703
704 /* Shift */
705 case Pav_SHL: return "vsl"; // ' ',b,h,w
706 case Pav_SHR: return "vsr"; // ' ',b,h,w
707 case Pav_SAR: return "vsra"; // b,h,w
708 case Pav_ROTL: return "vrl"; // b,h,w
709
710 /* Pack */
cerionf34ccc42005-09-16 08:55:50 +0000711 case Pav_PACKUU: return "vpku_um"; // h,w
712 case Pav_QPACKUU: return "vpku_us"; // h,w
713 case Pav_QPACKSU: return "vpks_us"; // h,w
714 case Pav_QPACKSS: return "vpks_ss"; // h,w
cerion6b6f59e2005-06-28 20:59:18 +0000715 case Pav_PACKPXL: return "vpkpx";
716
cerionc3d8bdc2005-06-28 18:06:23 +0000717 /* Merge */
cerion6b6f59e2005-06-28 20:59:18 +0000718 case Pav_MRGHI: return "vmrgh"; // b,h,w
719 case Pav_MRGLO: return "vmrgl"; // b,h,w
720
cerion5b2325f2005-12-23 00:55:09 +0000721 default: vpanic("showPPCAvOp");
cerion8ea0d3e2005-11-14 00:44:47 +0000722 }
723}
724
florian55085f82012-11-21 00:36:55 +0000725const HChar* showPPCAvFpOp ( PPCAvFpOp op ) {
cerion8ea0d3e2005-11-14 00:44:47 +0000726 switch (op) {
cerion6b6f59e2005-06-28 20:59:18 +0000727 /* Floating Point Binary */
cerion8ea0d3e2005-11-14 00:44:47 +0000728 case Pavfp_ADDF: return "vaddfp";
729 case Pavfp_SUBF: return "vsubfp";
730 case Pavfp_MULF: return "vmaddfp";
731 case Pavfp_MAXF: return "vmaxfp";
732 case Pavfp_MINF: return "vminfp";
733 case Pavfp_CMPEQF: return "vcmpeqfp";
734 case Pavfp_CMPGTF: return "vcmpgtfp";
735 case Pavfp_CMPGEF: return "vcmpgefp";
cerionc3d8bdc2005-06-28 18:06:23 +0000736
cerion8ea0d3e2005-11-14 00:44:47 +0000737 /* Floating Point Unary */
738 case Pavfp_RCPF: return "vrefp";
739 case Pavfp_RSQRTF: return "vrsqrtefp";
ceriond963eb42005-11-16 18:02:58 +0000740 case Pavfp_CVTU2F: return "vcfux";
741 case Pavfp_CVTS2F: return "vcfsx";
742 case Pavfp_QCVTF2U: return "vctuxs";
743 case Pavfp_QCVTF2S: return "vctsxs";
744 case Pavfp_ROUNDM: return "vrfim";
745 case Pavfp_ROUNDP: return "vrfip";
746 case Pavfp_ROUNDN: return "vrfin";
747 case Pavfp_ROUNDZ: return "vrfiz";
cerion8ea0d3e2005-11-14 00:44:47 +0000748
cerion5b2325f2005-12-23 00:55:09 +0000749 default: vpanic("showPPCAvFpOp");
cerionc3d8bdc2005-06-28 18:06:23 +0000750 }
751}
752
cerion5b2325f2005-12-23 00:55:09 +0000753PPCInstr* PPCInstr_LI ( HReg dst, ULong imm64, Bool mode64 )
sewardjb51f0f42005-07-18 11:38:02 +0000754{
cerion5b2325f2005-12-23 00:55:09 +0000755 PPCInstr* i = LibVEX_Alloc(sizeof(PPCInstr));
cerionf0de28c2005-12-13 20:21:11 +0000756 i->tag = Pin_LI;
757 i->Pin.LI.dst = dst;
758 i->Pin.LI.imm64 = imm64;
759 if (!mode64)
760 vassert( (Long)imm64 == (Long)(Int)(UInt)imm64 );
sewardjb51f0f42005-07-18 11:38:02 +0000761 return i;
762}
cerion5b2325f2005-12-23 00:55:09 +0000763PPCInstr* PPCInstr_Alu ( PPCAluOp op, HReg dst,
764 HReg srcL, PPCRH* srcR ) {
765 PPCInstr* i = LibVEX_Alloc(sizeof(PPCInstr));
cerionf0de28c2005-12-13 20:21:11 +0000766 i->tag = Pin_Alu;
767 i->Pin.Alu.op = op;
768 i->Pin.Alu.dst = dst;
769 i->Pin.Alu.srcL = srcL;
770 i->Pin.Alu.srcR = srcR;
cerioncd304492005-02-08 19:40:24 +0000771 return i;
772}
cerion5b2325f2005-12-23 00:55:09 +0000773PPCInstr* PPCInstr_Shft ( PPCShftOp op, Bool sz32,
774 HReg dst, HReg srcL, PPCRH* srcR ) {
775 PPCInstr* i = LibVEX_Alloc(sizeof(PPCInstr));
cerionbb01b7c2005-12-16 13:40:18 +0000776 i->tag = Pin_Shft;
777 i->Pin.Shft.op = op;
778 i->Pin.Shft.sz32 = sz32;
779 i->Pin.Shft.dst = dst;
780 i->Pin.Shft.srcL = srcL;
781 i->Pin.Shft.srcR = srcR;
782 return i;
783}
cerion5b2325f2005-12-23 00:55:09 +0000784PPCInstr* PPCInstr_AddSubC ( Bool isAdd, Bool setC,
785 HReg dst, HReg srcL, HReg srcR ) {
786 PPCInstr* i = LibVEX_Alloc(sizeof(PPCInstr));
787 i->tag = Pin_AddSubC;
788 i->Pin.AddSubC.isAdd = isAdd;
789 i->Pin.AddSubC.setC = setC;
790 i->Pin.AddSubC.dst = dst;
791 i->Pin.AddSubC.srcL = srcL;
792 i->Pin.AddSubC.srcR = srcR;
cerion4a49b032005-11-08 16:23:07 +0000793 return i;
794}
cerion5b2325f2005-12-23 00:55:09 +0000795PPCInstr* PPCInstr_Cmp ( Bool syned, Bool sz32,
796 UInt crfD, HReg srcL, PPCRH* srcR ) {
797 PPCInstr* i = LibVEX_Alloc(sizeof(PPCInstr));
cerionf0de28c2005-12-13 20:21:11 +0000798 i->tag = Pin_Cmp;
799 i->Pin.Cmp.syned = syned;
cerionbb01b7c2005-12-16 13:40:18 +0000800 i->Pin.Cmp.sz32 = sz32;
cerionf0de28c2005-12-13 20:21:11 +0000801 i->Pin.Cmp.crfD = crfD;
802 i->Pin.Cmp.srcL = srcL;
803 i->Pin.Cmp.srcR = srcR;
cerion2c49e032005-02-09 17:29:49 +0000804 return i;
805}
cerion5b2325f2005-12-23 00:55:09 +0000806PPCInstr* PPCInstr_Unary ( PPCUnaryOp op, HReg dst, HReg src ) {
807 PPCInstr* i = LibVEX_Alloc(sizeof(PPCInstr));
808 i->tag = Pin_Unary;
809 i->Pin.Unary.op = op;
810 i->Pin.Unary.dst = dst;
811 i->Pin.Unary.src = src;
cerion2c49e032005-02-09 17:29:49 +0000812 return i;
813}
cerion5b2325f2005-12-23 00:55:09 +0000814PPCInstr* PPCInstr_MulL ( Bool syned, Bool hi, Bool sz32,
815 HReg dst, HReg srcL, HReg srcR ) {
816 PPCInstr* i = LibVEX_Alloc(sizeof(PPCInstr));
cerion92f5dc72005-02-10 16:11:35 +0000817 i->tag = Pin_MulL;
818 i->Pin.MulL.syned = syned;
cerionf0de28c2005-12-13 20:21:11 +0000819 i->Pin.MulL.hi = hi;
cerionbb01b7c2005-12-16 13:40:18 +0000820 i->Pin.MulL.sz32 = sz32;
cerionc0e707e2005-02-10 22:35:34 +0000821 i->Pin.MulL.dst = dst;
ceriona2f75882005-03-15 16:33:38 +0000822 i->Pin.MulL.srcL = srcL;
823 i->Pin.MulL.srcR = srcR;
cerionf0de28c2005-12-13 20:21:11 +0000824 /* if doing the low word, the signedness is irrelevant, but tie it
sewardjb51f0f42005-07-18 11:38:02 +0000825 down anyway. */
cerionf0de28c2005-12-13 20:21:11 +0000826 if (!hi) vassert(!syned);
cerion92f5dc72005-02-10 16:11:35 +0000827 return i;
828}
sewardj4aa412a2011-07-24 14:13:21 +0000829PPCInstr* PPCInstr_Div ( Bool extended, Bool syned, Bool sz32,
cerion5b2325f2005-12-23 00:55:09 +0000830 HReg dst, HReg srcL, HReg srcR ) {
831 PPCInstr* i = LibVEX_Alloc(sizeof(PPCInstr));
832 i->tag = Pin_Div;
sewardj4aa412a2011-07-24 14:13:21 +0000833 i->Pin.Div.extended = extended;
cerion5b2325f2005-12-23 00:55:09 +0000834 i->Pin.Div.syned = syned;
835 i->Pin.Div.sz32 = sz32;
836 i->Pin.Div.dst = dst;
837 i->Pin.Div.srcL = srcL;
838 i->Pin.Div.srcR = srcR;
cerionc0e707e2005-02-10 22:35:34 +0000839 return i;
840}
cerion5b2325f2005-12-23 00:55:09 +0000841PPCInstr* PPCInstr_Call ( PPCCondCode cond,
842 Addr64 target, UInt argiregs ) {
sewardj6a64a9f2005-08-21 00:48:37 +0000843 UInt mask;
cerion5b2325f2005-12-23 00:55:09 +0000844 PPCInstr* i = LibVEX_Alloc(sizeof(PPCInstr));
cerion2c49e032005-02-09 17:29:49 +0000845 i->tag = Pin_Call;
846 i->Pin.Call.cond = cond;
847 i->Pin.Call.target = target;
sewardj6a64a9f2005-08-21 00:48:37 +0000848 i->Pin.Call.argiregs = argiregs;
849 /* Only r3 .. r10 inclusive may be used as arg regs. Hence: */
850 mask = (1<<3)|(1<<4)|(1<<5)|(1<<6)|(1<<7)|(1<<8)|(1<<9)|(1<<10);
851 vassert(0 == (argiregs & ~mask));
cerion2c49e032005-02-09 17:29:49 +0000852 return i;
853}
sewardj3dee8492012-04-20 00:13:28 +0000854PPCInstr* PPCInstr_XDirect ( Addr64 dstGA, PPCAMode* amCIA,
855 PPCCondCode cond, Bool toFastEP ) {
856 PPCInstr* i = LibVEX_Alloc(sizeof(PPCInstr));
857 i->tag = Pin_XDirect;
858 i->Pin.XDirect.dstGA = dstGA;
859 i->Pin.XDirect.amCIA = amCIA;
860 i->Pin.XDirect.cond = cond;
861 i->Pin.XDirect.toFastEP = toFastEP;
862 return i;
863}
864PPCInstr* PPCInstr_XIndir ( HReg dstGA, PPCAMode* amCIA,
865 PPCCondCode cond ) {
866 PPCInstr* i = LibVEX_Alloc(sizeof(PPCInstr));
867 i->tag = Pin_XIndir;
868 i->Pin.XIndir.dstGA = dstGA;
869 i->Pin.XIndir.amCIA = amCIA;
870 i->Pin.XIndir.cond = cond;
871 return i;
872}
873PPCInstr* PPCInstr_XAssisted ( HReg dstGA, PPCAMode* amCIA,
874 PPCCondCode cond, IRJumpKind jk ) {
875 PPCInstr* i = LibVEX_Alloc(sizeof(PPCInstr));
876 i->tag = Pin_XAssisted;
877 i->Pin.XAssisted.dstGA = dstGA;
878 i->Pin.XAssisted.amCIA = amCIA;
879 i->Pin.XAssisted.cond = cond;
880 i->Pin.XAssisted.jk = jk;
cerion2c49e032005-02-09 17:29:49 +0000881 return i;
882}
cerion5b2325f2005-12-23 00:55:09 +0000883PPCInstr* PPCInstr_CMov ( PPCCondCode cond,
884 HReg dst, PPCRI* src ) {
sewardje9d8a262009-07-01 08:06:34 +0000885 PPCInstr* i = LibVEX_Alloc(sizeof(PPCInstr));
cerionf0de28c2005-12-13 20:21:11 +0000886 i->tag = Pin_CMov;
887 i->Pin.CMov.cond = cond;
888 i->Pin.CMov.src = src;
889 i->Pin.CMov.dst = dst;
cerionab9132d2005-02-15 15:46:59 +0000890 vassert(cond.test != Pct_ALWAYS);
cerionb536af92005-02-10 15:03:19 +0000891 return i;
892}
sewardj7fd5bb02006-01-26 02:24:17 +0000893PPCInstr* PPCInstr_Load ( UChar sz,
cerion5b2325f2005-12-23 00:55:09 +0000894 HReg dst, PPCAMode* src, Bool mode64 ) {
895 PPCInstr* i = LibVEX_Alloc(sizeof(PPCInstr));
cerion7cf8e4e2005-02-16 16:08:17 +0000896 i->tag = Pin_Load;
897 i->Pin.Load.sz = sz;
cerion7cf8e4e2005-02-16 16:08:17 +0000898 i->Pin.Load.src = src;
899 i->Pin.Load.dst = dst;
cerionf0de28c2005-12-13 20:21:11 +0000900 vassert(sz == 1 || sz == 2 || sz == 4 || sz == 8);
901 if (sz == 8) vassert(mode64);
cerioncd304492005-02-08 19:40:24 +0000902 return i;
903}
sewardje9d8a262009-07-01 08:06:34 +0000904PPCInstr* PPCInstr_LoadL ( UChar sz,
905 HReg dst, HReg src, Bool mode64 )
906{
907 PPCInstr* i = LibVEX_Alloc(sizeof(PPCInstr));
908 i->tag = Pin_LoadL;
909 i->Pin.LoadL.sz = sz;
910 i->Pin.LoadL.src = src;
911 i->Pin.LoadL.dst = dst;
912 vassert(sz == 4 || sz == 8);
913 if (sz == 8) vassert(mode64);
914 return i;
915}
cerion5b2325f2005-12-23 00:55:09 +0000916PPCInstr* PPCInstr_Store ( UChar sz, PPCAMode* dst, HReg src,
917 Bool mode64 ) {
918 PPCInstr* i = LibVEX_Alloc(sizeof(PPCInstr));
cerioncd304492005-02-08 19:40:24 +0000919 i->tag = Pin_Store;
920 i->Pin.Store.sz = sz;
921 i->Pin.Store.src = src;
922 i->Pin.Store.dst = dst;
cerionf0de28c2005-12-13 20:21:11 +0000923 vassert(sz == 1 || sz == 2 || sz == 4 || sz == 8);
924 if (sz == 8) vassert(mode64);
cerioncd304492005-02-08 19:40:24 +0000925 return i;
926}
sewardje9d8a262009-07-01 08:06:34 +0000927PPCInstr* PPCInstr_StoreC ( UChar sz, HReg dst, HReg src, Bool mode64 ) {
928 PPCInstr* i = LibVEX_Alloc(sizeof(PPCInstr));
929 i->tag = Pin_StoreC;
930 i->Pin.StoreC.sz = sz;
931 i->Pin.StoreC.src = src;
932 i->Pin.StoreC.dst = dst;
933 vassert(sz == 4 || sz == 8);
934 if (sz == 8) vassert(mode64);
935 return i;
936}
cerion5b2325f2005-12-23 00:55:09 +0000937PPCInstr* PPCInstr_Set ( PPCCondCode cond, HReg dst ) {
938 PPCInstr* i = LibVEX_Alloc(sizeof(PPCInstr));
939 i->tag = Pin_Set;
940 i->Pin.Set.cond = cond;
941 i->Pin.Set.dst = dst;
cerionb536af92005-02-10 15:03:19 +0000942 return i;
943}
cerion5b2325f2005-12-23 00:55:09 +0000944PPCInstr* PPCInstr_MfCR ( HReg dst )
sewardjb51f0f42005-07-18 11:38:02 +0000945{
cerion5b2325f2005-12-23 00:55:09 +0000946 PPCInstr* i = LibVEX_Alloc(sizeof(PPCInstr));
947 i->tag = Pin_MfCR;
948 i->Pin.MfCR.dst = dst;
sewardjb51f0f42005-07-18 11:38:02 +0000949 return i;
950}
cerion5b2325f2005-12-23 00:55:09 +0000951PPCInstr* PPCInstr_MFence ( void )
cerion92f5dc72005-02-10 16:11:35 +0000952{
cerion5b2325f2005-12-23 00:55:09 +0000953 PPCInstr* i = LibVEX_Alloc(sizeof(PPCInstr));
954 i->tag = Pin_MFence;
cerion92f5dc72005-02-10 16:11:35 +0000955 return i;
956}
cerioncd304492005-02-08 19:40:24 +0000957
cerion5b2325f2005-12-23 00:55:09 +0000958PPCInstr* PPCInstr_FpUnary ( PPCFpOp op, HReg dst, HReg src ) {
959 PPCInstr* i = LibVEX_Alloc(sizeof(PPCInstr));
cerion094d1392005-06-20 13:45:57 +0000960 i->tag = Pin_FpUnary;
961 i->Pin.FpUnary.op = op;
962 i->Pin.FpUnary.dst = dst;
963 i->Pin.FpUnary.src = src;
964 return i;
965}
cerion5b2325f2005-12-23 00:55:09 +0000966PPCInstr* PPCInstr_FpBinary ( PPCFpOp op, HReg dst,
967 HReg srcL, HReg srcR ) {
968 PPCInstr* i = LibVEX_Alloc(sizeof(PPCInstr));
cerion094d1392005-06-20 13:45:57 +0000969 i->tag = Pin_FpBinary;
970 i->Pin.FpBinary.op = op;
971 i->Pin.FpBinary.dst = dst;
972 i->Pin.FpBinary.srcL = srcL;
973 i->Pin.FpBinary.srcR = srcR;
974 return i;
975}
sewardj40c80262006-02-08 19:30:46 +0000976PPCInstr* PPCInstr_FpMulAcc ( PPCFpOp op, HReg dst, HReg srcML,
977 HReg srcMR, HReg srcAcc )
978{
979 PPCInstr* i = LibVEX_Alloc(sizeof(PPCInstr));
980 i->tag = Pin_FpMulAcc;
981 i->Pin.FpMulAcc.op = op;
982 i->Pin.FpMulAcc.dst = dst;
983 i->Pin.FpMulAcc.srcML = srcML;
984 i->Pin.FpMulAcc.srcMR = srcMR;
985 i->Pin.FpMulAcc.srcAcc = srcAcc;
986 return i;
987}
cerion5b2325f2005-12-23 00:55:09 +0000988PPCInstr* PPCInstr_FpLdSt ( Bool isLoad, UChar sz,
989 HReg reg, PPCAMode* addr ) {
990 PPCInstr* i = LibVEX_Alloc(sizeof(PPCInstr));
cerion094d1392005-06-20 13:45:57 +0000991 i->tag = Pin_FpLdSt;
992 i->Pin.FpLdSt.isLoad = isLoad;
993 i->Pin.FpLdSt.sz = sz;
994 i->Pin.FpLdSt.reg = reg;
995 i->Pin.FpLdSt.addr = addr;
996 vassert(sz == 4 || sz == 8);
997 return i;
998}
sewardj92923de2006-01-25 21:29:48 +0000999PPCInstr* PPCInstr_FpSTFIW ( HReg addr, HReg data )
1000{
1001 PPCInstr* i = LibVEX_Alloc(sizeof(PPCInstr));
1002 i->tag = Pin_FpSTFIW;
1003 i->Pin.FpSTFIW.addr = addr;
1004 i->Pin.FpSTFIW.data = data;
cerion094d1392005-06-20 13:45:57 +00001005 return i;
1006}
sewardj92923de2006-01-25 21:29:48 +00001007PPCInstr* PPCInstr_FpRSP ( HReg dst, HReg src ) {
1008 PPCInstr* i = LibVEX_Alloc(sizeof(PPCInstr));
1009 i->tag = Pin_FpRSP;
1010 i->Pin.FpRSP.dst = dst;
1011 i->Pin.FpRSP.src = src;
cerion094d1392005-06-20 13:45:57 +00001012 return i;
1013}
sewardjc6bbd472012-04-02 10:20:48 +00001014PPCInstr* PPCInstr_Dfp64Unary(PPCFpOp op, HReg dst, HReg src) {
1015 PPCInstr* i = LibVEX_Alloc( sizeof(PPCInstr) );
1016 i->tag = Pin_Dfp64Unary;
1017 i->Pin.Dfp64Unary.op = op;
1018 i->Pin.Dfp64Unary.dst = dst;
1019 i->Pin.Dfp64Unary.src = src;
1020 return i;
1021}
1022PPCInstr* PPCInstr_Dfp64Binary(PPCFpOp op, HReg dst, HReg srcL, HReg srcR) {
1023 PPCInstr* i = LibVEX_Alloc( sizeof(PPCInstr) );
1024 i->tag = Pin_Dfp64Binary;
1025 i->Pin.Dfp64Binary.op = op;
1026 i->Pin.Dfp64Binary.dst = dst;
1027 i->Pin.Dfp64Binary.srcL = srcL;
1028 i->Pin.Dfp64Binary.srcR = srcR;
1029 return i;
1030}
sewardj26217b02012-04-12 17:19:48 +00001031PPCInstr* PPCInstr_DfpShift ( PPCFpOp op, HReg dst, HReg src, PPCRI* shift ) {
1032 PPCInstr* i = LibVEX_Alloc(sizeof(PPCInstr));
1033 i->tag = Pin_DfpShift;
1034 i->Pin.DfpShift.op = op;
1035 i->Pin.DfpShift.shift = shift;
1036 i->Pin.DfpShift.src = src;
1037 i->Pin.DfpShift.dst = dst;
1038 return i;
1039}
1040PPCInstr* PPCInstr_Dfp128Unary(PPCFpOp op, HReg dst_hi, HReg dst_lo,
1041 HReg src_hi, HReg src_lo) {
1042 PPCInstr* i = LibVEX_Alloc( sizeof(PPCInstr) );
1043 i->tag = Pin_Dfp128Unary;
1044 i->Pin.Dfp128Unary.op = op;
1045 i->Pin.Dfp128Unary.dst_hi = dst_hi;
1046 i->Pin.Dfp128Unary.dst_lo = dst_lo;
1047 i->Pin.Dfp128Unary.src_hi = src_hi;
1048 i->Pin.Dfp128Unary.src_lo = src_lo;
1049 return i;
1050}
sewardjc6bbd472012-04-02 10:20:48 +00001051PPCInstr* PPCInstr_Dfp128Binary(PPCFpOp op, HReg dst_hi, HReg dst_lo,
1052 HReg srcR_hi, HReg srcR_lo) {
1053 /* dst is used to pass the srcL argument and return the result */
1054 PPCInstr* i = LibVEX_Alloc( sizeof(PPCInstr) );
1055 i->tag = Pin_Dfp128Binary;
1056 i->Pin.Dfp128Binary.op = op;
1057 i->Pin.Dfp128Binary.dst_hi = dst_hi;
1058 i->Pin.Dfp128Binary.dst_lo = dst_lo;
1059 i->Pin.Dfp128Binary.srcR_hi = srcR_hi;
1060 i->Pin.Dfp128Binary.srcR_lo = srcR_lo;
1061 return i;
1062}
sewardj26217b02012-04-12 17:19:48 +00001063PPCInstr* PPCInstr_DfpShift128 ( PPCFpOp op, HReg dst_hi, HReg dst_lo,
1064 HReg src_hi, HReg src_lo,
1065 PPCRI* shift ) {
1066 PPCInstr* i = LibVEX_Alloc(sizeof(PPCInstr));
1067 i->tag = Pin_DfpShift128;
1068 i->Pin.DfpShift128.op = op;
1069 i->Pin.DfpShift128.shift = shift;
1070 i->Pin.DfpShift128.src_hi = src_hi;
1071 i->Pin.DfpShift128.src_lo = src_lo;
1072 i->Pin.DfpShift128.dst_hi = dst_hi;
1073 i->Pin.DfpShift128.dst_lo = dst_lo;
1074 return i;
1075}
sewardjcdc376d2012-04-23 11:21:12 +00001076PPCInstr* PPCInstr_DfpRound ( HReg dst, HReg src, PPCRI* r_rmc ) {
1077 PPCInstr* i = LibVEX_Alloc(sizeof(PPCInstr));
1078 i->tag = Pin_DfpRound;
1079 i->Pin.DfpRound.dst = dst;
1080 i->Pin.DfpRound.src = src;
1081 i->Pin.DfpRound.r_rmc = r_rmc;
1082 return i;
1083}
1084PPCInstr* PPCInstr_DfpRound128 ( HReg dst_hi, HReg dst_lo, HReg src_hi,
1085 HReg src_lo, PPCRI* r_rmc ) {
1086 PPCInstr* i = LibVEX_Alloc(sizeof(PPCInstr));
1087 i->tag = Pin_DfpRound128;
1088 i->Pin.DfpRound128.dst_hi = dst_hi;
1089 i->Pin.DfpRound128.dst_lo = dst_lo;
1090 i->Pin.DfpRound128.src_hi = src_hi;
1091 i->Pin.DfpRound128.src_lo = src_lo;
1092 i->Pin.DfpRound128.r_rmc = r_rmc;
1093 return i;
1094}
floriana7b0d102012-06-15 20:55:43 +00001095PPCInstr* PPCInstr_DfpQuantize ( PPCFpOp op, HReg dst, HReg srcL, HReg srcR,
sewardjcdc376d2012-04-23 11:21:12 +00001096 PPCRI* rmc ) {
1097 PPCInstr* i = LibVEX_Alloc(sizeof(PPCInstr));
1098 i->tag = Pin_DfpQuantize;
1099 i->Pin.DfpQuantize.op = op;
1100 i->Pin.DfpQuantize.dst = dst;
1101 i->Pin.DfpQuantize.srcL = srcL;
1102 i->Pin.DfpQuantize.srcR = srcR;
1103 i->Pin.DfpQuantize.rmc = rmc;
1104 return i;
1105}
floriana7b0d102012-06-15 20:55:43 +00001106PPCInstr* PPCInstr_DfpQuantize128 ( PPCFpOp op, HReg dst_hi, HReg dst_lo,
sewardjcdc376d2012-04-23 11:21:12 +00001107 HReg src_hi, HReg src_lo, PPCRI* rmc ) {
1108 /* dst is used to pass left operand in and return result */
1109 PPCInstr* i = LibVEX_Alloc(sizeof(PPCInstr));
1110 i->tag = Pin_DfpQuantize128;
1111 i->Pin.DfpQuantize128.op = op;
1112 i->Pin.DfpQuantize128.dst_hi = dst_hi;
1113 i->Pin.DfpQuantize128.dst_lo = dst_lo;
1114 i->Pin.DfpQuantize128.src_hi = src_hi;
1115 i->Pin.DfpQuantize128.src_lo = src_lo;
1116 i->Pin.DfpQuantize128.rmc = rmc;
1117 return i;
1118}
sewardj26217b02012-04-12 17:19:48 +00001119PPCInstr* PPCInstr_DfpD128toD64 ( PPCFpOp op, HReg dst,
1120 HReg src_hi, HReg src_lo ) {
1121 PPCInstr* i = LibVEX_Alloc(sizeof(PPCInstr));
1122 i->tag = Pin_DfpD128toD64;
1123 i->Pin.DfpD128toD64.op = op;
1124 i->Pin.DfpD128toD64.src_hi = src_hi;
1125 i->Pin.DfpD128toD64.src_lo = src_lo;
1126 i->Pin.DfpD128toD64.dst = dst;
1127 return i;
1128}
sewardj26217b02012-04-12 17:19:48 +00001129PPCInstr* PPCInstr_DfpI64StoD128 ( PPCFpOp op, HReg dst_hi,
1130 HReg dst_lo, HReg src ) {
1131 PPCInstr* i = LibVEX_Alloc(sizeof(PPCInstr));
1132 i->tag = Pin_DfpI64StoD128;
1133 i->Pin.DfpI64StoD128.op = op;
1134 i->Pin.DfpI64StoD128.src = src;
1135 i->Pin.DfpI64StoD128.dst_hi = dst_hi;
1136 i->Pin.DfpI64StoD128.dst_lo = dst_lo;
1137 return i;
1138}
sewardjcdc376d2012-04-23 11:21:12 +00001139PPCInstr* PPCInstr_ExtractExpD128 ( PPCFpOp op, HReg dst,
1140 HReg src_hi, HReg src_lo ) {
1141 /* dst is used to pass the srcL argument */
1142 PPCInstr* i = LibVEX_Alloc(sizeof(PPCInstr));
1143 i->tag = Pin_ExtractExpD128;
1144 i->Pin.ExtractExpD128.op = op;
1145 i->Pin.ExtractExpD128.dst = dst;
1146 i->Pin.ExtractExpD128.src_hi = src_hi;
1147 i->Pin.ExtractExpD128.src_lo = src_lo;
1148 return i;
1149}
1150PPCInstr* PPCInstr_InsertExpD128 ( PPCFpOp op, HReg dst_hi, HReg dst_lo,
1151 HReg srcL, HReg srcR_hi, HReg srcR_lo ) {
1152 /* dst is used to pass the srcL argument */
1153 PPCInstr* i = LibVEX_Alloc(sizeof(PPCInstr));
1154 i->tag = Pin_InsertExpD128;
1155 i->Pin.InsertExpD128.op = op;
1156 i->Pin.InsertExpD128.dst_hi = dst_hi;
1157 i->Pin.InsertExpD128.dst_lo = dst_lo;
1158 i->Pin.InsertExpD128.srcL = srcL;
1159 i->Pin.InsertExpD128.srcR_hi = srcR_hi;
1160 i->Pin.InsertExpD128.srcR_lo = srcR_lo;
1161 return i;
1162}
1163PPCInstr* PPCInstr_Dfp64Cmp (/* UInt crfD,*/ HReg dst, HReg srcL, HReg srcR ) {
1164 PPCInstr* i = LibVEX_Alloc(sizeof(PPCInstr));
1165 i->tag = Pin_Dfp64Cmp;
1166 i->Pin.Dfp64Cmp.dst = dst;
1167 i->Pin.Dfp64Cmp.srcL = srcL;
1168 i->Pin.Dfp64Cmp.srcR = srcR;
1169 return i;
1170}
1171PPCInstr* PPCInstr_Dfp128Cmp ( HReg dst, HReg srcL_hi, HReg srcL_lo,
1172 HReg srcR_hi, HReg srcR_lo ) {
1173 PPCInstr* i = LibVEX_Alloc(sizeof(PPCInstr));
1174 i->tag = Pin_Dfp128Cmp;
1175 i->Pin.Dfp128Cmp.dst = dst;
1176 i->Pin.Dfp128Cmp.srcL_hi = srcL_hi;
1177 i->Pin.Dfp128Cmp.srcL_lo = srcL_lo;
1178 i->Pin.Dfp128Cmp.srcR_hi = srcR_hi;
1179 i->Pin.Dfp128Cmp.srcR_lo = srcR_lo;
1180 return i;
1181}
sewardj3dee8492012-04-20 00:13:28 +00001182PPCInstr* PPCInstr_EvCheck ( PPCAMode* amCounter,
1183 PPCAMode* amFailAddr ) {
1184 PPCInstr* i = LibVEX_Alloc(sizeof(PPCInstr));
1185 i->tag = Pin_EvCheck;
1186 i->Pin.EvCheck.amCounter = amCounter;
1187 i->Pin.EvCheck.amFailAddr = amFailAddr;
1188 return i;
1189}
1190PPCInstr* PPCInstr_ProfInc ( void ) {
1191 PPCInstr* i = LibVEX_Alloc(sizeof(PPCInstr));
1192 i->tag = Pin_ProfInc;
1193 return i;
1194}
1195
sewardj7d810d72011-05-08 22:05:10 +00001196/*
1197Valid combo | fromI | int32 | syned | flt64 |
1198--------------------------------------------
1199 | n n n n |
1200--------------------------------------------
1201 F64->I64U | n n n y |
1202--------------------------------------------
1203 | n n y n |
1204--------------------------------------------
1205 F64->I64S | n n y y |
1206--------------------------------------------
1207 | n y n n |
1208--------------------------------------------
1209 F64->I32U | n y n y |
1210--------------------------------------------
1211 | n y y n |
1212--------------------------------------------
1213 F64->I32S | n y y y |
1214--------------------------------------------
1215 I64U->F32 | y n n n |
1216--------------------------------------------
1217 I64U->F64 | y n n y |
1218--------------------------------------------
1219 | y n y n |
1220--------------------------------------------
1221 I64S->F64 | y n y y |
1222--------------------------------------------
1223 | y y n n |
1224--------------------------------------------
1225 | y y n y |
1226--------------------------------------------
1227 | y y y n |
1228--------------------------------------------
1229 | y y y y |
1230--------------------------------------------
1231*/
sewardj66d5ef22011-04-15 11:55:00 +00001232PPCInstr* PPCInstr_FpCftI ( Bool fromI, Bool int32, Bool syned,
sewardj7d810d72011-05-08 22:05:10 +00001233 Bool flt64, HReg dst, HReg src ) {
1234 Bool tmp = fromI | int32 | syned | flt64;
1235 vassert(tmp == True || tmp == False); // iow, no high bits set
1236 UShort conversion = 0;
1237 conversion = (fromI << 3) | (int32 << 2) | (syned << 1) | flt64;
1238 switch (conversion) {
1239 // Supported conversion operations
1240 case 1: case 3: case 5: case 7:
1241 case 8: case 9: case 11:
1242 break;
1243 default:
1244 vpanic("PPCInstr_FpCftI(ppc_host)");
1245 }
sewardj92923de2006-01-25 21:29:48 +00001246 PPCInstr* i = LibVEX_Alloc(sizeof(PPCInstr));
1247 i->tag = Pin_FpCftI;
1248 i->Pin.FpCftI.fromI = fromI;
1249 i->Pin.FpCftI.int32 = int32;
sewardj66d5ef22011-04-15 11:55:00 +00001250 i->Pin.FpCftI.syned = syned;
sewardj7d810d72011-05-08 22:05:10 +00001251 i->Pin.FpCftI.flt64 = flt64;
sewardj92923de2006-01-25 21:29:48 +00001252 i->Pin.FpCftI.dst = dst;
1253 i->Pin.FpCftI.src = src;
cerion07b07a92005-12-22 14:32:35 +00001254 return i;
1255}
cerion5b2325f2005-12-23 00:55:09 +00001256PPCInstr* PPCInstr_FpCMov ( PPCCondCode cond, HReg dst, HReg src ) {
1257 PPCInstr* i = LibVEX_Alloc(sizeof(PPCInstr));
cerion094d1392005-06-20 13:45:57 +00001258 i->tag = Pin_FpCMov;
1259 i->Pin.FpCMov.cond = cond;
1260 i->Pin.FpCMov.dst = dst;
1261 i->Pin.FpCMov.src = src;
1262 vassert(cond.test != Pct_ALWAYS);
1263 return i;
1264}
sewardjc6bbd472012-04-02 10:20:48 +00001265PPCInstr* PPCInstr_FpLdFPSCR ( HReg src, Bool dfp_rm ) {
cerion5b2325f2005-12-23 00:55:09 +00001266 PPCInstr* i = LibVEX_Alloc(sizeof(PPCInstr));
cerion094d1392005-06-20 13:45:57 +00001267 i->tag = Pin_FpLdFPSCR;
1268 i->Pin.FpLdFPSCR.src = src;
sewardjc6bbd472012-04-02 10:20:48 +00001269 i->Pin.FpLdFPSCR.dfp_rm = dfp_rm ? 1 : 0;
cerion094d1392005-06-20 13:45:57 +00001270 return i;
1271}
cerion5b2325f2005-12-23 00:55:09 +00001272PPCInstr* PPCInstr_FpCmp ( HReg dst, HReg srcL, HReg srcR ) {
1273 PPCInstr* i = LibVEX_Alloc(sizeof(PPCInstr));
cerion094d1392005-06-20 13:45:57 +00001274 i->tag = Pin_FpCmp;
1275 i->Pin.FpCmp.dst = dst;
1276 i->Pin.FpCmp.srcL = srcL;
1277 i->Pin.FpCmp.srcR = srcR;
1278 return i;
1279}
cerionbcf8c3e2005-02-04 16:17:07 +00001280
cerion7f000af2005-02-22 20:36:49 +00001281/* Read/Write Link Register */
cerion5b2325f2005-12-23 00:55:09 +00001282PPCInstr* PPCInstr_RdWrLR ( Bool wrLR, HReg gpr ) {
1283 PPCInstr* i = LibVEX_Alloc(sizeof(PPCInstr));
cerion7f000af2005-02-22 20:36:49 +00001284 i->tag = Pin_RdWrLR;
1285 i->Pin.RdWrLR.wrLR = wrLR;
1286 i->Pin.RdWrLR.gpr = gpr;
1287 return i;
1288}
1289
cerionc3d8bdc2005-06-28 18:06:23 +00001290/* AltiVec */
cerion5b2325f2005-12-23 00:55:09 +00001291PPCInstr* PPCInstr_AvLdSt ( Bool isLoad, UChar sz,
1292 HReg reg, PPCAMode* addr ) {
1293 PPCInstr* i = LibVEX_Alloc(sizeof(PPCInstr));
cerionc3d8bdc2005-06-28 18:06:23 +00001294 i->tag = Pin_AvLdSt;
1295 i->Pin.AvLdSt.isLoad = isLoad;
1296 i->Pin.AvLdSt.sz = sz;
1297 i->Pin.AvLdSt.reg = reg;
1298 i->Pin.AvLdSt.addr = addr;
1299 return i;
1300}
cerion5b2325f2005-12-23 00:55:09 +00001301PPCInstr* PPCInstr_AvUnary ( PPCAvOp op, HReg dst, HReg src ) {
1302 PPCInstr* i = LibVEX_Alloc(sizeof(PPCInstr));
cerion8ea0d3e2005-11-14 00:44:47 +00001303 i->tag = Pin_AvUnary;
cerionc3d8bdc2005-06-28 18:06:23 +00001304 i->Pin.AvUnary.op = op;
1305 i->Pin.AvUnary.dst = dst;
1306 i->Pin.AvUnary.src = src;
1307 return i;
1308}
cerion5b2325f2005-12-23 00:55:09 +00001309PPCInstr* PPCInstr_AvBinary ( PPCAvOp op, HReg dst,
1310 HReg srcL, HReg srcR ) {
1311 PPCInstr* i = LibVEX_Alloc(sizeof(PPCInstr));
cerionc3d8bdc2005-06-28 18:06:23 +00001312 i->tag = Pin_AvBinary;
1313 i->Pin.AvBinary.op = op;
1314 i->Pin.AvBinary.dst = dst;
1315 i->Pin.AvBinary.srcL = srcL;
1316 i->Pin.AvBinary.srcR = srcR;
1317 return i;
1318}
cerion5b2325f2005-12-23 00:55:09 +00001319PPCInstr* PPCInstr_AvBin8x16 ( PPCAvOp op, HReg dst,
1320 HReg srcL, HReg srcR ) {
1321 PPCInstr* i = LibVEX_Alloc(sizeof(PPCInstr));
1322 i->tag = Pin_AvBin8x16;
cerion6b6f59e2005-06-28 20:59:18 +00001323 i->Pin.AvBin8x16.op = op;
1324 i->Pin.AvBin8x16.dst = dst;
1325 i->Pin.AvBin8x16.srcL = srcL;
1326 i->Pin.AvBin8x16.srcR = srcR;
1327 return i;
1328}
cerion5b2325f2005-12-23 00:55:09 +00001329PPCInstr* PPCInstr_AvBin16x8 ( PPCAvOp op, HReg dst,
1330 HReg srcL, HReg srcR ) {
1331 PPCInstr* i = LibVEX_Alloc(sizeof(PPCInstr));
1332 i->tag = Pin_AvBin16x8;
cerion6b6f59e2005-06-28 20:59:18 +00001333 i->Pin.AvBin16x8.op = op;
1334 i->Pin.AvBin16x8.dst = dst;
1335 i->Pin.AvBin16x8.srcL = srcL;
1336 i->Pin.AvBin16x8.srcR = srcR;
1337 return i;
1338}
cerion5b2325f2005-12-23 00:55:09 +00001339PPCInstr* PPCInstr_AvBin32x4 ( PPCAvOp op, HReg dst,
1340 HReg srcL, HReg srcR ) {
1341 PPCInstr* i = LibVEX_Alloc(sizeof(PPCInstr));
1342 i->tag = Pin_AvBin32x4;
cerion6b6f59e2005-06-28 20:59:18 +00001343 i->Pin.AvBin32x4.op = op;
1344 i->Pin.AvBin32x4.dst = dst;
1345 i->Pin.AvBin32x4.srcL = srcL;
1346 i->Pin.AvBin32x4.srcR = srcR;
1347 return i;
1348}
sewardje522d4b2011-04-26 21:36:09 +00001349PPCInstr* PPCInstr_AvBin32Fx4 ( PPCAvFpOp op, HReg dst,
cerion5b2325f2005-12-23 00:55:09 +00001350 HReg srcL, HReg srcR ) {
1351 PPCInstr* i = LibVEX_Alloc(sizeof(PPCInstr));
cerion6b6f59e2005-06-28 20:59:18 +00001352 i->tag = Pin_AvBin32Fx4;
1353 i->Pin.AvBin32Fx4.op = op;
1354 i->Pin.AvBin32Fx4.dst = dst;
1355 i->Pin.AvBin32Fx4.srcL = srcL;
1356 i->Pin.AvBin32Fx4.srcR = srcR;
1357 return i;
1358}
sewardje522d4b2011-04-26 21:36:09 +00001359PPCInstr* PPCInstr_AvUn32Fx4 ( PPCAvFpOp op, HReg dst, HReg src ) {
cerion5b2325f2005-12-23 00:55:09 +00001360 PPCInstr* i = LibVEX_Alloc(sizeof(PPCInstr));
cerion8ea0d3e2005-11-14 00:44:47 +00001361 i->tag = Pin_AvUn32Fx4;
1362 i->Pin.AvUn32Fx4.op = op;
1363 i->Pin.AvUn32Fx4.dst = dst;
1364 i->Pin.AvUn32Fx4.src = src;
1365 return i;
1366}
cerion5b2325f2005-12-23 00:55:09 +00001367PPCInstr* PPCInstr_AvPerm ( HReg dst, HReg srcL, HReg srcR, HReg ctl ) {
1368 PPCInstr* i = LibVEX_Alloc(sizeof(PPCInstr));
cerionc3d8bdc2005-06-28 18:06:23 +00001369 i->tag = Pin_AvPerm;
cerionc3d8bdc2005-06-28 18:06:23 +00001370 i->Pin.AvPerm.dst = dst;
1371 i->Pin.AvPerm.srcL = srcL;
1372 i->Pin.AvPerm.srcR = srcR;
cerion92d9d872005-09-15 21:58:50 +00001373 i->Pin.AvPerm.ctl = ctl;
cerionc3d8bdc2005-06-28 18:06:23 +00001374 return i;
1375}
cerion5b2325f2005-12-23 00:55:09 +00001376PPCInstr* PPCInstr_AvSel ( HReg ctl, HReg dst, HReg srcL, HReg srcR ) {
1377 PPCInstr* i = LibVEX_Alloc(sizeof(PPCInstr));
cerionc3d8bdc2005-06-28 18:06:23 +00001378 i->tag = Pin_AvSel;
1379 i->Pin.AvSel.ctl = ctl;
1380 i->Pin.AvSel.dst = dst;
1381 i->Pin.AvSel.srcL = srcL;
1382 i->Pin.AvSel.srcR = srcR;
1383 return i;
1384}
cerion5b2325f2005-12-23 00:55:09 +00001385PPCInstr* PPCInstr_AvShlDbl ( UChar shift, HReg dst,
1386 HReg srcL, HReg srcR ) {
1387 PPCInstr* i = LibVEX_Alloc(sizeof(PPCInstr));
cerionc3d8bdc2005-06-28 18:06:23 +00001388 i->tag = Pin_AvShlDbl;
1389 i->Pin.AvShlDbl.shift = shift;
1390 i->Pin.AvShlDbl.dst = dst;
1391 i->Pin.AvShlDbl.srcL = srcL;
1392 i->Pin.AvShlDbl.srcR = srcR;
1393 return i;
1394}
cerion5b2325f2005-12-23 00:55:09 +00001395PPCInstr* PPCInstr_AvSplat ( UChar sz, HReg dst, PPCVI5s* src ) {
1396 PPCInstr* i = LibVEX_Alloc(sizeof(PPCInstr));
cerionc3d8bdc2005-06-28 18:06:23 +00001397 i->tag = Pin_AvSplat;
1398 i->Pin.AvSplat.sz = sz;
1399 i->Pin.AvSplat.dst = dst;
1400 i->Pin.AvSplat.src = src;
1401 return i;
1402}
cerion5b2325f2005-12-23 00:55:09 +00001403PPCInstr* PPCInstr_AvCMov ( PPCCondCode cond, HReg dst, HReg src ) {
1404 PPCInstr* i = LibVEX_Alloc(sizeof(PPCInstr));
cerion6b6f59e2005-06-28 20:59:18 +00001405 i->tag = Pin_AvCMov;
1406 i->Pin.AvCMov.cond = cond;
1407 i->Pin.AvCMov.dst = dst;
1408 i->Pin.AvCMov.src = src;
1409 vassert(cond.test != Pct_ALWAYS);
1410 return i;
1411}
cerion5b2325f2005-12-23 00:55:09 +00001412PPCInstr* PPCInstr_AvLdVSCR ( HReg src ) {
1413 PPCInstr* i = LibVEX_Alloc(sizeof(PPCInstr));
cerionc3d8bdc2005-06-28 18:06:23 +00001414 i->tag = Pin_AvLdVSCR;
1415 i->Pin.AvLdVSCR.src = src;
1416 return i;
1417}
1418
cerion9e263e32005-03-03 17:21:51 +00001419
1420/* Pretty Print instructions */
cerionf0de28c2005-12-13 20:21:11 +00001421static void ppLoadImm ( HReg dst, ULong imm, Bool mode64 ) {
cerionf0de28c2005-12-13 20:21:11 +00001422 vex_printf("li_word ");
cerion5b2325f2005-12-23 00:55:09 +00001423 ppHRegPPC(dst);
cerionf0de28c2005-12-13 20:21:11 +00001424 if (!mode64) {
cerionf0de28c2005-12-13 20:21:11 +00001425 vex_printf(",0x%08x", (UInt)imm);
1426 } else {
1427 vex_printf(",0x%016llx", imm);
1428 }
cerion9e263e32005-03-03 17:21:51 +00001429}
1430
1431static void ppMovReg ( HReg dst, HReg src ) {
1432 if (hregNumber(dst) != hregNumber(src)) {
1433 vex_printf("mr ");
cerion5b2325f2005-12-23 00:55:09 +00001434 ppHRegPPC(dst);
cerion9e263e32005-03-03 17:21:51 +00001435 vex_printf(",");
cerion5b2325f2005-12-23 00:55:09 +00001436 ppHRegPPC(src);
cerion9e263e32005-03-03 17:21:51 +00001437 }
1438}
1439
cerion5b2325f2005-12-23 00:55:09 +00001440void ppPPCInstr ( PPCInstr* i, Bool mode64 )
cerionbcf8c3e2005-02-04 16:17:07 +00001441{
1442 switch (i->tag) {
cerionf0de28c2005-12-13 20:21:11 +00001443 case Pin_LI:
1444 ppLoadImm(i->Pin.LI.dst, i->Pin.LI.imm64, mode64);
sewardjb51f0f42005-07-18 11:38:02 +00001445 break;
cerionf0de28c2005-12-13 20:21:11 +00001446 case Pin_Alu: {
cerion5b2325f2005-12-23 00:55:09 +00001447 HReg r_srcL = i->Pin.Alu.srcL;
1448 PPCRH* rh_srcR = i->Pin.Alu.srcR;
sewardjb51f0f42005-07-18 11:38:02 +00001449 /* special-case "mr" */
cerionf0de28c2005-12-13 20:21:11 +00001450 if (i->Pin.Alu.op == Palu_OR && // or Rd,Rs,Rs == mr Rd,Rs
1451 rh_srcR->tag == Prh_Reg &&
1452 rh_srcR->Prh.Reg.reg == r_srcL) {
cerionb85e8bb2005-02-16 08:54:33 +00001453 vex_printf("mr ");
cerion5b2325f2005-12-23 00:55:09 +00001454 ppHRegPPC(i->Pin.Alu.dst);
cerioncd304492005-02-08 19:40:24 +00001455 vex_printf(",");
cerion5b2325f2005-12-23 00:55:09 +00001456 ppHRegPPC(r_srcL);
cerionbb01b7c2005-12-16 13:40:18 +00001457 return;
1458 }
1459 /* special-case "li" */
1460 if (i->Pin.Alu.op == Palu_ADD && // addi Rd,0,imm == li Rd,imm
1461 rh_srcR->tag == Prh_Imm &&
1462 hregNumber(r_srcL) == 0) {
1463 vex_printf("li ");
cerion5b2325f2005-12-23 00:55:09 +00001464 ppHRegPPC(i->Pin.Alu.dst);
cerionb8c3b7f2005-03-01 20:27:49 +00001465 vex_printf(",");
cerion5b2325f2005-12-23 00:55:09 +00001466 ppPPCRH(rh_srcR);
cerionbb01b7c2005-12-16 13:40:18 +00001467 return;
cerionb8c3b7f2005-03-01 20:27:49 +00001468 }
cerionbb01b7c2005-12-16 13:40:18 +00001469 /* generic */
cerion5b2325f2005-12-23 00:55:09 +00001470 vex_printf("%s ", showPPCAluOp(i->Pin.Alu.op,
1471 toBool(rh_srcR->tag == Prh_Imm)));
1472 ppHRegPPC(i->Pin.Alu.dst);
cerionbb01b7c2005-12-16 13:40:18 +00001473 vex_printf(",");
cerion5b2325f2005-12-23 00:55:09 +00001474 ppHRegPPC(r_srcL);
cerionbb01b7c2005-12-16 13:40:18 +00001475 vex_printf(",");
cerion5b2325f2005-12-23 00:55:09 +00001476 ppPPCRH(rh_srcR);
cerionbb01b7c2005-12-16 13:40:18 +00001477 return;
1478 }
1479 case Pin_Shft: {
cerion5b2325f2005-12-23 00:55:09 +00001480 HReg r_srcL = i->Pin.Shft.srcL;
1481 PPCRH* rh_srcR = i->Pin.Shft.srcR;
1482 vex_printf("%s ", showPPCShftOp(i->Pin.Shft.op,
1483 toBool(rh_srcR->tag == Prh_Imm),
1484 i->Pin.Shft.sz32));
1485 ppHRegPPC(i->Pin.Shft.dst);
cerionbb01b7c2005-12-16 13:40:18 +00001486 vex_printf(",");
cerion5b2325f2005-12-23 00:55:09 +00001487 ppHRegPPC(r_srcL);
cerionbb01b7c2005-12-16 13:40:18 +00001488 vex_printf(",");
cerion5b2325f2005-12-23 00:55:09 +00001489 ppPPCRH(rh_srcR);
cerionb85e8bb2005-02-16 08:54:33 +00001490 return;
cerionf0de28c2005-12-13 20:21:11 +00001491 }
cerion5b2325f2005-12-23 00:55:09 +00001492 case Pin_AddSubC:
cerion4a49b032005-11-08 16:23:07 +00001493 vex_printf("%s%s ",
cerion5b2325f2005-12-23 00:55:09 +00001494 i->Pin.AddSubC.isAdd ? "add" : "sub",
1495 i->Pin.AddSubC.setC ? "c" : "e");
1496 ppHRegPPC(i->Pin.AddSubC.dst);
cerion4a49b032005-11-08 16:23:07 +00001497 vex_printf(",");
cerion5b2325f2005-12-23 00:55:09 +00001498 ppHRegPPC(i->Pin.AddSubC.srcL);
cerion4a49b032005-11-08 16:23:07 +00001499 vex_printf(",");
cerion5b2325f2005-12-23 00:55:09 +00001500 ppHRegPPC(i->Pin.AddSubC.srcR);
cerion4a49b032005-11-08 16:23:07 +00001501 return;
cerionf0de28c2005-12-13 20:21:11 +00001502 case Pin_Cmp:
cerionbb01b7c2005-12-16 13:40:18 +00001503 vex_printf("%s%c%s %%cr%u,",
cerionf0de28c2005-12-13 20:21:11 +00001504 i->Pin.Cmp.syned ? "cmp" : "cmpl",
cerionbb01b7c2005-12-16 13:40:18 +00001505 i->Pin.Cmp.sz32 ? 'w' : 'd',
cerionf0de28c2005-12-13 20:21:11 +00001506 i->Pin.Cmp.srcR->tag == Prh_Imm ? "i" : "",
1507 i->Pin.Cmp.crfD);
cerion5b2325f2005-12-23 00:55:09 +00001508 ppHRegPPC(i->Pin.Cmp.srcL);
cerionb85e8bb2005-02-16 08:54:33 +00001509 vex_printf(",");
cerion5b2325f2005-12-23 00:55:09 +00001510 ppPPCRH(i->Pin.Cmp.srcR);
cerionb85e8bb2005-02-16 08:54:33 +00001511 return;
cerionf0de28c2005-12-13 20:21:11 +00001512 case Pin_Unary:
cerion5b2325f2005-12-23 00:55:09 +00001513 vex_printf("%s ", showPPCUnaryOp(i->Pin.Unary.op));
1514 ppHRegPPC(i->Pin.Unary.dst);
cerionb85e8bb2005-02-16 08:54:33 +00001515 vex_printf(",");
cerion5b2325f2005-12-23 00:55:09 +00001516 ppHRegPPC(i->Pin.Unary.src);
cerionb85e8bb2005-02-16 08:54:33 +00001517 return;
1518 case Pin_MulL:
cerionbb01b7c2005-12-16 13:40:18 +00001519 vex_printf("mul%c%c%s ",
1520 i->Pin.MulL.hi ? 'h' : 'l',
1521 i->Pin.MulL.sz32 ? 'w' : 'd',
cerionf0de28c2005-12-13 20:21:11 +00001522 i->Pin.MulL.hi ? (i->Pin.MulL.syned ? "s" : "u") : "");
cerion5b2325f2005-12-23 00:55:09 +00001523 ppHRegPPC(i->Pin.MulL.dst);
cerionb85e8bb2005-02-16 08:54:33 +00001524 vex_printf(",");
cerion5b2325f2005-12-23 00:55:09 +00001525 ppHRegPPC(i->Pin.MulL.srcL);
cerionb85e8bb2005-02-16 08:54:33 +00001526 vex_printf(",");
cerion5b2325f2005-12-23 00:55:09 +00001527 ppHRegPPC(i->Pin.MulL.srcR);
cerionb85e8bb2005-02-16 08:54:33 +00001528 return;
1529 case Pin_Div:
sewardj4aa412a2011-07-24 14:13:21 +00001530 vex_printf("div%c%s%s ",
cerionbb01b7c2005-12-16 13:40:18 +00001531 i->Pin.Div.sz32 ? 'w' : 'd',
sewardj4aa412a2011-07-24 14:13:21 +00001532 i->Pin.Div.extended ? "e" : "",
cerionb85e8bb2005-02-16 08:54:33 +00001533 i->Pin.Div.syned ? "" : "u");
cerion5b2325f2005-12-23 00:55:09 +00001534 ppHRegPPC(i->Pin.Div.dst);
cerionb85e8bb2005-02-16 08:54:33 +00001535 vex_printf(",");
cerion5b2325f2005-12-23 00:55:09 +00001536 ppHRegPPC(i->Pin.Div.srcL);
cerionb85e8bb2005-02-16 08:54:33 +00001537 vex_printf(",");
cerion5b2325f2005-12-23 00:55:09 +00001538 ppHRegPPC(i->Pin.Div.srcR);
cerionb85e8bb2005-02-16 08:54:33 +00001539 return;
sewardj6a64a9f2005-08-21 00:48:37 +00001540 case Pin_Call: {
1541 Int n;
cerion8c51ed42005-02-22 11:16:54 +00001542 vex_printf("call: ");
1543 if (i->Pin.Call.cond.test != Pct_ALWAYS) {
cerion5b2325f2005-12-23 00:55:09 +00001544 vex_printf("if (%s) ", showPPCCondCode(i->Pin.Call.cond));
cerion8c51ed42005-02-22 11:16:54 +00001545 }
1546 vex_printf("{ ");
cerionf0de28c2005-12-13 20:21:11 +00001547 ppLoadImm(hregPPC_GPR10(mode64), i->Pin.Call.target, mode64);
1548 vex_printf(" ; mtctr r10 ; bctrl [");
sewardj6a64a9f2005-08-21 00:48:37 +00001549 for (n = 0; n < 32; n++) {
1550 if (i->Pin.Call.argiregs & (1<<n)) {
1551 vex_printf("r%d", n);
1552 if ((i->Pin.Call.argiregs >> n) > 1)
1553 vex_printf(",");
1554 }
1555 }
1556 vex_printf("] }");
cerionb85e8bb2005-02-16 08:54:33 +00001557 break;
sewardj6a64a9f2005-08-21 00:48:37 +00001558 }
sewardj3dee8492012-04-20 00:13:28 +00001559 case Pin_XDirect:
1560 vex_printf("(xDirect) ");
1561 vex_printf("if (%s) { ",
1562 showPPCCondCode(i->Pin.XDirect.cond));
1563 if (mode64) {
1564 vex_printf("imm64 r30,0x%llx; ", i->Pin.XDirect.dstGA);
1565 vex_printf("std r30,");
cerione97e1062005-02-21 15:09:19 +00001566 } else {
sewardj3dee8492012-04-20 00:13:28 +00001567 vex_printf("imm32 r30,0x%llx; ", i->Pin.XDirect.dstGA);
1568 vex_printf("stw r30,");
cerione97e1062005-02-21 15:09:19 +00001569 }
sewardj3dee8492012-04-20 00:13:28 +00001570 ppPPCAMode(i->Pin.XDirect.amCIA);
1571 vex_printf("; ");
1572 if (mode64) {
1573 vex_printf("imm64-fixed5 r30,$disp_cp_chain_me_to_%sEP; ",
1574 i->Pin.XDirect.toFastEP ? "fast" : "slow");
1575 } else {
1576 vex_printf("imm32-fixed2 r30,$disp_cp_chain_me_to_%sEP; ",
1577 i->Pin.XDirect.toFastEP ? "fast" : "slow");
1578 }
1579 vex_printf("mtctr r30; bctrl }");
1580 return;
1581 case Pin_XIndir:
1582 vex_printf("(xIndir) ");
1583 vex_printf("if (%s) { ",
1584 showPPCCondCode(i->Pin.XIndir.cond));
1585 vex_printf("%s ", mode64 ? "std" : "stw");
1586 ppHRegPPC(i->Pin.XIndir.dstGA);
1587 vex_printf(",");
1588 ppPPCAMode(i->Pin.XIndir.amCIA);
1589 vex_printf("; ");
1590 vex_printf("imm%s r30,$disp_cp_xindir; ", mode64 ? "64" : "32");
1591 vex_printf("mtctr r30; bctr }");
1592 return;
1593 case Pin_XAssisted:
1594 vex_printf("(xAssisted) ");
1595 vex_printf("if (%s) { ",
1596 showPPCCondCode(i->Pin.XAssisted.cond));
1597 vex_printf("%s ", mode64 ? "std" : "stw");
1598 ppHRegPPC(i->Pin.XAssisted.dstGA);
1599 vex_printf(",");
1600 ppPPCAMode(i->Pin.XAssisted.amCIA);
1601 vex_printf("; ");
1602 vex_printf("li r31,$IRJumpKind_to_TRCVAL(%d); ",
1603 (Int)i->Pin.XAssisted.jk);
1604 vex_printf("imm%s r30,$disp_cp_xindir; ", mode64 ? "64" : "32");
1605 vex_printf("mtctr r30; bctr }");
cerionb85e8bb2005-02-16 08:54:33 +00001606 return;
cerionf0de28c2005-12-13 20:21:11 +00001607 case Pin_CMov:
cerion5b2325f2005-12-23 00:55:09 +00001608 vex_printf("cmov (%s) ", showPPCCondCode(i->Pin.CMov.cond));
1609 ppHRegPPC(i->Pin.CMov.dst);
cerionb85e8bb2005-02-16 08:54:33 +00001610 vex_printf(",");
cerion5b2325f2005-12-23 00:55:09 +00001611 ppPPCRI(i->Pin.CMov.src);
cerion8c51ed42005-02-22 11:16:54 +00001612 vex_printf(": ");
cerionf0de28c2005-12-13 20:21:11 +00001613 if (i->Pin.CMov.cond.test != Pct_ALWAYS) {
cerion5b2325f2005-12-23 00:55:09 +00001614 vex_printf("if (%s) ", showPPCCondCode(i->Pin.CMov.cond));
cerion8c51ed42005-02-22 11:16:54 +00001615 }
1616 vex_printf("{ ");
cerionf0de28c2005-12-13 20:21:11 +00001617 if (i->Pin.CMov.src->tag == Pri_Imm) {
1618 ppLoadImm(i->Pin.CMov.dst, i->Pin.CMov.src->Pri.Imm, mode64);
cerion8c51ed42005-02-22 11:16:54 +00001619 } else {
cerionf0de28c2005-12-13 20:21:11 +00001620 ppMovReg(i->Pin.CMov.dst, i->Pin.CMov.src->Pri.Reg);
cerion8c51ed42005-02-22 11:16:54 +00001621 }
1622 vex_printf(" }");
cerionb85e8bb2005-02-16 08:54:33 +00001623 return;
cerion7cf8e4e2005-02-16 16:08:17 +00001624 case Pin_Load: {
sewardj428fabd2005-03-21 03:11:17 +00001625 Bool idxd = toBool(i->Pin.Load.src->tag == Pam_RR);
cerionf0de28c2005-12-13 20:21:11 +00001626 UChar sz = i->Pin.Load.sz;
florian5df8ab02012-10-13 19:34:19 +00001627 HChar c_sz = sz==1 ? 'b' : sz==2 ? 'h' : sz==4 ? 'w' : 'd';
sewardj34085e32007-03-09 18:07:00 +00001628 vex_printf("l%c%s%s ", c_sz, sz==8 ? "" : "z", idxd ? "x" : "" );
cerion5b2325f2005-12-23 00:55:09 +00001629 ppHRegPPC(i->Pin.Load.dst);
cerionb85e8bb2005-02-16 08:54:33 +00001630 vex_printf(",");
cerion5b2325f2005-12-23 00:55:09 +00001631 ppPPCAMode(i->Pin.Load.src);
cerionb85e8bb2005-02-16 08:54:33 +00001632 return;
1633 }
sewardje9d8a262009-07-01 08:06:34 +00001634 case Pin_LoadL:
1635 vex_printf("l%carx ", i->Pin.LoadL.sz==4 ? 'w' : 'd');
1636 ppHRegPPC(i->Pin.LoadL.dst);
1637 vex_printf(",%%r0,");
1638 ppHRegPPC(i->Pin.LoadL.src);
1639 return;
cerionb85e8bb2005-02-16 08:54:33 +00001640 case Pin_Store: {
1641 UChar sz = i->Pin.Store.sz;
sewardj428fabd2005-03-21 03:11:17 +00001642 Bool idxd = toBool(i->Pin.Store.dst->tag == Pam_RR);
florian5df8ab02012-10-13 19:34:19 +00001643 HChar c_sz = sz==1 ? 'b' : sz==2 ? 'h' : sz==4 ? 'w' : /*8*/ 'd';
cerionf0de28c2005-12-13 20:21:11 +00001644 vex_printf("st%c%s ", c_sz, idxd ? "x" : "" );
cerion5b2325f2005-12-23 00:55:09 +00001645 ppHRegPPC(i->Pin.Store.src);
cerionb85e8bb2005-02-16 08:54:33 +00001646 vex_printf(",");
cerion5b2325f2005-12-23 00:55:09 +00001647 ppPPCAMode(i->Pin.Store.dst);
cerionb85e8bb2005-02-16 08:54:33 +00001648 return;
1649 }
sewardje9d8a262009-07-01 08:06:34 +00001650 case Pin_StoreC:
1651 vex_printf("st%ccx. ", i->Pin.StoreC.sz==4 ? 'w' : 'd');
1652 ppHRegPPC(i->Pin.StoreC.src);
1653 vex_printf(",%%r0,");
1654 ppHRegPPC(i->Pin.StoreC.dst);
1655 return;
cerion5b2325f2005-12-23 00:55:09 +00001656 case Pin_Set: {
1657 PPCCondCode cc = i->Pin.Set.cond;
1658 vex_printf("set (%s),", showPPCCondCode(cc));
1659 ppHRegPPC(i->Pin.Set.dst);
cerionf9d6e222005-02-23 18:21:31 +00001660 if (cc.test == Pct_ALWAYS) {
1661 vex_printf(": { li ");
cerion5b2325f2005-12-23 00:55:09 +00001662 ppHRegPPC(i->Pin.Set.dst);
cerionf9d6e222005-02-23 18:21:31 +00001663 vex_printf(",1 }");
1664 } else {
1665 vex_printf(": { mfcr r0 ; rlwinm ");
cerion5b2325f2005-12-23 00:55:09 +00001666 ppHRegPPC(i->Pin.Set.dst);
sewardj428fabd2005-03-21 03:11:17 +00001667 vex_printf(",r0,%u,31,31", cc.flag+1);
cerionf9d6e222005-02-23 18:21:31 +00001668 if (cc.test == Pct_FALSE) {
1669 vex_printf("; xori ");
cerion5b2325f2005-12-23 00:55:09 +00001670 ppHRegPPC(i->Pin.Set.dst);
cerionf9d6e222005-02-23 18:21:31 +00001671 vex_printf(",");
cerion5b2325f2005-12-23 00:55:09 +00001672 ppHRegPPC(i->Pin.Set.dst);
sewardjf7745052005-12-16 01:06:42 +00001673 vex_printf(",1");
cerionf9d6e222005-02-23 18:21:31 +00001674 }
1675 vex_printf(" }");
1676 }
cerionb85e8bb2005-02-16 08:54:33 +00001677 return;
cerionf9d6e222005-02-23 18:21:31 +00001678 }
sewardjb51f0f42005-07-18 11:38:02 +00001679 case Pin_MfCR:
1680 vex_printf("mfcr ");
cerion5b2325f2005-12-23 00:55:09 +00001681 ppHRegPPC(i->Pin.MfCR.dst);
sewardjb51f0f42005-07-18 11:38:02 +00001682 break;
cerionb85e8bb2005-02-16 08:54:33 +00001683 case Pin_MFence:
cerion98411db2005-02-16 14:14:49 +00001684 vex_printf("mfence (=sync)");
cerionb85e8bb2005-02-16 08:54:33 +00001685 return;
cerion094d1392005-06-20 13:45:57 +00001686
1687 case Pin_FpUnary:
cerion5b2325f2005-12-23 00:55:09 +00001688 vex_printf("%s ", showPPCFpOp(i->Pin.FpUnary.op));
1689 ppHRegPPC(i->Pin.FpUnary.dst);
cerion094d1392005-06-20 13:45:57 +00001690 vex_printf(",");
cerion5b2325f2005-12-23 00:55:09 +00001691 ppHRegPPC(i->Pin.FpUnary.src);
cerion094d1392005-06-20 13:45:57 +00001692 return;
1693 case Pin_FpBinary:
cerion5b2325f2005-12-23 00:55:09 +00001694 vex_printf("%s ", showPPCFpOp(i->Pin.FpBinary.op));
1695 ppHRegPPC(i->Pin.FpBinary.dst);
cerion094d1392005-06-20 13:45:57 +00001696 vex_printf(",");
cerion5b2325f2005-12-23 00:55:09 +00001697 ppHRegPPC(i->Pin.FpBinary.srcL);
cerion094d1392005-06-20 13:45:57 +00001698 vex_printf(",");
cerion5b2325f2005-12-23 00:55:09 +00001699 ppHRegPPC(i->Pin.FpBinary.srcR);
cerion094d1392005-06-20 13:45:57 +00001700 return;
sewardj40c80262006-02-08 19:30:46 +00001701 case Pin_FpMulAcc:
1702 vex_printf("%s ", showPPCFpOp(i->Pin.FpMulAcc.op));
1703 ppHRegPPC(i->Pin.FpMulAcc.dst);
1704 vex_printf(",");
1705 ppHRegPPC(i->Pin.FpMulAcc.srcML);
1706 vex_printf(",");
1707 ppHRegPPC(i->Pin.FpMulAcc.srcMR);
1708 vex_printf(",");
1709 ppHRegPPC(i->Pin.FpMulAcc.srcAcc);
1710 return;
cerion094d1392005-06-20 13:45:57 +00001711 case Pin_FpLdSt: {
1712 UChar sz = i->Pin.FpLdSt.sz;
1713 Bool idxd = toBool(i->Pin.FpLdSt.addr->tag == Pam_RR);
1714 if (i->Pin.FpLdSt.isLoad) {
1715 vex_printf("lf%c%s ",
1716 (sz==4 ? 's' : 'd'),
1717 idxd ? "x" : "" );
cerion5b2325f2005-12-23 00:55:09 +00001718 ppHRegPPC(i->Pin.FpLdSt.reg);
cerion094d1392005-06-20 13:45:57 +00001719 vex_printf(",");
cerion5b2325f2005-12-23 00:55:09 +00001720 ppPPCAMode(i->Pin.FpLdSt.addr);
cerion094d1392005-06-20 13:45:57 +00001721 } else {
1722 vex_printf("stf%c%s ",
1723 (sz==4 ? 's' : 'd'),
1724 idxd ? "x" : "" );
cerion5b2325f2005-12-23 00:55:09 +00001725 ppHRegPPC(i->Pin.FpLdSt.reg);
cerion094d1392005-06-20 13:45:57 +00001726 vex_printf(",");
cerion5b2325f2005-12-23 00:55:09 +00001727 ppPPCAMode(i->Pin.FpLdSt.addr);
cerion094d1392005-06-20 13:45:57 +00001728 }
1729 return;
1730 }
sewardj92923de2006-01-25 21:29:48 +00001731 case Pin_FpSTFIW:
1732 vex_printf("stfiwz ");
1733 ppHRegPPC(i->Pin.FpSTFIW.data);
1734 vex_printf(",0(");
1735 ppHRegPPC(i->Pin.FpSTFIW.addr);
1736 vex_printf(")");
1737 return;
1738 case Pin_FpRSP:
cerion094d1392005-06-20 13:45:57 +00001739 vex_printf("frsp ");
sewardj92923de2006-01-25 21:29:48 +00001740 ppHRegPPC(i->Pin.FpRSP.dst);
cerion094d1392005-06-20 13:45:57 +00001741 vex_printf(",");
sewardj92923de2006-01-25 21:29:48 +00001742 ppHRegPPC(i->Pin.FpRSP.src);
cerion094d1392005-06-20 13:45:57 +00001743 return;
sewardj92923de2006-01-25 21:29:48 +00001744 case Pin_FpCftI: {
florian55085f82012-11-21 00:36:55 +00001745 const HChar* str = "fc?????";
sewardj4aa412a2011-07-24 14:13:21 +00001746 /* Note that "fcfids" is missing from below. That instruction would
1747 * satisfy the predicate:
1748 * (i->Pin.FpCftI.fromI == True && i->Pin.FpCftI.int32 == False)
1749 * which would go into a final "else" clause to make this if-else
1750 * block balanced. But we're able to implement fcfids by leveraging
1751 * the fcfid implementation, so it wasn't necessary to include it here.
1752 */
sewardj92923de2006-01-25 21:29:48 +00001753 if (i->Pin.FpCftI.fromI == False && i->Pin.FpCftI.int32 == False)
sewardj66d5ef22011-04-15 11:55:00 +00001754 if (i->Pin.FpCftI.syned == True)
sewardj4aa412a2011-07-24 14:13:21 +00001755 str = "fctid";
sewardj66d5ef22011-04-15 11:55:00 +00001756 else
sewardj4aa412a2011-07-24 14:13:21 +00001757 str = "fctidu";
1758 else if (i->Pin.FpCftI.fromI == False && i->Pin.FpCftI.int32 == True)
1759 if (i->Pin.FpCftI.syned == True)
1760 str = "fctiw";
1761 else
1762 str = "fctiwu";
1763 else if (i->Pin.FpCftI.fromI == True && i->Pin.FpCftI.int32 == False) {
1764 if (i->Pin.FpCftI.syned == True) {
1765 str = "fcfid";
1766 } else {
1767 if (i->Pin.FpCftI.flt64 == True)
1768 str = "fcfidu";
1769 else
1770 str = "fcfidus";
1771 }
sewardj66d5ef22011-04-15 11:55:00 +00001772 }
sewardj92923de2006-01-25 21:29:48 +00001773 vex_printf("%s ", str);
1774 ppHRegPPC(i->Pin.FpCftI.dst);
1775 vex_printf(",");
1776 ppHRegPPC(i->Pin.FpCftI.src);
cerion094d1392005-06-20 13:45:57 +00001777 return;
sewardj92923de2006-01-25 21:29:48 +00001778 }
cerion094d1392005-06-20 13:45:57 +00001779 case Pin_FpCMov:
cerion5b2325f2005-12-23 00:55:09 +00001780 vex_printf("fpcmov (%s) ", showPPCCondCode(i->Pin.FpCMov.cond));
1781 ppHRegPPC(i->Pin.FpCMov.dst);
cerion094d1392005-06-20 13:45:57 +00001782 vex_printf(",");
cerion5b2325f2005-12-23 00:55:09 +00001783 ppHRegPPC(i->Pin.FpCMov.src);
cerion094d1392005-06-20 13:45:57 +00001784 vex_printf(": ");
1785 vex_printf("if (fr_dst != fr_src) { ");
1786 if (i->Pin.FpCMov.cond.test != Pct_ALWAYS) {
cerion5b2325f2005-12-23 00:55:09 +00001787 vex_printf("if (%s) { ", showPPCCondCode(i->Pin.FpCMov.cond));
cerion094d1392005-06-20 13:45:57 +00001788 }
1789 vex_printf("fmr ");
cerion5b2325f2005-12-23 00:55:09 +00001790 ppHRegPPC(i->Pin.FpCMov.dst);
cerion094d1392005-06-20 13:45:57 +00001791 vex_printf(",");
cerion5b2325f2005-12-23 00:55:09 +00001792 ppHRegPPC(i->Pin.FpCMov.src);
cerion094d1392005-06-20 13:45:57 +00001793 if (i->Pin.FpCMov.cond.test != Pct_ALWAYS)
1794 vex_printf(" }");
1795 vex_printf(" }");
1796 return;
1797 case Pin_FpLdFPSCR:
1798 vex_printf("mtfsf 0xFF,");
cerion5b2325f2005-12-23 00:55:09 +00001799 ppHRegPPC(i->Pin.FpLdFPSCR.src);
sewardjc6bbd472012-04-02 10:20:48 +00001800 vex_printf(",0, %s", i->Pin.FpLdFPSCR.dfp_rm ? "1" : "0");
cerion094d1392005-06-20 13:45:57 +00001801 return;
1802 case Pin_FpCmp:
sewardjb51f0f42005-07-18 11:38:02 +00001803 vex_printf("fcmpo %%cr1,");
cerion5b2325f2005-12-23 00:55:09 +00001804 ppHRegPPC(i->Pin.FpCmp.srcL);
cerion094d1392005-06-20 13:45:57 +00001805 vex_printf(",");
cerion5b2325f2005-12-23 00:55:09 +00001806 ppHRegPPC(i->Pin.FpCmp.srcR);
cerion094d1392005-06-20 13:45:57 +00001807 vex_printf("; mfcr ");
cerion5b2325f2005-12-23 00:55:09 +00001808 ppHRegPPC(i->Pin.FpCmp.dst);
cerion094d1392005-06-20 13:45:57 +00001809 vex_printf("; rlwinm ");
cerion5b2325f2005-12-23 00:55:09 +00001810 ppHRegPPC(i->Pin.FpCmp.dst);
cerion094d1392005-06-20 13:45:57 +00001811 vex_printf(",");
cerion5b2325f2005-12-23 00:55:09 +00001812 ppHRegPPC(i->Pin.FpCmp.dst);
cerion094d1392005-06-20 13:45:57 +00001813 vex_printf(",8,28,31");
1814 return;
cerionbcf8c3e2005-02-04 16:17:07 +00001815
cerion7f000af2005-02-22 20:36:49 +00001816 case Pin_RdWrLR:
1817 vex_printf("%s ", i->Pin.RdWrLR.wrLR ? "mtlr" : "mflr");
cerion5b2325f2005-12-23 00:55:09 +00001818 ppHRegPPC(i->Pin.RdWrLR.gpr);
cerion7f000af2005-02-22 20:36:49 +00001819 return;
1820
cerionc3d8bdc2005-06-28 18:06:23 +00001821 case Pin_AvLdSt: {
sewardj197bd172005-10-12 11:34:33 +00001822 UChar sz = i->Pin.AvLdSt.sz;
florian55085f82012-11-21 00:36:55 +00001823 const HChar* str_size;
cerionc3d8bdc2005-06-28 18:06:23 +00001824 if (i->Pin.AvLdSt.addr->tag == Pam_IR) {
cerionf0de28c2005-12-13 20:21:11 +00001825 ppLoadImm(hregPPC_GPR30(mode64),
1826 i->Pin.AvLdSt.addr->Pam.RR.index, mode64);
cerion01713102005-06-29 19:05:08 +00001827 vex_printf(" ; ");
cerionc3d8bdc2005-06-28 18:06:23 +00001828 }
sewardj197bd172005-10-12 11:34:33 +00001829 str_size = sz==1 ? "eb" : sz==2 ? "eh" : sz==4 ? "ew" : "";
cerion01713102005-06-29 19:05:08 +00001830 if (i->Pin.AvLdSt.isLoad)
cerion225a0342005-09-12 20:49:09 +00001831 vex_printf("lv%sx ", str_size);
cerion01713102005-06-29 19:05:08 +00001832 else
cerion225a0342005-09-12 20:49:09 +00001833 vex_printf("stv%sx ", str_size);
cerion5b2325f2005-12-23 00:55:09 +00001834 ppHRegPPC(i->Pin.AvLdSt.reg);
cerion01713102005-06-29 19:05:08 +00001835 vex_printf(",");
1836 if (i->Pin.AvLdSt.addr->tag == Pam_IR)
1837 vex_printf("%%r30");
1838 else
cerion5b2325f2005-12-23 00:55:09 +00001839 ppHRegPPC(i->Pin.AvLdSt.addr->Pam.RR.index);
cerion01713102005-06-29 19:05:08 +00001840 vex_printf(",");
cerion5b2325f2005-12-23 00:55:09 +00001841 ppHRegPPC(i->Pin.AvLdSt.addr->Pam.RR.base);
cerionc3d8bdc2005-06-28 18:06:23 +00001842 return;
1843 }
1844 case Pin_AvUnary:
cerion5b2325f2005-12-23 00:55:09 +00001845 vex_printf("%s ", showPPCAvOp(i->Pin.AvUnary.op));
1846 ppHRegPPC(i->Pin.AvUnary.dst);
cerionc3d8bdc2005-06-28 18:06:23 +00001847 vex_printf(",");
cerion5b2325f2005-12-23 00:55:09 +00001848 ppHRegPPC(i->Pin.AvUnary.src);
cerionc3d8bdc2005-06-28 18:06:23 +00001849 return;
1850 case Pin_AvBinary:
cerion5b2325f2005-12-23 00:55:09 +00001851 vex_printf("%s ", showPPCAvOp(i->Pin.AvBinary.op));
1852 ppHRegPPC(i->Pin.AvBinary.dst);
cerionc3d8bdc2005-06-28 18:06:23 +00001853 vex_printf(",");
cerion5b2325f2005-12-23 00:55:09 +00001854 ppHRegPPC(i->Pin.AvBinary.srcL);
cerionc3d8bdc2005-06-28 18:06:23 +00001855 vex_printf(",");
cerion5b2325f2005-12-23 00:55:09 +00001856 ppHRegPPC(i->Pin.AvBinary.srcR);
cerionc3d8bdc2005-06-28 18:06:23 +00001857 return;
cerion6b6f59e2005-06-28 20:59:18 +00001858 case Pin_AvBin8x16:
cerion5b2325f2005-12-23 00:55:09 +00001859 vex_printf("%s(b) ", showPPCAvOp(i->Pin.AvBin8x16.op));
1860 ppHRegPPC(i->Pin.AvBin8x16.dst);
cerion6b6f59e2005-06-28 20:59:18 +00001861 vex_printf(",");
cerion5b2325f2005-12-23 00:55:09 +00001862 ppHRegPPC(i->Pin.AvBin8x16.srcL);
cerion6b6f59e2005-06-28 20:59:18 +00001863 vex_printf(",");
cerion5b2325f2005-12-23 00:55:09 +00001864 ppHRegPPC(i->Pin.AvBin8x16.srcR);
cerion6b6f59e2005-06-28 20:59:18 +00001865 return;
1866 case Pin_AvBin16x8:
cerion5b2325f2005-12-23 00:55:09 +00001867 vex_printf("%s(h) ", showPPCAvOp(i->Pin.AvBin16x8.op));
1868 ppHRegPPC(i->Pin.AvBin16x8.dst);
cerion6b6f59e2005-06-28 20:59:18 +00001869 vex_printf(",");
cerion5b2325f2005-12-23 00:55:09 +00001870 ppHRegPPC(i->Pin.AvBin16x8.srcL);
cerion6b6f59e2005-06-28 20:59:18 +00001871 vex_printf(",");
cerion5b2325f2005-12-23 00:55:09 +00001872 ppHRegPPC(i->Pin.AvBin16x8.srcR);
cerion6b6f59e2005-06-28 20:59:18 +00001873 return;
1874 case Pin_AvBin32x4:
cerion5b2325f2005-12-23 00:55:09 +00001875 vex_printf("%s(w) ", showPPCAvOp(i->Pin.AvBin32x4.op));
1876 ppHRegPPC(i->Pin.AvBin32x4.dst);
cerion6b6f59e2005-06-28 20:59:18 +00001877 vex_printf(",");
cerion5b2325f2005-12-23 00:55:09 +00001878 ppHRegPPC(i->Pin.AvBin32x4.srcL);
cerion6b6f59e2005-06-28 20:59:18 +00001879 vex_printf(",");
cerion5b2325f2005-12-23 00:55:09 +00001880 ppHRegPPC(i->Pin.AvBin32x4.srcR);
cerion6b6f59e2005-06-28 20:59:18 +00001881 return;
1882 case Pin_AvBin32Fx4:
cerion5b2325f2005-12-23 00:55:09 +00001883 vex_printf("%s ", showPPCAvFpOp(i->Pin.AvBin32Fx4.op));
1884 ppHRegPPC(i->Pin.AvBin32Fx4.dst);
cerion6b6f59e2005-06-28 20:59:18 +00001885 vex_printf(",");
cerion5b2325f2005-12-23 00:55:09 +00001886 ppHRegPPC(i->Pin.AvBin32Fx4.srcL);
cerion6b6f59e2005-06-28 20:59:18 +00001887 vex_printf(",");
cerion5b2325f2005-12-23 00:55:09 +00001888 ppHRegPPC(i->Pin.AvBin32Fx4.srcR);
cerion6b6f59e2005-06-28 20:59:18 +00001889 return;
cerion8ea0d3e2005-11-14 00:44:47 +00001890 case Pin_AvUn32Fx4:
cerion5b2325f2005-12-23 00:55:09 +00001891 vex_printf("%s ", showPPCAvFpOp(i->Pin.AvUn32Fx4.op));
1892 ppHRegPPC(i->Pin.AvUn32Fx4.dst);
cerion8ea0d3e2005-11-14 00:44:47 +00001893 vex_printf(",");
cerion5b2325f2005-12-23 00:55:09 +00001894 ppHRegPPC(i->Pin.AvUn32Fx4.src);
cerion8ea0d3e2005-11-14 00:44:47 +00001895 return;
cerionc3d8bdc2005-06-28 18:06:23 +00001896 case Pin_AvPerm:
1897 vex_printf("vperm ");
cerion5b2325f2005-12-23 00:55:09 +00001898 ppHRegPPC(i->Pin.AvPerm.dst);
cerionc3d8bdc2005-06-28 18:06:23 +00001899 vex_printf(",");
cerion5b2325f2005-12-23 00:55:09 +00001900 ppHRegPPC(i->Pin.AvPerm.srcL);
cerionc3d8bdc2005-06-28 18:06:23 +00001901 vex_printf(",");
cerion5b2325f2005-12-23 00:55:09 +00001902 ppHRegPPC(i->Pin.AvPerm.srcR);
cerionc3d8bdc2005-06-28 18:06:23 +00001903 vex_printf(",");
cerion5b2325f2005-12-23 00:55:09 +00001904 ppHRegPPC(i->Pin.AvPerm.ctl);
cerionc3d8bdc2005-06-28 18:06:23 +00001905 return;
1906
1907 case Pin_AvSel:
1908 vex_printf("vsel ");
cerion5b2325f2005-12-23 00:55:09 +00001909 ppHRegPPC(i->Pin.AvSel.dst);
cerionc3d8bdc2005-06-28 18:06:23 +00001910 vex_printf(",");
cerion5b2325f2005-12-23 00:55:09 +00001911 ppHRegPPC(i->Pin.AvSel.srcL);
cerionc3d8bdc2005-06-28 18:06:23 +00001912 vex_printf(",");
cerion5b2325f2005-12-23 00:55:09 +00001913 ppHRegPPC(i->Pin.AvSel.srcR);
cerionc3d8bdc2005-06-28 18:06:23 +00001914 vex_printf(",");
cerion5b2325f2005-12-23 00:55:09 +00001915 ppHRegPPC(i->Pin.AvSel.ctl);
cerionc3d8bdc2005-06-28 18:06:23 +00001916 return;
1917
1918 case Pin_AvShlDbl:
1919 vex_printf("vsldoi ");
cerion5b2325f2005-12-23 00:55:09 +00001920 ppHRegPPC(i->Pin.AvShlDbl.dst);
cerionc3d8bdc2005-06-28 18:06:23 +00001921 vex_printf(",");
cerion5b2325f2005-12-23 00:55:09 +00001922 ppHRegPPC(i->Pin.AvShlDbl.srcL);
cerionc3d8bdc2005-06-28 18:06:23 +00001923 vex_printf(",");
cerion5b2325f2005-12-23 00:55:09 +00001924 ppHRegPPC(i->Pin.AvShlDbl.srcR);
sewardjdb36c0f2005-07-03 00:05:31 +00001925 vex_printf(",%d", i->Pin.AvShlDbl.shift);
cerionc3d8bdc2005-06-28 18:06:23 +00001926 return;
1927
1928 case Pin_AvSplat: {
cerion27b3d7e2005-09-14 20:35:47 +00001929 UChar sz = i->Pin.AvSplat.sz;
florian5df8ab02012-10-13 19:34:19 +00001930 HChar ch_sz = toUChar( (sz == 8) ? 'b' : (sz == 16) ? 'h' : 'w' );
cerionc3d8bdc2005-06-28 18:06:23 +00001931 vex_printf("vsplt%s%c ",
cerion27b3d7e2005-09-14 20:35:47 +00001932 i->Pin.AvSplat.src->tag == Pvi_Imm ? "is" : "", ch_sz);
cerion5b2325f2005-12-23 00:55:09 +00001933 ppHRegPPC(i->Pin.AvSplat.dst);
cerionc3d8bdc2005-06-28 18:06:23 +00001934 vex_printf(",");
cerion5b2325f2005-12-23 00:55:09 +00001935 ppPPCVI5s(i->Pin.AvSplat.src);
cerion27b3d7e2005-09-14 20:35:47 +00001936 if (i->Pin.AvSplat.src->tag == Pvi_Reg)
sewardj62d05432005-10-29 22:30:47 +00001937 vex_printf(", %d", (128/sz)-1); /* louis lane */
cerionc3d8bdc2005-06-28 18:06:23 +00001938 return;
1939 }
1940
cerion6b6f59e2005-06-28 20:59:18 +00001941 case Pin_AvCMov:
cerion5b2325f2005-12-23 00:55:09 +00001942 vex_printf("avcmov (%s) ", showPPCCondCode(i->Pin.AvCMov.cond));
1943 ppHRegPPC(i->Pin.AvCMov.dst);
cerion6b6f59e2005-06-28 20:59:18 +00001944 vex_printf(",");
cerion5b2325f2005-12-23 00:55:09 +00001945 ppHRegPPC(i->Pin.AvCMov.src);
cerion6b6f59e2005-06-28 20:59:18 +00001946 vex_printf(": ");
1947 vex_printf("if (v_dst != v_src) { ");
1948 if (i->Pin.AvCMov.cond.test != Pct_ALWAYS) {
cerion5b2325f2005-12-23 00:55:09 +00001949 vex_printf("if (%s) { ", showPPCCondCode(i->Pin.AvCMov.cond));
cerion6b6f59e2005-06-28 20:59:18 +00001950 }
1951 vex_printf("vmr ");
cerion5b2325f2005-12-23 00:55:09 +00001952 ppHRegPPC(i->Pin.AvCMov.dst);
cerion6b6f59e2005-06-28 20:59:18 +00001953 vex_printf(",");
cerion5b2325f2005-12-23 00:55:09 +00001954 ppHRegPPC(i->Pin.AvCMov.src);
cerion6b6f59e2005-06-28 20:59:18 +00001955 if (i->Pin.FpCMov.cond.test != Pct_ALWAYS)
1956 vex_printf(" }");
1957 vex_printf(" }");
1958 return;
1959
cerionc3d8bdc2005-06-28 18:06:23 +00001960 case Pin_AvLdVSCR:
1961 vex_printf("mtvscr ");
cerion5b2325f2005-12-23 00:55:09 +00001962 ppHRegPPC(i->Pin.AvLdVSCR.src);
cerionc3d8bdc2005-06-28 18:06:23 +00001963 return;
1964
sewardjc6bbd472012-04-02 10:20:48 +00001965 case Pin_Dfp64Unary:
1966 vex_printf("%s ", showPPCFpOp(i->Pin.Dfp64Unary.op));
1967 ppHRegPPC(i->Pin.Dfp64Unary.dst);
1968 vex_printf(",");
1969 ppHRegPPC(i->Pin.Dfp64Unary.src);
1970 return;
1971
1972 case Pin_Dfp64Binary:
1973 vex_printf("%s ", showPPCFpOp(i->Pin.Dfp64Binary.op));
1974 ppHRegPPC(i->Pin.Dfp64Binary.dst);
1975 vex_printf(",");
1976 ppHRegPPC(i->Pin.Dfp64Binary.srcL);
1977 vex_printf(",");
1978 ppHRegPPC(i->Pin.Dfp64Binary.srcR);
1979 return;
1980
sewardj26217b02012-04-12 17:19:48 +00001981 case Pin_DfpShift:
1982 vex_printf("%s ", showPPCFpOp(i->Pin.DfpShift.op));
1983 ppHRegPPC(i->Pin.DfpShift.dst);
1984 vex_printf(",");
1985 ppHRegPPC(i->Pin.DfpShift.src);
1986 vex_printf(",");
1987 ppPPCRI(i->Pin.DfpShift.shift);
1988 return;
1989
1990 case Pin_Dfp128Unary:
1991 vex_printf("%s ", showPPCFpOp(i->Pin.Dfp128Unary.op));
1992 ppHRegPPC(i->Pin.Dfp128Unary.dst_hi);
1993 vex_printf(",");
1994 ppHRegPPC(i->Pin.Dfp128Unary.src_hi);
1995 return;
1996
sewardjc6bbd472012-04-02 10:20:48 +00001997 case Pin_Dfp128Binary:
1998 vex_printf("%s ", showPPCFpOp(i->Pin.Dfp128Binary.op));
1999 ppHRegPPC(i->Pin.Dfp128Binary.dst_hi);
2000 vex_printf(",");
2001 ppHRegPPC(i->Pin.Dfp128Binary.srcR_hi);
2002 return;
2003
sewardj26217b02012-04-12 17:19:48 +00002004 case Pin_DfpShift128:
2005 vex_printf("%s ", showPPCFpOp(i->Pin.DfpShift128.op));
2006 ppHRegPPC(i->Pin.DfpShift128.dst_hi);
2007 vex_printf(",");
2008 ppHRegPPC(i->Pin.DfpShift128.src_hi);
2009 vex_printf(",");
2010 ppPPCRI(i->Pin.DfpShift128.shift);
2011 return;
2012
sewardjcdc376d2012-04-23 11:21:12 +00002013 case Pin_DfpRound:
2014 vex_printf("drintx ");
2015 ppHRegPPC(i->Pin.DfpRound.dst);
2016 vex_printf(",");
2017 ppHRegPPC(i->Pin.DfpRound.src);
2018 vex_printf(",");
2019 ppPPCRI(i->Pin.DfpRound.r_rmc); /* R in bit 3 and RMC in bits 2:0 */
2020 return;
2021
2022 case Pin_DfpRound128:
2023 vex_printf("drintxq ");
2024 ppHRegPPC(i->Pin.DfpRound128.dst_hi);
2025 vex_printf(",");
2026 ppHRegPPC(i->Pin.DfpRound128.src_hi);
2027 vex_printf(",");
2028 ppPPCRI(i->Pin.DfpRound128.r_rmc); /* R in bit 3 and RMC in bits 2:0 */
2029 return;
2030
2031 case Pin_DfpQuantize:
2032 vex_printf("%s ", showPPCFpOp(i->Pin.DfpQuantize.op));
2033 ppHRegPPC(i->Pin.DfpQuantize.dst);
2034 vex_printf(",");
2035 ppHRegPPC(i->Pin.DfpQuantize.srcL);
2036 vex_printf(",");
2037 ppHRegPPC(i->Pin.DfpQuantize.srcR);
2038 vex_printf(",");
2039 ppPPCRI(i->Pin.DfpQuantize.rmc);
2040 return;
2041
2042 case Pin_DfpQuantize128:
2043 /* Dst is used to pass in left source and return result */
2044 vex_printf("dquaq ");
2045 ppHRegPPC(i->Pin.DfpQuantize128.dst_hi);
2046 vex_printf(",");
2047 ppHRegPPC(i->Pin.DfpQuantize128.dst_hi);
2048 vex_printf(",");
2049 ppHRegPPC(i->Pin.DfpQuantize128.src_hi);
2050 vex_printf(",");
2051 ppPPCRI(i->Pin.DfpQuantize128.rmc);
2052 return;
2053
sewardj26217b02012-04-12 17:19:48 +00002054 case Pin_DfpD128toD64:
2055 vex_printf("%s ", showPPCFpOp(i->Pin.DfpD128toD64.op));
2056 ppHRegPPC(i->Pin.DfpD128toD64.dst);
2057 vex_printf(",");
2058 ppHRegPPC(i->Pin.DfpD128toD64.src_hi);
2059 vex_printf(",");
2060 return;
2061
2062 case Pin_DfpI64StoD128:
2063 vex_printf("%s ", showPPCFpOp(i->Pin.DfpI64StoD128.op));
2064 ppHRegPPC(i->Pin.DfpI64StoD128.dst_hi);
2065 vex_printf(",");
2066 ppHRegPPC(i->Pin.DfpI64StoD128.src);
2067 vex_printf(",");
2068 return;
sewardjcdc376d2012-04-23 11:21:12 +00002069 case Pin_ExtractExpD128:
2070 vex_printf("dxexq ");
2071 ppHRegPPC(i->Pin.ExtractExpD128.dst);
2072 vex_printf(",");
2073 ppHRegPPC(i->Pin.ExtractExpD128.src_hi);
2074 return;
2075 case Pin_InsertExpD128:
2076 vex_printf("diexq ");
2077 ppHRegPPC(i->Pin.InsertExpD128.dst_hi);
2078 vex_printf(",");
2079 ppHRegPPC(i->Pin.InsertExpD128.srcL);
2080 vex_printf(",");
2081 ppHRegPPC(i->Pin.InsertExpD128.srcR_hi);
2082 return;
2083 case Pin_Dfp64Cmp:
2084 vex_printf("dcmpo %%cr1,");
2085 ppHRegPPC(i->Pin.Dfp64Cmp.srcL);
2086 vex_printf(",");
2087 ppHRegPPC(i->Pin.Dfp64Cmp.srcR);
2088 vex_printf("; mfcr ");
2089 ppHRegPPC(i->Pin.Dfp64Cmp.dst);
2090 vex_printf("; rlwinm ");
2091 ppHRegPPC(i->Pin.Dfp64Cmp.dst);
2092 vex_printf(",");
2093 ppHRegPPC(i->Pin.Dfp64Cmp.dst);
2094 vex_printf(",8,28,31");
2095 return;
2096 case Pin_Dfp128Cmp:
2097 vex_printf("dcmpoq %%cr1,");
2098 ppHRegPPC(i->Pin.Dfp128Cmp.srcL_hi);
2099 vex_printf(",");
2100 ppHRegPPC(i->Pin.Dfp128Cmp.srcR_hi);
2101 vex_printf("; mfcr ");
2102 ppHRegPPC(i->Pin.Dfp128Cmp.dst);
2103 vex_printf("; rlwinm ");
2104 ppHRegPPC(i->Pin.Dfp128Cmp.dst);
2105 vex_printf(",");
2106 ppHRegPPC(i->Pin.Dfp128Cmp.dst);
2107 vex_printf(",8,28,31");
2108 return;
sewardj3dee8492012-04-20 00:13:28 +00002109 case Pin_EvCheck:
2110 /* Note that the counter dec is 32 bit even in 64-bit mode. */
2111 vex_printf("(evCheck) ");
2112 vex_printf("lwz r30,");
2113 ppPPCAMode(i->Pin.EvCheck.amCounter);
2114 vex_printf("; addic. r30,r30,-1; ");
2115 vex_printf("stw r30,");
2116 ppPPCAMode(i->Pin.EvCheck.amCounter);
2117 vex_printf("; bge nofail; lwz r30,");
2118 ppPPCAMode(i->Pin.EvCheck.amFailAddr);
2119 vex_printf("; mtctr r30; bctr; nofail:");
2120 return;
sewardj3dee8492012-04-20 00:13:28 +00002121 case Pin_ProfInc:
2122 if (mode64) {
sewardjf252de52012-04-20 10:42:24 +00002123 vex_printf("(profInc) imm64-fixed5 r30,$NotKnownYet; ");
sewardj3dee8492012-04-20 00:13:28 +00002124 vex_printf("ld r29,(r30); addi r29,r29,1; std r29,(r30)");
2125 } else {
sewardjf252de52012-04-20 10:42:24 +00002126 vex_printf("(profInc) imm32-fixed2 r30,$NotKnownYet; ");
sewardj3dee8492012-04-20 00:13:28 +00002127 vex_printf("lwz r29,4(r30); addic. r29,r29,1; stw r29,4(r30)");
2128 vex_printf("lwz r29,0(r30); addze r29,r29; stw r29,0(r30)");
2129 }
2130 break;
cerionb85e8bb2005-02-16 08:54:33 +00002131 default:
cerion5b2325f2005-12-23 00:55:09 +00002132 vex_printf("\nppPPCInstr: No such tag(%d)\n", (Int)i->tag);
2133 vpanic("ppPPCInstr");
cerionbcf8c3e2005-02-04 16:17:07 +00002134 }
2135}
2136
2137/* --------- Helpers for register allocation. --------- */
2138
cerion5b2325f2005-12-23 00:55:09 +00002139void getRegUsage_PPCInstr ( HRegUsage* u, PPCInstr* i, Bool mode64 )
cerionbcf8c3e2005-02-04 16:17:07 +00002140{
cerionbcf8c3e2005-02-04 16:17:07 +00002141 initHRegUsage(u);
2142 switch (i->tag) {
cerionf0de28c2005-12-13 20:21:11 +00002143 case Pin_LI:
2144 addHRegUse(u, HRmWrite, i->Pin.LI.dst);
sewardjb51f0f42005-07-18 11:38:02 +00002145 break;
cerionf0de28c2005-12-13 20:21:11 +00002146 case Pin_Alu:
cerion5b2325f2005-12-23 00:55:09 +00002147 addHRegUse(u, HRmRead, i->Pin.Alu.srcL);
2148 addRegUsage_PPCRH(u, i->Pin.Alu.srcR);
cerionf0de28c2005-12-13 20:21:11 +00002149 addHRegUse(u, HRmWrite, i->Pin.Alu.dst);
cerionb85e8bb2005-02-16 08:54:33 +00002150 return;
cerionbb01b7c2005-12-16 13:40:18 +00002151 case Pin_Shft:
2152 addHRegUse(u, HRmRead, i->Pin.Shft.srcL);
cerion5b2325f2005-12-23 00:55:09 +00002153 addRegUsage_PPCRH(u, i->Pin.Shft.srcR);
cerionbb01b7c2005-12-16 13:40:18 +00002154 addHRegUse(u, HRmWrite, i->Pin.Shft.dst);
2155 return;
cerion5b2325f2005-12-23 00:55:09 +00002156 case Pin_AddSubC:
2157 addHRegUse(u, HRmWrite, i->Pin.AddSubC.dst);
2158 addHRegUse(u, HRmRead, i->Pin.AddSubC.srcL);
2159 addHRegUse(u, HRmRead, i->Pin.AddSubC.srcR);
cerion4a49b032005-11-08 16:23:07 +00002160 return;
cerionf0de28c2005-12-13 20:21:11 +00002161 case Pin_Cmp:
2162 addHRegUse(u, HRmRead, i->Pin.Cmp.srcL);
cerion5b2325f2005-12-23 00:55:09 +00002163 addRegUsage_PPCRH(u, i->Pin.Cmp.srcR);
cerionb85e8bb2005-02-16 08:54:33 +00002164 return;
cerionf0de28c2005-12-13 20:21:11 +00002165 case Pin_Unary:
cerion5b2325f2005-12-23 00:55:09 +00002166 addHRegUse(u, HRmWrite, i->Pin.Unary.dst);
2167 addHRegUse(u, HRmRead, i->Pin.Unary.src);
cerionb85e8bb2005-02-16 08:54:33 +00002168 return;
2169 case Pin_MulL:
2170 addHRegUse(u, HRmWrite, i->Pin.MulL.dst);
cerion5b2325f2005-12-23 00:55:09 +00002171 addHRegUse(u, HRmRead, i->Pin.MulL.srcL);
2172 addHRegUse(u, HRmRead, i->Pin.MulL.srcR);
cerionb85e8bb2005-02-16 08:54:33 +00002173 return;
2174 case Pin_Div:
2175 addHRegUse(u, HRmWrite, i->Pin.Div.dst);
cerion5b2325f2005-12-23 00:55:09 +00002176 addHRegUse(u, HRmRead, i->Pin.Div.srcL);
2177 addHRegUse(u, HRmRead, i->Pin.Div.srcR);
cerionb85e8bb2005-02-16 08:54:33 +00002178 return;
cerionf0de28c2005-12-13 20:21:11 +00002179 case Pin_Call: {
2180 UInt argir;
cerionb85e8bb2005-02-16 08:54:33 +00002181 /* This is a bit subtle. */
2182 /* First off, claim it trashes all the caller-saved regs
2183 which fall within the register allocator's jurisdiction.
cerionf0de28c2005-12-13 20:21:11 +00002184 These I believe to be:
2185 mode32: r3 to r12
2186 mode64: r3 to r10
cerionb85e8bb2005-02-16 08:54:33 +00002187 */
sewardjcb1f68e2005-12-30 03:39:14 +00002188 /* XXXXXXXXXXXXXXXXX BUG! This doesn't say anything about the FP
2189 or Altivec registers. We get away with this ONLY because
2190 getAllocatableRegs_PPC gives the allocator callee-saved fp
2191 and Altivec regs, and no caller-save ones. */
cerionf0de28c2005-12-13 20:21:11 +00002192 addHRegUse(u, HRmWrite, hregPPC_GPR3(mode64));
2193 addHRegUse(u, HRmWrite, hregPPC_GPR4(mode64));
2194 addHRegUse(u, HRmWrite, hregPPC_GPR5(mode64));
2195 addHRegUse(u, HRmWrite, hregPPC_GPR6(mode64));
2196 addHRegUse(u, HRmWrite, hregPPC_GPR7(mode64));
2197 addHRegUse(u, HRmWrite, hregPPC_GPR8(mode64));
2198 addHRegUse(u, HRmWrite, hregPPC_GPR9(mode64));
2199 addHRegUse(u, HRmWrite, hregPPC_GPR10(mode64));
2200 if (!mode64) {
2201 addHRegUse(u, HRmWrite, hregPPC_GPR11(mode64));
2202 addHRegUse(u, HRmWrite, hregPPC_GPR12(mode64));
2203 }
2204
cerionb85e8bb2005-02-16 08:54:33 +00002205 /* Now we have to state any parameter-carrying registers
sewardj6a64a9f2005-08-21 00:48:37 +00002206 which might be read. This depends on the argiregs field. */
cerionf0de28c2005-12-13 20:21:11 +00002207 argir = i->Pin.Call.argiregs;
2208 if (argir &(1<<10)) addHRegUse(u, HRmRead, hregPPC_GPR10(mode64));
2209 if (argir & (1<<9)) addHRegUse(u, HRmRead, hregPPC_GPR9(mode64));
2210 if (argir & (1<<8)) addHRegUse(u, HRmRead, hregPPC_GPR8(mode64));
2211 if (argir & (1<<7)) addHRegUse(u, HRmRead, hregPPC_GPR7(mode64));
2212 if (argir & (1<<6)) addHRegUse(u, HRmRead, hregPPC_GPR6(mode64));
2213 if (argir & (1<<5)) addHRegUse(u, HRmRead, hregPPC_GPR5(mode64));
2214 if (argir & (1<<4)) addHRegUse(u, HRmRead, hregPPC_GPR4(mode64));
2215 if (argir & (1<<3)) addHRegUse(u, HRmRead, hregPPC_GPR3(mode64));
sewardj6a64a9f2005-08-21 00:48:37 +00002216
cerionf0de28c2005-12-13 20:21:11 +00002217 vassert(0 == (argir & ~((1<<3)|(1<<4)|(1<<5)|(1<<6)
2218 |(1<<7)|(1<<8)|(1<<9)|(1<<10))));
sewardj6a64a9f2005-08-21 00:48:37 +00002219
cerionb85e8bb2005-02-16 08:54:33 +00002220 /* Finally, there is the issue that the insn trashes a
2221 register because the literal target address has to be
cerionf0de28c2005-12-13 20:21:11 +00002222 loaded into a register. %r10 seems a suitable victim.
sewardje9d8a262009-07-01 08:06:34 +00002223 (Can't use %r0, as some insns interpret it as value zero). */
cerionf0de28c2005-12-13 20:21:11 +00002224 addHRegUse(u, HRmWrite, hregPPC_GPR10(mode64));
2225 /* Upshot of this is that the assembler really must use %r10,
ceriona56e9cc2005-02-16 18:08:25 +00002226 and no other, as a destination temporary. */
cerionb85e8bb2005-02-16 08:54:33 +00002227 return;
cerionf0de28c2005-12-13 20:21:11 +00002228 }
sewardj3dee8492012-04-20 00:13:28 +00002229 /* XDirect/XIndir/XAssisted are also a bit subtle. They
2230 conditionally exit the block. Hence we only need to list (1)
2231 the registers that they read, and (2) the registers that they
2232 write in the case where the block is not exited. (2) is empty,
2233 hence only (1) is relevant here. */
2234 case Pin_XDirect:
2235 addRegUsage_PPCAMode(u, i->Pin.XDirect.amCIA);
2236 return;
2237 case Pin_XIndir:
2238 addHRegUse(u, HRmRead, i->Pin.XIndir.dstGA);
2239 addRegUsage_PPCAMode(u, i->Pin.XIndir.amCIA);
2240 return;
2241 case Pin_XAssisted:
2242 addHRegUse(u, HRmRead, i->Pin.XAssisted.dstGA);
2243 addRegUsage_PPCAMode(u, i->Pin.XAssisted.amCIA);
cerionb85e8bb2005-02-16 08:54:33 +00002244 return;
cerionf0de28c2005-12-13 20:21:11 +00002245 case Pin_CMov:
cerion5b2325f2005-12-23 00:55:09 +00002246 addRegUsage_PPCRI(u, i->Pin.CMov.src);
cerionf0de28c2005-12-13 20:21:11 +00002247 addHRegUse(u, HRmWrite, i->Pin.CMov.dst);
cerionb85e8bb2005-02-16 08:54:33 +00002248 return;
cerion7cf8e4e2005-02-16 16:08:17 +00002249 case Pin_Load:
cerion5b2325f2005-12-23 00:55:09 +00002250 addRegUsage_PPCAMode(u, i->Pin.Load.src);
cerion7cf8e4e2005-02-16 16:08:17 +00002251 addHRegUse(u, HRmWrite, i->Pin.Load.dst);
cerionb85e8bb2005-02-16 08:54:33 +00002252 return;
sewardje9d8a262009-07-01 08:06:34 +00002253 case Pin_LoadL:
2254 addHRegUse(u, HRmRead, i->Pin.LoadL.src);
2255 addHRegUse(u, HRmWrite, i->Pin.LoadL.dst);
2256 return;
cerionb85e8bb2005-02-16 08:54:33 +00002257 case Pin_Store:
cerion5b2325f2005-12-23 00:55:09 +00002258 addHRegUse(u, HRmRead, i->Pin.Store.src);
2259 addRegUsage_PPCAMode(u, i->Pin.Store.dst);
cerionb85e8bb2005-02-16 08:54:33 +00002260 return;
sewardje9d8a262009-07-01 08:06:34 +00002261 case Pin_StoreC:
2262 addHRegUse(u, HRmRead, i->Pin.StoreC.src);
2263 addHRegUse(u, HRmRead, i->Pin.StoreC.dst);
2264 return;
cerion5b2325f2005-12-23 00:55:09 +00002265 case Pin_Set:
2266 addHRegUse(u, HRmWrite, i->Pin.Set.dst);
cerionb85e8bb2005-02-16 08:54:33 +00002267 return;
sewardjb51f0f42005-07-18 11:38:02 +00002268 case Pin_MfCR:
2269 addHRegUse(u, HRmWrite, i->Pin.MfCR.dst);
2270 return;
cerionb85e8bb2005-02-16 08:54:33 +00002271 case Pin_MFence:
2272 return;
cerion094d1392005-06-20 13:45:57 +00002273
2274 case Pin_FpUnary:
2275 addHRegUse(u, HRmWrite, i->Pin.FpUnary.dst);
2276 addHRegUse(u, HRmRead, i->Pin.FpUnary.src);
2277 return;
2278 case Pin_FpBinary:
2279 addHRegUse(u, HRmWrite, i->Pin.FpBinary.dst);
2280 addHRegUse(u, HRmRead, i->Pin.FpBinary.srcL);
2281 addHRegUse(u, HRmRead, i->Pin.FpBinary.srcR);
2282 return;
sewardj40c80262006-02-08 19:30:46 +00002283 case Pin_FpMulAcc:
2284 addHRegUse(u, HRmWrite, i->Pin.FpMulAcc.dst);
2285 addHRegUse(u, HRmRead, i->Pin.FpMulAcc.srcML);
2286 addHRegUse(u, HRmRead, i->Pin.FpMulAcc.srcMR);
2287 addHRegUse(u, HRmRead, i->Pin.FpMulAcc.srcAcc);
2288 return;
cerion094d1392005-06-20 13:45:57 +00002289 case Pin_FpLdSt:
2290 addHRegUse(u, (i->Pin.FpLdSt.isLoad ? HRmWrite : HRmRead),
2291 i->Pin.FpLdSt.reg);
cerion5b2325f2005-12-23 00:55:09 +00002292 addRegUsage_PPCAMode(u, i->Pin.FpLdSt.addr);
cerion094d1392005-06-20 13:45:57 +00002293 return;
sewardj92923de2006-01-25 21:29:48 +00002294 case Pin_FpSTFIW:
2295 addHRegUse(u, HRmRead, i->Pin.FpSTFIW.addr);
2296 addHRegUse(u, HRmRead, i->Pin.FpSTFIW.data);
cerion094d1392005-06-20 13:45:57 +00002297 return;
sewardj92923de2006-01-25 21:29:48 +00002298 case Pin_FpRSP:
2299 addHRegUse(u, HRmWrite, i->Pin.FpRSP.dst);
2300 addHRegUse(u, HRmRead, i->Pin.FpRSP.src);
cerion094d1392005-06-20 13:45:57 +00002301 return;
sewardj92923de2006-01-25 21:29:48 +00002302 case Pin_FpCftI:
2303 addHRegUse(u, HRmWrite, i->Pin.FpCftI.dst);
2304 addHRegUse(u, HRmRead, i->Pin.FpCftI.src);
cerion07b07a92005-12-22 14:32:35 +00002305 return;
cerion094d1392005-06-20 13:45:57 +00002306 case Pin_FpCMov:
2307 addHRegUse(u, HRmModify, i->Pin.FpCMov.dst);
cerion5b2325f2005-12-23 00:55:09 +00002308 addHRegUse(u, HRmRead, i->Pin.FpCMov.src);
cerion094d1392005-06-20 13:45:57 +00002309 return;
2310 case Pin_FpLdFPSCR:
2311 addHRegUse(u, HRmRead, i->Pin.FpLdFPSCR.src);
2312 return;
2313 case Pin_FpCmp:
2314 addHRegUse(u, HRmWrite, i->Pin.FpCmp.dst);
cerion5b2325f2005-12-23 00:55:09 +00002315 addHRegUse(u, HRmRead, i->Pin.FpCmp.srcL);
2316 addHRegUse(u, HRmRead, i->Pin.FpCmp.srcR);
cerion094d1392005-06-20 13:45:57 +00002317 return;
cerion7f000af2005-02-22 20:36:49 +00002318
2319 case Pin_RdWrLR:
2320 addHRegUse(u, (i->Pin.RdWrLR.wrLR ? HRmRead : HRmWrite),
2321 i->Pin.RdWrLR.gpr);
2322 return;
2323
cerionc3d8bdc2005-06-28 18:06:23 +00002324 case Pin_AvLdSt:
2325 addHRegUse(u, (i->Pin.AvLdSt.isLoad ? HRmWrite : HRmRead),
2326 i->Pin.AvLdSt.reg);
2327 if (i->Pin.AvLdSt.addr->tag == Pam_IR)
cerionf0de28c2005-12-13 20:21:11 +00002328 addHRegUse(u, HRmWrite, hregPPC_GPR30(mode64));
cerion5b2325f2005-12-23 00:55:09 +00002329 addRegUsage_PPCAMode(u, i->Pin.AvLdSt.addr);
cerionc3d8bdc2005-06-28 18:06:23 +00002330 return;
2331 case Pin_AvUnary:
2332 addHRegUse(u, HRmWrite, i->Pin.AvUnary.dst);
2333 addHRegUse(u, HRmRead, i->Pin.AvUnary.src);
2334 return;
2335 case Pin_AvBinary:
sewardjdc1f9132005-10-22 12:49:49 +00002336 if (i->Pin.AvBinary.op == Pav_XOR
2337 && i->Pin.AvBinary.dst == i->Pin.AvBinary.srcL
2338 && i->Pin.AvBinary.dst == i->Pin.AvBinary.srcR) {
2339 /* reg-alloc needs to understand 'xor r,r,r' as a write of r */
2340 /* (as opposed to a rite of passage :-) */
2341 addHRegUse(u, HRmWrite, i->Pin.AvBinary.dst);
2342 } else {
2343 addHRegUse(u, HRmWrite, i->Pin.AvBinary.dst);
2344 addHRegUse(u, HRmRead, i->Pin.AvBinary.srcL);
2345 addHRegUse(u, HRmRead, i->Pin.AvBinary.srcR);
2346 }
cerionc3d8bdc2005-06-28 18:06:23 +00002347 return;
cerion6b6f59e2005-06-28 20:59:18 +00002348 case Pin_AvBin8x16:
2349 addHRegUse(u, HRmWrite, i->Pin.AvBin8x16.dst);
2350 addHRegUse(u, HRmRead, i->Pin.AvBin8x16.srcL);
2351 addHRegUse(u, HRmRead, i->Pin.AvBin8x16.srcR);
2352 return;
2353 case Pin_AvBin16x8:
2354 addHRegUse(u, HRmWrite, i->Pin.AvBin16x8.dst);
2355 addHRegUse(u, HRmRead, i->Pin.AvBin16x8.srcL);
2356 addHRegUse(u, HRmRead, i->Pin.AvBin16x8.srcR);
2357 return;
2358 case Pin_AvBin32x4:
2359 addHRegUse(u, HRmWrite, i->Pin.AvBin32x4.dst);
2360 addHRegUse(u, HRmRead, i->Pin.AvBin32x4.srcL);
2361 addHRegUse(u, HRmRead, i->Pin.AvBin32x4.srcR);
cerion6b6f59e2005-06-28 20:59:18 +00002362 return;
2363 case Pin_AvBin32Fx4:
2364 addHRegUse(u, HRmWrite, i->Pin.AvBin32Fx4.dst);
2365 addHRegUse(u, HRmRead, i->Pin.AvBin32Fx4.srcL);
2366 addHRegUse(u, HRmRead, i->Pin.AvBin32Fx4.srcR);
cerion8ea0d3e2005-11-14 00:44:47 +00002367 if (i->Pin.AvBin32Fx4.op == Pavfp_MULF)
cerion5b2325f2005-12-23 00:55:09 +00002368 addHRegUse(u, HRmWrite, hregPPC_VR29());
cerion8ea0d3e2005-11-14 00:44:47 +00002369 return;
2370 case Pin_AvUn32Fx4:
2371 addHRegUse(u, HRmWrite, i->Pin.AvUn32Fx4.dst);
2372 addHRegUse(u, HRmRead, i->Pin.AvUn32Fx4.src);
cerion6b6f59e2005-06-28 20:59:18 +00002373 return;
cerionc3d8bdc2005-06-28 18:06:23 +00002374 case Pin_AvPerm:
2375 addHRegUse(u, HRmWrite, i->Pin.AvPerm.dst);
cerionc3d8bdc2005-06-28 18:06:23 +00002376 addHRegUse(u, HRmRead, i->Pin.AvPerm.srcL);
2377 addHRegUse(u, HRmRead, i->Pin.AvPerm.srcR);
cerion92d9d872005-09-15 21:58:50 +00002378 addHRegUse(u, HRmRead, i->Pin.AvPerm.ctl);
cerionc3d8bdc2005-06-28 18:06:23 +00002379 return;
2380 case Pin_AvSel:
2381 addHRegUse(u, HRmWrite, i->Pin.AvSel.dst);
2382 addHRegUse(u, HRmRead, i->Pin.AvSel.ctl);
2383 addHRegUse(u, HRmRead, i->Pin.AvSel.srcL);
2384 addHRegUse(u, HRmRead, i->Pin.AvSel.srcR);
2385 return;
2386 case Pin_AvShlDbl:
2387 addHRegUse(u, HRmWrite, i->Pin.AvShlDbl.dst);
2388 addHRegUse(u, HRmRead, i->Pin.AvShlDbl.srcL);
2389 addHRegUse(u, HRmRead, i->Pin.AvShlDbl.srcR);
2390 return;
2391 case Pin_AvSplat:
cerion5b2325f2005-12-23 00:55:09 +00002392 addHRegUse(u, HRmWrite, i->Pin.AvSplat.dst);
2393 addRegUsage_PPCVI5s(u, i->Pin.AvSplat.src);
cerionc3d8bdc2005-06-28 18:06:23 +00002394 return;
cerion6b6f59e2005-06-28 20:59:18 +00002395 case Pin_AvCMov:
2396 addHRegUse(u, HRmModify, i->Pin.AvCMov.dst);
cerion5b2325f2005-12-23 00:55:09 +00002397 addHRegUse(u, HRmRead, i->Pin.AvCMov.src);
cerion6b6f59e2005-06-28 20:59:18 +00002398 return;
cerionc3d8bdc2005-06-28 18:06:23 +00002399 case Pin_AvLdVSCR:
2400 addHRegUse(u, HRmRead, i->Pin.AvLdVSCR.src);
2401 return;
sewardjc6bbd472012-04-02 10:20:48 +00002402 case Pin_Dfp64Unary:
2403 addHRegUse(u, HRmWrite, i->Pin.Dfp64Unary.dst);
2404 addHRegUse(u, HRmRead, i->Pin.Dfp64Unary.src);
2405 return;
2406 case Pin_Dfp64Binary:
2407 addHRegUse(u, HRmWrite, i->Pin.Dfp64Binary.dst);
2408 addHRegUse(u, HRmRead, i->Pin.Dfp64Binary.srcL);
2409 addHRegUse(u, HRmRead, i->Pin.Dfp64Binary.srcR);
2410 return;
sewardj26217b02012-04-12 17:19:48 +00002411 case Pin_DfpShift:
2412 addRegUsage_PPCRI(u, i->Pin.DfpShift.shift);
2413 addHRegUse(u, HRmWrite, i->Pin.DfpShift.src);
2414 addHRegUse(u, HRmWrite, i->Pin.DfpShift.dst);
2415 return;
2416 case Pin_Dfp128Unary:
2417 addHRegUse(u, HRmWrite, i->Pin.Dfp128Unary.dst_hi);
2418 addHRegUse(u, HRmWrite, i->Pin.Dfp128Unary.dst_lo);
2419 addHRegUse(u, HRmRead, i->Pin.Dfp128Unary.src_hi);
2420 addHRegUse(u, HRmRead, i->Pin.Dfp128Unary.src_lo);
2421 return;
sewardjc6bbd472012-04-02 10:20:48 +00002422 case Pin_Dfp128Binary:
2423 addHRegUse(u, HRmWrite, i->Pin.Dfp128Binary.dst_hi);
2424 addHRegUse(u, HRmWrite, i->Pin.Dfp128Binary.dst_lo);
2425 addHRegUse(u, HRmRead, i->Pin.Dfp128Binary.srcR_hi);
2426 addHRegUse(u, HRmRead, i->Pin.Dfp128Binary.srcR_lo);
2427 return;
sewardjcdc376d2012-04-23 11:21:12 +00002428 case Pin_DfpRound:
2429 addHRegUse(u, HRmWrite, i->Pin.DfpRound.dst);
2430 addHRegUse(u, HRmRead, i->Pin.DfpRound.src);
2431 return;
2432 case Pin_DfpRound128:
2433 addHRegUse(u, HRmWrite, i->Pin.DfpRound128.dst_hi);
2434 addHRegUse(u, HRmWrite, i->Pin.DfpRound128.dst_lo);
2435 addHRegUse(u, HRmRead, i->Pin.DfpRound128.src_hi);
2436 addHRegUse(u, HRmRead, i->Pin.DfpRound128.src_lo);
2437 return;
2438 case Pin_DfpQuantize:
2439 addRegUsage_PPCRI(u, i->Pin.DfpQuantize.rmc);
2440 addHRegUse(u, HRmWrite, i->Pin.DfpQuantize.dst);
2441 addHRegUse(u, HRmRead, i->Pin.DfpQuantize.srcL);
2442 addHRegUse(u, HRmRead, i->Pin.DfpQuantize.srcR);
2443 return;
2444 case Pin_DfpQuantize128:
2445 addHRegUse(u, HRmWrite, i->Pin.DfpQuantize128.dst_hi);
2446 addHRegUse(u, HRmWrite, i->Pin.DfpQuantize128.dst_lo);
2447 addHRegUse(u, HRmRead, i->Pin.DfpQuantize128.src_hi);
2448 addHRegUse(u, HRmRead, i->Pin.DfpQuantize128.src_lo);
2449 return;
sewardj26217b02012-04-12 17:19:48 +00002450 case Pin_DfpShift128:
2451 addRegUsage_PPCRI(u, i->Pin.DfpShift128.shift);
2452 addHRegUse(u, HRmWrite, i->Pin.DfpShift128.src_hi);
2453 addHRegUse(u, HRmWrite, i->Pin.DfpShift128.src_lo);
2454 addHRegUse(u, HRmWrite, i->Pin.DfpShift128.dst_hi);
2455 addHRegUse(u, HRmWrite, i->Pin.DfpShift128.dst_lo);
2456 return;
2457 case Pin_DfpD128toD64:
2458 addHRegUse(u, HRmWrite, i->Pin.DfpD128toD64.src_hi);
2459 addHRegUse(u, HRmWrite, i->Pin.DfpD128toD64.src_lo);
2460 addHRegUse(u, HRmWrite, i->Pin.DfpD128toD64.dst);
2461 return;
2462 case Pin_DfpI64StoD128:
2463 addHRegUse(u, HRmWrite, i->Pin.DfpI64StoD128.src);
2464 addHRegUse(u, HRmWrite, i->Pin.DfpI64StoD128.dst_hi);
2465 addHRegUse(u, HRmWrite, i->Pin.DfpI64StoD128.dst_lo);
2466 return;
sewardjcdc376d2012-04-23 11:21:12 +00002467 case Pin_ExtractExpD128:
2468 addHRegUse(u, HRmWrite, i->Pin.ExtractExpD128.dst);
2469 addHRegUse(u, HRmRead, i->Pin.ExtractExpD128.src_hi);
2470 addHRegUse(u, HRmRead, i->Pin.ExtractExpD128.src_lo);
2471 return;
2472 case Pin_InsertExpD128:
2473 addHRegUse(u, HRmWrite, i->Pin.InsertExpD128.dst_hi);
2474 addHRegUse(u, HRmWrite, i->Pin.InsertExpD128.dst_lo);
2475 addHRegUse(u, HRmRead, i->Pin.InsertExpD128.srcL);
2476 addHRegUse(u, HRmRead, i->Pin.InsertExpD128.srcR_hi);
2477 addHRegUse(u, HRmRead, i->Pin.InsertExpD128.srcR_lo);
2478 return;
2479 case Pin_Dfp64Cmp:
2480 addHRegUse(u, HRmWrite, i->Pin.Dfp64Cmp.dst);
2481 addHRegUse(u, HRmRead, i->Pin.Dfp64Cmp.srcL);
2482 addHRegUse(u, HRmRead, i->Pin.Dfp64Cmp.srcR);
2483 return;
2484 case Pin_Dfp128Cmp:
2485 addHRegUse(u, HRmWrite, i->Pin.Dfp128Cmp.dst);
2486 addHRegUse(u, HRmRead, i->Pin.Dfp128Cmp.srcL_hi);
2487 addHRegUse(u, HRmRead, i->Pin.Dfp128Cmp.srcL_lo);
2488 addHRegUse(u, HRmRead, i->Pin.Dfp128Cmp.srcR_hi);
2489 addHRegUse(u, HRmRead, i->Pin.Dfp128Cmp.srcR_lo);
2490 return;
sewardj3dee8492012-04-20 00:13:28 +00002491 case Pin_EvCheck:
2492 /* We expect both amodes only to mention the GSP (r31), so this
2493 is in fact pointless, since GSP isn't allocatable, but
2494 anyway.. */
2495 addRegUsage_PPCAMode(u, i->Pin.EvCheck.amCounter);
2496 addRegUsage_PPCAMode(u, i->Pin.EvCheck.amFailAddr);
2497 addHRegUse(u, HRmWrite, hregPPC_GPR30(mode64)); /* also unavail to RA */
2498 return;
2499 case Pin_ProfInc:
2500 addHRegUse(u, HRmWrite, hregPPC_GPR29(mode64));
2501 addHRegUse(u, HRmWrite, hregPPC_GPR30(mode64));
2502 return;
cerionb85e8bb2005-02-16 08:54:33 +00002503 default:
cerion5b2325f2005-12-23 00:55:09 +00002504 ppPPCInstr(i, mode64);
2505 vpanic("getRegUsage_PPCInstr");
cerionbcf8c3e2005-02-04 16:17:07 +00002506 }
2507}
2508
cerioncd304492005-02-08 19:40:24 +00002509/* local helper */
cerion92b64362005-12-13 12:02:26 +00002510static void mapReg( HRegRemap* m, HReg* r )
cerioncd304492005-02-08 19:40:24 +00002511{
2512 *r = lookupHRegRemap(m, *r);
2513}
cerionbcf8c3e2005-02-04 16:17:07 +00002514
cerion5b2325f2005-12-23 00:55:09 +00002515void mapRegs_PPCInstr ( HRegRemap* m, PPCInstr* i, Bool mode64 )
cerionbcf8c3e2005-02-04 16:17:07 +00002516{
2517 switch (i->tag) {
cerionf0de28c2005-12-13 20:21:11 +00002518 case Pin_LI:
2519 mapReg(m, &i->Pin.LI.dst);
sewardjb51f0f42005-07-18 11:38:02 +00002520 return;
cerionf0de28c2005-12-13 20:21:11 +00002521 case Pin_Alu:
2522 mapReg(m, &i->Pin.Alu.dst);
2523 mapReg(m, &i->Pin.Alu.srcL);
cerion5b2325f2005-12-23 00:55:09 +00002524 mapRegs_PPCRH(m, i->Pin.Alu.srcR);
cerionb85e8bb2005-02-16 08:54:33 +00002525 return;
cerionbb01b7c2005-12-16 13:40:18 +00002526 case Pin_Shft:
2527 mapReg(m, &i->Pin.Shft.dst);
2528 mapReg(m, &i->Pin.Shft.srcL);
cerion5b2325f2005-12-23 00:55:09 +00002529 mapRegs_PPCRH(m, i->Pin.Shft.srcR);
cerionbb01b7c2005-12-16 13:40:18 +00002530 return;
cerion5b2325f2005-12-23 00:55:09 +00002531 case Pin_AddSubC:
2532 mapReg(m, &i->Pin.AddSubC.dst);
2533 mapReg(m, &i->Pin.AddSubC.srcL);
2534 mapReg(m, &i->Pin.AddSubC.srcR);
cerion4a49b032005-11-08 16:23:07 +00002535 return;
cerionf0de28c2005-12-13 20:21:11 +00002536 case Pin_Cmp:
2537 mapReg(m, &i->Pin.Cmp.srcL);
cerion5b2325f2005-12-23 00:55:09 +00002538 mapRegs_PPCRH(m, i->Pin.Cmp.srcR);
cerionb85e8bb2005-02-16 08:54:33 +00002539 return;
cerionf0de28c2005-12-13 20:21:11 +00002540 case Pin_Unary:
cerion5b2325f2005-12-23 00:55:09 +00002541 mapReg(m, &i->Pin.Unary.dst);
2542 mapReg(m, &i->Pin.Unary.src);
cerionb85e8bb2005-02-16 08:54:33 +00002543 return;
2544 case Pin_MulL:
2545 mapReg(m, &i->Pin.MulL.dst);
ceriona2f75882005-03-15 16:33:38 +00002546 mapReg(m, &i->Pin.MulL.srcL);
sewardjb51f0f42005-07-18 11:38:02 +00002547 mapReg(m, &i->Pin.MulL.srcR);
cerionb85e8bb2005-02-16 08:54:33 +00002548 return;
2549 case Pin_Div:
2550 mapReg(m, &i->Pin.Div.dst);
ceriona2f75882005-03-15 16:33:38 +00002551 mapReg(m, &i->Pin.Div.srcL);
2552 mapReg(m, &i->Pin.Div.srcR);
cerionb85e8bb2005-02-16 08:54:33 +00002553 return;
cerionb85e8bb2005-02-16 08:54:33 +00002554 case Pin_Call:
2555 return;
sewardj3dee8492012-04-20 00:13:28 +00002556 case Pin_XDirect:
2557 mapRegs_PPCAMode(m, i->Pin.XDirect.amCIA);
2558 return;
2559 case Pin_XIndir:
2560 mapReg(m, &i->Pin.XIndir.dstGA);
2561 mapRegs_PPCAMode(m, i->Pin.XIndir.amCIA);
2562 return;
2563 case Pin_XAssisted:
2564 mapReg(m, &i->Pin.XAssisted.dstGA);
2565 mapRegs_PPCAMode(m, i->Pin.XAssisted.amCIA);
cerionb85e8bb2005-02-16 08:54:33 +00002566 return;
cerionf0de28c2005-12-13 20:21:11 +00002567 case Pin_CMov:
cerion5b2325f2005-12-23 00:55:09 +00002568 mapRegs_PPCRI(m, i->Pin.CMov.src);
cerionf0de28c2005-12-13 20:21:11 +00002569 mapReg(m, &i->Pin.CMov.dst);
cerionb85e8bb2005-02-16 08:54:33 +00002570 return;
cerion7cf8e4e2005-02-16 16:08:17 +00002571 case Pin_Load:
cerion5b2325f2005-12-23 00:55:09 +00002572 mapRegs_PPCAMode(m, i->Pin.Load.src);
cerion7cf8e4e2005-02-16 16:08:17 +00002573 mapReg(m, &i->Pin.Load.dst);
cerionb85e8bb2005-02-16 08:54:33 +00002574 return;
sewardje9d8a262009-07-01 08:06:34 +00002575 case Pin_LoadL:
2576 mapReg(m, &i->Pin.LoadL.src);
2577 mapReg(m, &i->Pin.LoadL.dst);
2578 return;
cerionb85e8bb2005-02-16 08:54:33 +00002579 case Pin_Store:
2580 mapReg(m, &i->Pin.Store.src);
cerion5b2325f2005-12-23 00:55:09 +00002581 mapRegs_PPCAMode(m, i->Pin.Store.dst);
cerionb85e8bb2005-02-16 08:54:33 +00002582 return;
sewardje9d8a262009-07-01 08:06:34 +00002583 case Pin_StoreC:
2584 mapReg(m, &i->Pin.StoreC.src);
2585 mapReg(m, &i->Pin.StoreC.dst);
2586 return;
cerion5b2325f2005-12-23 00:55:09 +00002587 case Pin_Set:
2588 mapReg(m, &i->Pin.Set.dst);
cerionb85e8bb2005-02-16 08:54:33 +00002589 return;
sewardjb51f0f42005-07-18 11:38:02 +00002590 case Pin_MfCR:
2591 mapReg(m, &i->Pin.MfCR.dst);
2592 return;
cerionb85e8bb2005-02-16 08:54:33 +00002593 case Pin_MFence:
2594 return;
cerion094d1392005-06-20 13:45:57 +00002595 case Pin_FpUnary:
sewardjb51f0f42005-07-18 11:38:02 +00002596 mapReg(m, &i->Pin.FpUnary.dst);
2597 mapReg(m, &i->Pin.FpUnary.src);
2598 return;
2599 case Pin_FpBinary:
2600 mapReg(m, &i->Pin.FpBinary.dst);
2601 mapReg(m, &i->Pin.FpBinary.srcL);
2602 mapReg(m, &i->Pin.FpBinary.srcR);
2603 return;
sewardj40c80262006-02-08 19:30:46 +00002604 case Pin_FpMulAcc:
2605 mapReg(m, &i->Pin.FpMulAcc.dst);
2606 mapReg(m, &i->Pin.FpMulAcc.srcML);
2607 mapReg(m, &i->Pin.FpMulAcc.srcMR);
2608 mapReg(m, &i->Pin.FpMulAcc.srcAcc);
2609 return;
sewardjb51f0f42005-07-18 11:38:02 +00002610 case Pin_FpLdSt:
2611 mapReg(m, &i->Pin.FpLdSt.reg);
cerion5b2325f2005-12-23 00:55:09 +00002612 mapRegs_PPCAMode(m, i->Pin.FpLdSt.addr);
sewardjb51f0f42005-07-18 11:38:02 +00002613 return;
sewardj92923de2006-01-25 21:29:48 +00002614 case Pin_FpSTFIW:
2615 mapReg(m, &i->Pin.FpSTFIW.addr);
2616 mapReg(m, &i->Pin.FpSTFIW.data);
sewardjb51f0f42005-07-18 11:38:02 +00002617 return;
sewardj92923de2006-01-25 21:29:48 +00002618 case Pin_FpRSP:
2619 mapReg(m, &i->Pin.FpRSP.dst);
2620 mapReg(m, &i->Pin.FpRSP.src);
sewardjb51f0f42005-07-18 11:38:02 +00002621 return;
sewardj92923de2006-01-25 21:29:48 +00002622 case Pin_FpCftI:
2623 mapReg(m, &i->Pin.FpCftI.dst);
2624 mapReg(m, &i->Pin.FpCftI.src);
cerion07b07a92005-12-22 14:32:35 +00002625 return;
sewardjb51f0f42005-07-18 11:38:02 +00002626 case Pin_FpCMov:
2627 mapReg(m, &i->Pin.FpCMov.dst);
2628 mapReg(m, &i->Pin.FpCMov.src);
2629 return;
2630 case Pin_FpLdFPSCR:
2631 mapReg(m, &i->Pin.FpLdFPSCR.src);
2632 return;
2633 case Pin_FpCmp:
2634 mapReg(m, &i->Pin.FpCmp.dst);
2635 mapReg(m, &i->Pin.FpCmp.srcL);
2636 mapReg(m, &i->Pin.FpCmp.srcR);
2637 return;
cerion7f000af2005-02-22 20:36:49 +00002638 case Pin_RdWrLR:
2639 mapReg(m, &i->Pin.RdWrLR.gpr);
2640 return;
cerionc3d8bdc2005-06-28 18:06:23 +00002641 case Pin_AvLdSt:
2642 mapReg(m, &i->Pin.AvLdSt.reg);
cerion5b2325f2005-12-23 00:55:09 +00002643 mapRegs_PPCAMode(m, i->Pin.AvLdSt.addr);
cerionc3d8bdc2005-06-28 18:06:23 +00002644 return;
2645 case Pin_AvUnary:
2646 mapReg(m, &i->Pin.AvUnary.dst);
2647 mapReg(m, &i->Pin.AvUnary.src);
2648 return;
2649 case Pin_AvBinary:
2650 mapReg(m, &i->Pin.AvBinary.dst);
2651 mapReg(m, &i->Pin.AvBinary.srcL);
2652 mapReg(m, &i->Pin.AvBinary.srcR);
2653 return;
cerion6b6f59e2005-06-28 20:59:18 +00002654 case Pin_AvBin8x16:
2655 mapReg(m, &i->Pin.AvBin8x16.dst);
2656 mapReg(m, &i->Pin.AvBin8x16.srcL);
2657 mapReg(m, &i->Pin.AvBin8x16.srcR);
2658 return;
2659 case Pin_AvBin16x8:
2660 mapReg(m, &i->Pin.AvBin16x8.dst);
2661 mapReg(m, &i->Pin.AvBin16x8.srcL);
2662 mapReg(m, &i->Pin.AvBin16x8.srcR);
2663 return;
2664 case Pin_AvBin32x4:
2665 mapReg(m, &i->Pin.AvBin32x4.dst);
2666 mapReg(m, &i->Pin.AvBin32x4.srcL);
2667 mapReg(m, &i->Pin.AvBin32x4.srcR);
2668 return;
2669 case Pin_AvBin32Fx4:
2670 mapReg(m, &i->Pin.AvBin32Fx4.dst);
2671 mapReg(m, &i->Pin.AvBin32Fx4.srcL);
2672 mapReg(m, &i->Pin.AvBin32Fx4.srcR);
2673 return;
cerion8ea0d3e2005-11-14 00:44:47 +00002674 case Pin_AvUn32Fx4:
2675 mapReg(m, &i->Pin.AvUn32Fx4.dst);
2676 mapReg(m, &i->Pin.AvUn32Fx4.src);
2677 return;
cerionc3d8bdc2005-06-28 18:06:23 +00002678 case Pin_AvPerm:
2679 mapReg(m, &i->Pin.AvPerm.dst);
2680 mapReg(m, &i->Pin.AvPerm.srcL);
2681 mapReg(m, &i->Pin.AvPerm.srcR);
2682 mapReg(m, &i->Pin.AvPerm.ctl);
2683 return;
2684 case Pin_AvSel:
2685 mapReg(m, &i->Pin.AvSel.dst);
2686 mapReg(m, &i->Pin.AvSel.srcL);
2687 mapReg(m, &i->Pin.AvSel.srcR);
2688 mapReg(m, &i->Pin.AvSel.ctl);
2689 return;
2690 case Pin_AvShlDbl:
2691 mapReg(m, &i->Pin.AvShlDbl.dst);
2692 mapReg(m, &i->Pin.AvShlDbl.srcL);
2693 mapReg(m, &i->Pin.AvShlDbl.srcR);
2694 return;
2695 case Pin_AvSplat:
2696 mapReg(m, &i->Pin.AvSplat.dst);
cerion5b2325f2005-12-23 00:55:09 +00002697 mapRegs_PPCVI5s(m, i->Pin.AvSplat.src);
cerionc3d8bdc2005-06-28 18:06:23 +00002698 return;
cerion6b6f59e2005-06-28 20:59:18 +00002699 case Pin_AvCMov:
2700 mapReg(m, &i->Pin.AvCMov.dst);
2701 mapReg(m, &i->Pin.AvCMov.src);
2702 return;
cerionc3d8bdc2005-06-28 18:06:23 +00002703 case Pin_AvLdVSCR:
2704 mapReg(m, &i->Pin.AvLdVSCR.src);
2705 return;
sewardjc6bbd472012-04-02 10:20:48 +00002706 case Pin_Dfp64Unary:
2707 mapReg(m, &i->Pin.Dfp64Unary.dst);
2708 mapReg(m, &i->Pin.Dfp64Unary.src);
2709 return;
2710 case Pin_Dfp64Binary:
2711 mapReg(m, &i->Pin.Dfp64Binary.dst);
2712 mapReg(m, &i->Pin.Dfp64Binary.srcL);
2713 mapReg(m, &i->Pin.Dfp64Binary.srcR);
2714 return;
sewardj26217b02012-04-12 17:19:48 +00002715 case Pin_DfpShift:
2716 mapRegs_PPCRI(m, i->Pin.DfpShift.shift);
2717 mapReg(m, &i->Pin.DfpShift.src);
2718 mapReg(m, &i->Pin.DfpShift.dst);
2719 return;
2720 case Pin_Dfp128Unary:
2721 mapReg(m, &i->Pin.Dfp128Unary.dst_hi);
2722 mapReg(m, &i->Pin.Dfp128Unary.dst_lo);
2723 mapReg(m, &i->Pin.Dfp128Unary.src_hi);
2724 mapReg(m, &i->Pin.Dfp128Unary.src_lo);
2725 return;
sewardjc6bbd472012-04-02 10:20:48 +00002726 case Pin_Dfp128Binary:
2727 mapReg(m, &i->Pin.Dfp128Binary.dst_hi);
2728 mapReg(m, &i->Pin.Dfp128Binary.dst_lo);
2729 mapReg(m, &i->Pin.Dfp128Binary.srcR_hi);
2730 mapReg(m, &i->Pin.Dfp128Binary.srcR_lo);
2731 return;
sewardj26217b02012-04-12 17:19:48 +00002732 case Pin_DfpShift128:
2733 mapRegs_PPCRI(m, i->Pin.DfpShift128.shift);
2734 mapReg(m, &i->Pin.DfpShift128.src_hi);
2735 mapReg(m, &i->Pin.DfpShift128.src_lo);
2736 mapReg(m, &i->Pin.DfpShift128.dst_hi);
2737 mapReg(m, &i->Pin.DfpShift128.dst_lo);
2738 return;
sewardjcdc376d2012-04-23 11:21:12 +00002739 case Pin_DfpRound:
2740 mapReg(m, &i->Pin.DfpRound.dst);
2741 mapReg(m, &i->Pin.DfpRound.src);
2742 return;
2743 case Pin_DfpRound128:
2744 mapReg(m, &i->Pin.DfpRound128.dst_hi);
2745 mapReg(m, &i->Pin.DfpRound128.dst_lo);
2746 mapReg(m, &i->Pin.DfpRound128.src_hi);
2747 mapReg(m, &i->Pin.DfpRound128.src_lo);
2748 return;
2749 case Pin_DfpQuantize:
2750 mapRegs_PPCRI(m, i->Pin.DfpQuantize.rmc);
2751 mapReg(m, &i->Pin.DfpQuantize.dst);
2752 mapReg(m, &i->Pin.DfpQuantize.srcL);
2753 mapReg(m, &i->Pin.DfpQuantize.srcR);
2754 return;
2755 case Pin_DfpQuantize128:
2756 mapRegs_PPCRI(m, i->Pin.DfpQuantize128.rmc);
2757 mapReg(m, &i->Pin.DfpQuantize128.dst_hi);
2758 mapReg(m, &i->Pin.DfpQuantize128.dst_lo);
2759 mapReg(m, &i->Pin.DfpQuantize128.src_hi);
2760 mapReg(m, &i->Pin.DfpQuantize128.src_lo);
floriana7b0d102012-06-15 20:55:43 +00002761 return;
sewardj26217b02012-04-12 17:19:48 +00002762 case Pin_DfpD128toD64:
2763 mapReg(m, &i->Pin.DfpD128toD64.src_hi);
2764 mapReg(m, &i->Pin.DfpD128toD64.src_lo);
2765 mapReg(m, &i->Pin.DfpD128toD64.dst);
2766 return;
2767 case Pin_DfpI64StoD128:
2768 mapReg(m, &i->Pin.DfpI64StoD128.src);
2769 mapReg(m, &i->Pin.DfpI64StoD128.dst_hi);
2770 mapReg(m, &i->Pin.DfpI64StoD128.dst_lo);
2771 return;
sewardjcdc376d2012-04-23 11:21:12 +00002772 case Pin_ExtractExpD128:
2773 mapReg(m, &i->Pin.ExtractExpD128.dst);
2774 mapReg(m, &i->Pin.ExtractExpD128.src_hi);
2775 mapReg(m, &i->Pin.ExtractExpD128.src_lo);
2776 return;
2777 case Pin_InsertExpD128:
2778 mapReg(m, &i->Pin.InsertExpD128.dst_hi);
2779 mapReg(m, &i->Pin.InsertExpD128.dst_lo);
2780 mapReg(m, &i->Pin.InsertExpD128.srcL);
2781 mapReg(m, &i->Pin.InsertExpD128.srcR_hi);
2782 mapReg(m, &i->Pin.InsertExpD128.srcR_lo);
2783 return;
2784 case Pin_Dfp64Cmp:
2785 mapReg(m, &i->Pin.Dfp64Cmp.dst);
2786 mapReg(m, &i->Pin.Dfp64Cmp.srcL);
2787 mapReg(m, &i->Pin.Dfp64Cmp.srcR);
2788 return;
2789 case Pin_Dfp128Cmp:
2790 mapReg(m, &i->Pin.Dfp128Cmp.dst);
2791 mapReg(m, &i->Pin.Dfp128Cmp.srcL_hi);
2792 mapReg(m, &i->Pin.Dfp128Cmp.srcL_lo);
2793 mapReg(m, &i->Pin.Dfp128Cmp.srcR_hi);
2794 mapReg(m, &i->Pin.Dfp128Cmp.srcR_lo);
2795 return;
sewardj3dee8492012-04-20 00:13:28 +00002796 case Pin_EvCheck:
2797 /* We expect both amodes only to mention the GSP (r31), so this
2798 is in fact pointless, since GSP isn't allocatable, but
2799 anyway.. */
2800 mapRegs_PPCAMode(m, i->Pin.EvCheck.amCounter);
2801 mapRegs_PPCAMode(m, i->Pin.EvCheck.amFailAddr);
2802 return;
2803 case Pin_ProfInc:
2804 /* hardwires r29 and r30 -- nothing to modify. */
2805 return;
cerionb85e8bb2005-02-16 08:54:33 +00002806 default:
cerion5b2325f2005-12-23 00:55:09 +00002807 ppPPCInstr(i, mode64);
2808 vpanic("mapRegs_PPCInstr");
cerionbcf8c3e2005-02-04 16:17:07 +00002809 }
2810}
2811
2812/* Figure out if i represents a reg-reg move, and if so assign the
2813 source and destination to *src and *dst. If in doubt say No. Used
2814 by the register allocator to do move coalescing.
2815*/
cerion5b2325f2005-12-23 00:55:09 +00002816Bool isMove_PPCInstr ( PPCInstr* i, HReg* src, HReg* dst )
cerionbcf8c3e2005-02-04 16:17:07 +00002817{
cerionab9132d2005-02-15 15:46:59 +00002818 /* Moves between integer regs */
cerionf0de28c2005-12-13 20:21:11 +00002819 if (i->tag == Pin_Alu) {
cerionab9132d2005-02-15 15:46:59 +00002820 // or Rd,Rs,Rs == mr Rd,Rs
cerionf0de28c2005-12-13 20:21:11 +00002821 if (i->Pin.Alu.op != Palu_OR)
cerionab9132d2005-02-15 15:46:59 +00002822 return False;
cerionf0de28c2005-12-13 20:21:11 +00002823 if (i->Pin.Alu.srcR->tag != Prh_Reg)
cerionab9132d2005-02-15 15:46:59 +00002824 return False;
cerionf0de28c2005-12-13 20:21:11 +00002825 if (i->Pin.Alu.srcR->Prh.Reg.reg != i->Pin.Alu.srcL)
cerionb85e8bb2005-02-16 08:54:33 +00002826 return False;
cerionf0de28c2005-12-13 20:21:11 +00002827 *src = i->Pin.Alu.srcL;
2828 *dst = i->Pin.Alu.dst;
cerionab9132d2005-02-15 15:46:59 +00002829 return True;
2830 }
cerion094d1392005-06-20 13:45:57 +00002831 /* Moves between FP regs */
2832 if (i->tag == Pin_FpUnary) {
2833 if (i->Pin.FpUnary.op != Pfp_MOV)
2834 return False;
2835 *src = i->Pin.FpUnary.src;
2836 *dst = i->Pin.FpUnary.dst;
2837 return True;
2838 }
cerionbcf8c3e2005-02-04 16:17:07 +00002839 return False;
2840}
2841
2842
cerion75949202005-12-24 13:14:11 +00002843/* Generate ppc spill/reload instructions under the direction of the
cerionbcf8c3e2005-02-04 16:17:07 +00002844 register allocator. Note it's critical these don't write the
2845 condition codes. */
sewardj2a0cc852010-01-02 13:23:54 +00002846
2847void genSpill_PPC ( /*OUT*/HInstr** i1, /*OUT*/HInstr** i2,
2848 HReg rreg, Int offsetB, Bool mode64 )
cerione13bb312005-02-10 19:51:03 +00002849{
cerion5b2325f2005-12-23 00:55:09 +00002850 PPCAMode* am;
cerione13bb312005-02-10 19:51:03 +00002851 vassert(!hregIsVirtual(rreg));
sewardj2a0cc852010-01-02 13:23:54 +00002852 *i1 = *i2 = NULL;
cerion5b2325f2005-12-23 00:55:09 +00002853 am = PPCAMode_IR( offsetB, GuestStatePtr(mode64) );
cerione13bb312005-02-10 19:51:03 +00002854 switch (hregClass(rreg)) {
sewardj2a0cc852010-01-02 13:23:54 +00002855 case HRcInt64:
2856 vassert(mode64);
2857 *i1 = PPCInstr_Store( 8, am, rreg, mode64 );
2858 return;
2859 case HRcInt32:
2860 vassert(!mode64);
2861 *i1 = PPCInstr_Store( 4, am, rreg, mode64 );
2862 return;
2863 case HRcFlt64:
2864 *i1 = PPCInstr_FpLdSt ( False/*store*/, 8, rreg, am );
2865 return;
2866 case HRcVec128:
2867 // XXX: GPR30 used as spill register to kludge AltiVec
2868 // AMode_IR
2869 *i1 = PPCInstr_AvLdSt ( False/*store*/, 16, rreg, am );
2870 return;
2871 default:
2872 ppHRegClass(hregClass(rreg));
2873 vpanic("genSpill_PPC: unimplemented regclass");
cerione13bb312005-02-10 19:51:03 +00002874 }
cerionbcf8c3e2005-02-04 16:17:07 +00002875}
2876
sewardj2a0cc852010-01-02 13:23:54 +00002877void genReload_PPC ( /*OUT*/HInstr** i1, /*OUT*/HInstr** i2,
2878 HReg rreg, Int offsetB, Bool mode64 )
cerione13bb312005-02-10 19:51:03 +00002879{
cerion5b2325f2005-12-23 00:55:09 +00002880 PPCAMode* am;
cerione13bb312005-02-10 19:51:03 +00002881 vassert(!hregIsVirtual(rreg));
sewardj2a0cc852010-01-02 13:23:54 +00002882 *i1 = *i2 = NULL;
cerion5b2325f2005-12-23 00:55:09 +00002883 am = PPCAMode_IR( offsetB, GuestStatePtr(mode64) );
cerione13bb312005-02-10 19:51:03 +00002884 switch (hregClass(rreg)) {
sewardj2a0cc852010-01-02 13:23:54 +00002885 case HRcInt64:
2886 vassert(mode64);
2887 *i1 = PPCInstr_Load( 8, rreg, am, mode64 );
2888 return;
2889 case HRcInt32:
2890 vassert(!mode64);
2891 *i1 = PPCInstr_Load( 4, rreg, am, mode64 );
2892 return;
2893 case HRcFlt64:
2894 *i1 = PPCInstr_FpLdSt ( True/*load*/, 8, rreg, am );
2895 return;
2896 case HRcVec128:
2897 // XXX: GPR30 used as spill register to kludge AltiVec AMode_IR
2898 *i1 = PPCInstr_AvLdSt ( True/*load*/, 16, rreg, am );
2899 return;
2900 default:
2901 ppHRegClass(hregClass(rreg));
2902 vpanic("genReload_PPC: unimplemented regclass");
cerione13bb312005-02-10 19:51:03 +00002903 }
cerionbcf8c3e2005-02-04 16:17:07 +00002904}
2905
2906
cerion75949202005-12-24 13:14:11 +00002907/* --------- The ppc assembler (bleh.) --------- */
cerioncd304492005-02-08 19:40:24 +00002908
cerionf0de28c2005-12-13 20:21:11 +00002909static UInt iregNo ( HReg r, Bool mode64 )
cerioncd304492005-02-08 19:40:24 +00002910{
2911 UInt n;
cerionf0de28c2005-12-13 20:21:11 +00002912 vassert(hregClass(r) == mode64 ? HRcInt64 : HRcInt32);
cerioncd304492005-02-08 19:40:24 +00002913 vassert(!hregIsVirtual(r));
2914 n = hregNumber(r);
2915 vassert(n <= 32);
2916 return n;
2917}
cerioncd304492005-02-08 19:40:24 +00002918
cerion094d1392005-06-20 13:45:57 +00002919static UInt fregNo ( HReg fr )
2920{
2921 UInt n;
2922 vassert(hregClass(fr) == HRcFlt64);
2923 vassert(!hregIsVirtual(fr));
2924 n = hregNumber(fr);
2925 vassert(n <= 32);
2926 return n;
2927}
cerioncd304492005-02-08 19:40:24 +00002928
cerionc3d8bdc2005-06-28 18:06:23 +00002929static UInt vregNo ( HReg v )
2930{
2931 UInt n;
2932 vassert(hregClass(v) == HRcVec128);
2933 vassert(!hregIsVirtual(v));
2934 n = hregNumber(v);
2935 vassert(n <= 32);
2936 return n;
2937}
2938
sewardj3dee8492012-04-20 00:13:28 +00002939/* Emit an instruction big-endianly */
ceriond5e38382005-02-11 13:38:15 +00002940static UChar* emit32 ( UChar* p, UInt w32 )
2941{
sewardj428fabd2005-03-21 03:11:17 +00002942 *p++ = toUChar((w32 >> 24) & 0x000000FF);
2943 *p++ = toUChar((w32 >> 16) & 0x000000FF);
2944 *p++ = toUChar((w32 >> 8) & 0x000000FF);
2945 *p++ = toUChar((w32) & 0x000000FF);
ceriond5e38382005-02-11 13:38:15 +00002946 return p;
2947}
cerioncd304492005-02-08 19:40:24 +00002948
sewardj3dee8492012-04-20 00:13:28 +00002949/* Fetch an instruction big-endianly */
2950static UInt fetch32 ( UChar* p )
2951{
2952 UInt w32 = 0;
2953 w32 |= ((0xFF & (UInt)p[0]) << 24);
2954 w32 |= ((0xFF & (UInt)p[1]) << 16);
2955 w32 |= ((0xFF & (UInt)p[2]) << 8);
2956 w32 |= ((0xFF & (UInt)p[3]) << 0);
2957 return w32;
2958}
2959
cerion75949202005-12-24 13:14:11 +00002960/* The following mkForm[...] functions refer to ppc instruction forms
cerion094d1392005-06-20 13:45:57 +00002961 as per PPC32 p576
2962 */
cerioned623db2005-06-20 12:42:04 +00002963
cerion5b2325f2005-12-23 00:55:09 +00002964static UChar* mkFormD ( UChar* p, UInt opc1,
2965 UInt r1, UInt r2, UInt imm )
ceriond5e38382005-02-11 13:38:15 +00002966{
sewardj9a036bf2005-03-14 18:19:08 +00002967 UInt theInstr;
ceriona2f75882005-03-15 16:33:38 +00002968 vassert(opc1 < 0x40);
cerionf0de28c2005-12-13 20:21:11 +00002969 vassert(r1 < 0x20);
2970 vassert(r2 < 0x20);
cerion35663a72005-03-01 09:11:49 +00002971 imm = imm & 0xFFFF;
ceriona2f75882005-03-15 16:33:38 +00002972 theInstr = ((opc1<<26) | (r1<<21) | (r2<<16) | (imm));
ceriond5e38382005-02-11 13:38:15 +00002973 return emit32(p, theInstr);
2974}
2975
cerionf0de28c2005-12-13 20:21:11 +00002976static UChar* mkFormMD ( UChar* p, UInt opc1, UInt r1, UInt r2,
2977 UInt imm1, UInt imm2, UInt opc2 )
2978{
2979 UInt theInstr;
2980 vassert(opc1 < 0x40);
2981 vassert(r1 < 0x20);
2982 vassert(r2 < 0x20);
2983 vassert(imm1 < 0x40);
2984 vassert(imm2 < 0x40);
2985 vassert(opc2 < 0x08);
2986 imm2 = ((imm2 & 0x1F) << 1) | (imm2 >> 5);
2987 theInstr = ((opc1<<26) | (r1<<21) | (r2<<16) |
cerion5b2325f2005-12-23 00:55:09 +00002988 ((imm1 & 0x1F)<<11) | (imm2<<5) |
2989 (opc2<<2) | ((imm1 >> 5)<<1));
cerionf0de28c2005-12-13 20:21:11 +00002990 return emit32(p, theInstr);
2991}
2992
ceriona2f75882005-03-15 16:33:38 +00002993static UChar* mkFormX ( UChar* p, UInt opc1, UInt r1, UInt r2,
2994 UInt r3, UInt opc2, UInt b0 )
ceriond5e38382005-02-11 13:38:15 +00002995{
sewardj9a036bf2005-03-14 18:19:08 +00002996 UInt theInstr;
ceriona2f75882005-03-15 16:33:38 +00002997 vassert(opc1 < 0x40);
cerionf0de28c2005-12-13 20:21:11 +00002998 vassert(r1 < 0x20);
2999 vassert(r2 < 0x20);
3000 vassert(r3 < 0x20);
ceriona2f75882005-03-15 16:33:38 +00003001 vassert(opc2 < 0x400);
cerionf0de28c2005-12-13 20:21:11 +00003002 vassert(b0 < 0x2);
cerion5b2325f2005-12-23 00:55:09 +00003003 theInstr = ((opc1<<26) | (r1<<21) | (r2<<16) |
3004 (r3<<11) | (opc2<<1) | (b0));
ceriond5e38382005-02-11 13:38:15 +00003005 return emit32(p, theInstr);
3006}
3007
ceriona2f75882005-03-15 16:33:38 +00003008static UChar* mkFormXO ( UChar* p, UInt opc1, UInt r1, UInt r2,
3009 UInt r3, UInt b10, UInt opc2, UInt b0 )
cerionab9132d2005-02-15 15:46:59 +00003010{
sewardj9a036bf2005-03-14 18:19:08 +00003011 UInt theInstr;
ceriona2f75882005-03-15 16:33:38 +00003012 vassert(opc1 < 0x40);
cerionf0de28c2005-12-13 20:21:11 +00003013 vassert(r1 < 0x20);
3014 vassert(r2 < 0x20);
3015 vassert(r3 < 0x20);
3016 vassert(b10 < 0x2);
ceriona2f75882005-03-15 16:33:38 +00003017 vassert(opc2 < 0x200);
cerionf0de28c2005-12-13 20:21:11 +00003018 vassert(b0 < 0x2);
ceriona2f75882005-03-15 16:33:38 +00003019 theInstr = ((opc1<<26) | (r1<<21) | (r2<<16) |
3020 (r3<<11) | (b10 << 10) | (opc2<<1) | (b0));
cerionab9132d2005-02-15 15:46:59 +00003021 return emit32(p, theInstr);
3022}
ceriond5e38382005-02-11 13:38:15 +00003023
ceriona2f75882005-03-15 16:33:38 +00003024static UChar* mkFormXL ( UChar* p, UInt opc1, UInt f1, UInt f2,
3025 UInt f3, UInt opc2, UInt b0 )
cerion33aa6da2005-02-16 10:25:26 +00003026{
sewardj9a036bf2005-03-14 18:19:08 +00003027 UInt theInstr;
ceriona2f75882005-03-15 16:33:38 +00003028 vassert(opc1 < 0x40);
cerionf0de28c2005-12-13 20:21:11 +00003029 vassert(f1 < 0x20);
3030 vassert(f2 < 0x20);
3031 vassert(f3 < 0x20);
ceriona2f75882005-03-15 16:33:38 +00003032 vassert(opc2 < 0x400);
cerionf0de28c2005-12-13 20:21:11 +00003033 vassert(b0 < 0x2);
cerion5b2325f2005-12-23 00:55:09 +00003034 theInstr = ((opc1<<26) | (f1<<21) | (f2<<16) |
3035 (f3<<11) | (opc2<<1) | (b0));
cerion33aa6da2005-02-16 10:25:26 +00003036 return emit32(p, theInstr);
3037}
3038
3039// Note: for split field ops, give mnemonic arg
ceriona2f75882005-03-15 16:33:38 +00003040static UChar* mkFormXFX ( UChar* p, UInt r1, UInt f2, UInt opc2 )
cerion33aa6da2005-02-16 10:25:26 +00003041{
sewardj9a036bf2005-03-14 18:19:08 +00003042 UInt theInstr;
cerionf0de28c2005-12-13 20:21:11 +00003043 vassert(r1 < 0x20);
3044 vassert(f2 < 0x20);
ceriona2f75882005-03-15 16:33:38 +00003045 vassert(opc2 < 0x400);
3046 switch (opc2) {
cerion33aa6da2005-02-16 10:25:26 +00003047 case 144: // mtcrf
3048 vassert(f2 < 0x100);
3049 f2 = f2 << 1;
3050 break;
3051 case 339: // mfspr
3052 case 371: // mftb
3053 case 467: // mtspr
3054 vassert(f2 < 0x400);
cerion5b2325f2005-12-23 00:55:09 +00003055 // re-arrange split field
3056 f2 = ((f2>>5) & 0x1F) | ((f2 & 0x1F)<<5);
cerion33aa6da2005-02-16 10:25:26 +00003057 break;
cerion5b2325f2005-12-23 00:55:09 +00003058 default: vpanic("mkFormXFX(ppch)");
cerion33aa6da2005-02-16 10:25:26 +00003059 }
ceriona2f75882005-03-15 16:33:38 +00003060 theInstr = ((31<<26) | (r1<<21) | (f2<<11) | (opc2<<1));
cerion33aa6da2005-02-16 10:25:26 +00003061 return emit32(p, theInstr);
3062}
3063
cerion094d1392005-06-20 13:45:57 +00003064// Only used by mtfsf
sewardjc6bbd472012-04-02 10:20:48 +00003065static UChar* mkFormXFL ( UChar* p, UInt FM, UInt freg, UInt dfp_rm )
cerion094d1392005-06-20 13:45:57 +00003066{
3067 UInt theInstr;
3068 vassert(FM < 0x100);
3069 vassert(freg < 0x20);
sewardjc6bbd472012-04-02 10:20:48 +00003070 theInstr = ((63<<26) | (FM<<17) | (dfp_rm<<16) | (freg<<11) | (711<<1));
cerion094d1392005-06-20 13:45:57 +00003071 return emit32(p, theInstr);
3072}
3073
cerionf0de28c2005-12-13 20:21:11 +00003074static UChar* mkFormXS ( UChar* p, UInt opc1, UInt r1, UInt r2,
3075 UInt imm, UInt opc2, UInt b0 )
3076{
3077 UInt theInstr;
3078 vassert(opc1 < 0x40);
3079 vassert(r1 < 0x20);
3080 vassert(r2 < 0x20);
3081 vassert(imm < 0x40);
3082 vassert(opc2 < 0x400);
3083 vassert(b0 < 0x2);
3084 theInstr = ((opc1<<26) | (r1<<21) | (r2<<16) |
3085 ((imm & 0x1F)<<11) | (opc2<<2) | ((imm>>5)<<1) | (b0));
3086 return emit32(p, theInstr);
3087}
3088
3089
cerion33aa6da2005-02-16 10:25:26 +00003090#if 0
3091// 'b'
3092static UChar* mkFormI ( UChar* p, UInt LI, UInt AA, UInt LK )
3093{
sewardj9a036bf2005-03-14 18:19:08 +00003094 UInt theInstr;
cerion33aa6da2005-02-16 10:25:26 +00003095 vassert(LI < 0x1000000);
3096 vassert(AA < 0x2);
3097 vassert(LK < 0x2);
sewardj9a036bf2005-03-14 18:19:08 +00003098 theInstr = ((18<<26) | (LI<<2) | (AA<<1) | (LK));
cerion33aa6da2005-02-16 10:25:26 +00003099 return emit32(p, theInstr);
3100}
3101#endif
3102
3103// 'bc'
3104static UChar* mkFormB ( UChar* p, UInt BO, UInt BI,
3105 UInt BD, UInt AA, UInt LK )
3106{
sewardj9a036bf2005-03-14 18:19:08 +00003107 UInt theInstr;
cerion33aa6da2005-02-16 10:25:26 +00003108 vassert(BO < 0x20);
3109 vassert(BI < 0x20);
3110 vassert(BD < 0x4000);
3111 vassert(AA < 0x2);
3112 vassert(LK < 0x2);
cerion5b2325f2005-12-23 00:55:09 +00003113 theInstr = ((16<<26) | (BO<<21) | (BI<<16) |
3114 (BD<<2) | (AA<<1) | (LK));
cerion33aa6da2005-02-16 10:25:26 +00003115 return emit32(p, theInstr);
3116}
3117
cerion33aa6da2005-02-16 10:25:26 +00003118// rotates
ceriona2f75882005-03-15 16:33:38 +00003119static UChar* mkFormM ( UChar* p, UInt opc1, UInt r1, UInt r2,
cerion33aa6da2005-02-16 10:25:26 +00003120 UInt f3, UInt MB, UInt ME, UInt Rc )
3121{
sewardj9a036bf2005-03-14 18:19:08 +00003122 UInt theInstr;
ceriona2f75882005-03-15 16:33:38 +00003123 vassert(opc1 < 0x40);
cerionf0de28c2005-12-13 20:21:11 +00003124 vassert(r1 < 0x20);
3125 vassert(r2 < 0x20);
3126 vassert(f3 < 0x20);
3127 vassert(MB < 0x20);
3128 vassert(ME < 0x20);
3129 vassert(Rc < 0x2);
ceriona2f75882005-03-15 16:33:38 +00003130 theInstr = ((opc1<<26) | (r1<<21) | (r2<<16) |
sewardj9a036bf2005-03-14 18:19:08 +00003131 (f3<<11) | (MB<<6) | (ME<<1) | (Rc));
cerion33aa6da2005-02-16 10:25:26 +00003132 return emit32(p, theInstr);
3133}
cerion33aa6da2005-02-16 10:25:26 +00003134
cerion094d1392005-06-20 13:45:57 +00003135static UChar* mkFormA ( UChar* p, UInt opc1, UInt r1, UInt r2,
3136 UInt r3, UInt r4, UInt opc2, UInt b0 )
3137{
3138 UInt theInstr;
3139 vassert(opc1 < 0x40);
3140 vassert(r1 < 0x20);
3141 vassert(r2 < 0x20);
3142 vassert(r3 < 0x20);
3143 vassert(r4 < 0x20);
3144 vassert(opc2 < 0x20);
3145 vassert(b0 < 0x2 );
3146 theInstr = ((opc1<<26) | (r1<<21) | (r2<<16) | (r3<<11) |
3147 (r4<<6) | (opc2<<1) | (b0));
3148 return emit32(p, theInstr);
3149}
3150
sewardj26217b02012-04-12 17:19:48 +00003151static UChar* mkFormZ22 ( UChar* p, UInt opc1, UInt r1, UInt r2,
3152 UInt constant, UInt opc2, UInt b0 )
3153{
3154 UInt theInstr;
3155 vassert(opc1 < 0x40);
3156 vassert(r1 < 0x20);
3157 vassert(r2 < 0x20);
3158 vassert(constant < 0x40); /* 6 bit constant */
3159 vassert(opc2 < 0x200); /* 9 bit field */
3160 vassert(b0 < 0x2);
3161 theInstr = ((opc1<<26) | (r1<<21) | (r2<<16) |
3162 (constant<<10) | (opc2<<1) | (b0));
3163 return emit32(p, theInstr);
3164}
3165
sewardjcdc376d2012-04-23 11:21:12 +00003166static UChar* mkFormZ23 ( UChar* p, UInt opc1, UInt r1, UInt r2,
3167 UInt r3, UInt rmc, UInt opc2, UInt b0 )
3168{
3169 UInt theInstr;
3170 vassert(opc1 < 0x40);
3171 vassert(r1 < 0x20);
3172 vassert(r2 < 0x20);
3173 vassert(r3 < 0x20);
3174 vassert(rmc < 0x4);
3175 vassert(opc2 < 0x100);
3176 vassert(b0 < 0x2);
3177 theInstr = ((opc1<<26) | (r1<<21) | (r2<<16) |
3178 (r3<<11) | (rmc<<9) | (opc2<<1) | (b0));
3179 return emit32(p, theInstr);
3180}
3181
cerionf0de28c2005-12-13 20:21:11 +00003182static UChar* doAMode_IR ( UChar* p, UInt opc1, UInt rSD,
cerion5b2325f2005-12-23 00:55:09 +00003183 PPCAMode* am, Bool mode64 )
ceriond5e38382005-02-11 13:38:15 +00003184{
cerioned623db2005-06-20 12:42:04 +00003185 UInt rA, idx;
ceriond5e38382005-02-11 13:38:15 +00003186 vassert(am->tag == Pam_IR);
ceriona2f75882005-03-15 16:33:38 +00003187 vassert(am->Pam.IR.index < 0x10000);
3188
cerionf0de28c2005-12-13 20:21:11 +00003189 rA = iregNo(am->Pam.IR.base, mode64);
sewardj9a036bf2005-03-14 18:19:08 +00003190 idx = am->Pam.IR.index;
ceriona2f75882005-03-15 16:33:38 +00003191
cerionf0de28c2005-12-13 20:21:11 +00003192 if (opc1 == 58 || opc1 == 62) { // ld/std: mode64 only
3193 vassert(mode64);
sewardj34085e32007-03-09 18:07:00 +00003194 /* stay sane with DS form: lowest 2 bits must be 00. This
3195 should be guaranteed to us by iselWordExpr_AMode. */
3196 vassert(0 == (idx & 3));
cerionf0de28c2005-12-13 20:21:11 +00003197 }
ceriona2f75882005-03-15 16:33:38 +00003198 p = mkFormD(p, opc1, rSD, rA, idx);
ceriond5e38382005-02-11 13:38:15 +00003199 return p;
3200}
3201
ceriona2f75882005-03-15 16:33:38 +00003202static UChar* doAMode_RR ( UChar* p, UInt opc1, UInt opc2,
cerion5b2325f2005-12-23 00:55:09 +00003203 UInt rSD, PPCAMode* am, Bool mode64 )
ceriond5e38382005-02-11 13:38:15 +00003204{
cerioned623db2005-06-20 12:42:04 +00003205 UInt rA, rB;
ceriond5e38382005-02-11 13:38:15 +00003206 vassert(am->tag == Pam_RR);
ceriona2f75882005-03-15 16:33:38 +00003207
cerionf0de28c2005-12-13 20:21:11 +00003208 rA = iregNo(am->Pam.RR.base, mode64);
3209 rB = iregNo(am->Pam.RR.index, mode64);
ceriona2f75882005-03-15 16:33:38 +00003210
3211 p = mkFormX(p, opc1, rSD, rA, rB, opc2, 0);
ceriond5e38382005-02-11 13:38:15 +00003212 return p;
3213}
3214
cerionf0de28c2005-12-13 20:21:11 +00003215
cerione97e1062005-02-21 15:09:19 +00003216/* Load imm to r_dst */
cerionf0de28c2005-12-13 20:21:11 +00003217static UChar* mkLoadImm ( UChar* p, UInt r_dst, ULong imm, Bool mode64 )
cerione97e1062005-02-21 15:09:19 +00003218{
3219 vassert(r_dst < 0x20);
3220
sewardjafd16392006-05-06 14:40:40 +00003221 if (!mode64) {
3222 /* In 32-bit mode, make sure the top 32 bits of imm are a sign
3223 extension of the bottom 32 bits, so that the range tests
3224 below work correctly. */
3225 UInt u32 = (UInt)imm;
3226 Int s32 = (Int)u32;
3227 Long s64 = (Long)s32;
3228 imm = (ULong)s64;
3229 }
3230
cerion5b2325f2005-12-23 00:55:09 +00003231 if (imm >= 0xFFFFFFFFFFFF8000ULL || imm < 0x8000) {
cerionf0de28c2005-12-13 20:21:11 +00003232 // sign-extendable from 16 bits
3233
cerione97e1062005-02-21 15:09:19 +00003234 // addi r_dst,0,imm => li r_dst,imm
sewardjb51f0f42005-07-18 11:38:02 +00003235 p = mkFormD(p, 14, r_dst, 0, imm & 0xFFFF);
cerione97e1062005-02-21 15:09:19 +00003236 } else {
cerion5b2325f2005-12-23 00:55:09 +00003237 if (imm >= 0xFFFFFFFF80000000ULL || imm < 0x80000000ULL) {
cerionf0de28c2005-12-13 20:21:11 +00003238 // sign-extendable from 32 bits
3239
3240 // addis r_dst,r0,(imm>>16) => lis r_dst, (imm>>16)
3241 p = mkFormD(p, 15, r_dst, 0, (imm>>16) & 0xFFFF);
3242 // ori r_dst, r_dst, (imm & 0xFFFF)
3243 p = mkFormD(p, 24, r_dst, r_dst, imm & 0xFFFF);
3244 } else {
3245 // full 64bit immediate load: 5 (five!) insns.
3246 vassert(mode64);
3247
3248 // load high word
sewardjaca070a2006-10-17 00:28:22 +00003249
cerionf0de28c2005-12-13 20:21:11 +00003250 // lis r_dst, (imm>>48) & 0xFFFF
3251 p = mkFormD(p, 15, r_dst, 0, (imm>>48) & 0xFFFF);
sewardjaca070a2006-10-17 00:28:22 +00003252
cerionf0de28c2005-12-13 20:21:11 +00003253 // ori r_dst, r_dst, (imm>>32) & 0xFFFF
sewardjaca070a2006-10-17 00:28:22 +00003254 if ((imm>>32) & 0xFFFF)
3255 p = mkFormD(p, 24, r_dst, r_dst, (imm>>32) & 0xFFFF);
cerionf0de28c2005-12-13 20:21:11 +00003256
3257 // shift r_dst low word to high word => rldicr
3258 p = mkFormMD(p, 30, r_dst, r_dst, 32, 31, 1);
3259
3260 // load low word
sewardjaca070a2006-10-17 00:28:22 +00003261
cerionf0de28c2005-12-13 20:21:11 +00003262 // oris r_dst, r_dst, (imm>>16) & 0xFFFF
sewardjaca070a2006-10-17 00:28:22 +00003263 if ((imm>>16) & 0xFFFF)
3264 p = mkFormD(p, 25, r_dst, r_dst, (imm>>16) & 0xFFFF);
3265
cerionf0de28c2005-12-13 20:21:11 +00003266 // ori r_dst, r_dst, (imm) & 0xFFFF
sewardjaca070a2006-10-17 00:28:22 +00003267 if (imm & 0xFFFF)
3268 p = mkFormD(p, 24, r_dst, r_dst, imm & 0xFFFF);
cerionf0de28c2005-12-13 20:21:11 +00003269 }
cerione97e1062005-02-21 15:09:19 +00003270 }
3271 return p;
3272}
3273
sewardj3dee8492012-04-20 00:13:28 +00003274/* A simplified version of mkLoadImm that always generates 2 or 5
3275 instructions (32 or 64 bits respectively) even if it could generate
3276 fewer. This is needed for generating fixed sized patchable
3277 sequences. */
3278static UChar* mkLoadImm_EXACTLY2or5 ( UChar* p,
3279 UInt r_dst, ULong imm, Bool mode64 )
3280{
3281 vassert(r_dst < 0x20);
3282
3283 if (!mode64) {
3284 /* In 32-bit mode, make sure the top 32 bits of imm are a sign
3285 extension of the bottom 32 bits. (Probably unnecessary.) */
3286 UInt u32 = (UInt)imm;
3287 Int s32 = (Int)u32;
3288 Long s64 = (Long)s32;
3289 imm = (ULong)s64;
3290 }
3291
3292 if (!mode64) {
3293 // addis r_dst,r0,(imm>>16) => lis r_dst, (imm>>16)
3294 p = mkFormD(p, 15, r_dst, 0, (imm>>16) & 0xFFFF);
3295 // ori r_dst, r_dst, (imm & 0xFFFF)
3296 p = mkFormD(p, 24, r_dst, r_dst, imm & 0xFFFF);
3297
3298 } else {
3299 // full 64bit immediate load: 5 (five!) insns.
3300
3301 // load high word
3302 // lis r_dst, (imm>>48) & 0xFFFF
3303 p = mkFormD(p, 15, r_dst, 0, (imm>>48) & 0xFFFF);
3304
3305 // ori r_dst, r_dst, (imm>>32) & 0xFFFF
3306 p = mkFormD(p, 24, r_dst, r_dst, (imm>>32) & 0xFFFF);
3307
3308 // shift r_dst low word to high word => rldicr
3309 p = mkFormMD(p, 30, r_dst, r_dst, 32, 31, 1);
3310
3311 // load low word
3312 // oris r_dst, r_dst, (imm>>16) & 0xFFFF
3313 p = mkFormD(p, 25, r_dst, r_dst, (imm>>16) & 0xFFFF);
3314
3315 // ori r_dst, r_dst, (imm) & 0xFFFF
3316 p = mkFormD(p, 24, r_dst, r_dst, imm & 0xFFFF);
3317 }
3318 return p;
3319}
3320
3321/* Checks whether the sequence of bytes at p was indeed created
3322 by mkLoadImm_EXACTLY2or5 with the given parameters. */
3323static Bool isLoadImm_EXACTLY2or5 ( UChar* p_to_check,
3324 UInt r_dst, ULong imm, Bool mode64 )
3325{
3326 vassert(r_dst < 0x20);
3327
3328 if (!mode64) {
3329 /* In 32-bit mode, make sure the top 32 bits of imm are a sign
3330 extension of the bottom 32 bits. (Probably unnecessary.) */
3331 UInt u32 = (UInt)imm;
3332 Int s32 = (Int)u32;
3333 Long s64 = (Long)s32;
3334 imm = (ULong)s64;
3335 }
3336
3337 if (!mode64) {
3338 UInt expect[2] = { 0, 0 };
3339 UChar* p = (UChar*)&expect[0];
3340 // addis r_dst,r0,(imm>>16) => lis r_dst, (imm>>16)
3341 p = mkFormD(p, 15, r_dst, 0, (imm>>16) & 0xFFFF);
3342 // ori r_dst, r_dst, (imm & 0xFFFF)
3343 p = mkFormD(p, 24, r_dst, r_dst, imm & 0xFFFF);
3344 vassert(p == (UChar*)&expect[2]);
3345
3346 return fetch32(p_to_check + 0) == expect[0]
3347 && fetch32(p_to_check + 4) == expect[1];
3348
3349 } else {
3350 UInt expect[5] = { 0, 0, 0, 0, 0 };
3351 UChar* p = (UChar*)&expect[0];
3352 // full 64bit immediate load: 5 (five!) insns.
3353
3354 // load high word
3355 // lis r_dst, (imm>>48) & 0xFFFF
3356 p = mkFormD(p, 15, r_dst, 0, (imm>>48) & 0xFFFF);
3357
3358 // ori r_dst, r_dst, (imm>>32) & 0xFFFF
3359 p = mkFormD(p, 24, r_dst, r_dst, (imm>>32) & 0xFFFF);
3360
3361 // shift r_dst low word to high word => rldicr
3362 p = mkFormMD(p, 30, r_dst, r_dst, 32, 31, 1);
3363
3364 // load low word
3365 // oris r_dst, r_dst, (imm>>16) & 0xFFFF
3366 p = mkFormD(p, 25, r_dst, r_dst, (imm>>16) & 0xFFFF);
3367
3368 // ori r_dst, r_dst, (imm) & 0xFFFF
3369 p = mkFormD(p, 24, r_dst, r_dst, imm & 0xFFFF);
3370
3371 vassert(p == (UChar*)&expect[5]);
3372
3373 return fetch32(p_to_check + 0) == expect[0]
3374 && fetch32(p_to_check + 4) == expect[1]
3375 && fetch32(p_to_check + 8) == expect[2]
3376 && fetch32(p_to_check + 12) == expect[3]
3377 && fetch32(p_to_check + 16) == expect[4];
3378 }
3379}
3380
3381
3382/* Generate a machine-word sized load or store. Simplified version of
3383 the Pin_Load and Pin_Store cases below. */
3384static UChar* do_load_or_store_machine_word (
3385 UChar* p, Bool isLoad,
3386 UInt reg, PPCAMode* am, Bool mode64 )
3387{
3388 if (isLoad) {
3389 UInt opc1, sz = mode64 ? 8 : 4;
3390 switch (am->tag) {
3391 case Pam_IR:
3392 if (mode64) {
3393 vassert(0 == (am->Pam.IR.index & 3));
3394 }
3395 switch (sz) {
3396 case 4: opc1 = 32; vassert(!mode64); break;
3397 case 8: opc1 = 58; vassert(mode64); break;
3398 default: vassert(0);
3399 }
3400 p = doAMode_IR(p, opc1, reg, am, mode64);
3401 break;
3402 case Pam_RR:
3403 /* we could handle this case, but we don't expect to ever
3404 need to. */
3405 vassert(0);
3406 default:
3407 vassert(0);
3408 }
3409 } else /*store*/ {
3410 UInt opc1, sz = mode64 ? 8 : 4;
3411 switch (am->tag) {
3412 case Pam_IR:
3413 if (mode64) {
3414 vassert(0 == (am->Pam.IR.index & 3));
3415 }
3416 switch (sz) {
3417 case 4: opc1 = 36; vassert(!mode64); break;
3418 case 8: opc1 = 62; vassert(mode64); break;
3419 default: vassert(0);
3420 }
3421 p = doAMode_IR(p, opc1, reg, am, mode64);
3422 break;
3423 case Pam_RR:
3424 /* we could handle this case, but we don't expect to ever
3425 need to. */
3426 vassert(0);
3427 default:
3428 vassert(0);
3429 }
3430 }
3431 return p;
3432}
3433
3434/* Generate a 32-bit sized load or store. Simplified version of
3435 do_load_or_store_machine_word above. */
3436static UChar* do_load_or_store_word32 (
3437 UChar* p, Bool isLoad,
3438 UInt reg, PPCAMode* am, Bool mode64 )
3439{
3440 if (isLoad) {
3441 UInt opc1;
3442 switch (am->tag) {
3443 case Pam_IR:
3444 if (mode64) {
3445 vassert(0 == (am->Pam.IR.index & 3));
3446 }
3447 opc1 = 32;
3448 p = doAMode_IR(p, opc1, reg, am, mode64);
3449 break;
3450 case Pam_RR:
3451 /* we could handle this case, but we don't expect to ever
3452 need to. */
3453 vassert(0);
3454 default:
3455 vassert(0);
3456 }
3457 } else /*store*/ {
3458 UInt opc1;
3459 switch (am->tag) {
3460 case Pam_IR:
3461 if (mode64) {
3462 vassert(0 == (am->Pam.IR.index & 3));
3463 }
3464 opc1 = 36;
3465 p = doAMode_IR(p, opc1, reg, am, mode64);
3466 break;
3467 case Pam_RR:
3468 /* we could handle this case, but we don't expect to ever
3469 need to. */
3470 vassert(0);
3471 default:
3472 vassert(0);
3473 }
3474 }
3475 return p;
3476}
3477
cerione97e1062005-02-21 15:09:19 +00003478/* Move r_dst to r_src */
3479static UChar* mkMoveReg ( UChar* p, UInt r_dst, UInt r_src )
3480{
3481 vassert(r_dst < 0x20);
3482 vassert(r_src < 0x20);
3483
3484 if (r_dst != r_src) {
3485 /* or r_dst, r_src, r_src */
3486 p = mkFormX(p, 31, r_src, r_dst, r_src, 444, 0 );
3487 }
3488 return p;
3489}
3490
cerionc3d8bdc2005-06-28 18:06:23 +00003491static UChar* mkFormVX ( UChar* p, UInt opc1, UInt r1, UInt r2,
3492 UInt r3, UInt opc2 )
3493{
3494 UInt theInstr;
3495 vassert(opc1 < 0x40);
3496 vassert(r1 < 0x20);
3497 vassert(r2 < 0x20);
3498 vassert(r3 < 0x20);
3499 vassert(opc2 < 0x800);
cerion6b6f59e2005-06-28 20:59:18 +00003500 theInstr = ((opc1<<26) | (r1<<21) | (r2<<16) | (r3<<11) | opc2);
3501 return emit32(p, theInstr);
3502}
3503
cerion8ea0d3e2005-11-14 00:44:47 +00003504static UChar* mkFormVXR ( UChar* p, UInt opc1, UInt r1, UInt r2,
3505 UInt r3, UInt Rc, UInt opc2 )
cerion6b6f59e2005-06-28 20:59:18 +00003506{
3507 UInt theInstr;
3508 vassert(opc1 < 0x40);
3509 vassert(r1 < 0x20);
3510 vassert(r2 < 0x20);
3511 vassert(r3 < 0x20);
3512 vassert(Rc < 0x2);
3513 vassert(opc2 < 0x400);
cerion5b2325f2005-12-23 00:55:09 +00003514 theInstr = ((opc1<<26) | (r1<<21) | (r2<<16) |
3515 (r3<<11) | (Rc<<10) | opc2);
cerionc3d8bdc2005-06-28 18:06:23 +00003516 return emit32(p, theInstr);
3517}
3518
3519static UChar* mkFormVA ( UChar* p, UInt opc1, UInt r1, UInt r2,
3520 UInt r3, UInt r4, UInt opc2 )
3521{
3522 UInt theInstr;
3523 vassert(opc1 < 0x40);
3524 vassert(r1 < 0x20);
3525 vassert(r2 < 0x20);
3526 vassert(r3 < 0x20);
3527 vassert(r4 < 0x20);
3528 vassert(opc2 < 0x40);
cerion5b2325f2005-12-23 00:55:09 +00003529 theInstr = ((opc1<<26) | (r1<<21) | (r2<<16) |
3530 (r3<<11) | (r4<<6) | opc2);
cerionc3d8bdc2005-06-28 18:06:23 +00003531 return emit32(p, theInstr);
3532}
3533
3534
ceriond5e38382005-02-11 13:38:15 +00003535
cerionbcf8c3e2005-02-04 16:17:07 +00003536/* Emit an instruction into buf and return the number of bytes used.
3537 Note that buf is not the insn's final place, and therefore it is
sewardj3dee8492012-04-20 00:13:28 +00003538 imperative to emit position-independent code. If the emitted
3539 instruction was a profiler inc, set *is_profInc to True, else leave
3540 it unchanged.
sewardjb8a8dba2005-12-15 21:33:50 +00003541*/
sewardj3dee8492012-04-20 00:13:28 +00003542Int emit_PPCInstr ( /*MB_MOD*/Bool* is_profInc,
3543 UChar* buf, Int nbuf, PPCInstr* i,
sewardj010ac542011-05-29 09:29:18 +00003544 Bool mode64,
sewardj3dee8492012-04-20 00:13:28 +00003545 void* disp_cp_chain_me_to_slowEP,
3546 void* disp_cp_chain_me_to_fastEP,
3547 void* disp_cp_xindir,
3548 void* disp_cp_xassisted )
cerionbcf8c3e2005-02-04 16:17:07 +00003549{
cerionbcf8c3e2005-02-04 16:17:07 +00003550 UChar* p = &buf[0];
cerion7cf8e4e2005-02-16 16:08:17 +00003551 vassert(nbuf >= 32);
cerion2c49e032005-02-09 17:29:49 +00003552
sewardj7fd5bb02006-01-26 02:24:17 +00003553 if (0) {
3554 vex_printf("asm ");ppPPCInstr(i, mode64); vex_printf("\n");
3555 }
cerionbcf8c3e2005-02-04 16:17:07 +00003556
3557 switch (i->tag) {
3558
cerionf0de28c2005-12-13 20:21:11 +00003559 case Pin_LI:
3560 p = mkLoadImm(p, iregNo(i->Pin.LI.dst, mode64),
3561 i->Pin.LI.imm64, mode64);
sewardjb51f0f42005-07-18 11:38:02 +00003562 goto done;
3563
cerionf0de28c2005-12-13 20:21:11 +00003564 case Pin_Alu: {
cerion5b2325f2005-12-23 00:55:09 +00003565 PPCRH* srcR = i->Pin.Alu.srcR;
3566 Bool immR = toBool(srcR->tag == Prh_Imm);
3567 UInt r_dst = iregNo(i->Pin.Alu.dst, mode64);
3568 UInt r_srcL = iregNo(i->Pin.Alu.srcL, mode64);
3569 UInt r_srcR = immR ? (-1)/*bogus*/ :
3570 iregNo(srcR->Prh.Reg.reg, mode64);
cerion2c49e032005-02-09 17:29:49 +00003571
cerionf0de28c2005-12-13 20:21:11 +00003572 switch (i->Pin.Alu.op) {
sewardjb51f0f42005-07-18 11:38:02 +00003573 case Palu_ADD:
3574 if (immR) {
3575 /* addi (PPC32 p350) */
3576 vassert(srcR->Prh.Imm.syned);
3577 vassert(srcR->Prh.Imm.imm16 != 0x8000);
3578 p = mkFormD(p, 14, r_dst, r_srcL, srcR->Prh.Imm.imm16);
cerion9e263e32005-03-03 17:21:51 +00003579 } else {
sewardjb51f0f42005-07-18 11:38:02 +00003580 /* add (PPC32 p347) */
3581 p = mkFormXO(p, 31, r_dst, r_srcL, r_srcR, 0, 266, 0);
cerionab9132d2005-02-15 15:46:59 +00003582 }
sewardjb51f0f42005-07-18 11:38:02 +00003583 break;
cerionab9132d2005-02-15 15:46:59 +00003584
sewardjb51f0f42005-07-18 11:38:02 +00003585 case Palu_SUB:
3586 if (immR) {
3587 /* addi (PPC32 p350), but with negated imm */
3588 vassert(srcR->Prh.Imm.syned);
3589 vassert(srcR->Prh.Imm.imm16 != 0x8000);
3590 p = mkFormD(p, 14, r_dst, r_srcL, (- srcR->Prh.Imm.imm16));
cerion9e263e32005-03-03 17:21:51 +00003591 } else {
sewardjb51f0f42005-07-18 11:38:02 +00003592 /* subf (PPC32 p537), with args the "wrong" way round */
3593 p = mkFormXO(p, 31, r_dst, r_srcR, r_srcL, 0, 40, 0);
cerionab9132d2005-02-15 15:46:59 +00003594 }
cerion5e2527e2005-02-25 16:39:58 +00003595 break;
cerion5e2527e2005-02-25 16:39:58 +00003596
sewardjb51f0f42005-07-18 11:38:02 +00003597 case Palu_AND:
3598 if (immR) {
3599 /* andi. (PPC32 p358) */
3600 vassert(!srcR->Prh.Imm.syned);
3601 p = mkFormD(p, 28, r_srcL, r_dst, srcR->Prh.Imm.imm16);
3602 } else {
3603 /* and (PPC32 p356) */
3604 p = mkFormX(p, 31, r_srcL, r_dst, r_srcR, 28, 0);
cerion9e263e32005-03-03 17:21:51 +00003605 }
cerionb85e8bb2005-02-16 08:54:33 +00003606 break;
cerion9e263e32005-03-03 17:21:51 +00003607
sewardjb51f0f42005-07-18 11:38:02 +00003608 case Palu_OR:
3609 if (immR) {
3610 /* ori (PPC32 p497) */
3611 vassert(!srcR->Prh.Imm.syned);
3612 p = mkFormD(p, 24, r_srcL, r_dst, srcR->Prh.Imm.imm16);
3613 } else {
3614 /* or (PPC32 p495) */
3615 p = mkFormX(p, 31, r_srcL, r_dst, r_srcR, 444, 0);
3616 }
3617 break;
3618
3619 case Palu_XOR:
3620 if (immR) {
3621 /* xori (PPC32 p550) */
3622 vassert(!srcR->Prh.Imm.syned);
3623 p = mkFormD(p, 26, r_srcL, r_dst, srcR->Prh.Imm.imm16);
3624 } else {
3625 /* xor (PPC32 p549) */
3626 p = mkFormX(p, 31, r_srcL, r_dst, r_srcR, 316, 0);
3627 }
3628 break;
3629
cerionbb01b7c2005-12-16 13:40:18 +00003630 default:
3631 goto bad;
3632 }
3633 goto done;
3634 }
3635
3636 case Pin_Shft: {
cerion5b2325f2005-12-23 00:55:09 +00003637 PPCRH* srcR = i->Pin.Shft.srcR;
3638 Bool sz32 = i->Pin.Shft.sz32;
3639 Bool immR = toBool(srcR->tag == Prh_Imm);
3640 UInt r_dst = iregNo(i->Pin.Shft.dst, mode64);
3641 UInt r_srcL = iregNo(i->Pin.Shft.srcL, mode64);
3642 UInt r_srcR = immR ? (-1)/*bogus*/ :
3643 iregNo(srcR->Prh.Reg.reg, mode64);
cerionbb01b7c2005-12-16 13:40:18 +00003644 if (!mode64)
3645 vassert(sz32);
3646
3647 switch (i->Pin.Shft.op) {
3648 case Pshft_SHL:
3649 if (sz32) {
cerionf0de28c2005-12-13 20:21:11 +00003650 if (immR) {
3651 /* rd = rs << n, 1 <= n <= 31
3652 is
3653 rlwinm rd,rs,n,0,31-n (PPC32 p501)
3654 */
3655 UInt n = srcR->Prh.Imm.imm16;
3656 vassert(!srcR->Prh.Imm.syned);
3657 vassert(n > 0 && n < 32);
3658 p = mkFormM(p, 21, r_srcL, r_dst, n, 0, 31-n, 0);
3659 } else {
3660 /* slw (PPC32 p505) */
3661 p = mkFormX(p, 31, r_srcL, r_dst, r_srcR, 24, 0);
3662 }
sewardjb51f0f42005-07-18 11:38:02 +00003663 } else {
cerionf0de28c2005-12-13 20:21:11 +00003664 if (immR) {
3665 /* rd = rs << n, 1 <= n <= 63
3666 is
3667 rldicr rd,rs,n,63-n (PPC64 p559)
3668 */
3669 UInt n = srcR->Prh.Imm.imm16;
3670 vassert(!srcR->Prh.Imm.syned);
3671 vassert(n > 0 && n < 64);
3672 p = mkFormMD(p, 30, r_srcL, r_dst, n, 63-n, 1);
3673 } else {
3674 /* sld (PPC64 p568) */
3675 p = mkFormX(p, 31, r_srcL, r_dst, r_srcR, 27, 0);
3676 }
sewardjb51f0f42005-07-18 11:38:02 +00003677 }
3678 break;
3679
cerionbb01b7c2005-12-16 13:40:18 +00003680 case Pshft_SHR:
3681 if (sz32) {
3682 if (immR) {
cerionf0de28c2005-12-13 20:21:11 +00003683 /* rd = rs >>u n, 1 <= n <= 31
3684 is
3685 rlwinm rd,rs,32-n,n,31 (PPC32 p501)
3686 */
3687 UInt n = srcR->Prh.Imm.imm16;
3688 vassert(!srcR->Prh.Imm.syned);
3689 vassert(n > 0 && n < 32);
3690 p = mkFormM(p, 21, r_srcL, r_dst, 32-n, n, 31, 0);
3691 } else {
3692 /* srw (PPC32 p508) */
3693 p = mkFormX(p, 31, r_srcL, r_dst, r_srcR, 536, 0);
3694 }
sewardjb51f0f42005-07-18 11:38:02 +00003695 } else {
cerionf0de28c2005-12-13 20:21:11 +00003696 if (immR) {
3697 /* rd = rs >>u n, 1 <= n <= 63
3698 is
3699 rldicl rd,rs,64-n,n (PPC64 p558)
3700 */
3701 UInt n = srcR->Prh.Imm.imm16;
3702 vassert(!srcR->Prh.Imm.syned);
3703 vassert(n > 0 && n < 64);
3704 p = mkFormMD(p, 30, r_srcL, r_dst, 64-n, n, 0);
3705 } else {
3706 /* srd (PPC64 p574) */
3707 p = mkFormX(p, 31, r_srcL, r_dst, r_srcR, 539, 0);
3708 }
sewardjb51f0f42005-07-18 11:38:02 +00003709 }
3710 break;
3711
cerionbb01b7c2005-12-16 13:40:18 +00003712 case Pshft_SAR:
3713 if (sz32) {
cerionf0de28c2005-12-13 20:21:11 +00003714 if (immR) {
3715 /* srawi (PPC32 p507) */
3716 UInt n = srcR->Prh.Imm.imm16;
3717 vassert(!srcR->Prh.Imm.syned);
sewardjeb17e492007-08-25 23:07:44 +00003718 /* In 64-bit mode, we allow right shifts by zero bits
3719 as that is a handy way to sign extend the lower 32
3720 bits into the upper 32 bits. */
3721 if (mode64)
3722 vassert(n >= 0 && n < 32);
3723 else
3724 vassert(n > 0 && n < 32);
cerionf0de28c2005-12-13 20:21:11 +00003725 p = mkFormX(p, 31, r_srcL, r_dst, n, 824, 0);
3726 } else {
3727 /* sraw (PPC32 p506) */
3728 p = mkFormX(p, 31, r_srcL, r_dst, r_srcR, 792, 0);
3729 }
sewardjb51f0f42005-07-18 11:38:02 +00003730 } else {
cerionf0de28c2005-12-13 20:21:11 +00003731 if (immR) {
3732 /* sradi (PPC64 p571) */
3733 UInt n = srcR->Prh.Imm.imm16;
3734 vassert(!srcR->Prh.Imm.syned);
3735 vassert(n > 0 && n < 64);
3736 p = mkFormXS(p, 31, r_srcL, r_dst, n, 413, 0);
3737 } else {
3738 /* srad (PPC32 p570) */
3739 p = mkFormX(p, 31, r_srcL, r_dst, r_srcR, 794, 0);
3740 }
sewardjb51f0f42005-07-18 11:38:02 +00003741 }
cerionb85e8bb2005-02-16 08:54:33 +00003742 break;
cerion9e263e32005-03-03 17:21:51 +00003743
cerionab9132d2005-02-15 15:46:59 +00003744 default:
3745 goto bad;
3746 }
cerionb85e8bb2005-02-16 08:54:33 +00003747 goto done;
cerionab9132d2005-02-15 15:46:59 +00003748 }
cerion2c49e032005-02-09 17:29:49 +00003749
cerion5b2325f2005-12-23 00:55:09 +00003750 case Pin_AddSubC: {
3751 Bool isAdd = i->Pin.AddSubC.isAdd;
3752 Bool setC = i->Pin.AddSubC.setC;
3753 UInt r_srcL = iregNo(i->Pin.AddSubC.srcL, mode64);
3754 UInt r_srcR = iregNo(i->Pin.AddSubC.srcR, mode64);
3755 UInt r_dst = iregNo(i->Pin.AddSubC.dst, mode64);
cerion4a49b032005-11-08 16:23:07 +00003756
3757 if (isAdd) {
3758 if (setC) /* addc (PPC32 p348) */
3759 p = mkFormXO(p, 31, r_dst, r_srcL, r_srcR, 0, 10, 0);
3760 else /* adde (PPC32 p349) */
3761 p = mkFormXO(p, 31, r_dst, r_srcL, r_srcR, 0, 138, 0);
3762 } else {
3763 /* subfX, with args the "wrong" way round */
3764 if (setC) /* subfc (PPC32 p538) */
3765 p = mkFormXO(p, 31, r_dst, r_srcR, r_srcL, 0, 8, 0);
3766 else /* subfe (PPC32 p539) */
3767 p = mkFormXO(p, 31, r_dst, r_srcR, r_srcL, 0, 136, 0);
3768 }
3769 goto done;
3770 }
3771
cerionf0de28c2005-12-13 20:21:11 +00003772 case Pin_Cmp: {
3773 Bool syned = i->Pin.Cmp.syned;
cerionbb01b7c2005-12-16 13:40:18 +00003774 Bool sz32 = i->Pin.Cmp.sz32;
cerionf0de28c2005-12-13 20:21:11 +00003775 UInt fld1 = i->Pin.Cmp.crfD << 2;
3776 UInt r_srcL = iregNo(i->Pin.Cmp.srcL, mode64);
ceriona2f75882005-03-15 16:33:38 +00003777 UInt r_srcR, imm_srcR;
cerion5b2325f2005-12-23 00:55:09 +00003778 PPCRH* srcR = i->Pin.Cmp.srcR;
cerionab9132d2005-02-15 15:46:59 +00003779
cerionbb01b7c2005-12-16 13:40:18 +00003780 if (!mode64) // cmp double word invalid for mode32
3781 vassert(sz32);
3782 else if (!sz32) // mode64 && cmp64: set L=1
3783 fld1 |= 1;
3784
sewardjb51f0f42005-07-18 11:38:02 +00003785 switch (srcR->tag) {
3786 case Prh_Imm:
cerionbb01b7c2005-12-16 13:40:18 +00003787 vassert(syned == srcR->Prh.Imm.syned);
sewardjb51f0f42005-07-18 11:38:02 +00003788 imm_srcR = srcR->Prh.Imm.imm16;
cerionbb01b7c2005-12-16 13:40:18 +00003789 if (syned) { // cmpw/di (signed) (PPC32 p368)
sewardjb51f0f42005-07-18 11:38:02 +00003790 vassert(imm_srcR != 0x8000);
cerionbb01b7c2005-12-16 13:40:18 +00003791 p = mkFormD(p, 11, fld1, r_srcL, imm_srcR);
3792 } else { // cmplw/di (unsigned) (PPC32 p370)
3793 p = mkFormD(p, 10, fld1, r_srcL, imm_srcR);
sewardjb51f0f42005-07-18 11:38:02 +00003794 }
cerion98411db2005-02-16 14:14:49 +00003795 break;
sewardjb51f0f42005-07-18 11:38:02 +00003796 case Prh_Reg:
cerionf0de28c2005-12-13 20:21:11 +00003797 r_srcR = iregNo(srcR->Prh.Reg.reg, mode64);
cerionbb01b7c2005-12-16 13:40:18 +00003798 if (syned) // cmpwi (signed) (PPC32 p367)
3799 p = mkFormX(p, 31, fld1, r_srcL, r_srcR, 0, 0);
3800 else // cmplwi (unsigned) (PPC32 p379)
3801 p = mkFormX(p, 31, fld1, r_srcL, r_srcR, 32, 0);
cerion98411db2005-02-16 14:14:49 +00003802 break;
sewardjb51f0f42005-07-18 11:38:02 +00003803 default:
3804 goto bad;
cerion98411db2005-02-16 14:14:49 +00003805 }
3806 goto done;
3807 }
cerionb536af92005-02-10 15:03:19 +00003808
cerionf0de28c2005-12-13 20:21:11 +00003809 case Pin_Unary: {
cerion5b2325f2005-12-23 00:55:09 +00003810 UInt r_dst = iregNo(i->Pin.Unary.dst, mode64);
3811 UInt r_src = iregNo(i->Pin.Unary.src, mode64);
cerion98411db2005-02-16 14:14:49 +00003812
cerion5b2325f2005-12-23 00:55:09 +00003813 switch (i->Pin.Unary.op) {
cerion98411db2005-02-16 14:14:49 +00003814 case Pun_NOT: // nor r_dst,r_src,r_src
3815 p = mkFormX(p, 31, r_src, r_dst, r_src, 124, 0);
3816 break;
3817 case Pun_NEG: // neg r_dst,r_src
3818 p = mkFormXO(p, 31, r_dst, r_src, 0, 0, 104, 0);
3819 break;
cerion07b07a92005-12-22 14:32:35 +00003820 case Pun_CLZ32: // cntlzw r_dst, r_src
cerion99f35772005-03-15 16:36:02 +00003821 p = mkFormX(p, 31, r_src, r_dst, 0, 26, 0);
cerion98411db2005-02-16 14:14:49 +00003822 break;
cerion07b07a92005-12-22 14:32:35 +00003823 case Pun_CLZ64: // cntlzd r_dst, r_src
sewardj7fd5bb02006-01-26 02:24:17 +00003824 vassert(mode64);
cerion07b07a92005-12-22 14:32:35 +00003825 p = mkFormX(p, 31, r_src, r_dst, 0, 58, 0);
3826 break;
sewardj7fd5bb02006-01-26 02:24:17 +00003827 case Pun_EXTSW: // extsw r_dst, r_src
3828 vassert(mode64);
3829 p = mkFormX(p, 31, r_src, r_dst, 0, 986, 0);
3830 break;
cerion98411db2005-02-16 14:14:49 +00003831 default: goto bad;
3832 }
3833 goto done;
3834 }
3835
3836 case Pin_MulL: {
3837 Bool syned = i->Pin.MulL.syned;
cerionbb01b7c2005-12-16 13:40:18 +00003838 Bool sz32 = i->Pin.MulL.sz32;
cerionf0de28c2005-12-13 20:21:11 +00003839 UInt r_dst = iregNo(i->Pin.MulL.dst, mode64);
3840 UInt r_srcL = iregNo(i->Pin.MulL.srcL, mode64);
3841 UInt r_srcR = iregNo(i->Pin.MulL.srcR, mode64);
cerionbb01b7c2005-12-16 13:40:18 +00003842
3843 if (!mode64)
3844 vassert(sz32);
cerion98411db2005-02-16 14:14:49 +00003845
cerionf0de28c2005-12-13 20:21:11 +00003846 if (i->Pin.MulL.hi) {
sewardjb51f0f42005-07-18 11:38:02 +00003847 // mul hi words, must consider sign
cerionbb01b7c2005-12-16 13:40:18 +00003848 if (sz32) {
3849 if (syned) // mulhw r_dst,r_srcL,r_srcR
cerionf0de28c2005-12-13 20:21:11 +00003850 p = mkFormXO(p, 31, r_dst, r_srcL, r_srcR, 0, 75, 0);
cerionbb01b7c2005-12-16 13:40:18 +00003851 else // mulhwu r_dst,r_srcL,r_srcR
cerionf0de28c2005-12-13 20:21:11 +00003852 p = mkFormXO(p, 31, r_dst, r_srcL, r_srcR, 0, 11, 0);
cerionbb01b7c2005-12-16 13:40:18 +00003853 } else {
3854 if (syned) // mulhd r_dst,r_srcL,r_srcR
3855 p = mkFormXO(p, 31, r_dst, r_srcL, r_srcR, 0, 73, 0);
3856 else // mulhdu r_dst,r_srcL,r_srcR
cerionf0de28c2005-12-13 20:21:11 +00003857 p = mkFormXO(p, 31, r_dst, r_srcL, r_srcR, 0, 9, 0);
cerion98411db2005-02-16 14:14:49 +00003858 }
sewardjb51f0f42005-07-18 11:38:02 +00003859 } else {
3860 // mul low word, sign is irrelevant
3861 vassert(!i->Pin.MulL.syned);
cerionbb01b7c2005-12-16 13:40:18 +00003862 if (sz32) // mullw r_dst,r_srcL,r_srcR
cerionf0de28c2005-12-13 20:21:11 +00003863 p = mkFormXO(p, 31, r_dst, r_srcL, r_srcR, 0, 235, 0);
cerionbb01b7c2005-12-16 13:40:18 +00003864 else // mulld r_dst,r_srcL,r_srcR
cerionf0de28c2005-12-13 20:21:11 +00003865 p = mkFormXO(p, 31, r_dst, r_srcL, r_srcR, 0, 233, 0);
cerion98411db2005-02-16 14:14:49 +00003866 }
3867 goto done;
3868 }
cerion2c49e032005-02-09 17:29:49 +00003869
cerionfd0b87f2005-02-16 14:43:14 +00003870 case Pin_Div: {
cerionf0de28c2005-12-13 20:21:11 +00003871 Bool syned = i->Pin.Div.syned;
cerionbb01b7c2005-12-16 13:40:18 +00003872 Bool sz32 = i->Pin.Div.sz32;
cerionf0de28c2005-12-13 20:21:11 +00003873 UInt r_dst = iregNo(i->Pin.Div.dst, mode64);
3874 UInt r_srcL = iregNo(i->Pin.Div.srcL, mode64);
3875 UInt r_srcR = iregNo(i->Pin.Div.srcR, mode64);
cerionfd0b87f2005-02-16 14:43:14 +00003876
cerionbb01b7c2005-12-16 13:40:18 +00003877 if (!mode64)
3878 vassert(sz32);
3879
sewardj4aa412a2011-07-24 14:13:21 +00003880 if (i->Pin.Div.extended) {
3881 if (sz32) {
3882 if (syned)
3883 // divwe r_dst,r_srcL,r_srcR
3884 p = mkFormXO(p, 31, r_dst, r_srcL, r_srcR, 0, 427, 0);
3885 else
3886 // divweu r_dst,r_srcL,r_srcR
3887 p = mkFormXO(p, 31, r_dst, r_srcL, r_srcR, 0, 395, 0);
3888 } else {
sewardje71e56a2011-09-05 12:11:06 +00003889 if (syned)
3890 // divde r_dst,r_srcL,r_srcR
3891 p = mkFormXO(p, 31, r_dst, r_srcL, r_srcR, 0, 425, 0);
3892 else
3893 // divdeu r_dst,r_srcL,r_srcR
3894 p = mkFormXO(p, 31, r_dst, r_srcL, r_srcR, 0, 393, 0);
sewardj4aa412a2011-07-24 14:13:21 +00003895 }
3896 } else if (sz32) {
cerionbb01b7c2005-12-16 13:40:18 +00003897 if (syned) // divw r_dst,r_srcL,r_srcR
cerionf0de28c2005-12-13 20:21:11 +00003898 p = mkFormXO(p, 31, r_dst, r_srcL, r_srcR, 0, 491, 0);
cerionbb01b7c2005-12-16 13:40:18 +00003899 else // divwu r_dst,r_srcL,r_srcR
cerionf0de28c2005-12-13 20:21:11 +00003900 p = mkFormXO(p, 31, r_dst, r_srcL, r_srcR, 0, 459, 0);
cerionbb01b7c2005-12-16 13:40:18 +00003901 } else {
3902 if (syned) // divd r_dst,r_srcL,r_srcR
3903 p = mkFormXO(p, 31, r_dst, r_srcL, r_srcR, 0, 489, 0);
3904 else // divdu r_dst,r_srcL,r_srcR
cerionf0de28c2005-12-13 20:21:11 +00003905 p = mkFormXO(p, 31, r_dst, r_srcL, r_srcR, 0, 457, 0);
cerionfd0b87f2005-02-16 14:43:14 +00003906 }
3907 goto done;
3908 }
cerion2c49e032005-02-09 17:29:49 +00003909
cerion33aa6da2005-02-16 10:25:26 +00003910 case Pin_Call: {
cerion5b2325f2005-12-23 00:55:09 +00003911 PPCCondCode cond = i->Pin.Call.cond;
3912 UInt r_dst = 10;
ceriona56e9cc2005-02-16 18:08:25 +00003913 /* As per detailed comment for Pin_Call in
cerion5b2325f2005-12-23 00:55:09 +00003914 getRegUsage_PPCInstr above, %r10 is used as an address temp */
ceriona56e9cc2005-02-16 18:08:25 +00003915
cerioned623db2005-06-20 12:42:04 +00003916 /* jump over the following insns if condition does not hold */
sewardj3dee8492012-04-20 00:13:28 +00003917 UChar* ptmp = NULL;
cerione97e1062005-02-21 15:09:19 +00003918 if (cond.test != Pct_ALWAYS) {
cerion9762bbf2005-06-23 08:44:52 +00003919 /* jmp fwds if !condition */
3920 /* don't know how many bytes to jump over yet...
3921 make space for a jump instruction and fill in later. */
3922 ptmp = p; /* fill in this bit later */
cerion5b2325f2005-12-23 00:55:09 +00003923 p += 4; // p += 4
cerionab9132d2005-02-15 15:46:59 +00003924 }
3925
cerion5b2325f2005-12-23 00:55:09 +00003926 /* load target to r_dst */ // p += 4|8|20
3927 p = mkLoadImm(p, r_dst, i->Pin.Call.target, mode64);
cerionab9132d2005-02-15 15:46:59 +00003928
ceriona56e9cc2005-02-16 18:08:25 +00003929 /* mtspr 9,r_dst => move r_dst to count register */
cerion5b2325f2005-12-23 00:55:09 +00003930 p = mkFormXFX(p, r_dst, 9, 467); // p += 4
cerion33aa6da2005-02-16 10:25:26 +00003931
cerion8c51ed42005-02-22 11:16:54 +00003932 /* bctrl => branch to count register (and save to lr) */
cerion5b2325f2005-12-23 00:55:09 +00003933 p = mkFormXL(p, 19, Pct_ALWAYS, 0, 0, 528, 1); // p += 4
cerion9762bbf2005-06-23 08:44:52 +00003934
3935 /* Fix up the conditional jump, if there was one. */
3936 if (cond.test != Pct_ALWAYS) {
3937 Int delta = p - ptmp;
cerionf0de28c2005-12-13 20:21:11 +00003938 vassert(delta >= 16 && delta <= 32);
cerion9762bbf2005-06-23 08:44:52 +00003939 /* bc !ct,cf,delta */
cerion5b2325f2005-12-23 00:55:09 +00003940 mkFormB(ptmp, invertCondTest(cond.test),
3941 cond.flag, (delta>>2), 0, 0);
cerion9762bbf2005-06-23 08:44:52 +00003942 }
cerion33aa6da2005-02-16 10:25:26 +00003943 goto done;
3944 }
3945
sewardj3dee8492012-04-20 00:13:28 +00003946 case Pin_XDirect: {
3947 /* NB: what goes on here has to be very closely coordinated
3948 with the chainXDirect_PPC and unchainXDirect_PPC below. */
3949 /* We're generating chain-me requests here, so we need to be
3950 sure this is actually allowed -- no-redir translations
3951 can't use chain-me's. Hence: */
3952 vassert(disp_cp_chain_me_to_slowEP != NULL);
3953 vassert(disp_cp_chain_me_to_fastEP != NULL);
sewardjb8a8dba2005-12-15 21:33:50 +00003954
sewardj3dee8492012-04-20 00:13:28 +00003955 /* First off, if this is conditional, create a conditional jump
3956 over the rest of it. Or at least, leave a space for it that
3957 we will shortly fill in. */
3958 UChar* ptmp = NULL;
3959 if (i->Pin.XDirect.cond.test != Pct_ALWAYS) {
3960 vassert(i->Pin.XDirect.cond.flag != Pcf_NONE);
3961 ptmp = p;
cerione97e1062005-02-21 15:09:19 +00003962 p += 4;
cerion33aa6da2005-02-16 10:25:26 +00003963 } else {
sewardj3dee8492012-04-20 00:13:28 +00003964 vassert(i->Pin.XDirect.cond.flag == Pcf_NONE);
cerion33aa6da2005-02-16 10:25:26 +00003965 }
sewardj3dee8492012-04-20 00:13:28 +00003966
3967 /* Update the guest CIA. */
3968 /* imm32/64 r30, dstGA */
3969 if (!mode64) vassert(0 == (((ULong)i->Pin.XDirect.dstGA) >> 32));
3970 p = mkLoadImm(p, /*r*/30, (ULong)i->Pin.XDirect.dstGA, mode64);
3971 /* stw/std r30, amCIA */
3972 p = do_load_or_store_machine_word(
3973 p, False/*!isLoad*/,
3974 /*r*/30, i->Pin.XDirect.amCIA, mode64
3975 );
3976
3977 /* --- FIRST PATCHABLE BYTE follows --- */
3978 /* VG_(disp_cp_chain_me_to_{slowEP,fastEP}) (where we're calling
3979 to) backs up the return address, so as to find the address of
3980 the first patchable byte. So: don't change the number of
3981 instructions (32-bit: 4, 64-bit: 7) below. */
3982 /* imm32/64-fixed r30, VG_(disp_cp_chain_me_to_{slowEP,fastEP} */
3983 void* disp_cp_chain_me
3984 = i->Pin.XDirect.toFastEP ? disp_cp_chain_me_to_fastEP
3985 : disp_cp_chain_me_to_slowEP;
3986 p = mkLoadImm_EXACTLY2or5(
3987 p, /*r*/30, Ptr_to_ULong(disp_cp_chain_me), mode64);
3988 /* mtctr r30 */
3989 p = mkFormXFX(p, /*r*/30, 9, 467);
3990 /* bctrl */
3991 p = mkFormXL(p, 19, Pct_ALWAYS, 0, 0, 528, 1);
3992 /* --- END of PATCHABLE BYTES --- */
cerion7cf8e4e2005-02-16 16:08:17 +00003993
3994 /* Fix up the conditional jump, if there was one. */
sewardj3dee8492012-04-20 00:13:28 +00003995 if (i->Pin.XDirect.cond.test != Pct_ALWAYS) {
cerion7cf8e4e2005-02-16 16:08:17 +00003996 Int delta = p - ptmp;
sewardj9e1cf152012-04-20 02:18:31 +00003997 vassert(delta >= 16 && delta <= 64 && 0 == (delta & 3));
cerione97e1062005-02-21 15:09:19 +00003998 /* bc !ct,cf,delta */
sewardj3dee8492012-04-20 00:13:28 +00003999 mkFormB(ptmp, invertCondTest(i->Pin.XDirect.cond.test),
4000 i->Pin.XDirect.cond.flag, (delta>>2), 0, 0);
4001 }
4002 goto done;
4003 }
4004
4005 case Pin_XIndir: {
4006 /* We're generating transfers that could lead indirectly to a
4007 chain-me, so we need to be sure this is actually allowed --
4008 no-redir translations are not allowed to reach normal
4009 translations without going through the scheduler. That means
4010 no XDirects or XIndirs out from no-redir translations.
4011 Hence: */
4012 vassert(disp_cp_xindir != NULL);
4013
4014 /* First off, if this is conditional, create a conditional jump
4015 over the rest of it. Or at least, leave a space for it that
4016 we will shortly fill in. */
4017 UChar* ptmp = NULL;
4018 if (i->Pin.XIndir.cond.test != Pct_ALWAYS) {
4019 vassert(i->Pin.XIndir.cond.flag != Pcf_NONE);
4020 ptmp = p;
4021 p += 4;
4022 } else {
4023 vassert(i->Pin.XIndir.cond.flag == Pcf_NONE);
4024 }
4025
4026 /* Update the guest CIA. */
4027 /* stw/std r-dstGA, amCIA */
4028 p = do_load_or_store_machine_word(
4029 p, False/*!isLoad*/,
4030 iregNo(i->Pin.XIndir.dstGA, mode64),
4031 i->Pin.XIndir.amCIA, mode64
4032 );
4033
4034 /* imm32/64 r30, VG_(disp_cp_xindir) */
4035 p = mkLoadImm(p, /*r*/30, (ULong)Ptr_to_ULong(disp_cp_xindir), mode64);
4036 /* mtctr r30 */
4037 p = mkFormXFX(p, /*r*/30, 9, 467);
4038 /* bctr */
4039 p = mkFormXL(p, 19, Pct_ALWAYS, 0, 0, 528, 0);
4040
4041 /* Fix up the conditional jump, if there was one. */
4042 if (i->Pin.XIndir.cond.test != Pct_ALWAYS) {
4043 Int delta = p - ptmp;
4044 vassert(delta >= 16 && delta <= 32 && 0 == (delta & 3));
4045 /* bc !ct,cf,delta */
4046 mkFormB(ptmp, invertCondTest(i->Pin.XIndir.cond.test),
4047 i->Pin.XIndir.cond.flag, (delta>>2), 0, 0);
4048 }
4049 goto done;
4050 }
4051
4052 case Pin_XAssisted: {
4053 /* First off, if this is conditional, create a conditional jump
4054 over the rest of it. Or at least, leave a space for it that
4055 we will shortly fill in. */
4056 UChar* ptmp = NULL;
4057 if (i->Pin.XAssisted.cond.test != Pct_ALWAYS) {
4058 vassert(i->Pin.XAssisted.cond.flag != Pcf_NONE);
4059 ptmp = p;
4060 p += 4;
4061 } else {
4062 vassert(i->Pin.XAssisted.cond.flag == Pcf_NONE);
4063 }
4064
4065 /* Update the guest CIA. */
4066 /* stw/std r-dstGA, amCIA */
4067 p = do_load_or_store_machine_word(
4068 p, False/*!isLoad*/,
4069 iregNo(i->Pin.XIndir.dstGA, mode64),
4070 i->Pin.XIndir.amCIA, mode64
4071 );
4072
4073 /* imm32/64 r31, $magic_number */
4074 UInt trcval = 0;
4075 switch (i->Pin.XAssisted.jk) {
4076 case Ijk_ClientReq: trcval = VEX_TRC_JMP_CLIENTREQ; break;
4077 case Ijk_Sys_syscall: trcval = VEX_TRC_JMP_SYS_SYSCALL; break;
4078 //case Ijk_Sys_int128: trcval = VEX_TRC_JMP_SYS_INT128; break;
4079 //case Ijk_Yield: trcval = VEX_TRC_JMP_YIELD; break;
4080 case Ijk_EmWarn: trcval = VEX_TRC_JMP_EMWARN; break;
sewardjf252de52012-04-20 10:42:24 +00004081 case Ijk_EmFail: trcval = VEX_TRC_JMP_EMFAIL; break;
sewardj3dee8492012-04-20 00:13:28 +00004082 //case Ijk_MapFail: trcval = VEX_TRC_JMP_MAPFAIL; break;
4083 case Ijk_NoDecode: trcval = VEX_TRC_JMP_NODECODE; break;
4084 case Ijk_TInval: trcval = VEX_TRC_JMP_TINVAL; break;
4085 case Ijk_NoRedir: trcval = VEX_TRC_JMP_NOREDIR; break;
4086 case Ijk_SigTRAP: trcval = VEX_TRC_JMP_SIGTRAP; break;
4087 //case Ijk_SigSEGV: trcval = VEX_TRC_JMP_SIGSEGV; break;
4088 case Ijk_SigBUS: trcval = VEX_TRC_JMP_SIGBUS; break;
4089 case Ijk_Boring: trcval = VEX_TRC_JMP_BORING; break;
4090 /* We don't expect to see the following being assisted. */
4091 //case Ijk_Ret:
4092 //case Ijk_Call:
4093 /* fallthrough */
4094 default:
4095 ppIRJumpKind(i->Pin.XAssisted.jk);
4096 vpanic("emit_ARMInstr.Pin_XAssisted: unexpected jump kind");
4097 }
4098 vassert(trcval != 0);
4099 p = mkLoadImm(p, /*r*/31, trcval, mode64);
4100
4101 /* imm32/64 r30, VG_(disp_cp_xassisted) */
4102 p = mkLoadImm(p, /*r*/30,
4103 (ULong)Ptr_to_ULong(disp_cp_xassisted), mode64);
4104 /* mtctr r30 */
4105 p = mkFormXFX(p, /*r*/30, 9, 467);
4106 /* bctr */
4107 p = mkFormXL(p, 19, Pct_ALWAYS, 0, 0, 528, 0);
4108
4109 /* Fix up the conditional jump, if there was one. */
4110 if (i->Pin.XAssisted.cond.test != Pct_ALWAYS) {
4111 Int delta = p - ptmp;
4112 vassert(delta >= 16 && delta <= 32 && 0 == (delta & 3));
4113 /* bc !ct,cf,delta */
4114 mkFormB(ptmp, invertCondTest(i->Pin.XAssisted.cond.test),
4115 i->Pin.XAssisted.cond.flag, (delta>>2), 0, 0);
cerion7cf8e4e2005-02-16 16:08:17 +00004116 }
cerion33aa6da2005-02-16 10:25:26 +00004117 goto done;
4118 }
cerionb536af92005-02-10 15:03:19 +00004119
cerionf0de28c2005-12-13 20:21:11 +00004120 case Pin_CMov: {
cerion5b2325f2005-12-23 00:55:09 +00004121 UInt r_dst, r_src;
cerionf0de28c2005-12-13 20:21:11 +00004122 ULong imm_src;
cerion5b2325f2005-12-23 00:55:09 +00004123 PPCCondCode cond;
cerionf0de28c2005-12-13 20:21:11 +00004124 vassert(i->Pin.CMov.cond.test != Pct_ALWAYS);
ceriona2f75882005-03-15 16:33:38 +00004125
cerionf0de28c2005-12-13 20:21:11 +00004126 r_dst = iregNo(i->Pin.CMov.dst, mode64);
4127 cond = i->Pin.CMov.cond;
cerion98411db2005-02-16 14:14:49 +00004128
cerione97e1062005-02-21 15:09:19 +00004129 /* branch (if cond fails) over move instrs */
sewardj3dee8492012-04-20 00:13:28 +00004130 UChar* ptmp = NULL;
cerione97e1062005-02-21 15:09:19 +00004131 if (cond.test != Pct_ALWAYS) {
4132 /* don't know how many bytes to jump over yet...
4133 make space for a jump instruction and fill in later. */
4134 ptmp = p; /* fill in this bit later */
4135 p += 4;
4136 }
cerion98411db2005-02-16 14:14:49 +00004137
4138 // cond true: move src => dst
cerionf0de28c2005-12-13 20:21:11 +00004139 switch (i->Pin.CMov.src->tag) {
cerion98411db2005-02-16 14:14:49 +00004140 case Pri_Imm:
cerionf0de28c2005-12-13 20:21:11 +00004141 imm_src = i->Pin.CMov.src->Pri.Imm;
4142 p = mkLoadImm(p, r_dst, imm_src, mode64); // p += 4|8|20
cerion98411db2005-02-16 14:14:49 +00004143 break;
4144 case Pri_Reg:
cerionf0de28c2005-12-13 20:21:11 +00004145 r_src = iregNo(i->Pin.CMov.src->Pri.Reg, mode64);
4146 p = mkMoveReg(p, r_dst, r_src); // p += 4
cerion98411db2005-02-16 14:14:49 +00004147 break;
4148 default: goto bad;
4149 }
cerione97e1062005-02-21 15:09:19 +00004150
4151 /* Fix up the conditional jump, if there was one. */
4152 if (cond.test != Pct_ALWAYS) {
4153 Int delta = p - ptmp;
cerionf0de28c2005-12-13 20:21:11 +00004154 vassert(delta >= 8 && delta <= 24);
cerione97e1062005-02-21 15:09:19 +00004155 /* bc !ct,cf,delta */
cerion5b2325f2005-12-23 00:55:09 +00004156 mkFormB(ptmp, invertCondTest(cond.test),
4157 cond.flag, (delta>>2), 0, 0);
cerione97e1062005-02-21 15:09:19 +00004158 }
cerion98411db2005-02-16 14:14:49 +00004159 goto done;
4160 }
cerionb536af92005-02-10 15:03:19 +00004161
cerion7cf8e4e2005-02-16 16:08:17 +00004162 case Pin_Load: {
cerion5b2325f2005-12-23 00:55:09 +00004163 PPCAMode* am_addr = i->Pin.Load.src;
cerionf0de28c2005-12-13 20:21:11 +00004164 UInt r_dst = iregNo(i->Pin.Load.dst, mode64);
ceriona2f75882005-03-15 16:33:38 +00004165 UInt opc1, opc2, sz = i->Pin.Load.sz;
cerionf0de28c2005-12-13 20:21:11 +00004166 switch (am_addr->tag) {
ceriond5e38382005-02-11 13:38:15 +00004167 case Pam_IR:
sewardj34085e32007-03-09 18:07:00 +00004168 if (mode64 && (sz == 4 || sz == 8)) {
4169 /* should be guaranteed to us by iselWordExpr_AMode */
4170 vassert(0 == (am_addr->Pam.IR.index & 3));
4171 }
cerionf0de28c2005-12-13 20:21:11 +00004172 switch(sz) {
sewardj7fd5bb02006-01-26 02:24:17 +00004173 case 1: opc1 = 34; break;
4174 case 2: opc1 = 40; break;
4175 case 4: opc1 = 32; break;
4176 case 8: opc1 = 58; vassert(mode64); break;
4177 default: goto bad;
cerionab9132d2005-02-15 15:46:59 +00004178 }
cerionf0de28c2005-12-13 20:21:11 +00004179 p = doAMode_IR(p, opc1, r_dst, am_addr, mode64);
cerionab9132d2005-02-15 15:46:59 +00004180 goto done;
ceriond5e38382005-02-11 13:38:15 +00004181 case Pam_RR:
cerionf0de28c2005-12-13 20:21:11 +00004182 switch(sz) {
sewardj7fd5bb02006-01-26 02:24:17 +00004183 case 1: opc2 = 87; break;
4184 case 2: opc2 = 279; break;
4185 case 4: opc2 = 23; break;
4186 case 8: opc2 = 21; vassert(mode64); break;
4187 default: goto bad;
cerionab9132d2005-02-15 15:46:59 +00004188 }
cerionf0de28c2005-12-13 20:21:11 +00004189 p = doAMode_RR(p, 31, opc2, r_dst, am_addr, mode64);
cerionab9132d2005-02-15 15:46:59 +00004190 goto done;
ceriond5e38382005-02-11 13:38:15 +00004191 default:
cerionab9132d2005-02-15 15:46:59 +00004192 goto bad;
ceriond5e38382005-02-11 13:38:15 +00004193 }
4194 }
cerionb536af92005-02-10 15:03:19 +00004195
sewardje9d8a262009-07-01 08:06:34 +00004196 case Pin_LoadL: {
4197 if (i->Pin.LoadL.sz == 4) {
4198 p = mkFormX(p, 31, iregNo(i->Pin.LoadL.dst, mode64),
4199 0, iregNo(i->Pin.LoadL.src, mode64), 20, 0);
4200 goto done;
4201 }
4202 if (i->Pin.LoadL.sz == 8 && mode64) {
4203 p = mkFormX(p, 31, iregNo(i->Pin.LoadL.dst, mode64),
4204 0, iregNo(i->Pin.LoadL.src, mode64), 84, 0);
4205 goto done;
4206 }
4207 goto bad;
4208 }
4209
cerion5b2325f2005-12-23 00:55:09 +00004210 case Pin_Set: {
cerionab9132d2005-02-15 15:46:59 +00004211 /* Make the destination register be 1 or 0, depending on whether
cerion9e263e32005-03-03 17:21:51 +00004212 the relevant condition holds. */
cerion5b2325f2005-12-23 00:55:09 +00004213 UInt r_dst = iregNo(i->Pin.Set.dst, mode64);
4214 PPCCondCode cond = i->Pin.Set.cond;
4215 UInt rot_imm, r_tmp;
cerion98411db2005-02-16 14:14:49 +00004216
4217 if (cond.test == Pct_ALWAYS) {
cerion9e263e32005-03-03 17:21:51 +00004218 // Just load 1 to dst => li dst,1
cerion98411db2005-02-16 14:14:49 +00004219 p = mkFormD(p, 14, r_dst, 0, 1);
cerionab9132d2005-02-15 15:46:59 +00004220 } else {
sewardj7e308072011-05-04 09:50:48 +00004221 vassert(cond.flag != Pcf_NONE);
cerion7cf8e4e2005-02-16 16:08:17 +00004222 rot_imm = 1 + cond.flag;
cerion5b2325f2005-12-23 00:55:09 +00004223 r_tmp = 0; // Not set in getAllocable, so no need to declare.
cerion98411db2005-02-16 14:14:49 +00004224
4225 // r_tmp = CR => mfcr r_tmp
4226 p = mkFormX(p, 31, r_tmp, 0, 0, 19, 0);
4227
4228 // r_dst = flag (rotate left and mask)
cerion7cf8e4e2005-02-16 16:08:17 +00004229 // => rlwinm r_dst,r_tmp,rot_imm,31,31
cerione97e1062005-02-21 15:09:19 +00004230 p = mkFormM(p, 21, r_tmp, r_dst, rot_imm, 31, 31, 0);
cerion98411db2005-02-16 14:14:49 +00004231
4232 if (cond.test == Pct_FALSE) {
ceriona2f75882005-03-15 16:33:38 +00004233 // flip bit => xori r_dst,r_dst,1
cerion98411db2005-02-16 14:14:49 +00004234 p = mkFormD(p, 26, r_dst, r_dst, 1);
cerionab9132d2005-02-15 15:46:59 +00004235 }
4236 }
4237 goto done;
cerionab9132d2005-02-15 15:46:59 +00004238 }
cerionb536af92005-02-10 15:03:19 +00004239
sewardjb51f0f42005-07-18 11:38:02 +00004240 case Pin_MfCR:
4241 // mfcr dst
cerionf0de28c2005-12-13 20:21:11 +00004242 p = mkFormX(p, 31, iregNo(i->Pin.MfCR.dst, mode64), 0, 0, 19, 0);
sewardjb51f0f42005-07-18 11:38:02 +00004243 goto done;
4244
cerion98411db2005-02-16 14:14:49 +00004245 case Pin_MFence: {
cerioned623db2005-06-20 12:42:04 +00004246 p = mkFormX(p, 31, 0, 0, 0, 598, 0); // sync, PPC32 p616
sewardje9d8a262009-07-01 08:06:34 +00004247 // CAB: Should this be isync?
4248 // p = mkFormXL(p, 19, 0, 0, 0, 150, 0); // isync, PPC32 p467
cerion98411db2005-02-16 14:14:49 +00004249 goto done;
4250 }
cerionb536af92005-02-10 15:03:19 +00004251
ceriond5e38382005-02-11 13:38:15 +00004252 case Pin_Store: {
cerion5b2325f2005-12-23 00:55:09 +00004253 PPCAMode* am_addr = i->Pin.Store.dst;
cerionf0de28c2005-12-13 20:21:11 +00004254 UInt r_src = iregNo(i->Pin.Store.src, mode64);
ceriona2f75882005-03-15 16:33:38 +00004255 UInt opc1, opc2, sz = i->Pin.Store.sz;
ceriond5e38382005-02-11 13:38:15 +00004256 switch (i->Pin.Store.dst->tag) {
4257 case Pam_IR:
sewardj34085e32007-03-09 18:07:00 +00004258 if (mode64 && (sz == 4 || sz == 8)) {
4259 /* should be guaranteed to us by iselWordExpr_AMode */
4260 vassert(0 == (am_addr->Pam.IR.index & 3));
4261 }
cerionf0de28c2005-12-13 20:21:11 +00004262 switch(sz) {
4263 case 1: opc1 = 38; break;
4264 case 2: opc1 = 44; break;
4265 case 4: opc1 = 36; break;
4266 case 8: vassert(mode64);
4267 opc1 = 62; break;
4268 default:
4269 goto bad;
4270 }
4271 p = doAMode_IR(p, opc1, r_src, am_addr, mode64);
cerionab9132d2005-02-15 15:46:59 +00004272 goto done;
ceriond5e38382005-02-11 13:38:15 +00004273 case Pam_RR:
cerionf0de28c2005-12-13 20:21:11 +00004274 switch(sz) {
4275 case 1: opc2 = 215; break;
4276 case 2: opc2 = 407; break;
4277 case 4: opc2 = 151; break;
4278 case 8: vassert(mode64);
4279 opc2 = 149; break;
4280 default:
4281 goto bad;
4282 }
4283 p = doAMode_RR(p, 31, opc2, r_src, am_addr, mode64);
cerionab9132d2005-02-15 15:46:59 +00004284 goto done;
ceriond5e38382005-02-11 13:38:15 +00004285 default:
cerionab9132d2005-02-15 15:46:59 +00004286 goto bad;
ceriond5e38382005-02-11 13:38:15 +00004287 }
4288 goto done;
4289 }
cerionb536af92005-02-10 15:03:19 +00004290
sewardje9d8a262009-07-01 08:06:34 +00004291 case Pin_StoreC: {
4292 if (i->Pin.StoreC.sz == 4) {
4293 p = mkFormX(p, 31, iregNo(i->Pin.StoreC.src, mode64),
4294 0, iregNo(i->Pin.StoreC.dst, mode64), 150, 1);
4295 goto done;
4296 }
4297 if (i->Pin.StoreC.sz == 8 && mode64) {
4298 p = mkFormX(p, 31, iregNo(i->Pin.StoreC.src, mode64),
4299 0, iregNo(i->Pin.StoreC.dst, mode64), 214, 1);
4300 goto done;
4301 }
4302 goto bad;
4303 }
4304
cerion094d1392005-06-20 13:45:57 +00004305 case Pin_FpUnary: {
4306 UInt fr_dst = fregNo(i->Pin.FpUnary.dst);
4307 UInt fr_src = fregNo(i->Pin.FpUnary.src);
4308 switch (i->Pin.FpUnary.op) {
sewardjbaf971a2006-01-27 15:09:35 +00004309 case Pfp_RSQRTE: // frsqrtre, PPC32 p424
4310 p = mkFormA( p, 63, fr_dst, 0, fr_src, 0, 26, 0 );
4311 break;
4312 case Pfp_RES: // fres, PPC32 p421
4313 p = mkFormA( p, 59, fr_dst, 0, fr_src, 0, 24, 0 );
4314 break;
cerion094d1392005-06-20 13:45:57 +00004315 case Pfp_SQRT: // fsqrt, PPC32 p427
4316 p = mkFormA( p, 63, fr_dst, 0, fr_src, 0, 22, 0 );
4317 break;
4318 case Pfp_ABS: // fabs, PPC32 p399
4319 p = mkFormX(p, 63, fr_dst, 0, fr_src, 264, 0);
4320 break;
4321 case Pfp_NEG: // fneg, PPC32 p416
4322 p = mkFormX(p, 63, fr_dst, 0, fr_src, 40, 0);
4323 break;
4324 case Pfp_MOV: // fmr, PPC32 p410
4325 p = mkFormX(p, 63, fr_dst, 0, fr_src, 72, 0);
4326 break;
sewardj0f1ef862008-08-08 08:37:06 +00004327 case Pfp_FRIM: // frim, PPC ISA 2.05 p137
4328 p = mkFormX(p, 63, fr_dst, 0, fr_src, 488, 0);
4329 break;
4330 case Pfp_FRIP: // frip, PPC ISA 2.05 p137
4331 p = mkFormX(p, 63, fr_dst, 0, fr_src, 456, 0);
4332 break;
4333 case Pfp_FRIN: // frin, PPC ISA 2.05 p137
4334 p = mkFormX(p, 63, fr_dst, 0, fr_src, 392, 0);
4335 break;
4336 case Pfp_FRIZ: // friz, PPC ISA 2.05 p137
4337 p = mkFormX(p, 63, fr_dst, 0, fr_src, 424, 0);
4338 break;
cerion094d1392005-06-20 13:45:57 +00004339 default:
4340 goto bad;
4341 }
4342 goto done;
4343 }
4344
4345 case Pin_FpBinary: {
4346 UInt fr_dst = fregNo(i->Pin.FpBinary.dst);
4347 UInt fr_srcL = fregNo(i->Pin.FpBinary.srcL);
4348 UInt fr_srcR = fregNo(i->Pin.FpBinary.srcR);
4349 switch (i->Pin.FpBinary.op) {
sewardjb183b852006-02-03 16:08:03 +00004350 case Pfp_ADDD: // fadd, PPC32 p400
cerion094d1392005-06-20 13:45:57 +00004351 p = mkFormA( p, 63, fr_dst, fr_srcL, fr_srcR, 0, 21, 0 );
4352 break;
sewardjb183b852006-02-03 16:08:03 +00004353 case Pfp_ADDS: // fadds, PPC32 p401
4354 p = mkFormA( p, 59, fr_dst, fr_srcL, fr_srcR, 0, 21, 0 );
4355 break;
4356 case Pfp_SUBD: // fsub, PPC32 p429
cerion094d1392005-06-20 13:45:57 +00004357 p = mkFormA( p, 63, fr_dst, fr_srcL, fr_srcR, 0, 20, 0 );
4358 break;
sewardjb183b852006-02-03 16:08:03 +00004359 case Pfp_SUBS: // fsubs, PPC32 p430
4360 p = mkFormA( p, 59, fr_dst, fr_srcL, fr_srcR, 0, 20, 0 );
4361 break;
4362 case Pfp_MULD: // fmul, PPC32 p413
cerion094d1392005-06-20 13:45:57 +00004363 p = mkFormA( p, 63, fr_dst, fr_srcL, 0, fr_srcR, 25, 0 );
4364 break;
sewardjb183b852006-02-03 16:08:03 +00004365 case Pfp_MULS: // fmuls, PPC32 p414
4366 p = mkFormA( p, 59, fr_dst, fr_srcL, 0, fr_srcR, 25, 0 );
4367 break;
4368 case Pfp_DIVD: // fdiv, PPC32 p406
cerion094d1392005-06-20 13:45:57 +00004369 p = mkFormA( p, 63, fr_dst, fr_srcL, fr_srcR, 0, 18, 0 );
4370 break;
sewardjb183b852006-02-03 16:08:03 +00004371 case Pfp_DIVS: // fdivs, PPC32 p407
4372 p = mkFormA( p, 59, fr_dst, fr_srcL, fr_srcR, 0, 18, 0 );
4373 break;
cerion094d1392005-06-20 13:45:57 +00004374 default:
4375 goto bad;
4376 }
4377 goto done;
4378 }
4379
sewardj40c80262006-02-08 19:30:46 +00004380 case Pin_FpMulAcc: {
4381 UInt fr_dst = fregNo(i->Pin.FpMulAcc.dst);
4382 UInt fr_srcML = fregNo(i->Pin.FpMulAcc.srcML);
4383 UInt fr_srcMR = fregNo(i->Pin.FpMulAcc.srcMR);
4384 UInt fr_srcAcc = fregNo(i->Pin.FpMulAcc.srcAcc);
4385 switch (i->Pin.FpMulAcc.op) {
4386 case Pfp_MADDD: // fmadd, PPC32 p408
4387 p = mkFormA( p, 63, fr_dst, fr_srcML, fr_srcAcc, fr_srcMR, 29, 0 );
4388 break;
4389 case Pfp_MADDS: // fmadds, PPC32 p409
4390 p = mkFormA( p, 59, fr_dst, fr_srcML, fr_srcAcc, fr_srcMR, 29, 0 );
4391 break;
4392 case Pfp_MSUBD: // fmsub, PPC32 p411
4393 p = mkFormA( p, 63, fr_dst, fr_srcML, fr_srcAcc, fr_srcMR, 28, 0 );
4394 break;
4395 case Pfp_MSUBS: // fmsubs, PPC32 p412
4396 p = mkFormA( p, 59, fr_dst, fr_srcML, fr_srcAcc, fr_srcMR, 28, 0 );
4397 break;
4398 default:
4399 goto bad;
4400 }
4401 goto done;
4402 }
4403
cerion094d1392005-06-20 13:45:57 +00004404 case Pin_FpLdSt: {
cerion5b2325f2005-12-23 00:55:09 +00004405 PPCAMode* am_addr = i->Pin.FpLdSt.addr;
cerion094d1392005-06-20 13:45:57 +00004406 UInt f_reg = fregNo(i->Pin.FpLdSt.reg);
4407 Bool idxd = toBool(i->Pin.FpLdSt.addr->tag == Pam_RR);
4408 UChar sz = i->Pin.FpLdSt.sz;
cerionf0de28c2005-12-13 20:21:11 +00004409 UInt opc;
cerion094d1392005-06-20 13:45:57 +00004410 vassert(sz == 4 || sz == 8);
4411
4412 if (i->Pin.FpLdSt.isLoad) { // Load from memory
4413 if (idxd) { // lf[s|d]x, PPC32 p444|440
cerionf0de28c2005-12-13 20:21:11 +00004414 opc = (sz == 4) ? 535 : 599;
4415 p = doAMode_RR(p, 31, opc, f_reg, am_addr, mode64);
cerion094d1392005-06-20 13:45:57 +00004416 } else { // lf[s|d], PPC32 p441|437
cerionf0de28c2005-12-13 20:21:11 +00004417 opc = (sz == 4) ? 48 : 50;
4418 p = doAMode_IR(p, opc, f_reg, am_addr, mode64);
cerion094d1392005-06-20 13:45:57 +00004419 }
4420 } else { // Store to memory
4421 if (idxd) { // stf[s|d]x, PPC32 p521|516
cerionf0de28c2005-12-13 20:21:11 +00004422 opc = (sz == 4) ? 663 : 727;
4423 p = doAMode_RR(p, 31, opc, f_reg, am_addr, mode64);
cerion094d1392005-06-20 13:45:57 +00004424 } else { // stf[s|d], PPC32 p518|513
cerionf0de28c2005-12-13 20:21:11 +00004425 opc = (sz == 4) ? 52 : 54;
4426 p = doAMode_IR(p, opc, f_reg, am_addr, mode64);
cerion094d1392005-06-20 13:45:57 +00004427 }
4428 }
4429 goto done;
4430 }
4431
sewardj92923de2006-01-25 21:29:48 +00004432 case Pin_FpSTFIW: {
4433 UInt ir_addr = iregNo(i->Pin.FpSTFIW.addr, mode64);
4434 UInt fr_data = fregNo(i->Pin.FpSTFIW.data);
4435 // stfiwx (store fp64[lo32] as int32), PPC32 p517
4436 // Use rA==0, so that EA == rB == ir_addr
4437 p = mkFormX(p, 31, fr_data, 0/*rA=0*/, ir_addr, 983, 0);
4438 goto done;
4439 }
4440
4441 case Pin_FpRSP: {
4442 UInt fr_dst = fregNo(i->Pin.FpRSP.dst);
4443 UInt fr_src = fregNo(i->Pin.FpRSP.src);
cerion094d1392005-06-20 13:45:57 +00004444 // frsp, PPC32 p423
4445 p = mkFormX(p, 63, fr_dst, 0, fr_src, 12, 0);
4446 goto done;
4447 }
4448
sewardj92923de2006-01-25 21:29:48 +00004449 case Pin_FpCftI: {
4450 UInt fr_dst = fregNo(i->Pin.FpCftI.dst);
4451 UInt fr_src = fregNo(i->Pin.FpCftI.src);
4452 if (i->Pin.FpCftI.fromI == False && i->Pin.FpCftI.int32 == True) {
sewardj4aa412a2011-07-24 14:13:21 +00004453 if (i->Pin.FpCftI.syned == True) {
4454 // fctiw (conv f64 to i32), PPC32 p404
4455 p = mkFormX(p, 63, fr_dst, 0, fr_src, 14, 0);
4456 goto done;
4457 } else {
4458 // fctiwu (conv f64 to u32)
4459 p = mkFormX(p, 63, fr_dst, 0, fr_src, 142, 0);
4460 goto done;
4461 }
sewardj92923de2006-01-25 21:29:48 +00004462 }
sewardj7fd5bb02006-01-26 02:24:17 +00004463 if (i->Pin.FpCftI.fromI == False && i->Pin.FpCftI.int32 == False) {
sewardj4aa412a2011-07-24 14:13:21 +00004464 if (i->Pin.FpCftI.syned == True) {
4465 // fctid (conv f64 to i64), PPC64 p437
4466 p = mkFormX(p, 63, fr_dst, 0, fr_src, 814, 0);
4467 goto done;
4468 } else {
4469 // fctidu (conv f64 to u64)
4470 p = mkFormX(p, 63, fr_dst, 0, fr_src, 942, 0);
4471 goto done;
4472 }
sewardj7fd5bb02006-01-26 02:24:17 +00004473 }
4474 if (i->Pin.FpCftI.fromI == True && i->Pin.FpCftI.int32 == False) {
sewardj66d5ef22011-04-15 11:55:00 +00004475 if (i->Pin.FpCftI.syned == True) {
4476 // fcfid (conv i64 to f64), PPC64 p434
4477 p = mkFormX(p, 63, fr_dst, 0, fr_src, 846, 0);
4478 goto done;
sewardj7d810d72011-05-08 22:05:10 +00004479 } else if (i->Pin.FpCftI.flt64 == True) {
sewardj66d5ef22011-04-15 11:55:00 +00004480 // fcfidu (conv u64 to f64)
4481 p = mkFormX(p, 63, fr_dst, 0, fr_src, 974, 0);
4482 goto done;
4483 } else {
4484 // fcfidus (conv u64 to f32)
4485 p = mkFormX(p, 59, fr_dst, 0, fr_src, 974, 0);
4486 goto done;
4487 }
sewardj7fd5bb02006-01-26 02:24:17 +00004488 }
sewardj92923de2006-01-25 21:29:48 +00004489 goto bad;
cerion094d1392005-06-20 13:45:57 +00004490 }
4491
4492 case Pin_FpCMov: {
cerion5b2325f2005-12-23 00:55:09 +00004493 UInt fr_dst = fregNo(i->Pin.FpCMov.dst);
4494 UInt fr_src = fregNo(i->Pin.FpCMov.src);
4495 PPCCondCode cc = i->Pin.FpCMov.cond;
cerion094d1392005-06-20 13:45:57 +00004496
4497 if (fr_dst == fr_src) goto done;
4498
4499 vassert(cc.test != Pct_ALWAYS);
4500
4501 /* jmp fwds if !condition */
4502 if (cc.test != Pct_ALWAYS) {
4503 /* bc !ct,cf,n_bytes>>2 */
4504 p = mkFormB(p, invertCondTest(cc.test), cc.flag, 8>>2, 0, 0);
4505 }
4506
4507 // fmr, PPC32 p410
4508 p = mkFormX(p, 63, fr_dst, 0, fr_src, 72, 0);
4509 goto done;
4510 }
4511
4512 case Pin_FpLdFPSCR: {
4513 UInt fr_src = fregNo(i->Pin.FpLdFPSCR.src);
sewardjc6bbd472012-04-02 10:20:48 +00004514 p = mkFormXFL(p, 0xFF, fr_src, i->Pin.FpLdFPSCR.dfp_rm); // mtfsf, PPC32 p480
cerion094d1392005-06-20 13:45:57 +00004515 goto done;
4516 }
4517
4518 case Pin_FpCmp: {
sewardjb51f0f42005-07-18 11:38:02 +00004519 UChar crfD = 1;
cerionf0de28c2005-12-13 20:21:11 +00004520 UInt r_dst = iregNo(i->Pin.FpCmp.dst, mode64);
sewardjb51f0f42005-07-18 11:38:02 +00004521 UInt fr_srcL = fregNo(i->Pin.FpCmp.srcL);
4522 UInt fr_srcR = fregNo(i->Pin.FpCmp.srcR);
cerion094d1392005-06-20 13:45:57 +00004523 vassert(crfD < 8);
4524 // fcmpo, PPC32 p402
sewardjb51f0f42005-07-18 11:38:02 +00004525 p = mkFormX(p, 63, crfD<<2, fr_srcL, fr_srcR, 32, 0);
cerion094d1392005-06-20 13:45:57 +00004526
4527 // mfcr (mv CR to r_dst), PPC32 p467
4528 p = mkFormX(p, 31, r_dst, 0, 0, 19, 0);
4529
4530 // rlwinm r_dst,r_dst,8,28,31, PPC32 p501
sewardjb51f0f42005-07-18 11:38:02 +00004531 // => rotate field 1 to bottomw of word, masking out upper 28
cerion094d1392005-06-20 13:45:57 +00004532 p = mkFormM(p, 21, r_dst, r_dst, 8, 28, 31, 0);
4533 goto done;
4534 }
cerionbcf8c3e2005-02-04 16:17:07 +00004535
cerion7f000af2005-02-22 20:36:49 +00004536 case Pin_RdWrLR: {
cerionf0de28c2005-12-13 20:21:11 +00004537 UInt reg = iregNo(i->Pin.RdWrLR.gpr, mode64);
cerion7f000af2005-02-22 20:36:49 +00004538 /* wrLR==True ? mtlr r4 : mflr r4 */
4539 p = mkFormXFX(p, reg, 8, (i->Pin.RdWrLR.wrLR==True) ? 467 : 339);
4540 goto done;
4541 }
4542
cerionc3d8bdc2005-06-28 18:06:23 +00004543
4544 /* AltiVec */
4545 case Pin_AvLdSt: {
4546 UInt opc2, v_reg, r_idx, r_base;
4547 UChar sz = i->Pin.AvLdSt.sz;
4548 Bool idxd = toBool(i->Pin.AvLdSt.addr->tag == Pam_RR);
cerion225a0342005-09-12 20:49:09 +00004549 vassert(sz == 1 || sz == 2 || sz == 4 || sz == 16);
cerionc3d8bdc2005-06-28 18:06:23 +00004550
4551 v_reg = vregNo(i->Pin.AvLdSt.reg);
cerionf0de28c2005-12-13 20:21:11 +00004552 r_base = iregNo(i->Pin.AvLdSt.addr->Pam.RR.base, mode64);
cerionc3d8bdc2005-06-28 18:06:23 +00004553
4554 // Only have AltiVec AMode_RR: kludge AMode_IR
4555 if (!idxd) {
4556 r_idx = 30; // XXX: Using r30 as temp
cerion5b2325f2005-12-23 00:55:09 +00004557 p = mkLoadImm(p, r_idx,
4558 i->Pin.AvLdSt.addr->Pam.IR.index, mode64);
cerionc3d8bdc2005-06-28 18:06:23 +00004559 } else {
cerionf0de28c2005-12-13 20:21:11 +00004560 r_idx = iregNo(i->Pin.AvLdSt.addr->Pam.RR.index, mode64);
cerionc3d8bdc2005-06-28 18:06:23 +00004561 }
4562
cerion225a0342005-09-12 20:49:09 +00004563 if (i->Pin.FpLdSt.isLoad) { // Load from memory (1,2,4,16)
cerion5b2325f2005-12-23 00:55:09 +00004564 opc2 = (sz==1) ? 7 : (sz==2) ? 39 : (sz==4) ? 71 : 103;
cerionc3d8bdc2005-06-28 18:06:23 +00004565 p = mkFormX(p, 31, v_reg, r_idx, r_base, opc2, 0);
cerion225a0342005-09-12 20:49:09 +00004566 } else { // Store to memory (1,2,4,16)
cerion5b2325f2005-12-23 00:55:09 +00004567 opc2 = (sz==1) ? 135 : (sz==2) ? 167 : (sz==4) ? 199 : 231;
cerionc3d8bdc2005-06-28 18:06:23 +00004568 p = mkFormX(p, 31, v_reg, r_idx, r_base, opc2, 0);
4569 }
4570 goto done;
4571 }
4572
4573 case Pin_AvUnary: {
4574 UInt v_dst = vregNo(i->Pin.AvUnary.dst);
4575 UInt v_src = vregNo(i->Pin.AvUnary.src);
4576 UInt opc2;
4577 switch (i->Pin.AvUnary.op) {
4578 case Pav_MOV: opc2 = 1156; break; // vor vD,vS,vS
4579 case Pav_NOT: opc2 = 1284; break; // vnor vD,vS,vS
4580 case Pav_UNPCKH8S: opc2 = 526; break; // vupkhsb
4581 case Pav_UNPCKH16S: opc2 = 590; break; // vupkhsh
4582 case Pav_UNPCKL8S: opc2 = 654; break; // vupklsb
4583 case Pav_UNPCKL16S: opc2 = 718; break; // vupklsh
4584 case Pav_UNPCKHPIX: opc2 = 846; break; // vupkhpx
4585 case Pav_UNPCKLPIX: opc2 = 974; break; // vupklpx
4586 default:
4587 goto bad;
4588 }
4589 switch (i->Pin.AvUnary.op) {
4590 case Pav_MOV:
4591 case Pav_NOT:
4592 p = mkFormVX( p, 4, v_dst, v_src, v_src, opc2 );
4593 break;
4594 default:
cerion8ea0d3e2005-11-14 00:44:47 +00004595 p = mkFormVX( p, 4, v_dst, 0, v_src, opc2 );
4596 break;
cerionc3d8bdc2005-06-28 18:06:23 +00004597 }
4598 goto done;
4599 }
4600
4601 case Pin_AvBinary: {
4602 UInt v_dst = vregNo(i->Pin.AvBinary.dst);
4603 UInt v_srcL = vregNo(i->Pin.AvBinary.srcL);
4604 UInt v_srcR = vregNo(i->Pin.AvBinary.srcR);
4605 UInt opc2;
cerion27b3d7e2005-09-14 20:35:47 +00004606 if (i->Pin.AvBinary.op == Pav_SHL) {
4607 p = mkFormVX( p, 4, v_dst, v_srcL, v_srcR, 1036 ); // vslo
4608 p = mkFormVX( p, 4, v_dst, v_dst, v_srcR, 452 ); // vsl
4609 goto done;
4610 }
4611 if (i->Pin.AvBinary.op == Pav_SHR) {
4612 p = mkFormVX( p, 4, v_dst, v_srcL, v_srcR, 1100 ); // vsro
4613 p = mkFormVX( p, 4, v_dst, v_dst, v_srcR, 708 ); // vsr
4614 goto done;
4615 }
cerionc3d8bdc2005-06-28 18:06:23 +00004616 switch (i->Pin.AvBinary.op) {
4617 /* Bitwise */
cerion225a0342005-09-12 20:49:09 +00004618 case Pav_AND: opc2 = 1028; break; // vand
cerionc3d8bdc2005-06-28 18:06:23 +00004619 case Pav_OR: opc2 = 1156; break; // vor
cerion225a0342005-09-12 20:49:09 +00004620 case Pav_XOR: opc2 = 1220; break; // vxor
cerionc3d8bdc2005-06-28 18:06:23 +00004621 default:
4622 goto bad;
4623 }
4624 p = mkFormVX( p, 4, v_dst, v_srcL, v_srcR, opc2 );
4625 goto done;
4626 }
4627
cerion6b6f59e2005-06-28 20:59:18 +00004628 case Pin_AvBin8x16: {
4629 UInt v_dst = vregNo(i->Pin.AvBin8x16.dst);
4630 UInt v_srcL = vregNo(i->Pin.AvBin8x16.srcL);
4631 UInt v_srcR = vregNo(i->Pin.AvBin8x16.srcR);
4632 UInt opc2;
4633 switch (i->Pin.AvBin8x16.op) {
4634
cerionf34ccc42005-09-16 08:55:50 +00004635 case Pav_ADDU: opc2 = 0; break; // vaddubm
4636 case Pav_QADDU: opc2 = 512; break; // vaddubs
4637 case Pav_QADDS: opc2 = 768; break; // vaddsbs
cerion6b6f59e2005-06-28 20:59:18 +00004638
cerionf34ccc42005-09-16 08:55:50 +00004639 case Pav_SUBU: opc2 = 1024; break; // vsububm
4640 case Pav_QSUBU: opc2 = 1536; break; // vsububs
4641 case Pav_QSUBS: opc2 = 1792; break; // vsubsbs
cerion6b6f59e2005-06-28 20:59:18 +00004642
cerion1ac656a2005-11-04 19:44:48 +00004643 case Pav_OMULU: opc2 = 8; break; // vmuloub
4644 case Pav_OMULS: opc2 = 264; break; // vmulosb
4645 case Pav_EMULU: opc2 = 520; break; // vmuleub
4646 case Pav_EMULS: opc2 = 776; break; // vmulesb
4647
cerion6b6f59e2005-06-28 20:59:18 +00004648 case Pav_AVGU: opc2 = 1026; break; // vavgub
4649 case Pav_AVGS: opc2 = 1282; break; // vavgsb
4650 case Pav_MAXU: opc2 = 2; break; // vmaxub
4651 case Pav_MAXS: opc2 = 258; break; // vmaxsb
4652 case Pav_MINU: opc2 = 514; break; // vminub
4653 case Pav_MINS: opc2 = 770; break; // vminsb
4654
4655 case Pav_CMPEQU: opc2 = 6; break; // vcmpequb
4656 case Pav_CMPGTU: opc2 = 518; break; // vcmpgtub
4657 case Pav_CMPGTS: opc2 = 774; break; // vcmpgtsb
4658
4659 case Pav_SHL: opc2 = 260; break; // vslb
4660 case Pav_SHR: opc2 = 516; break; // vsrb
4661 case Pav_SAR: opc2 = 772; break; // vsrab
4662 case Pav_ROTL: opc2 = 4; break; // vrlb
4663
4664 case Pav_MRGHI: opc2 = 12; break; // vmrghb
4665 case Pav_MRGLO: opc2 = 268; break; // vmrglb
4666
4667 default:
4668 goto bad;
4669 }
4670 p = mkFormVX( p, 4, v_dst, v_srcL, v_srcR, opc2 );
4671 goto done;
4672 }
4673
4674 case Pin_AvBin16x8: {
4675 UInt v_dst = vregNo(i->Pin.AvBin16x8.dst);
4676 UInt v_srcL = vregNo(i->Pin.AvBin16x8.srcL);
4677 UInt v_srcR = vregNo(i->Pin.AvBin16x8.srcR);
4678 UInt opc2;
4679 switch (i->Pin.AvBin16x8.op) {
4680
cerionf34ccc42005-09-16 08:55:50 +00004681 case Pav_ADDU: opc2 = 64; break; // vadduhm
4682 case Pav_QADDU: opc2 = 576; break; // vadduhs
4683 case Pav_QADDS: opc2 = 832; break; // vaddshs
cerion6b6f59e2005-06-28 20:59:18 +00004684
cerionf34ccc42005-09-16 08:55:50 +00004685 case Pav_SUBU: opc2 = 1088; break; // vsubuhm
4686 case Pav_QSUBU: opc2 = 1600; break; // vsubuhs
4687 case Pav_QSUBS: opc2 = 1856; break; // vsubshs
cerion6b6f59e2005-06-28 20:59:18 +00004688
cerion1ac656a2005-11-04 19:44:48 +00004689 case Pav_OMULU: opc2 = 72; break; // vmulouh
4690 case Pav_OMULS: opc2 = 328; break; // vmulosh
4691 case Pav_EMULU: opc2 = 584; break; // vmuleuh
4692 case Pav_EMULS: opc2 = 840; break; // vmulesh
cerion6b6f59e2005-06-28 20:59:18 +00004693
4694 case Pav_AVGU: opc2 = 1090; break; // vavguh
4695 case Pav_AVGS: opc2 = 1346; break; // vavgsh
4696 case Pav_MAXU: opc2 = 66; break; // vmaxuh
4697 case Pav_MAXS: opc2 = 322; break; // vmaxsh
4698 case Pav_MINS: opc2 = 834; break; // vminsh
4699 case Pav_MINU: opc2 = 578; break; // vminuh
4700
4701 case Pav_CMPEQU: opc2 = 70; break; // vcmpequh
4702 case Pav_CMPGTU: opc2 = 582; break; // vcmpgtuh
4703 case Pav_CMPGTS: opc2 = 838; break; // vcmpgtsh
4704
4705 case Pav_SHL: opc2 = 324; break; // vslh
4706 case Pav_SHR: opc2 = 580; break; // vsrh
4707 case Pav_SAR: opc2 = 836; break; // vsrah
4708 case Pav_ROTL: opc2 = 68; break; // vrlh
4709
cerionf34ccc42005-09-16 08:55:50 +00004710 case Pav_PACKUU: opc2 = 14; break; // vpkuhum
4711 case Pav_QPACKUU: opc2 = 142; break; // vpkuhus
4712 case Pav_QPACKSU: opc2 = 270; break; // vpkshus
4713 case Pav_QPACKSS: opc2 = 398; break; // vpkshss
4714 case Pav_PACKPXL: opc2 = 782; break; // vpkpx
cerion6b6f59e2005-06-28 20:59:18 +00004715
4716 case Pav_MRGHI: opc2 = 76; break; // vmrghh
4717 case Pav_MRGLO: opc2 = 332; break; // vmrglh
4718
4719 default:
4720 goto bad;
4721 }
4722 p = mkFormVX( p, 4, v_dst, v_srcL, v_srcR, opc2 );
4723 goto done;
4724 }
4725
4726 case Pin_AvBin32x4: {
4727 UInt v_dst = vregNo(i->Pin.AvBin32x4.dst);
4728 UInt v_srcL = vregNo(i->Pin.AvBin32x4.srcL);
4729 UInt v_srcR = vregNo(i->Pin.AvBin32x4.srcR);
4730 UInt opc2;
4731 switch (i->Pin.AvBin32x4.op) {
4732
cerionf34ccc42005-09-16 08:55:50 +00004733 case Pav_ADDU: opc2 = 128; break; // vadduwm
4734 case Pav_QADDU: opc2 = 640; break; // vadduws
4735 case Pav_QADDS: opc2 = 896; break; // vaddsws
cerion6b6f59e2005-06-28 20:59:18 +00004736
cerionf34ccc42005-09-16 08:55:50 +00004737 case Pav_SUBU: opc2 = 1152; break; // vsubuwm
4738 case Pav_QSUBU: opc2 = 1664; break; // vsubuws
4739 case Pav_QSUBS: opc2 = 1920; break; // vsubsws
cerion6b6f59e2005-06-28 20:59:18 +00004740
4741 case Pav_AVGU: opc2 = 1154; break; // vavguw
4742 case Pav_AVGS: opc2 = 1410; break; // vavgsw
4743
4744 case Pav_MAXU: opc2 = 130; break; // vmaxuw
4745 case Pav_MAXS: opc2 = 386; break; // vmaxsw
4746
4747 case Pav_MINS: opc2 = 898; break; // vminsw
4748 case Pav_MINU: opc2 = 642; break; // vminuw
4749
4750 case Pav_CMPEQU: opc2 = 134; break; // vcmpequw
4751 case Pav_CMPGTS: opc2 = 902; break; // vcmpgtsw
4752 case Pav_CMPGTU: opc2 = 646; break; // vcmpgtuw
4753
4754 case Pav_SHL: opc2 = 388; break; // vslw
4755 case Pav_SHR: opc2 = 644; break; // vsrw
4756 case Pav_SAR: opc2 = 900; break; // vsraw
4757 case Pav_ROTL: opc2 = 132; break; // vrlw
4758
cerionf34ccc42005-09-16 08:55:50 +00004759 case Pav_PACKUU: opc2 = 78; break; // vpkuwum
4760 case Pav_QPACKUU: opc2 = 206; break; // vpkuwus
4761 case Pav_QPACKSU: opc2 = 334; break; // vpkswus
4762 case Pav_QPACKSS: opc2 = 462; break; // vpkswss
cerion6b6f59e2005-06-28 20:59:18 +00004763
4764 case Pav_MRGHI: opc2 = 140; break; // vmrghw
4765 case Pav_MRGLO: opc2 = 396; break; // vmrglw
4766
4767 default:
4768 goto bad;
4769 }
4770 p = mkFormVX( p, 4, v_dst, v_srcL, v_srcR, opc2 );
4771 goto done;
4772 }
4773
4774 case Pin_AvBin32Fx4: {
4775 UInt v_dst = vregNo(i->Pin.AvBin32Fx4.dst);
4776 UInt v_srcL = vregNo(i->Pin.AvBin32Fx4.srcL);
4777 UInt v_srcR = vregNo(i->Pin.AvBin32Fx4.srcR);
4778 switch (i->Pin.AvBin32Fx4.op) {
4779
cerion8ea0d3e2005-11-14 00:44:47 +00004780 case Pavfp_ADDF:
cerion6b6f59e2005-06-28 20:59:18 +00004781 p = mkFormVX( p, 4, v_dst, v_srcL, v_srcR, 10 ); // vaddfp
4782 break;
cerion8ea0d3e2005-11-14 00:44:47 +00004783 case Pavfp_SUBF:
cerion6b6f59e2005-06-28 20:59:18 +00004784 p = mkFormVX( p, 4, v_dst, v_srcL, v_srcR, 74 ); // vsubfp
4785 break;
cerion8ea0d3e2005-11-14 00:44:47 +00004786 case Pavfp_MAXF:
cerion6b6f59e2005-06-28 20:59:18 +00004787 p = mkFormVX( p, 4, v_dst, v_srcL, v_srcR, 1034 ); // vmaxfp
4788 break;
cerion8ea0d3e2005-11-14 00:44:47 +00004789 case Pavfp_MINF:
cerion6b6f59e2005-06-28 20:59:18 +00004790 p = mkFormVX( p, 4, v_dst, v_srcL, v_srcR, 1098 ); // vminfp
4791 break;
4792
cerion8ea0d3e2005-11-14 00:44:47 +00004793 case Pavfp_MULF: {
cerion6b6f59e2005-06-28 20:59:18 +00004794 /* Make a vmulfp from a vmaddfp:
4795 load -0.0 (0x8000_0000) to each 32-bit word of vB
4796 this makes the add a noop.
4797 */
sewardjf7745052005-12-16 01:06:42 +00004798 UInt vB = 29; // XXX: Using v29 for temp do not change
4799 // without also changing
cerion5b2325f2005-12-23 00:55:09 +00004800 // getRegUsage_PPCInstr
cerion8ea0d3e2005-11-14 00:44:47 +00004801 UInt konst = 0x1F;
cerion6b6f59e2005-06-28 20:59:18 +00004802
ceriond963eb42005-11-16 18:02:58 +00004803 // Better way to load -0.0 (0x80000000) ?
cerion6b6f59e2005-06-28 20:59:18 +00004804 // vspltisw vB,0x1F (0x1F => each word of vB)
cerion8ea0d3e2005-11-14 00:44:47 +00004805 p = mkFormVX( p, 4, vB, konst, 0, 908 );
cerion6b6f59e2005-06-28 20:59:18 +00004806
cerion5b2325f2005-12-23 00:55:09 +00004807 // vslw vB,vB,vB (each word of vB = (0x1F << 0x1F) = 0x80000000
cerion6b6f59e2005-06-28 20:59:18 +00004808 p = mkFormVX( p, 4, vB, vB, vB, 388 );
4809
4810 // Finally, do the multiply:
4811 p = mkFormVA( p, 4, v_dst, v_srcL, vB, v_srcR, 46 );
cerion36991ef2005-09-15 12:42:16 +00004812 break;
cerion6b6f59e2005-06-28 20:59:18 +00004813 }
cerion5b2325f2005-12-23 00:55:09 +00004814 case Pavfp_CMPEQF: // vcmpeqfp
4815 p = mkFormVXR( p, 4, v_dst, v_srcL, v_srcR, 0, 198 );
cerion36991ef2005-09-15 12:42:16 +00004816 break;
cerion5b2325f2005-12-23 00:55:09 +00004817 case Pavfp_CMPGTF: // vcmpgtfp
4818 p = mkFormVXR( p, 4, v_dst, v_srcL, v_srcR, 0, 710 );
cerion36991ef2005-09-15 12:42:16 +00004819 break;
cerion5b2325f2005-12-23 00:55:09 +00004820 case Pavfp_CMPGEF: // vcmpgefp
4821 p = mkFormVXR( p, 4, v_dst, v_srcL, v_srcR, 0, 454 );
cerion36991ef2005-09-15 12:42:16 +00004822 break;
cerion6b6f59e2005-06-28 20:59:18 +00004823
4824 default:
4825 goto bad;
4826 }
4827 goto done;
4828 }
4829
cerion8ea0d3e2005-11-14 00:44:47 +00004830 case Pin_AvUn32Fx4: {
4831 UInt v_dst = vregNo(i->Pin.AvUn32Fx4.dst);
4832 UInt v_src = vregNo(i->Pin.AvUn32Fx4.src);
4833 UInt opc2;
4834 switch (i->Pin.AvUn32Fx4.op) {
ceriond963eb42005-11-16 18:02:58 +00004835 case Pavfp_RCPF: opc2 = 266; break; // vrefp
4836 case Pavfp_RSQRTF: opc2 = 330; break; // vrsqrtefp
4837 case Pavfp_CVTU2F: opc2 = 778; break; // vcfux
4838 case Pavfp_CVTS2F: opc2 = 842; break; // vcfsx
4839 case Pavfp_QCVTF2U: opc2 = 906; break; // vctuxs
4840 case Pavfp_QCVTF2S: opc2 = 970; break; // vctsxs
4841 case Pavfp_ROUNDM: opc2 = 714; break; // vrfim
4842 case Pavfp_ROUNDP: opc2 = 650; break; // vrfip
4843 case Pavfp_ROUNDN: opc2 = 522; break; // vrfin
4844 case Pavfp_ROUNDZ: opc2 = 586; break; // vrfiz
cerion8ea0d3e2005-11-14 00:44:47 +00004845 default:
4846 goto bad;
4847 }
4848 p = mkFormVX( p, 4, v_dst, 0, v_src, opc2 );
4849 goto done;
4850 }
4851
cerionc3d8bdc2005-06-28 18:06:23 +00004852 case Pin_AvPerm: { // vperm
cerionc3d8bdc2005-06-28 18:06:23 +00004853 UInt v_dst = vregNo(i->Pin.AvPerm.dst);
4854 UInt v_srcL = vregNo(i->Pin.AvPerm.srcL);
4855 UInt v_srcR = vregNo(i->Pin.AvPerm.srcR);
cerion92d9d872005-09-15 21:58:50 +00004856 UInt v_ctl = vregNo(i->Pin.AvPerm.ctl);
cerionc3d8bdc2005-06-28 18:06:23 +00004857 p = mkFormVA( p, 4, v_dst, v_srcL, v_srcR, v_ctl, 43 );
4858 goto done;
4859 }
4860
4861 case Pin_AvSel: { // vsel
4862 UInt v_ctl = vregNo(i->Pin.AvSel.ctl);
4863 UInt v_dst = vregNo(i->Pin.AvSel.dst);
4864 UInt v_srcL = vregNo(i->Pin.AvSel.srcL);
4865 UInt v_srcR = vregNo(i->Pin.AvSel.srcR);
4866 p = mkFormVA( p, 4, v_dst, v_srcL, v_srcR, v_ctl, 42 );
4867 goto done;
4868 }
4869
4870 case Pin_AvShlDbl: { // vsldoi
4871 UInt shift = i->Pin.AvShlDbl.shift;
4872 UInt v_dst = vregNo(i->Pin.AvShlDbl.dst);
4873 UInt v_srcL = vregNo(i->Pin.AvShlDbl.srcL);
4874 UInt v_srcR = vregNo(i->Pin.AvShlDbl.srcR);
4875 vassert(shift <= 0xF);
4876 p = mkFormVA( p, 4, v_dst, v_srcL, v_srcR, shift, 44 );
4877 goto done;
4878 }
4879
4880 case Pin_AvSplat: { // vsplt(is)(b,h,w)
4881 UInt v_dst = vregNo(i->Pin.AvShlDbl.dst);
4882 UChar sz = i->Pin.AvSplat.sz;
cerion27b3d7e2005-09-14 20:35:47 +00004883 UInt v_src, opc2;
cerionc3d8bdc2005-06-28 18:06:23 +00004884 vassert(sz == 8 || sz == 16 || sz == 32);
4885
cerion27b3d7e2005-09-14 20:35:47 +00004886 if (i->Pin.AvSplat.src->tag == Pvi_Imm) {
sewardj197bd172005-10-12 11:34:33 +00004887 Char simm5;
cerion6b6f59e2005-06-28 20:59:18 +00004888 opc2 = (sz == 8) ? 780 : (sz == 16) ? 844 : 908; // 8,16,32
cerion27b3d7e2005-09-14 20:35:47 +00004889 /* expects 5-bit-signed-imm */
sewardj197bd172005-10-12 11:34:33 +00004890 simm5 = i->Pin.AvSplat.src->Pvi.Imm5s;
cerion27b3d7e2005-09-14 20:35:47 +00004891 vassert(simm5 >= -16 && simm5 <= 15);
ceriond3e52412005-09-14 21:15:40 +00004892 simm5 = simm5 & 0x1F;
cerion27b3d7e2005-09-14 20:35:47 +00004893 p = mkFormVX( p, 4, v_dst, (UInt)simm5, 0, opc2 );
4894 }
4895 else { // Pri_Reg
sewardj197bd172005-10-12 11:34:33 +00004896 UInt lowest_lane;
cerionc3d8bdc2005-06-28 18:06:23 +00004897 opc2 = (sz == 8) ? 524 : (sz == 16) ? 588 : 652; // 8,16,32
cerion27b3d7e2005-09-14 20:35:47 +00004898 vassert(hregClass(i->Pin.AvSplat.src->Pvi.Reg) == HRcVec128);
4899 v_src = vregNo(i->Pin.AvSplat.src->Pvi.Reg);
sewardj197bd172005-10-12 11:34:33 +00004900 lowest_lane = (128/sz)-1;
cerion27b3d7e2005-09-14 20:35:47 +00004901 p = mkFormVX( p, 4, v_dst, lowest_lane, v_src, opc2 );
cerionc3d8bdc2005-06-28 18:06:23 +00004902 }
4903 goto done;
4904 }
4905
cerion6b6f59e2005-06-28 20:59:18 +00004906 case Pin_AvCMov: {
cerion5b2325f2005-12-23 00:55:09 +00004907 UInt v_dst = vregNo(i->Pin.AvCMov.dst);
4908 UInt v_src = vregNo(i->Pin.AvCMov.src);
4909 PPCCondCode cc = i->Pin.AvCMov.cond;
cerion6b6f59e2005-06-28 20:59:18 +00004910
4911 if (v_dst == v_src) goto done;
4912
4913 vassert(cc.test != Pct_ALWAYS);
4914
4915 /* jmp fwds 2 insns if !condition */
4916 if (cc.test != Pct_ALWAYS) {
4917 /* bc !ct,cf,n_bytes>>2 */
4918 p = mkFormB(p, invertCondTest(cc.test), cc.flag, 8>>2, 0, 0);
4919 }
4920 /* vmr */
4921 p = mkFormVX( p, 4, v_dst, v_src, v_src, 1156 );
4922 goto done;
4923 }
4924
cerionc3d8bdc2005-06-28 18:06:23 +00004925 case Pin_AvLdVSCR: { // mtvscr
4926 UInt v_src = vregNo(i->Pin.AvLdVSCR.src);
4927 p = mkFormVX( p, 4, 0, 0, v_src, 1604 );
4928 goto done;
4929 }
4930
sewardjc6bbd472012-04-02 10:20:48 +00004931 case Pin_Dfp64Unary: {
4932 UInt fr_dst = fregNo( i->Pin.FpUnary.dst );
4933 UInt fr_src = fregNo( i->Pin.FpUnary.src );
4934
4935 switch (i->Pin.Dfp64Unary.op) {
4936 case Pfp_MOV: // fmr, PPC32 p410
4937 p = mkFormX( p, 63, fr_dst, 0, fr_src, 72, 0 );
4938 break;
sewardj26217b02012-04-12 17:19:48 +00004939 case Pfp_DCTDP: // D32 to D64
4940 p = mkFormX( p, 59, fr_dst, 0, fr_src, 258, 0 );
4941 break;
4942 case Pfp_DRSP: // D64 to D32
4943 p = mkFormX( p, 59, fr_dst, 0, fr_src, 770, 0 );
4944 break;
4945 case Pfp_DCFFIX: // I64 to D64 conversion
4946 /* ONLY WORKS ON POWER7 */
4947 p = mkFormX( p, 59, fr_dst, 0, fr_src, 802, 0);
4948 break;
4949 case Pfp_DCTFIX: // D64 to I64 conversion
4950 p = mkFormX( p, 59, fr_dst, 0, fr_src, 290, 0);
4951 break;
sewardjcdc376d2012-04-23 11:21:12 +00004952 case Pfp_DXEX: // Extract exponent
4953 p = mkFormX( p, 59, fr_dst, 0, fr_src, 354, 0 );
4954 break;
sewardjc6bbd472012-04-02 10:20:48 +00004955 default:
4956 goto bad;
4957 }
4958 goto done;
4959 }
4960
4961 case Pin_Dfp64Binary: {
4962 UInt fr_dst = fregNo( i->Pin.Dfp64Binary.dst );
4963 UInt fr_srcL = fregNo( i->Pin.Dfp64Binary.srcL );
4964 UInt fr_srcR = fregNo( i->Pin.Dfp64Binary.srcR );
4965 switch (i->Pin.Dfp64Binary.op) {
4966 case Pfp_DFPADD: /* dadd, dfp add, use default RM from reg ignore mode
4967 * from the Iop instruction. */
4968 p = mkFormX( p, 59, fr_dst, fr_srcL, fr_srcR, 2, 0 );
4969 break;
4970 case Pfp_DFPSUB: /* dsub, dfp subtract, use default RM from reg ignore
4971 * mode from the Iop instruction. */
4972 p = mkFormX( p, 59, fr_dst, fr_srcL, fr_srcR, 514, 0 );
4973 break;
4974 case Pfp_DFPMUL: /* dmul, dfp multipy, use default RM from reg ignore
4975 * mode from the Iop instruction. */
4976 p = mkFormX( p, 59, fr_dst, fr_srcL, fr_srcR, 34, 0 );
4977 break;
4978 case Pfp_DFPDIV: /* ddiv, dfp divide, use default RM from reg ignore
4979 * mode from the Iop instruction. */
4980 p = mkFormX( p, 59, fr_dst, fr_srcL, fr_srcR, 546, 0 );
4981 break;
sewardjcdc376d2012-04-23 11:21:12 +00004982 case Pfp_DIEX: /* diex, insert exponent */
4983 p = mkFormX( p, 59, fr_dst, fr_srcL, fr_srcR, 866, 0 );
4984 break;
sewardjc6bbd472012-04-02 10:20:48 +00004985 default:
4986 goto bad;
4987 }
4988 goto done;
4989 }
4990
sewardj26217b02012-04-12 17:19:48 +00004991 case Pin_DfpShift: {
4992 UInt fr_src = fregNo(i->Pin.DfpShift.src);
4993 UInt fr_dst = fregNo(i->Pin.DfpShift.dst);
4994 UInt shift;
4995
4996 shift = i->Pin.DfpShift.shift->Pri.Imm;
4997
4998 switch (i->Pin.DfpShift.op) {
4999 case Pfp_DSCLI: /* dscli, DFP shift left by fr_srcR */
5000 p = mkFormZ22( p, 59, fr_dst, fr_src, shift, 66, 0 );
5001 break;
5002 case Pfp_DSCRI: /* dscri, DFP shift right by fr_srcR */
5003 p = mkFormZ22( p, 59, fr_dst, fr_src, shift, 98, 0 );
5004 break;
5005 default:
5006 vex_printf("ERROR: emit_PPCInstr default case\n");
5007 goto bad;
5008 }
5009 goto done;
5010 }
5011
sewardjcdc376d2012-04-23 11:21:12 +00005012 case Pin_ExtractExpD128: {
5013 UInt fr_dst = fregNo(i->Pin.ExtractExpD128.dst);
5014 UInt fr_srcHi = fregNo(i->Pin.ExtractExpD128.src_hi);
5015 UInt fr_srcLo = fregNo(i->Pin.ExtractExpD128.src_lo);
5016
5017 switch (i->Pin.ExtractExpD128.op) {
5018 case Pfp_DXEXQ:
5019 /* Setup the upper and lower registers of the source operand
5020 * register pair.
5021 */
5022 p = mkFormX( p, 63, 12, 0, fr_srcHi, 72, 0);
5023 p = mkFormX( p, 63, 13, 0, fr_srcLo, 72, 0);
5024 p = mkFormX( p, 63, 10, 0, 12, 354, 0 );
5025
5026 /* The instruction will put the 64-bit result in
5027 * register 10.
5028 */
5029 p = mkFormX(p, 63, fr_dst, 0, 10, 72, 0);
5030 break;
5031 default:
5032 vex_printf("Error: emit_PPCInstr case Pin_DfpExtractExp, case inst Default\n");
5033 goto bad;
5034 }
5035 goto done;
5036 }
sewardj26217b02012-04-12 17:19:48 +00005037 case Pin_Dfp128Unary: {
5038 UInt fr_dstHi = fregNo(i->Pin.Dfp128Unary.dst_hi);
5039 UInt fr_dstLo = fregNo(i->Pin.Dfp128Unary.dst_lo);
5040 UInt fr_srcLo = fregNo(i->Pin.Dfp128Unary.src_lo);
5041
5042 /* Do instruction with 128-bit source operands in registers (10,11)
5043 * and (12,13).
5044 */
5045 switch (i->Pin.Dfp128Unary.op) {
5046 case Pfp_DCTQPQ: // D64 to D128, srcLo holds 64 bit operand
5047 p = mkFormX( p, 63, 12, 0, fr_srcLo, 72, 0);
5048
5049 p = mkFormX( p, 63, 10, 0, 12, 258, 0 );
5050
5051 /* The instruction will put the 128-bit result in
5052 * registers (10,11). Note, the operand in the instruction only
5053 * reference the first of the two registers in the pair.
5054 */
5055 p = mkFormX(p, 63, fr_dstHi, 0, 10, 72, 0);
5056 p = mkFormX(p, 63, fr_dstLo, 0, 11, 72, 0);
5057 break;
5058 default:
5059 vex_printf("Error: emit_PPCInstr case Pin_Dfp128Unary, case inst Default\
5060\n");
5061 goto bad;
5062 }
5063 goto done;
5064 }
5065
sewardjc6bbd472012-04-02 10:20:48 +00005066 case Pin_Dfp128Binary: {
5067 /* dst is used to supply the left source operand and return
5068 * the result.
5069 */
5070 UInt fr_dstHi = fregNo( i->Pin.Dfp128Binary.dst_hi );
5071 UInt fr_dstLo = fregNo( i->Pin.Dfp128Binary.dst_lo );
5072 UInt fr_srcRHi = fregNo( i->Pin.Dfp128Binary.srcR_hi );
5073 UInt fr_srcRLo = fregNo( i->Pin.Dfp128Binary.srcR_lo );
5074
5075 /* Setup the upper and lower registers of the source operand
5076 * register pair.
5077 */
5078 p = mkFormX( p, 63, 10, 0, fr_dstHi, 72, 0 );
5079 p = mkFormX( p, 63, 11, 0, fr_dstLo, 72, 0 );
5080 p = mkFormX( p, 63, 12, 0, fr_srcRHi, 72, 0 );
5081 p = mkFormX( p, 63, 13, 0, fr_srcRLo, 72, 0 );
5082
5083 /* Do instruction with 128-bit source operands in registers (10,11)
5084 * and (12,13).
5085 */
5086 switch (i->Pin.Dfp128Binary.op) {
5087 case Pfp_DFPADDQ:
5088 p = mkFormX( p, 63, 10, 10, 12, 2, 0 );
5089 break;
5090 case Pfp_DFPSUBQ:
5091 p = mkFormX( p, 63, 10, 10, 12, 514, 0 );
5092 break;
5093 case Pfp_DFPMULQ:
5094 p = mkFormX( p, 63, 10, 10, 12, 34, 0 );
5095 break;
5096 case Pfp_DFPDIVQ:
5097 p = mkFormX( p, 63, 10, 10, 12, 546, 0 );
5098 break;
5099 default:
5100 goto bad;
5101 }
5102
5103 /* The instruction will put the 128-bit result in
5104 * registers (10,11). Note, the operand in the instruction only
5105 * reference the first of the two registers in the pair.
5106 */
5107 p = mkFormX(p, 63, fr_dstHi, 0, 10, 72, 0);
5108 p = mkFormX(p, 63, fr_dstLo, 0, 11, 72, 0);
5109 goto done;
5110 }
5111
sewardj26217b02012-04-12 17:19:48 +00005112 case Pin_DfpShift128: {
5113 UInt fr_src_hi = fregNo(i->Pin.DfpShift128.src_hi);
5114 UInt fr_src_lo = fregNo(i->Pin.DfpShift128.src_lo);
5115 UInt fr_dst_hi = fregNo(i->Pin.DfpShift128.dst_hi);
5116 UInt fr_dst_lo = fregNo(i->Pin.DfpShift128.dst_lo);
5117 UInt shift;
5118
5119 shift = i->Pin.DfpShift128.shift->Pri.Imm;
5120
5121 /* setup source operand in register 12, 13 pair */
5122 p = mkFormX(p, 63, 12, 0, fr_src_hi, 72, 0);
5123 p = mkFormX(p, 63, 13, 0, fr_src_lo, 72, 0);
5124
5125 /* execute instruction putting result in register 10, 11 pair */
5126 switch (i->Pin.DfpShift128.op) {
5127 case Pfp_DSCLIQ: /* dscliq, DFP shift left, fr_srcR is the integer
5128 * shift amount.
5129 */
5130 p = mkFormZ22( p, 63, 10, 12, shift, 66, 0 );
5131 break;
5132 case Pfp_DSCRIQ: /* dscriq, DFP shift right, fr_srcR is the integer
5133 * shift amount.
5134 */
5135 p = mkFormZ22( p, 63, 10, 12, shift, 98, 0 );
5136 break;
5137 default:
5138 vex_printf("ERROR: emit_PPCInstr quad default case %d \n",
5139 i->Pin.DfpShift128.op);
5140 goto bad;
5141 }
5142
5143 /* The instruction put the 128-bit result in registers (10,11).
5144 * Note, the operand in the instruction only reference the first of
5145 * the two registers in the pair.
5146 */
5147 p = mkFormX(p, 63, fr_dst_hi, 0, 10, 72, 0);
5148 p = mkFormX(p, 63, fr_dst_lo, 0, 11, 72, 0);
5149 goto done;
5150 }
5151
sewardjcdc376d2012-04-23 11:21:12 +00005152 case Pin_DfpRound: {
5153 UInt fr_dst = fregNo(i->Pin.DfpRound.dst);
5154 UInt fr_src = fregNo(i->Pin.DfpRound.src);
5155 UInt r_rmc, r, rmc;
5156
5157 r_rmc = i->Pin.DfpRound.r_rmc->Pri.Imm;
5158 r = (r_rmc & 0x8) >> 3;
5159 rmc = r_rmc & 0x3;
5160
5161 // drintx
5162 p = mkFormZ23(p, 59, fr_dst, r, fr_src, rmc, 99, 0);
5163 goto done;
5164 }
5165
5166 case Pin_DfpRound128: {
5167 UInt fr_dstHi = fregNo(i->Pin.DfpRound128.dst_hi);
5168 UInt fr_dstLo = fregNo(i->Pin.DfpRound128.dst_lo);
5169 UInt fr_srcHi = fregNo(i->Pin.DfpRound128.src_hi);
5170 UInt fr_srcLo = fregNo(i->Pin.DfpRound128.src_lo);
5171 UInt r_rmc, r, rmc;
5172
5173 r_rmc = i->Pin.DfpRound128.r_rmc->Pri.Imm;
5174 r = (r_rmc & 0x8) >> 3;
5175 rmc = r_rmc & 0x3;
5176
5177 /* Setup the upper and lower registers of the source operand
5178 * register pair.
5179 */
5180 p = mkFormX(p, 63, 12, 0, fr_srcHi, 72, 0);
5181 p = mkFormX(p, 63, 13, 0, fr_srcLo, 72, 0);
5182
5183 /* Do drintx instruction with 128-bit source operands in
5184 * registers (12,13).
5185 */
5186 p = mkFormZ23(p, 63, 10, r, 12, rmc, 99, 0);
5187
5188 /* The instruction will put the 128-bit result in
5189 * registers (10,11). Note, the operand in the instruction only
5190 * reference the first of the two registers in the pair.
5191 */
5192 p = mkFormX(p, 63, fr_dstHi, 0, 10, 72, 0);
5193 p = mkFormX(p, 63, fr_dstLo, 0, 11, 72, 0);
5194 goto done;
5195 }
5196
5197 case Pin_DfpQuantize: {
5198 UInt fr_dst = fregNo(i->Pin.DfpQuantize.dst);
5199 UInt fr_srcL = fregNo(i->Pin.DfpQuantize.srcL);
5200 UInt fr_srcR = fregNo(i->Pin.DfpQuantize.srcR);
5201 UInt rmc;
5202
5203 rmc = i->Pin.DfpQuantize.rmc->Pri.Imm;
5204
5205 switch (i->Pin.DfpQuantize.op) {
5206 case Pfp_DQUA:
5207 p = mkFormZ23(p, 59, fr_dst, fr_srcL, fr_srcR, rmc, 3, 0);
5208 break;
5209 case Pfp_RRDTR:
5210 p = mkFormZ23(p, 59, fr_dst, fr_srcL, fr_srcR, rmc, 35, 0);
5211 break;
5212 default:
5213 break;
5214 }
5215 goto done;
5216 }
5217
5218 case Pin_DfpQuantize128: {
5219 UInt fr_dst_hi = fregNo(i->Pin.DfpQuantize128.dst_hi);
5220 UInt fr_dst_lo = fregNo(i->Pin.DfpQuantize128.dst_lo);
5221 UInt fr_src_hi = fregNo(i->Pin.DfpQuantize128.src_hi);
5222 UInt fr_src_lo = fregNo(i->Pin.DfpQuantize128.src_lo);
5223 UInt rmc;
5224
5225 rmc = i->Pin.DfpQuantize128.rmc->Pri.Imm;
5226 /* Setup the upper and lower registers of the source operand
5227 * register pairs. Note, left source operand passed in via the
5228 * dst register pair.
5229 */
5230 p = mkFormX(p, 63, 10, 0, fr_dst_hi, 72, 0);
5231 p = mkFormX(p, 63, 11, 0, fr_dst_lo, 72, 0);
5232 p = mkFormX(p, 63, 12, 0, fr_src_hi, 72, 0);
5233 p = mkFormX(p, 63, 13, 0, fr_src_lo, 72, 0);
5234
5235 /* Do dquaq instruction with 128-bit source operands in
5236 * registers (12,13).
5237 */
5238 switch (i->Pin.DfpQuantize128.op) {
5239 case Pfp_DQUAQ:
5240 p = mkFormZ23(p, 63, 10, 10, 12, rmc, 3, 0);
5241 break;
5242 case Pfp_DRRNDQ:
5243 p = mkFormZ23(p, 63, 10, 10, 12, rmc, 35, 0);
5244 break;
5245 default:
5246 vpanic("Pin_DfpQuantize128: default case, couldn't find inst to issue \n");
5247 break;
5248 }
5249
5250 /* The instruction will put the 128-bit result in
5251 * registers (10,11). Note, the operand in the instruction only
5252 * reference the first of the two registers in the pair.
5253 */
5254 p = mkFormX(p, 63, fr_dst_hi, 0, 10, 72, 0);
5255 p = mkFormX(p, 63, fr_dst_lo, 0, 11, 72, 0);
5256 goto done;
5257 }
5258
sewardj26217b02012-04-12 17:19:48 +00005259 case Pin_DfpD128toD64: {
5260 UInt fr_dst = fregNo( i->Pin.DfpD128toD64.dst );
5261 UInt fr_srcHi = fregNo( i->Pin.DfpD128toD64.src_hi );
5262 UInt fr_srcLo = fregNo( i->Pin.DfpD128toD64.src_lo );
5263
5264 /* Setup the upper and lower registers of the source operand
5265 * register pair.
5266 */
5267 p = mkFormX( p, 63, 10, 0, fr_dst, 72, 0 );
5268 p = mkFormX( p, 63, 12, 0, fr_srcHi, 72, 0 );
5269 p = mkFormX( p, 63, 13, 0, fr_srcLo, 72, 0 );
5270
5271 /* Do instruction with 128-bit source operands in registers (10,11) */
5272 switch (i->Pin.Dfp128Binary.op) {
5273 case Pfp_DRDPQ:
5274 p = mkFormX( p, 63, 10, 0, 12, 770, 0 );
5275 break;
5276 case Pfp_DCTFIXQ:
5277 p = mkFormX( p, 63, 10, 0, 12, 290, 0 );
5278 break;
5279 default:
5280 goto bad;
5281 }
5282
5283 /* The instruction will put the 64-bit result in registers 10. */
5284 p = mkFormX(p, 63, fr_dst, 0, 10, 72, 0);
5285 goto done;
5286 }
sewardjdb014092012-04-20 23:58:17 +00005287
sewardj26217b02012-04-12 17:19:48 +00005288 case Pin_DfpI64StoD128: {
5289 UInt fr_dstHi = fregNo( i->Pin.DfpI64StoD128.dst_hi );
5290 UInt fr_dstLo = fregNo( i->Pin.DfpI64StoD128.dst_lo );
5291 UInt fr_src = fregNo( i->Pin.DfpI64StoD128.src );
5292
5293 switch (i->Pin.Dfp128Binary.op) {
5294 case Pfp_DCFFIXQ:
5295 p = mkFormX( p, 63, 10, 11, fr_src, 802, 0 );
5296 break;
5297 default:
5298 goto bad;
5299 }
5300
5301 /* The instruction will put the 64-bit result in registers 10, 11. */
5302 p = mkFormX(p, 63, fr_dstHi, 0, 10, 72, 0);
5303 p = mkFormX(p, 63, fr_dstLo, 0, 11, 72, 0);
5304 goto done;
5305 }
sewardjdb014092012-04-20 23:58:17 +00005306
sewardjcdc376d2012-04-23 11:21:12 +00005307 case Pin_InsertExpD128: {
5308 UInt fr_dstHi = fregNo(i->Pin.InsertExpD128.dst_hi);
5309 UInt fr_dstLo = fregNo(i->Pin.InsertExpD128.dst_lo);
5310 UInt fr_srcL = fregNo(i->Pin.InsertExpD128.srcL);
5311 UInt fr_srcRHi = fregNo(i->Pin.InsertExpD128.srcR_hi);
5312 UInt fr_srcRLo = fregNo(i->Pin.InsertExpD128.srcR_lo);
5313
5314 /* The left operand is a single F64 value, the right is an F128
5315 * register pair.
5316 */
5317 p = mkFormX(p, 63, 10, 0, fr_srcL, 72, 0);
5318 p = mkFormX(p, 63, 12, 0, fr_srcRHi, 72, 0);
5319 p = mkFormX(p, 63, 13, 0, fr_srcRLo, 72, 0);
5320 p = mkFormX(p, 63, 10, 10, 12, 866, 0 );
5321
5322 /* The instruction will put the 128-bit result into
5323 * registers (10,11). Note, the operand in the instruction only
5324 * reference the first of the two registers in the pair.
5325 */
5326 p = mkFormX(p, 63, fr_dstHi, 0, 10, 72, 0);
5327 p = mkFormX(p, 63, fr_dstLo, 0, 11, 72, 0);
5328 goto done;
5329 }
5330
5331 case Pin_Dfp64Cmp:{
5332 UChar crfD = 1;
5333 UInt r_dst = iregNo(i->Pin.Dfp64Cmp.dst, mode64);
5334 UInt fr_srcL = fregNo(i->Pin.Dfp64Cmp.srcL);
5335 UInt fr_srcR = fregNo(i->Pin.Dfp64Cmp.srcR);
5336 vassert(crfD < 8);
5337 // dcmpo, dcmpu
5338 p = mkFormX(p, 59, crfD<<2, fr_srcL, fr_srcR, 130, 0);
5339
5340 // mfcr (mv CR to r_dst)
5341 p = mkFormX(p, 31, r_dst, 0, 0, 19, 0);
5342
5343 // rlwinm r_dst,r_dst,8,28,31
5344 // => rotate field 1 to bottomw of word, masking out upper 28
5345 p = mkFormM(p, 21, r_dst, r_dst, 8, 28, 31, 0);
5346 goto done;
5347 }
5348
5349 case Pin_Dfp128Cmp: {
5350 UChar crfD = 1;
5351 UInt r_dst = iregNo(i->Pin.Dfp128Cmp.dst, mode64);
5352 UInt fr_srcL_hi = fregNo(i->Pin.Dfp128Cmp.srcL_hi);
5353 UInt fr_srcL_lo = fregNo(i->Pin.Dfp128Cmp.srcL_lo);
5354 UInt fr_srcR_hi = fregNo(i->Pin.Dfp128Cmp.srcR_hi);
5355 UInt fr_srcR_lo = fregNo(i->Pin.Dfp128Cmp.srcR_lo);
5356 vassert(crfD < 8);
5357 // dcmpoq, dcmpuq
5358 /* Setup the upper and lower registers of the source operand
5359 * register pair.
5360 */
5361 p = mkFormX(p, 63, 10, 0, fr_srcL_hi, 72, 0);
5362 p = mkFormX(p, 63, 11, 0, fr_srcL_lo, 72, 0);
5363 p = mkFormX(p, 63, 12, 0, fr_srcR_hi, 72, 0);
5364 p = mkFormX(p, 63, 13, 0, fr_srcR_lo, 72, 0);
5365
5366 p = mkFormX(p, 63, crfD<<2, 10, 12, 130, 0);
5367
5368 // mfcr (mv CR to r_dst)
5369 p = mkFormX(p, 31, r_dst, 0, 0, 19, 0);
5370
5371 // rlwinm r_dst,r_dst,8,28,31
5372 // => rotate field 1 to bottomw of word, masking out upper 28
5373 p = mkFormM(p, 21, r_dst, r_dst, 8, 28, 31, 0);
5374 goto done;
5375 }
5376
sewardj3dee8492012-04-20 00:13:28 +00005377 case Pin_EvCheck: {
5378 /* This requires a 32-bit dec/test in both 32- and 64-bit
5379 modes. */
5380 /* We generate:
5381 lwz r30, amCounter
5382 addic. r30, r30, -1
5383 stw r30, amCounter
5384 bge nofail
5385 lwz/ld r30, amFailAddr
5386 mtctr r30
5387 bctr
5388 nofail:
5389 */
5390 UChar* p0 = p;
5391 /* lwz r30, amCounter */
5392 p = do_load_or_store_word32(p, True/*isLoad*/, /*r*/30,
5393 i->Pin.EvCheck.amCounter, mode64);
5394 /* addic. r30,r30,-1 */
5395 p = emit32(p, 0x37DEFFFF);
5396 /* stw r30, amCounter */
5397 p = do_load_or_store_word32(p, False/*!isLoad*/, /*r*/30,
5398 i->Pin.EvCheck.amCounter, mode64);
5399 /* bge nofail */
5400 p = emit32(p, 0x40800010);
5401 /* lwz/ld r30, amFailAddr */
5402 p = do_load_or_store_machine_word(p, True/*isLoad*/, /*r*/30,
5403 i->Pin.EvCheck.amFailAddr, mode64);
5404 /* mtctr r30 */
5405 p = mkFormXFX(p, /*r*/30, 9, 467);
5406 /* bctr */
5407 p = mkFormXL(p, 19, Pct_ALWAYS, 0, 0, 528, 0);
5408 /* nofail: */
5409
5410 /* Crosscheck */
5411 vassert(evCheckSzB_PPC() == (UChar*)p - (UChar*)p0);
5412 goto done;
5413 }
5414
5415 case Pin_ProfInc: {
5416 /* We generate:
5417 (ctrP is unknown now, so use 0x65556555(65556555) in the
5418 expectation that a later call to LibVEX_patchProfCtr
5419 will be used to fill in the immediate fields once the
5420 right value is known.)
5421 32-bit:
5422 imm32-exactly r30, 0x65556555
5423 lwz r29, 4(r30)
5424 addic. r29, r29, 1
5425 stw r29, 4(r30)
5426 lwz r29, 0(r30)
5427 addze r29, r29
5428 stw r29, 0(r30)
5429 64-bit:
5430 imm64-exactly r30, 0x6555655565556555
5431 ld r29, 0(r30)
sewardjf252de52012-04-20 10:42:24 +00005432 addi r29, r29, 1
sewardj3dee8492012-04-20 00:13:28 +00005433 std r29, 0(r30)
5434 */
5435 if (mode64) {
5436 p = mkLoadImm_EXACTLY2or5(
5437 p, /*r*/30, 0x6555655565556555ULL, True/*mode64*/);
5438 p = emit32(p, 0xEBBE0000);
sewardjf252de52012-04-20 10:42:24 +00005439 p = emit32(p, 0x3BBD0001);
sewardj3dee8492012-04-20 00:13:28 +00005440 p = emit32(p, 0xFBBE0000);
5441 } else {
5442 p = mkLoadImm_EXACTLY2or5(
5443 p, /*r*/30, 0x65556555ULL, False/*!mode64*/);
5444 p = emit32(p, 0x83BE0004);
5445 p = emit32(p, 0x37BD0001);
5446 p = emit32(p, 0x93BE0004);
5447 p = emit32(p, 0x83BE0000);
5448 p = emit32(p, 0x7FBD0194);
5449 p = emit32(p, 0x93BE0000);
5450 }
5451 /* Tell the caller .. */
5452 vassert(!(*is_profInc));
5453 *is_profInc = True;
5454 goto done;
5455 }
5456
cerionbcf8c3e2005-02-04 16:17:07 +00005457 default:
5458 goto bad;
5459 }
5460
5461 bad:
cerionab9132d2005-02-15 15:46:59 +00005462 vex_printf("\n=> ");
cerion5b2325f2005-12-23 00:55:09 +00005463 ppPPCInstr(i, mode64);
5464 vpanic("emit_PPCInstr");
cerionbcf8c3e2005-02-04 16:17:07 +00005465 /*NOTREACHED*/
5466
cerionbcf8c3e2005-02-04 16:17:07 +00005467 done:
sewardj9e1cf152012-04-20 02:18:31 +00005468 vassert(p - &buf[0] <= 64);
cerionbcf8c3e2005-02-04 16:17:07 +00005469 return p - &buf[0];
cerionbcf8c3e2005-02-04 16:17:07 +00005470}
5471
sewardj3dee8492012-04-20 00:13:28 +00005472
5473/* How big is an event check? See case for Pin_EvCheck in
5474 emit_PPCInstr just above. That crosschecks what this returns, so
5475 we can tell if we're inconsistent. */
5476Int evCheckSzB_PPC ( void )
5477{
5478 return 28;
5479}
5480
5481
5482/* NB: what goes on here has to be very closely coordinated with the
5483 emitInstr case for XDirect, above. */
5484VexInvalRange chainXDirect_PPC ( void* place_to_chain,
5485 void* disp_cp_chain_me_EXPECTED,
5486 void* place_to_jump_to,
5487 Bool mode64 )
5488{
5489 /* What we're expecting to see is:
5490 imm32/64-fixed r30, disp_cp_chain_me_to_EXPECTED
5491 mtctr r30
5492 bctrl
5493 viz
5494 <8 or 20 bytes generated by mkLoadImm_EXACTLY2or5>
5495 7F C9 03 A6
5496 4E 80 04 21
5497 */
5498 UChar* p = (UChar*)place_to_chain;
5499 vassert(0 == (3 & (HWord)p));
5500 vassert(isLoadImm_EXACTLY2or5(p, /*r*/30,
5501 Ptr_to_ULong(disp_cp_chain_me_EXPECTED),
5502 mode64));
5503 vassert(fetch32(p + (mode64 ? 20 : 8) + 0) == 0x7FC903A6);
5504 vassert(fetch32(p + (mode64 ? 20 : 8) + 4) == 0x4E800421);
5505 /* And what we want to change it to is:
5506 imm32/64-fixed r30, place_to_jump_to
5507 mtctr r30
5508 bctr
5509 viz
5510 <8 or 20 bytes generated by mkLoadImm_EXACTLY2or5>
5511 7F C9 03 A6
5512 4E 80 04 20
5513 The replacement has the same length as the original.
5514 */
5515 p = mkLoadImm_EXACTLY2or5(p, /*r*/30,
5516 Ptr_to_ULong(place_to_jump_to), mode64);
5517 p = emit32(p, 0x7FC903A6);
5518 p = emit32(p, 0x4E800420);
5519
5520 Int len = p - (UChar*)place_to_chain;
5521 vassert(len == (mode64 ? 28 : 16)); /* stay sane */
5522 VexInvalRange vir = {(HWord)place_to_chain, len};
5523 return vir;
5524}
5525
5526
5527/* NB: what goes on here has to be very closely coordinated with the
5528 emitInstr case for XDirect, above. */
5529VexInvalRange unchainXDirect_PPC ( void* place_to_unchain,
5530 void* place_to_jump_to_EXPECTED,
5531 void* disp_cp_chain_me,
5532 Bool mode64 )
5533{
5534 /* What we're expecting to see is:
5535 imm32/64-fixed r30, place_to_jump_to_EXPECTED
5536 mtctr r30
5537 bctr
5538 viz
5539 <8 or 20 bytes generated by mkLoadImm_EXACTLY2or5>
5540 7F C9 03 A6
5541 4E 80 04 20
5542 */
5543 UChar* p = (UChar*)place_to_unchain;
5544 vassert(0 == (3 & (HWord)p));
5545 vassert(isLoadImm_EXACTLY2or5(p, /*r*/30,
5546 Ptr_to_ULong(place_to_jump_to_EXPECTED),
5547 mode64));
5548 vassert(fetch32(p + (mode64 ? 20 : 8) + 0) == 0x7FC903A6);
5549 vassert(fetch32(p + (mode64 ? 20 : 8) + 4) == 0x4E800420);
5550 /* And what we want to change it to is:
5551 imm32/64-fixed r30, disp_cp_chain_me
5552 mtctr r30
5553 bctrl
5554 viz
5555 <8 or 20 bytes generated by mkLoadImm_EXACTLY2or5>
5556 7F C9 03 A6
5557 4E 80 04 21
5558 The replacement has the same length as the original.
5559 */
5560 p = mkLoadImm_EXACTLY2or5(p, /*r*/30,
5561 Ptr_to_ULong(disp_cp_chain_me), mode64);
5562 p = emit32(p, 0x7FC903A6);
5563 p = emit32(p, 0x4E800421);
5564
5565 Int len = p - (UChar*)place_to_unchain;
5566 vassert(len == (mode64 ? 28 : 16)); /* stay sane */
5567 VexInvalRange vir = {(HWord)place_to_unchain, len};
5568 return vir;
5569}
5570
5571
5572/* Patch the counter address into a profile inc point, as previously
5573 created by the Pin_ProfInc case for emit_PPCInstr. */
5574VexInvalRange patchProfInc_PPC ( void* place_to_patch,
5575 ULong* location_of_counter,
5576 Bool mode64 )
5577{
5578 UChar* p = (UChar*)place_to_patch;
5579 vassert(0 == (3 & (HWord)p));
5580
5581 Int len = 0;
5582 if (mode64) {
5583 vassert(isLoadImm_EXACTLY2or5(p, /*r*/30,
5584 0x6555655565556555ULL, True/*mode64*/));
5585 vassert(fetch32(p + 20) == 0xEBBE0000);
sewardjf252de52012-04-20 10:42:24 +00005586 vassert(fetch32(p + 24) == 0x3BBD0001);
sewardj3dee8492012-04-20 00:13:28 +00005587 vassert(fetch32(p + 28) == 0xFBBE0000);
5588 p = mkLoadImm_EXACTLY2or5(p, /*r*/30,
5589 Ptr_to_ULong(location_of_counter),
5590 True/*mode64*/);
5591 len = p - (UChar*)place_to_patch;
5592 vassert(len == 20);
5593 } else {
5594 vassert(isLoadImm_EXACTLY2or5(p, /*r*/30,
5595 0x65556555ULL, False/*!mode64*/));
5596 vassert(fetch32(p + 8) == 0x83BE0004);
5597 vassert(fetch32(p + 12) == 0x37BD0001);
5598 vassert(fetch32(p + 16) == 0x93BE0004);
5599 vassert(fetch32(p + 20) == 0x83BE0000);
5600 vassert(fetch32(p + 24) == 0x7FBD0194);
5601 vassert(fetch32(p + 28) == 0x93BE0000);
5602 p = mkLoadImm_EXACTLY2or5(p, /*r*/30,
5603 Ptr_to_ULong(location_of_counter),
5604 False/*!mode64*/);
5605 len = p - (UChar*)place_to_patch;
5606 vassert(len == 8);
5607 }
5608 VexInvalRange vir = {(HWord)place_to_patch, len};
5609 return vir;
5610}
5611
5612
cerionbcf8c3e2005-02-04 16:17:07 +00005613/*---------------------------------------------------------------*/
sewardjcef7d3e2009-07-02 12:21:59 +00005614/*--- end host_ppc_defs.c ---*/
cerionbcf8c3e2005-02-04 16:17:07 +00005615/*---------------------------------------------------------------*/