1
2 /*---------------------------------------------------------------*/
3 /*--- begin host_ppc_defs.c ---*/
4 /*---------------------------------------------------------------*/
5
6 /*
7 This file is part of Valgrind, a dynamic binary instrumentation
8 framework.
9
10 Copyright (C) 2004-2013 OpenWorks LLP
11 info@open-works.net
12
13 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.
17
18 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
26 02110-1301, USA.
27
28 The GNU General Public License is contained in the file COPYING.
29
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.
34 */
35
36 #include "libvex_basictypes.h"
37 #include "libvex.h"
38 #include "libvex_trc_values.h"
39
40 #include "main_util.h"
41 #include "host_generic_regs.h"
42 #include "host_ppc_defs.h"
43
44
45 /* --------- Registers. --------- */
46
ppHRegPPC(HReg reg)47 void ppHRegPPC ( HReg reg )
48 {
49 Int r;
50 static const HChar* ireg32_names[32]
51 = { "%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" };
59 /* 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)) {
66 case HRcInt64:
67 r = hregNumber(reg);
68 vassert(r >= 0 && r < 32);
69 vex_printf("%s", ireg32_names[r]);
70 return;
71 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);
78 vassert(r >= 0 && r < 32);
79 vex_printf("%%fr%d", r);
80 return;
81 case HRcVec128:
82 r = hregNumber(reg);
83 vassert(r >= 0 && r < 32);
84 vex_printf("%%v%d", r);
85 return;
86 default:
87 vpanic("ppHRegPPC");
88 }
89 }
90
91
92 #define MkHRegGPR(_n, _mode64) \
93 mkHReg(_n, _mode64 ? HRcInt64 : HRcInt32, False)
94
hregPPC_GPR0(Bool mode64)95 HReg hregPPC_GPR0 ( Bool mode64 ) { return MkHRegGPR( 0, mode64); }
hregPPC_GPR1(Bool mode64)96 HReg hregPPC_GPR1 ( Bool mode64 ) { return MkHRegGPR( 1, mode64); }
hregPPC_GPR2(Bool mode64)97 HReg hregPPC_GPR2 ( Bool mode64 ) { return MkHRegGPR( 2, mode64); }
hregPPC_GPR3(Bool mode64)98 HReg hregPPC_GPR3 ( Bool mode64 ) { return MkHRegGPR( 3, mode64); }
hregPPC_GPR4(Bool mode64)99 HReg hregPPC_GPR4 ( Bool mode64 ) { return MkHRegGPR( 4, mode64); }
hregPPC_GPR5(Bool mode64)100 HReg hregPPC_GPR5 ( Bool mode64 ) { return MkHRegGPR( 5, mode64); }
hregPPC_GPR6(Bool mode64)101 HReg hregPPC_GPR6 ( Bool mode64 ) { return MkHRegGPR( 6, mode64); }
hregPPC_GPR7(Bool mode64)102 HReg hregPPC_GPR7 ( Bool mode64 ) { return MkHRegGPR( 7, mode64); }
hregPPC_GPR8(Bool mode64)103 HReg hregPPC_GPR8 ( Bool mode64 ) { return MkHRegGPR( 8, mode64); }
hregPPC_GPR9(Bool mode64)104 HReg hregPPC_GPR9 ( Bool mode64 ) { return MkHRegGPR( 9, mode64); }
hregPPC_GPR10(Bool mode64)105 HReg hregPPC_GPR10 ( Bool mode64 ) { return MkHRegGPR(10, mode64); }
hregPPC_GPR11(Bool mode64)106 HReg hregPPC_GPR11 ( Bool mode64 ) { return MkHRegGPR(11, mode64); }
hregPPC_GPR12(Bool mode64)107 HReg hregPPC_GPR12 ( Bool mode64 ) { return MkHRegGPR(12, mode64); }
hregPPC_GPR13(Bool mode64)108 HReg hregPPC_GPR13 ( Bool mode64 ) { return MkHRegGPR(13, mode64); }
hregPPC_GPR14(Bool mode64)109 HReg hregPPC_GPR14 ( Bool mode64 ) { return MkHRegGPR(14, mode64); }
hregPPC_GPR15(Bool mode64)110 HReg hregPPC_GPR15 ( Bool mode64 ) { return MkHRegGPR(15, mode64); }
hregPPC_GPR16(Bool mode64)111 HReg hregPPC_GPR16 ( Bool mode64 ) { return MkHRegGPR(16, mode64); }
hregPPC_GPR17(Bool mode64)112 HReg hregPPC_GPR17 ( Bool mode64 ) { return MkHRegGPR(17, mode64); }
hregPPC_GPR18(Bool mode64)113 HReg hregPPC_GPR18 ( Bool mode64 ) { return MkHRegGPR(18, mode64); }
hregPPC_GPR19(Bool mode64)114 HReg hregPPC_GPR19 ( Bool mode64 ) { return MkHRegGPR(19, mode64); }
hregPPC_GPR20(Bool mode64)115 HReg hregPPC_GPR20 ( Bool mode64 ) { return MkHRegGPR(20, mode64); }
hregPPC_GPR21(Bool mode64)116 HReg hregPPC_GPR21 ( Bool mode64 ) { return MkHRegGPR(21, mode64); }
hregPPC_GPR22(Bool mode64)117 HReg hregPPC_GPR22 ( Bool mode64 ) { return MkHRegGPR(22, mode64); }
hregPPC_GPR23(Bool mode64)118 HReg hregPPC_GPR23 ( Bool mode64 ) { return MkHRegGPR(23, mode64); }
hregPPC_GPR24(Bool mode64)119 HReg hregPPC_GPR24 ( Bool mode64 ) { return MkHRegGPR(24, mode64); }
hregPPC_GPR25(Bool mode64)120 HReg hregPPC_GPR25 ( Bool mode64 ) { return MkHRegGPR(25, mode64); }
hregPPC_GPR26(Bool mode64)121 HReg hregPPC_GPR26 ( Bool mode64 ) { return MkHRegGPR(26, mode64); }
hregPPC_GPR27(Bool mode64)122 HReg hregPPC_GPR27 ( Bool mode64 ) { return MkHRegGPR(27, mode64); }
hregPPC_GPR28(Bool mode64)123 HReg hregPPC_GPR28 ( Bool mode64 ) { return MkHRegGPR(28, mode64); }
hregPPC_GPR29(Bool mode64)124 HReg hregPPC_GPR29 ( Bool mode64 ) { return MkHRegGPR(29, mode64); }
hregPPC_GPR30(Bool mode64)125 HReg hregPPC_GPR30 ( Bool mode64 ) { return MkHRegGPR(30, mode64); }
hregPPC_GPR31(Bool mode64)126 HReg hregPPC_GPR31 ( Bool mode64 ) { return MkHRegGPR(31, mode64); }
127
128 #undef MK_INT_HREG
129
hregPPC_FPR0(void)130 HReg hregPPC_FPR0 ( void ) { return mkHReg( 0, HRcFlt64, False); }
hregPPC_FPR1(void)131 HReg hregPPC_FPR1 ( void ) { return mkHReg( 1, HRcFlt64, False); }
hregPPC_FPR2(void)132 HReg hregPPC_FPR2 ( void ) { return mkHReg( 2, HRcFlt64, False); }
hregPPC_FPR3(void)133 HReg hregPPC_FPR3 ( void ) { return mkHReg( 3, HRcFlt64, False); }
hregPPC_FPR4(void)134 HReg hregPPC_FPR4 ( void ) { return mkHReg( 4, HRcFlt64, False); }
hregPPC_FPR5(void)135 HReg hregPPC_FPR5 ( void ) { return mkHReg( 5, HRcFlt64, False); }
hregPPC_FPR6(void)136 HReg hregPPC_FPR6 ( void ) { return mkHReg( 6, HRcFlt64, False); }
hregPPC_FPR7(void)137 HReg hregPPC_FPR7 ( void ) { return mkHReg( 7, HRcFlt64, False); }
hregPPC_FPR8(void)138 HReg hregPPC_FPR8 ( void ) { return mkHReg( 8, HRcFlt64, False); }
hregPPC_FPR9(void)139 HReg hregPPC_FPR9 ( void ) { return mkHReg( 9, HRcFlt64, False); }
hregPPC_FPR10(void)140 HReg hregPPC_FPR10 ( void ) { return mkHReg(10, HRcFlt64, False); }
hregPPC_FPR11(void)141 HReg hregPPC_FPR11 ( void ) { return mkHReg(11, HRcFlt64, False); }
hregPPC_FPR12(void)142 HReg hregPPC_FPR12 ( void ) { return mkHReg(12, HRcFlt64, False); }
hregPPC_FPR13(void)143 HReg hregPPC_FPR13 ( void ) { return mkHReg(13, HRcFlt64, False); }
hregPPC_FPR14(void)144 HReg hregPPC_FPR14 ( void ) { return mkHReg(14, HRcFlt64, False); }
hregPPC_FPR15(void)145 HReg hregPPC_FPR15 ( void ) { return mkHReg(15, HRcFlt64, False); }
hregPPC_FPR16(void)146 HReg hregPPC_FPR16 ( void ) { return mkHReg(16, HRcFlt64, False); }
hregPPC_FPR17(void)147 HReg hregPPC_FPR17 ( void ) { return mkHReg(17, HRcFlt64, False); }
hregPPC_FPR18(void)148 HReg hregPPC_FPR18 ( void ) { return mkHReg(18, HRcFlt64, False); }
hregPPC_FPR19(void)149 HReg hregPPC_FPR19 ( void ) { return mkHReg(19, HRcFlt64, False); }
hregPPC_FPR20(void)150 HReg hregPPC_FPR20 ( void ) { return mkHReg(20, HRcFlt64, False); }
hregPPC_FPR21(void)151 HReg hregPPC_FPR21 ( void ) { return mkHReg(21, HRcFlt64, False); }
hregPPC_FPR22(void)152 HReg hregPPC_FPR22 ( void ) { return mkHReg(22, HRcFlt64, False); }
hregPPC_FPR23(void)153 HReg hregPPC_FPR23 ( void ) { return mkHReg(23, HRcFlt64, False); }
hregPPC_FPR24(void)154 HReg hregPPC_FPR24 ( void ) { return mkHReg(24, HRcFlt64, False); }
hregPPC_FPR25(void)155 HReg hregPPC_FPR25 ( void ) { return mkHReg(25, HRcFlt64, False); }
hregPPC_FPR26(void)156 HReg hregPPC_FPR26 ( void ) { return mkHReg(26, HRcFlt64, False); }
hregPPC_FPR27(void)157 HReg hregPPC_FPR27 ( void ) { return mkHReg(27, HRcFlt64, False); }
hregPPC_FPR28(void)158 HReg hregPPC_FPR28 ( void ) { return mkHReg(28, HRcFlt64, False); }
hregPPC_FPR29(void)159 HReg hregPPC_FPR29 ( void ) { return mkHReg(29, HRcFlt64, False); }
hregPPC_FPR30(void)160 HReg hregPPC_FPR30 ( void ) { return mkHReg(30, HRcFlt64, False); }
hregPPC_FPR31(void)161 HReg hregPPC_FPR31 ( void ) { return mkHReg(31, HRcFlt64, False); }
162
hregPPC_VR0(void)163 HReg hregPPC_VR0 ( void ) { return mkHReg( 0, HRcVec128, False); }
hregPPC_VR1(void)164 HReg hregPPC_VR1 ( void ) { return mkHReg( 1, HRcVec128, False); }
hregPPC_VR2(void)165 HReg hregPPC_VR2 ( void ) { return mkHReg( 2, HRcVec128, False); }
hregPPC_VR3(void)166 HReg hregPPC_VR3 ( void ) { return mkHReg( 3, HRcVec128, False); }
hregPPC_VR4(void)167 HReg hregPPC_VR4 ( void ) { return mkHReg( 4, HRcVec128, False); }
hregPPC_VR5(void)168 HReg hregPPC_VR5 ( void ) { return mkHReg( 5, HRcVec128, False); }
hregPPC_VR6(void)169 HReg hregPPC_VR6 ( void ) { return mkHReg( 6, HRcVec128, False); }
hregPPC_VR7(void)170 HReg hregPPC_VR7 ( void ) { return mkHReg( 7, HRcVec128, False); }
hregPPC_VR8(void)171 HReg hregPPC_VR8 ( void ) { return mkHReg( 8, HRcVec128, False); }
hregPPC_VR9(void)172 HReg hregPPC_VR9 ( void ) { return mkHReg( 9, HRcVec128, False); }
hregPPC_VR10(void)173 HReg hregPPC_VR10 ( void ) { return mkHReg(10, HRcVec128, False); }
hregPPC_VR11(void)174 HReg hregPPC_VR11 ( void ) { return mkHReg(11, HRcVec128, False); }
hregPPC_VR12(void)175 HReg hregPPC_VR12 ( void ) { return mkHReg(12, HRcVec128, False); }
hregPPC_VR13(void)176 HReg hregPPC_VR13 ( void ) { return mkHReg(13, HRcVec128, False); }
hregPPC_VR14(void)177 HReg hregPPC_VR14 ( void ) { return mkHReg(14, HRcVec128, False); }
hregPPC_VR15(void)178 HReg hregPPC_VR15 ( void ) { return mkHReg(15, HRcVec128, False); }
hregPPC_VR16(void)179 HReg hregPPC_VR16 ( void ) { return mkHReg(16, HRcVec128, False); }
hregPPC_VR17(void)180 HReg hregPPC_VR17 ( void ) { return mkHReg(17, HRcVec128, False); }
hregPPC_VR18(void)181 HReg hregPPC_VR18 ( void ) { return mkHReg(18, HRcVec128, False); }
hregPPC_VR19(void)182 HReg hregPPC_VR19 ( void ) { return mkHReg(19, HRcVec128, False); }
hregPPC_VR20(void)183 HReg hregPPC_VR20 ( void ) { return mkHReg(20, HRcVec128, False); }
hregPPC_VR21(void)184 HReg hregPPC_VR21 ( void ) { return mkHReg(21, HRcVec128, False); }
hregPPC_VR22(void)185 HReg hregPPC_VR22 ( void ) { return mkHReg(22, HRcVec128, False); }
hregPPC_VR23(void)186 HReg hregPPC_VR23 ( void ) { return mkHReg(23, HRcVec128, False); }
hregPPC_VR24(void)187 HReg hregPPC_VR24 ( void ) { return mkHReg(24, HRcVec128, False); }
hregPPC_VR25(void)188 HReg hregPPC_VR25 ( void ) { return mkHReg(25, HRcVec128, False); }
hregPPC_VR26(void)189 HReg hregPPC_VR26 ( void ) { return mkHReg(26, HRcVec128, False); }
hregPPC_VR27(void)190 HReg hregPPC_VR27 ( void ) { return mkHReg(27, HRcVec128, False); }
hregPPC_VR28(void)191 HReg hregPPC_VR28 ( void ) { return mkHReg(28, HRcVec128, False); }
hregPPC_VR29(void)192 HReg hregPPC_VR29 ( void ) { return mkHReg(29, HRcVec128, False); }
hregPPC_VR30(void)193 HReg hregPPC_VR30 ( void ) { return mkHReg(30, HRcVec128, False); }
hregPPC_VR31(void)194 HReg hregPPC_VR31 ( void ) { return mkHReg(31, HRcVec128, False); }
195
getAllocableRegs_PPC(Int * nregs,HReg ** arr,Bool mode64)196 void getAllocableRegs_PPC ( Int* nregs, HReg** arr, Bool mode64 )
197 {
198 UInt i=0;
199 if (mode64)
200 *nregs = (32-9) + (32-24) + (32-24);
201 else
202 *nregs = (32-7) + (32-24) + (32-24);
203 *arr = LibVEX_Alloc(*nregs * sizeof(HReg));
204 // GPR0 = scratch reg where poss. - some ops interpret as value zero
205 // GPR1 = stack pointer
206 // GPR2 = TOC pointer
207 (*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 }
222 // GPR13 = thread specific pointer
223 // GPR14 and above are callee save. Yay.
224 (*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);
239 // GPR29 is reserved for the dispatcher
240 // GPR30 is reserved as AltiVec spill reg temporary
241 // GPR31 is reserved for the GuestStatePtr
242
243 /* 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. */
246 /* 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();
256
257 /* Same deal re Altivec */
258 /* For both ppc32-linux and ppc64-linux, v20-v31 are callee save.
259 So use them. */
260 /* NB, vr29 is used as a scratch temporary -- do not allocate */
261 (*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();
269
270 vassert(i == *nregs);
271 }
272
273
274 /* --------- Condition codes, Intel encoding. --------- */
275
showPPCCondCode(PPCCondCode cond)276 const HChar* showPPCCondCode ( PPCCondCode cond )
277 {
278 if (cond.test == Pct_ALWAYS) return "always";
279
280 switch (cond.flag) {
281 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";
289 case Pcf_NONE:
290 return "no-flag";
291 default: vpanic("ppPPCCondCode");
292 }
293 }
294
295 /* construct condition code */
mk_PPCCondCode(PPCCondTest test,PPCCondFlag flag)296 PPCCondCode mk_PPCCondCode ( PPCCondTest test, PPCCondFlag flag )
297 {
298 PPCCondCode cc;
299 cc.flag = flag;
300 cc.test = test;
301 if (test == Pct_ALWAYS) {
302 vassert(flag == Pcf_NONE);
303 } else {
304 vassert(flag != Pcf_NONE);
305 }
306 return cc;
307 }
308
309 /* false->true, true->false */
invertCondTest(PPCCondTest ct)310 PPCCondTest invertCondTest ( PPCCondTest ct )
311 {
312 vassert(ct != Pct_ALWAYS);
313 return (ct == Pct_TRUE) ? Pct_FALSE : Pct_TRUE;
314 }
315
316
317 /* --------- PPCAMode: memory address expressions. --------- */
318
PPCAMode_IR(Int idx,HReg base)319 PPCAMode* PPCAMode_IR ( Int idx, HReg base ) {
320 PPCAMode* am = LibVEX_Alloc(sizeof(PPCAMode));
321 vassert(idx >= -0x8000 && idx < 0x8000);
322 am->tag = Pam_IR;
323 am->Pam.IR.base = base;
324 am->Pam.IR.index = idx;
325 return am;
326 }
PPCAMode_RR(HReg idx,HReg base)327 PPCAMode* PPCAMode_RR ( HReg idx, HReg base ) {
328 PPCAMode* am = LibVEX_Alloc(sizeof(PPCAMode));
329 am->tag = Pam_RR;
330 am->Pam.RR.base = base;
331 am->Pam.RR.index = idx;
332 return am;
333 }
334
dopyPPCAMode(PPCAMode * am)335 PPCAMode* dopyPPCAMode ( PPCAMode* am ) {
336 switch (am->tag) {
337 case Pam_IR:
338 return PPCAMode_IR( am->Pam.IR.index, am->Pam.IR.base );
339 case Pam_RR:
340 return PPCAMode_RR( am->Pam.RR.index, am->Pam.RR.base );
341 default:
342 vpanic("dopyPPCAMode");
343 }
344 }
345
ppPPCAMode(PPCAMode * am)346 void ppPPCAMode ( PPCAMode* am ) {
347 switch (am->tag) {
348 case Pam_IR:
349 if (am->Pam.IR.index == 0)
350 vex_printf("0(");
351 else
352 vex_printf("%d(", (Int)am->Pam.IR.index);
353 ppHRegPPC(am->Pam.IR.base);
354 vex_printf(")");
355 return;
356 case Pam_RR:
357 ppHRegPPC(am->Pam.RR.base);
358 vex_printf(",");
359 ppHRegPPC(am->Pam.RR.index);
360 return;
361 default:
362 vpanic("ppPPCAMode");
363 }
364 }
365
addRegUsage_PPCAMode(HRegUsage * u,PPCAMode * am)366 static void addRegUsage_PPCAMode ( HRegUsage* u, PPCAMode* am ) {
367 switch (am->tag) {
368 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:
376 vpanic("addRegUsage_PPCAMode");
377 }
378 }
379
mapRegs_PPCAMode(HRegRemap * m,PPCAMode * am)380 static void mapRegs_PPCAMode ( HRegRemap* m, PPCAMode* am ) {
381 switch (am->tag) {
382 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:
390 vpanic("mapRegs_PPCAMode");
391 }
392 }
393
394 /* --------- Operand, which can be a reg or a u16/s16. --------- */
395
PPCRH_Imm(Bool syned,UShort imm16)396 PPCRH* PPCRH_Imm ( Bool syned, UShort imm16 ) {
397 PPCRH* op = LibVEX_Alloc(sizeof(PPCRH));
398 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 }
PPCRH_Reg(HReg reg)408 PPCRH* PPCRH_Reg ( HReg reg ) {
409 PPCRH* op = LibVEX_Alloc(sizeof(PPCRH));
410 op->tag = Prh_Reg;
411 op->Prh.Reg.reg = reg;
412 return op;
413 }
414
ppPPCRH(PPCRH * op)415 void ppPPCRH ( PPCRH* op ) {
416 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
421 vex_printf("%u", (UInt)(UShort)op->Prh.Imm.imm16);
422 return;
423 case Prh_Reg:
424 ppHRegPPC(op->Prh.Reg.reg);
425 return;
426 default:
427 vpanic("ppPPCRH");
428 }
429 }
430
431 /* An PPCRH can only be used in a "read" context (what would it mean
432 to write or modify a literal?) and so we enumerate its registers
433 accordingly. */
addRegUsage_PPCRH(HRegUsage * u,PPCRH * op)434 static void addRegUsage_PPCRH ( HRegUsage* u, PPCRH* op ) {
435 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:
442 vpanic("addRegUsage_PPCRH");
443 }
444 }
445
mapRegs_PPCRH(HRegRemap * m,PPCRH * op)446 static void mapRegs_PPCRH ( HRegRemap* m, PPCRH* op ) {
447 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:
454 vpanic("mapRegs_PPCRH");
455 }
456 }
457
458
459 /* --------- Operand, which can be a reg or a u32/64. --------- */
460
PPCRI_Imm(ULong imm64)461 PPCRI* PPCRI_Imm ( ULong imm64 ) {
462 PPCRI* op = LibVEX_Alloc(sizeof(PPCRI));
463 op->tag = Pri_Imm;
464 op->Pri.Imm = imm64;
465 return op;
466 }
PPCRI_Reg(HReg reg)467 PPCRI* PPCRI_Reg ( HReg reg ) {
468 PPCRI* op = LibVEX_Alloc(sizeof(PPCRI));
469 op->tag = Pri_Reg;
470 op->Pri.Reg = reg;
471 return op;
472 }
473
ppPPCRI(PPCRI * dst)474 void ppPPCRI ( PPCRI* dst ) {
475 switch (dst->tag) {
476 case Pri_Imm:
477 vex_printf("0x%llx", dst->Pri.Imm);
478 break;
479 case Pri_Reg:
480 ppHRegPPC(dst->Pri.Reg);
481 break;
482 default:
483 vpanic("ppPPCRI");
484 }
485 }
486
487 /* An PPCRI can only be used in a "read" context (what would it
488 mean to write or modify a literal?) and so we enumerate its
489 registers accordingly. */
addRegUsage_PPCRI(HRegUsage * u,PPCRI * dst)490 static void addRegUsage_PPCRI ( HRegUsage* u, PPCRI* dst ) {
491 switch (dst->tag) {
492 case Pri_Imm:
493 return;
494 case Pri_Reg:
495 addHRegUse(u, HRmRead, dst->Pri.Reg);
496 return;
497 default:
498 vpanic("addRegUsage_PPCRI");
499 }
500 }
501
mapRegs_PPCRI(HRegRemap * m,PPCRI * dst)502 static void mapRegs_PPCRI ( HRegRemap* m, PPCRI* dst ) {
503 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:
510 vpanic("mapRegs_PPCRI");
511 }
512 }
513
514
515 /* --------- Operand, which can be a vector reg or a simm5. --------- */
516
PPCVI5s_Imm(Char simm5)517 PPCVI5s* PPCVI5s_Imm ( Char simm5 ) {
518 PPCVI5s* op = LibVEX_Alloc(sizeof(PPCVI5s));
519 op->tag = Pvi_Imm;
520 op->Pvi.Imm5s = simm5;
521 vassert(simm5 >= -16 && simm5 <= 15);
522 return op;
523 }
PPCVI5s_Reg(HReg reg)524 PPCVI5s* PPCVI5s_Reg ( HReg reg ) {
525 PPCVI5s* op = LibVEX_Alloc(sizeof(PPCVI5s));
526 op->tag = Pvi_Reg;
527 op->Pvi.Reg = reg;
528 vassert(hregClass(reg) == HRcVec128);
529 return op;
530 }
531
ppPPCVI5s(PPCVI5s * src)532 void ppPPCVI5s ( PPCVI5s* src ) {
533 switch (src->tag) {
534 case Pvi_Imm:
535 vex_printf("%d", (Int)src->Pvi.Imm5s);
536 break;
537 case Pvi_Reg:
538 ppHRegPPC(src->Pvi.Reg);
539 break;
540 default:
541 vpanic("ppPPCVI5s");
542 }
543 }
544
545 /* An PPCVI5s can only be used in a "read" context (what would it
546 mean to write or modify a literal?) and so we enumerate its
547 registers accordingly. */
addRegUsage_PPCVI5s(HRegUsage * u,PPCVI5s * dst)548 static void addRegUsage_PPCVI5s ( HRegUsage* u, PPCVI5s* dst ) {
549 switch (dst->tag) {
550 case Pvi_Imm:
551 return;
552 case Pvi_Reg:
553 addHRegUse(u, HRmRead, dst->Pvi.Reg);
554 return;
555 default:
556 vpanic("addRegUsage_PPCVI5s");
557 }
558 }
559
mapRegs_PPCVI5s(HRegRemap * m,PPCVI5s * dst)560 static void mapRegs_PPCVI5s ( HRegRemap* m, PPCVI5s* dst ) {
561 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:
568 vpanic("mapRegs_PPCVI5s");
569 }
570 }
571
572
573 /* --------- Instructions. --------- */
574
showPPCUnaryOp(PPCUnaryOp op)575 const HChar* showPPCUnaryOp ( PPCUnaryOp op ) {
576 switch (op) {
577 case Pun_NOT: return "not";
578 case Pun_NEG: return "neg";
579 case Pun_CLZ32: return "cntlzw";
580 case Pun_CLZ64: return "cntlzd";
581 case Pun_EXTSW: return "extsw";
582 default: vpanic("showPPCUnaryOp");
583 }
584 }
585
showPPCAluOp(PPCAluOp op,Bool immR)586 const HChar* showPPCAluOp ( PPCAluOp op, Bool immR ) {
587 switch (op) {
588 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";
593 default: vpanic("showPPCAluOp");
594 }
595 }
596
showPPCShftOp(PPCShftOp op,Bool immR,Bool sz32)597 const HChar* showPPCShftOp ( PPCShftOp op, Bool immR, Bool sz32 ) {
598 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");
605 default: vpanic("showPPCShftOp");
606 }
607 }
608
showPPCFpOp(PPCFpOp op)609 const HChar* showPPCFpOp ( PPCFpOp op ) {
610 switch (op) {
611 case Pfp_ADDD: return "fadd";
612 case Pfp_SUBD: return "fsub";
613 case Pfp_MULD: return "fmul";
614 case Pfp_DIVD: return "fdiv";
615 case Pfp_MADDD: return "fmadd";
616 case Pfp_MSUBD: return "fmsub";
617 case Pfp_MADDS: return "fmadds";
618 case Pfp_MSUBS: return "fmsubs";
619 case Pfp_ADDS: return "fadds";
620 case Pfp_SUBS: return "fsubs";
621 case Pfp_MULS: return "fmuls";
622 case Pfp_DIVS: return "fdivs";
623 case Pfp_SQRT: return "fsqrt";
624 case Pfp_ABS: return "fabs";
625 case Pfp_NEG: return "fneg";
626 case Pfp_MOV: return "fmr";
627 case Pfp_RES: return "fres";
628 case Pfp_RSQRTE: return "frsqrte";
629 case Pfp_FRIM: return "frim";
630 case Pfp_FRIN: return "frin";
631 case Pfp_FRIP: return "frip";
632 case Pfp_FRIZ: return "friz";
633 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";
641 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";
647 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";
654 default: vpanic("showPPCFpOp");
655 }
656 }
657
showPPCAvOp(PPCAvOp op)658 const HChar* showPPCAvOp ( PPCAvOp op ) {
659 switch (op) {
660
661 /* Unary */
662 case Pav_MOV: return "vmr"; /* Mov */
663
664 case Pav_AND: return "vand"; /* Bitwise */
665 case Pav_OR: return "vor";
666 case Pav_XOR: return "vxor";
667 case Pav_NOT: return "vnot";
668
669 case Pav_UNPCKH8S: return "vupkhsb"; /* Unpack */
670 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";
675
676 /* Integer binary */
677 case Pav_ADDU: return "vaddu_m"; // b,h,w,dw
678 case Pav_QADDU: return "vaddu_s"; // b,h,w,dw
679 case Pav_QADDS: return "vadds_s"; // b,h,w,dw
680
681 case Pav_SUBU: return "vsubu_m"; // b,h,w,dw
682 case Pav_QSUBU: return "vsubu_s"; // b,h,w,dw
683 case Pav_QSUBS: return "vsubs_s"; // b,h,w,dw
684
685 case Pav_MULU: return "vmulu"; // w
686 case Pav_OMULU: return "vmulou"; // b,h,w
687 case Pav_OMULS: return "vmulos"; // b,h,w
688 case Pav_EMULU: return "vmuleu"; // b,h,w
689 case Pav_EMULS: return "vmules"; // b,h,w
690
691 case Pav_AVGU: return "vavgu"; // b,h,w
692 case Pav_AVGS: return "vavgs"; // b,h,w
693
694 case Pav_MAXU: return "vmaxu"; // b,h,w
695 case Pav_MAXS: return "vmaxs"; // b,h,w
696
697 case Pav_MINU: return "vminu"; // b,h,w
698 case Pav_MINS: return "vmins"; // b,h,w
699
700 /* Compare (always affects CR field 6) */
701 case Pav_CMPEQU: return "vcmpequ"; // b,h,w
702 case Pav_CMPGTU: return "vcmpgtu"; // b,h,w
703 case Pav_CMPGTS: return "vcmpgts"; // b,h,w
704
705 /* Shift */
706 case Pav_SHL: return "vsl"; // ' ',b,h,w,dw
707 case Pav_SHR: return "vsr"; // ' ',b,h,w,dw
708 case Pav_SAR: return "vsra"; // b,h,w,dw
709 case Pav_ROTL: return "vrl"; // b,h,w,dw
710
711 /* Pack */
712 case Pav_PACKUU: return "vpku_um"; // h,w,dw
713 case Pav_QPACKUU: return "vpku_us"; // h,w
714 case Pav_QPACKSU: return "vpks_us"; // h,w
715 case Pav_QPACKSS: return "vpks_ss"; // h,w
716 case Pav_PACKPXL: return "vpkpx";
717
718 /* Merge */
719 case Pav_MRGHI: return "vmrgh"; // b,h,w
720 case Pav_MRGLO: return "vmrgl"; // b,h,w
721
722 /* Concatenation */
723 case Pav_CATODD: return "vmrgow"; // w
724 case Pav_CATEVEN: return "vmrgew"; // w
725
726 /* SHA */
727 case Pav_SHA256: return "vshasigmaw"; // w
728 case Pav_SHA512: return "vshasigmaw"; // dw
729
730 /* BCD */
731 case Pav_BCDAdd: return "bcdadd."; // qw
732 case Pav_BCDSub: return "bcdsub."; // qw
733
734 /* Polynomial arith */
735 case Pav_POLYMULADD: return "vpmsum"; // b, h, w, d
736
737 /* Cipher */
738 case Pav_CIPHERV128: case Pav_CIPHERLV128:
739 case Pav_NCIPHERV128: case Pav_NCIPHERLV128:
740 case Pav_CIPHERSUBV128: return "v_cipher_"; // qw
741
742 /* zero count */
743 case Pav_ZEROCNTBYTE: case Pav_ZEROCNTWORD:
744 case Pav_ZEROCNTHALF: case Pav_ZEROCNTDBL:
745 return "vclz_"; // b, h, w, d
746
747 /* vector gather (byte-by-byte bit matrix transpose) */
748 case Pav_BITMTXXPOSE:
749 return "vgbbd";
750
751 default: vpanic("showPPCAvOp");
752 }
753 }
754
showPPCAvFpOp(PPCAvFpOp op)755 const HChar* showPPCAvFpOp ( PPCAvFpOp op ) {
756 switch (op) {
757 /* Floating Point Binary */
758 case Pavfp_ADDF: return "vaddfp";
759 case Pavfp_SUBF: return "vsubfp";
760 case Pavfp_MULF: return "vmaddfp";
761 case Pavfp_MAXF: return "vmaxfp";
762 case Pavfp_MINF: return "vminfp";
763 case Pavfp_CMPEQF: return "vcmpeqfp";
764 case Pavfp_CMPGTF: return "vcmpgtfp";
765 case Pavfp_CMPGEF: return "vcmpgefp";
766
767 /* Floating Point Unary */
768 case Pavfp_RCPF: return "vrefp";
769 case Pavfp_RSQRTF: return "vrsqrtefp";
770 case Pavfp_CVTU2F: return "vcfux";
771 case Pavfp_CVTS2F: return "vcfsx";
772 case Pavfp_QCVTF2U: return "vctuxs";
773 case Pavfp_QCVTF2S: return "vctsxs";
774 case Pavfp_ROUNDM: return "vrfim";
775 case Pavfp_ROUNDP: return "vrfip";
776 case Pavfp_ROUNDN: return "vrfin";
777 case Pavfp_ROUNDZ: return "vrfiz";
778
779 default: vpanic("showPPCAvFpOp");
780 }
781 }
782
PPCInstr_LI(HReg dst,ULong imm64,Bool mode64)783 PPCInstr* PPCInstr_LI ( HReg dst, ULong imm64, Bool mode64 )
784 {
785 PPCInstr* i = LibVEX_Alloc(sizeof(PPCInstr));
786 i->tag = Pin_LI;
787 i->Pin.LI.dst = dst;
788 i->Pin.LI.imm64 = imm64;
789 if (!mode64)
790 vassert( (Long)imm64 == (Long)(Int)(UInt)imm64 );
791 return i;
792 }
PPCInstr_Alu(PPCAluOp op,HReg dst,HReg srcL,PPCRH * srcR)793 PPCInstr* PPCInstr_Alu ( PPCAluOp op, HReg dst,
794 HReg srcL, PPCRH* srcR ) {
795 PPCInstr* i = LibVEX_Alloc(sizeof(PPCInstr));
796 i->tag = Pin_Alu;
797 i->Pin.Alu.op = op;
798 i->Pin.Alu.dst = dst;
799 i->Pin.Alu.srcL = srcL;
800 i->Pin.Alu.srcR = srcR;
801 return i;
802 }
PPCInstr_Shft(PPCShftOp op,Bool sz32,HReg dst,HReg srcL,PPCRH * srcR)803 PPCInstr* PPCInstr_Shft ( PPCShftOp op, Bool sz32,
804 HReg dst, HReg srcL, PPCRH* srcR ) {
805 PPCInstr* i = LibVEX_Alloc(sizeof(PPCInstr));
806 i->tag = Pin_Shft;
807 i->Pin.Shft.op = op;
808 i->Pin.Shft.sz32 = sz32;
809 i->Pin.Shft.dst = dst;
810 i->Pin.Shft.srcL = srcL;
811 i->Pin.Shft.srcR = srcR;
812 return i;
813 }
PPCInstr_AddSubC(Bool isAdd,Bool setC,HReg dst,HReg srcL,HReg srcR)814 PPCInstr* PPCInstr_AddSubC ( Bool isAdd, Bool setC,
815 HReg dst, HReg srcL, HReg srcR ) {
816 PPCInstr* i = LibVEX_Alloc(sizeof(PPCInstr));
817 i->tag = Pin_AddSubC;
818 i->Pin.AddSubC.isAdd = isAdd;
819 i->Pin.AddSubC.setC = setC;
820 i->Pin.AddSubC.dst = dst;
821 i->Pin.AddSubC.srcL = srcL;
822 i->Pin.AddSubC.srcR = srcR;
823 return i;
824 }
PPCInstr_Cmp(Bool syned,Bool sz32,UInt crfD,HReg srcL,PPCRH * srcR)825 PPCInstr* PPCInstr_Cmp ( Bool syned, Bool sz32,
826 UInt crfD, HReg srcL, PPCRH* srcR ) {
827 PPCInstr* i = LibVEX_Alloc(sizeof(PPCInstr));
828 i->tag = Pin_Cmp;
829 i->Pin.Cmp.syned = syned;
830 i->Pin.Cmp.sz32 = sz32;
831 i->Pin.Cmp.crfD = crfD;
832 i->Pin.Cmp.srcL = srcL;
833 i->Pin.Cmp.srcR = srcR;
834 return i;
835 }
PPCInstr_Unary(PPCUnaryOp op,HReg dst,HReg src)836 PPCInstr* PPCInstr_Unary ( PPCUnaryOp op, HReg dst, HReg src ) {
837 PPCInstr* i = LibVEX_Alloc(sizeof(PPCInstr));
838 i->tag = Pin_Unary;
839 i->Pin.Unary.op = op;
840 i->Pin.Unary.dst = dst;
841 i->Pin.Unary.src = src;
842 return i;
843 }
PPCInstr_MulL(Bool syned,Bool hi,Bool sz32,HReg dst,HReg srcL,HReg srcR)844 PPCInstr* PPCInstr_MulL ( Bool syned, Bool hi, Bool sz32,
845 HReg dst, HReg srcL, HReg srcR ) {
846 PPCInstr* i = LibVEX_Alloc(sizeof(PPCInstr));
847 i->tag = Pin_MulL;
848 i->Pin.MulL.syned = syned;
849 i->Pin.MulL.hi = hi;
850 i->Pin.MulL.sz32 = sz32;
851 i->Pin.MulL.dst = dst;
852 i->Pin.MulL.srcL = srcL;
853 i->Pin.MulL.srcR = srcR;
854 /* if doing the low word, the signedness is irrelevant, but tie it
855 down anyway. */
856 if (!hi) vassert(!syned);
857 return i;
858 }
PPCInstr_Div(Bool extended,Bool syned,Bool sz32,HReg dst,HReg srcL,HReg srcR)859 PPCInstr* PPCInstr_Div ( Bool extended, Bool syned, Bool sz32,
860 HReg dst, HReg srcL, HReg srcR ) {
861 PPCInstr* i = LibVEX_Alloc(sizeof(PPCInstr));
862 i->tag = Pin_Div;
863 i->Pin.Div.extended = extended;
864 i->Pin.Div.syned = syned;
865 i->Pin.Div.sz32 = sz32;
866 i->Pin.Div.dst = dst;
867 i->Pin.Div.srcL = srcL;
868 i->Pin.Div.srcR = srcR;
869 return i;
870 }
PPCInstr_Call(PPCCondCode cond,Addr64 target,UInt argiregs,RetLoc rloc)871 PPCInstr* PPCInstr_Call ( PPCCondCode cond,
872 Addr64 target, UInt argiregs, RetLoc rloc ) {
873 UInt mask;
874 PPCInstr* i = LibVEX_Alloc(sizeof(PPCInstr));
875 i->tag = Pin_Call;
876 i->Pin.Call.cond = cond;
877 i->Pin.Call.target = target;
878 i->Pin.Call.argiregs = argiregs;
879 i->Pin.Call.rloc = rloc;
880 /* Only r3 .. r10 inclusive may be used as arg regs. Hence: */
881 mask = (1<<3)|(1<<4)|(1<<5)|(1<<6)|(1<<7)|(1<<8)|(1<<9)|(1<<10);
882 vassert(0 == (argiregs & ~mask));
883 vassert(is_sane_RetLoc(rloc));
884 return i;
885 }
PPCInstr_XDirect(Addr64 dstGA,PPCAMode * amCIA,PPCCondCode cond,Bool toFastEP)886 PPCInstr* PPCInstr_XDirect ( Addr64 dstGA, PPCAMode* amCIA,
887 PPCCondCode cond, Bool toFastEP ) {
888 PPCInstr* i = LibVEX_Alloc(sizeof(PPCInstr));
889 i->tag = Pin_XDirect;
890 i->Pin.XDirect.dstGA = dstGA;
891 i->Pin.XDirect.amCIA = amCIA;
892 i->Pin.XDirect.cond = cond;
893 i->Pin.XDirect.toFastEP = toFastEP;
894 return i;
895 }
PPCInstr_XIndir(HReg dstGA,PPCAMode * amCIA,PPCCondCode cond)896 PPCInstr* PPCInstr_XIndir ( HReg dstGA, PPCAMode* amCIA,
897 PPCCondCode cond ) {
898 PPCInstr* i = LibVEX_Alloc(sizeof(PPCInstr));
899 i->tag = Pin_XIndir;
900 i->Pin.XIndir.dstGA = dstGA;
901 i->Pin.XIndir.amCIA = amCIA;
902 i->Pin.XIndir.cond = cond;
903 return i;
904 }
PPCInstr_XAssisted(HReg dstGA,PPCAMode * amCIA,PPCCondCode cond,IRJumpKind jk)905 PPCInstr* PPCInstr_XAssisted ( HReg dstGA, PPCAMode* amCIA,
906 PPCCondCode cond, IRJumpKind jk ) {
907 PPCInstr* i = LibVEX_Alloc(sizeof(PPCInstr));
908 i->tag = Pin_XAssisted;
909 i->Pin.XAssisted.dstGA = dstGA;
910 i->Pin.XAssisted.amCIA = amCIA;
911 i->Pin.XAssisted.cond = cond;
912 i->Pin.XAssisted.jk = jk;
913 return i;
914 }
PPCInstr_CMov(PPCCondCode cond,HReg dst,PPCRI * src)915 PPCInstr* PPCInstr_CMov ( PPCCondCode cond,
916 HReg dst, PPCRI* src ) {
917 PPCInstr* i = LibVEX_Alloc(sizeof(PPCInstr));
918 i->tag = Pin_CMov;
919 i->Pin.CMov.cond = cond;
920 i->Pin.CMov.src = src;
921 i->Pin.CMov.dst = dst;
922 vassert(cond.test != Pct_ALWAYS);
923 return i;
924 }
PPCInstr_Load(UChar sz,HReg dst,PPCAMode * src,Bool mode64)925 PPCInstr* PPCInstr_Load ( UChar sz,
926 HReg dst, PPCAMode* src, Bool mode64 ) {
927 PPCInstr* i = LibVEX_Alloc(sizeof(PPCInstr));
928 i->tag = Pin_Load;
929 i->Pin.Load.sz = sz;
930 i->Pin.Load.src = src;
931 i->Pin.Load.dst = dst;
932 vassert(sz == 1 || sz == 2 || sz == 4 || sz == 8);
933 if (sz == 8) vassert(mode64);
934 return i;
935 }
PPCInstr_LoadL(UChar sz,HReg dst,HReg src,Bool mode64)936 PPCInstr* PPCInstr_LoadL ( UChar sz,
937 HReg dst, HReg src, Bool mode64 )
938 {
939 PPCInstr* i = LibVEX_Alloc(sizeof(PPCInstr));
940 i->tag = Pin_LoadL;
941 i->Pin.LoadL.sz = sz;
942 i->Pin.LoadL.src = src;
943 i->Pin.LoadL.dst = dst;
944 vassert(sz == 4 || sz == 8);
945 if (sz == 8) vassert(mode64);
946 return i;
947 }
PPCInstr_Store(UChar sz,PPCAMode * dst,HReg src,Bool mode64)948 PPCInstr* PPCInstr_Store ( UChar sz, PPCAMode* dst, HReg src,
949 Bool mode64 ) {
950 PPCInstr* i = LibVEX_Alloc(sizeof(PPCInstr));
951 i->tag = Pin_Store;
952 i->Pin.Store.sz = sz;
953 i->Pin.Store.src = src;
954 i->Pin.Store.dst = dst;
955 vassert(sz == 1 || sz == 2 || sz == 4 || sz == 8);
956 if (sz == 8) vassert(mode64);
957 return i;
958 }
PPCInstr_StoreC(UChar sz,HReg dst,HReg src,Bool mode64)959 PPCInstr* PPCInstr_StoreC ( UChar sz, HReg dst, HReg src, Bool mode64 ) {
960 PPCInstr* i = LibVEX_Alloc(sizeof(PPCInstr));
961 i->tag = Pin_StoreC;
962 i->Pin.StoreC.sz = sz;
963 i->Pin.StoreC.src = src;
964 i->Pin.StoreC.dst = dst;
965 vassert(sz == 4 || sz == 8);
966 if (sz == 8) vassert(mode64);
967 return i;
968 }
PPCInstr_Set(PPCCondCode cond,HReg dst)969 PPCInstr* PPCInstr_Set ( PPCCondCode cond, HReg dst ) {
970 PPCInstr* i = LibVEX_Alloc(sizeof(PPCInstr));
971 i->tag = Pin_Set;
972 i->Pin.Set.cond = cond;
973 i->Pin.Set.dst = dst;
974 return i;
975 }
PPCInstr_MfCR(HReg dst)976 PPCInstr* PPCInstr_MfCR ( HReg dst )
977 {
978 PPCInstr* i = LibVEX_Alloc(sizeof(PPCInstr));
979 i->tag = Pin_MfCR;
980 i->Pin.MfCR.dst = dst;
981 return i;
982 }
PPCInstr_MFence(void)983 PPCInstr* PPCInstr_MFence ( void )
984 {
985 PPCInstr* i = LibVEX_Alloc(sizeof(PPCInstr));
986 i->tag = Pin_MFence;
987 return i;
988 }
989
PPCInstr_FpUnary(PPCFpOp op,HReg dst,HReg src)990 PPCInstr* PPCInstr_FpUnary ( PPCFpOp op, HReg dst, HReg src ) {
991 PPCInstr* i = LibVEX_Alloc(sizeof(PPCInstr));
992 i->tag = Pin_FpUnary;
993 i->Pin.FpUnary.op = op;
994 i->Pin.FpUnary.dst = dst;
995 i->Pin.FpUnary.src = src;
996 return i;
997 }
PPCInstr_FpBinary(PPCFpOp op,HReg dst,HReg srcL,HReg srcR)998 PPCInstr* PPCInstr_FpBinary ( PPCFpOp op, HReg dst,
999 HReg srcL, HReg srcR ) {
1000 PPCInstr* i = LibVEX_Alloc(sizeof(PPCInstr));
1001 i->tag = Pin_FpBinary;
1002 i->Pin.FpBinary.op = op;
1003 i->Pin.FpBinary.dst = dst;
1004 i->Pin.FpBinary.srcL = srcL;
1005 i->Pin.FpBinary.srcR = srcR;
1006 return i;
1007 }
PPCInstr_FpMulAcc(PPCFpOp op,HReg dst,HReg srcML,HReg srcMR,HReg srcAcc)1008 PPCInstr* PPCInstr_FpMulAcc ( PPCFpOp op, HReg dst, HReg srcML,
1009 HReg srcMR, HReg srcAcc )
1010 {
1011 PPCInstr* i = LibVEX_Alloc(sizeof(PPCInstr));
1012 i->tag = Pin_FpMulAcc;
1013 i->Pin.FpMulAcc.op = op;
1014 i->Pin.FpMulAcc.dst = dst;
1015 i->Pin.FpMulAcc.srcML = srcML;
1016 i->Pin.FpMulAcc.srcMR = srcMR;
1017 i->Pin.FpMulAcc.srcAcc = srcAcc;
1018 return i;
1019 }
PPCInstr_FpLdSt(Bool isLoad,UChar sz,HReg reg,PPCAMode * addr)1020 PPCInstr* PPCInstr_FpLdSt ( Bool isLoad, UChar sz,
1021 HReg reg, PPCAMode* addr ) {
1022 PPCInstr* i = LibVEX_Alloc(sizeof(PPCInstr));
1023 i->tag = Pin_FpLdSt;
1024 i->Pin.FpLdSt.isLoad = isLoad;
1025 i->Pin.FpLdSt.sz = sz;
1026 i->Pin.FpLdSt.reg = reg;
1027 i->Pin.FpLdSt.addr = addr;
1028 vassert(sz == 4 || sz == 8);
1029 return i;
1030 }
PPCInstr_FpSTFIW(HReg addr,HReg data)1031 PPCInstr* PPCInstr_FpSTFIW ( HReg addr, HReg data )
1032 {
1033 PPCInstr* i = LibVEX_Alloc(sizeof(PPCInstr));
1034 i->tag = Pin_FpSTFIW;
1035 i->Pin.FpSTFIW.addr = addr;
1036 i->Pin.FpSTFIW.data = data;
1037 return i;
1038 }
PPCInstr_FpRSP(HReg dst,HReg src)1039 PPCInstr* PPCInstr_FpRSP ( HReg dst, HReg src ) {
1040 PPCInstr* i = LibVEX_Alloc(sizeof(PPCInstr));
1041 i->tag = Pin_FpRSP;
1042 i->Pin.FpRSP.dst = dst;
1043 i->Pin.FpRSP.src = src;
1044 return i;
1045 }
PPCInstr_Dfp64Unary(PPCFpOp op,HReg dst,HReg src)1046 PPCInstr* PPCInstr_Dfp64Unary(PPCFpOp op, HReg dst, HReg src) {
1047 PPCInstr* i = LibVEX_Alloc( sizeof(PPCInstr) );
1048 i->tag = Pin_Dfp64Unary;
1049 i->Pin.Dfp64Unary.op = op;
1050 i->Pin.Dfp64Unary.dst = dst;
1051 i->Pin.Dfp64Unary.src = src;
1052 return i;
1053 }
PPCInstr_Dfp64Binary(PPCFpOp op,HReg dst,HReg srcL,HReg srcR)1054 PPCInstr* PPCInstr_Dfp64Binary(PPCFpOp op, HReg dst, HReg srcL, HReg srcR) {
1055 PPCInstr* i = LibVEX_Alloc( sizeof(PPCInstr) );
1056 i->tag = Pin_Dfp64Binary;
1057 i->Pin.Dfp64Binary.op = op;
1058 i->Pin.Dfp64Binary.dst = dst;
1059 i->Pin.Dfp64Binary.srcL = srcL;
1060 i->Pin.Dfp64Binary.srcR = srcR;
1061 return i;
1062 }
PPCInstr_DfpShift(PPCFpOp op,HReg dst,HReg src,PPCRI * shift)1063 PPCInstr* PPCInstr_DfpShift ( PPCFpOp op, HReg dst, HReg src, PPCRI* shift ) {
1064 PPCInstr* i = LibVEX_Alloc(sizeof(PPCInstr));
1065 i->tag = Pin_DfpShift;
1066 i->Pin.DfpShift.op = op;
1067 i->Pin.DfpShift.shift = shift;
1068 i->Pin.DfpShift.src = src;
1069 i->Pin.DfpShift.dst = dst;
1070 return i;
1071 }
PPCInstr_Dfp128Unary(PPCFpOp op,HReg dst_hi,HReg dst_lo,HReg src_hi,HReg src_lo)1072 PPCInstr* PPCInstr_Dfp128Unary(PPCFpOp op, HReg dst_hi, HReg dst_lo,
1073 HReg src_hi, HReg src_lo) {
1074 PPCInstr* i = LibVEX_Alloc( sizeof(PPCInstr) );
1075 i->tag = Pin_Dfp128Unary;
1076 i->Pin.Dfp128Unary.op = op;
1077 i->Pin.Dfp128Unary.dst_hi = dst_hi;
1078 i->Pin.Dfp128Unary.dst_lo = dst_lo;
1079 i->Pin.Dfp128Unary.src_hi = src_hi;
1080 i->Pin.Dfp128Unary.src_lo = src_lo;
1081 return i;
1082 }
PPCInstr_Dfp128Binary(PPCFpOp op,HReg dst_hi,HReg dst_lo,HReg srcR_hi,HReg srcR_lo)1083 PPCInstr* PPCInstr_Dfp128Binary(PPCFpOp op, HReg dst_hi, HReg dst_lo,
1084 HReg srcR_hi, HReg srcR_lo) {
1085 /* dst is used to pass the srcL argument and return the result */
1086 PPCInstr* i = LibVEX_Alloc( sizeof(PPCInstr) );
1087 i->tag = Pin_Dfp128Binary;
1088 i->Pin.Dfp128Binary.op = op;
1089 i->Pin.Dfp128Binary.dst_hi = dst_hi;
1090 i->Pin.Dfp128Binary.dst_lo = dst_lo;
1091 i->Pin.Dfp128Binary.srcR_hi = srcR_hi;
1092 i->Pin.Dfp128Binary.srcR_lo = srcR_lo;
1093 return i;
1094 }
PPCInstr_DfpShift128(PPCFpOp op,HReg dst_hi,HReg dst_lo,HReg src_hi,HReg src_lo,PPCRI * shift)1095 PPCInstr* PPCInstr_DfpShift128 ( PPCFpOp op, HReg dst_hi, HReg dst_lo,
1096 HReg src_hi, HReg src_lo,
1097 PPCRI* shift ) {
1098 PPCInstr* i = LibVEX_Alloc(sizeof(PPCInstr));
1099 i->tag = Pin_DfpShift128;
1100 i->Pin.DfpShift128.op = op;
1101 i->Pin.DfpShift128.shift = shift;
1102 i->Pin.DfpShift128.src_hi = src_hi;
1103 i->Pin.DfpShift128.src_lo = src_lo;
1104 i->Pin.DfpShift128.dst_hi = dst_hi;
1105 i->Pin.DfpShift128.dst_lo = dst_lo;
1106 return i;
1107 }
PPCInstr_DfpRound(HReg dst,HReg src,PPCRI * r_rmc)1108 PPCInstr* PPCInstr_DfpRound ( HReg dst, HReg src, PPCRI* r_rmc ) {
1109 PPCInstr* i = LibVEX_Alloc(sizeof(PPCInstr));
1110 i->tag = Pin_DfpRound;
1111 i->Pin.DfpRound.dst = dst;
1112 i->Pin.DfpRound.src = src;
1113 i->Pin.DfpRound.r_rmc = r_rmc;
1114 return i;
1115 }
PPCInstr_DfpRound128(HReg dst_hi,HReg dst_lo,HReg src_hi,HReg src_lo,PPCRI * r_rmc)1116 PPCInstr* PPCInstr_DfpRound128 ( HReg dst_hi, HReg dst_lo, HReg src_hi,
1117 HReg src_lo, PPCRI* r_rmc ) {
1118 PPCInstr* i = LibVEX_Alloc(sizeof(PPCInstr));
1119 i->tag = Pin_DfpRound128;
1120 i->Pin.DfpRound128.dst_hi = dst_hi;
1121 i->Pin.DfpRound128.dst_lo = dst_lo;
1122 i->Pin.DfpRound128.src_hi = src_hi;
1123 i->Pin.DfpRound128.src_lo = src_lo;
1124 i->Pin.DfpRound128.r_rmc = r_rmc;
1125 return i;
1126 }
PPCInstr_DfpQuantize(PPCFpOp op,HReg dst,HReg srcL,HReg srcR,PPCRI * rmc)1127 PPCInstr* PPCInstr_DfpQuantize ( PPCFpOp op, HReg dst, HReg srcL, HReg srcR,
1128 PPCRI* rmc ) {
1129 PPCInstr* i = LibVEX_Alloc(sizeof(PPCInstr));
1130 i->tag = Pin_DfpQuantize;
1131 i->Pin.DfpQuantize.op = op;
1132 i->Pin.DfpQuantize.dst = dst;
1133 i->Pin.DfpQuantize.srcL = srcL;
1134 i->Pin.DfpQuantize.srcR = srcR;
1135 i->Pin.DfpQuantize.rmc = rmc;
1136 return i;
1137 }
PPCInstr_DfpQuantize128(PPCFpOp op,HReg dst_hi,HReg dst_lo,HReg src_hi,HReg src_lo,PPCRI * rmc)1138 PPCInstr* PPCInstr_DfpQuantize128 ( PPCFpOp op, HReg dst_hi, HReg dst_lo,
1139 HReg src_hi, HReg src_lo, PPCRI* rmc ) {
1140 /* dst is used to pass left operand in and return result */
1141 PPCInstr* i = LibVEX_Alloc(sizeof(PPCInstr));
1142 i->tag = Pin_DfpQuantize128;
1143 i->Pin.DfpQuantize128.op = op;
1144 i->Pin.DfpQuantize128.dst_hi = dst_hi;
1145 i->Pin.DfpQuantize128.dst_lo = dst_lo;
1146 i->Pin.DfpQuantize128.src_hi = src_hi;
1147 i->Pin.DfpQuantize128.src_lo = src_lo;
1148 i->Pin.DfpQuantize128.rmc = rmc;
1149 return i;
1150 }
PPCInstr_DfpD128toD64(PPCFpOp op,HReg dst,HReg src_hi,HReg src_lo)1151 PPCInstr* PPCInstr_DfpD128toD64 ( PPCFpOp op, HReg dst,
1152 HReg src_hi, HReg src_lo ) {
1153 PPCInstr* i = LibVEX_Alloc(sizeof(PPCInstr));
1154 i->tag = Pin_DfpD128toD64;
1155 i->Pin.DfpD128toD64.op = op;
1156 i->Pin.DfpD128toD64.src_hi = src_hi;
1157 i->Pin.DfpD128toD64.src_lo = src_lo;
1158 i->Pin.DfpD128toD64.dst = dst;
1159 return i;
1160 }
PPCInstr_DfpI64StoD128(PPCFpOp op,HReg dst_hi,HReg dst_lo,HReg src)1161 PPCInstr* PPCInstr_DfpI64StoD128 ( PPCFpOp op, HReg dst_hi,
1162 HReg dst_lo, HReg src ) {
1163 PPCInstr* i = LibVEX_Alloc(sizeof(PPCInstr));
1164 i->tag = Pin_DfpI64StoD128;
1165 i->Pin.DfpI64StoD128.op = op;
1166 i->Pin.DfpI64StoD128.src = src;
1167 i->Pin.DfpI64StoD128.dst_hi = dst_hi;
1168 i->Pin.DfpI64StoD128.dst_lo = dst_lo;
1169 return i;
1170 }
PPCInstr_ExtractExpD128(PPCFpOp op,HReg dst,HReg src_hi,HReg src_lo)1171 PPCInstr* PPCInstr_ExtractExpD128 ( PPCFpOp op, HReg dst,
1172 HReg src_hi, HReg src_lo ) {
1173 /* dst is used to pass the srcL argument */
1174 PPCInstr* i = LibVEX_Alloc(sizeof(PPCInstr));
1175 i->tag = Pin_ExtractExpD128;
1176 i->Pin.ExtractExpD128.op = op;
1177 i->Pin.ExtractExpD128.dst = dst;
1178 i->Pin.ExtractExpD128.src_hi = src_hi;
1179 i->Pin.ExtractExpD128.src_lo = src_lo;
1180 return i;
1181 }
PPCInstr_InsertExpD128(PPCFpOp op,HReg dst_hi,HReg dst_lo,HReg srcL,HReg srcR_hi,HReg srcR_lo)1182 PPCInstr* PPCInstr_InsertExpD128 ( PPCFpOp op, HReg dst_hi, HReg dst_lo,
1183 HReg srcL, HReg srcR_hi, HReg srcR_lo ) {
1184 /* dst is used to pass the srcL argument */
1185 PPCInstr* i = LibVEX_Alloc(sizeof(PPCInstr));
1186 i->tag = Pin_InsertExpD128;
1187 i->Pin.InsertExpD128.op = op;
1188 i->Pin.InsertExpD128.dst_hi = dst_hi;
1189 i->Pin.InsertExpD128.dst_lo = dst_lo;
1190 i->Pin.InsertExpD128.srcL = srcL;
1191 i->Pin.InsertExpD128.srcR_hi = srcR_hi;
1192 i->Pin.InsertExpD128.srcR_lo = srcR_lo;
1193 return i;
1194 }
PPCInstr_Dfp64Cmp(HReg dst,HReg srcL,HReg srcR)1195 PPCInstr* PPCInstr_Dfp64Cmp (/* UInt crfD,*/ HReg dst, HReg srcL, HReg srcR ) {
1196 PPCInstr* i = LibVEX_Alloc(sizeof(PPCInstr));
1197 i->tag = Pin_Dfp64Cmp;
1198 i->Pin.Dfp64Cmp.dst = dst;
1199 i->Pin.Dfp64Cmp.srcL = srcL;
1200 i->Pin.Dfp64Cmp.srcR = srcR;
1201 return i;
1202 }
PPCInstr_Dfp128Cmp(HReg dst,HReg srcL_hi,HReg srcL_lo,HReg srcR_hi,HReg srcR_lo)1203 PPCInstr* PPCInstr_Dfp128Cmp ( HReg dst, HReg srcL_hi, HReg srcL_lo,
1204 HReg srcR_hi, HReg srcR_lo ) {
1205 PPCInstr* i = LibVEX_Alloc(sizeof(PPCInstr));
1206 i->tag = Pin_Dfp128Cmp;
1207 i->Pin.Dfp128Cmp.dst = dst;
1208 i->Pin.Dfp128Cmp.srcL_hi = srcL_hi;
1209 i->Pin.Dfp128Cmp.srcL_lo = srcL_lo;
1210 i->Pin.Dfp128Cmp.srcR_hi = srcR_hi;
1211 i->Pin.Dfp128Cmp.srcR_lo = srcR_lo;
1212 return i;
1213 }
PPCInstr_EvCheck(PPCAMode * amCounter,PPCAMode * amFailAddr)1214 PPCInstr* PPCInstr_EvCheck ( PPCAMode* amCounter,
1215 PPCAMode* amFailAddr ) {
1216 PPCInstr* i = LibVEX_Alloc(sizeof(PPCInstr));
1217 i->tag = Pin_EvCheck;
1218 i->Pin.EvCheck.amCounter = amCounter;
1219 i->Pin.EvCheck.amFailAddr = amFailAddr;
1220 return i;
1221 }
PPCInstr_ProfInc(void)1222 PPCInstr* PPCInstr_ProfInc ( void ) {
1223 PPCInstr* i = LibVEX_Alloc(sizeof(PPCInstr));
1224 i->tag = Pin_ProfInc;
1225 return i;
1226 }
1227
1228 /*
1229 Valid combo | fromI | int32 | syned | flt64 |
1230 --------------------------------------------
1231 | n n n n |
1232 --------------------------------------------
1233 F64->I64U | n n n y |
1234 --------------------------------------------
1235 | n n y n |
1236 --------------------------------------------
1237 F64->I64S | n n y y |
1238 --------------------------------------------
1239 | n y n n |
1240 --------------------------------------------
1241 F64->I32U | n y n y |
1242 --------------------------------------------
1243 | n y y n |
1244 --------------------------------------------
1245 F64->I32S | n y y y |
1246 --------------------------------------------
1247 I64U->F32 | y n n n |
1248 --------------------------------------------
1249 I64U->F64 | y n n y |
1250 --------------------------------------------
1251 | y n y n |
1252 --------------------------------------------
1253 I64S->F64 | y n y y |
1254 --------------------------------------------
1255 | y y n n |
1256 --------------------------------------------
1257 | y y n y |
1258 --------------------------------------------
1259 | y y y n |
1260 --------------------------------------------
1261 | y y y y |
1262 --------------------------------------------
1263 */
PPCInstr_FpCftI(Bool fromI,Bool int32,Bool syned,Bool flt64,HReg dst,HReg src)1264 PPCInstr* PPCInstr_FpCftI ( Bool fromI, Bool int32, Bool syned,
1265 Bool flt64, HReg dst, HReg src ) {
1266 Bool tmp = fromI | int32 | syned | flt64;
1267 vassert(tmp == True || tmp == False); // iow, no high bits set
1268 UShort conversion = 0;
1269 conversion = (fromI << 3) | (int32 << 2) | (syned << 1) | flt64;
1270 switch (conversion) {
1271 // Supported conversion operations
1272 case 1: case 3: case 5: case 7:
1273 case 8: case 9: case 11:
1274 break;
1275 default:
1276 vpanic("PPCInstr_FpCftI(ppc_host)");
1277 }
1278 PPCInstr* i = LibVEX_Alloc(sizeof(PPCInstr));
1279 i->tag = Pin_FpCftI;
1280 i->Pin.FpCftI.fromI = fromI;
1281 i->Pin.FpCftI.int32 = int32;
1282 i->Pin.FpCftI.syned = syned;
1283 i->Pin.FpCftI.flt64 = flt64;
1284 i->Pin.FpCftI.dst = dst;
1285 i->Pin.FpCftI.src = src;
1286 return i;
1287 }
PPCInstr_FpCMov(PPCCondCode cond,HReg dst,HReg src)1288 PPCInstr* PPCInstr_FpCMov ( PPCCondCode cond, HReg dst, HReg src ) {
1289 PPCInstr* i = LibVEX_Alloc(sizeof(PPCInstr));
1290 i->tag = Pin_FpCMov;
1291 i->Pin.FpCMov.cond = cond;
1292 i->Pin.FpCMov.dst = dst;
1293 i->Pin.FpCMov.src = src;
1294 vassert(cond.test != Pct_ALWAYS);
1295 return i;
1296 }
PPCInstr_FpLdFPSCR(HReg src,Bool dfp_rm)1297 PPCInstr* PPCInstr_FpLdFPSCR ( HReg src, Bool dfp_rm ) {
1298 PPCInstr* i = LibVEX_Alloc(sizeof(PPCInstr));
1299 i->tag = Pin_FpLdFPSCR;
1300 i->Pin.FpLdFPSCR.src = src;
1301 i->Pin.FpLdFPSCR.dfp_rm = dfp_rm ? 1 : 0;
1302 return i;
1303 }
PPCInstr_FpCmp(HReg dst,HReg srcL,HReg srcR)1304 PPCInstr* PPCInstr_FpCmp ( HReg dst, HReg srcL, HReg srcR ) {
1305 PPCInstr* i = LibVEX_Alloc(sizeof(PPCInstr));
1306 i->tag = Pin_FpCmp;
1307 i->Pin.FpCmp.dst = dst;
1308 i->Pin.FpCmp.srcL = srcL;
1309 i->Pin.FpCmp.srcR = srcR;
1310 return i;
1311 }
1312
1313 /* Read/Write Link Register */
PPCInstr_RdWrLR(Bool wrLR,HReg gpr)1314 PPCInstr* PPCInstr_RdWrLR ( Bool wrLR, HReg gpr ) {
1315 PPCInstr* i = LibVEX_Alloc(sizeof(PPCInstr));
1316 i->tag = Pin_RdWrLR;
1317 i->Pin.RdWrLR.wrLR = wrLR;
1318 i->Pin.RdWrLR.gpr = gpr;
1319 return i;
1320 }
1321
1322 /* AltiVec */
PPCInstr_AvLdSt(Bool isLoad,UChar sz,HReg reg,PPCAMode * addr)1323 PPCInstr* PPCInstr_AvLdSt ( Bool isLoad, UChar sz,
1324 HReg reg, PPCAMode* addr ) {
1325 PPCInstr* i = LibVEX_Alloc(sizeof(PPCInstr));
1326 i->tag = Pin_AvLdSt;
1327 i->Pin.AvLdSt.isLoad = isLoad;
1328 i->Pin.AvLdSt.sz = sz;
1329 i->Pin.AvLdSt.reg = reg;
1330 i->Pin.AvLdSt.addr = addr;
1331 return i;
1332 }
PPCInstr_AvUnary(PPCAvOp op,HReg dst,HReg src)1333 PPCInstr* PPCInstr_AvUnary ( PPCAvOp op, HReg dst, HReg src ) {
1334 PPCInstr* i = LibVEX_Alloc(sizeof(PPCInstr));
1335 i->tag = Pin_AvUnary;
1336 i->Pin.AvUnary.op = op;
1337 i->Pin.AvUnary.dst = dst;
1338 i->Pin.AvUnary.src = src;
1339 return i;
1340 }
PPCInstr_AvBinary(PPCAvOp op,HReg dst,HReg srcL,HReg srcR)1341 PPCInstr* PPCInstr_AvBinary ( PPCAvOp op, HReg dst,
1342 HReg srcL, HReg srcR ) {
1343 PPCInstr* i = LibVEX_Alloc(sizeof(PPCInstr));
1344 i->tag = Pin_AvBinary;
1345 i->Pin.AvBinary.op = op;
1346 i->Pin.AvBinary.dst = dst;
1347 i->Pin.AvBinary.srcL = srcL;
1348 i->Pin.AvBinary.srcR = srcR;
1349 return i;
1350 }
PPCInstr_AvBin8x16(PPCAvOp op,HReg dst,HReg srcL,HReg srcR)1351 PPCInstr* PPCInstr_AvBin8x16 ( PPCAvOp op, HReg dst,
1352 HReg srcL, HReg srcR ) {
1353 PPCInstr* i = LibVEX_Alloc(sizeof(PPCInstr));
1354 i->tag = Pin_AvBin8x16;
1355 i->Pin.AvBin8x16.op = op;
1356 i->Pin.AvBin8x16.dst = dst;
1357 i->Pin.AvBin8x16.srcL = srcL;
1358 i->Pin.AvBin8x16.srcR = srcR;
1359 return i;
1360 }
PPCInstr_AvBin16x8(PPCAvOp op,HReg dst,HReg srcL,HReg srcR)1361 PPCInstr* PPCInstr_AvBin16x8 ( PPCAvOp op, HReg dst,
1362 HReg srcL, HReg srcR ) {
1363 PPCInstr* i = LibVEX_Alloc(sizeof(PPCInstr));
1364 i->tag = Pin_AvBin16x8;
1365 i->Pin.AvBin16x8.op = op;
1366 i->Pin.AvBin16x8.dst = dst;
1367 i->Pin.AvBin16x8.srcL = srcL;
1368 i->Pin.AvBin16x8.srcR = srcR;
1369 return i;
1370 }
PPCInstr_AvBin32x4(PPCAvOp op,HReg dst,HReg srcL,HReg srcR)1371 PPCInstr* PPCInstr_AvBin32x4 ( PPCAvOp op, HReg dst,
1372 HReg srcL, HReg srcR ) {
1373 PPCInstr* i = LibVEX_Alloc(sizeof(PPCInstr));
1374 i->tag = Pin_AvBin32x4;
1375 i->Pin.AvBin32x4.op = op;
1376 i->Pin.AvBin32x4.dst = dst;
1377 i->Pin.AvBin32x4.srcL = srcL;
1378 i->Pin.AvBin32x4.srcR = srcR;
1379 return i;
1380 }
PPCInstr_AvBin64x2(PPCAvOp op,HReg dst,HReg srcL,HReg srcR)1381 PPCInstr* PPCInstr_AvBin64x2 ( PPCAvOp op, HReg dst,
1382 HReg srcL, HReg srcR ) {
1383 PPCInstr* i = LibVEX_Alloc(sizeof(PPCInstr));
1384 i->tag = Pin_AvBin64x2;
1385 i->Pin.AvBin64x2.op = op;
1386 i->Pin.AvBin64x2.dst = dst;
1387 i->Pin.AvBin64x2.srcL = srcL;
1388 i->Pin.AvBin64x2.srcR = srcR;
1389 return i;
1390 }
1391
PPCInstr_AvBin32Fx4(PPCAvFpOp op,HReg dst,HReg srcL,HReg srcR)1392 PPCInstr* PPCInstr_AvBin32Fx4 ( PPCAvFpOp op, HReg dst,
1393 HReg srcL, HReg srcR ) {
1394 PPCInstr* i = LibVEX_Alloc(sizeof(PPCInstr));
1395 i->tag = Pin_AvBin32Fx4;
1396 i->Pin.AvBin32Fx4.op = op;
1397 i->Pin.AvBin32Fx4.dst = dst;
1398 i->Pin.AvBin32Fx4.srcL = srcL;
1399 i->Pin.AvBin32Fx4.srcR = srcR;
1400 return i;
1401 }
PPCInstr_AvUn32Fx4(PPCAvFpOp op,HReg dst,HReg src)1402 PPCInstr* PPCInstr_AvUn32Fx4 ( PPCAvFpOp op, HReg dst, HReg src ) {
1403 PPCInstr* i = LibVEX_Alloc(sizeof(PPCInstr));
1404 i->tag = Pin_AvUn32Fx4;
1405 i->Pin.AvUn32Fx4.op = op;
1406 i->Pin.AvUn32Fx4.dst = dst;
1407 i->Pin.AvUn32Fx4.src = src;
1408 return i;
1409 }
PPCInstr_AvPerm(HReg dst,HReg srcL,HReg srcR,HReg ctl)1410 PPCInstr* PPCInstr_AvPerm ( HReg dst, HReg srcL, HReg srcR, HReg ctl ) {
1411 PPCInstr* i = LibVEX_Alloc(sizeof(PPCInstr));
1412 i->tag = Pin_AvPerm;
1413 i->Pin.AvPerm.dst = dst;
1414 i->Pin.AvPerm.srcL = srcL;
1415 i->Pin.AvPerm.srcR = srcR;
1416 i->Pin.AvPerm.ctl = ctl;
1417 return i;
1418 }
1419
PPCInstr_AvSel(HReg ctl,HReg dst,HReg srcL,HReg srcR)1420 PPCInstr* PPCInstr_AvSel ( HReg ctl, HReg dst, HReg srcL, HReg srcR ) {
1421 PPCInstr* i = LibVEX_Alloc(sizeof(PPCInstr));
1422 i->tag = Pin_AvSel;
1423 i->Pin.AvSel.ctl = ctl;
1424 i->Pin.AvSel.dst = dst;
1425 i->Pin.AvSel.srcL = srcL;
1426 i->Pin.AvSel.srcR = srcR;
1427 return i;
1428 }
PPCInstr_AvShlDbl(UChar shift,HReg dst,HReg srcL,HReg srcR)1429 PPCInstr* PPCInstr_AvShlDbl ( UChar shift, HReg dst,
1430 HReg srcL, HReg srcR ) {
1431 PPCInstr* i = LibVEX_Alloc(sizeof(PPCInstr));
1432 i->tag = Pin_AvShlDbl;
1433 i->Pin.AvShlDbl.shift = shift;
1434 i->Pin.AvShlDbl.dst = dst;
1435 i->Pin.AvShlDbl.srcL = srcL;
1436 i->Pin.AvShlDbl.srcR = srcR;
1437 return i;
1438 }
PPCInstr_AvSplat(UChar sz,HReg dst,PPCVI5s * src)1439 PPCInstr* PPCInstr_AvSplat ( UChar sz, HReg dst, PPCVI5s* src ) {
1440 PPCInstr* i = LibVEX_Alloc(sizeof(PPCInstr));
1441 i->tag = Pin_AvSplat;
1442 i->Pin.AvSplat.sz = sz;
1443 i->Pin.AvSplat.dst = dst;
1444 i->Pin.AvSplat.src = src;
1445 return i;
1446 }
PPCInstr_AvCMov(PPCCondCode cond,HReg dst,HReg src)1447 PPCInstr* PPCInstr_AvCMov ( PPCCondCode cond, HReg dst, HReg src ) {
1448 PPCInstr* i = LibVEX_Alloc(sizeof(PPCInstr));
1449 i->tag = Pin_AvCMov;
1450 i->Pin.AvCMov.cond = cond;
1451 i->Pin.AvCMov.dst = dst;
1452 i->Pin.AvCMov.src = src;
1453 vassert(cond.test != Pct_ALWAYS);
1454 return i;
1455 }
PPCInstr_AvLdVSCR(HReg src)1456 PPCInstr* PPCInstr_AvLdVSCR ( HReg src ) {
1457 PPCInstr* i = LibVEX_Alloc(sizeof(PPCInstr));
1458 i->tag = Pin_AvLdVSCR;
1459 i->Pin.AvLdVSCR.src = src;
1460 return i;
1461 }
PPCInstr_AvCipherV128Unary(PPCAvOp op,HReg dst,HReg src)1462 PPCInstr* PPCInstr_AvCipherV128Unary ( PPCAvOp op, HReg dst, HReg src ) {
1463 PPCInstr* i = LibVEX_Alloc(sizeof(PPCInstr));
1464 i->tag = Pin_AvCipherV128Unary;
1465 i->Pin.AvCipherV128Unary.op = op;
1466 i->Pin.AvCipherV128Unary.dst = dst;
1467 i->Pin.AvCipherV128Unary.src = src;
1468 return i;
1469 }
PPCInstr_AvCipherV128Binary(PPCAvOp op,HReg dst,HReg srcL,HReg srcR)1470 PPCInstr* PPCInstr_AvCipherV128Binary ( PPCAvOp op, HReg dst,
1471 HReg srcL, HReg srcR ) {
1472 PPCInstr* i = LibVEX_Alloc(sizeof(PPCInstr));
1473 i->tag = Pin_AvCipherV128Binary;
1474 i->Pin.AvCipherV128Binary.op = op;
1475 i->Pin.AvCipherV128Binary.dst = dst;
1476 i->Pin.AvCipherV128Binary.srcL = srcL;
1477 i->Pin.AvCipherV128Binary.srcR = srcR;
1478 return i;
1479 }
PPCInstr_AvHashV128Binary(PPCAvOp op,HReg dst,HReg src,PPCRI * s_field)1480 PPCInstr* PPCInstr_AvHashV128Binary ( PPCAvOp op, HReg dst,
1481 HReg src, PPCRI* s_field ) {
1482 PPCInstr* i = LibVEX_Alloc(sizeof(PPCInstr));
1483 i->tag = Pin_AvHashV128Binary;
1484 i->Pin.AvHashV128Binary.op = op;
1485 i->Pin.AvHashV128Binary.dst = dst;
1486 i->Pin.AvHashV128Binary.src = src;
1487 i->Pin.AvHashV128Binary.s_field = s_field;
1488 return i;
1489 }
PPCInstr_AvBCDV128Trinary(PPCAvOp op,HReg dst,HReg src1,HReg src2,PPCRI * ps)1490 PPCInstr* PPCInstr_AvBCDV128Trinary ( PPCAvOp op, HReg dst,
1491 HReg src1, HReg src2, PPCRI* ps ) {
1492 PPCInstr* i = LibVEX_Alloc(sizeof(PPCInstr));
1493 i->tag = Pin_AvBCDV128Trinary;
1494 i->Pin.AvBCDV128Trinary.op = op;
1495 i->Pin.AvBCDV128Trinary.dst = dst;
1496 i->Pin.AvBCDV128Trinary.src1 = src1;
1497 i->Pin.AvBCDV128Trinary.src2 = src2;
1498 i->Pin.AvBCDV128Trinary.ps = ps;
1499 return i;
1500 }
1501
1502
1503 /* Pretty Print instructions */
ppLoadImm(HReg dst,ULong imm,Bool mode64)1504 static void ppLoadImm ( HReg dst, ULong imm, Bool mode64 ) {
1505 vex_printf("li_word ");
1506 ppHRegPPC(dst);
1507 if (!mode64) {
1508 vex_printf(",0x%08x", (UInt)imm);
1509 } else {
1510 vex_printf(",0x%016llx", imm);
1511 }
1512 }
1513
ppMovReg(HReg dst,HReg src)1514 static void ppMovReg ( HReg dst, HReg src ) {
1515 if (hregNumber(dst) != hregNumber(src)) {
1516 vex_printf("mr ");
1517 ppHRegPPC(dst);
1518 vex_printf(",");
1519 ppHRegPPC(src);
1520 }
1521 }
1522
ppPPCInstr(PPCInstr * i,Bool mode64)1523 void ppPPCInstr ( PPCInstr* i, Bool mode64 )
1524 {
1525 switch (i->tag) {
1526 case Pin_LI:
1527 ppLoadImm(i->Pin.LI.dst, i->Pin.LI.imm64, mode64);
1528 break;
1529 case Pin_Alu: {
1530 HReg r_srcL = i->Pin.Alu.srcL;
1531 PPCRH* rh_srcR = i->Pin.Alu.srcR;
1532 /* special-case "mr" */
1533 if (i->Pin.Alu.op == Palu_OR && // or Rd,Rs,Rs == mr Rd,Rs
1534 rh_srcR->tag == Prh_Reg &&
1535 sameHReg(rh_srcR->Prh.Reg.reg, r_srcL)) {
1536 vex_printf("mr ");
1537 ppHRegPPC(i->Pin.Alu.dst);
1538 vex_printf(",");
1539 ppHRegPPC(r_srcL);
1540 return;
1541 }
1542 /* special-case "li" */
1543 if (i->Pin.Alu.op == Palu_ADD && // addi Rd,0,imm == li Rd,imm
1544 rh_srcR->tag == Prh_Imm &&
1545 hregNumber(r_srcL) == 0) {
1546 vex_printf("li ");
1547 ppHRegPPC(i->Pin.Alu.dst);
1548 vex_printf(",");
1549 ppPPCRH(rh_srcR);
1550 return;
1551 }
1552 /* generic */
1553 vex_printf("%s ", showPPCAluOp(i->Pin.Alu.op,
1554 toBool(rh_srcR->tag == Prh_Imm)));
1555 ppHRegPPC(i->Pin.Alu.dst);
1556 vex_printf(",");
1557 ppHRegPPC(r_srcL);
1558 vex_printf(",");
1559 ppPPCRH(rh_srcR);
1560 return;
1561 }
1562 case Pin_Shft: {
1563 HReg r_srcL = i->Pin.Shft.srcL;
1564 PPCRH* rh_srcR = i->Pin.Shft.srcR;
1565 vex_printf("%s ", showPPCShftOp(i->Pin.Shft.op,
1566 toBool(rh_srcR->tag == Prh_Imm),
1567 i->Pin.Shft.sz32));
1568 ppHRegPPC(i->Pin.Shft.dst);
1569 vex_printf(",");
1570 ppHRegPPC(r_srcL);
1571 vex_printf(",");
1572 ppPPCRH(rh_srcR);
1573 return;
1574 }
1575 case Pin_AddSubC:
1576 vex_printf("%s%s ",
1577 i->Pin.AddSubC.isAdd ? "add" : "sub",
1578 i->Pin.AddSubC.setC ? "c" : "e");
1579 ppHRegPPC(i->Pin.AddSubC.dst);
1580 vex_printf(",");
1581 ppHRegPPC(i->Pin.AddSubC.srcL);
1582 vex_printf(",");
1583 ppHRegPPC(i->Pin.AddSubC.srcR);
1584 return;
1585 case Pin_Cmp:
1586 vex_printf("%s%c%s %%cr%u,",
1587 i->Pin.Cmp.syned ? "cmp" : "cmpl",
1588 i->Pin.Cmp.sz32 ? 'w' : 'd',
1589 i->Pin.Cmp.srcR->tag == Prh_Imm ? "i" : "",
1590 i->Pin.Cmp.crfD);
1591 ppHRegPPC(i->Pin.Cmp.srcL);
1592 vex_printf(",");
1593 ppPPCRH(i->Pin.Cmp.srcR);
1594 return;
1595 case Pin_Unary:
1596 vex_printf("%s ", showPPCUnaryOp(i->Pin.Unary.op));
1597 ppHRegPPC(i->Pin.Unary.dst);
1598 vex_printf(",");
1599 ppHRegPPC(i->Pin.Unary.src);
1600 return;
1601 case Pin_MulL:
1602 vex_printf("mul%c%c%s ",
1603 i->Pin.MulL.hi ? 'h' : 'l',
1604 i->Pin.MulL.sz32 ? 'w' : 'd',
1605 i->Pin.MulL.hi ? (i->Pin.MulL.syned ? "s" : "u") : "");
1606 ppHRegPPC(i->Pin.MulL.dst);
1607 vex_printf(",");
1608 ppHRegPPC(i->Pin.MulL.srcL);
1609 vex_printf(",");
1610 ppHRegPPC(i->Pin.MulL.srcR);
1611 return;
1612 case Pin_Div:
1613 vex_printf("div%c%s%s ",
1614 i->Pin.Div.sz32 ? 'w' : 'd',
1615 i->Pin.Div.extended ? "e" : "",
1616 i->Pin.Div.syned ? "" : "u");
1617 ppHRegPPC(i->Pin.Div.dst);
1618 vex_printf(",");
1619 ppHRegPPC(i->Pin.Div.srcL);
1620 vex_printf(",");
1621 ppHRegPPC(i->Pin.Div.srcR);
1622 return;
1623 case Pin_Call: {
1624 Int n;
1625 vex_printf("call: ");
1626 if (i->Pin.Call.cond.test != Pct_ALWAYS) {
1627 vex_printf("if (%s) ", showPPCCondCode(i->Pin.Call.cond));
1628 }
1629 vex_printf("{ ");
1630 ppLoadImm(hregPPC_GPR10(mode64), i->Pin.Call.target, mode64);
1631 vex_printf(" ; mtctr r10 ; bctrl [");
1632 for (n = 0; n < 32; n++) {
1633 if (i->Pin.Call.argiregs & (1<<n)) {
1634 vex_printf("r%d", n);
1635 if ((i->Pin.Call.argiregs >> n) > 1)
1636 vex_printf(",");
1637 }
1638 }
1639 vex_printf(",");
1640 ppRetLoc(i->Pin.Call.rloc);
1641 vex_printf("] }");
1642 break;
1643 }
1644 case Pin_XDirect:
1645 vex_printf("(xDirect) ");
1646 vex_printf("if (%s) { ",
1647 showPPCCondCode(i->Pin.XDirect.cond));
1648 if (mode64) {
1649 vex_printf("imm64 r30,0x%llx; ", i->Pin.XDirect.dstGA);
1650 vex_printf("std r30,");
1651 } else {
1652 vex_printf("imm32 r30,0x%llx; ", i->Pin.XDirect.dstGA);
1653 vex_printf("stw r30,");
1654 }
1655 ppPPCAMode(i->Pin.XDirect.amCIA);
1656 vex_printf("; ");
1657 if (mode64) {
1658 vex_printf("imm64-fixed5 r30,$disp_cp_chain_me_to_%sEP; ",
1659 i->Pin.XDirect.toFastEP ? "fast" : "slow");
1660 } else {
1661 vex_printf("imm32-fixed2 r30,$disp_cp_chain_me_to_%sEP; ",
1662 i->Pin.XDirect.toFastEP ? "fast" : "slow");
1663 }
1664 vex_printf("mtctr r30; bctrl }");
1665 return;
1666 case Pin_XIndir:
1667 vex_printf("(xIndir) ");
1668 vex_printf("if (%s) { ",
1669 showPPCCondCode(i->Pin.XIndir.cond));
1670 vex_printf("%s ", mode64 ? "std" : "stw");
1671 ppHRegPPC(i->Pin.XIndir.dstGA);
1672 vex_printf(",");
1673 ppPPCAMode(i->Pin.XIndir.amCIA);
1674 vex_printf("; ");
1675 vex_printf("imm%s r30,$disp_cp_xindir; ", mode64 ? "64" : "32");
1676 vex_printf("mtctr r30; bctr }");
1677 return;
1678 case Pin_XAssisted:
1679 vex_printf("(xAssisted) ");
1680 vex_printf("if (%s) { ",
1681 showPPCCondCode(i->Pin.XAssisted.cond));
1682 vex_printf("%s ", mode64 ? "std" : "stw");
1683 ppHRegPPC(i->Pin.XAssisted.dstGA);
1684 vex_printf(",");
1685 ppPPCAMode(i->Pin.XAssisted.amCIA);
1686 vex_printf("; ");
1687 vex_printf("li r31,$IRJumpKind_to_TRCVAL(%d); ",
1688 (Int)i->Pin.XAssisted.jk);
1689 vex_printf("imm%s r30,$disp_cp_xindir; ", mode64 ? "64" : "32");
1690 vex_printf("mtctr r30; bctr }");
1691 return;
1692 case Pin_CMov:
1693 vex_printf("cmov (%s) ", showPPCCondCode(i->Pin.CMov.cond));
1694 ppHRegPPC(i->Pin.CMov.dst);
1695 vex_printf(",");
1696 ppPPCRI(i->Pin.CMov.src);
1697 vex_printf(": ");
1698 if (i->Pin.CMov.cond.test != Pct_ALWAYS) {
1699 vex_printf("if (%s) ", showPPCCondCode(i->Pin.CMov.cond));
1700 }
1701 vex_printf("{ ");
1702 if (i->Pin.CMov.src->tag == Pri_Imm) {
1703 ppLoadImm(i->Pin.CMov.dst, i->Pin.CMov.src->Pri.Imm, mode64);
1704 } else {
1705 ppMovReg(i->Pin.CMov.dst, i->Pin.CMov.src->Pri.Reg);
1706 }
1707 vex_printf(" }");
1708 return;
1709 case Pin_Load: {
1710 Bool idxd = toBool(i->Pin.Load.src->tag == Pam_RR);
1711 UChar sz = i->Pin.Load.sz;
1712 HChar c_sz = sz==1 ? 'b' : sz==2 ? 'h' : sz==4 ? 'w' : 'd';
1713 vex_printf("l%c%s%s ", c_sz, sz==8 ? "" : "z", idxd ? "x" : "" );
1714 ppHRegPPC(i->Pin.Load.dst);
1715 vex_printf(",");
1716 ppPPCAMode(i->Pin.Load.src);
1717 return;
1718 }
1719 case Pin_LoadL:
1720 vex_printf("l%carx ", i->Pin.LoadL.sz==4 ? 'w' : 'd');
1721 ppHRegPPC(i->Pin.LoadL.dst);
1722 vex_printf(",%%r0,");
1723 ppHRegPPC(i->Pin.LoadL.src);
1724 return;
1725 case Pin_Store: {
1726 UChar sz = i->Pin.Store.sz;
1727 Bool idxd = toBool(i->Pin.Store.dst->tag == Pam_RR);
1728 HChar c_sz = sz==1 ? 'b' : sz==2 ? 'h' : sz==4 ? 'w' : /*8*/ 'd';
1729 vex_printf("st%c%s ", c_sz, idxd ? "x" : "" );
1730 ppHRegPPC(i->Pin.Store.src);
1731 vex_printf(",");
1732 ppPPCAMode(i->Pin.Store.dst);
1733 return;
1734 }
1735 case Pin_StoreC:
1736 vex_printf("st%ccx. ", i->Pin.StoreC.sz==4 ? 'w' : 'd');
1737 ppHRegPPC(i->Pin.StoreC.src);
1738 vex_printf(",%%r0,");
1739 ppHRegPPC(i->Pin.StoreC.dst);
1740 return;
1741 case Pin_Set: {
1742 PPCCondCode cc = i->Pin.Set.cond;
1743 vex_printf("set (%s),", showPPCCondCode(cc));
1744 ppHRegPPC(i->Pin.Set.dst);
1745 if (cc.test == Pct_ALWAYS) {
1746 vex_printf(": { li ");
1747 ppHRegPPC(i->Pin.Set.dst);
1748 vex_printf(",1 }");
1749 } else {
1750 vex_printf(": { mfcr r0 ; rlwinm ");
1751 ppHRegPPC(i->Pin.Set.dst);
1752 vex_printf(",r0,%u,31,31", cc.flag+1);
1753 if (cc.test == Pct_FALSE) {
1754 vex_printf("; xori ");
1755 ppHRegPPC(i->Pin.Set.dst);
1756 vex_printf(",");
1757 ppHRegPPC(i->Pin.Set.dst);
1758 vex_printf(",1");
1759 }
1760 vex_printf(" }");
1761 }
1762 return;
1763 }
1764 case Pin_MfCR:
1765 vex_printf("mfcr ");
1766 ppHRegPPC(i->Pin.MfCR.dst);
1767 break;
1768 case Pin_MFence:
1769 vex_printf("mfence (=sync)");
1770 return;
1771
1772 case Pin_FpUnary:
1773 vex_printf("%s ", showPPCFpOp(i->Pin.FpUnary.op));
1774 ppHRegPPC(i->Pin.FpUnary.dst);
1775 vex_printf(",");
1776 ppHRegPPC(i->Pin.FpUnary.src);
1777 return;
1778 case Pin_FpBinary:
1779 vex_printf("%s ", showPPCFpOp(i->Pin.FpBinary.op));
1780 ppHRegPPC(i->Pin.FpBinary.dst);
1781 vex_printf(",");
1782 ppHRegPPC(i->Pin.FpBinary.srcL);
1783 vex_printf(",");
1784 ppHRegPPC(i->Pin.FpBinary.srcR);
1785 return;
1786 case Pin_FpMulAcc:
1787 vex_printf("%s ", showPPCFpOp(i->Pin.FpMulAcc.op));
1788 ppHRegPPC(i->Pin.FpMulAcc.dst);
1789 vex_printf(",");
1790 ppHRegPPC(i->Pin.FpMulAcc.srcML);
1791 vex_printf(",");
1792 ppHRegPPC(i->Pin.FpMulAcc.srcMR);
1793 vex_printf(",");
1794 ppHRegPPC(i->Pin.FpMulAcc.srcAcc);
1795 return;
1796 case Pin_FpLdSt: {
1797 UChar sz = i->Pin.FpLdSt.sz;
1798 Bool idxd = toBool(i->Pin.FpLdSt.addr->tag == Pam_RR);
1799 if (i->Pin.FpLdSt.isLoad) {
1800 vex_printf("lf%c%s ",
1801 (sz==4 ? 's' : 'd'),
1802 idxd ? "x" : "" );
1803 ppHRegPPC(i->Pin.FpLdSt.reg);
1804 vex_printf(",");
1805 ppPPCAMode(i->Pin.FpLdSt.addr);
1806 } else {
1807 vex_printf("stf%c%s ",
1808 (sz==4 ? 's' : 'd'),
1809 idxd ? "x" : "" );
1810 ppHRegPPC(i->Pin.FpLdSt.reg);
1811 vex_printf(",");
1812 ppPPCAMode(i->Pin.FpLdSt.addr);
1813 }
1814 return;
1815 }
1816 case Pin_FpSTFIW:
1817 vex_printf("stfiwz ");
1818 ppHRegPPC(i->Pin.FpSTFIW.data);
1819 vex_printf(",0(");
1820 ppHRegPPC(i->Pin.FpSTFIW.addr);
1821 vex_printf(")");
1822 return;
1823 case Pin_FpRSP:
1824 vex_printf("frsp ");
1825 ppHRegPPC(i->Pin.FpRSP.dst);
1826 vex_printf(",");
1827 ppHRegPPC(i->Pin.FpRSP.src);
1828 return;
1829 case Pin_FpCftI: {
1830 const HChar* str = "fc?????";
1831 /* Note that "fcfids" is missing from below. That instruction would
1832 * satisfy the predicate:
1833 * (i->Pin.FpCftI.fromI == True && i->Pin.FpCftI.int32 == False)
1834 * which would go into a final "else" clause to make this if-else
1835 * block balanced. But we're able to implement fcfids by leveraging
1836 * the fcfid implementation, so it wasn't necessary to include it here.
1837 */
1838 if (i->Pin.FpCftI.fromI == False && i->Pin.FpCftI.int32 == False)
1839 if (i->Pin.FpCftI.syned == True)
1840 str = "fctid";
1841 else
1842 str = "fctidu";
1843 else if (i->Pin.FpCftI.fromI == False && i->Pin.FpCftI.int32 == True)
1844 if (i->Pin.FpCftI.syned == True)
1845 str = "fctiw";
1846 else
1847 str = "fctiwu";
1848 else if (i->Pin.FpCftI.fromI == True && i->Pin.FpCftI.int32 == False) {
1849 if (i->Pin.FpCftI.syned == True) {
1850 str = "fcfid";
1851 } else {
1852 if (i->Pin.FpCftI.flt64 == True)
1853 str = "fcfidu";
1854 else
1855 str = "fcfidus";
1856 }
1857 }
1858 vex_printf("%s ", str);
1859 ppHRegPPC(i->Pin.FpCftI.dst);
1860 vex_printf(",");
1861 ppHRegPPC(i->Pin.FpCftI.src);
1862 return;
1863 }
1864 case Pin_FpCMov:
1865 vex_printf("fpcmov (%s) ", showPPCCondCode(i->Pin.FpCMov.cond));
1866 ppHRegPPC(i->Pin.FpCMov.dst);
1867 vex_printf(",");
1868 ppHRegPPC(i->Pin.FpCMov.src);
1869 vex_printf(": ");
1870 vex_printf("if (fr_dst != fr_src) { ");
1871 if (i->Pin.FpCMov.cond.test != Pct_ALWAYS) {
1872 vex_printf("if (%s) { ", showPPCCondCode(i->Pin.FpCMov.cond));
1873 }
1874 vex_printf("fmr ");
1875 ppHRegPPC(i->Pin.FpCMov.dst);
1876 vex_printf(",");
1877 ppHRegPPC(i->Pin.FpCMov.src);
1878 if (i->Pin.FpCMov.cond.test != Pct_ALWAYS)
1879 vex_printf(" }");
1880 vex_printf(" }");
1881 return;
1882 case Pin_FpLdFPSCR:
1883 vex_printf("mtfsf 0xFF,");
1884 ppHRegPPC(i->Pin.FpLdFPSCR.src);
1885 vex_printf(",0, %s", i->Pin.FpLdFPSCR.dfp_rm ? "1" : "0");
1886 return;
1887 case Pin_FpCmp:
1888 vex_printf("fcmpo %%cr1,");
1889 ppHRegPPC(i->Pin.FpCmp.srcL);
1890 vex_printf(",");
1891 ppHRegPPC(i->Pin.FpCmp.srcR);
1892 vex_printf("; mfcr ");
1893 ppHRegPPC(i->Pin.FpCmp.dst);
1894 vex_printf("; rlwinm ");
1895 ppHRegPPC(i->Pin.FpCmp.dst);
1896 vex_printf(",");
1897 ppHRegPPC(i->Pin.FpCmp.dst);
1898 vex_printf(",8,28,31");
1899 return;
1900
1901 case Pin_RdWrLR:
1902 vex_printf("%s ", i->Pin.RdWrLR.wrLR ? "mtlr" : "mflr");
1903 ppHRegPPC(i->Pin.RdWrLR.gpr);
1904 return;
1905
1906 case Pin_AvLdSt: {
1907 UChar sz = i->Pin.AvLdSt.sz;
1908 const HChar* str_size;
1909 if (i->Pin.AvLdSt.addr->tag == Pam_IR) {
1910 ppLoadImm(hregPPC_GPR30(mode64),
1911 i->Pin.AvLdSt.addr->Pam.IR.index, mode64);
1912 vex_printf(" ; ");
1913 }
1914 str_size = sz==1 ? "eb" : sz==2 ? "eh" : sz==4 ? "ew" : "";
1915 if (i->Pin.AvLdSt.isLoad)
1916 vex_printf("lv%sx ", str_size);
1917 else
1918 vex_printf("stv%sx ", str_size);
1919 ppHRegPPC(i->Pin.AvLdSt.reg);
1920 vex_printf(",");
1921 if (i->Pin.AvLdSt.addr->tag == Pam_IR)
1922 vex_printf("%%r30");
1923 else
1924 ppHRegPPC(i->Pin.AvLdSt.addr->Pam.RR.index);
1925 vex_printf(",");
1926 ppHRegPPC(i->Pin.AvLdSt.addr->Pam.RR.base);
1927 return;
1928 }
1929 case Pin_AvUnary:
1930 vex_printf("%s ", showPPCAvOp(i->Pin.AvUnary.op));
1931 ppHRegPPC(i->Pin.AvUnary.dst);
1932 vex_printf(",");
1933 ppHRegPPC(i->Pin.AvUnary.src);
1934 return;
1935 case Pin_AvBinary:
1936 vex_printf("%s ", showPPCAvOp(i->Pin.AvBinary.op));
1937 ppHRegPPC(i->Pin.AvBinary.dst);
1938 vex_printf(",");
1939 ppHRegPPC(i->Pin.AvBinary.srcL);
1940 vex_printf(",");
1941 ppHRegPPC(i->Pin.AvBinary.srcR);
1942 return;
1943 case Pin_AvBin8x16:
1944 vex_printf("%s(b) ", showPPCAvOp(i->Pin.AvBin8x16.op));
1945 ppHRegPPC(i->Pin.AvBin8x16.dst);
1946 vex_printf(",");
1947 ppHRegPPC(i->Pin.AvBin8x16.srcL);
1948 vex_printf(",");
1949 ppHRegPPC(i->Pin.AvBin8x16.srcR);
1950 return;
1951 case Pin_AvBin16x8:
1952 vex_printf("%s(h) ", showPPCAvOp(i->Pin.AvBin16x8.op));
1953 ppHRegPPC(i->Pin.AvBin16x8.dst);
1954 vex_printf(",");
1955 ppHRegPPC(i->Pin.AvBin16x8.srcL);
1956 vex_printf(",");
1957 ppHRegPPC(i->Pin.AvBin16x8.srcR);
1958 return;
1959 case Pin_AvBin32x4:
1960 vex_printf("%s(w) ", showPPCAvOp(i->Pin.AvBin32x4.op));
1961 ppHRegPPC(i->Pin.AvBin32x4.dst);
1962 vex_printf(",");
1963 ppHRegPPC(i->Pin.AvBin32x4.srcL);
1964 vex_printf(",");
1965 ppHRegPPC(i->Pin.AvBin32x4.srcR);
1966 return;
1967 case Pin_AvBin64x2:
1968 vex_printf("%s(w) ", showPPCAvOp(i->Pin.AvBin64x2.op));
1969 ppHRegPPC(i->Pin.AvBin64x2.dst);
1970 vex_printf(",");
1971 ppHRegPPC(i->Pin.AvBin64x2.srcL);
1972 vex_printf(",");
1973 ppHRegPPC(i->Pin.AvBin64x2.srcR);
1974 return;
1975 case Pin_AvBin32Fx4:
1976 vex_printf("%s ", showPPCAvFpOp(i->Pin.AvBin32Fx4.op));
1977 ppHRegPPC(i->Pin.AvBin32Fx4.dst);
1978 vex_printf(",");
1979 ppHRegPPC(i->Pin.AvBin32Fx4.srcL);
1980 vex_printf(",");
1981 ppHRegPPC(i->Pin.AvBin32Fx4.srcR);
1982 return;
1983 case Pin_AvUn32Fx4:
1984 vex_printf("%s ", showPPCAvFpOp(i->Pin.AvUn32Fx4.op));
1985 ppHRegPPC(i->Pin.AvUn32Fx4.dst);
1986 vex_printf(",");
1987 ppHRegPPC(i->Pin.AvUn32Fx4.src);
1988 return;
1989 case Pin_AvPerm:
1990 vex_printf("vperm ");
1991 ppHRegPPC(i->Pin.AvPerm.dst);
1992 vex_printf(",");
1993 ppHRegPPC(i->Pin.AvPerm.srcL);
1994 vex_printf(",");
1995 ppHRegPPC(i->Pin.AvPerm.srcR);
1996 vex_printf(",");
1997 ppHRegPPC(i->Pin.AvPerm.ctl);
1998 return;
1999
2000 case Pin_AvSel:
2001 vex_printf("vsel ");
2002 ppHRegPPC(i->Pin.AvSel.dst);
2003 vex_printf(",");
2004 ppHRegPPC(i->Pin.AvSel.srcL);
2005 vex_printf(",");
2006 ppHRegPPC(i->Pin.AvSel.srcR);
2007 vex_printf(",");
2008 ppHRegPPC(i->Pin.AvSel.ctl);
2009 return;
2010
2011 case Pin_AvShlDbl:
2012 vex_printf("vsldoi ");
2013 ppHRegPPC(i->Pin.AvShlDbl.dst);
2014 vex_printf(",");
2015 ppHRegPPC(i->Pin.AvShlDbl.srcL);
2016 vex_printf(",");
2017 ppHRegPPC(i->Pin.AvShlDbl.srcR);
2018 vex_printf(",%d", i->Pin.AvShlDbl.shift);
2019 return;
2020
2021 case Pin_AvSplat: {
2022 UChar sz = i->Pin.AvSplat.sz;
2023 HChar ch_sz = toUChar( (sz == 8) ? 'b' : (sz == 16) ? 'h' : 'w' );
2024 vex_printf("vsplt%s%c ",
2025 i->Pin.AvSplat.src->tag == Pvi_Imm ? "is" : "", ch_sz);
2026 ppHRegPPC(i->Pin.AvSplat.dst);
2027 vex_printf(",");
2028 ppPPCVI5s(i->Pin.AvSplat.src);
2029 if (i->Pin.AvSplat.src->tag == Pvi_Reg)
2030 vex_printf(", %d", (128/sz)-1); /* louis lane */
2031 return;
2032 }
2033
2034 case Pin_AvCMov:
2035 vex_printf("avcmov (%s) ", showPPCCondCode(i->Pin.AvCMov.cond));
2036 ppHRegPPC(i->Pin.AvCMov.dst);
2037 vex_printf(",");
2038 ppHRegPPC(i->Pin.AvCMov.src);
2039 vex_printf(": ");
2040 vex_printf("if (v_dst != v_src) { ");
2041 if (i->Pin.AvCMov.cond.test != Pct_ALWAYS) {
2042 vex_printf("if (%s) { ", showPPCCondCode(i->Pin.AvCMov.cond));
2043 }
2044 vex_printf("vmr ");
2045 ppHRegPPC(i->Pin.AvCMov.dst);
2046 vex_printf(",");
2047 ppHRegPPC(i->Pin.AvCMov.src);
2048 if (i->Pin.FpCMov.cond.test != Pct_ALWAYS)
2049 vex_printf(" }");
2050 vex_printf(" }");
2051 return;
2052
2053 case Pin_AvLdVSCR:
2054 vex_printf("mtvscr ");
2055 ppHRegPPC(i->Pin.AvLdVSCR.src);
2056 return;
2057
2058 case Pin_AvCipherV128Unary:
2059 vex_printf("%s(w) ", showPPCAvOp(i->Pin.AvCipherV128Unary.op));
2060 ppHRegPPC(i->Pin.AvCipherV128Unary.dst);
2061 vex_printf(",");
2062 ppHRegPPC(i->Pin.AvCipherV128Unary.src);
2063 return;
2064
2065 case Pin_AvCipherV128Binary:
2066 vex_printf("%s(w) ", showPPCAvOp(i->Pin.AvCipherV128Binary.op));
2067 ppHRegPPC(i->Pin.AvCipherV128Binary.dst);
2068 vex_printf(",");
2069 ppHRegPPC(i->Pin.AvCipherV128Binary.srcL);
2070 vex_printf(",");
2071 ppHRegPPC(i->Pin.AvCipherV128Binary.srcR);
2072 return;
2073
2074 case Pin_AvHashV128Binary:
2075 vex_printf("%s(w) ", showPPCAvOp(i->Pin.AvHashV128Binary.op));
2076 ppHRegPPC(i->Pin.AvHashV128Binary.dst);
2077 vex_printf(",");
2078 ppHRegPPC(i->Pin.AvHashV128Binary.src);
2079 vex_printf(",");
2080 ppPPCRI(i->Pin.AvHashV128Binary.s_field);
2081 return;
2082
2083 case Pin_AvBCDV128Trinary:
2084 vex_printf("%s(w) ", showPPCAvOp(i->Pin.AvBCDV128Trinary.op));
2085 ppHRegPPC(i->Pin.AvBCDV128Trinary.dst);
2086 vex_printf(",");
2087 ppHRegPPC(i->Pin.AvBCDV128Trinary.src1);
2088 vex_printf(",");
2089 ppHRegPPC(i->Pin.AvBCDV128Trinary.src2);
2090 vex_printf(",");
2091 ppPPCRI(i->Pin.AvBCDV128Trinary.ps);
2092 return;
2093
2094 case Pin_Dfp64Unary:
2095 vex_printf("%s ", showPPCFpOp(i->Pin.Dfp64Unary.op));
2096 ppHRegPPC(i->Pin.Dfp64Unary.dst);
2097 vex_printf(",");
2098 ppHRegPPC(i->Pin.Dfp64Unary.src);
2099 return;
2100
2101 case Pin_Dfp64Binary:
2102 vex_printf("%s ", showPPCFpOp(i->Pin.Dfp64Binary.op));
2103 ppHRegPPC(i->Pin.Dfp64Binary.dst);
2104 vex_printf(",");
2105 ppHRegPPC(i->Pin.Dfp64Binary.srcL);
2106 vex_printf(",");
2107 ppHRegPPC(i->Pin.Dfp64Binary.srcR);
2108 return;
2109
2110 case Pin_DfpShift:
2111 vex_printf("%s ", showPPCFpOp(i->Pin.DfpShift.op));
2112 ppHRegPPC(i->Pin.DfpShift.dst);
2113 vex_printf(",");
2114 ppHRegPPC(i->Pin.DfpShift.src);
2115 vex_printf(",");
2116 ppPPCRI(i->Pin.DfpShift.shift);
2117 return;
2118
2119 case Pin_Dfp128Unary:
2120 vex_printf("%s ", showPPCFpOp(i->Pin.Dfp128Unary.op));
2121 ppHRegPPC(i->Pin.Dfp128Unary.dst_hi);
2122 vex_printf(",");
2123 ppHRegPPC(i->Pin.Dfp128Unary.src_hi);
2124 return;
2125
2126 case Pin_Dfp128Binary:
2127 vex_printf("%s ", showPPCFpOp(i->Pin.Dfp128Binary.op));
2128 ppHRegPPC(i->Pin.Dfp128Binary.dst_hi);
2129 vex_printf(",");
2130 ppHRegPPC(i->Pin.Dfp128Binary.srcR_hi);
2131 return;
2132
2133 case Pin_DfpShift128:
2134 vex_printf("%s ", showPPCFpOp(i->Pin.DfpShift128.op));
2135 ppHRegPPC(i->Pin.DfpShift128.dst_hi);
2136 vex_printf(",");
2137 ppHRegPPC(i->Pin.DfpShift128.src_hi);
2138 vex_printf(",");
2139 ppPPCRI(i->Pin.DfpShift128.shift);
2140 return;
2141
2142 case Pin_DfpRound:
2143 vex_printf("drintx ");
2144 ppHRegPPC(i->Pin.DfpRound.dst);
2145 vex_printf(",");
2146 ppHRegPPC(i->Pin.DfpRound.src);
2147 vex_printf(",");
2148 ppPPCRI(i->Pin.DfpRound.r_rmc); /* R in bit 3 and RMC in bits 2:0 */
2149 return;
2150
2151 case Pin_DfpRound128:
2152 vex_printf("drintxq ");
2153 ppHRegPPC(i->Pin.DfpRound128.dst_hi);
2154 vex_printf(",");
2155 ppHRegPPC(i->Pin.DfpRound128.src_hi);
2156 vex_printf(",");
2157 ppPPCRI(i->Pin.DfpRound128.r_rmc); /* R in bit 3 and RMC in bits 2:0 */
2158 return;
2159
2160 case Pin_DfpQuantize:
2161 vex_printf("%s ", showPPCFpOp(i->Pin.DfpQuantize.op));
2162 ppHRegPPC(i->Pin.DfpQuantize.dst);
2163 vex_printf(",");
2164 ppHRegPPC(i->Pin.DfpQuantize.srcL);
2165 vex_printf(",");
2166 ppHRegPPC(i->Pin.DfpQuantize.srcR);
2167 vex_printf(",");
2168 ppPPCRI(i->Pin.DfpQuantize.rmc);
2169 return;
2170
2171 case Pin_DfpQuantize128:
2172 /* Dst is used to pass in left source and return result */
2173 vex_printf("dquaq ");
2174 ppHRegPPC(i->Pin.DfpQuantize128.dst_hi);
2175 vex_printf(",");
2176 ppHRegPPC(i->Pin.DfpQuantize128.dst_hi);
2177 vex_printf(",");
2178 ppHRegPPC(i->Pin.DfpQuantize128.src_hi);
2179 vex_printf(",");
2180 ppPPCRI(i->Pin.DfpQuantize128.rmc);
2181 return;
2182
2183 case Pin_DfpD128toD64:
2184 vex_printf("%s ", showPPCFpOp(i->Pin.DfpD128toD64.op));
2185 ppHRegPPC(i->Pin.DfpD128toD64.dst);
2186 vex_printf(",");
2187 ppHRegPPC(i->Pin.DfpD128toD64.src_hi);
2188 vex_printf(",");
2189 return;
2190
2191 case Pin_DfpI64StoD128:
2192 vex_printf("%s ", showPPCFpOp(i->Pin.DfpI64StoD128.op));
2193 ppHRegPPC(i->Pin.DfpI64StoD128.dst_hi);
2194 vex_printf(",");
2195 ppHRegPPC(i->Pin.DfpI64StoD128.src);
2196 vex_printf(",");
2197 return;
2198 case Pin_ExtractExpD128:
2199 vex_printf("dxexq ");
2200 ppHRegPPC(i->Pin.ExtractExpD128.dst);
2201 vex_printf(",");
2202 ppHRegPPC(i->Pin.ExtractExpD128.src_hi);
2203 return;
2204 case Pin_InsertExpD128:
2205 vex_printf("diexq ");
2206 ppHRegPPC(i->Pin.InsertExpD128.dst_hi);
2207 vex_printf(",");
2208 ppHRegPPC(i->Pin.InsertExpD128.srcL);
2209 vex_printf(",");
2210 ppHRegPPC(i->Pin.InsertExpD128.srcR_hi);
2211 return;
2212 case Pin_Dfp64Cmp:
2213 vex_printf("dcmpo %%cr1,");
2214 ppHRegPPC(i->Pin.Dfp64Cmp.srcL);
2215 vex_printf(",");
2216 ppHRegPPC(i->Pin.Dfp64Cmp.srcR);
2217 vex_printf("; mfcr ");
2218 ppHRegPPC(i->Pin.Dfp64Cmp.dst);
2219 vex_printf("; rlwinm ");
2220 ppHRegPPC(i->Pin.Dfp64Cmp.dst);
2221 vex_printf(",");
2222 ppHRegPPC(i->Pin.Dfp64Cmp.dst);
2223 vex_printf(",8,28,31");
2224 return;
2225 case Pin_Dfp128Cmp:
2226 vex_printf("dcmpoq %%cr1,");
2227 ppHRegPPC(i->Pin.Dfp128Cmp.srcL_hi);
2228 vex_printf(",");
2229 ppHRegPPC(i->Pin.Dfp128Cmp.srcR_hi);
2230 vex_printf("; mfcr ");
2231 ppHRegPPC(i->Pin.Dfp128Cmp.dst);
2232 vex_printf("; rlwinm ");
2233 ppHRegPPC(i->Pin.Dfp128Cmp.dst);
2234 vex_printf(",");
2235 ppHRegPPC(i->Pin.Dfp128Cmp.dst);
2236 vex_printf(",8,28,31");
2237 return;
2238 case Pin_EvCheck:
2239 /* Note that the counter dec is 32 bit even in 64-bit mode. */
2240 vex_printf("(evCheck) ");
2241 vex_printf("lwz r30,");
2242 ppPPCAMode(i->Pin.EvCheck.amCounter);
2243 vex_printf("; addic. r30,r30,-1; ");
2244 vex_printf("stw r30,");
2245 ppPPCAMode(i->Pin.EvCheck.amCounter);
2246 vex_printf("; bge nofail; lwz r30,");
2247 ppPPCAMode(i->Pin.EvCheck.amFailAddr);
2248 vex_printf("; mtctr r30; bctr; nofail:");
2249 return;
2250 case Pin_ProfInc:
2251 if (mode64) {
2252 vex_printf("(profInc) imm64-fixed5 r30,$NotKnownYet; ");
2253 vex_printf("ld r29,(r30); addi r29,r29,1; std r29,(r30)");
2254 } else {
2255 vex_printf("(profInc) imm32-fixed2 r30,$NotKnownYet; ");
2256 vex_printf("lwz r29,4(r30); addic. r29,r29,1; stw r29,4(r30)");
2257 vex_printf("lwz r29,0(r30); addze r29,r29; stw r29,0(r30)");
2258 }
2259 break;
2260 default:
2261 vex_printf("\nppPPCInstr: No such tag(%d)\n", (Int)i->tag);
2262 vpanic("ppPPCInstr");
2263 }
2264 }
2265
2266 /* --------- Helpers for register allocation. --------- */
2267
getRegUsage_PPCInstr(HRegUsage * u,PPCInstr * i,Bool mode64)2268 void getRegUsage_PPCInstr ( HRegUsage* u, PPCInstr* i, Bool mode64 )
2269 {
2270 initHRegUsage(u);
2271 switch (i->tag) {
2272 case Pin_LI:
2273 addHRegUse(u, HRmWrite, i->Pin.LI.dst);
2274 break;
2275 case Pin_Alu:
2276 addHRegUse(u, HRmRead, i->Pin.Alu.srcL);
2277 addRegUsage_PPCRH(u, i->Pin.Alu.srcR);
2278 addHRegUse(u, HRmWrite, i->Pin.Alu.dst);
2279 return;
2280 case Pin_Shft:
2281 addHRegUse(u, HRmRead, i->Pin.Shft.srcL);
2282 addRegUsage_PPCRH(u, i->Pin.Shft.srcR);
2283 addHRegUse(u, HRmWrite, i->Pin.Shft.dst);
2284 return;
2285 case Pin_AddSubC:
2286 addHRegUse(u, HRmWrite, i->Pin.AddSubC.dst);
2287 addHRegUse(u, HRmRead, i->Pin.AddSubC.srcL);
2288 addHRegUse(u, HRmRead, i->Pin.AddSubC.srcR);
2289 return;
2290 case Pin_Cmp:
2291 addHRegUse(u, HRmRead, i->Pin.Cmp.srcL);
2292 addRegUsage_PPCRH(u, i->Pin.Cmp.srcR);
2293 return;
2294 case Pin_Unary:
2295 addHRegUse(u, HRmWrite, i->Pin.Unary.dst);
2296 addHRegUse(u, HRmRead, i->Pin.Unary.src);
2297 return;
2298 case Pin_MulL:
2299 addHRegUse(u, HRmWrite, i->Pin.MulL.dst);
2300 addHRegUse(u, HRmRead, i->Pin.MulL.srcL);
2301 addHRegUse(u, HRmRead, i->Pin.MulL.srcR);
2302 return;
2303 case Pin_Div:
2304 addHRegUse(u, HRmWrite, i->Pin.Div.dst);
2305 addHRegUse(u, HRmRead, i->Pin.Div.srcL);
2306 addHRegUse(u, HRmRead, i->Pin.Div.srcR);
2307 return;
2308 case Pin_Call: {
2309 UInt argir;
2310 /* This is a bit subtle. */
2311 /* First off, claim it trashes all the caller-saved regs
2312 which fall within the register allocator's jurisdiction.
2313 These I believe to be:
2314 mode32: r3 to r12
2315 mode64: r3 to r10
2316 */
2317 /* XXXXXXXXXXXXXXXXX BUG! This doesn't say anything about the FP
2318 or Altivec registers. We get away with this ONLY because
2319 getAllocatableRegs_PPC gives the allocator callee-saved fp
2320 and Altivec regs, and no caller-save ones. */
2321 addHRegUse(u, HRmWrite, hregPPC_GPR3(mode64));
2322 addHRegUse(u, HRmWrite, hregPPC_GPR4(mode64));
2323 addHRegUse(u, HRmWrite, hregPPC_GPR5(mode64));
2324 addHRegUse(u, HRmWrite, hregPPC_GPR6(mode64));
2325 addHRegUse(u, HRmWrite, hregPPC_GPR7(mode64));
2326 addHRegUse(u, HRmWrite, hregPPC_GPR8(mode64));
2327 addHRegUse(u, HRmWrite, hregPPC_GPR9(mode64));
2328 addHRegUse(u, HRmWrite, hregPPC_GPR10(mode64));
2329 if (!mode64) {
2330 addHRegUse(u, HRmWrite, hregPPC_GPR11(mode64));
2331 addHRegUse(u, HRmWrite, hregPPC_GPR12(mode64));
2332 }
2333
2334 /* Now we have to state any parameter-carrying registers
2335 which might be read. This depends on the argiregs field. */
2336 argir = i->Pin.Call.argiregs;
2337 if (argir &(1<<10)) addHRegUse(u, HRmRead, hregPPC_GPR10(mode64));
2338 if (argir & (1<<9)) addHRegUse(u, HRmRead, hregPPC_GPR9(mode64));
2339 if (argir & (1<<8)) addHRegUse(u, HRmRead, hregPPC_GPR8(mode64));
2340 if (argir & (1<<7)) addHRegUse(u, HRmRead, hregPPC_GPR7(mode64));
2341 if (argir & (1<<6)) addHRegUse(u, HRmRead, hregPPC_GPR6(mode64));
2342 if (argir & (1<<5)) addHRegUse(u, HRmRead, hregPPC_GPR5(mode64));
2343 if (argir & (1<<4)) addHRegUse(u, HRmRead, hregPPC_GPR4(mode64));
2344 if (argir & (1<<3)) addHRegUse(u, HRmRead, hregPPC_GPR3(mode64));
2345
2346 vassert(0 == (argir & ~((1<<3)|(1<<4)|(1<<5)|(1<<6)
2347 |(1<<7)|(1<<8)|(1<<9)|(1<<10))));
2348
2349 /* Finally, there is the issue that the insn trashes a
2350 register because the literal target address has to be
2351 loaded into a register. %r10 seems a suitable victim.
2352 (Can't use %r0, as some insns interpret it as value zero). */
2353 addHRegUse(u, HRmWrite, hregPPC_GPR10(mode64));
2354 /* Upshot of this is that the assembler really must use %r10,
2355 and no other, as a destination temporary. */
2356 return;
2357 }
2358 /* XDirect/XIndir/XAssisted are also a bit subtle. They
2359 conditionally exit the block. Hence we only need to list (1)
2360 the registers that they read, and (2) the registers that they
2361 write in the case where the block is not exited. (2) is empty,
2362 hence only (1) is relevant here. */
2363 case Pin_XDirect:
2364 addRegUsage_PPCAMode(u, i->Pin.XDirect.amCIA);
2365 return;
2366 case Pin_XIndir:
2367 addHRegUse(u, HRmRead, i->Pin.XIndir.dstGA);
2368 addRegUsage_PPCAMode(u, i->Pin.XIndir.amCIA);
2369 return;
2370 case Pin_XAssisted:
2371 addHRegUse(u, HRmRead, i->Pin.XAssisted.dstGA);
2372 addRegUsage_PPCAMode(u, i->Pin.XAssisted.amCIA);
2373 return;
2374 case Pin_CMov:
2375 addRegUsage_PPCRI(u, i->Pin.CMov.src);
2376 addHRegUse(u, HRmWrite, i->Pin.CMov.dst);
2377 return;
2378 case Pin_Load:
2379 addRegUsage_PPCAMode(u, i->Pin.Load.src);
2380 addHRegUse(u, HRmWrite, i->Pin.Load.dst);
2381 return;
2382 case Pin_LoadL:
2383 addHRegUse(u, HRmRead, i->Pin.LoadL.src);
2384 addHRegUse(u, HRmWrite, i->Pin.LoadL.dst);
2385 return;
2386 case Pin_Store:
2387 addHRegUse(u, HRmRead, i->Pin.Store.src);
2388 addRegUsage_PPCAMode(u, i->Pin.Store.dst);
2389 return;
2390 case Pin_StoreC:
2391 addHRegUse(u, HRmRead, i->Pin.StoreC.src);
2392 addHRegUse(u, HRmRead, i->Pin.StoreC.dst);
2393 return;
2394 case Pin_Set:
2395 addHRegUse(u, HRmWrite, i->Pin.Set.dst);
2396 return;
2397 case Pin_MfCR:
2398 addHRegUse(u, HRmWrite, i->Pin.MfCR.dst);
2399 return;
2400 case Pin_MFence:
2401 return;
2402
2403 case Pin_FpUnary:
2404 addHRegUse(u, HRmWrite, i->Pin.FpUnary.dst);
2405 addHRegUse(u, HRmRead, i->Pin.FpUnary.src);
2406 return;
2407 case Pin_FpBinary:
2408 addHRegUse(u, HRmWrite, i->Pin.FpBinary.dst);
2409 addHRegUse(u, HRmRead, i->Pin.FpBinary.srcL);
2410 addHRegUse(u, HRmRead, i->Pin.FpBinary.srcR);
2411 return;
2412 case Pin_FpMulAcc:
2413 addHRegUse(u, HRmWrite, i->Pin.FpMulAcc.dst);
2414 addHRegUse(u, HRmRead, i->Pin.FpMulAcc.srcML);
2415 addHRegUse(u, HRmRead, i->Pin.FpMulAcc.srcMR);
2416 addHRegUse(u, HRmRead, i->Pin.FpMulAcc.srcAcc);
2417 return;
2418 case Pin_FpLdSt:
2419 addHRegUse(u, (i->Pin.FpLdSt.isLoad ? HRmWrite : HRmRead),
2420 i->Pin.FpLdSt.reg);
2421 addRegUsage_PPCAMode(u, i->Pin.FpLdSt.addr);
2422 return;
2423 case Pin_FpSTFIW:
2424 addHRegUse(u, HRmRead, i->Pin.FpSTFIW.addr);
2425 addHRegUse(u, HRmRead, i->Pin.FpSTFIW.data);
2426 return;
2427 case Pin_FpRSP:
2428 addHRegUse(u, HRmWrite, i->Pin.FpRSP.dst);
2429 addHRegUse(u, HRmRead, i->Pin.FpRSP.src);
2430 return;
2431 case Pin_FpCftI:
2432 addHRegUse(u, HRmWrite, i->Pin.FpCftI.dst);
2433 addHRegUse(u, HRmRead, i->Pin.FpCftI.src);
2434 return;
2435 case Pin_FpCMov:
2436 addHRegUse(u, HRmModify, i->Pin.FpCMov.dst);
2437 addHRegUse(u, HRmRead, i->Pin.FpCMov.src);
2438 return;
2439 case Pin_FpLdFPSCR:
2440 addHRegUse(u, HRmRead, i->Pin.FpLdFPSCR.src);
2441 return;
2442 case Pin_FpCmp:
2443 addHRegUse(u, HRmWrite, i->Pin.FpCmp.dst);
2444 addHRegUse(u, HRmRead, i->Pin.FpCmp.srcL);
2445 addHRegUse(u, HRmRead, i->Pin.FpCmp.srcR);
2446 return;
2447
2448 case Pin_RdWrLR:
2449 addHRegUse(u, (i->Pin.RdWrLR.wrLR ? HRmRead : HRmWrite),
2450 i->Pin.RdWrLR.gpr);
2451 return;
2452
2453 case Pin_AvLdSt:
2454 addHRegUse(u, (i->Pin.AvLdSt.isLoad ? HRmWrite : HRmRead),
2455 i->Pin.AvLdSt.reg);
2456 if (i->Pin.AvLdSt.addr->tag == Pam_IR)
2457 addHRegUse(u, HRmWrite, hregPPC_GPR30(mode64));
2458 addRegUsage_PPCAMode(u, i->Pin.AvLdSt.addr);
2459 return;
2460 case Pin_AvUnary:
2461 addHRegUse(u, HRmWrite, i->Pin.AvUnary.dst);
2462 addHRegUse(u, HRmRead, i->Pin.AvUnary.src);
2463 return;
2464 case Pin_AvBinary:
2465 if (i->Pin.AvBinary.op == Pav_XOR
2466 && sameHReg(i->Pin.AvBinary.dst, i->Pin.AvBinary.srcL)
2467 && sameHReg(i->Pin.AvBinary.dst, i->Pin.AvBinary.srcR)) {
2468 /* reg-alloc needs to understand 'xor r,r,r' as a write of r */
2469 /* (as opposed to a rite of passage :-) */
2470 addHRegUse(u, HRmWrite, i->Pin.AvBinary.dst);
2471 } else {
2472 addHRegUse(u, HRmWrite, i->Pin.AvBinary.dst);
2473 addHRegUse(u, HRmRead, i->Pin.AvBinary.srcL);
2474 addHRegUse(u, HRmRead, i->Pin.AvBinary.srcR);
2475 }
2476 return;
2477 case Pin_AvBin8x16:
2478 addHRegUse(u, HRmWrite, i->Pin.AvBin8x16.dst);
2479 addHRegUse(u, HRmRead, i->Pin.AvBin8x16.srcL);
2480 addHRegUse(u, HRmRead, i->Pin.AvBin8x16.srcR);
2481 return;
2482 case Pin_AvBin16x8:
2483 addHRegUse(u, HRmWrite, i->Pin.AvBin16x8.dst);
2484 addHRegUse(u, HRmRead, i->Pin.AvBin16x8.srcL);
2485 addHRegUse(u, HRmRead, i->Pin.AvBin16x8.srcR);
2486 return;
2487 case Pin_AvBin32x4:
2488 addHRegUse(u, HRmWrite, i->Pin.AvBin32x4.dst);
2489 addHRegUse(u, HRmRead, i->Pin.AvBin32x4.srcL);
2490 addHRegUse(u, HRmRead, i->Pin.AvBin32x4.srcR);
2491 return;
2492 case Pin_AvBin64x2:
2493 addHRegUse(u, HRmWrite, i->Pin.AvBin64x2.dst);
2494 addHRegUse(u, HRmRead, i->Pin.AvBin64x2.srcL);
2495 addHRegUse(u, HRmRead, i->Pin.AvBin64x2.srcR);
2496 return;
2497 case Pin_AvBin32Fx4:
2498 addHRegUse(u, HRmWrite, i->Pin.AvBin32Fx4.dst);
2499 addHRegUse(u, HRmRead, i->Pin.AvBin32Fx4.srcL);
2500 addHRegUse(u, HRmRead, i->Pin.AvBin32Fx4.srcR);
2501 if (i->Pin.AvBin32Fx4.op == Pavfp_MULF)
2502 addHRegUse(u, HRmWrite, hregPPC_VR29());
2503 return;
2504 case Pin_AvUn32Fx4:
2505 addHRegUse(u, HRmWrite, i->Pin.AvUn32Fx4.dst);
2506 addHRegUse(u, HRmRead, i->Pin.AvUn32Fx4.src);
2507 return;
2508 case Pin_AvPerm:
2509 addHRegUse(u, HRmWrite, i->Pin.AvPerm.dst);
2510 addHRegUse(u, HRmRead, i->Pin.AvPerm.srcL);
2511 addHRegUse(u, HRmRead, i->Pin.AvPerm.srcR);
2512 addHRegUse(u, HRmRead, i->Pin.AvPerm.ctl);
2513 return;
2514 case Pin_AvSel:
2515 addHRegUse(u, HRmWrite, i->Pin.AvSel.dst);
2516 addHRegUse(u, HRmRead, i->Pin.AvSel.ctl);
2517 addHRegUse(u, HRmRead, i->Pin.AvSel.srcL);
2518 addHRegUse(u, HRmRead, i->Pin.AvSel.srcR);
2519 return;
2520 case Pin_AvShlDbl:
2521 addHRegUse(u, HRmWrite, i->Pin.AvShlDbl.dst);
2522 addHRegUse(u, HRmRead, i->Pin.AvShlDbl.srcL);
2523 addHRegUse(u, HRmRead, i->Pin.AvShlDbl.srcR);
2524 return;
2525 case Pin_AvSplat:
2526 addHRegUse(u, HRmWrite, i->Pin.AvSplat.dst);
2527 addRegUsage_PPCVI5s(u, i->Pin.AvSplat.src);
2528 return;
2529 case Pin_AvCMov:
2530 addHRegUse(u, HRmModify, i->Pin.AvCMov.dst);
2531 addHRegUse(u, HRmRead, i->Pin.AvCMov.src);
2532 return;
2533 case Pin_AvLdVSCR:
2534 addHRegUse(u, HRmRead, i->Pin.AvLdVSCR.src);
2535 return;
2536 case Pin_AvCipherV128Unary:
2537 addHRegUse(u, HRmWrite, i->Pin.AvCipherV128Unary.dst);
2538 addHRegUse(u, HRmRead, i->Pin.AvCipherV128Unary.src);
2539 return;
2540 case Pin_AvCipherV128Binary:
2541 addHRegUse(u, HRmWrite, i->Pin.AvCipherV128Binary.dst);
2542 addHRegUse(u, HRmRead, i->Pin.AvCipherV128Binary.srcL);
2543 addHRegUse(u, HRmRead, i->Pin.AvCipherV128Binary.srcR);
2544 return;
2545 case Pin_AvHashV128Binary:
2546 addHRegUse(u, HRmWrite, i->Pin.AvHashV128Binary.dst);
2547 addHRegUse(u, HRmRead, i->Pin.AvHashV128Binary.src);
2548 addRegUsage_PPCRI(u, i->Pin.AvHashV128Binary.s_field);
2549 return;
2550 case Pin_AvBCDV128Trinary:
2551 addHRegUse(u, HRmWrite, i->Pin.AvBCDV128Trinary.dst);
2552 addHRegUse(u, HRmRead, i->Pin.AvBCDV128Trinary.src1);
2553 addHRegUse(u, HRmRead, i->Pin.AvBCDV128Trinary.src2);
2554 addRegUsage_PPCRI(u, i->Pin.AvBCDV128Trinary.ps);
2555 return;
2556 case Pin_Dfp64Unary:
2557 addHRegUse(u, HRmWrite, i->Pin.Dfp64Unary.dst);
2558 addHRegUse(u, HRmRead, i->Pin.Dfp64Unary.src);
2559 return;
2560 case Pin_Dfp64Binary:
2561 addHRegUse(u, HRmWrite, i->Pin.Dfp64Binary.dst);
2562 addHRegUse(u, HRmRead, i->Pin.Dfp64Binary.srcL);
2563 addHRegUse(u, HRmRead, i->Pin.Dfp64Binary.srcR);
2564 return;
2565 case Pin_DfpShift:
2566 addRegUsage_PPCRI(u, i->Pin.DfpShift.shift);
2567 addHRegUse(u, HRmWrite, i->Pin.DfpShift.src);
2568 addHRegUse(u, HRmWrite, i->Pin.DfpShift.dst);
2569 return;
2570 case Pin_Dfp128Unary:
2571 addHRegUse(u, HRmWrite, i->Pin.Dfp128Unary.dst_hi);
2572 addHRegUse(u, HRmWrite, i->Pin.Dfp128Unary.dst_lo);
2573 addHRegUse(u, HRmRead, i->Pin.Dfp128Unary.src_hi);
2574 addHRegUse(u, HRmRead, i->Pin.Dfp128Unary.src_lo);
2575 return;
2576 case Pin_Dfp128Binary:
2577 addHRegUse(u, HRmWrite, i->Pin.Dfp128Binary.dst_hi);
2578 addHRegUse(u, HRmWrite, i->Pin.Dfp128Binary.dst_lo);
2579 addHRegUse(u, HRmRead, i->Pin.Dfp128Binary.srcR_hi);
2580 addHRegUse(u, HRmRead, i->Pin.Dfp128Binary.srcR_lo);
2581 return;
2582 case Pin_DfpRound:
2583 addHRegUse(u, HRmWrite, i->Pin.DfpRound.dst);
2584 addHRegUse(u, HRmRead, i->Pin.DfpRound.src);
2585 return;
2586 case Pin_DfpRound128:
2587 addHRegUse(u, HRmWrite, i->Pin.DfpRound128.dst_hi);
2588 addHRegUse(u, HRmWrite, i->Pin.DfpRound128.dst_lo);
2589 addHRegUse(u, HRmRead, i->Pin.DfpRound128.src_hi);
2590 addHRegUse(u, HRmRead, i->Pin.DfpRound128.src_lo);
2591 return;
2592 case Pin_DfpQuantize:
2593 addRegUsage_PPCRI(u, i->Pin.DfpQuantize.rmc);
2594 addHRegUse(u, HRmWrite, i->Pin.DfpQuantize.dst);
2595 addHRegUse(u, HRmRead, i->Pin.DfpQuantize.srcL);
2596 addHRegUse(u, HRmRead, i->Pin.DfpQuantize.srcR);
2597 return;
2598 case Pin_DfpQuantize128:
2599 addHRegUse(u, HRmWrite, i->Pin.DfpQuantize128.dst_hi);
2600 addHRegUse(u, HRmWrite, i->Pin.DfpQuantize128.dst_lo);
2601 addHRegUse(u, HRmRead, i->Pin.DfpQuantize128.src_hi);
2602 addHRegUse(u, HRmRead, i->Pin.DfpQuantize128.src_lo);
2603 return;
2604 case Pin_DfpShift128:
2605 addRegUsage_PPCRI(u, i->Pin.DfpShift128.shift);
2606 addHRegUse(u, HRmWrite, i->Pin.DfpShift128.src_hi);
2607 addHRegUse(u, HRmWrite, i->Pin.DfpShift128.src_lo);
2608 addHRegUse(u, HRmWrite, i->Pin.DfpShift128.dst_hi);
2609 addHRegUse(u, HRmWrite, i->Pin.DfpShift128.dst_lo);
2610 return;
2611 case Pin_DfpD128toD64:
2612 addHRegUse(u, HRmWrite, i->Pin.DfpD128toD64.src_hi);
2613 addHRegUse(u, HRmWrite, i->Pin.DfpD128toD64.src_lo);
2614 addHRegUse(u, HRmWrite, i->Pin.DfpD128toD64.dst);
2615 return;
2616 case Pin_DfpI64StoD128:
2617 addHRegUse(u, HRmWrite, i->Pin.DfpI64StoD128.src);
2618 addHRegUse(u, HRmWrite, i->Pin.DfpI64StoD128.dst_hi);
2619 addHRegUse(u, HRmWrite, i->Pin.DfpI64StoD128.dst_lo);
2620 return;
2621 case Pin_ExtractExpD128:
2622 addHRegUse(u, HRmWrite, i->Pin.ExtractExpD128.dst);
2623 addHRegUse(u, HRmRead, i->Pin.ExtractExpD128.src_hi);
2624 addHRegUse(u, HRmRead, i->Pin.ExtractExpD128.src_lo);
2625 return;
2626 case Pin_InsertExpD128:
2627 addHRegUse(u, HRmWrite, i->Pin.InsertExpD128.dst_hi);
2628 addHRegUse(u, HRmWrite, i->Pin.InsertExpD128.dst_lo);
2629 addHRegUse(u, HRmRead, i->Pin.InsertExpD128.srcL);
2630 addHRegUse(u, HRmRead, i->Pin.InsertExpD128.srcR_hi);
2631 addHRegUse(u, HRmRead, i->Pin.InsertExpD128.srcR_lo);
2632 return;
2633 case Pin_Dfp64Cmp:
2634 addHRegUse(u, HRmWrite, i->Pin.Dfp64Cmp.dst);
2635 addHRegUse(u, HRmRead, i->Pin.Dfp64Cmp.srcL);
2636 addHRegUse(u, HRmRead, i->Pin.Dfp64Cmp.srcR);
2637 return;
2638 case Pin_Dfp128Cmp:
2639 addHRegUse(u, HRmWrite, i->Pin.Dfp128Cmp.dst);
2640 addHRegUse(u, HRmRead, i->Pin.Dfp128Cmp.srcL_hi);
2641 addHRegUse(u, HRmRead, i->Pin.Dfp128Cmp.srcL_lo);
2642 addHRegUse(u, HRmRead, i->Pin.Dfp128Cmp.srcR_hi);
2643 addHRegUse(u, HRmRead, i->Pin.Dfp128Cmp.srcR_lo);
2644 return;
2645 case Pin_EvCheck:
2646 /* We expect both amodes only to mention the GSP (r31), so this
2647 is in fact pointless, since GSP isn't allocatable, but
2648 anyway.. */
2649 addRegUsage_PPCAMode(u, i->Pin.EvCheck.amCounter);
2650 addRegUsage_PPCAMode(u, i->Pin.EvCheck.amFailAddr);
2651 addHRegUse(u, HRmWrite, hregPPC_GPR30(mode64)); /* also unavail to RA */
2652 return;
2653 case Pin_ProfInc:
2654 addHRegUse(u, HRmWrite, hregPPC_GPR29(mode64));
2655 addHRegUse(u, HRmWrite, hregPPC_GPR30(mode64));
2656 return;
2657 default:
2658 ppPPCInstr(i, mode64);
2659 vpanic("getRegUsage_PPCInstr");
2660 }
2661 }
2662
2663 /* local helper */
mapReg(HRegRemap * m,HReg * r)2664 static void mapReg( HRegRemap* m, HReg* r )
2665 {
2666 *r = lookupHRegRemap(m, *r);
2667 }
2668
mapRegs_PPCInstr(HRegRemap * m,PPCInstr * i,Bool mode64)2669 void mapRegs_PPCInstr ( HRegRemap* m, PPCInstr* i, Bool mode64 )
2670 {
2671 switch (i->tag) {
2672 case Pin_LI:
2673 mapReg(m, &i->Pin.LI.dst);
2674 return;
2675 case Pin_Alu:
2676 mapReg(m, &i->Pin.Alu.dst);
2677 mapReg(m, &i->Pin.Alu.srcL);
2678 mapRegs_PPCRH(m, i->Pin.Alu.srcR);
2679 return;
2680 case Pin_Shft:
2681 mapReg(m, &i->Pin.Shft.dst);
2682 mapReg(m, &i->Pin.Shft.srcL);
2683 mapRegs_PPCRH(m, i->Pin.Shft.srcR);
2684 return;
2685 case Pin_AddSubC:
2686 mapReg(m, &i->Pin.AddSubC.dst);
2687 mapReg(m, &i->Pin.AddSubC.srcL);
2688 mapReg(m, &i->Pin.AddSubC.srcR);
2689 return;
2690 case Pin_Cmp:
2691 mapReg(m, &i->Pin.Cmp.srcL);
2692 mapRegs_PPCRH(m, i->Pin.Cmp.srcR);
2693 return;
2694 case Pin_Unary:
2695 mapReg(m, &i->Pin.Unary.dst);
2696 mapReg(m, &i->Pin.Unary.src);
2697 return;
2698 case Pin_MulL:
2699 mapReg(m, &i->Pin.MulL.dst);
2700 mapReg(m, &i->Pin.MulL.srcL);
2701 mapReg(m, &i->Pin.MulL.srcR);
2702 return;
2703 case Pin_Div:
2704 mapReg(m, &i->Pin.Div.dst);
2705 mapReg(m, &i->Pin.Div.srcL);
2706 mapReg(m, &i->Pin.Div.srcR);
2707 return;
2708 case Pin_Call:
2709 return;
2710 case Pin_XDirect:
2711 mapRegs_PPCAMode(m, i->Pin.XDirect.amCIA);
2712 return;
2713 case Pin_XIndir:
2714 mapReg(m, &i->Pin.XIndir.dstGA);
2715 mapRegs_PPCAMode(m, i->Pin.XIndir.amCIA);
2716 return;
2717 case Pin_XAssisted:
2718 mapReg(m, &i->Pin.XAssisted.dstGA);
2719 mapRegs_PPCAMode(m, i->Pin.XAssisted.amCIA);
2720 return;
2721 case Pin_CMov:
2722 mapRegs_PPCRI(m, i->Pin.CMov.src);
2723 mapReg(m, &i->Pin.CMov.dst);
2724 return;
2725 case Pin_Load:
2726 mapRegs_PPCAMode(m, i->Pin.Load.src);
2727 mapReg(m, &i->Pin.Load.dst);
2728 return;
2729 case Pin_LoadL:
2730 mapReg(m, &i->Pin.LoadL.src);
2731 mapReg(m, &i->Pin.LoadL.dst);
2732 return;
2733 case Pin_Store:
2734 mapReg(m, &i->Pin.Store.src);
2735 mapRegs_PPCAMode(m, i->Pin.Store.dst);
2736 return;
2737 case Pin_StoreC:
2738 mapReg(m, &i->Pin.StoreC.src);
2739 mapReg(m, &i->Pin.StoreC.dst);
2740 return;
2741 case Pin_Set:
2742 mapReg(m, &i->Pin.Set.dst);
2743 return;
2744 case Pin_MfCR:
2745 mapReg(m, &i->Pin.MfCR.dst);
2746 return;
2747 case Pin_MFence:
2748 return;
2749 case Pin_FpUnary:
2750 mapReg(m, &i->Pin.FpUnary.dst);
2751 mapReg(m, &i->Pin.FpUnary.src);
2752 return;
2753 case Pin_FpBinary:
2754 mapReg(m, &i->Pin.FpBinary.dst);
2755 mapReg(m, &i->Pin.FpBinary.srcL);
2756 mapReg(m, &i->Pin.FpBinary.srcR);
2757 return;
2758 case Pin_FpMulAcc:
2759 mapReg(m, &i->Pin.FpMulAcc.dst);
2760 mapReg(m, &i->Pin.FpMulAcc.srcML);
2761 mapReg(m, &i->Pin.FpMulAcc.srcMR);
2762 mapReg(m, &i->Pin.FpMulAcc.srcAcc);
2763 return;
2764 case Pin_FpLdSt:
2765 mapReg(m, &i->Pin.FpLdSt.reg);
2766 mapRegs_PPCAMode(m, i->Pin.FpLdSt.addr);
2767 return;
2768 case Pin_FpSTFIW:
2769 mapReg(m, &i->Pin.FpSTFIW.addr);
2770 mapReg(m, &i->Pin.FpSTFIW.data);
2771 return;
2772 case Pin_FpRSP:
2773 mapReg(m, &i->Pin.FpRSP.dst);
2774 mapReg(m, &i->Pin.FpRSP.src);
2775 return;
2776 case Pin_FpCftI:
2777 mapReg(m, &i->Pin.FpCftI.dst);
2778 mapReg(m, &i->Pin.FpCftI.src);
2779 return;
2780 case Pin_FpCMov:
2781 mapReg(m, &i->Pin.FpCMov.dst);
2782 mapReg(m, &i->Pin.FpCMov.src);
2783 return;
2784 case Pin_FpLdFPSCR:
2785 mapReg(m, &i->Pin.FpLdFPSCR.src);
2786 return;
2787 case Pin_FpCmp:
2788 mapReg(m, &i->Pin.FpCmp.dst);
2789 mapReg(m, &i->Pin.FpCmp.srcL);
2790 mapReg(m, &i->Pin.FpCmp.srcR);
2791 return;
2792 case Pin_RdWrLR:
2793 mapReg(m, &i->Pin.RdWrLR.gpr);
2794 return;
2795 case Pin_AvLdSt:
2796 mapReg(m, &i->Pin.AvLdSt.reg);
2797 mapRegs_PPCAMode(m, i->Pin.AvLdSt.addr);
2798 return;
2799 case Pin_AvUnary:
2800 mapReg(m, &i->Pin.AvUnary.dst);
2801 mapReg(m, &i->Pin.AvUnary.src);
2802 return;
2803 case Pin_AvBinary:
2804 mapReg(m, &i->Pin.AvBinary.dst);
2805 mapReg(m, &i->Pin.AvBinary.srcL);
2806 mapReg(m, &i->Pin.AvBinary.srcR);
2807 return;
2808 case Pin_AvBin8x16:
2809 mapReg(m, &i->Pin.AvBin8x16.dst);
2810 mapReg(m, &i->Pin.AvBin8x16.srcL);
2811 mapReg(m, &i->Pin.AvBin8x16.srcR);
2812 return;
2813 case Pin_AvBin16x8:
2814 mapReg(m, &i->Pin.AvBin16x8.dst);
2815 mapReg(m, &i->Pin.AvBin16x8.srcL);
2816 mapReg(m, &i->Pin.AvBin16x8.srcR);
2817 return;
2818 case Pin_AvBin32x4:
2819 mapReg(m, &i->Pin.AvBin32x4.dst);
2820 mapReg(m, &i->Pin.AvBin32x4.srcL);
2821 mapReg(m, &i->Pin.AvBin32x4.srcR);
2822 return;
2823 case Pin_AvBin64x2:
2824 mapReg(m, &i->Pin.AvBin64x2.dst);
2825 mapReg(m, &i->Pin.AvBin64x2.srcL);
2826 mapReg(m, &i->Pin.AvBin64x2.srcR);
2827 return;
2828 case Pin_AvBin32Fx4:
2829 mapReg(m, &i->Pin.AvBin32Fx4.dst);
2830 mapReg(m, &i->Pin.AvBin32Fx4.srcL);
2831 mapReg(m, &i->Pin.AvBin32Fx4.srcR);
2832 return;
2833 case Pin_AvUn32Fx4:
2834 mapReg(m, &i->Pin.AvUn32Fx4.dst);
2835 mapReg(m, &i->Pin.AvUn32Fx4.src);
2836 return;
2837 case Pin_AvPerm:
2838 mapReg(m, &i->Pin.AvPerm.dst);
2839 mapReg(m, &i->Pin.AvPerm.srcL);
2840 mapReg(m, &i->Pin.AvPerm.srcR);
2841 mapReg(m, &i->Pin.AvPerm.ctl);
2842 return;
2843 case Pin_AvSel:
2844 mapReg(m, &i->Pin.AvSel.dst);
2845 mapReg(m, &i->Pin.AvSel.srcL);
2846 mapReg(m, &i->Pin.AvSel.srcR);
2847 mapReg(m, &i->Pin.AvSel.ctl);
2848 return;
2849 case Pin_AvShlDbl:
2850 mapReg(m, &i->Pin.AvShlDbl.dst);
2851 mapReg(m, &i->Pin.AvShlDbl.srcL);
2852 mapReg(m, &i->Pin.AvShlDbl.srcR);
2853 return;
2854 case Pin_AvSplat:
2855 mapReg(m, &i->Pin.AvSplat.dst);
2856 mapRegs_PPCVI5s(m, i->Pin.AvSplat.src);
2857 return;
2858 case Pin_AvCMov:
2859 mapReg(m, &i->Pin.AvCMov.dst);
2860 mapReg(m, &i->Pin.AvCMov.src);
2861 return;
2862 case Pin_AvLdVSCR:
2863 mapReg(m, &i->Pin.AvLdVSCR.src);
2864 return;
2865 case Pin_AvCipherV128Unary:
2866 mapReg(m, &i->Pin.AvCipherV128Unary.dst);
2867 mapReg(m, &i->Pin.AvCipherV128Unary.src);
2868 return;
2869 case Pin_AvCipherV128Binary:
2870 mapReg(m, &i->Pin.AvCipherV128Binary.dst);
2871 mapReg(m, &i->Pin.AvCipherV128Binary.srcL);
2872 mapReg(m, &i->Pin.AvCipherV128Binary.srcR);
2873 return;
2874 case Pin_AvHashV128Binary:
2875 mapRegs_PPCRI(m, i->Pin.AvHashV128Binary.s_field);
2876 mapReg(m, &i->Pin.AvHashV128Binary.dst);
2877 mapReg(m, &i->Pin.AvHashV128Binary.src);
2878 return;
2879 case Pin_AvBCDV128Trinary:
2880 mapReg(m, &i->Pin.AvBCDV128Trinary.dst);
2881 mapReg(m, &i->Pin.AvBCDV128Trinary.src1);
2882 mapReg(m, &i->Pin.AvBCDV128Trinary.src2);
2883 mapRegs_PPCRI(m, i->Pin.AvBCDV128Trinary.ps);
2884 return;
2885 case Pin_Dfp64Unary:
2886 mapReg(m, &i->Pin.Dfp64Unary.dst);
2887 mapReg(m, &i->Pin.Dfp64Unary.src);
2888 return;
2889 case Pin_Dfp64Binary:
2890 mapReg(m, &i->Pin.Dfp64Binary.dst);
2891 mapReg(m, &i->Pin.Dfp64Binary.srcL);
2892 mapReg(m, &i->Pin.Dfp64Binary.srcR);
2893 return;
2894 case Pin_DfpShift:
2895 mapRegs_PPCRI(m, i->Pin.DfpShift.shift);
2896 mapReg(m, &i->Pin.DfpShift.src);
2897 mapReg(m, &i->Pin.DfpShift.dst);
2898 return;
2899 case Pin_Dfp128Unary:
2900 mapReg(m, &i->Pin.Dfp128Unary.dst_hi);
2901 mapReg(m, &i->Pin.Dfp128Unary.dst_lo);
2902 mapReg(m, &i->Pin.Dfp128Unary.src_hi);
2903 mapReg(m, &i->Pin.Dfp128Unary.src_lo);
2904 return;
2905 case Pin_Dfp128Binary:
2906 mapReg(m, &i->Pin.Dfp128Binary.dst_hi);
2907 mapReg(m, &i->Pin.Dfp128Binary.dst_lo);
2908 mapReg(m, &i->Pin.Dfp128Binary.srcR_hi);
2909 mapReg(m, &i->Pin.Dfp128Binary.srcR_lo);
2910 return;
2911 case Pin_DfpShift128:
2912 mapRegs_PPCRI(m, i->Pin.DfpShift128.shift);
2913 mapReg(m, &i->Pin.DfpShift128.src_hi);
2914 mapReg(m, &i->Pin.DfpShift128.src_lo);
2915 mapReg(m, &i->Pin.DfpShift128.dst_hi);
2916 mapReg(m, &i->Pin.DfpShift128.dst_lo);
2917 return;
2918 case Pin_DfpRound:
2919 mapReg(m, &i->Pin.DfpRound.dst);
2920 mapReg(m, &i->Pin.DfpRound.src);
2921 return;
2922 case Pin_DfpRound128:
2923 mapReg(m, &i->Pin.DfpRound128.dst_hi);
2924 mapReg(m, &i->Pin.DfpRound128.dst_lo);
2925 mapReg(m, &i->Pin.DfpRound128.src_hi);
2926 mapReg(m, &i->Pin.DfpRound128.src_lo);
2927 return;
2928 case Pin_DfpQuantize:
2929 mapRegs_PPCRI(m, i->Pin.DfpQuantize.rmc);
2930 mapReg(m, &i->Pin.DfpQuantize.dst);
2931 mapReg(m, &i->Pin.DfpQuantize.srcL);
2932 mapReg(m, &i->Pin.DfpQuantize.srcR);
2933 return;
2934 case Pin_DfpQuantize128:
2935 mapRegs_PPCRI(m, i->Pin.DfpQuantize128.rmc);
2936 mapReg(m, &i->Pin.DfpQuantize128.dst_hi);
2937 mapReg(m, &i->Pin.DfpQuantize128.dst_lo);
2938 mapReg(m, &i->Pin.DfpQuantize128.src_hi);
2939 mapReg(m, &i->Pin.DfpQuantize128.src_lo);
2940 return;
2941 case Pin_DfpD128toD64:
2942 mapReg(m, &i->Pin.DfpD128toD64.src_hi);
2943 mapReg(m, &i->Pin.DfpD128toD64.src_lo);
2944 mapReg(m, &i->Pin.DfpD128toD64.dst);
2945 return;
2946 case Pin_DfpI64StoD128:
2947 mapReg(m, &i->Pin.DfpI64StoD128.src);
2948 mapReg(m, &i->Pin.DfpI64StoD128.dst_hi);
2949 mapReg(m, &i->Pin.DfpI64StoD128.dst_lo);
2950 return;
2951 case Pin_ExtractExpD128:
2952 mapReg(m, &i->Pin.ExtractExpD128.dst);
2953 mapReg(m, &i->Pin.ExtractExpD128.src_hi);
2954 mapReg(m, &i->Pin.ExtractExpD128.src_lo);
2955 return;
2956 case Pin_InsertExpD128:
2957 mapReg(m, &i->Pin.InsertExpD128.dst_hi);
2958 mapReg(m, &i->Pin.InsertExpD128.dst_lo);
2959 mapReg(m, &i->Pin.InsertExpD128.srcL);
2960 mapReg(m, &i->Pin.InsertExpD128.srcR_hi);
2961 mapReg(m, &i->Pin.InsertExpD128.srcR_lo);
2962 return;
2963 case Pin_Dfp64Cmp:
2964 mapReg(m, &i->Pin.Dfp64Cmp.dst);
2965 mapReg(m, &i->Pin.Dfp64Cmp.srcL);
2966 mapReg(m, &i->Pin.Dfp64Cmp.srcR);
2967 return;
2968 case Pin_Dfp128Cmp:
2969 mapReg(m, &i->Pin.Dfp128Cmp.dst);
2970 mapReg(m, &i->Pin.Dfp128Cmp.srcL_hi);
2971 mapReg(m, &i->Pin.Dfp128Cmp.srcL_lo);
2972 mapReg(m, &i->Pin.Dfp128Cmp.srcR_hi);
2973 mapReg(m, &i->Pin.Dfp128Cmp.srcR_lo);
2974 return;
2975 case Pin_EvCheck:
2976 /* We expect both amodes only to mention the GSP (r31), so this
2977 is in fact pointless, since GSP isn't allocatable, but
2978 anyway.. */
2979 mapRegs_PPCAMode(m, i->Pin.EvCheck.amCounter);
2980 mapRegs_PPCAMode(m, i->Pin.EvCheck.amFailAddr);
2981 return;
2982 case Pin_ProfInc:
2983 /* hardwires r29 and r30 -- nothing to modify. */
2984 return;
2985 default:
2986 ppPPCInstr(i, mode64);
2987 vpanic("mapRegs_PPCInstr");
2988 }
2989 }
2990
2991 /* Figure out if i represents a reg-reg move, and if so assign the
2992 source and destination to *src and *dst. If in doubt say No. Used
2993 by the register allocator to do move coalescing.
2994 */
isMove_PPCInstr(PPCInstr * i,HReg * src,HReg * dst)2995 Bool isMove_PPCInstr ( PPCInstr* i, HReg* src, HReg* dst )
2996 {
2997 /* Moves between integer regs */
2998 if (i->tag == Pin_Alu) {
2999 // or Rd,Rs,Rs == mr Rd,Rs
3000 if (i->Pin.Alu.op != Palu_OR)
3001 return False;
3002 if (i->Pin.Alu.srcR->tag != Prh_Reg)
3003 return False;
3004 if (! sameHReg(i->Pin.Alu.srcR->Prh.Reg.reg, i->Pin.Alu.srcL))
3005 return False;
3006 *src = i->Pin.Alu.srcL;
3007 *dst = i->Pin.Alu.dst;
3008 return True;
3009 }
3010 /* Moves between FP regs */
3011 if (i->tag == Pin_FpUnary) {
3012 if (i->Pin.FpUnary.op != Pfp_MOV)
3013 return False;
3014 *src = i->Pin.FpUnary.src;
3015 *dst = i->Pin.FpUnary.dst;
3016 return True;
3017 }
3018 return False;
3019 }
3020
3021
3022 /* Generate ppc spill/reload instructions under the direction of the
3023 register allocator. Note it's critical these don't write the
3024 condition codes. */
3025
genSpill_PPC(HInstr ** i1,HInstr ** i2,HReg rreg,Int offsetB,Bool mode64)3026 void genSpill_PPC ( /*OUT*/HInstr** i1, /*OUT*/HInstr** i2,
3027 HReg rreg, Int offsetB, Bool mode64 )
3028 {
3029 PPCAMode* am;
3030 vassert(!hregIsVirtual(rreg));
3031 *i1 = *i2 = NULL;
3032 am = PPCAMode_IR( offsetB, GuestStatePtr(mode64) );
3033 switch (hregClass(rreg)) {
3034 case HRcInt64:
3035 vassert(mode64);
3036 *i1 = PPCInstr_Store( 8, am, rreg, mode64 );
3037 return;
3038 case HRcInt32:
3039 vassert(!mode64);
3040 *i1 = PPCInstr_Store( 4, am, rreg, mode64 );
3041 return;
3042 case HRcFlt64:
3043 *i1 = PPCInstr_FpLdSt ( False/*store*/, 8, rreg, am );
3044 return;
3045 case HRcVec128:
3046 // XXX: GPR30 used as spill register to kludge AltiVec
3047 // AMode_IR
3048 *i1 = PPCInstr_AvLdSt ( False/*store*/, 16, rreg, am );
3049 return;
3050 default:
3051 ppHRegClass(hregClass(rreg));
3052 vpanic("genSpill_PPC: unimplemented regclass");
3053 }
3054 }
3055
genReload_PPC(HInstr ** i1,HInstr ** i2,HReg rreg,Int offsetB,Bool mode64)3056 void genReload_PPC ( /*OUT*/HInstr** i1, /*OUT*/HInstr** i2,
3057 HReg rreg, Int offsetB, Bool mode64 )
3058 {
3059 PPCAMode* am;
3060 vassert(!hregIsVirtual(rreg));
3061 *i1 = *i2 = NULL;
3062 am = PPCAMode_IR( offsetB, GuestStatePtr(mode64) );
3063 switch (hregClass(rreg)) {
3064 case HRcInt64:
3065 vassert(mode64);
3066 *i1 = PPCInstr_Load( 8, rreg, am, mode64 );
3067 return;
3068 case HRcInt32:
3069 vassert(!mode64);
3070 *i1 = PPCInstr_Load( 4, rreg, am, mode64 );
3071 return;
3072 case HRcFlt64:
3073 *i1 = PPCInstr_FpLdSt ( True/*load*/, 8, rreg, am );
3074 return;
3075 case HRcVec128:
3076 // XXX: GPR30 used as spill register to kludge AltiVec AMode_IR
3077 *i1 = PPCInstr_AvLdSt ( True/*load*/, 16, rreg, am );
3078 return;
3079 default:
3080 ppHRegClass(hregClass(rreg));
3081 vpanic("genReload_PPC: unimplemented regclass");
3082 }
3083 }
3084
3085
3086 /* --------- The ppc assembler (bleh.) --------- */
3087
iregNo(HReg r,Bool mode64)3088 static UInt iregNo ( HReg r, Bool mode64 )
3089 {
3090 UInt n;
3091 vassert(hregClass(r) == mode64 ? HRcInt64 : HRcInt32);
3092 vassert(!hregIsVirtual(r));
3093 n = hregNumber(r);
3094 vassert(n <= 32);
3095 return n;
3096 }
3097
fregNo(HReg fr)3098 static UInt fregNo ( HReg fr )
3099 {
3100 UInt n;
3101 vassert(hregClass(fr) == HRcFlt64);
3102 vassert(!hregIsVirtual(fr));
3103 n = hregNumber(fr);
3104 vassert(n <= 32);
3105 return n;
3106 }
3107
vregNo(HReg v)3108 static UInt vregNo ( HReg v )
3109 {
3110 UInt n;
3111 vassert(hregClass(v) == HRcVec128);
3112 vassert(!hregIsVirtual(v));
3113 n = hregNumber(v);
3114 vassert(n <= 32);
3115 return n;
3116 }
3117
3118 /* Emit an instruction big-endianly */
emit32(UChar * p,UInt w32)3119 static UChar* emit32 ( UChar* p, UInt w32 )
3120 {
3121 *p++ = toUChar((w32 >> 24) & 0x000000FF);
3122 *p++ = toUChar((w32 >> 16) & 0x000000FF);
3123 *p++ = toUChar((w32 >> 8) & 0x000000FF);
3124 *p++ = toUChar((w32) & 0x000000FF);
3125 return p;
3126 }
3127
3128 /* Fetch an instruction big-endianly */
fetch32(UChar * p)3129 static UInt fetch32 ( UChar* p )
3130 {
3131 UInt w32 = 0;
3132 w32 |= ((0xFF & (UInt)p[0]) << 24);
3133 w32 |= ((0xFF & (UInt)p[1]) << 16);
3134 w32 |= ((0xFF & (UInt)p[2]) << 8);
3135 w32 |= ((0xFF & (UInt)p[3]) << 0);
3136 return w32;
3137 }
3138
3139 /* The following mkForm[...] functions refer to ppc instruction forms
3140 as per PPC32 p576
3141 */
3142
mkFormD(UChar * p,UInt opc1,UInt r1,UInt r2,UInt imm)3143 static UChar* mkFormD ( UChar* p, UInt opc1,
3144 UInt r1, UInt r2, UInt imm )
3145 {
3146 UInt theInstr;
3147 vassert(opc1 < 0x40);
3148 vassert(r1 < 0x20);
3149 vassert(r2 < 0x20);
3150 imm = imm & 0xFFFF;
3151 theInstr = ((opc1<<26) | (r1<<21) | (r2<<16) | (imm));
3152 return emit32(p, theInstr);
3153 }
3154
mkFormMD(UChar * p,UInt opc1,UInt r1,UInt r2,UInt imm1,UInt imm2,UInt opc2)3155 static UChar* mkFormMD ( UChar* p, UInt opc1, UInt r1, UInt r2,
3156 UInt imm1, UInt imm2, UInt opc2 )
3157 {
3158 UInt theInstr;
3159 vassert(opc1 < 0x40);
3160 vassert(r1 < 0x20);
3161 vassert(r2 < 0x20);
3162 vassert(imm1 < 0x40);
3163 vassert(imm2 < 0x40);
3164 vassert(opc2 < 0x08);
3165 imm2 = ((imm2 & 0x1F) << 1) | (imm2 >> 5);
3166 theInstr = ((opc1<<26) | (r1<<21) | (r2<<16) |
3167 ((imm1 & 0x1F)<<11) | (imm2<<5) |
3168 (opc2<<2) | ((imm1 >> 5)<<1));
3169 return emit32(p, theInstr);
3170 }
3171
mkFormX(UChar * p,UInt opc1,UInt r1,UInt r2,UInt r3,UInt opc2,UInt b0)3172 static UChar* mkFormX ( UChar* p, UInt opc1, UInt r1, UInt r2,
3173 UInt r3, UInt opc2, UInt b0 )
3174 {
3175 UInt theInstr;
3176 vassert(opc1 < 0x40);
3177 vassert(r1 < 0x20);
3178 vassert(r2 < 0x20);
3179 vassert(r3 < 0x20);
3180 vassert(opc2 < 0x400);
3181 vassert(b0 < 0x2);
3182 theInstr = ((opc1<<26) | (r1<<21) | (r2<<16) |
3183 (r3<<11) | (opc2<<1) | (b0));
3184 return emit32(p, theInstr);
3185 }
3186
mkFormXO(UChar * p,UInt opc1,UInt r1,UInt r2,UInt r3,UInt b10,UInt opc2,UInt b0)3187 static UChar* mkFormXO ( UChar* p, UInt opc1, UInt r1, UInt r2,
3188 UInt r3, UInt b10, UInt opc2, UInt b0 )
3189 {
3190 UInt theInstr;
3191 vassert(opc1 < 0x40);
3192 vassert(r1 < 0x20);
3193 vassert(r2 < 0x20);
3194 vassert(r3 < 0x20);
3195 vassert(b10 < 0x2);
3196 vassert(opc2 < 0x200);
3197 vassert(b0 < 0x2);
3198 theInstr = ((opc1<<26) | (r1<<21) | (r2<<16) |
3199 (r3<<11) | (b10 << 10) | (opc2<<1) | (b0));
3200 return emit32(p, theInstr);
3201 }
3202
mkFormXL(UChar * p,UInt opc1,UInt f1,UInt f2,UInt f3,UInt opc2,UInt b0)3203 static UChar* mkFormXL ( UChar* p, UInt opc1, UInt f1, UInt f2,
3204 UInt f3, UInt opc2, UInt b0 )
3205 {
3206 UInt theInstr;
3207 vassert(opc1 < 0x40);
3208 vassert(f1 < 0x20);
3209 vassert(f2 < 0x20);
3210 vassert(f3 < 0x20);
3211 vassert(opc2 < 0x400);
3212 vassert(b0 < 0x2);
3213 theInstr = ((opc1<<26) | (f1<<21) | (f2<<16) |
3214 (f3<<11) | (opc2<<1) | (b0));
3215 return emit32(p, theInstr);
3216 }
3217
3218 // Note: for split field ops, give mnemonic arg
mkFormXFX(UChar * p,UInt r1,UInt f2,UInt opc2)3219 static UChar* mkFormXFX ( UChar* p, UInt r1, UInt f2, UInt opc2 )
3220 {
3221 UInt theInstr;
3222 vassert(r1 < 0x20);
3223 vassert(f2 < 0x20);
3224 vassert(opc2 < 0x400);
3225 switch (opc2) {
3226 case 144: // mtcrf
3227 vassert(f2 < 0x100);
3228 f2 = f2 << 1;
3229 break;
3230 case 339: // mfspr
3231 case 371: // mftb
3232 case 467: // mtspr
3233 vassert(f2 < 0x400);
3234 // re-arrange split field
3235 f2 = ((f2>>5) & 0x1F) | ((f2 & 0x1F)<<5);
3236 break;
3237 default: vpanic("mkFormXFX(ppch)");
3238 }
3239 theInstr = ((31<<26) | (r1<<21) | (f2<<11) | (opc2<<1));
3240 return emit32(p, theInstr);
3241 }
3242
3243 // Only used by mtfsf
mkFormXFL(UChar * p,UInt FM,UInt freg,UInt dfp_rm)3244 static UChar* mkFormXFL ( UChar* p, UInt FM, UInt freg, UInt dfp_rm )
3245 {
3246 UInt theInstr;
3247 vassert(FM < 0x100);
3248 vassert(freg < 0x20);
3249 theInstr = ((63<<26) | (FM<<17) | (dfp_rm<<16) | (freg<<11) | (711<<1));
3250 return emit32(p, theInstr);
3251 }
3252
mkFormXS(UChar * p,UInt opc1,UInt r1,UInt r2,UInt imm,UInt opc2,UInt b0)3253 static UChar* mkFormXS ( UChar* p, UInt opc1, UInt r1, UInt r2,
3254 UInt imm, UInt opc2, UInt b0 )
3255 {
3256 UInt theInstr;
3257 vassert(opc1 < 0x40);
3258 vassert(r1 < 0x20);
3259 vassert(r2 < 0x20);
3260 vassert(imm < 0x40);
3261 vassert(opc2 < 0x400);
3262 vassert(b0 < 0x2);
3263 theInstr = ((opc1<<26) | (r1<<21) | (r2<<16) |
3264 ((imm & 0x1F)<<11) | (opc2<<2) | ((imm>>5)<<1) | (b0));
3265 return emit32(p, theInstr);
3266 }
3267
3268
3269 #if 0
3270 // 'b'
3271 static UChar* mkFormI ( UChar* p, UInt LI, UInt AA, UInt LK )
3272 {
3273 UInt theInstr;
3274 vassert(LI < 0x1000000);
3275 vassert(AA < 0x2);
3276 vassert(LK < 0x2);
3277 theInstr = ((18<<26) | (LI<<2) | (AA<<1) | (LK));
3278 return emit32(p, theInstr);
3279 }
3280 #endif
3281
3282 // 'bc'
mkFormB(UChar * p,UInt BO,UInt BI,UInt BD,UInt AA,UInt LK)3283 static UChar* mkFormB ( UChar* p, UInt BO, UInt BI,
3284 UInt BD, UInt AA, UInt LK )
3285 {
3286 UInt theInstr;
3287 vassert(BO < 0x20);
3288 vassert(BI < 0x20);
3289 vassert(BD < 0x4000);
3290 vassert(AA < 0x2);
3291 vassert(LK < 0x2);
3292 theInstr = ((16<<26) | (BO<<21) | (BI<<16) |
3293 (BD<<2) | (AA<<1) | (LK));
3294 return emit32(p, theInstr);
3295 }
3296
3297 // rotates
mkFormM(UChar * p,UInt opc1,UInt r1,UInt r2,UInt f3,UInt MB,UInt ME,UInt Rc)3298 static UChar* mkFormM ( UChar* p, UInt opc1, UInt r1, UInt r2,
3299 UInt f3, UInt MB, UInt ME, UInt Rc )
3300 {
3301 UInt theInstr;
3302 vassert(opc1 < 0x40);
3303 vassert(r1 < 0x20);
3304 vassert(r2 < 0x20);
3305 vassert(f3 < 0x20);
3306 vassert(MB < 0x20);
3307 vassert(ME < 0x20);
3308 vassert(Rc < 0x2);
3309 theInstr = ((opc1<<26) | (r1<<21) | (r2<<16) |
3310 (f3<<11) | (MB<<6) | (ME<<1) | (Rc));
3311 return emit32(p, theInstr);
3312 }
3313
mkFormA(UChar * p,UInt opc1,UInt r1,UInt r2,UInt r3,UInt r4,UInt opc2,UInt b0)3314 static UChar* mkFormA ( UChar* p, UInt opc1, UInt r1, UInt r2,
3315 UInt r3, UInt r4, UInt opc2, UInt b0 )
3316 {
3317 UInt theInstr;
3318 vassert(opc1 < 0x40);
3319 vassert(r1 < 0x20);
3320 vassert(r2 < 0x20);
3321 vassert(r3 < 0x20);
3322 vassert(r4 < 0x20);
3323 vassert(opc2 < 0x20);
3324 vassert(b0 < 0x2 );
3325 theInstr = ((opc1<<26) | (r1<<21) | (r2<<16) | (r3<<11) |
3326 (r4<<6) | (opc2<<1) | (b0));
3327 return emit32(p, theInstr);
3328 }
3329
mkFormZ22(UChar * p,UInt opc1,UInt r1,UInt r2,UInt constant,UInt opc2,UInt b0)3330 static UChar* mkFormZ22 ( UChar* p, UInt opc1, UInt r1, UInt r2,
3331 UInt constant, UInt opc2, UInt b0 )
3332 {
3333 UInt theInstr;
3334 vassert(opc1 < 0x40);
3335 vassert(r1 < 0x20);
3336 vassert(r2 < 0x20);
3337 vassert(constant < 0x40); /* 6 bit constant */
3338 vassert(opc2 < 0x200); /* 9 bit field */
3339 vassert(b0 < 0x2);
3340 theInstr = ((opc1<<26) | (r1<<21) | (r2<<16) |
3341 (constant<<10) | (opc2<<1) | (b0));
3342 return emit32(p, theInstr);
3343 }
3344
mkFormZ23(UChar * p,UInt opc1,UInt r1,UInt r2,UInt r3,UInt rmc,UInt opc2,UInt b0)3345 static UChar* mkFormZ23 ( UChar* p, UInt opc1, UInt r1, UInt r2,
3346 UInt r3, UInt rmc, UInt opc2, UInt b0 )
3347 {
3348 UInt theInstr;
3349 vassert(opc1 < 0x40);
3350 vassert(r1 < 0x20);
3351 vassert(r2 < 0x20);
3352 vassert(r3 < 0x20);
3353 vassert(rmc < 0x4);
3354 vassert(opc2 < 0x100);
3355 vassert(b0 < 0x2);
3356 theInstr = ((opc1<<26) | (r1<<21) | (r2<<16) |
3357 (r3<<11) | (rmc<<9) | (opc2<<1) | (b0));
3358 return emit32(p, theInstr);
3359 }
3360
doAMode_IR(UChar * p,UInt opc1,UInt rSD,PPCAMode * am,Bool mode64)3361 static UChar* doAMode_IR ( UChar* p, UInt opc1, UInt rSD,
3362 PPCAMode* am, Bool mode64 )
3363 {
3364 UInt rA, idx;
3365 vassert(am->tag == Pam_IR);
3366 vassert(am->Pam.IR.index < 0x10000);
3367
3368 rA = iregNo(am->Pam.IR.base, mode64);
3369 idx = am->Pam.IR.index;
3370
3371 if (opc1 == 58 || opc1 == 62) { // ld/std: mode64 only
3372 vassert(mode64);
3373 /* stay sane with DS form: lowest 2 bits must be 00. This
3374 should be guaranteed to us by iselWordExpr_AMode. */
3375 vassert(0 == (idx & 3));
3376 }
3377 p = mkFormD(p, opc1, rSD, rA, idx);
3378 return p;
3379 }
3380
doAMode_RR(UChar * p,UInt opc1,UInt opc2,UInt rSD,PPCAMode * am,Bool mode64)3381 static UChar* doAMode_RR ( UChar* p, UInt opc1, UInt opc2,
3382 UInt rSD, PPCAMode* am, Bool mode64 )
3383 {
3384 UInt rA, rB;
3385 vassert(am->tag == Pam_RR);
3386
3387 rA = iregNo(am->Pam.RR.base, mode64);
3388 rB = iregNo(am->Pam.RR.index, mode64);
3389
3390 p = mkFormX(p, opc1, rSD, rA, rB, opc2, 0);
3391 return p;
3392 }
3393
3394
3395 /* Load imm to r_dst */
mkLoadImm(UChar * p,UInt r_dst,ULong imm,Bool mode64)3396 static UChar* mkLoadImm ( UChar* p, UInt r_dst, ULong imm, Bool mode64 )
3397 {
3398 vassert(r_dst < 0x20);
3399
3400 if (!mode64) {
3401 /* In 32-bit mode, make sure the top 32 bits of imm are a sign
3402 extension of the bottom 32 bits, so that the range tests
3403 below work correctly. */
3404 UInt u32 = (UInt)imm;
3405 Int s32 = (Int)u32;
3406 Long s64 = (Long)s32;
3407 imm = (ULong)s64;
3408 }
3409
3410 if (imm >= 0xFFFFFFFFFFFF8000ULL || imm < 0x8000) {
3411 // sign-extendable from 16 bits
3412
3413 // addi r_dst,0,imm => li r_dst,imm
3414 p = mkFormD(p, 14, r_dst, 0, imm & 0xFFFF);
3415 } else {
3416 if (imm >= 0xFFFFFFFF80000000ULL || imm < 0x80000000ULL) {
3417 // sign-extendable from 32 bits
3418
3419 // addis r_dst,r0,(imm>>16) => lis r_dst, (imm>>16)
3420 p = mkFormD(p, 15, r_dst, 0, (imm>>16) & 0xFFFF);
3421 // ori r_dst, r_dst, (imm & 0xFFFF)
3422 p = mkFormD(p, 24, r_dst, r_dst, imm & 0xFFFF);
3423 } else {
3424 // full 64bit immediate load: 5 (five!) insns.
3425 vassert(mode64);
3426
3427 // load high word
3428
3429 // lis r_dst, (imm>>48) & 0xFFFF
3430 p = mkFormD(p, 15, r_dst, 0, (imm>>48) & 0xFFFF);
3431
3432 // ori r_dst, r_dst, (imm>>32) & 0xFFFF
3433 if ((imm>>32) & 0xFFFF)
3434 p = mkFormD(p, 24, r_dst, r_dst, (imm>>32) & 0xFFFF);
3435
3436 // shift r_dst low word to high word => rldicr
3437 p = mkFormMD(p, 30, r_dst, r_dst, 32, 31, 1);
3438
3439 // load low word
3440
3441 // oris r_dst, r_dst, (imm>>16) & 0xFFFF
3442 if ((imm>>16) & 0xFFFF)
3443 p = mkFormD(p, 25, r_dst, r_dst, (imm>>16) & 0xFFFF);
3444
3445 // ori r_dst, r_dst, (imm) & 0xFFFF
3446 if (imm & 0xFFFF)
3447 p = mkFormD(p, 24, r_dst, r_dst, imm & 0xFFFF);
3448 }
3449 }
3450 return p;
3451 }
3452
3453 /* A simplified version of mkLoadImm that always generates 2 or 5
3454 instructions (32 or 64 bits respectively) even if it could generate
3455 fewer. This is needed for generating fixed sized patchable
3456 sequences. */
mkLoadImm_EXACTLY2or5(UChar * p,UInt r_dst,ULong imm,Bool mode64)3457 static UChar* mkLoadImm_EXACTLY2or5 ( UChar* p,
3458 UInt r_dst, ULong imm, Bool mode64 )
3459 {
3460 vassert(r_dst < 0x20);
3461
3462 if (!mode64) {
3463 /* In 32-bit mode, make sure the top 32 bits of imm are a sign
3464 extension of the bottom 32 bits. (Probably unnecessary.) */
3465 UInt u32 = (UInt)imm;
3466 Int s32 = (Int)u32;
3467 Long s64 = (Long)s32;
3468 imm = (ULong)s64;
3469 }
3470
3471 if (!mode64) {
3472 // addis r_dst,r0,(imm>>16) => lis r_dst, (imm>>16)
3473 p = mkFormD(p, 15, r_dst, 0, (imm>>16) & 0xFFFF);
3474 // ori r_dst, r_dst, (imm & 0xFFFF)
3475 p = mkFormD(p, 24, r_dst, r_dst, imm & 0xFFFF);
3476
3477 } else {
3478 // full 64bit immediate load: 5 (five!) insns.
3479
3480 // load high word
3481 // lis r_dst, (imm>>48) & 0xFFFF
3482 p = mkFormD(p, 15, r_dst, 0, (imm>>48) & 0xFFFF);
3483
3484 // ori r_dst, r_dst, (imm>>32) & 0xFFFF
3485 p = mkFormD(p, 24, r_dst, r_dst, (imm>>32) & 0xFFFF);
3486
3487 // shift r_dst low word to high word => rldicr
3488 p = mkFormMD(p, 30, r_dst, r_dst, 32, 31, 1);
3489
3490 // load low word
3491 // oris r_dst, r_dst, (imm>>16) & 0xFFFF
3492 p = mkFormD(p, 25, r_dst, r_dst, (imm>>16) & 0xFFFF);
3493
3494 // ori r_dst, r_dst, (imm) & 0xFFFF
3495 p = mkFormD(p, 24, r_dst, r_dst, imm & 0xFFFF);
3496 }
3497 return p;
3498 }
3499
3500 /* Checks whether the sequence of bytes at p was indeed created
3501 by mkLoadImm_EXACTLY2or5 with the given parameters. */
isLoadImm_EXACTLY2or5(UChar * p_to_check,UInt r_dst,ULong imm,Bool mode64)3502 static Bool isLoadImm_EXACTLY2or5 ( UChar* p_to_check,
3503 UInt r_dst, ULong imm, Bool mode64 )
3504 {
3505 vassert(r_dst < 0x20);
3506
3507 if (!mode64) {
3508 /* In 32-bit mode, make sure the top 32 bits of imm are a sign
3509 extension of the bottom 32 bits. (Probably unnecessary.) */
3510 UInt u32 = (UInt)imm;
3511 Int s32 = (Int)u32;
3512 Long s64 = (Long)s32;
3513 imm = (ULong)s64;
3514 }
3515
3516 if (!mode64) {
3517 UInt expect[2] = { 0, 0 };
3518 UChar* p = (UChar*)&expect[0];
3519 // addis r_dst,r0,(imm>>16) => lis r_dst, (imm>>16)
3520 p = mkFormD(p, 15, r_dst, 0, (imm>>16) & 0xFFFF);
3521 // ori r_dst, r_dst, (imm & 0xFFFF)
3522 p = mkFormD(p, 24, r_dst, r_dst, imm & 0xFFFF);
3523 vassert(p == (UChar*)&expect[2]);
3524
3525 return fetch32(p_to_check + 0) == expect[0]
3526 && fetch32(p_to_check + 4) == expect[1];
3527
3528 } else {
3529 UInt expect[5] = { 0, 0, 0, 0, 0 };
3530 UChar* p = (UChar*)&expect[0];
3531 // full 64bit immediate load: 5 (five!) insns.
3532
3533 // load high word
3534 // lis r_dst, (imm>>48) & 0xFFFF
3535 p = mkFormD(p, 15, r_dst, 0, (imm>>48) & 0xFFFF);
3536
3537 // ori r_dst, r_dst, (imm>>32) & 0xFFFF
3538 p = mkFormD(p, 24, r_dst, r_dst, (imm>>32) & 0xFFFF);
3539
3540 // shift r_dst low word to high word => rldicr
3541 p = mkFormMD(p, 30, r_dst, r_dst, 32, 31, 1);
3542
3543 // load low word
3544 // oris r_dst, r_dst, (imm>>16) & 0xFFFF
3545 p = mkFormD(p, 25, r_dst, r_dst, (imm>>16) & 0xFFFF);
3546
3547 // ori r_dst, r_dst, (imm) & 0xFFFF
3548 p = mkFormD(p, 24, r_dst, r_dst, imm & 0xFFFF);
3549
3550 vassert(p == (UChar*)&expect[5]);
3551
3552 return fetch32(p_to_check + 0) == expect[0]
3553 && fetch32(p_to_check + 4) == expect[1]
3554 && fetch32(p_to_check + 8) == expect[2]
3555 && fetch32(p_to_check + 12) == expect[3]
3556 && fetch32(p_to_check + 16) == expect[4];
3557 }
3558 }
3559
3560
3561 /* Generate a machine-word sized load or store. Simplified version of
3562 the Pin_Load and Pin_Store cases below. */
do_load_or_store_machine_word(UChar * p,Bool isLoad,UInt reg,PPCAMode * am,Bool mode64)3563 static UChar* do_load_or_store_machine_word (
3564 UChar* p, Bool isLoad,
3565 UInt reg, PPCAMode* am, Bool mode64 )
3566 {
3567 if (isLoad) {
3568 UInt opc1, sz = mode64 ? 8 : 4;
3569 switch (am->tag) {
3570 case Pam_IR:
3571 if (mode64) {
3572 vassert(0 == (am->Pam.IR.index & 3));
3573 }
3574 switch (sz) {
3575 case 4: opc1 = 32; vassert(!mode64); break;
3576 case 8: opc1 = 58; vassert(mode64); break;
3577 default: vassert(0);
3578 }
3579 p = doAMode_IR(p, opc1, reg, am, mode64);
3580 break;
3581 case Pam_RR:
3582 /* we could handle this case, but we don't expect to ever
3583 need to. */
3584 vassert(0);
3585 default:
3586 vassert(0);
3587 }
3588 } else /*store*/ {
3589 UInt opc1, sz = mode64 ? 8 : 4;
3590 switch (am->tag) {
3591 case Pam_IR:
3592 if (mode64) {
3593 vassert(0 == (am->Pam.IR.index & 3));
3594 }
3595 switch (sz) {
3596 case 4: opc1 = 36; vassert(!mode64); break;
3597 case 8: opc1 = 62; vassert(mode64); break;
3598 default: vassert(0);
3599 }
3600 p = doAMode_IR(p, opc1, reg, am, mode64);
3601 break;
3602 case Pam_RR:
3603 /* we could handle this case, but we don't expect to ever
3604 need to. */
3605 vassert(0);
3606 default:
3607 vassert(0);
3608 }
3609 }
3610 return p;
3611 }
3612
3613 /* Generate a 32-bit sized load or store. Simplified version of
3614 do_load_or_store_machine_word above. */
do_load_or_store_word32(UChar * p,Bool isLoad,UInt reg,PPCAMode * am,Bool mode64)3615 static UChar* do_load_or_store_word32 (
3616 UChar* p, Bool isLoad,
3617 UInt reg, PPCAMode* am, Bool mode64 )
3618 {
3619 if (isLoad) {
3620 UInt opc1;
3621 switch (am->tag) {
3622 case Pam_IR:
3623 if (mode64) {
3624 vassert(0 == (am->Pam.IR.index & 3));
3625 }
3626 opc1 = 32;
3627 p = doAMode_IR(p, opc1, reg, am, mode64);
3628 break;
3629 case Pam_RR:
3630 /* we could handle this case, but we don't expect to ever
3631 need to. */
3632 vassert(0);
3633 default:
3634 vassert(0);
3635 }
3636 } else /*store*/ {
3637 UInt opc1;
3638 switch (am->tag) {
3639 case Pam_IR:
3640 if (mode64) {
3641 vassert(0 == (am->Pam.IR.index & 3));
3642 }
3643 opc1 = 36;
3644 p = doAMode_IR(p, opc1, reg, am, mode64);
3645 break;
3646 case Pam_RR:
3647 /* we could handle this case, but we don't expect to ever
3648 need to. */
3649 vassert(0);
3650 default:
3651 vassert(0);
3652 }
3653 }
3654 return p;
3655 }
3656
3657 /* Move r_dst to r_src */
mkMoveReg(UChar * p,UInt r_dst,UInt r_src)3658 static UChar* mkMoveReg ( UChar* p, UInt r_dst, UInt r_src )
3659 {
3660 vassert(r_dst < 0x20);
3661 vassert(r_src < 0x20);
3662
3663 if (r_dst != r_src) {
3664 /* or r_dst, r_src, r_src */
3665 p = mkFormX(p, 31, r_src, r_dst, r_src, 444, 0 );
3666 }
3667 return p;
3668 }
3669
mkFormVX(UChar * p,UInt opc1,UInt r1,UInt r2,UInt r3,UInt opc2)3670 static UChar* mkFormVX ( UChar* p, UInt opc1, UInt r1, UInt r2,
3671 UInt r3, UInt opc2 )
3672 {
3673 UInt theInstr;
3674 vassert(opc1 < 0x40);
3675 vassert(r1 < 0x20);
3676 vassert(r2 < 0x20);
3677 vassert(r3 < 0x20);
3678 vassert(opc2 < 0x800);
3679 theInstr = ((opc1<<26) | (r1<<21) | (r2<<16) | (r3<<11) | opc2);
3680 return emit32(p, theInstr);
3681 }
3682
mkFormVXR(UChar * p,UInt opc1,UInt r1,UInt r2,UInt r3,UInt Rc,UInt opc2)3683 static UChar* mkFormVXR ( UChar* p, UInt opc1, UInt r1, UInt r2,
3684 UInt r3, UInt Rc, UInt opc2 )
3685 {
3686 UInt theInstr;
3687 vassert(opc1 < 0x40);
3688 vassert(r1 < 0x20);
3689 vassert(r2 < 0x20);
3690 vassert(r3 < 0x20);
3691 vassert(Rc < 0x2);
3692 vassert(opc2 < 0x400);
3693 theInstr = ((opc1<<26) | (r1<<21) | (r2<<16) |
3694 (r3<<11) | (Rc<<10) | opc2);
3695 return emit32(p, theInstr);
3696 }
3697
mkFormVA(UChar * p,UInt opc1,UInt r1,UInt r2,UInt r3,UInt r4,UInt opc2)3698 static UChar* mkFormVA ( UChar* p, UInt opc1, UInt r1, UInt r2,
3699 UInt r3, UInt r4, UInt opc2 )
3700 {
3701 UInt theInstr;
3702 vassert(opc1 < 0x40);
3703 vassert(r1 < 0x20);
3704 vassert(r2 < 0x20);
3705 vassert(r3 < 0x20);
3706 vassert(r4 < 0x20);
3707 vassert(opc2 < 0x40);
3708 theInstr = ((opc1<<26) | (r1<<21) | (r2<<16) |
3709 (r3<<11) | (r4<<6) | opc2);
3710 return emit32(p, theInstr);
3711 }
3712
3713
3714
3715 /* Emit an instruction into buf and return the number of bytes used.
3716 Note that buf is not the insn's final place, and therefore it is
3717 imperative to emit position-independent code. If the emitted
3718 instruction was a profiler inc, set *is_profInc to True, else leave
3719 it unchanged.
3720 */
emit_PPCInstr(Bool * is_profInc,UChar * buf,Int nbuf,PPCInstr * i,Bool mode64,void * disp_cp_chain_me_to_slowEP,void * disp_cp_chain_me_to_fastEP,void * disp_cp_xindir,void * disp_cp_xassisted)3721 Int emit_PPCInstr ( /*MB_MOD*/Bool* is_profInc,
3722 UChar* buf, Int nbuf, PPCInstr* i,
3723 Bool mode64,
3724 void* disp_cp_chain_me_to_slowEP,
3725 void* disp_cp_chain_me_to_fastEP,
3726 void* disp_cp_xindir,
3727 void* disp_cp_xassisted )
3728 {
3729 UChar* p = &buf[0];
3730 vassert(nbuf >= 32);
3731
3732 if (0) {
3733 vex_printf("asm ");ppPPCInstr(i, mode64); vex_printf("\n");
3734 }
3735
3736 switch (i->tag) {
3737
3738 case Pin_LI:
3739 p = mkLoadImm(p, iregNo(i->Pin.LI.dst, mode64),
3740 i->Pin.LI.imm64, mode64);
3741 goto done;
3742
3743 case Pin_Alu: {
3744 PPCRH* srcR = i->Pin.Alu.srcR;
3745 Bool immR = toBool(srcR->tag == Prh_Imm);
3746 UInt r_dst = iregNo(i->Pin.Alu.dst, mode64);
3747 UInt r_srcL = iregNo(i->Pin.Alu.srcL, mode64);
3748 UInt r_srcR = immR ? (-1)/*bogus*/ :
3749 iregNo(srcR->Prh.Reg.reg, mode64);
3750
3751 switch (i->Pin.Alu.op) {
3752 case Palu_ADD:
3753 if (immR) {
3754 /* addi (PPC32 p350) */
3755 vassert(srcR->Prh.Imm.syned);
3756 vassert(srcR->Prh.Imm.imm16 != 0x8000);
3757 p = mkFormD(p, 14, r_dst, r_srcL, srcR->Prh.Imm.imm16);
3758 } else {
3759 /* add (PPC32 p347) */
3760 p = mkFormXO(p, 31, r_dst, r_srcL, r_srcR, 0, 266, 0);
3761 }
3762 break;
3763
3764 case Palu_SUB:
3765 if (immR) {
3766 /* addi (PPC32 p350), but with negated imm */
3767 vassert(srcR->Prh.Imm.syned);
3768 vassert(srcR->Prh.Imm.imm16 != 0x8000);
3769 p = mkFormD(p, 14, r_dst, r_srcL, (- srcR->Prh.Imm.imm16));
3770 } else {
3771 /* subf (PPC32 p537), with args the "wrong" way round */
3772 p = mkFormXO(p, 31, r_dst, r_srcR, r_srcL, 0, 40, 0);
3773 }
3774 break;
3775
3776 case Palu_AND:
3777 if (immR) {
3778 /* andi. (PPC32 p358) */
3779 vassert(!srcR->Prh.Imm.syned);
3780 p = mkFormD(p, 28, r_srcL, r_dst, srcR->Prh.Imm.imm16);
3781 } else {
3782 /* and (PPC32 p356) */
3783 p = mkFormX(p, 31, r_srcL, r_dst, r_srcR, 28, 0);
3784 }
3785 break;
3786
3787 case Palu_OR:
3788 if (immR) {
3789 /* ori (PPC32 p497) */
3790 vassert(!srcR->Prh.Imm.syned);
3791 p = mkFormD(p, 24, r_srcL, r_dst, srcR->Prh.Imm.imm16);
3792 } else {
3793 /* or (PPC32 p495) */
3794 p = mkFormX(p, 31, r_srcL, r_dst, r_srcR, 444, 0);
3795 }
3796 break;
3797
3798 case Palu_XOR:
3799 if (immR) {
3800 /* xori (PPC32 p550) */
3801 vassert(!srcR->Prh.Imm.syned);
3802 p = mkFormD(p, 26, r_srcL, r_dst, srcR->Prh.Imm.imm16);
3803 } else {
3804 /* xor (PPC32 p549) */
3805 p = mkFormX(p, 31, r_srcL, r_dst, r_srcR, 316, 0);
3806 }
3807 break;
3808
3809 default:
3810 goto bad;
3811 }
3812 goto done;
3813 }
3814
3815 case Pin_Shft: {
3816 PPCRH* srcR = i->Pin.Shft.srcR;
3817 Bool sz32 = i->Pin.Shft.sz32;
3818 Bool immR = toBool(srcR->tag == Prh_Imm);
3819 UInt r_dst = iregNo(i->Pin.Shft.dst, mode64);
3820 UInt r_srcL = iregNo(i->Pin.Shft.srcL, mode64);
3821 UInt r_srcR = immR ? (-1)/*bogus*/ :
3822 iregNo(srcR->Prh.Reg.reg, mode64);
3823 if (!mode64)
3824 vassert(sz32);
3825
3826 switch (i->Pin.Shft.op) {
3827 case Pshft_SHL:
3828 if (sz32) {
3829 if (immR) {
3830 /* rd = rs << n, 1 <= n <= 31
3831 is
3832 rlwinm rd,rs,n,0,31-n (PPC32 p501)
3833 */
3834 UInt n = srcR->Prh.Imm.imm16;
3835 vassert(!srcR->Prh.Imm.syned);
3836 vassert(n > 0 && n < 32);
3837 p = mkFormM(p, 21, r_srcL, r_dst, n, 0, 31-n, 0);
3838 } else {
3839 /* slw (PPC32 p505) */
3840 p = mkFormX(p, 31, r_srcL, r_dst, r_srcR, 24, 0);
3841 }
3842 } else {
3843 if (immR) {
3844 /* rd = rs << n, 1 <= n <= 63
3845 is
3846 rldicr rd,rs,n,63-n (PPC64 p559)
3847 */
3848 UInt n = srcR->Prh.Imm.imm16;
3849 vassert(!srcR->Prh.Imm.syned);
3850 vassert(n > 0 && n < 64);
3851 p = mkFormMD(p, 30, r_srcL, r_dst, n, 63-n, 1);
3852 } else {
3853 /* sld (PPC64 p568) */
3854 p = mkFormX(p, 31, r_srcL, r_dst, r_srcR, 27, 0);
3855 }
3856 }
3857 break;
3858
3859 case Pshft_SHR:
3860 if (sz32) {
3861 if (immR) {
3862 /* rd = rs >>u n, 1 <= n <= 31
3863 is
3864 rlwinm rd,rs,32-n,n,31 (PPC32 p501)
3865 */
3866 UInt n = srcR->Prh.Imm.imm16;
3867 vassert(!srcR->Prh.Imm.syned);
3868 vassert(n > 0 && n < 32);
3869 p = mkFormM(p, 21, r_srcL, r_dst, 32-n, n, 31, 0);
3870 } else {
3871 /* srw (PPC32 p508) */
3872 p = mkFormX(p, 31, r_srcL, r_dst, r_srcR, 536, 0);
3873 }
3874 } else {
3875 if (immR) {
3876 /* rd = rs >>u n, 1 <= n <= 63
3877 is
3878 rldicl rd,rs,64-n,n (PPC64 p558)
3879 */
3880 UInt n = srcR->Prh.Imm.imm16;
3881 vassert(!srcR->Prh.Imm.syned);
3882 vassert(n > 0 && n < 64);
3883 p = mkFormMD(p, 30, r_srcL, r_dst, 64-n, n, 0);
3884 } else {
3885 /* srd (PPC64 p574) */
3886 p = mkFormX(p, 31, r_srcL, r_dst, r_srcR, 539, 0);
3887 }
3888 }
3889 break;
3890
3891 case Pshft_SAR:
3892 if (sz32) {
3893 if (immR) {
3894 /* srawi (PPC32 p507) */
3895 UInt n = srcR->Prh.Imm.imm16;
3896 vassert(!srcR->Prh.Imm.syned);
3897 /* In 64-bit mode, we allow right shifts by zero bits
3898 as that is a handy way to sign extend the lower 32
3899 bits into the upper 32 bits. */
3900 if (mode64)
3901 vassert(n >= 0 && n < 32);
3902 else
3903 vassert(n > 0 && n < 32);
3904 p = mkFormX(p, 31, r_srcL, r_dst, n, 824, 0);
3905 } else {
3906 /* sraw (PPC32 p506) */
3907 p = mkFormX(p, 31, r_srcL, r_dst, r_srcR, 792, 0);
3908 }
3909 } else {
3910 if (immR) {
3911 /* sradi (PPC64 p571) */
3912 UInt n = srcR->Prh.Imm.imm16;
3913 vassert(!srcR->Prh.Imm.syned);
3914 vassert(n > 0 && n < 64);
3915 p = mkFormXS(p, 31, r_srcL, r_dst, n, 413, 0);
3916 } else {
3917 /* srad (PPC32 p570) */
3918 p = mkFormX(p, 31, r_srcL, r_dst, r_srcR, 794, 0);
3919 }
3920 }
3921 break;
3922
3923 default:
3924 goto bad;
3925 }
3926 goto done;
3927 }
3928
3929 case Pin_AddSubC: {
3930 Bool isAdd = i->Pin.AddSubC.isAdd;
3931 Bool setC = i->Pin.AddSubC.setC;
3932 UInt r_srcL = iregNo(i->Pin.AddSubC.srcL, mode64);
3933 UInt r_srcR = iregNo(i->Pin.AddSubC.srcR, mode64);
3934 UInt r_dst = iregNo(i->Pin.AddSubC.dst, mode64);
3935
3936 if (isAdd) {
3937 if (setC) /* addc (PPC32 p348) */
3938 p = mkFormXO(p, 31, r_dst, r_srcL, r_srcR, 0, 10, 0);
3939 else /* adde (PPC32 p349) */
3940 p = mkFormXO(p, 31, r_dst, r_srcL, r_srcR, 0, 138, 0);
3941 } else {
3942 /* subfX, with args the "wrong" way round */
3943 if (setC) /* subfc (PPC32 p538) */
3944 p = mkFormXO(p, 31, r_dst, r_srcR, r_srcL, 0, 8, 0);
3945 else /* subfe (PPC32 p539) */
3946 p = mkFormXO(p, 31, r_dst, r_srcR, r_srcL, 0, 136, 0);
3947 }
3948 goto done;
3949 }
3950
3951 case Pin_Cmp: {
3952 Bool syned = i->Pin.Cmp.syned;
3953 Bool sz32 = i->Pin.Cmp.sz32;
3954 UInt fld1 = i->Pin.Cmp.crfD << 2;
3955 UInt r_srcL = iregNo(i->Pin.Cmp.srcL, mode64);
3956 UInt r_srcR, imm_srcR;
3957 PPCRH* srcR = i->Pin.Cmp.srcR;
3958
3959 if (!mode64) // cmp double word invalid for mode32
3960 vassert(sz32);
3961 else if (!sz32) // mode64 && cmp64: set L=1
3962 fld1 |= 1;
3963
3964 switch (srcR->tag) {
3965 case Prh_Imm:
3966 vassert(syned == srcR->Prh.Imm.syned);
3967 imm_srcR = srcR->Prh.Imm.imm16;
3968 if (syned) { // cmpw/di (signed) (PPC32 p368)
3969 vassert(imm_srcR != 0x8000);
3970 p = mkFormD(p, 11, fld1, r_srcL, imm_srcR);
3971 } else { // cmplw/di (unsigned) (PPC32 p370)
3972 p = mkFormD(p, 10, fld1, r_srcL, imm_srcR);
3973 }
3974 break;
3975 case Prh_Reg:
3976 r_srcR = iregNo(srcR->Prh.Reg.reg, mode64);
3977 if (syned) // cmpwi (signed) (PPC32 p367)
3978 p = mkFormX(p, 31, fld1, r_srcL, r_srcR, 0, 0);
3979 else // cmplwi (unsigned) (PPC32 p379)
3980 p = mkFormX(p, 31, fld1, r_srcL, r_srcR, 32, 0);
3981 break;
3982 default:
3983 goto bad;
3984 }
3985 goto done;
3986 }
3987
3988 case Pin_Unary: {
3989 UInt r_dst = iregNo(i->Pin.Unary.dst, mode64);
3990 UInt r_src = iregNo(i->Pin.Unary.src, mode64);
3991
3992 switch (i->Pin.Unary.op) {
3993 case Pun_NOT: // nor r_dst,r_src,r_src
3994 p = mkFormX(p, 31, r_src, r_dst, r_src, 124, 0);
3995 break;
3996 case Pun_NEG: // neg r_dst,r_src
3997 p = mkFormXO(p, 31, r_dst, r_src, 0, 0, 104, 0);
3998 break;
3999 case Pun_CLZ32: // cntlzw r_dst, r_src
4000 p = mkFormX(p, 31, r_src, r_dst, 0, 26, 0);
4001 break;
4002 case Pun_CLZ64: // cntlzd r_dst, r_src
4003 vassert(mode64);
4004 p = mkFormX(p, 31, r_src, r_dst, 0, 58, 0);
4005 break;
4006 case Pun_EXTSW: // extsw r_dst, r_src
4007 vassert(mode64);
4008 p = mkFormX(p, 31, r_src, r_dst, 0, 986, 0);
4009 break;
4010 default: goto bad;
4011 }
4012 goto done;
4013 }
4014
4015 case Pin_MulL: {
4016 Bool syned = i->Pin.MulL.syned;
4017 Bool sz32 = i->Pin.MulL.sz32;
4018 UInt r_dst = iregNo(i->Pin.MulL.dst, mode64);
4019 UInt r_srcL = iregNo(i->Pin.MulL.srcL, mode64);
4020 UInt r_srcR = iregNo(i->Pin.MulL.srcR, mode64);
4021
4022 if (!mode64)
4023 vassert(sz32);
4024
4025 if (i->Pin.MulL.hi) {
4026 // mul hi words, must consider sign
4027 if (sz32) {
4028 if (syned) // mulhw r_dst,r_srcL,r_srcR
4029 p = mkFormXO(p, 31, r_dst, r_srcL, r_srcR, 0, 75, 0);
4030 else // mulhwu r_dst,r_srcL,r_srcR
4031 p = mkFormXO(p, 31, r_dst, r_srcL, r_srcR, 0, 11, 0);
4032 } else {
4033 if (syned) // mulhd r_dst,r_srcL,r_srcR
4034 p = mkFormXO(p, 31, r_dst, r_srcL, r_srcR, 0, 73, 0);
4035 else // mulhdu r_dst,r_srcL,r_srcR
4036 p = mkFormXO(p, 31, r_dst, r_srcL, r_srcR, 0, 9, 0);
4037 }
4038 } else {
4039 // mul low word, sign is irrelevant
4040 vassert(!i->Pin.MulL.syned);
4041 if (sz32) // mullw r_dst,r_srcL,r_srcR
4042 p = mkFormXO(p, 31, r_dst, r_srcL, r_srcR, 0, 235, 0);
4043 else // mulld r_dst,r_srcL,r_srcR
4044 p = mkFormXO(p, 31, r_dst, r_srcL, r_srcR, 0, 233, 0);
4045 }
4046 goto done;
4047 }
4048
4049 case Pin_Div: {
4050 Bool syned = i->Pin.Div.syned;
4051 Bool sz32 = i->Pin.Div.sz32;
4052 UInt r_dst = iregNo(i->Pin.Div.dst, mode64);
4053 UInt r_srcL = iregNo(i->Pin.Div.srcL, mode64);
4054 UInt r_srcR = iregNo(i->Pin.Div.srcR, mode64);
4055
4056 if (!mode64)
4057 vassert(sz32);
4058
4059 if (i->Pin.Div.extended) {
4060 if (sz32) {
4061 if (syned)
4062 // divwe r_dst,r_srcL,r_srcR
4063 p = mkFormXO(p, 31, r_dst, r_srcL, r_srcR, 0, 427, 0);
4064 else
4065 // divweu r_dst,r_srcL,r_srcR
4066 p = mkFormXO(p, 31, r_dst, r_srcL, r_srcR, 0, 395, 0);
4067 } else {
4068 if (syned)
4069 // divde r_dst,r_srcL,r_srcR
4070 p = mkFormXO(p, 31, r_dst, r_srcL, r_srcR, 0, 425, 0);
4071 else
4072 // divdeu r_dst,r_srcL,r_srcR
4073 p = mkFormXO(p, 31, r_dst, r_srcL, r_srcR, 0, 393, 0);
4074 }
4075 } else if (sz32) {
4076 if (syned) // divw r_dst,r_srcL,r_srcR
4077 p = mkFormXO(p, 31, r_dst, r_srcL, r_srcR, 0, 491, 0);
4078 else // divwu r_dst,r_srcL,r_srcR
4079 p = mkFormXO(p, 31, r_dst, r_srcL, r_srcR, 0, 459, 0);
4080 } else {
4081 if (syned) // divd r_dst,r_srcL,r_srcR
4082 p = mkFormXO(p, 31, r_dst, r_srcL, r_srcR, 0, 489, 0);
4083 else // divdu r_dst,r_srcL,r_srcR
4084 p = mkFormXO(p, 31, r_dst, r_srcL, r_srcR, 0, 457, 0);
4085 }
4086 goto done;
4087 }
4088
4089 case Pin_Call: {
4090 if (i->Pin.Call.cond.test != Pct_ALWAYS
4091 && i->Pin.Call.rloc.pri != RLPri_None) {
4092 /* The call might not happen (it isn't unconditional) and it
4093 returns a result. In this case we will need to generate a
4094 control flow diamond to put 0x555..555 in the return
4095 register(s) in the case where the call doesn't happen. If
4096 this ever becomes necessary, maybe copy code from the ARM
4097 equivalent. Until that day, just give up. */
4098 goto bad;
4099 }
4100 PPCCondCode cond = i->Pin.Call.cond;
4101 UInt r_dst = 10;
4102 /* As per detailed comment for Pin_Call in
4103 getRegUsage_PPCInstr above, %r10 is used as an address temp */
4104
4105 /* jump over the following insns if condition does not hold */
4106 UChar* ptmp = NULL;
4107 if (cond.test != Pct_ALWAYS) {
4108 /* jmp fwds if !condition */
4109 /* don't know how many bytes to jump over yet...
4110 make space for a jump instruction and fill in later. */
4111 ptmp = p; /* fill in this bit later */
4112 p += 4; // p += 4
4113 }
4114
4115 /* load target to r_dst */ // p += 4|8|20
4116 p = mkLoadImm(p, r_dst, i->Pin.Call.target, mode64);
4117
4118 /* mtspr 9,r_dst => move r_dst to count register */
4119 p = mkFormXFX(p, r_dst, 9, 467); // p += 4
4120
4121 /* bctrl => branch to count register (and save to lr) */
4122 p = mkFormXL(p, 19, Pct_ALWAYS, 0, 0, 528, 1); // p += 4
4123
4124 /* Fix up the conditional jump, if there was one. */
4125 if (cond.test != Pct_ALWAYS) {
4126 Int delta = p - ptmp;
4127 vassert(delta >= 16 && delta <= 32);
4128 /* bc !ct,cf,delta */
4129 mkFormB(ptmp, invertCondTest(cond.test),
4130 cond.flag, (delta>>2), 0, 0);
4131 }
4132 goto done;
4133 }
4134
4135 case Pin_XDirect: {
4136 /* NB: what goes on here has to be very closely coordinated
4137 with the chainXDirect_PPC and unchainXDirect_PPC below. */
4138 /* We're generating chain-me requests here, so we need to be
4139 sure this is actually allowed -- no-redir translations
4140 can't use chain-me's. Hence: */
4141 vassert(disp_cp_chain_me_to_slowEP != NULL);
4142 vassert(disp_cp_chain_me_to_fastEP != NULL);
4143
4144 /* First off, if this is conditional, create a conditional jump
4145 over the rest of it. Or at least, leave a space for it that
4146 we will shortly fill in. */
4147 UChar* ptmp = NULL;
4148 if (i->Pin.XDirect.cond.test != Pct_ALWAYS) {
4149 vassert(i->Pin.XDirect.cond.flag != Pcf_NONE);
4150 ptmp = p;
4151 p += 4;
4152 } else {
4153 vassert(i->Pin.XDirect.cond.flag == Pcf_NONE);
4154 }
4155
4156 /* Update the guest CIA. */
4157 /* imm32/64 r30, dstGA */
4158 if (!mode64) vassert(0 == (((ULong)i->Pin.XDirect.dstGA) >> 32));
4159 p = mkLoadImm(p, /*r*/30, (ULong)i->Pin.XDirect.dstGA, mode64);
4160 /* stw/std r30, amCIA */
4161 p = do_load_or_store_machine_word(
4162 p, False/*!isLoad*/,
4163 /*r*/30, i->Pin.XDirect.amCIA, mode64
4164 );
4165
4166 /* --- FIRST PATCHABLE BYTE follows --- */
4167 /* VG_(disp_cp_chain_me_to_{slowEP,fastEP}) (where we're calling
4168 to) backs up the return address, so as to find the address of
4169 the first patchable byte. So: don't change the number of
4170 instructions (32-bit: 4, 64-bit: 7) below. */
4171 /* imm32/64-fixed r30, VG_(disp_cp_chain_me_to_{slowEP,fastEP} */
4172 void* disp_cp_chain_me
4173 = i->Pin.XDirect.toFastEP ? disp_cp_chain_me_to_fastEP
4174 : disp_cp_chain_me_to_slowEP;
4175 p = mkLoadImm_EXACTLY2or5(
4176 p, /*r*/30, Ptr_to_ULong(disp_cp_chain_me), mode64);
4177 /* mtctr r30 */
4178 p = mkFormXFX(p, /*r*/30, 9, 467);
4179 /* bctrl */
4180 p = mkFormXL(p, 19, Pct_ALWAYS, 0, 0, 528, 1);
4181 /* --- END of PATCHABLE BYTES --- */
4182
4183 /* Fix up the conditional jump, if there was one. */
4184 if (i->Pin.XDirect.cond.test != Pct_ALWAYS) {
4185 Int delta = p - ptmp;
4186 vassert(delta >= 16 && delta <= 64 && 0 == (delta & 3));
4187 /* bc !ct,cf,delta */
4188 mkFormB(ptmp, invertCondTest(i->Pin.XDirect.cond.test),
4189 i->Pin.XDirect.cond.flag, (delta>>2), 0, 0);
4190 }
4191 goto done;
4192 }
4193
4194 case Pin_XIndir: {
4195 /* We're generating transfers that could lead indirectly to a
4196 chain-me, so we need to be sure this is actually allowed --
4197 no-redir translations are not allowed to reach normal
4198 translations without going through the scheduler. That means
4199 no XDirects or XIndirs out from no-redir translations.
4200 Hence: */
4201 vassert(disp_cp_xindir != NULL);
4202
4203 /* First off, if this is conditional, create a conditional jump
4204 over the rest of it. Or at least, leave a space for it that
4205 we will shortly fill in. */
4206 UChar* ptmp = NULL;
4207 if (i->Pin.XIndir.cond.test != Pct_ALWAYS) {
4208 vassert(i->Pin.XIndir.cond.flag != Pcf_NONE);
4209 ptmp = p;
4210 p += 4;
4211 } else {
4212 vassert(i->Pin.XIndir.cond.flag == Pcf_NONE);
4213 }
4214
4215 /* Update the guest CIA. */
4216 /* stw/std r-dstGA, amCIA */
4217 p = do_load_or_store_machine_word(
4218 p, False/*!isLoad*/,
4219 iregNo(i->Pin.XIndir.dstGA, mode64),
4220 i->Pin.XIndir.amCIA, mode64
4221 );
4222
4223 /* imm32/64 r30, VG_(disp_cp_xindir) */
4224 p = mkLoadImm(p, /*r*/30, (ULong)Ptr_to_ULong(disp_cp_xindir), mode64);
4225 /* mtctr r30 */
4226 p = mkFormXFX(p, /*r*/30, 9, 467);
4227 /* bctr */
4228 p = mkFormXL(p, 19, Pct_ALWAYS, 0, 0, 528, 0);
4229
4230 /* Fix up the conditional jump, if there was one. */
4231 if (i->Pin.XIndir.cond.test != Pct_ALWAYS) {
4232 Int delta = p - ptmp;
4233 vassert(delta >= 16 && delta <= 32 && 0 == (delta & 3));
4234 /* bc !ct,cf,delta */
4235 mkFormB(ptmp, invertCondTest(i->Pin.XIndir.cond.test),
4236 i->Pin.XIndir.cond.flag, (delta>>2), 0, 0);
4237 }
4238 goto done;
4239 }
4240
4241 case Pin_XAssisted: {
4242 /* First off, if this is conditional, create a conditional jump
4243 over the rest of it. Or at least, leave a space for it that
4244 we will shortly fill in. */
4245 UChar* ptmp = NULL;
4246 if (i->Pin.XAssisted.cond.test != Pct_ALWAYS) {
4247 vassert(i->Pin.XAssisted.cond.flag != Pcf_NONE);
4248 ptmp = p;
4249 p += 4;
4250 } else {
4251 vassert(i->Pin.XAssisted.cond.flag == Pcf_NONE);
4252 }
4253
4254 /* Update the guest CIA. */
4255 /* stw/std r-dstGA, amCIA */
4256 p = do_load_or_store_machine_word(
4257 p, False/*!isLoad*/,
4258 iregNo(i->Pin.XIndir.dstGA, mode64),
4259 i->Pin.XIndir.amCIA, mode64
4260 );
4261
4262 /* imm32/64 r31, $magic_number */
4263 UInt trcval = 0;
4264 switch (i->Pin.XAssisted.jk) {
4265 case Ijk_ClientReq: trcval = VEX_TRC_JMP_CLIENTREQ; break;
4266 case Ijk_Sys_syscall: trcval = VEX_TRC_JMP_SYS_SYSCALL; break;
4267 //case Ijk_Sys_int128: trcval = VEX_TRC_JMP_SYS_INT128; break;
4268 //case Ijk_Yield: trcval = VEX_TRC_JMP_YIELD; break;
4269 case Ijk_EmWarn: trcval = VEX_TRC_JMP_EMWARN; break;
4270 case Ijk_EmFail: trcval = VEX_TRC_JMP_EMFAIL; break;
4271 //case Ijk_MapFail: trcval = VEX_TRC_JMP_MAPFAIL; break;
4272 case Ijk_NoDecode: trcval = VEX_TRC_JMP_NODECODE; break;
4273 case Ijk_InvalICache: trcval = VEX_TRC_JMP_INVALICACHE; break;
4274 case Ijk_NoRedir: trcval = VEX_TRC_JMP_NOREDIR; break;
4275 case Ijk_SigTRAP: trcval = VEX_TRC_JMP_SIGTRAP; break;
4276 //case Ijk_SigSEGV: trcval = VEX_TRC_JMP_SIGSEGV; break;
4277 case Ijk_SigBUS: trcval = VEX_TRC_JMP_SIGBUS; break;
4278 case Ijk_Boring: trcval = VEX_TRC_JMP_BORING; break;
4279 /* We don't expect to see the following being assisted. */
4280 //case Ijk_Ret:
4281 //case Ijk_Call:
4282 /* fallthrough */
4283 default:
4284 ppIRJumpKind(i->Pin.XAssisted.jk);
4285 vpanic("emit_ARMInstr.Pin_XAssisted: unexpected jump kind");
4286 }
4287 vassert(trcval != 0);
4288 p = mkLoadImm(p, /*r*/31, trcval, mode64);
4289
4290 /* imm32/64 r30, VG_(disp_cp_xassisted) */
4291 p = mkLoadImm(p, /*r*/30,
4292 (ULong)Ptr_to_ULong(disp_cp_xassisted), mode64);
4293 /* mtctr r30 */
4294 p = mkFormXFX(p, /*r*/30, 9, 467);
4295 /* bctr */
4296 p = mkFormXL(p, 19, Pct_ALWAYS, 0, 0, 528, 0);
4297
4298 /* Fix up the conditional jump, if there was one. */
4299 if (i->Pin.XAssisted.cond.test != Pct_ALWAYS) {
4300 Int delta = p - ptmp;
4301 vassert(delta >= 16 && delta <= 32 && 0 == (delta & 3));
4302 /* bc !ct,cf,delta */
4303 mkFormB(ptmp, invertCondTest(i->Pin.XAssisted.cond.test),
4304 i->Pin.XAssisted.cond.flag, (delta>>2), 0, 0);
4305 }
4306 goto done;
4307 }
4308
4309 case Pin_CMov: {
4310 UInt r_dst, r_src;
4311 ULong imm_src;
4312 PPCCondCode cond;
4313 vassert(i->Pin.CMov.cond.test != Pct_ALWAYS);
4314
4315 r_dst = iregNo(i->Pin.CMov.dst, mode64);
4316 cond = i->Pin.CMov.cond;
4317
4318 /* branch (if cond fails) over move instrs */
4319 UChar* ptmp = NULL;
4320 if (cond.test != Pct_ALWAYS) {
4321 /* don't know how many bytes to jump over yet...
4322 make space for a jump instruction and fill in later. */
4323 ptmp = p; /* fill in this bit later */
4324 p += 4;
4325 }
4326
4327 // cond true: move src => dst
4328 switch (i->Pin.CMov.src->tag) {
4329 case Pri_Imm:
4330 imm_src = i->Pin.CMov.src->Pri.Imm;
4331 p = mkLoadImm(p, r_dst, imm_src, mode64); // p += 4|8|20
4332 break;
4333 case Pri_Reg:
4334 r_src = iregNo(i->Pin.CMov.src->Pri.Reg, mode64);
4335 p = mkMoveReg(p, r_dst, r_src); // p += 4
4336 break;
4337 default: goto bad;
4338 }
4339
4340 /* Fix up the conditional jump, if there was one. */
4341 if (cond.test != Pct_ALWAYS) {
4342 Int delta = p - ptmp;
4343 vassert(delta >= 8 && delta <= 24);
4344 /* bc !ct,cf,delta */
4345 mkFormB(ptmp, invertCondTest(cond.test),
4346 cond.flag, (delta>>2), 0, 0);
4347 }
4348 goto done;
4349 }
4350
4351 case Pin_Load: {
4352 PPCAMode* am_addr = i->Pin.Load.src;
4353 UInt r_dst = iregNo(i->Pin.Load.dst, mode64);
4354 UInt opc1, opc2, sz = i->Pin.Load.sz;
4355 switch (am_addr->tag) {
4356 case Pam_IR:
4357 if (mode64 && (sz == 4 || sz == 8)) {
4358 /* should be guaranteed to us by iselWordExpr_AMode */
4359 vassert(0 == (am_addr->Pam.IR.index & 3));
4360 }
4361 switch(sz) {
4362 case 1: opc1 = 34; break;
4363 case 2: opc1 = 40; break;
4364 case 4: opc1 = 32; break;
4365 case 8: opc1 = 58; vassert(mode64); break;
4366 default: goto bad;
4367 }
4368 p = doAMode_IR(p, opc1, r_dst, am_addr, mode64);
4369 goto done;
4370 case Pam_RR:
4371 switch(sz) {
4372 case 1: opc2 = 87; break;
4373 case 2: opc2 = 279; break;
4374 case 4: opc2 = 23; break;
4375 case 8: opc2 = 21; vassert(mode64); break;
4376 default: goto bad;
4377 }
4378 p = doAMode_RR(p, 31, opc2, r_dst, am_addr, mode64);
4379 goto done;
4380 default:
4381 goto bad;
4382 }
4383 }
4384
4385 case Pin_LoadL: {
4386 if (i->Pin.LoadL.sz == 4) {
4387 p = mkFormX(p, 31, iregNo(i->Pin.LoadL.dst, mode64),
4388 0, iregNo(i->Pin.LoadL.src, mode64), 20, 0);
4389 goto done;
4390 }
4391 if (i->Pin.LoadL.sz == 8 && mode64) {
4392 p = mkFormX(p, 31, iregNo(i->Pin.LoadL.dst, mode64),
4393 0, iregNo(i->Pin.LoadL.src, mode64), 84, 0);
4394 goto done;
4395 }
4396 goto bad;
4397 }
4398
4399 case Pin_Set: {
4400 /* Make the destination register be 1 or 0, depending on whether
4401 the relevant condition holds. */
4402 UInt r_dst = iregNo(i->Pin.Set.dst, mode64);
4403 PPCCondCode cond = i->Pin.Set.cond;
4404 UInt rot_imm, r_tmp;
4405
4406 if (cond.test == Pct_ALWAYS) {
4407 // Just load 1 to dst => li dst,1
4408 p = mkFormD(p, 14, r_dst, 0, 1);
4409 } else {
4410 vassert(cond.flag != Pcf_NONE);
4411 rot_imm = 1 + cond.flag;
4412 r_tmp = 0; // Not set in getAllocable, so no need to declare.
4413
4414 // r_tmp = CR => mfcr r_tmp
4415 p = mkFormX(p, 31, r_tmp, 0, 0, 19, 0);
4416
4417 // r_dst = flag (rotate left and mask)
4418 // => rlwinm r_dst,r_tmp,rot_imm,31,31
4419 p = mkFormM(p, 21, r_tmp, r_dst, rot_imm, 31, 31, 0);
4420
4421 if (cond.test == Pct_FALSE) {
4422 // flip bit => xori r_dst,r_dst,1
4423 p = mkFormD(p, 26, r_dst, r_dst, 1);
4424 }
4425 }
4426 goto done;
4427 }
4428
4429 case Pin_MfCR:
4430 // mfcr dst
4431 p = mkFormX(p, 31, iregNo(i->Pin.MfCR.dst, mode64), 0, 0, 19, 0);
4432 goto done;
4433
4434 case Pin_MFence: {
4435 p = mkFormX(p, 31, 0, 0, 0, 598, 0); // sync, PPC32 p616
4436 // CAB: Should this be isync?
4437 // p = mkFormXL(p, 19, 0, 0, 0, 150, 0); // isync, PPC32 p467
4438 goto done;
4439 }
4440
4441 case Pin_Store: {
4442 PPCAMode* am_addr = i->Pin.Store.dst;
4443 UInt r_src = iregNo(i->Pin.Store.src, mode64);
4444 UInt opc1, opc2, sz = i->Pin.Store.sz;
4445 switch (i->Pin.Store.dst->tag) {
4446 case Pam_IR:
4447 if (mode64 && (sz == 4 || sz == 8)) {
4448 /* should be guaranteed to us by iselWordExpr_AMode */
4449 vassert(0 == (am_addr->Pam.IR.index & 3));
4450 }
4451 switch(sz) {
4452 case 1: opc1 = 38; break;
4453 case 2: opc1 = 44; break;
4454 case 4: opc1 = 36; break;
4455 case 8: vassert(mode64);
4456 opc1 = 62; break;
4457 default:
4458 goto bad;
4459 }
4460 p = doAMode_IR(p, opc1, r_src, am_addr, mode64);
4461 goto done;
4462 case Pam_RR:
4463 switch(sz) {
4464 case 1: opc2 = 215; break;
4465 case 2: opc2 = 407; break;
4466 case 4: opc2 = 151; break;
4467 case 8: vassert(mode64);
4468 opc2 = 149; break;
4469 default:
4470 goto bad;
4471 }
4472 p = doAMode_RR(p, 31, opc2, r_src, am_addr, mode64);
4473 goto done;
4474 default:
4475 goto bad;
4476 }
4477 goto done;
4478 }
4479
4480 case Pin_StoreC: {
4481 if (i->Pin.StoreC.sz == 4) {
4482 p = mkFormX(p, 31, iregNo(i->Pin.StoreC.src, mode64),
4483 0, iregNo(i->Pin.StoreC.dst, mode64), 150, 1);
4484 goto done;
4485 }
4486 if (i->Pin.StoreC.sz == 8 && mode64) {
4487 p = mkFormX(p, 31, iregNo(i->Pin.StoreC.src, mode64),
4488 0, iregNo(i->Pin.StoreC.dst, mode64), 214, 1);
4489 goto done;
4490 }
4491 goto bad;
4492 }
4493
4494 case Pin_FpUnary: {
4495 UInt fr_dst = fregNo(i->Pin.FpUnary.dst);
4496 UInt fr_src = fregNo(i->Pin.FpUnary.src);
4497 switch (i->Pin.FpUnary.op) {
4498 case Pfp_RSQRTE: // frsqrtre, PPC32 p424
4499 p = mkFormA( p, 63, fr_dst, 0, fr_src, 0, 26, 0 );
4500 break;
4501 case Pfp_RES: // fres, PPC32 p421
4502 p = mkFormA( p, 59, fr_dst, 0, fr_src, 0, 24, 0 );
4503 break;
4504 case Pfp_SQRT: // fsqrt, PPC32 p427
4505 p = mkFormA( p, 63, fr_dst, 0, fr_src, 0, 22, 0 );
4506 break;
4507 case Pfp_ABS: // fabs, PPC32 p399
4508 p = mkFormX(p, 63, fr_dst, 0, fr_src, 264, 0);
4509 break;
4510 case Pfp_NEG: // fneg, PPC32 p416
4511 p = mkFormX(p, 63, fr_dst, 0, fr_src, 40, 0);
4512 break;
4513 case Pfp_MOV: // fmr, PPC32 p410
4514 p = mkFormX(p, 63, fr_dst, 0, fr_src, 72, 0);
4515 break;
4516 case Pfp_FRIM: // frim, PPC ISA 2.05 p137
4517 p = mkFormX(p, 63, fr_dst, 0, fr_src, 488, 0);
4518 break;
4519 case Pfp_FRIP: // frip, PPC ISA 2.05 p137
4520 p = mkFormX(p, 63, fr_dst, 0, fr_src, 456, 0);
4521 break;
4522 case Pfp_FRIN: // frin, PPC ISA 2.05 p137
4523 p = mkFormX(p, 63, fr_dst, 0, fr_src, 392, 0);
4524 break;
4525 case Pfp_FRIZ: // friz, PPC ISA 2.05 p137
4526 p = mkFormX(p, 63, fr_dst, 0, fr_src, 424, 0);
4527 break;
4528 default:
4529 goto bad;
4530 }
4531 goto done;
4532 }
4533
4534 case Pin_FpBinary: {
4535 UInt fr_dst = fregNo(i->Pin.FpBinary.dst);
4536 UInt fr_srcL = fregNo(i->Pin.FpBinary.srcL);
4537 UInt fr_srcR = fregNo(i->Pin.FpBinary.srcR);
4538 switch (i->Pin.FpBinary.op) {
4539 case Pfp_ADDD: // fadd, PPC32 p400
4540 p = mkFormA( p, 63, fr_dst, fr_srcL, fr_srcR, 0, 21, 0 );
4541 break;
4542 case Pfp_ADDS: // fadds, PPC32 p401
4543 p = mkFormA( p, 59, fr_dst, fr_srcL, fr_srcR, 0, 21, 0 );
4544 break;
4545 case Pfp_SUBD: // fsub, PPC32 p429
4546 p = mkFormA( p, 63, fr_dst, fr_srcL, fr_srcR, 0, 20, 0 );
4547 break;
4548 case Pfp_SUBS: // fsubs, PPC32 p430
4549 p = mkFormA( p, 59, fr_dst, fr_srcL, fr_srcR, 0, 20, 0 );
4550 break;
4551 case Pfp_MULD: // fmul, PPC32 p413
4552 p = mkFormA( p, 63, fr_dst, fr_srcL, 0, fr_srcR, 25, 0 );
4553 break;
4554 case Pfp_MULS: // fmuls, PPC32 p414
4555 p = mkFormA( p, 59, fr_dst, fr_srcL, 0, fr_srcR, 25, 0 );
4556 break;
4557 case Pfp_DIVD: // fdiv, PPC32 p406
4558 p = mkFormA( p, 63, fr_dst, fr_srcL, fr_srcR, 0, 18, 0 );
4559 break;
4560 case Pfp_DIVS: // fdivs, PPC32 p407
4561 p = mkFormA( p, 59, fr_dst, fr_srcL, fr_srcR, 0, 18, 0 );
4562 break;
4563 default:
4564 goto bad;
4565 }
4566 goto done;
4567 }
4568
4569 case Pin_FpMulAcc: {
4570 UInt fr_dst = fregNo(i->Pin.FpMulAcc.dst);
4571 UInt fr_srcML = fregNo(i->Pin.FpMulAcc.srcML);
4572 UInt fr_srcMR = fregNo(i->Pin.FpMulAcc.srcMR);
4573 UInt fr_srcAcc = fregNo(i->Pin.FpMulAcc.srcAcc);
4574 switch (i->Pin.FpMulAcc.op) {
4575 case Pfp_MADDD: // fmadd, PPC32 p408
4576 p = mkFormA( p, 63, fr_dst, fr_srcML, fr_srcAcc, fr_srcMR, 29, 0 );
4577 break;
4578 case Pfp_MADDS: // fmadds, PPC32 p409
4579 p = mkFormA( p, 59, fr_dst, fr_srcML, fr_srcAcc, fr_srcMR, 29, 0 );
4580 break;
4581 case Pfp_MSUBD: // fmsub, PPC32 p411
4582 p = mkFormA( p, 63, fr_dst, fr_srcML, fr_srcAcc, fr_srcMR, 28, 0 );
4583 break;
4584 case Pfp_MSUBS: // fmsubs, PPC32 p412
4585 p = mkFormA( p, 59, fr_dst, fr_srcML, fr_srcAcc, fr_srcMR, 28, 0 );
4586 break;
4587 default:
4588 goto bad;
4589 }
4590 goto done;
4591 }
4592
4593 case Pin_FpLdSt: {
4594 PPCAMode* am_addr = i->Pin.FpLdSt.addr;
4595 UInt f_reg = fregNo(i->Pin.FpLdSt.reg);
4596 Bool idxd = toBool(i->Pin.FpLdSt.addr->tag == Pam_RR);
4597 UChar sz = i->Pin.FpLdSt.sz;
4598 UInt opc;
4599 vassert(sz == 4 || sz == 8);
4600
4601 if (i->Pin.FpLdSt.isLoad) { // Load from memory
4602 if (idxd) { // lf[s|d]x, PPC32 p444|440
4603 opc = (sz == 4) ? 535 : 599;
4604 p = doAMode_RR(p, 31, opc, f_reg, am_addr, mode64);
4605 } else { // lf[s|d], PPC32 p441|437
4606 opc = (sz == 4) ? 48 : 50;
4607 p = doAMode_IR(p, opc, f_reg, am_addr, mode64);
4608 }
4609 } else { // Store to memory
4610 if (idxd) { // stf[s|d]x, PPC32 p521|516
4611 opc = (sz == 4) ? 663 : 727;
4612 p = doAMode_RR(p, 31, opc, f_reg, am_addr, mode64);
4613 } else { // stf[s|d], PPC32 p518|513
4614 opc = (sz == 4) ? 52 : 54;
4615 p = doAMode_IR(p, opc, f_reg, am_addr, mode64);
4616 }
4617 }
4618 goto done;
4619 }
4620
4621 case Pin_FpSTFIW: {
4622 UInt ir_addr = iregNo(i->Pin.FpSTFIW.addr, mode64);
4623 UInt fr_data = fregNo(i->Pin.FpSTFIW.data);
4624 // stfiwx (store fp64[lo32] as int32), PPC32 p517
4625 // Use rA==0, so that EA == rB == ir_addr
4626 p = mkFormX(p, 31, fr_data, 0/*rA=0*/, ir_addr, 983, 0);
4627 goto done;
4628 }
4629
4630 case Pin_FpRSP: {
4631 UInt fr_dst = fregNo(i->Pin.FpRSP.dst);
4632 UInt fr_src = fregNo(i->Pin.FpRSP.src);
4633 // frsp, PPC32 p423
4634 p = mkFormX(p, 63, fr_dst, 0, fr_src, 12, 0);
4635 goto done;
4636 }
4637
4638 case Pin_FpCftI: {
4639 UInt fr_dst = fregNo(i->Pin.FpCftI.dst);
4640 UInt fr_src = fregNo(i->Pin.FpCftI.src);
4641 if (i->Pin.FpCftI.fromI == False && i->Pin.FpCftI.int32 == True) {
4642 if (i->Pin.FpCftI.syned == True) {
4643 // fctiw (conv f64 to i32), PPC32 p404
4644 p = mkFormX(p, 63, fr_dst, 0, fr_src, 14, 0);
4645 goto done;
4646 } else {
4647 // fctiwu (conv f64 to u32)
4648 p = mkFormX(p, 63, fr_dst, 0, fr_src, 142, 0);
4649 goto done;
4650 }
4651 }
4652 if (i->Pin.FpCftI.fromI == False && i->Pin.FpCftI.int32 == False) {
4653 if (i->Pin.FpCftI.syned == True) {
4654 // fctid (conv f64 to i64), PPC64 p437
4655 p = mkFormX(p, 63, fr_dst, 0, fr_src, 814, 0);
4656 goto done;
4657 } else {
4658 // fctidu (conv f64 to u64)
4659 p = mkFormX(p, 63, fr_dst, 0, fr_src, 942, 0);
4660 goto done;
4661 }
4662 }
4663 if (i->Pin.FpCftI.fromI == True && i->Pin.FpCftI.int32 == False) {
4664 if (i->Pin.FpCftI.syned == True) {
4665 // fcfid (conv i64 to f64), PPC64 p434
4666 p = mkFormX(p, 63, fr_dst, 0, fr_src, 846, 0);
4667 goto done;
4668 } else if (i->Pin.FpCftI.flt64 == True) {
4669 // fcfidu (conv u64 to f64)
4670 p = mkFormX(p, 63, fr_dst, 0, fr_src, 974, 0);
4671 goto done;
4672 } else {
4673 // fcfidus (conv u64 to f32)
4674 p = mkFormX(p, 59, fr_dst, 0, fr_src, 974, 0);
4675 goto done;
4676 }
4677 }
4678 goto bad;
4679 }
4680
4681 case Pin_FpCMov: {
4682 UInt fr_dst = fregNo(i->Pin.FpCMov.dst);
4683 UInt fr_src = fregNo(i->Pin.FpCMov.src);
4684 PPCCondCode cc = i->Pin.FpCMov.cond;
4685
4686 if (fr_dst == fr_src) goto done;
4687
4688 vassert(cc.test != Pct_ALWAYS);
4689
4690 /* jmp fwds if !condition */
4691 if (cc.test != Pct_ALWAYS) {
4692 /* bc !ct,cf,n_bytes>>2 */
4693 p = mkFormB(p, invertCondTest(cc.test), cc.flag, 8>>2, 0, 0);
4694 }
4695
4696 // fmr, PPC32 p410
4697 p = mkFormX(p, 63, fr_dst, 0, fr_src, 72, 0);
4698 goto done;
4699 }
4700
4701 case Pin_FpLdFPSCR: {
4702 UInt fr_src = fregNo(i->Pin.FpLdFPSCR.src);
4703 p = mkFormXFL(p, 0xFF, fr_src, i->Pin.FpLdFPSCR.dfp_rm); // mtfsf, PPC32 p480
4704 goto done;
4705 }
4706
4707 case Pin_FpCmp: {
4708 UChar crfD = 1;
4709 UInt r_dst = iregNo(i->Pin.FpCmp.dst, mode64);
4710 UInt fr_srcL = fregNo(i->Pin.FpCmp.srcL);
4711 UInt fr_srcR = fregNo(i->Pin.FpCmp.srcR);
4712 vassert(crfD < 8);
4713 // fcmpo, PPC32 p402
4714 p = mkFormX(p, 63, crfD<<2, fr_srcL, fr_srcR, 32, 0);
4715
4716 // mfcr (mv CR to r_dst), PPC32 p467
4717 p = mkFormX(p, 31, r_dst, 0, 0, 19, 0);
4718
4719 // rlwinm r_dst,r_dst,8,28,31, PPC32 p501
4720 // => rotate field 1 to bottomw of word, masking out upper 28
4721 p = mkFormM(p, 21, r_dst, r_dst, 8, 28, 31, 0);
4722 goto done;
4723 }
4724
4725 case Pin_RdWrLR: {
4726 UInt reg = iregNo(i->Pin.RdWrLR.gpr, mode64);
4727 /* wrLR==True ? mtlr r4 : mflr r4 */
4728 p = mkFormXFX(p, reg, 8, (i->Pin.RdWrLR.wrLR==True) ? 467 : 339);
4729 goto done;
4730 }
4731
4732
4733 /* AltiVec */
4734 case Pin_AvLdSt: {
4735 UInt opc2, v_reg, r_idx, r_base;
4736 UChar sz = i->Pin.AvLdSt.sz;
4737 Bool idxd = toBool(i->Pin.AvLdSt.addr->tag == Pam_RR);
4738 vassert(sz == 1 || sz == 2 || sz == 4 || sz == 16);
4739
4740 v_reg = vregNo(i->Pin.AvLdSt.reg);
4741 r_base = iregNo(i->Pin.AvLdSt.addr->Pam.RR.base, mode64);
4742
4743 // Only have AltiVec AMode_RR: kludge AMode_IR
4744 if (!idxd) {
4745 r_idx = 30; // XXX: Using r30 as temp
4746 p = mkLoadImm(p, r_idx,
4747 i->Pin.AvLdSt.addr->Pam.IR.index, mode64);
4748 } else {
4749 r_idx = iregNo(i->Pin.AvLdSt.addr->Pam.RR.index, mode64);
4750 }
4751
4752 if (i->Pin.FpLdSt.isLoad) { // Load from memory (1,2,4,16)
4753 opc2 = (sz==1) ? 7 : (sz==2) ? 39 : (sz==4) ? 71 : 103;
4754 p = mkFormX(p, 31, v_reg, r_idx, r_base, opc2, 0);
4755 } else { // Store to memory (1,2,4,16)
4756 opc2 = (sz==1) ? 135 : (sz==2) ? 167 : (sz==4) ? 199 : 231;
4757 p = mkFormX(p, 31, v_reg, r_idx, r_base, opc2, 0);
4758 }
4759 goto done;
4760 }
4761
4762 case Pin_AvUnary: {
4763 UInt v_dst = vregNo(i->Pin.AvUnary.dst);
4764 UInt v_src = vregNo(i->Pin.AvUnary.src);
4765 UInt opc2;
4766 switch (i->Pin.AvUnary.op) {
4767 case Pav_MOV: opc2 = 1156; break; // vor vD,vS,vS
4768 case Pav_NOT: opc2 = 1284; break; // vnor vD,vS,vS
4769 case Pav_UNPCKH8S: opc2 = 526; break; // vupkhsb
4770 case Pav_UNPCKH16S: opc2 = 590; break; // vupkhsh
4771 case Pav_UNPCKL8S: opc2 = 654; break; // vupklsb
4772 case Pav_UNPCKL16S: opc2 = 718; break; // vupklsh
4773 case Pav_UNPCKHPIX: opc2 = 846; break; // vupkhpx
4774 case Pav_UNPCKLPIX: opc2 = 974; break; // vupklpx
4775
4776 case Pav_ZEROCNTBYTE: opc2 = 1794; break; // vclzb
4777 case Pav_ZEROCNTHALF: opc2 = 1858; break; // vclzh
4778 case Pav_ZEROCNTWORD: opc2 = 1922; break; // vclzw
4779 case Pav_ZEROCNTDBL: opc2 = 1986; break; // vclzd
4780 case Pav_BITMTXXPOSE: opc2 = 1292; break; // vgbbd
4781 default:
4782 goto bad;
4783 }
4784 switch (i->Pin.AvUnary.op) {
4785 case Pav_MOV:
4786 case Pav_NOT:
4787 p = mkFormVX( p, 4, v_dst, v_src, v_src, opc2 );
4788 break;
4789 default:
4790 p = mkFormVX( p, 4, v_dst, 0, v_src, opc2 );
4791 break;
4792 }
4793 goto done;
4794 }
4795
4796 case Pin_AvBinary: {
4797 UInt v_dst = vregNo(i->Pin.AvBinary.dst);
4798 UInt v_srcL = vregNo(i->Pin.AvBinary.srcL);
4799 UInt v_srcR = vregNo(i->Pin.AvBinary.srcR);
4800 UInt opc2;
4801 if (i->Pin.AvBinary.op == Pav_SHL) {
4802 p = mkFormVX( p, 4, v_dst, v_srcL, v_srcR, 1036 ); // vslo
4803 p = mkFormVX( p, 4, v_dst, v_dst, v_srcR, 452 ); // vsl
4804 goto done;
4805 }
4806 if (i->Pin.AvBinary.op == Pav_SHR) {
4807 p = mkFormVX( p, 4, v_dst, v_srcL, v_srcR, 1100 ); // vsro
4808 p = mkFormVX( p, 4, v_dst, v_dst, v_srcR, 708 ); // vsr
4809 goto done;
4810 }
4811 switch (i->Pin.AvBinary.op) {
4812 /* Bitwise */
4813 case Pav_AND: opc2 = 1028; break; // vand
4814 case Pav_OR: opc2 = 1156; break; // vor
4815 case Pav_XOR: opc2 = 1220; break; // vxor
4816 default:
4817 goto bad;
4818 }
4819 p = mkFormVX( p, 4, v_dst, v_srcL, v_srcR, opc2 );
4820 goto done;
4821 }
4822
4823 case Pin_AvBin8x16: {
4824 UInt v_dst = vregNo(i->Pin.AvBin8x16.dst);
4825 UInt v_srcL = vregNo(i->Pin.AvBin8x16.srcL);
4826 UInt v_srcR = vregNo(i->Pin.AvBin8x16.srcR);
4827 UInt opc2;
4828 switch (i->Pin.AvBin8x16.op) {
4829
4830 case Pav_ADDU: opc2 = 0; break; // vaddubm
4831 case Pav_QADDU: opc2 = 512; break; // vaddubs
4832 case Pav_QADDS: opc2 = 768; break; // vaddsbs
4833
4834 case Pav_SUBU: opc2 = 1024; break; // vsububm
4835 case Pav_QSUBU: opc2 = 1536; break; // vsububs
4836 case Pav_QSUBS: opc2 = 1792; break; // vsubsbs
4837
4838 case Pav_OMULU: opc2 = 8; break; // vmuloub
4839 case Pav_OMULS: opc2 = 264; break; // vmulosb
4840 case Pav_EMULU: opc2 = 520; break; // vmuleub
4841 case Pav_EMULS: opc2 = 776; break; // vmulesb
4842
4843 case Pav_AVGU: opc2 = 1026; break; // vavgub
4844 case Pav_AVGS: opc2 = 1282; break; // vavgsb
4845 case Pav_MAXU: opc2 = 2; break; // vmaxub
4846 case Pav_MAXS: opc2 = 258; break; // vmaxsb
4847 case Pav_MINU: opc2 = 514; break; // vminub
4848 case Pav_MINS: opc2 = 770; break; // vminsb
4849
4850 case Pav_CMPEQU: opc2 = 6; break; // vcmpequb
4851 case Pav_CMPGTU: opc2 = 518; break; // vcmpgtub
4852 case Pav_CMPGTS: opc2 = 774; break; // vcmpgtsb
4853
4854 case Pav_SHL: opc2 = 260; break; // vslb
4855 case Pav_SHR: opc2 = 516; break; // vsrb
4856 case Pav_SAR: opc2 = 772; break; // vsrab
4857 case Pav_ROTL: opc2 = 4; break; // vrlb
4858
4859 case Pav_MRGHI: opc2 = 12; break; // vmrghb
4860 case Pav_MRGLO: opc2 = 268; break; // vmrglb
4861
4862 case Pav_POLYMULADD: opc2 = 1032; break; // vpmsumb
4863
4864 default:
4865 goto bad;
4866 }
4867 p = mkFormVX( p, 4, v_dst, v_srcL, v_srcR, opc2 );
4868 goto done;
4869 }
4870
4871 case Pin_AvBin16x8: {
4872 UInt v_dst = vregNo(i->Pin.AvBin16x8.dst);
4873 UInt v_srcL = vregNo(i->Pin.AvBin16x8.srcL);
4874 UInt v_srcR = vregNo(i->Pin.AvBin16x8.srcR);
4875 UInt opc2;
4876 switch (i->Pin.AvBin16x8.op) {
4877
4878 case Pav_ADDU: opc2 = 64; break; // vadduhm
4879 case Pav_QADDU: opc2 = 576; break; // vadduhs
4880 case Pav_QADDS: opc2 = 832; break; // vaddshs
4881
4882 case Pav_SUBU: opc2 = 1088; break; // vsubuhm
4883 case Pav_QSUBU: opc2 = 1600; break; // vsubuhs
4884 case Pav_QSUBS: opc2 = 1856; break; // vsubshs
4885
4886 case Pav_OMULU: opc2 = 72; break; // vmulouh
4887 case Pav_OMULS: opc2 = 328; break; // vmulosh
4888 case Pav_EMULU: opc2 = 584; break; // vmuleuh
4889 case Pav_EMULS: opc2 = 840; break; // vmulesh
4890
4891 case Pav_AVGU: opc2 = 1090; break; // vavguh
4892 case Pav_AVGS: opc2 = 1346; break; // vavgsh
4893 case Pav_MAXU: opc2 = 66; break; // vmaxuh
4894 case Pav_MAXS: opc2 = 322; break; // vmaxsh
4895 case Pav_MINS: opc2 = 834; break; // vminsh
4896 case Pav_MINU: opc2 = 578; break; // vminuh
4897
4898 case Pav_CMPEQU: opc2 = 70; break; // vcmpequh
4899 case Pav_CMPGTU: opc2 = 582; break; // vcmpgtuh
4900 case Pav_CMPGTS: opc2 = 838; break; // vcmpgtsh
4901
4902 case Pav_SHL: opc2 = 324; break; // vslh
4903 case Pav_SHR: opc2 = 580; break; // vsrh
4904 case Pav_SAR: opc2 = 836; break; // vsrah
4905 case Pav_ROTL: opc2 = 68; break; // vrlh
4906
4907 case Pav_PACKUU: opc2 = 14; break; // vpkuhum
4908 case Pav_QPACKUU: opc2 = 142; break; // vpkuhus
4909 case Pav_QPACKSU: opc2 = 270; break; // vpkshus
4910 case Pav_QPACKSS: opc2 = 398; break; // vpkshss
4911 case Pav_PACKPXL: opc2 = 782; break; // vpkpx
4912
4913 case Pav_MRGHI: opc2 = 76; break; // vmrghh
4914 case Pav_MRGLO: opc2 = 332; break; // vmrglh
4915
4916 case Pav_POLYMULADD: opc2 = 1224; break; // vpmsumh
4917
4918 default:
4919 goto bad;
4920 }
4921 p = mkFormVX( p, 4, v_dst, v_srcL, v_srcR, opc2 );
4922 goto done;
4923 }
4924
4925 case Pin_AvBin32x4: {
4926 UInt v_dst = vregNo(i->Pin.AvBin32x4.dst);
4927 UInt v_srcL = vregNo(i->Pin.AvBin32x4.srcL);
4928 UInt v_srcR = vregNo(i->Pin.AvBin32x4.srcR);
4929 UInt opc2;
4930 switch (i->Pin.AvBin32x4.op) {
4931
4932 case Pav_ADDU: opc2 = 128; break; // vadduwm
4933 case Pav_QADDU: opc2 = 640; break; // vadduws
4934 case Pav_QADDS: opc2 = 896; break; // vaddsws
4935
4936 case Pav_SUBU: opc2 = 1152; break; // vsubuwm
4937 case Pav_QSUBU: opc2 = 1664; break; // vsubuws
4938 case Pav_QSUBS: opc2 = 1920; break; // vsubsws
4939
4940 case Pav_MULU: opc2 = 137; break; // vmuluwm
4941 case Pav_OMULU: opc2 = 136; break; // vmulouw
4942 case Pav_OMULS: opc2 = 392; break; // vmulosw
4943 case Pav_EMULU: opc2 = 648; break; // vmuleuw
4944 case Pav_EMULS: opc2 = 904; break; // vmulesw
4945
4946 case Pav_AVGU: opc2 = 1154; break; // vavguw
4947 case Pav_AVGS: opc2 = 1410; break; // vavgsw
4948
4949 case Pav_MAXU: opc2 = 130; break; // vmaxuw
4950 case Pav_MAXS: opc2 = 386; break; // vmaxsw
4951
4952 case Pav_MINS: opc2 = 898; break; // vminsw
4953 case Pav_MINU: opc2 = 642; break; // vminuw
4954
4955 case Pav_CMPEQU: opc2 = 134; break; // vcmpequw
4956 case Pav_CMPGTS: opc2 = 902; break; // vcmpgtsw
4957 case Pav_CMPGTU: opc2 = 646; break; // vcmpgtuw
4958
4959 case Pav_SHL: opc2 = 388; break; // vslw
4960 case Pav_SHR: opc2 = 644; break; // vsrw
4961 case Pav_SAR: opc2 = 900; break; // vsraw
4962 case Pav_ROTL: opc2 = 132; break; // vrlw
4963
4964 case Pav_PACKUU: opc2 = 78; break; // vpkuwum
4965 case Pav_QPACKUU: opc2 = 206; break; // vpkuwus
4966 case Pav_QPACKSU: opc2 = 334; break; // vpkswus
4967 case Pav_QPACKSS: opc2 = 462; break; // vpkswss
4968
4969 case Pav_MRGHI: opc2 = 140; break; // vmrghw
4970 case Pav_MRGLO: opc2 = 396; break; // vmrglw
4971
4972 case Pav_CATODD: opc2 = 1676; break; // vmrgow
4973 case Pav_CATEVEN: opc2 = 1932; break; // vmrgew
4974
4975 case Pav_POLYMULADD: opc2 = 1160; break; // vpmsumw
4976
4977 default:
4978 goto bad;
4979 }
4980 p = mkFormVX( p, 4, v_dst, v_srcL, v_srcR, opc2 );
4981 goto done;
4982 }
4983
4984 case Pin_AvBin64x2: {
4985 UInt v_dst = vregNo(i->Pin.AvBin64x2.dst);
4986 UInt v_srcL = vregNo(i->Pin.AvBin64x2.srcL);
4987 UInt v_srcR = vregNo(i->Pin.AvBin64x2.srcR);
4988 UInt opc2;
4989 switch (i->Pin.AvBin64x2.op) {
4990 case Pav_ADDU: opc2 = 192; break; // vaddudm vector double add
4991 case Pav_SUBU: opc2 = 1216; break; // vsubudm vector double add
4992 case Pav_MAXU: opc2 = 194; break; // vmaxud vector double max
4993 case Pav_MAXS: opc2 = 450; break; // vmaxsd vector double max
4994 case Pav_MINU: opc2 = 706; break; // vminud vector double min
4995 case Pav_MINS: opc2 = 962; break; // vminsd vector double min
4996 case Pav_CMPEQU: opc2 = 199; break; // vcmpequd vector double compare
4997 case Pav_CMPGTU: opc2 = 711; break; // vcmpgtud vector double compare
4998 case Pav_CMPGTS: opc2 = 967; break; // vcmpgtsd vector double compare
4999 case Pav_SHL: opc2 = 1476; break; // vsld
5000 case Pav_SHR: opc2 = 1732; break; // vsrd
5001 case Pav_SAR: opc2 = 964; break; // vsrad
5002 case Pav_ROTL: opc2 = 196; break; // vrld
5003 case Pav_PACKUU: opc2 = 1102; break; // vpkudum
5004 case Pav_QPACKUU: opc2 = 1230; break; // vpkudus, vpksdus (emulated)
5005 case Pav_QPACKSS: opc2 = 1486; break; // vpksdsm
5006 case Pav_MRGHI: opc2 = 1614; break; // vmrghw
5007 case Pav_MRGLO: opc2 = 1742; break; // vmrglw
5008 case Pav_POLYMULADD: opc2 = 1096; break; // vpmsumd
5009 default:
5010 goto bad;
5011 }
5012 p = mkFormVX( p, 4, v_dst, v_srcL, v_srcR, opc2 );
5013 goto done;
5014 }
5015 case Pin_AvCipherV128Unary: {
5016 UInt v_dst = vregNo(i->Pin.AvCipherV128Unary.dst);
5017 UInt v_src = vregNo(i->Pin.AvCipherV128Unary.src);
5018 UInt opc2;
5019 switch (i->Pin.AvCipherV128Unary.op) {
5020 case Pav_CIPHERSUBV128: opc2 = 1480; break; // vsbox
5021 default:
5022 goto bad;
5023 }
5024 p = mkFormVX( p, 4, v_dst, v_src, 0, opc2 );
5025 goto done;
5026 }
5027 case Pin_AvCipherV128Binary: {
5028 UInt v_dst = vregNo(i->Pin.AvCipherV128Binary.dst);
5029 UInt v_srcL = vregNo(i->Pin.AvCipherV128Binary.srcL);
5030 UInt v_srcR = vregNo(i->Pin.AvCipherV128Binary.srcR);
5031 UInt opc2;
5032 switch (i->Pin.AvCipherV128Binary.op) {
5033 case Pav_CIPHERV128: opc2 = 1288; break; // vcipher
5034 case Pav_CIPHERLV128: opc2 = 1289; break; // vcipherlast
5035 case Pav_NCIPHERV128: opc2 = 1352; break; // vncipher
5036 case Pav_NCIPHERLV128: opc2 = 1353; break; // vncipherlast
5037 default:
5038 goto bad;
5039 }
5040 p = mkFormVX( p, 4, v_dst, v_srcL, v_srcR, opc2 );
5041 goto done;
5042 }
5043 case Pin_AvHashV128Binary: {
5044 UInt v_dst = vregNo(i->Pin.AvHashV128Binary.dst);
5045 UInt v_src = vregNo(i->Pin.AvHashV128Binary.src);
5046 PPCRI* s_field = i->Pin.AvHashV128Binary.s_field;
5047 UInt opc2;
5048 switch (i->Pin.AvHashV128Binary.op) {
5049 case Pav_SHA256: opc2 = 1666; break; // vshasigmaw
5050 case Pav_SHA512: opc2 = 1730; break; // vshasigmad
5051 default:
5052 goto bad;
5053 }
5054 p = mkFormVX( p, 4, v_dst, v_src, s_field->Pri.Imm, opc2 );
5055 goto done;
5056 }
5057 case Pin_AvBCDV128Trinary: {
5058 UInt v_dst = vregNo(i->Pin.AvBCDV128Trinary.dst);
5059 UInt v_src1 = vregNo(i->Pin.AvBCDV128Trinary.src1);
5060 UInt v_src2 = vregNo(i->Pin.AvBCDV128Trinary.src2);
5061 PPCRI* ps = i->Pin.AvBCDV128Trinary.ps;
5062 UInt opc2;
5063 switch (i->Pin.AvBCDV128Trinary.op) {
5064 case Pav_BCDAdd: opc2 = 1; break; // bcdadd
5065 case Pav_BCDSub: opc2 = 65; break; // bcdsub
5066 default:
5067 goto bad;
5068 }
5069 p = mkFormVXR( p, 4, v_dst, v_src1, v_src2,
5070 0x1, (ps->Pri.Imm << 9) | opc2 );
5071 goto done;
5072 }
5073 case Pin_AvBin32Fx4: {
5074 UInt v_dst = vregNo(i->Pin.AvBin32Fx4.dst);
5075 UInt v_srcL = vregNo(i->Pin.AvBin32Fx4.srcL);
5076 UInt v_srcR = vregNo(i->Pin.AvBin32Fx4.srcR);
5077 switch (i->Pin.AvBin32Fx4.op) {
5078
5079 case Pavfp_ADDF:
5080 p = mkFormVX( p, 4, v_dst, v_srcL, v_srcR, 10 ); // vaddfp
5081 break;
5082 case Pavfp_SUBF:
5083 p = mkFormVX( p, 4, v_dst, v_srcL, v_srcR, 74 ); // vsubfp
5084 break;
5085 case Pavfp_MAXF:
5086 p = mkFormVX( p, 4, v_dst, v_srcL, v_srcR, 1034 ); // vmaxfp
5087 break;
5088 case Pavfp_MINF:
5089 p = mkFormVX( p, 4, v_dst, v_srcL, v_srcR, 1098 ); // vminfp
5090 break;
5091
5092 case Pavfp_MULF: {
5093 /* Make a vmulfp from a vmaddfp:
5094 load -0.0 (0x8000_0000) to each 32-bit word of vB
5095 this makes the add a noop.
5096 */
5097 UInt vB = 29; // XXX: Using v29 for temp do not change
5098 // without also changing
5099 // getRegUsage_PPCInstr
5100 UInt konst = 0x1F;
5101
5102 // Better way to load -0.0 (0x80000000) ?
5103 // vspltisw vB,0x1F (0x1F => each word of vB)
5104 p = mkFormVX( p, 4, vB, konst, 0, 908 );
5105
5106 // vslw vB,vB,vB (each word of vB = (0x1F << 0x1F) = 0x80000000
5107 p = mkFormVX( p, 4, vB, vB, vB, 388 );
5108
5109 // Finally, do the multiply:
5110 p = mkFormVA( p, 4, v_dst, v_srcL, vB, v_srcR, 46 );
5111 break;
5112 }
5113 case Pavfp_CMPEQF: // vcmpeqfp
5114 p = mkFormVXR( p, 4, v_dst, v_srcL, v_srcR, 0, 198 );
5115 break;
5116 case Pavfp_CMPGTF: // vcmpgtfp
5117 p = mkFormVXR( p, 4, v_dst, v_srcL, v_srcR, 0, 710 );
5118 break;
5119 case Pavfp_CMPGEF: // vcmpgefp
5120 p = mkFormVXR( p, 4, v_dst, v_srcL, v_srcR, 0, 454 );
5121 break;
5122
5123 default:
5124 goto bad;
5125 }
5126 goto done;
5127 }
5128
5129 case Pin_AvUn32Fx4: {
5130 UInt v_dst = vregNo(i->Pin.AvUn32Fx4.dst);
5131 UInt v_src = vregNo(i->Pin.AvUn32Fx4.src);
5132 UInt opc2;
5133 switch (i->Pin.AvUn32Fx4.op) {
5134 case Pavfp_RCPF: opc2 = 266; break; // vrefp
5135 case Pavfp_RSQRTF: opc2 = 330; break; // vrsqrtefp
5136 case Pavfp_CVTU2F: opc2 = 778; break; // vcfux
5137 case Pavfp_CVTS2F: opc2 = 842; break; // vcfsx
5138 case Pavfp_QCVTF2U: opc2 = 906; break; // vctuxs
5139 case Pavfp_QCVTF2S: opc2 = 970; break; // vctsxs
5140 case Pavfp_ROUNDM: opc2 = 714; break; // vrfim
5141 case Pavfp_ROUNDP: opc2 = 650; break; // vrfip
5142 case Pavfp_ROUNDN: opc2 = 522; break; // vrfin
5143 case Pavfp_ROUNDZ: opc2 = 586; break; // vrfiz
5144 default:
5145 goto bad;
5146 }
5147 p = mkFormVX( p, 4, v_dst, 0, v_src, opc2 );
5148 goto done;
5149 }
5150
5151 case Pin_AvPerm: { // vperm
5152 UInt v_dst = vregNo(i->Pin.AvPerm.dst);
5153 UInt v_srcL = vregNo(i->Pin.AvPerm.srcL);
5154 UInt v_srcR = vregNo(i->Pin.AvPerm.srcR);
5155 UInt v_ctl = vregNo(i->Pin.AvPerm.ctl);
5156 p = mkFormVA( p, 4, v_dst, v_srcL, v_srcR, v_ctl, 43 );
5157 goto done;
5158 }
5159
5160 case Pin_AvSel: { // vsel
5161 UInt v_ctl = vregNo(i->Pin.AvSel.ctl);
5162 UInt v_dst = vregNo(i->Pin.AvSel.dst);
5163 UInt v_srcL = vregNo(i->Pin.AvSel.srcL);
5164 UInt v_srcR = vregNo(i->Pin.AvSel.srcR);
5165 p = mkFormVA( p, 4, v_dst, v_srcL, v_srcR, v_ctl, 42 );
5166 goto done;
5167 }
5168
5169 case Pin_AvShlDbl: { // vsldoi
5170 UInt shift = i->Pin.AvShlDbl.shift;
5171 UInt v_dst = vregNo(i->Pin.AvShlDbl.dst);
5172 UInt v_srcL = vregNo(i->Pin.AvShlDbl.srcL);
5173 UInt v_srcR = vregNo(i->Pin.AvShlDbl.srcR);
5174 vassert(shift <= 0xF);
5175 p = mkFormVA( p, 4, v_dst, v_srcL, v_srcR, shift, 44 );
5176 goto done;
5177 }
5178
5179 case Pin_AvSplat: { // vsplt(is)(b,h,w)
5180 UInt v_dst = vregNo(i->Pin.AvShlDbl.dst);
5181 UChar sz = i->Pin.AvSplat.sz;
5182 UInt v_src, opc2;
5183 vassert(sz == 8 || sz == 16 || sz == 32);
5184
5185 if (i->Pin.AvSplat.src->tag == Pvi_Imm) {
5186 Char simm5;
5187 opc2 = (sz == 8) ? 780 : (sz == 16) ? 844 : 908; // 8,16,32
5188 /* expects 5-bit-signed-imm */
5189 simm5 = i->Pin.AvSplat.src->Pvi.Imm5s;
5190 vassert(simm5 >= -16 && simm5 <= 15);
5191 simm5 = simm5 & 0x1F;
5192 p = mkFormVX( p, 4, v_dst, (UInt)simm5, 0, opc2 );
5193 }
5194 else { // Pri_Reg
5195 UInt lowest_lane;
5196 opc2 = (sz == 8) ? 524 : (sz == 16) ? 588 : 652; // 8,16,32
5197 vassert(hregClass(i->Pin.AvSplat.src->Pvi.Reg) == HRcVec128);
5198 v_src = vregNo(i->Pin.AvSplat.src->Pvi.Reg);
5199 lowest_lane = (128/sz)-1;
5200 p = mkFormVX( p, 4, v_dst, lowest_lane, v_src, opc2 );
5201 }
5202 goto done;
5203 }
5204
5205 case Pin_AvCMov: {
5206 UInt v_dst = vregNo(i->Pin.AvCMov.dst);
5207 UInt v_src = vregNo(i->Pin.AvCMov.src);
5208 PPCCondCode cc = i->Pin.AvCMov.cond;
5209
5210 if (v_dst == v_src) goto done;
5211
5212 vassert(cc.test != Pct_ALWAYS);
5213
5214 /* jmp fwds 2 insns if !condition */
5215 if (cc.test != Pct_ALWAYS) {
5216 /* bc !ct,cf,n_bytes>>2 */
5217 p = mkFormB(p, invertCondTest(cc.test), cc.flag, 8>>2, 0, 0);
5218 }
5219 /* vmr */
5220 p = mkFormVX( p, 4, v_dst, v_src, v_src, 1156 );
5221 goto done;
5222 }
5223
5224 case Pin_AvLdVSCR: { // mtvscr
5225 UInt v_src = vregNo(i->Pin.AvLdVSCR.src);
5226 p = mkFormVX( p, 4, 0, 0, v_src, 1604 );
5227 goto done;
5228 }
5229
5230 case Pin_Dfp64Unary: {
5231 UInt fr_dst = fregNo( i->Pin.FpUnary.dst );
5232 UInt fr_src = fregNo( i->Pin.FpUnary.src );
5233
5234 switch (i->Pin.Dfp64Unary.op) {
5235 case Pfp_MOV: // fmr, PPC32 p410
5236 p = mkFormX( p, 63, fr_dst, 0, fr_src, 72, 0 );
5237 break;
5238 case Pfp_DCTDP: // D32 to D64
5239 p = mkFormX( p, 59, fr_dst, 0, fr_src, 258, 0 );
5240 break;
5241 case Pfp_DRSP: // D64 to D32
5242 p = mkFormX( p, 59, fr_dst, 0, fr_src, 770, 0 );
5243 break;
5244 case Pfp_DCFFIX: // I64 to D64 conversion
5245 /* ONLY WORKS ON POWER7 */
5246 p = mkFormX( p, 59, fr_dst, 0, fr_src, 802, 0);
5247 break;
5248 case Pfp_DCTFIX: // D64 to I64 conversion
5249 p = mkFormX( p, 59, fr_dst, 0, fr_src, 290, 0);
5250 break;
5251 case Pfp_DXEX: // Extract exponent
5252 p = mkFormX( p, 59, fr_dst, 0, fr_src, 354, 0 );
5253 break;
5254 default:
5255 goto bad;
5256 }
5257 goto done;
5258 }
5259
5260 case Pin_Dfp64Binary: {
5261 UInt fr_dst = fregNo( i->Pin.Dfp64Binary.dst );
5262 UInt fr_srcL = fregNo( i->Pin.Dfp64Binary.srcL );
5263 UInt fr_srcR = fregNo( i->Pin.Dfp64Binary.srcR );
5264 switch (i->Pin.Dfp64Binary.op) {
5265 case Pfp_DFPADD: /* dadd, dfp add, use default RM from reg ignore mode
5266 * from the Iop instruction. */
5267 p = mkFormX( p, 59, fr_dst, fr_srcL, fr_srcR, 2, 0 );
5268 break;
5269 case Pfp_DFPSUB: /* dsub, dfp subtract, use default RM from reg ignore
5270 * mode from the Iop instruction. */
5271 p = mkFormX( p, 59, fr_dst, fr_srcL, fr_srcR, 514, 0 );
5272 break;
5273 case Pfp_DFPMUL: /* dmul, dfp multipy, use default RM from reg ignore
5274 * mode from the Iop instruction. */
5275 p = mkFormX( p, 59, fr_dst, fr_srcL, fr_srcR, 34, 0 );
5276 break;
5277 case Pfp_DFPDIV: /* ddiv, dfp divide, use default RM from reg ignore
5278 * mode from the Iop instruction. */
5279 p = mkFormX( p, 59, fr_dst, fr_srcL, fr_srcR, 546, 0 );
5280 break;
5281 case Pfp_DIEX: /* diex, insert exponent */
5282 p = mkFormX( p, 59, fr_dst, fr_srcL, fr_srcR, 866, 0 );
5283 break;
5284 default:
5285 goto bad;
5286 }
5287 goto done;
5288 }
5289
5290 case Pin_DfpShift: {
5291 UInt fr_src = fregNo(i->Pin.DfpShift.src);
5292 UInt fr_dst = fregNo(i->Pin.DfpShift.dst);
5293 UInt shift;
5294
5295 shift = i->Pin.DfpShift.shift->Pri.Imm;
5296
5297 switch (i->Pin.DfpShift.op) {
5298 case Pfp_DSCLI: /* dscli, DFP shift left by fr_srcR */
5299 p = mkFormZ22( p, 59, fr_dst, fr_src, shift, 66, 0 );
5300 break;
5301 case Pfp_DSCRI: /* dscri, DFP shift right by fr_srcR */
5302 p = mkFormZ22( p, 59, fr_dst, fr_src, shift, 98, 0 );
5303 break;
5304 default:
5305 vex_printf("ERROR: emit_PPCInstr default case\n");
5306 goto bad;
5307 }
5308 goto done;
5309 }
5310
5311 case Pin_ExtractExpD128: {
5312 UInt fr_dst = fregNo(i->Pin.ExtractExpD128.dst);
5313 UInt fr_srcHi = fregNo(i->Pin.ExtractExpD128.src_hi);
5314 UInt fr_srcLo = fregNo(i->Pin.ExtractExpD128.src_lo);
5315
5316 switch (i->Pin.ExtractExpD128.op) {
5317 case Pfp_DXEXQ:
5318 /* Setup the upper and lower registers of the source operand
5319 * register pair.
5320 */
5321 p = mkFormX( p, 63, 12, 0, fr_srcHi, 72, 0);
5322 p = mkFormX( p, 63, 13, 0, fr_srcLo, 72, 0);
5323 p = mkFormX( p, 63, 10, 0, 12, 354, 0 );
5324
5325 /* The instruction will put the 64-bit result in
5326 * register 10.
5327 */
5328 p = mkFormX(p, 63, fr_dst, 0, 10, 72, 0);
5329 break;
5330 default:
5331 vex_printf("Error: emit_PPCInstr case Pin_DfpExtractExp, case inst Default\n");
5332 goto bad;
5333 }
5334 goto done;
5335 }
5336 case Pin_Dfp128Unary: {
5337 UInt fr_dstHi = fregNo(i->Pin.Dfp128Unary.dst_hi);
5338 UInt fr_dstLo = fregNo(i->Pin.Dfp128Unary.dst_lo);
5339 UInt fr_srcLo = fregNo(i->Pin.Dfp128Unary.src_lo);
5340
5341 /* Do instruction with 128-bit source operands in registers (10,11)
5342 * and (12,13).
5343 */
5344 switch (i->Pin.Dfp128Unary.op) {
5345 case Pfp_DCTQPQ: // D64 to D128, srcLo holds 64 bit operand
5346 p = mkFormX( p, 63, 12, 0, fr_srcLo, 72, 0);
5347
5348 p = mkFormX( p, 63, 10, 0, 12, 258, 0 );
5349
5350 /* The instruction will put the 128-bit result in
5351 * registers (10,11). Note, the operand in the instruction only
5352 * reference the first of the two registers in the pair.
5353 */
5354 p = mkFormX(p, 63, fr_dstHi, 0, 10, 72, 0);
5355 p = mkFormX(p, 63, fr_dstLo, 0, 11, 72, 0);
5356 break;
5357 default:
5358 vex_printf("Error: emit_PPCInstr case Pin_Dfp128Unary, case inst Default\
5359 \n");
5360 goto bad;
5361 }
5362 goto done;
5363 }
5364
5365 case Pin_Dfp128Binary: {
5366 /* dst is used to supply the left source operand and return
5367 * the result.
5368 */
5369 UInt fr_dstHi = fregNo( i->Pin.Dfp128Binary.dst_hi );
5370 UInt fr_dstLo = fregNo( i->Pin.Dfp128Binary.dst_lo );
5371 UInt fr_srcRHi = fregNo( i->Pin.Dfp128Binary.srcR_hi );
5372 UInt fr_srcRLo = fregNo( i->Pin.Dfp128Binary.srcR_lo );
5373
5374 /* Setup the upper and lower registers of the source operand
5375 * register pair.
5376 */
5377 p = mkFormX( p, 63, 10, 0, fr_dstHi, 72, 0 );
5378 p = mkFormX( p, 63, 11, 0, fr_dstLo, 72, 0 );
5379 p = mkFormX( p, 63, 12, 0, fr_srcRHi, 72, 0 );
5380 p = mkFormX( p, 63, 13, 0, fr_srcRLo, 72, 0 );
5381
5382 /* Do instruction with 128-bit source operands in registers (10,11)
5383 * and (12,13).
5384 */
5385 switch (i->Pin.Dfp128Binary.op) {
5386 case Pfp_DFPADDQ:
5387 p = mkFormX( p, 63, 10, 10, 12, 2, 0 );
5388 break;
5389 case Pfp_DFPSUBQ:
5390 p = mkFormX( p, 63, 10, 10, 12, 514, 0 );
5391 break;
5392 case Pfp_DFPMULQ:
5393 p = mkFormX( p, 63, 10, 10, 12, 34, 0 );
5394 break;
5395 case Pfp_DFPDIVQ:
5396 p = mkFormX( p, 63, 10, 10, 12, 546, 0 );
5397 break;
5398 default:
5399 goto bad;
5400 }
5401
5402 /* The instruction will put the 128-bit result in
5403 * registers (10,11). Note, the operand in the instruction only
5404 * reference the first of the two registers in the pair.
5405 */
5406 p = mkFormX(p, 63, fr_dstHi, 0, 10, 72, 0);
5407 p = mkFormX(p, 63, fr_dstLo, 0, 11, 72, 0);
5408 goto done;
5409 }
5410
5411 case Pin_DfpShift128: {
5412 UInt fr_src_hi = fregNo(i->Pin.DfpShift128.src_hi);
5413 UInt fr_src_lo = fregNo(i->Pin.DfpShift128.src_lo);
5414 UInt fr_dst_hi = fregNo(i->Pin.DfpShift128.dst_hi);
5415 UInt fr_dst_lo = fregNo(i->Pin.DfpShift128.dst_lo);
5416 UInt shift;
5417
5418 shift = i->Pin.DfpShift128.shift->Pri.Imm;
5419
5420 /* setup source operand in register 12, 13 pair */
5421 p = mkFormX(p, 63, 12, 0, fr_src_hi, 72, 0);
5422 p = mkFormX(p, 63, 13, 0, fr_src_lo, 72, 0);
5423
5424 /* execute instruction putting result in register 10, 11 pair */
5425 switch (i->Pin.DfpShift128.op) {
5426 case Pfp_DSCLIQ: /* dscliq, DFP shift left, fr_srcR is the integer
5427 * shift amount.
5428 */
5429 p = mkFormZ22( p, 63, 10, 12, shift, 66, 0 );
5430 break;
5431 case Pfp_DSCRIQ: /* dscriq, DFP shift right, fr_srcR is the integer
5432 * shift amount.
5433 */
5434 p = mkFormZ22( p, 63, 10, 12, shift, 98, 0 );
5435 break;
5436 default:
5437 vex_printf("ERROR: emit_PPCInstr quad default case %d \n",
5438 i->Pin.DfpShift128.op);
5439 goto bad;
5440 }
5441
5442 /* The instruction put the 128-bit result in registers (10,11).
5443 * Note, the operand in the instruction only reference the first of
5444 * the two registers in the pair.
5445 */
5446 p = mkFormX(p, 63, fr_dst_hi, 0, 10, 72, 0);
5447 p = mkFormX(p, 63, fr_dst_lo, 0, 11, 72, 0);
5448 goto done;
5449 }
5450
5451 case Pin_DfpRound: {
5452 UInt fr_dst = fregNo(i->Pin.DfpRound.dst);
5453 UInt fr_src = fregNo(i->Pin.DfpRound.src);
5454 UInt r_rmc, r, rmc;
5455
5456 r_rmc = i->Pin.DfpRound.r_rmc->Pri.Imm;
5457 r = (r_rmc & 0x8) >> 3;
5458 rmc = r_rmc & 0x3;
5459
5460 // drintx
5461 p = mkFormZ23(p, 59, fr_dst, r, fr_src, rmc, 99, 0);
5462 goto done;
5463 }
5464
5465 case Pin_DfpRound128: {
5466 UInt fr_dstHi = fregNo(i->Pin.DfpRound128.dst_hi);
5467 UInt fr_dstLo = fregNo(i->Pin.DfpRound128.dst_lo);
5468 UInt fr_srcHi = fregNo(i->Pin.DfpRound128.src_hi);
5469 UInt fr_srcLo = fregNo(i->Pin.DfpRound128.src_lo);
5470 UInt r_rmc, r, rmc;
5471
5472 r_rmc = i->Pin.DfpRound128.r_rmc->Pri.Imm;
5473 r = (r_rmc & 0x8) >> 3;
5474 rmc = r_rmc & 0x3;
5475
5476 /* Setup the upper and lower registers of the source operand
5477 * register pair.
5478 */
5479 p = mkFormX(p, 63, 12, 0, fr_srcHi, 72, 0);
5480 p = mkFormX(p, 63, 13, 0, fr_srcLo, 72, 0);
5481
5482 /* Do drintx instruction with 128-bit source operands in
5483 * registers (12,13).
5484 */
5485 p = mkFormZ23(p, 63, 10, r, 12, rmc, 99, 0);
5486
5487 /* The instruction will put the 128-bit result in
5488 * registers (10,11). Note, the operand in the instruction only
5489 * reference the first of the two registers in the pair.
5490 */
5491 p = mkFormX(p, 63, fr_dstHi, 0, 10, 72, 0);
5492 p = mkFormX(p, 63, fr_dstLo, 0, 11, 72, 0);
5493 goto done;
5494 }
5495
5496 case Pin_DfpQuantize: {
5497 UInt fr_dst = fregNo(i->Pin.DfpQuantize.dst);
5498 UInt fr_srcL = fregNo(i->Pin.DfpQuantize.srcL);
5499 UInt fr_srcR = fregNo(i->Pin.DfpQuantize.srcR);
5500 UInt rmc;
5501
5502 rmc = i->Pin.DfpQuantize.rmc->Pri.Imm;
5503
5504 switch (i->Pin.DfpQuantize.op) {
5505 case Pfp_DQUA:
5506 p = mkFormZ23(p, 59, fr_dst, fr_srcL, fr_srcR, rmc, 3, 0);
5507 break;
5508 case Pfp_RRDTR:
5509 p = mkFormZ23(p, 59, fr_dst, fr_srcL, fr_srcR, rmc, 35, 0);
5510 break;
5511 default:
5512 break;
5513 }
5514 goto done;
5515 }
5516
5517 case Pin_DfpQuantize128: {
5518 UInt fr_dst_hi = fregNo(i->Pin.DfpQuantize128.dst_hi);
5519 UInt fr_dst_lo = fregNo(i->Pin.DfpQuantize128.dst_lo);
5520 UInt fr_src_hi = fregNo(i->Pin.DfpQuantize128.src_hi);
5521 UInt fr_src_lo = fregNo(i->Pin.DfpQuantize128.src_lo);
5522 UInt rmc;
5523
5524 rmc = i->Pin.DfpQuantize128.rmc->Pri.Imm;
5525 /* Setup the upper and lower registers of the source operand
5526 * register pairs. Note, left source operand passed in via the
5527 * dst register pair.
5528 */
5529 p = mkFormX(p, 63, 10, 0, fr_dst_hi, 72, 0);
5530 p = mkFormX(p, 63, 11, 0, fr_dst_lo, 72, 0);
5531 p = mkFormX(p, 63, 12, 0, fr_src_hi, 72, 0);
5532 p = mkFormX(p, 63, 13, 0, fr_src_lo, 72, 0);
5533
5534 /* Do dquaq instruction with 128-bit source operands in
5535 * registers (12,13).
5536 */
5537 switch (i->Pin.DfpQuantize128.op) {
5538 case Pfp_DQUAQ:
5539 p = mkFormZ23(p, 63, 10, 10, 12, rmc, 3, 0);
5540 break;
5541 case Pfp_DRRNDQ:
5542 p = mkFormZ23(p, 63, 10, 10, 12, rmc, 35, 0);
5543 break;
5544 default:
5545 vpanic("Pin_DfpQuantize128: default case, couldn't find inst to issue \n");
5546 break;
5547 }
5548
5549 /* The instruction will put the 128-bit result in
5550 * registers (10,11). Note, the operand in the instruction only
5551 * reference the first of the two registers in the pair.
5552 */
5553 p = mkFormX(p, 63, fr_dst_hi, 0, 10, 72, 0);
5554 p = mkFormX(p, 63, fr_dst_lo, 0, 11, 72, 0);
5555 goto done;
5556 }
5557
5558 case Pin_DfpD128toD64: {
5559 UInt fr_dst = fregNo( i->Pin.DfpD128toD64.dst );
5560 UInt fr_srcHi = fregNo( i->Pin.DfpD128toD64.src_hi );
5561 UInt fr_srcLo = fregNo( i->Pin.DfpD128toD64.src_lo );
5562
5563 /* Setup the upper and lower registers of the source operand
5564 * register pair.
5565 */
5566 p = mkFormX( p, 63, 10, 0, fr_dst, 72, 0 );
5567 p = mkFormX( p, 63, 12, 0, fr_srcHi, 72, 0 );
5568 p = mkFormX( p, 63, 13, 0, fr_srcLo, 72, 0 );
5569
5570 /* Do instruction with 128-bit source operands in registers (10,11) */
5571 switch (i->Pin.Dfp128Binary.op) {
5572 case Pfp_DRDPQ:
5573 p = mkFormX( p, 63, 10, 0, 12, 770, 0 );
5574 break;
5575 case Pfp_DCTFIXQ:
5576 p = mkFormX( p, 63, 10, 0, 12, 290, 0 );
5577 break;
5578 default:
5579 goto bad;
5580 }
5581
5582 /* The instruction will put the 64-bit result in registers 10. */
5583 p = mkFormX(p, 63, fr_dst, 0, 10, 72, 0);
5584 goto done;
5585 }
5586
5587 case Pin_DfpI64StoD128: {
5588 UInt fr_dstHi = fregNo( i->Pin.DfpI64StoD128.dst_hi );
5589 UInt fr_dstLo = fregNo( i->Pin.DfpI64StoD128.dst_lo );
5590 UInt fr_src = fregNo( i->Pin.DfpI64StoD128.src );
5591
5592 switch (i->Pin.Dfp128Binary.op) {
5593 case Pfp_DCFFIXQ:
5594 p = mkFormX( p, 63, 10, 11, fr_src, 802, 0 );
5595 break;
5596 default:
5597 goto bad;
5598 }
5599
5600 /* The instruction will put the 64-bit result in registers 10, 11. */
5601 p = mkFormX(p, 63, fr_dstHi, 0, 10, 72, 0);
5602 p = mkFormX(p, 63, fr_dstLo, 0, 11, 72, 0);
5603 goto done;
5604 }
5605
5606 case Pin_InsertExpD128: {
5607 UInt fr_dstHi = fregNo(i->Pin.InsertExpD128.dst_hi);
5608 UInt fr_dstLo = fregNo(i->Pin.InsertExpD128.dst_lo);
5609 UInt fr_srcL = fregNo(i->Pin.InsertExpD128.srcL);
5610 UInt fr_srcRHi = fregNo(i->Pin.InsertExpD128.srcR_hi);
5611 UInt fr_srcRLo = fregNo(i->Pin.InsertExpD128.srcR_lo);
5612
5613 /* The left operand is a single F64 value, the right is an F128
5614 * register pair.
5615 */
5616 p = mkFormX(p, 63, 10, 0, fr_srcL, 72, 0);
5617 p = mkFormX(p, 63, 12, 0, fr_srcRHi, 72, 0);
5618 p = mkFormX(p, 63, 13, 0, fr_srcRLo, 72, 0);
5619 p = mkFormX(p, 63, 10, 10, 12, 866, 0 );
5620
5621 /* The instruction will put the 128-bit result into
5622 * registers (10,11). Note, the operand in the instruction only
5623 * reference the first of the two registers in the pair.
5624 */
5625 p = mkFormX(p, 63, fr_dstHi, 0, 10, 72, 0);
5626 p = mkFormX(p, 63, fr_dstLo, 0, 11, 72, 0);
5627 goto done;
5628 }
5629
5630 case Pin_Dfp64Cmp:{
5631 UChar crfD = 1;
5632 UInt r_dst = iregNo(i->Pin.Dfp64Cmp.dst, mode64);
5633 UInt fr_srcL = fregNo(i->Pin.Dfp64Cmp.srcL);
5634 UInt fr_srcR = fregNo(i->Pin.Dfp64Cmp.srcR);
5635 vassert(crfD < 8);
5636 // dcmpo, dcmpu
5637 p = mkFormX(p, 59, crfD<<2, fr_srcL, fr_srcR, 130, 0);
5638
5639 // mfcr (mv CR to r_dst)
5640 p = mkFormX(p, 31, r_dst, 0, 0, 19, 0);
5641
5642 // rlwinm r_dst,r_dst,8,28,31
5643 // => rotate field 1 to bottomw of word, masking out upper 28
5644 p = mkFormM(p, 21, r_dst, r_dst, 8, 28, 31, 0);
5645 goto done;
5646 }
5647
5648 case Pin_Dfp128Cmp: {
5649 UChar crfD = 1;
5650 UInt r_dst = iregNo(i->Pin.Dfp128Cmp.dst, mode64);
5651 UInt fr_srcL_hi = fregNo(i->Pin.Dfp128Cmp.srcL_hi);
5652 UInt fr_srcL_lo = fregNo(i->Pin.Dfp128Cmp.srcL_lo);
5653 UInt fr_srcR_hi = fregNo(i->Pin.Dfp128Cmp.srcR_hi);
5654 UInt fr_srcR_lo = fregNo(i->Pin.Dfp128Cmp.srcR_lo);
5655 vassert(crfD < 8);
5656 // dcmpoq, dcmpuq
5657 /* Setup the upper and lower registers of the source operand
5658 * register pair.
5659 */
5660 p = mkFormX(p, 63, 10, 0, fr_srcL_hi, 72, 0);
5661 p = mkFormX(p, 63, 11, 0, fr_srcL_lo, 72, 0);
5662 p = mkFormX(p, 63, 12, 0, fr_srcR_hi, 72, 0);
5663 p = mkFormX(p, 63, 13, 0, fr_srcR_lo, 72, 0);
5664
5665 p = mkFormX(p, 63, crfD<<2, 10, 12, 130, 0);
5666
5667 // mfcr (mv CR to r_dst)
5668 p = mkFormX(p, 31, r_dst, 0, 0, 19, 0);
5669
5670 // rlwinm r_dst,r_dst,8,28,31
5671 // => rotate field 1 to bottomw of word, masking out upper 28
5672 p = mkFormM(p, 21, r_dst, r_dst, 8, 28, 31, 0);
5673 goto done;
5674 }
5675
5676 case Pin_EvCheck: {
5677 /* This requires a 32-bit dec/test in both 32- and 64-bit
5678 modes. */
5679 /* We generate:
5680 lwz r30, amCounter
5681 addic. r30, r30, -1
5682 stw r30, amCounter
5683 bge nofail
5684 lwz/ld r30, amFailAddr
5685 mtctr r30
5686 bctr
5687 nofail:
5688 */
5689 UChar* p0 = p;
5690 /* lwz r30, amCounter */
5691 p = do_load_or_store_word32(p, True/*isLoad*/, /*r*/30,
5692 i->Pin.EvCheck.amCounter, mode64);
5693 /* addic. r30,r30,-1 */
5694 p = emit32(p, 0x37DEFFFF);
5695 /* stw r30, amCounter */
5696 p = do_load_or_store_word32(p, False/*!isLoad*/, /*r*/30,
5697 i->Pin.EvCheck.amCounter, mode64);
5698 /* bge nofail */
5699 p = emit32(p, 0x40800010);
5700 /* lwz/ld r30, amFailAddr */
5701 p = do_load_or_store_machine_word(p, True/*isLoad*/, /*r*/30,
5702 i->Pin.EvCheck.amFailAddr, mode64);
5703 /* mtctr r30 */
5704 p = mkFormXFX(p, /*r*/30, 9, 467);
5705 /* bctr */
5706 p = mkFormXL(p, 19, Pct_ALWAYS, 0, 0, 528, 0);
5707 /* nofail: */
5708
5709 /* Crosscheck */
5710 vassert(evCheckSzB_PPC() == (UChar*)p - (UChar*)p0);
5711 goto done;
5712 }
5713
5714 case Pin_ProfInc: {
5715 /* We generate:
5716 (ctrP is unknown now, so use 0x65556555(65556555) in the
5717 expectation that a later call to LibVEX_patchProfCtr
5718 will be used to fill in the immediate fields once the
5719 right value is known.)
5720 32-bit:
5721 imm32-exactly r30, 0x65556555
5722 lwz r29, 4(r30)
5723 addic. r29, r29, 1
5724 stw r29, 4(r30)
5725 lwz r29, 0(r30)
5726 addze r29, r29
5727 stw r29, 0(r30)
5728 64-bit:
5729 imm64-exactly r30, 0x6555655565556555
5730 ld r29, 0(r30)
5731 addi r29, r29, 1
5732 std r29, 0(r30)
5733 */
5734 if (mode64) {
5735 p = mkLoadImm_EXACTLY2or5(
5736 p, /*r*/30, 0x6555655565556555ULL, True/*mode64*/);
5737 p = emit32(p, 0xEBBE0000);
5738 p = emit32(p, 0x3BBD0001);
5739 p = emit32(p, 0xFBBE0000);
5740 } else {
5741 p = mkLoadImm_EXACTLY2or5(
5742 p, /*r*/30, 0x65556555ULL, False/*!mode64*/);
5743 p = emit32(p, 0x83BE0004);
5744 p = emit32(p, 0x37BD0001);
5745 p = emit32(p, 0x93BE0004);
5746 p = emit32(p, 0x83BE0000);
5747 p = emit32(p, 0x7FBD0194);
5748 p = emit32(p, 0x93BE0000);
5749 }
5750 /* Tell the caller .. */
5751 vassert(!(*is_profInc));
5752 *is_profInc = True;
5753 goto done;
5754 }
5755
5756 default:
5757 goto bad;
5758 }
5759
5760 bad:
5761 vex_printf("\n=> ");
5762 ppPPCInstr(i, mode64);
5763 vpanic("emit_PPCInstr");
5764 /*NOTREACHED*/
5765
5766 done:
5767 vassert(p - &buf[0] <= 64);
5768 return p - &buf[0];
5769 }
5770
5771
5772 /* How big is an event check? See case for Pin_EvCheck in
5773 emit_PPCInstr just above. That crosschecks what this returns, so
5774 we can tell if we're inconsistent. */
evCheckSzB_PPC(void)5775 Int evCheckSzB_PPC ( void )
5776 {
5777 return 28;
5778 }
5779
5780
5781 /* NB: what goes on here has to be very closely coordinated with the
5782 emitInstr case for XDirect, above. */
chainXDirect_PPC(void * place_to_chain,void * disp_cp_chain_me_EXPECTED,void * place_to_jump_to,Bool mode64)5783 VexInvalRange chainXDirect_PPC ( void* place_to_chain,
5784 void* disp_cp_chain_me_EXPECTED,
5785 void* place_to_jump_to,
5786 Bool mode64 )
5787 {
5788 /* What we're expecting to see is:
5789 imm32/64-fixed r30, disp_cp_chain_me_to_EXPECTED
5790 mtctr r30
5791 bctrl
5792 viz
5793 <8 or 20 bytes generated by mkLoadImm_EXACTLY2or5>
5794 7F C9 03 A6
5795 4E 80 04 21
5796 */
5797 UChar* p = (UChar*)place_to_chain;
5798 vassert(0 == (3 & (HWord)p));
5799 vassert(isLoadImm_EXACTLY2or5(p, /*r*/30,
5800 Ptr_to_ULong(disp_cp_chain_me_EXPECTED),
5801 mode64));
5802 vassert(fetch32(p + (mode64 ? 20 : 8) + 0) == 0x7FC903A6);
5803 vassert(fetch32(p + (mode64 ? 20 : 8) + 4) == 0x4E800421);
5804 /* And what we want to change it to is:
5805 imm32/64-fixed r30, place_to_jump_to
5806 mtctr r30
5807 bctr
5808 viz
5809 <8 or 20 bytes generated by mkLoadImm_EXACTLY2or5>
5810 7F C9 03 A6
5811 4E 80 04 20
5812 The replacement has the same length as the original.
5813 */
5814 p = mkLoadImm_EXACTLY2or5(p, /*r*/30,
5815 Ptr_to_ULong(place_to_jump_to), mode64);
5816 p = emit32(p, 0x7FC903A6);
5817 p = emit32(p, 0x4E800420);
5818
5819 Int len = p - (UChar*)place_to_chain;
5820 vassert(len == (mode64 ? 28 : 16)); /* stay sane */
5821 VexInvalRange vir = {(HWord)place_to_chain, len};
5822 return vir;
5823 }
5824
5825
5826 /* NB: what goes on here has to be very closely coordinated with the
5827 emitInstr case for XDirect, above. */
unchainXDirect_PPC(void * place_to_unchain,void * place_to_jump_to_EXPECTED,void * disp_cp_chain_me,Bool mode64)5828 VexInvalRange unchainXDirect_PPC ( void* place_to_unchain,
5829 void* place_to_jump_to_EXPECTED,
5830 void* disp_cp_chain_me,
5831 Bool mode64 )
5832 {
5833 /* What we're expecting to see is:
5834 imm32/64-fixed r30, place_to_jump_to_EXPECTED
5835 mtctr r30
5836 bctr
5837 viz
5838 <8 or 20 bytes generated by mkLoadImm_EXACTLY2or5>
5839 7F C9 03 A6
5840 4E 80 04 20
5841 */
5842 UChar* p = (UChar*)place_to_unchain;
5843 vassert(0 == (3 & (HWord)p));
5844 vassert(isLoadImm_EXACTLY2or5(p, /*r*/30,
5845 Ptr_to_ULong(place_to_jump_to_EXPECTED),
5846 mode64));
5847 vassert(fetch32(p + (mode64 ? 20 : 8) + 0) == 0x7FC903A6);
5848 vassert(fetch32(p + (mode64 ? 20 : 8) + 4) == 0x4E800420);
5849 /* And what we want to change it to is:
5850 imm32/64-fixed r30, disp_cp_chain_me
5851 mtctr r30
5852 bctrl
5853 viz
5854 <8 or 20 bytes generated by mkLoadImm_EXACTLY2or5>
5855 7F C9 03 A6
5856 4E 80 04 21
5857 The replacement has the same length as the original.
5858 */
5859 p = mkLoadImm_EXACTLY2or5(p, /*r*/30,
5860 Ptr_to_ULong(disp_cp_chain_me), mode64);
5861 p = emit32(p, 0x7FC903A6);
5862 p = emit32(p, 0x4E800421);
5863
5864 Int len = p - (UChar*)place_to_unchain;
5865 vassert(len == (mode64 ? 28 : 16)); /* stay sane */
5866 VexInvalRange vir = {(HWord)place_to_unchain, len};
5867 return vir;
5868 }
5869
5870
5871 /* Patch the counter address into a profile inc point, as previously
5872 created by the Pin_ProfInc case for emit_PPCInstr. */
patchProfInc_PPC(void * place_to_patch,ULong * location_of_counter,Bool mode64)5873 VexInvalRange patchProfInc_PPC ( void* place_to_patch,
5874 ULong* location_of_counter,
5875 Bool mode64 )
5876 {
5877 UChar* p = (UChar*)place_to_patch;
5878 vassert(0 == (3 & (HWord)p));
5879
5880 Int len = 0;
5881 if (mode64) {
5882 vassert(isLoadImm_EXACTLY2or5(p, /*r*/30,
5883 0x6555655565556555ULL, True/*mode64*/));
5884 vassert(fetch32(p + 20) == 0xEBBE0000);
5885 vassert(fetch32(p + 24) == 0x3BBD0001);
5886 vassert(fetch32(p + 28) == 0xFBBE0000);
5887 p = mkLoadImm_EXACTLY2or5(p, /*r*/30,
5888 Ptr_to_ULong(location_of_counter),
5889 True/*mode64*/);
5890 len = p - (UChar*)place_to_patch;
5891 vassert(len == 20);
5892 } else {
5893 vassert(isLoadImm_EXACTLY2or5(p, /*r*/30,
5894 0x65556555ULL, False/*!mode64*/));
5895 vassert(fetch32(p + 8) == 0x83BE0004);
5896 vassert(fetch32(p + 12) == 0x37BD0001);
5897 vassert(fetch32(p + 16) == 0x93BE0004);
5898 vassert(fetch32(p + 20) == 0x83BE0000);
5899 vassert(fetch32(p + 24) == 0x7FBD0194);
5900 vassert(fetch32(p + 28) == 0x93BE0000);
5901 p = mkLoadImm_EXACTLY2or5(p, /*r*/30,
5902 Ptr_to_ULong(location_of_counter),
5903 False/*!mode64*/);
5904 len = p - (UChar*)place_to_patch;
5905 vassert(len == 8);
5906 }
5907 VexInvalRange vir = {(HWord)place_to_patch, len};
5908 return vir;
5909 }
5910
5911
5912 /*---------------------------------------------------------------*/
5913 /*--- end host_ppc_defs.c ---*/
5914 /*---------------------------------------------------------------*/
5915