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-2010 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 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 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 default: vpanic("ppPPCCondCode");
290 }
291 }
292
293 /* construct condition code */
mk_PPCCondCode(PPCCondTest test,PPCCondFlag flag)294 PPCCondCode mk_PPCCondCode ( PPCCondTest test, PPCCondFlag flag )
295 {
296 PPCCondCode cc;
297 cc.flag = flag;
298 cc.test = test;
299 return cc;
300 }
301
302 /* false->true, true->false */
invertCondTest(PPCCondTest ct)303 PPCCondTest invertCondTest ( PPCCondTest ct )
304 {
305 vassert(ct != Pct_ALWAYS);
306 return (ct == Pct_TRUE) ? Pct_FALSE : Pct_TRUE;
307 }
308
309
310 /* --------- PPCAMode: memory address expressions. --------- */
311
PPCAMode_IR(Int idx,HReg base)312 PPCAMode* PPCAMode_IR ( Int idx, HReg base ) {
313 PPCAMode* am = LibVEX_Alloc(sizeof(PPCAMode));
314 vassert(idx >= -0x8000 && idx < 0x8000);
315 am->tag = Pam_IR;
316 am->Pam.IR.base = base;
317 am->Pam.IR.index = idx;
318 return am;
319 }
PPCAMode_RR(HReg idx,HReg base)320 PPCAMode* PPCAMode_RR ( HReg idx, HReg base ) {
321 PPCAMode* am = LibVEX_Alloc(sizeof(PPCAMode));
322 am->tag = Pam_RR;
323 am->Pam.RR.base = base;
324 am->Pam.RR.index = idx;
325 return am;
326 }
327
dopyPPCAMode(PPCAMode * am)328 PPCAMode* dopyPPCAMode ( PPCAMode* am ) {
329 switch (am->tag) {
330 case Pam_IR:
331 return PPCAMode_IR( am->Pam.IR.index, am->Pam.IR.base );
332 case Pam_RR:
333 return PPCAMode_RR( am->Pam.RR.index, am->Pam.RR.base );
334 default:
335 vpanic("dopyPPCAMode");
336 }
337 }
338
ppPPCAMode(PPCAMode * am)339 void ppPPCAMode ( PPCAMode* am ) {
340 switch (am->tag) {
341 case Pam_IR:
342 if (am->Pam.IR.index == 0)
343 vex_printf("0(");
344 else
345 vex_printf("%d(", (Int)am->Pam.IR.index);
346 ppHRegPPC(am->Pam.IR.base);
347 vex_printf(")");
348 return;
349 case Pam_RR:
350 ppHRegPPC(am->Pam.RR.base);
351 vex_printf(",");
352 ppHRegPPC(am->Pam.RR.index);
353 return;
354 default:
355 vpanic("ppPPCAMode");
356 }
357 }
358
addRegUsage_PPCAMode(HRegUsage * u,PPCAMode * am)359 static void addRegUsage_PPCAMode ( HRegUsage* u, PPCAMode* am ) {
360 switch (am->tag) {
361 case Pam_IR:
362 addHRegUse(u, HRmRead, am->Pam.IR.base);
363 return;
364 case Pam_RR:
365 addHRegUse(u, HRmRead, am->Pam.RR.base);
366 addHRegUse(u, HRmRead, am->Pam.RR.index);
367 return;
368 default:
369 vpanic("addRegUsage_PPCAMode");
370 }
371 }
372
mapRegs_PPCAMode(HRegRemap * m,PPCAMode * am)373 static void mapRegs_PPCAMode ( HRegRemap* m, PPCAMode* am ) {
374 switch (am->tag) {
375 case Pam_IR:
376 am->Pam.IR.base = lookupHRegRemap(m, am->Pam.IR.base);
377 return;
378 case Pam_RR:
379 am->Pam.RR.base = lookupHRegRemap(m, am->Pam.RR.base);
380 am->Pam.RR.index = lookupHRegRemap(m, am->Pam.RR.index);
381 return;
382 default:
383 vpanic("mapRegs_PPCAMode");
384 }
385 }
386
387 /* --------- Operand, which can be a reg or a u16/s16. --------- */
388
PPCRH_Imm(Bool syned,UShort imm16)389 PPCRH* PPCRH_Imm ( Bool syned, UShort imm16 ) {
390 PPCRH* op = LibVEX_Alloc(sizeof(PPCRH));
391 op->tag = Prh_Imm;
392 op->Prh.Imm.syned = syned;
393 op->Prh.Imm.imm16 = imm16;
394 /* If this is a signed value, ensure it's not -32768, so that we
395 are guaranteed always to be able to negate if needed. */
396 if (syned)
397 vassert(imm16 != 0x8000);
398 vassert(syned == True || syned == False);
399 return op;
400 }
PPCRH_Reg(HReg reg)401 PPCRH* PPCRH_Reg ( HReg reg ) {
402 PPCRH* op = LibVEX_Alloc(sizeof(PPCRH));
403 op->tag = Prh_Reg;
404 op->Prh.Reg.reg = reg;
405 return op;
406 }
407
ppPPCRH(PPCRH * op)408 void ppPPCRH ( PPCRH* op ) {
409 switch (op->tag) {
410 case Prh_Imm:
411 if (op->Prh.Imm.syned)
412 vex_printf("%d", (Int)(Short)op->Prh.Imm.imm16);
413 else
414 vex_printf("%u", (UInt)(UShort)op->Prh.Imm.imm16);
415 return;
416 case Prh_Reg:
417 ppHRegPPC(op->Prh.Reg.reg);
418 return;
419 default:
420 vpanic("ppPPCRH");
421 }
422 }
423
424 /* An PPCRH can only be used in a "read" context (what would it mean
425 to write or modify a literal?) and so we enumerate its registers
426 accordingly. */
addRegUsage_PPCRH(HRegUsage * u,PPCRH * op)427 static void addRegUsage_PPCRH ( HRegUsage* u, PPCRH* op ) {
428 switch (op->tag) {
429 case Prh_Imm:
430 return;
431 case Prh_Reg:
432 addHRegUse(u, HRmRead, op->Prh.Reg.reg);
433 return;
434 default:
435 vpanic("addRegUsage_PPCRH");
436 }
437 }
438
mapRegs_PPCRH(HRegRemap * m,PPCRH * op)439 static void mapRegs_PPCRH ( HRegRemap* m, PPCRH* op ) {
440 switch (op->tag) {
441 case Prh_Imm:
442 return;
443 case Prh_Reg:
444 op->Prh.Reg.reg = lookupHRegRemap(m, op->Prh.Reg.reg);
445 return;
446 default:
447 vpanic("mapRegs_PPCRH");
448 }
449 }
450
451
452 /* --------- Operand, which can be a reg or a u32/64. --------- */
453
PPCRI_Imm(ULong imm64)454 PPCRI* PPCRI_Imm ( ULong imm64 ) {
455 PPCRI* op = LibVEX_Alloc(sizeof(PPCRI));
456 op->tag = Pri_Imm;
457 op->Pri.Imm = imm64;
458 return op;
459 }
PPCRI_Reg(HReg reg)460 PPCRI* PPCRI_Reg ( HReg reg ) {
461 PPCRI* op = LibVEX_Alloc(sizeof(PPCRI));
462 op->tag = Pri_Reg;
463 op->Pri.Reg = reg;
464 return op;
465 }
466
ppPPCRI(PPCRI * dst)467 void ppPPCRI ( PPCRI* dst ) {
468 switch (dst->tag) {
469 case Pri_Imm:
470 vex_printf("0x%llx", dst->Pri.Imm);
471 break;
472 case Pri_Reg:
473 ppHRegPPC(dst->Pri.Reg);
474 break;
475 default:
476 vpanic("ppPPCRI");
477 }
478 }
479
480 /* An PPCRI can only be used in a "read" context (what would it
481 mean to write or modify a literal?) and so we enumerate its
482 registers accordingly. */
addRegUsage_PPCRI(HRegUsage * u,PPCRI * dst)483 static void addRegUsage_PPCRI ( HRegUsage* u, PPCRI* dst ) {
484 switch (dst->tag) {
485 case Pri_Imm:
486 return;
487 case Pri_Reg:
488 addHRegUse(u, HRmRead, dst->Pri.Reg);
489 return;
490 default:
491 vpanic("addRegUsage_PPCRI");
492 }
493 }
494
mapRegs_PPCRI(HRegRemap * m,PPCRI * dst)495 static void mapRegs_PPCRI ( HRegRemap* m, PPCRI* dst ) {
496 switch (dst->tag) {
497 case Pri_Imm:
498 return;
499 case Pri_Reg:
500 dst->Pri.Reg = lookupHRegRemap(m, dst->Pri.Reg);
501 return;
502 default:
503 vpanic("mapRegs_PPCRI");
504 }
505 }
506
507
508 /* --------- Operand, which can be a vector reg or a simm5. --------- */
509
PPCVI5s_Imm(Char simm5)510 PPCVI5s* PPCVI5s_Imm ( Char simm5 ) {
511 PPCVI5s* op = LibVEX_Alloc(sizeof(PPCVI5s));
512 op->tag = Pvi_Imm;
513 op->Pvi.Imm5s = simm5;
514 vassert(simm5 >= -16 && simm5 <= 15);
515 return op;
516 }
PPCVI5s_Reg(HReg reg)517 PPCVI5s* PPCVI5s_Reg ( HReg reg ) {
518 PPCVI5s* op = LibVEX_Alloc(sizeof(PPCVI5s));
519 op->tag = Pvi_Reg;
520 op->Pvi.Reg = reg;
521 vassert(hregClass(reg) == HRcVec128);
522 return op;
523 }
524
ppPPCVI5s(PPCVI5s * src)525 void ppPPCVI5s ( PPCVI5s* src ) {
526 switch (src->tag) {
527 case Pvi_Imm:
528 vex_printf("%d", (Int)src->Pvi.Imm5s);
529 break;
530 case Pvi_Reg:
531 ppHRegPPC(src->Pvi.Reg);
532 break;
533 default:
534 vpanic("ppPPCVI5s");
535 }
536 }
537
538 /* An PPCVI5s can only be used in a "read" context (what would it
539 mean to write or modify a literal?) and so we enumerate its
540 registers accordingly. */
addRegUsage_PPCVI5s(HRegUsage * u,PPCVI5s * dst)541 static void addRegUsage_PPCVI5s ( HRegUsage* u, PPCVI5s* dst ) {
542 switch (dst->tag) {
543 case Pvi_Imm:
544 return;
545 case Pvi_Reg:
546 addHRegUse(u, HRmRead, dst->Pvi.Reg);
547 return;
548 default:
549 vpanic("addRegUsage_PPCVI5s");
550 }
551 }
552
mapRegs_PPCVI5s(HRegRemap * m,PPCVI5s * dst)553 static void mapRegs_PPCVI5s ( HRegRemap* m, PPCVI5s* dst ) {
554 switch (dst->tag) {
555 case Pvi_Imm:
556 return;
557 case Pvi_Reg:
558 dst->Pvi.Reg = lookupHRegRemap(m, dst->Pvi.Reg);
559 return;
560 default:
561 vpanic("mapRegs_PPCVI5s");
562 }
563 }
564
565
566 /* --------- Instructions. --------- */
567
showPPCUnaryOp(PPCUnaryOp op)568 HChar* showPPCUnaryOp ( PPCUnaryOp op ) {
569 switch (op) {
570 case Pun_NOT: return "not";
571 case Pun_NEG: return "neg";
572 case Pun_CLZ32: return "cntlzw";
573 case Pun_CLZ64: return "cntlzd";
574 case Pun_EXTSW: return "extsw";
575 default: vpanic("showPPCUnaryOp");
576 }
577 }
578
showPPCAluOp(PPCAluOp op,Bool immR)579 HChar* showPPCAluOp ( PPCAluOp op, Bool immR ) {
580 switch (op) {
581 case Palu_ADD: return immR ? "addi" : "add";
582 case Palu_SUB: return immR ? "subi" : "sub";
583 case Palu_AND: return immR ? "andi." : "and";
584 case Palu_OR: return immR ? "ori" : "or";
585 case Palu_XOR: return immR ? "xori" : "xor";
586 default: vpanic("showPPCAluOp");
587 }
588 }
589
showPPCShftOp(PPCShftOp op,Bool immR,Bool sz32)590 HChar* showPPCShftOp ( PPCShftOp op, Bool immR, Bool sz32 ) {
591 switch (op) {
592 case Pshft_SHL: return sz32 ? (immR ? "slwi" : "slw") :
593 (immR ? "sldi" : "sld");
594 case Pshft_SHR: return sz32 ? (immR ? "srwi" : "srw") :
595 (immR ? "srdi" : "srd");
596 case Pshft_SAR: return sz32 ? (immR ? "srawi" : "sraw") :
597 (immR ? "sradi" : "srad");
598 default: vpanic("showPPCShftOp");
599 }
600 }
601
showPPCFpOp(PPCFpOp op)602 HChar* showPPCFpOp ( PPCFpOp op ) {
603 switch (op) {
604 case Pfp_ADDD: return "fadd";
605 case Pfp_SUBD: return "fsub";
606 case Pfp_MULD: return "fmul";
607 case Pfp_DIVD: return "fdiv";
608 case Pfp_MADDD: return "fmadd";
609 case Pfp_MSUBD: return "fmsub";
610 case Pfp_MADDS: return "fmadds";
611 case Pfp_MSUBS: return "fmsubs";
612 case Pfp_ADDS: return "fadds";
613 case Pfp_SUBS: return "fsubs";
614 case Pfp_MULS: return "fmuls";
615 case Pfp_DIVS: return "fdivs";
616 case Pfp_SQRT: return "fsqrt";
617 case Pfp_ABS: return "fabs";
618 case Pfp_NEG: return "fneg";
619 case Pfp_MOV: return "fmr";
620 case Pfp_RES: return "fres";
621 case Pfp_RSQRTE: return "frsqrte";
622 case Pfp_FRIM: return "frim";
623 case Pfp_FRIN: return "frin";
624 case Pfp_FRIP: return "frip";
625 case Pfp_FRIZ: return "friz";
626 default: vpanic("showPPCFpOp");
627 }
628 }
629
showPPCAvOp(PPCAvOp op)630 HChar* showPPCAvOp ( PPCAvOp op ) {
631 switch (op) {
632
633 /* Unary */
634 case Pav_MOV: return "vmr"; /* Mov */
635
636 case Pav_AND: return "vand"; /* Bitwise */
637 case Pav_OR: return "vor";
638 case Pav_XOR: return "vxor";
639 case Pav_NOT: return "vnot";
640
641 case Pav_UNPCKH8S: return "vupkhsb"; /* Unpack */
642 case Pav_UNPCKH16S: return "vupkhsh";
643 case Pav_UNPCKL8S: return "vupklsb";
644 case Pav_UNPCKL16S: return "vupklsh";
645 case Pav_UNPCKHPIX: return "vupkhpx";
646 case Pav_UNPCKLPIX: return "vupklpx";
647
648 /* Integer binary */
649 case Pav_ADDU: return "vaddu_m"; // b,h,w
650 case Pav_QADDU: return "vaddu_s"; // b,h,w
651 case Pav_QADDS: return "vadds_s"; // b,h,w
652
653 case Pav_SUBU: return "vsubu_m"; // b,h,w
654 case Pav_QSUBU: return "vsubu_s"; // b,h,w
655 case Pav_QSUBS: return "vsubs_s"; // b,h,w
656
657 case Pav_OMULU: return "vmulou"; // b,h
658 case Pav_OMULS: return "vmulos"; // b,h
659 case Pav_EMULU: return "vmuleu"; // b,h
660 case Pav_EMULS: return "vmules"; // b,h
661
662 case Pav_AVGU: return "vavgu"; // b,h,w
663 case Pav_AVGS: return "vavgs"; // b,h,w
664
665 case Pav_MAXU: return "vmaxu"; // b,h,w
666 case Pav_MAXS: return "vmaxs"; // b,h,w
667
668 case Pav_MINU: return "vminu"; // b,h,w
669 case Pav_MINS: return "vmins"; // b,h,w
670
671 /* Compare (always affects CR field 6) */
672 case Pav_CMPEQU: return "vcmpequ"; // b,h,w
673 case Pav_CMPGTU: return "vcmpgtu"; // b,h,w
674 case Pav_CMPGTS: return "vcmpgts"; // b,h,w
675
676 /* Shift */
677 case Pav_SHL: return "vsl"; // ' ',b,h,w
678 case Pav_SHR: return "vsr"; // ' ',b,h,w
679 case Pav_SAR: return "vsra"; // b,h,w
680 case Pav_ROTL: return "vrl"; // b,h,w
681
682 /* Pack */
683 case Pav_PACKUU: return "vpku_um"; // h,w
684 case Pav_QPACKUU: return "vpku_us"; // h,w
685 case Pav_QPACKSU: return "vpks_us"; // h,w
686 case Pav_QPACKSS: return "vpks_ss"; // h,w
687 case Pav_PACKPXL: return "vpkpx";
688
689 /* Merge */
690 case Pav_MRGHI: return "vmrgh"; // b,h,w
691 case Pav_MRGLO: return "vmrgl"; // b,h,w
692
693 default: vpanic("showPPCAvOp");
694 }
695 }
696
showPPCAvFpOp(PPCAvFpOp op)697 HChar* showPPCAvFpOp ( PPCAvFpOp op ) {
698 switch (op) {
699 /* Floating Point Binary */
700 case Pavfp_ADDF: return "vaddfp";
701 case Pavfp_SUBF: return "vsubfp";
702 case Pavfp_MULF: return "vmaddfp";
703 case Pavfp_MAXF: return "vmaxfp";
704 case Pavfp_MINF: return "vminfp";
705 case Pavfp_CMPEQF: return "vcmpeqfp";
706 case Pavfp_CMPGTF: return "vcmpgtfp";
707 case Pavfp_CMPGEF: return "vcmpgefp";
708
709 /* Floating Point Unary */
710 case Pavfp_RCPF: return "vrefp";
711 case Pavfp_RSQRTF: return "vrsqrtefp";
712 case Pavfp_CVTU2F: return "vcfux";
713 case Pavfp_CVTS2F: return "vcfsx";
714 case Pavfp_QCVTF2U: return "vctuxs";
715 case Pavfp_QCVTF2S: return "vctsxs";
716 case Pavfp_ROUNDM: return "vrfim";
717 case Pavfp_ROUNDP: return "vrfip";
718 case Pavfp_ROUNDN: return "vrfin";
719 case Pavfp_ROUNDZ: return "vrfiz";
720
721 default: vpanic("showPPCAvFpOp");
722 }
723 }
724
PPCInstr_LI(HReg dst,ULong imm64,Bool mode64)725 PPCInstr* PPCInstr_LI ( HReg dst, ULong imm64, Bool mode64 )
726 {
727 PPCInstr* i = LibVEX_Alloc(sizeof(PPCInstr));
728 i->tag = Pin_LI;
729 i->Pin.LI.dst = dst;
730 i->Pin.LI.imm64 = imm64;
731 if (!mode64)
732 vassert( (Long)imm64 == (Long)(Int)(UInt)imm64 );
733 return i;
734 }
PPCInstr_Alu(PPCAluOp op,HReg dst,HReg srcL,PPCRH * srcR)735 PPCInstr* PPCInstr_Alu ( PPCAluOp op, HReg dst,
736 HReg srcL, PPCRH* srcR ) {
737 PPCInstr* i = LibVEX_Alloc(sizeof(PPCInstr));
738 i->tag = Pin_Alu;
739 i->Pin.Alu.op = op;
740 i->Pin.Alu.dst = dst;
741 i->Pin.Alu.srcL = srcL;
742 i->Pin.Alu.srcR = srcR;
743 return i;
744 }
PPCInstr_Shft(PPCShftOp op,Bool sz32,HReg dst,HReg srcL,PPCRH * srcR)745 PPCInstr* PPCInstr_Shft ( PPCShftOp op, Bool sz32,
746 HReg dst, HReg srcL, PPCRH* srcR ) {
747 PPCInstr* i = LibVEX_Alloc(sizeof(PPCInstr));
748 i->tag = Pin_Shft;
749 i->Pin.Shft.op = op;
750 i->Pin.Shft.sz32 = sz32;
751 i->Pin.Shft.dst = dst;
752 i->Pin.Shft.srcL = srcL;
753 i->Pin.Shft.srcR = srcR;
754 return i;
755 }
PPCInstr_AddSubC(Bool isAdd,Bool setC,HReg dst,HReg srcL,HReg srcR)756 PPCInstr* PPCInstr_AddSubC ( Bool isAdd, Bool setC,
757 HReg dst, HReg srcL, HReg srcR ) {
758 PPCInstr* i = LibVEX_Alloc(sizeof(PPCInstr));
759 i->tag = Pin_AddSubC;
760 i->Pin.AddSubC.isAdd = isAdd;
761 i->Pin.AddSubC.setC = setC;
762 i->Pin.AddSubC.dst = dst;
763 i->Pin.AddSubC.srcL = srcL;
764 i->Pin.AddSubC.srcR = srcR;
765 return i;
766 }
PPCInstr_Cmp(Bool syned,Bool sz32,UInt crfD,HReg srcL,PPCRH * srcR)767 PPCInstr* PPCInstr_Cmp ( Bool syned, Bool sz32,
768 UInt crfD, HReg srcL, PPCRH* srcR ) {
769 PPCInstr* i = LibVEX_Alloc(sizeof(PPCInstr));
770 i->tag = Pin_Cmp;
771 i->Pin.Cmp.syned = syned;
772 i->Pin.Cmp.sz32 = sz32;
773 i->Pin.Cmp.crfD = crfD;
774 i->Pin.Cmp.srcL = srcL;
775 i->Pin.Cmp.srcR = srcR;
776 return i;
777 }
PPCInstr_Unary(PPCUnaryOp op,HReg dst,HReg src)778 PPCInstr* PPCInstr_Unary ( PPCUnaryOp op, HReg dst, HReg src ) {
779 PPCInstr* i = LibVEX_Alloc(sizeof(PPCInstr));
780 i->tag = Pin_Unary;
781 i->Pin.Unary.op = op;
782 i->Pin.Unary.dst = dst;
783 i->Pin.Unary.src = src;
784 return i;
785 }
PPCInstr_MulL(Bool syned,Bool hi,Bool sz32,HReg dst,HReg srcL,HReg srcR)786 PPCInstr* PPCInstr_MulL ( Bool syned, Bool hi, Bool sz32,
787 HReg dst, HReg srcL, HReg srcR ) {
788 PPCInstr* i = LibVEX_Alloc(sizeof(PPCInstr));
789 i->tag = Pin_MulL;
790 i->Pin.MulL.syned = syned;
791 i->Pin.MulL.hi = hi;
792 i->Pin.MulL.sz32 = sz32;
793 i->Pin.MulL.dst = dst;
794 i->Pin.MulL.srcL = srcL;
795 i->Pin.MulL.srcR = srcR;
796 /* if doing the low word, the signedness is irrelevant, but tie it
797 down anyway. */
798 if (!hi) vassert(!syned);
799 return i;
800 }
PPCInstr_Div(Bool syned,Bool sz32,HReg dst,HReg srcL,HReg srcR)801 PPCInstr* PPCInstr_Div ( Bool syned, Bool sz32,
802 HReg dst, HReg srcL, HReg srcR ) {
803 PPCInstr* i = LibVEX_Alloc(sizeof(PPCInstr));
804 i->tag = Pin_Div;
805 i->Pin.Div.syned = syned;
806 i->Pin.Div.sz32 = sz32;
807 i->Pin.Div.dst = dst;
808 i->Pin.Div.srcL = srcL;
809 i->Pin.Div.srcR = srcR;
810 return i;
811 }
PPCInstr_Call(PPCCondCode cond,Addr64 target,UInt argiregs)812 PPCInstr* PPCInstr_Call ( PPCCondCode cond,
813 Addr64 target, UInt argiregs ) {
814 UInt mask;
815 PPCInstr* i = LibVEX_Alloc(sizeof(PPCInstr));
816 i->tag = Pin_Call;
817 i->Pin.Call.cond = cond;
818 i->Pin.Call.target = target;
819 i->Pin.Call.argiregs = argiregs;
820 /* Only r3 .. r10 inclusive may be used as arg regs. Hence: */
821 mask = (1<<3)|(1<<4)|(1<<5)|(1<<6)|(1<<7)|(1<<8)|(1<<9)|(1<<10);
822 vassert(0 == (argiregs & ~mask));
823 return i;
824 }
PPCInstr_Goto(IRJumpKind jk,PPCCondCode cond,PPCRI * dst)825 PPCInstr* PPCInstr_Goto ( IRJumpKind jk,
826 PPCCondCode cond, PPCRI* dst ) {
827 PPCInstr* i = LibVEX_Alloc(sizeof(PPCInstr));
828 i->tag = Pin_Goto;
829 i->Pin.Goto.cond = cond;
830 i->Pin.Goto.dst = dst;
831 i->Pin.Goto.jk = jk;
832 return i;
833 }
PPCInstr_CMov(PPCCondCode cond,HReg dst,PPCRI * src)834 PPCInstr* PPCInstr_CMov ( PPCCondCode cond,
835 HReg dst, PPCRI* src ) {
836 PPCInstr* i = LibVEX_Alloc(sizeof(PPCInstr));
837 i->tag = Pin_CMov;
838 i->Pin.CMov.cond = cond;
839 i->Pin.CMov.src = src;
840 i->Pin.CMov.dst = dst;
841 vassert(cond.test != Pct_ALWAYS);
842 return i;
843 }
PPCInstr_Load(UChar sz,HReg dst,PPCAMode * src,Bool mode64)844 PPCInstr* PPCInstr_Load ( UChar sz,
845 HReg dst, PPCAMode* src, Bool mode64 ) {
846 PPCInstr* i = LibVEX_Alloc(sizeof(PPCInstr));
847 i->tag = Pin_Load;
848 i->Pin.Load.sz = sz;
849 i->Pin.Load.src = src;
850 i->Pin.Load.dst = dst;
851 vassert(sz == 1 || sz == 2 || sz == 4 || sz == 8);
852 if (sz == 8) vassert(mode64);
853 return i;
854 }
PPCInstr_LoadL(UChar sz,HReg dst,HReg src,Bool mode64)855 PPCInstr* PPCInstr_LoadL ( UChar sz,
856 HReg dst, HReg src, Bool mode64 )
857 {
858 PPCInstr* i = LibVEX_Alloc(sizeof(PPCInstr));
859 i->tag = Pin_LoadL;
860 i->Pin.LoadL.sz = sz;
861 i->Pin.LoadL.src = src;
862 i->Pin.LoadL.dst = dst;
863 vassert(sz == 4 || sz == 8);
864 if (sz == 8) vassert(mode64);
865 return i;
866 }
PPCInstr_Store(UChar sz,PPCAMode * dst,HReg src,Bool mode64)867 PPCInstr* PPCInstr_Store ( UChar sz, PPCAMode* dst, HReg src,
868 Bool mode64 ) {
869 PPCInstr* i = LibVEX_Alloc(sizeof(PPCInstr));
870 i->tag = Pin_Store;
871 i->Pin.Store.sz = sz;
872 i->Pin.Store.src = src;
873 i->Pin.Store.dst = dst;
874 vassert(sz == 1 || sz == 2 || sz == 4 || sz == 8);
875 if (sz == 8) vassert(mode64);
876 return i;
877 }
PPCInstr_StoreC(UChar sz,HReg dst,HReg src,Bool mode64)878 PPCInstr* PPCInstr_StoreC ( UChar sz, HReg dst, HReg src, Bool mode64 ) {
879 PPCInstr* i = LibVEX_Alloc(sizeof(PPCInstr));
880 i->tag = Pin_StoreC;
881 i->Pin.StoreC.sz = sz;
882 i->Pin.StoreC.src = src;
883 i->Pin.StoreC.dst = dst;
884 vassert(sz == 4 || sz == 8);
885 if (sz == 8) vassert(mode64);
886 return i;
887 }
PPCInstr_Set(PPCCondCode cond,HReg dst)888 PPCInstr* PPCInstr_Set ( PPCCondCode cond, HReg dst ) {
889 PPCInstr* i = LibVEX_Alloc(sizeof(PPCInstr));
890 i->tag = Pin_Set;
891 i->Pin.Set.cond = cond;
892 i->Pin.Set.dst = dst;
893 return i;
894 }
PPCInstr_MfCR(HReg dst)895 PPCInstr* PPCInstr_MfCR ( HReg dst )
896 {
897 PPCInstr* i = LibVEX_Alloc(sizeof(PPCInstr));
898 i->tag = Pin_MfCR;
899 i->Pin.MfCR.dst = dst;
900 return i;
901 }
PPCInstr_MFence(void)902 PPCInstr* PPCInstr_MFence ( void )
903 {
904 PPCInstr* i = LibVEX_Alloc(sizeof(PPCInstr));
905 i->tag = Pin_MFence;
906 return i;
907 }
908
PPCInstr_FpUnary(PPCFpOp op,HReg dst,HReg src)909 PPCInstr* PPCInstr_FpUnary ( PPCFpOp op, HReg dst, HReg src ) {
910 PPCInstr* i = LibVEX_Alloc(sizeof(PPCInstr));
911 i->tag = Pin_FpUnary;
912 i->Pin.FpUnary.op = op;
913 i->Pin.FpUnary.dst = dst;
914 i->Pin.FpUnary.src = src;
915 return i;
916 }
PPCInstr_FpBinary(PPCFpOp op,HReg dst,HReg srcL,HReg srcR)917 PPCInstr* PPCInstr_FpBinary ( PPCFpOp op, HReg dst,
918 HReg srcL, HReg srcR ) {
919 PPCInstr* i = LibVEX_Alloc(sizeof(PPCInstr));
920 i->tag = Pin_FpBinary;
921 i->Pin.FpBinary.op = op;
922 i->Pin.FpBinary.dst = dst;
923 i->Pin.FpBinary.srcL = srcL;
924 i->Pin.FpBinary.srcR = srcR;
925 return i;
926 }
PPCInstr_FpMulAcc(PPCFpOp op,HReg dst,HReg srcML,HReg srcMR,HReg srcAcc)927 PPCInstr* PPCInstr_FpMulAcc ( PPCFpOp op, HReg dst, HReg srcML,
928 HReg srcMR, HReg srcAcc )
929 {
930 PPCInstr* i = LibVEX_Alloc(sizeof(PPCInstr));
931 i->tag = Pin_FpMulAcc;
932 i->Pin.FpMulAcc.op = op;
933 i->Pin.FpMulAcc.dst = dst;
934 i->Pin.FpMulAcc.srcML = srcML;
935 i->Pin.FpMulAcc.srcMR = srcMR;
936 i->Pin.FpMulAcc.srcAcc = srcAcc;
937 return i;
938 }
PPCInstr_FpLdSt(Bool isLoad,UChar sz,HReg reg,PPCAMode * addr)939 PPCInstr* PPCInstr_FpLdSt ( Bool isLoad, UChar sz,
940 HReg reg, PPCAMode* addr ) {
941 PPCInstr* i = LibVEX_Alloc(sizeof(PPCInstr));
942 i->tag = Pin_FpLdSt;
943 i->Pin.FpLdSt.isLoad = isLoad;
944 i->Pin.FpLdSt.sz = sz;
945 i->Pin.FpLdSt.reg = reg;
946 i->Pin.FpLdSt.addr = addr;
947 vassert(sz == 4 || sz == 8);
948 return i;
949 }
PPCInstr_FpSTFIW(HReg addr,HReg data)950 PPCInstr* PPCInstr_FpSTFIW ( HReg addr, HReg data )
951 {
952 PPCInstr* i = LibVEX_Alloc(sizeof(PPCInstr));
953 i->tag = Pin_FpSTFIW;
954 i->Pin.FpSTFIW.addr = addr;
955 i->Pin.FpSTFIW.data = data;
956 return i;
957 }
PPCInstr_FpRSP(HReg dst,HReg src)958 PPCInstr* PPCInstr_FpRSP ( HReg dst, HReg src ) {
959 PPCInstr* i = LibVEX_Alloc(sizeof(PPCInstr));
960 i->tag = Pin_FpRSP;
961 i->Pin.FpRSP.dst = dst;
962 i->Pin.FpRSP.src = src;
963 return i;
964 }
PPCInstr_FpCftI(Bool fromI,Bool int32,HReg dst,HReg src)965 PPCInstr* PPCInstr_FpCftI ( Bool fromI, Bool int32,
966 HReg dst, HReg src ) {
967 PPCInstr* i = LibVEX_Alloc(sizeof(PPCInstr));
968 i->tag = Pin_FpCftI;
969 i->Pin.FpCftI.fromI = fromI;
970 i->Pin.FpCftI.int32 = int32;
971 i->Pin.FpCftI.dst = dst;
972 i->Pin.FpCftI.src = src;
973 vassert(!(int32 && fromI)); /* no such insn ("fcfiw"). */
974 return i;
975 }
PPCInstr_FpCMov(PPCCondCode cond,HReg dst,HReg src)976 PPCInstr* PPCInstr_FpCMov ( PPCCondCode cond, HReg dst, HReg src ) {
977 PPCInstr* i = LibVEX_Alloc(sizeof(PPCInstr));
978 i->tag = Pin_FpCMov;
979 i->Pin.FpCMov.cond = cond;
980 i->Pin.FpCMov.dst = dst;
981 i->Pin.FpCMov.src = src;
982 vassert(cond.test != Pct_ALWAYS);
983 return i;
984 }
PPCInstr_FpLdFPSCR(HReg src)985 PPCInstr* PPCInstr_FpLdFPSCR ( HReg src ) {
986 PPCInstr* i = LibVEX_Alloc(sizeof(PPCInstr));
987 i->tag = Pin_FpLdFPSCR;
988 i->Pin.FpLdFPSCR.src = src;
989 return i;
990 }
PPCInstr_FpCmp(HReg dst,HReg srcL,HReg srcR)991 PPCInstr* PPCInstr_FpCmp ( HReg dst, HReg srcL, HReg srcR ) {
992 PPCInstr* i = LibVEX_Alloc(sizeof(PPCInstr));
993 i->tag = Pin_FpCmp;
994 i->Pin.FpCmp.dst = dst;
995 i->Pin.FpCmp.srcL = srcL;
996 i->Pin.FpCmp.srcR = srcR;
997 return i;
998 }
999
1000 /* Read/Write Link Register */
PPCInstr_RdWrLR(Bool wrLR,HReg gpr)1001 PPCInstr* PPCInstr_RdWrLR ( Bool wrLR, HReg gpr ) {
1002 PPCInstr* i = LibVEX_Alloc(sizeof(PPCInstr));
1003 i->tag = Pin_RdWrLR;
1004 i->Pin.RdWrLR.wrLR = wrLR;
1005 i->Pin.RdWrLR.gpr = gpr;
1006 return i;
1007 }
1008
1009 /* AltiVec */
PPCInstr_AvLdSt(Bool isLoad,UChar sz,HReg reg,PPCAMode * addr)1010 PPCInstr* PPCInstr_AvLdSt ( Bool isLoad, UChar sz,
1011 HReg reg, PPCAMode* addr ) {
1012 PPCInstr* i = LibVEX_Alloc(sizeof(PPCInstr));
1013 i->tag = Pin_AvLdSt;
1014 i->Pin.AvLdSt.isLoad = isLoad;
1015 i->Pin.AvLdSt.sz = sz;
1016 i->Pin.AvLdSt.reg = reg;
1017 i->Pin.AvLdSt.addr = addr;
1018 return i;
1019 }
PPCInstr_AvUnary(PPCAvOp op,HReg dst,HReg src)1020 PPCInstr* PPCInstr_AvUnary ( PPCAvOp op, HReg dst, HReg src ) {
1021 PPCInstr* i = LibVEX_Alloc(sizeof(PPCInstr));
1022 i->tag = Pin_AvUnary;
1023 i->Pin.AvUnary.op = op;
1024 i->Pin.AvUnary.dst = dst;
1025 i->Pin.AvUnary.src = src;
1026 return i;
1027 }
PPCInstr_AvBinary(PPCAvOp op,HReg dst,HReg srcL,HReg srcR)1028 PPCInstr* PPCInstr_AvBinary ( PPCAvOp op, HReg dst,
1029 HReg srcL, HReg srcR ) {
1030 PPCInstr* i = LibVEX_Alloc(sizeof(PPCInstr));
1031 i->tag = Pin_AvBinary;
1032 i->Pin.AvBinary.op = op;
1033 i->Pin.AvBinary.dst = dst;
1034 i->Pin.AvBinary.srcL = srcL;
1035 i->Pin.AvBinary.srcR = srcR;
1036 return i;
1037 }
PPCInstr_AvBin8x16(PPCAvOp op,HReg dst,HReg srcL,HReg srcR)1038 PPCInstr* PPCInstr_AvBin8x16 ( PPCAvOp op, HReg dst,
1039 HReg srcL, HReg srcR ) {
1040 PPCInstr* i = LibVEX_Alloc(sizeof(PPCInstr));
1041 i->tag = Pin_AvBin8x16;
1042 i->Pin.AvBin8x16.op = op;
1043 i->Pin.AvBin8x16.dst = dst;
1044 i->Pin.AvBin8x16.srcL = srcL;
1045 i->Pin.AvBin8x16.srcR = srcR;
1046 return i;
1047 }
PPCInstr_AvBin16x8(PPCAvOp op,HReg dst,HReg srcL,HReg srcR)1048 PPCInstr* PPCInstr_AvBin16x8 ( PPCAvOp op, HReg dst,
1049 HReg srcL, HReg srcR ) {
1050 PPCInstr* i = LibVEX_Alloc(sizeof(PPCInstr));
1051 i->tag = Pin_AvBin16x8;
1052 i->Pin.AvBin16x8.op = op;
1053 i->Pin.AvBin16x8.dst = dst;
1054 i->Pin.AvBin16x8.srcL = srcL;
1055 i->Pin.AvBin16x8.srcR = srcR;
1056 return i;
1057 }
PPCInstr_AvBin32x4(PPCAvOp op,HReg dst,HReg srcL,HReg srcR)1058 PPCInstr* PPCInstr_AvBin32x4 ( PPCAvOp op, HReg dst,
1059 HReg srcL, HReg srcR ) {
1060 PPCInstr* i = LibVEX_Alloc(sizeof(PPCInstr));
1061 i->tag = Pin_AvBin32x4;
1062 i->Pin.AvBin32x4.op = op;
1063 i->Pin.AvBin32x4.dst = dst;
1064 i->Pin.AvBin32x4.srcL = srcL;
1065 i->Pin.AvBin32x4.srcR = srcR;
1066 return i;
1067 }
PPCInstr_AvBin32Fx4(PPCAvOp op,HReg dst,HReg srcL,HReg srcR)1068 PPCInstr* PPCInstr_AvBin32Fx4 ( PPCAvOp op, HReg dst,
1069 HReg srcL, HReg srcR ) {
1070 PPCInstr* i = LibVEX_Alloc(sizeof(PPCInstr));
1071 i->tag = Pin_AvBin32Fx4;
1072 i->Pin.AvBin32Fx4.op = op;
1073 i->Pin.AvBin32Fx4.dst = dst;
1074 i->Pin.AvBin32Fx4.srcL = srcL;
1075 i->Pin.AvBin32Fx4.srcR = srcR;
1076 return i;
1077 }
PPCInstr_AvUn32Fx4(PPCAvOp op,HReg dst,HReg src)1078 PPCInstr* PPCInstr_AvUn32Fx4 ( PPCAvOp op, HReg dst, HReg src ) {
1079 PPCInstr* i = LibVEX_Alloc(sizeof(PPCInstr));
1080 i->tag = Pin_AvUn32Fx4;
1081 i->Pin.AvUn32Fx4.op = op;
1082 i->Pin.AvUn32Fx4.dst = dst;
1083 i->Pin.AvUn32Fx4.src = src;
1084 return i;
1085 }
PPCInstr_AvPerm(HReg dst,HReg srcL,HReg srcR,HReg ctl)1086 PPCInstr* PPCInstr_AvPerm ( HReg dst, HReg srcL, HReg srcR, HReg ctl ) {
1087 PPCInstr* i = LibVEX_Alloc(sizeof(PPCInstr));
1088 i->tag = Pin_AvPerm;
1089 i->Pin.AvPerm.dst = dst;
1090 i->Pin.AvPerm.srcL = srcL;
1091 i->Pin.AvPerm.srcR = srcR;
1092 i->Pin.AvPerm.ctl = ctl;
1093 return i;
1094 }
PPCInstr_AvSel(HReg ctl,HReg dst,HReg srcL,HReg srcR)1095 PPCInstr* PPCInstr_AvSel ( HReg ctl, HReg dst, HReg srcL, HReg srcR ) {
1096 PPCInstr* i = LibVEX_Alloc(sizeof(PPCInstr));
1097 i->tag = Pin_AvSel;
1098 i->Pin.AvSel.ctl = ctl;
1099 i->Pin.AvSel.dst = dst;
1100 i->Pin.AvSel.srcL = srcL;
1101 i->Pin.AvSel.srcR = srcR;
1102 return i;
1103 }
PPCInstr_AvShlDbl(UChar shift,HReg dst,HReg srcL,HReg srcR)1104 PPCInstr* PPCInstr_AvShlDbl ( UChar shift, HReg dst,
1105 HReg srcL, HReg srcR ) {
1106 PPCInstr* i = LibVEX_Alloc(sizeof(PPCInstr));
1107 i->tag = Pin_AvShlDbl;
1108 i->Pin.AvShlDbl.shift = shift;
1109 i->Pin.AvShlDbl.dst = dst;
1110 i->Pin.AvShlDbl.srcL = srcL;
1111 i->Pin.AvShlDbl.srcR = srcR;
1112 return i;
1113 }
PPCInstr_AvSplat(UChar sz,HReg dst,PPCVI5s * src)1114 PPCInstr* PPCInstr_AvSplat ( UChar sz, HReg dst, PPCVI5s* src ) {
1115 PPCInstr* i = LibVEX_Alloc(sizeof(PPCInstr));
1116 i->tag = Pin_AvSplat;
1117 i->Pin.AvSplat.sz = sz;
1118 i->Pin.AvSplat.dst = dst;
1119 i->Pin.AvSplat.src = src;
1120 return i;
1121 }
PPCInstr_AvCMov(PPCCondCode cond,HReg dst,HReg src)1122 PPCInstr* PPCInstr_AvCMov ( PPCCondCode cond, HReg dst, HReg src ) {
1123 PPCInstr* i = LibVEX_Alloc(sizeof(PPCInstr));
1124 i->tag = Pin_AvCMov;
1125 i->Pin.AvCMov.cond = cond;
1126 i->Pin.AvCMov.dst = dst;
1127 i->Pin.AvCMov.src = src;
1128 vassert(cond.test != Pct_ALWAYS);
1129 return i;
1130 }
PPCInstr_AvLdVSCR(HReg src)1131 PPCInstr* PPCInstr_AvLdVSCR ( HReg src ) {
1132 PPCInstr* i = LibVEX_Alloc(sizeof(PPCInstr));
1133 i->tag = Pin_AvLdVSCR;
1134 i->Pin.AvLdVSCR.src = src;
1135 return i;
1136 }
1137
1138
1139 /* Pretty Print instructions */
ppLoadImm(HReg dst,ULong imm,Bool mode64)1140 static void ppLoadImm ( HReg dst, ULong imm, Bool mode64 ) {
1141 vex_printf("li_word ");
1142 ppHRegPPC(dst);
1143 if (!mode64) {
1144 vex_printf(",0x%08x", (UInt)imm);
1145 } else {
1146 vex_printf(",0x%016llx", imm);
1147 }
1148 }
1149
ppMovReg(HReg dst,HReg src)1150 static void ppMovReg ( HReg dst, HReg src ) {
1151 if (hregNumber(dst) != hregNumber(src)) {
1152 vex_printf("mr ");
1153 ppHRegPPC(dst);
1154 vex_printf(",");
1155 ppHRegPPC(src);
1156 }
1157 }
1158
ppPPCInstr(PPCInstr * i,Bool mode64)1159 void ppPPCInstr ( PPCInstr* i, Bool mode64 )
1160 {
1161 switch (i->tag) {
1162 case Pin_LI:
1163 ppLoadImm(i->Pin.LI.dst, i->Pin.LI.imm64, mode64);
1164 break;
1165 case Pin_Alu: {
1166 HReg r_srcL = i->Pin.Alu.srcL;
1167 PPCRH* rh_srcR = i->Pin.Alu.srcR;
1168 /* special-case "mr" */
1169 if (i->Pin.Alu.op == Palu_OR && // or Rd,Rs,Rs == mr Rd,Rs
1170 rh_srcR->tag == Prh_Reg &&
1171 rh_srcR->Prh.Reg.reg == r_srcL) {
1172 vex_printf("mr ");
1173 ppHRegPPC(i->Pin.Alu.dst);
1174 vex_printf(",");
1175 ppHRegPPC(r_srcL);
1176 return;
1177 }
1178 /* special-case "li" */
1179 if (i->Pin.Alu.op == Palu_ADD && // addi Rd,0,imm == li Rd,imm
1180 rh_srcR->tag == Prh_Imm &&
1181 hregNumber(r_srcL) == 0) {
1182 vex_printf("li ");
1183 ppHRegPPC(i->Pin.Alu.dst);
1184 vex_printf(",");
1185 ppPPCRH(rh_srcR);
1186 return;
1187 }
1188 /* generic */
1189 vex_printf("%s ", showPPCAluOp(i->Pin.Alu.op,
1190 toBool(rh_srcR->tag == Prh_Imm)));
1191 ppHRegPPC(i->Pin.Alu.dst);
1192 vex_printf(",");
1193 ppHRegPPC(r_srcL);
1194 vex_printf(",");
1195 ppPPCRH(rh_srcR);
1196 return;
1197 }
1198 case Pin_Shft: {
1199 HReg r_srcL = i->Pin.Shft.srcL;
1200 PPCRH* rh_srcR = i->Pin.Shft.srcR;
1201 vex_printf("%s ", showPPCShftOp(i->Pin.Shft.op,
1202 toBool(rh_srcR->tag == Prh_Imm),
1203 i->Pin.Shft.sz32));
1204 ppHRegPPC(i->Pin.Shft.dst);
1205 vex_printf(",");
1206 ppHRegPPC(r_srcL);
1207 vex_printf(",");
1208 ppPPCRH(rh_srcR);
1209 return;
1210 }
1211 case Pin_AddSubC:
1212 vex_printf("%s%s ",
1213 i->Pin.AddSubC.isAdd ? "add" : "sub",
1214 i->Pin.AddSubC.setC ? "c" : "e");
1215 ppHRegPPC(i->Pin.AddSubC.dst);
1216 vex_printf(",");
1217 ppHRegPPC(i->Pin.AddSubC.srcL);
1218 vex_printf(",");
1219 ppHRegPPC(i->Pin.AddSubC.srcR);
1220 return;
1221 case Pin_Cmp:
1222 vex_printf("%s%c%s %%cr%u,",
1223 i->Pin.Cmp.syned ? "cmp" : "cmpl",
1224 i->Pin.Cmp.sz32 ? 'w' : 'd',
1225 i->Pin.Cmp.srcR->tag == Prh_Imm ? "i" : "",
1226 i->Pin.Cmp.crfD);
1227 ppHRegPPC(i->Pin.Cmp.srcL);
1228 vex_printf(",");
1229 ppPPCRH(i->Pin.Cmp.srcR);
1230 return;
1231 case Pin_Unary:
1232 vex_printf("%s ", showPPCUnaryOp(i->Pin.Unary.op));
1233 ppHRegPPC(i->Pin.Unary.dst);
1234 vex_printf(",");
1235 ppHRegPPC(i->Pin.Unary.src);
1236 return;
1237 case Pin_MulL:
1238 vex_printf("mul%c%c%s ",
1239 i->Pin.MulL.hi ? 'h' : 'l',
1240 i->Pin.MulL.sz32 ? 'w' : 'd',
1241 i->Pin.MulL.hi ? (i->Pin.MulL.syned ? "s" : "u") : "");
1242 ppHRegPPC(i->Pin.MulL.dst);
1243 vex_printf(",");
1244 ppHRegPPC(i->Pin.MulL.srcL);
1245 vex_printf(",");
1246 ppHRegPPC(i->Pin.MulL.srcR);
1247 return;
1248 case Pin_Div:
1249 vex_printf("div%c%s ",
1250 i->Pin.Div.sz32 ? 'w' : 'd',
1251 i->Pin.Div.syned ? "" : "u");
1252 ppHRegPPC(i->Pin.Div.dst);
1253 vex_printf(",");
1254 ppHRegPPC(i->Pin.Div.srcL);
1255 vex_printf(",");
1256 ppHRegPPC(i->Pin.Div.srcR);
1257 return;
1258 case Pin_Call: {
1259 Int n;
1260 vex_printf("call: ");
1261 if (i->Pin.Call.cond.test != Pct_ALWAYS) {
1262 vex_printf("if (%s) ", showPPCCondCode(i->Pin.Call.cond));
1263 }
1264 vex_printf("{ ");
1265 ppLoadImm(hregPPC_GPR10(mode64), i->Pin.Call.target, mode64);
1266 vex_printf(" ; mtctr r10 ; bctrl [");
1267 for (n = 0; n < 32; n++) {
1268 if (i->Pin.Call.argiregs & (1<<n)) {
1269 vex_printf("r%d", n);
1270 if ((i->Pin.Call.argiregs >> n) > 1)
1271 vex_printf(",");
1272 }
1273 }
1274 vex_printf("] }");
1275 break;
1276 }
1277 case Pin_Goto:
1278 vex_printf("goto: ");
1279 if (i->Pin.Goto.cond.test != Pct_ALWAYS) {
1280 vex_printf("if (%s) ", showPPCCondCode(i->Pin.Goto.cond));
1281 }
1282 vex_printf("{ ");
1283 if (i->Pin.Goto.jk != Ijk_Boring
1284 && i->Pin.Goto.jk != Ijk_Call
1285 && i->Pin.Goto.jk != Ijk_Ret) {
1286 vex_printf("li %%r31,$");
1287 ppIRJumpKind(i->Pin.Goto.jk);
1288 vex_printf(" ; ");
1289 }
1290 if (i->Pin.Goto.dst->tag == Pri_Imm) {
1291 ppLoadImm(hregPPC_GPR3(mode64), i->Pin.Goto.dst->Pri.Imm,
1292 mode64);
1293 } else {
1294 ppMovReg(hregPPC_GPR3(mode64), i->Pin.Goto.dst->Pri.Reg);
1295 }
1296 vex_printf(" ; blr }");
1297 return;
1298 case Pin_CMov:
1299 vex_printf("cmov (%s) ", showPPCCondCode(i->Pin.CMov.cond));
1300 ppHRegPPC(i->Pin.CMov.dst);
1301 vex_printf(",");
1302 ppPPCRI(i->Pin.CMov.src);
1303 vex_printf(": ");
1304 if (i->Pin.CMov.cond.test != Pct_ALWAYS) {
1305 vex_printf("if (%s) ", showPPCCondCode(i->Pin.CMov.cond));
1306 }
1307 vex_printf("{ ");
1308 if (i->Pin.CMov.src->tag == Pri_Imm) {
1309 ppLoadImm(i->Pin.CMov.dst, i->Pin.CMov.src->Pri.Imm, mode64);
1310 } else {
1311 ppMovReg(i->Pin.CMov.dst, i->Pin.CMov.src->Pri.Reg);
1312 }
1313 vex_printf(" }");
1314 return;
1315 case Pin_Load: {
1316 Bool idxd = toBool(i->Pin.Load.src->tag == Pam_RR);
1317 UChar sz = i->Pin.Load.sz;
1318 UChar c_sz = sz==1 ? 'b' : sz==2 ? 'h' : sz==4 ? 'w' : 'd';
1319 vex_printf("l%c%s%s ", c_sz, sz==8 ? "" : "z", idxd ? "x" : "" );
1320 ppHRegPPC(i->Pin.Load.dst);
1321 vex_printf(",");
1322 ppPPCAMode(i->Pin.Load.src);
1323 return;
1324 }
1325 case Pin_LoadL:
1326 vex_printf("l%carx ", i->Pin.LoadL.sz==4 ? 'w' : 'd');
1327 ppHRegPPC(i->Pin.LoadL.dst);
1328 vex_printf(",%%r0,");
1329 ppHRegPPC(i->Pin.LoadL.src);
1330 return;
1331 case Pin_Store: {
1332 UChar sz = i->Pin.Store.sz;
1333 Bool idxd = toBool(i->Pin.Store.dst->tag == Pam_RR);
1334 UChar c_sz = sz==1 ? 'b' : sz==2 ? 'h' : sz==4 ? 'w' : /*8*/ 'd';
1335 vex_printf("st%c%s ", c_sz, idxd ? "x" : "" );
1336 ppHRegPPC(i->Pin.Store.src);
1337 vex_printf(",");
1338 ppPPCAMode(i->Pin.Store.dst);
1339 return;
1340 }
1341 case Pin_StoreC:
1342 vex_printf("st%ccx. ", i->Pin.StoreC.sz==4 ? 'w' : 'd');
1343 ppHRegPPC(i->Pin.StoreC.src);
1344 vex_printf(",%%r0,");
1345 ppHRegPPC(i->Pin.StoreC.dst);
1346 return;
1347 case Pin_Set: {
1348 PPCCondCode cc = i->Pin.Set.cond;
1349 vex_printf("set (%s),", showPPCCondCode(cc));
1350 ppHRegPPC(i->Pin.Set.dst);
1351 if (cc.test == Pct_ALWAYS) {
1352 vex_printf(": { li ");
1353 ppHRegPPC(i->Pin.Set.dst);
1354 vex_printf(",1 }");
1355 } else {
1356 vex_printf(": { mfcr r0 ; rlwinm ");
1357 ppHRegPPC(i->Pin.Set.dst);
1358 vex_printf(",r0,%u,31,31", cc.flag+1);
1359 if (cc.test == Pct_FALSE) {
1360 vex_printf("; xori ");
1361 ppHRegPPC(i->Pin.Set.dst);
1362 vex_printf(",");
1363 ppHRegPPC(i->Pin.Set.dst);
1364 vex_printf(",1");
1365 }
1366 vex_printf(" }");
1367 }
1368 return;
1369 }
1370 case Pin_MfCR:
1371 vex_printf("mfcr ");
1372 ppHRegPPC(i->Pin.MfCR.dst);
1373 break;
1374 case Pin_MFence:
1375 vex_printf("mfence (=sync)");
1376 return;
1377
1378 case Pin_FpUnary:
1379 vex_printf("%s ", showPPCFpOp(i->Pin.FpUnary.op));
1380 ppHRegPPC(i->Pin.FpUnary.dst);
1381 vex_printf(",");
1382 ppHRegPPC(i->Pin.FpUnary.src);
1383 return;
1384 case Pin_FpBinary:
1385 vex_printf("%s ", showPPCFpOp(i->Pin.FpBinary.op));
1386 ppHRegPPC(i->Pin.FpBinary.dst);
1387 vex_printf(",");
1388 ppHRegPPC(i->Pin.FpBinary.srcL);
1389 vex_printf(",");
1390 ppHRegPPC(i->Pin.FpBinary.srcR);
1391 return;
1392 case Pin_FpMulAcc:
1393 vex_printf("%s ", showPPCFpOp(i->Pin.FpMulAcc.op));
1394 ppHRegPPC(i->Pin.FpMulAcc.dst);
1395 vex_printf(",");
1396 ppHRegPPC(i->Pin.FpMulAcc.srcML);
1397 vex_printf(",");
1398 ppHRegPPC(i->Pin.FpMulAcc.srcMR);
1399 vex_printf(",");
1400 ppHRegPPC(i->Pin.FpMulAcc.srcAcc);
1401 return;
1402 case Pin_FpLdSt: {
1403 UChar sz = i->Pin.FpLdSt.sz;
1404 Bool idxd = toBool(i->Pin.FpLdSt.addr->tag == Pam_RR);
1405 if (i->Pin.FpLdSt.isLoad) {
1406 vex_printf("lf%c%s ",
1407 (sz==4 ? 's' : 'd'),
1408 idxd ? "x" : "" );
1409 ppHRegPPC(i->Pin.FpLdSt.reg);
1410 vex_printf(",");
1411 ppPPCAMode(i->Pin.FpLdSt.addr);
1412 } else {
1413 vex_printf("stf%c%s ",
1414 (sz==4 ? 's' : 'd'),
1415 idxd ? "x" : "" );
1416 ppHRegPPC(i->Pin.FpLdSt.reg);
1417 vex_printf(",");
1418 ppPPCAMode(i->Pin.FpLdSt.addr);
1419 }
1420 return;
1421 }
1422 case Pin_FpSTFIW:
1423 vex_printf("stfiwz ");
1424 ppHRegPPC(i->Pin.FpSTFIW.data);
1425 vex_printf(",0(");
1426 ppHRegPPC(i->Pin.FpSTFIW.addr);
1427 vex_printf(")");
1428 return;
1429 case Pin_FpRSP:
1430 vex_printf("frsp ");
1431 ppHRegPPC(i->Pin.FpRSP.dst);
1432 vex_printf(",");
1433 ppHRegPPC(i->Pin.FpRSP.src);
1434 return;
1435 case Pin_FpCftI: {
1436 HChar* str = "fc???";
1437 if (i->Pin.FpCftI.fromI == False && i->Pin.FpCftI.int32 == False)
1438 str = "fctid";
1439 else
1440 if (i->Pin.FpCftI.fromI == False && i->Pin.FpCftI.int32 == True)
1441 str = "fctiw";
1442 else
1443 if (i->Pin.FpCftI.fromI == True && i->Pin.FpCftI.int32 == False)
1444 str = "fcfid";
1445 vex_printf("%s ", str);
1446 ppHRegPPC(i->Pin.FpCftI.dst);
1447 vex_printf(",");
1448 ppHRegPPC(i->Pin.FpCftI.src);
1449 return;
1450 }
1451 case Pin_FpCMov:
1452 vex_printf("fpcmov (%s) ", showPPCCondCode(i->Pin.FpCMov.cond));
1453 ppHRegPPC(i->Pin.FpCMov.dst);
1454 vex_printf(",");
1455 ppHRegPPC(i->Pin.FpCMov.src);
1456 vex_printf(": ");
1457 vex_printf("if (fr_dst != fr_src) { ");
1458 if (i->Pin.FpCMov.cond.test != Pct_ALWAYS) {
1459 vex_printf("if (%s) { ", showPPCCondCode(i->Pin.FpCMov.cond));
1460 }
1461 vex_printf("fmr ");
1462 ppHRegPPC(i->Pin.FpCMov.dst);
1463 vex_printf(",");
1464 ppHRegPPC(i->Pin.FpCMov.src);
1465 if (i->Pin.FpCMov.cond.test != Pct_ALWAYS)
1466 vex_printf(" }");
1467 vex_printf(" }");
1468 return;
1469 case Pin_FpLdFPSCR:
1470 vex_printf("mtfsf 0xFF,");
1471 ppHRegPPC(i->Pin.FpLdFPSCR.src);
1472 return;
1473 case Pin_FpCmp:
1474 vex_printf("fcmpo %%cr1,");
1475 ppHRegPPC(i->Pin.FpCmp.srcL);
1476 vex_printf(",");
1477 ppHRegPPC(i->Pin.FpCmp.srcR);
1478 vex_printf("; mfcr ");
1479 ppHRegPPC(i->Pin.FpCmp.dst);
1480 vex_printf("; rlwinm ");
1481 ppHRegPPC(i->Pin.FpCmp.dst);
1482 vex_printf(",");
1483 ppHRegPPC(i->Pin.FpCmp.dst);
1484 vex_printf(",8,28,31");
1485 return;
1486
1487 case Pin_RdWrLR:
1488 vex_printf("%s ", i->Pin.RdWrLR.wrLR ? "mtlr" : "mflr");
1489 ppHRegPPC(i->Pin.RdWrLR.gpr);
1490 return;
1491
1492 case Pin_AvLdSt: {
1493 UChar sz = i->Pin.AvLdSt.sz;
1494 HChar* str_size;
1495 if (i->Pin.AvLdSt.addr->tag == Pam_IR) {
1496 ppLoadImm(hregPPC_GPR30(mode64),
1497 i->Pin.AvLdSt.addr->Pam.RR.index, mode64);
1498 vex_printf(" ; ");
1499 }
1500 str_size = sz==1 ? "eb" : sz==2 ? "eh" : sz==4 ? "ew" : "";
1501 if (i->Pin.AvLdSt.isLoad)
1502 vex_printf("lv%sx ", str_size);
1503 else
1504 vex_printf("stv%sx ", str_size);
1505 ppHRegPPC(i->Pin.AvLdSt.reg);
1506 vex_printf(",");
1507 if (i->Pin.AvLdSt.addr->tag == Pam_IR)
1508 vex_printf("%%r30");
1509 else
1510 ppHRegPPC(i->Pin.AvLdSt.addr->Pam.RR.index);
1511 vex_printf(",");
1512 ppHRegPPC(i->Pin.AvLdSt.addr->Pam.RR.base);
1513 return;
1514 }
1515 case Pin_AvUnary:
1516 vex_printf("%s ", showPPCAvOp(i->Pin.AvUnary.op));
1517 ppHRegPPC(i->Pin.AvUnary.dst);
1518 vex_printf(",");
1519 ppHRegPPC(i->Pin.AvUnary.src);
1520 return;
1521 case Pin_AvBinary:
1522 vex_printf("%s ", showPPCAvOp(i->Pin.AvBinary.op));
1523 ppHRegPPC(i->Pin.AvBinary.dst);
1524 vex_printf(",");
1525 ppHRegPPC(i->Pin.AvBinary.srcL);
1526 vex_printf(",");
1527 ppHRegPPC(i->Pin.AvBinary.srcR);
1528 return;
1529 case Pin_AvBin8x16:
1530 vex_printf("%s(b) ", showPPCAvOp(i->Pin.AvBin8x16.op));
1531 ppHRegPPC(i->Pin.AvBin8x16.dst);
1532 vex_printf(",");
1533 ppHRegPPC(i->Pin.AvBin8x16.srcL);
1534 vex_printf(",");
1535 ppHRegPPC(i->Pin.AvBin8x16.srcR);
1536 return;
1537 case Pin_AvBin16x8:
1538 vex_printf("%s(h) ", showPPCAvOp(i->Pin.AvBin16x8.op));
1539 ppHRegPPC(i->Pin.AvBin16x8.dst);
1540 vex_printf(",");
1541 ppHRegPPC(i->Pin.AvBin16x8.srcL);
1542 vex_printf(",");
1543 ppHRegPPC(i->Pin.AvBin16x8.srcR);
1544 return;
1545 case Pin_AvBin32x4:
1546 vex_printf("%s(w) ", showPPCAvOp(i->Pin.AvBin32x4.op));
1547 ppHRegPPC(i->Pin.AvBin32x4.dst);
1548 vex_printf(",");
1549 ppHRegPPC(i->Pin.AvBin32x4.srcL);
1550 vex_printf(",");
1551 ppHRegPPC(i->Pin.AvBin32x4.srcR);
1552 return;
1553 case Pin_AvBin32Fx4:
1554 vex_printf("%s ", showPPCAvFpOp(i->Pin.AvBin32Fx4.op));
1555 ppHRegPPC(i->Pin.AvBin32Fx4.dst);
1556 vex_printf(",");
1557 ppHRegPPC(i->Pin.AvBin32Fx4.srcL);
1558 vex_printf(",");
1559 ppHRegPPC(i->Pin.AvBin32Fx4.srcR);
1560 return;
1561 case Pin_AvUn32Fx4:
1562 vex_printf("%s ", showPPCAvFpOp(i->Pin.AvUn32Fx4.op));
1563 ppHRegPPC(i->Pin.AvUn32Fx4.dst);
1564 vex_printf(",");
1565 ppHRegPPC(i->Pin.AvUn32Fx4.src);
1566 return;
1567 case Pin_AvPerm:
1568 vex_printf("vperm ");
1569 ppHRegPPC(i->Pin.AvPerm.dst);
1570 vex_printf(",");
1571 ppHRegPPC(i->Pin.AvPerm.srcL);
1572 vex_printf(",");
1573 ppHRegPPC(i->Pin.AvPerm.srcR);
1574 vex_printf(",");
1575 ppHRegPPC(i->Pin.AvPerm.ctl);
1576 return;
1577
1578 case Pin_AvSel:
1579 vex_printf("vsel ");
1580 ppHRegPPC(i->Pin.AvSel.dst);
1581 vex_printf(",");
1582 ppHRegPPC(i->Pin.AvSel.srcL);
1583 vex_printf(",");
1584 ppHRegPPC(i->Pin.AvSel.srcR);
1585 vex_printf(",");
1586 ppHRegPPC(i->Pin.AvSel.ctl);
1587 return;
1588
1589 case Pin_AvShlDbl:
1590 vex_printf("vsldoi ");
1591 ppHRegPPC(i->Pin.AvShlDbl.dst);
1592 vex_printf(",");
1593 ppHRegPPC(i->Pin.AvShlDbl.srcL);
1594 vex_printf(",");
1595 ppHRegPPC(i->Pin.AvShlDbl.srcR);
1596 vex_printf(",%d", i->Pin.AvShlDbl.shift);
1597 return;
1598
1599 case Pin_AvSplat: {
1600 UChar sz = i->Pin.AvSplat.sz;
1601 UChar ch_sz = toUChar( (sz == 8) ? 'b' : (sz == 16) ? 'h' : 'w' );
1602 vex_printf("vsplt%s%c ",
1603 i->Pin.AvSplat.src->tag == Pvi_Imm ? "is" : "", ch_sz);
1604 ppHRegPPC(i->Pin.AvSplat.dst);
1605 vex_printf(",");
1606 ppPPCVI5s(i->Pin.AvSplat.src);
1607 if (i->Pin.AvSplat.src->tag == Pvi_Reg)
1608 vex_printf(", %d", (128/sz)-1); /* louis lane */
1609 return;
1610 }
1611
1612 case Pin_AvCMov:
1613 vex_printf("avcmov (%s) ", showPPCCondCode(i->Pin.AvCMov.cond));
1614 ppHRegPPC(i->Pin.AvCMov.dst);
1615 vex_printf(",");
1616 ppHRegPPC(i->Pin.AvCMov.src);
1617 vex_printf(": ");
1618 vex_printf("if (v_dst != v_src) { ");
1619 if (i->Pin.AvCMov.cond.test != Pct_ALWAYS) {
1620 vex_printf("if (%s) { ", showPPCCondCode(i->Pin.AvCMov.cond));
1621 }
1622 vex_printf("vmr ");
1623 ppHRegPPC(i->Pin.AvCMov.dst);
1624 vex_printf(",");
1625 ppHRegPPC(i->Pin.AvCMov.src);
1626 if (i->Pin.FpCMov.cond.test != Pct_ALWAYS)
1627 vex_printf(" }");
1628 vex_printf(" }");
1629 return;
1630
1631 case Pin_AvLdVSCR:
1632 vex_printf("mtvscr ");
1633 ppHRegPPC(i->Pin.AvLdVSCR.src);
1634 return;
1635
1636 default:
1637 vex_printf("\nppPPCInstr: No such tag(%d)\n", (Int)i->tag);
1638 vpanic("ppPPCInstr");
1639 }
1640 }
1641
1642 /* --------- Helpers for register allocation. --------- */
1643
getRegUsage_PPCInstr(HRegUsage * u,PPCInstr * i,Bool mode64)1644 void getRegUsage_PPCInstr ( HRegUsage* u, PPCInstr* i, Bool mode64 )
1645 {
1646 initHRegUsage(u);
1647 switch (i->tag) {
1648 case Pin_LI:
1649 addHRegUse(u, HRmWrite, i->Pin.LI.dst);
1650 break;
1651 case Pin_Alu:
1652 addHRegUse(u, HRmRead, i->Pin.Alu.srcL);
1653 addRegUsage_PPCRH(u, i->Pin.Alu.srcR);
1654 addHRegUse(u, HRmWrite, i->Pin.Alu.dst);
1655 return;
1656 case Pin_Shft:
1657 addHRegUse(u, HRmRead, i->Pin.Shft.srcL);
1658 addRegUsage_PPCRH(u, i->Pin.Shft.srcR);
1659 addHRegUse(u, HRmWrite, i->Pin.Shft.dst);
1660 return;
1661 case Pin_AddSubC:
1662 addHRegUse(u, HRmWrite, i->Pin.AddSubC.dst);
1663 addHRegUse(u, HRmRead, i->Pin.AddSubC.srcL);
1664 addHRegUse(u, HRmRead, i->Pin.AddSubC.srcR);
1665 return;
1666 case Pin_Cmp:
1667 addHRegUse(u, HRmRead, i->Pin.Cmp.srcL);
1668 addRegUsage_PPCRH(u, i->Pin.Cmp.srcR);
1669 return;
1670 case Pin_Unary:
1671 addHRegUse(u, HRmWrite, i->Pin.Unary.dst);
1672 addHRegUse(u, HRmRead, i->Pin.Unary.src);
1673 return;
1674 case Pin_MulL:
1675 addHRegUse(u, HRmWrite, i->Pin.MulL.dst);
1676 addHRegUse(u, HRmRead, i->Pin.MulL.srcL);
1677 addHRegUse(u, HRmRead, i->Pin.MulL.srcR);
1678 return;
1679 case Pin_Div:
1680 addHRegUse(u, HRmWrite, i->Pin.Div.dst);
1681 addHRegUse(u, HRmRead, i->Pin.Div.srcL);
1682 addHRegUse(u, HRmRead, i->Pin.Div.srcR);
1683 return;
1684 case Pin_Call: {
1685 UInt argir;
1686 /* This is a bit subtle. */
1687 /* First off, claim it trashes all the caller-saved regs
1688 which fall within the register allocator's jurisdiction.
1689 These I believe to be:
1690 mode32: r3 to r12
1691 mode64: r3 to r10
1692 */
1693 /* XXXXXXXXXXXXXXXXX BUG! This doesn't say anything about the FP
1694 or Altivec registers. We get away with this ONLY because
1695 getAllocatableRegs_PPC gives the allocator callee-saved fp
1696 and Altivec regs, and no caller-save ones. */
1697 addHRegUse(u, HRmWrite, hregPPC_GPR3(mode64));
1698 addHRegUse(u, HRmWrite, hregPPC_GPR4(mode64));
1699 addHRegUse(u, HRmWrite, hregPPC_GPR5(mode64));
1700 addHRegUse(u, HRmWrite, hregPPC_GPR6(mode64));
1701 addHRegUse(u, HRmWrite, hregPPC_GPR7(mode64));
1702 addHRegUse(u, HRmWrite, hregPPC_GPR8(mode64));
1703 addHRegUse(u, HRmWrite, hregPPC_GPR9(mode64));
1704 addHRegUse(u, HRmWrite, hregPPC_GPR10(mode64));
1705 if (!mode64) {
1706 addHRegUse(u, HRmWrite, hregPPC_GPR11(mode64));
1707 addHRegUse(u, HRmWrite, hregPPC_GPR12(mode64));
1708 }
1709
1710 /* Now we have to state any parameter-carrying registers
1711 which might be read. This depends on the argiregs field. */
1712 argir = i->Pin.Call.argiregs;
1713 if (argir &(1<<10)) addHRegUse(u, HRmRead, hregPPC_GPR10(mode64));
1714 if (argir & (1<<9)) addHRegUse(u, HRmRead, hregPPC_GPR9(mode64));
1715 if (argir & (1<<8)) addHRegUse(u, HRmRead, hregPPC_GPR8(mode64));
1716 if (argir & (1<<7)) addHRegUse(u, HRmRead, hregPPC_GPR7(mode64));
1717 if (argir & (1<<6)) addHRegUse(u, HRmRead, hregPPC_GPR6(mode64));
1718 if (argir & (1<<5)) addHRegUse(u, HRmRead, hregPPC_GPR5(mode64));
1719 if (argir & (1<<4)) addHRegUse(u, HRmRead, hregPPC_GPR4(mode64));
1720 if (argir & (1<<3)) addHRegUse(u, HRmRead, hregPPC_GPR3(mode64));
1721
1722 vassert(0 == (argir & ~((1<<3)|(1<<4)|(1<<5)|(1<<6)
1723 |(1<<7)|(1<<8)|(1<<9)|(1<<10))));
1724
1725 /* Finally, there is the issue that the insn trashes a
1726 register because the literal target address has to be
1727 loaded into a register. %r10 seems a suitable victim.
1728 (Can't use %r0, as some insns interpret it as value zero). */
1729 addHRegUse(u, HRmWrite, hregPPC_GPR10(mode64));
1730 /* Upshot of this is that the assembler really must use %r10,
1731 and no other, as a destination temporary. */
1732 return;
1733 }
1734 case Pin_Goto:
1735 addRegUsage_PPCRI(u, i->Pin.Goto.dst);
1736 /* GPR3 holds destination address from Pin_Goto */
1737 addHRegUse(u, HRmWrite, hregPPC_GPR3(mode64));
1738 if (i->Pin.Goto.jk != Ijk_Boring
1739 && i->Pin.Goto.jk != Ijk_Call
1740 && i->Pin.Goto.jk != Ijk_Ret)
1741 /* note, this is irrelevant since the guest state pointer
1742 register is not actually available to the allocator.
1743 But still .. */
1744 addHRegUse(u, HRmWrite, GuestStatePtr(mode64));
1745 return;
1746 case Pin_CMov:
1747 addRegUsage_PPCRI(u, i->Pin.CMov.src);
1748 addHRegUse(u, HRmWrite, i->Pin.CMov.dst);
1749 return;
1750 case Pin_Load:
1751 addRegUsage_PPCAMode(u, i->Pin.Load.src);
1752 addHRegUse(u, HRmWrite, i->Pin.Load.dst);
1753 return;
1754 case Pin_LoadL:
1755 addHRegUse(u, HRmRead, i->Pin.LoadL.src);
1756 addHRegUse(u, HRmWrite, i->Pin.LoadL.dst);
1757 return;
1758 case Pin_Store:
1759 addHRegUse(u, HRmRead, i->Pin.Store.src);
1760 addRegUsage_PPCAMode(u, i->Pin.Store.dst);
1761 return;
1762 case Pin_StoreC:
1763 addHRegUse(u, HRmRead, i->Pin.StoreC.src);
1764 addHRegUse(u, HRmRead, i->Pin.StoreC.dst);
1765 return;
1766 case Pin_Set:
1767 addHRegUse(u, HRmWrite, i->Pin.Set.dst);
1768 return;
1769 case Pin_MfCR:
1770 addHRegUse(u, HRmWrite, i->Pin.MfCR.dst);
1771 return;
1772 case Pin_MFence:
1773 return;
1774
1775 case Pin_FpUnary:
1776 addHRegUse(u, HRmWrite, i->Pin.FpUnary.dst);
1777 addHRegUse(u, HRmRead, i->Pin.FpUnary.src);
1778 return;
1779 case Pin_FpBinary:
1780 addHRegUse(u, HRmWrite, i->Pin.FpBinary.dst);
1781 addHRegUse(u, HRmRead, i->Pin.FpBinary.srcL);
1782 addHRegUse(u, HRmRead, i->Pin.FpBinary.srcR);
1783 return;
1784 case Pin_FpMulAcc:
1785 addHRegUse(u, HRmWrite, i->Pin.FpMulAcc.dst);
1786 addHRegUse(u, HRmRead, i->Pin.FpMulAcc.srcML);
1787 addHRegUse(u, HRmRead, i->Pin.FpMulAcc.srcMR);
1788 addHRegUse(u, HRmRead, i->Pin.FpMulAcc.srcAcc);
1789 return;
1790 case Pin_FpLdSt:
1791 addHRegUse(u, (i->Pin.FpLdSt.isLoad ? HRmWrite : HRmRead),
1792 i->Pin.FpLdSt.reg);
1793 addRegUsage_PPCAMode(u, i->Pin.FpLdSt.addr);
1794 return;
1795 case Pin_FpSTFIW:
1796 addHRegUse(u, HRmRead, i->Pin.FpSTFIW.addr);
1797 addHRegUse(u, HRmRead, i->Pin.FpSTFIW.data);
1798 return;
1799 case Pin_FpRSP:
1800 addHRegUse(u, HRmWrite, i->Pin.FpRSP.dst);
1801 addHRegUse(u, HRmRead, i->Pin.FpRSP.src);
1802 return;
1803 case Pin_FpCftI:
1804 addHRegUse(u, HRmWrite, i->Pin.FpCftI.dst);
1805 addHRegUse(u, HRmRead, i->Pin.FpCftI.src);
1806 return;
1807 case Pin_FpCMov:
1808 addHRegUse(u, HRmModify, i->Pin.FpCMov.dst);
1809 addHRegUse(u, HRmRead, i->Pin.FpCMov.src);
1810 return;
1811 case Pin_FpLdFPSCR:
1812 addHRegUse(u, HRmRead, i->Pin.FpLdFPSCR.src);
1813 return;
1814 case Pin_FpCmp:
1815 addHRegUse(u, HRmWrite, i->Pin.FpCmp.dst);
1816 addHRegUse(u, HRmRead, i->Pin.FpCmp.srcL);
1817 addHRegUse(u, HRmRead, i->Pin.FpCmp.srcR);
1818 return;
1819
1820 case Pin_RdWrLR:
1821 addHRegUse(u, (i->Pin.RdWrLR.wrLR ? HRmRead : HRmWrite),
1822 i->Pin.RdWrLR.gpr);
1823 return;
1824
1825 case Pin_AvLdSt:
1826 addHRegUse(u, (i->Pin.AvLdSt.isLoad ? HRmWrite : HRmRead),
1827 i->Pin.AvLdSt.reg);
1828 if (i->Pin.AvLdSt.addr->tag == Pam_IR)
1829 addHRegUse(u, HRmWrite, hregPPC_GPR30(mode64));
1830 addRegUsage_PPCAMode(u, i->Pin.AvLdSt.addr);
1831 return;
1832 case Pin_AvUnary:
1833 addHRegUse(u, HRmWrite, i->Pin.AvUnary.dst);
1834 addHRegUse(u, HRmRead, i->Pin.AvUnary.src);
1835 return;
1836 case Pin_AvBinary:
1837 if (i->Pin.AvBinary.op == Pav_XOR
1838 && i->Pin.AvBinary.dst == i->Pin.AvBinary.srcL
1839 && i->Pin.AvBinary.dst == i->Pin.AvBinary.srcR) {
1840 /* reg-alloc needs to understand 'xor r,r,r' as a write of r */
1841 /* (as opposed to a rite of passage :-) */
1842 addHRegUse(u, HRmWrite, i->Pin.AvBinary.dst);
1843 } else {
1844 addHRegUse(u, HRmWrite, i->Pin.AvBinary.dst);
1845 addHRegUse(u, HRmRead, i->Pin.AvBinary.srcL);
1846 addHRegUse(u, HRmRead, i->Pin.AvBinary.srcR);
1847 }
1848 return;
1849 case Pin_AvBin8x16:
1850 addHRegUse(u, HRmWrite, i->Pin.AvBin8x16.dst);
1851 addHRegUse(u, HRmRead, i->Pin.AvBin8x16.srcL);
1852 addHRegUse(u, HRmRead, i->Pin.AvBin8x16.srcR);
1853 return;
1854 case Pin_AvBin16x8:
1855 addHRegUse(u, HRmWrite, i->Pin.AvBin16x8.dst);
1856 addHRegUse(u, HRmRead, i->Pin.AvBin16x8.srcL);
1857 addHRegUse(u, HRmRead, i->Pin.AvBin16x8.srcR);
1858 return;
1859 case Pin_AvBin32x4:
1860 addHRegUse(u, HRmWrite, i->Pin.AvBin32x4.dst);
1861 addHRegUse(u, HRmRead, i->Pin.AvBin32x4.srcL);
1862 addHRegUse(u, HRmRead, i->Pin.AvBin32x4.srcR);
1863 return;
1864 case Pin_AvBin32Fx4:
1865 addHRegUse(u, HRmWrite, i->Pin.AvBin32Fx4.dst);
1866 addHRegUse(u, HRmRead, i->Pin.AvBin32Fx4.srcL);
1867 addHRegUse(u, HRmRead, i->Pin.AvBin32Fx4.srcR);
1868 if (i->Pin.AvBin32Fx4.op == Pavfp_MULF)
1869 addHRegUse(u, HRmWrite, hregPPC_VR29());
1870 return;
1871 case Pin_AvUn32Fx4:
1872 addHRegUse(u, HRmWrite, i->Pin.AvUn32Fx4.dst);
1873 addHRegUse(u, HRmRead, i->Pin.AvUn32Fx4.src);
1874 return;
1875 case Pin_AvPerm:
1876 addHRegUse(u, HRmWrite, i->Pin.AvPerm.dst);
1877 addHRegUse(u, HRmRead, i->Pin.AvPerm.srcL);
1878 addHRegUse(u, HRmRead, i->Pin.AvPerm.srcR);
1879 addHRegUse(u, HRmRead, i->Pin.AvPerm.ctl);
1880 return;
1881 case Pin_AvSel:
1882 addHRegUse(u, HRmWrite, i->Pin.AvSel.dst);
1883 addHRegUse(u, HRmRead, i->Pin.AvSel.ctl);
1884 addHRegUse(u, HRmRead, i->Pin.AvSel.srcL);
1885 addHRegUse(u, HRmRead, i->Pin.AvSel.srcR);
1886 return;
1887 case Pin_AvShlDbl:
1888 addHRegUse(u, HRmWrite, i->Pin.AvShlDbl.dst);
1889 addHRegUse(u, HRmRead, i->Pin.AvShlDbl.srcL);
1890 addHRegUse(u, HRmRead, i->Pin.AvShlDbl.srcR);
1891 return;
1892 case Pin_AvSplat:
1893 addHRegUse(u, HRmWrite, i->Pin.AvSplat.dst);
1894 addRegUsage_PPCVI5s(u, i->Pin.AvSplat.src);
1895 return;
1896 case Pin_AvCMov:
1897 addHRegUse(u, HRmModify, i->Pin.AvCMov.dst);
1898 addHRegUse(u, HRmRead, i->Pin.AvCMov.src);
1899 return;
1900 case Pin_AvLdVSCR:
1901 addHRegUse(u, HRmRead, i->Pin.AvLdVSCR.src);
1902 return;
1903
1904 default:
1905 ppPPCInstr(i, mode64);
1906 vpanic("getRegUsage_PPCInstr");
1907 }
1908 }
1909
1910 /* local helper */
mapReg(HRegRemap * m,HReg * r)1911 static void mapReg( HRegRemap* m, HReg* r )
1912 {
1913 *r = lookupHRegRemap(m, *r);
1914 }
1915
mapRegs_PPCInstr(HRegRemap * m,PPCInstr * i,Bool mode64)1916 void mapRegs_PPCInstr ( HRegRemap* m, PPCInstr* i, Bool mode64 )
1917 {
1918 switch (i->tag) {
1919 case Pin_LI:
1920 mapReg(m, &i->Pin.LI.dst);
1921 return;
1922 case Pin_Alu:
1923 mapReg(m, &i->Pin.Alu.dst);
1924 mapReg(m, &i->Pin.Alu.srcL);
1925 mapRegs_PPCRH(m, i->Pin.Alu.srcR);
1926 return;
1927 case Pin_Shft:
1928 mapReg(m, &i->Pin.Shft.dst);
1929 mapReg(m, &i->Pin.Shft.srcL);
1930 mapRegs_PPCRH(m, i->Pin.Shft.srcR);
1931 return;
1932 case Pin_AddSubC:
1933 mapReg(m, &i->Pin.AddSubC.dst);
1934 mapReg(m, &i->Pin.AddSubC.srcL);
1935 mapReg(m, &i->Pin.AddSubC.srcR);
1936 return;
1937 case Pin_Cmp:
1938 mapReg(m, &i->Pin.Cmp.srcL);
1939 mapRegs_PPCRH(m, i->Pin.Cmp.srcR);
1940 return;
1941 case Pin_Unary:
1942 mapReg(m, &i->Pin.Unary.dst);
1943 mapReg(m, &i->Pin.Unary.src);
1944 return;
1945 case Pin_MulL:
1946 mapReg(m, &i->Pin.MulL.dst);
1947 mapReg(m, &i->Pin.MulL.srcL);
1948 mapReg(m, &i->Pin.MulL.srcR);
1949 return;
1950 case Pin_Div:
1951 mapReg(m, &i->Pin.Div.dst);
1952 mapReg(m, &i->Pin.Div.srcL);
1953 mapReg(m, &i->Pin.Div.srcR);
1954 return;
1955 case Pin_Call:
1956 return;
1957 case Pin_Goto:
1958 mapRegs_PPCRI(m, i->Pin.Goto.dst);
1959 return;
1960 case Pin_CMov:
1961 mapRegs_PPCRI(m, i->Pin.CMov.src);
1962 mapReg(m, &i->Pin.CMov.dst);
1963 return;
1964 case Pin_Load:
1965 mapRegs_PPCAMode(m, i->Pin.Load.src);
1966 mapReg(m, &i->Pin.Load.dst);
1967 return;
1968 case Pin_LoadL:
1969 mapReg(m, &i->Pin.LoadL.src);
1970 mapReg(m, &i->Pin.LoadL.dst);
1971 return;
1972 case Pin_Store:
1973 mapReg(m, &i->Pin.Store.src);
1974 mapRegs_PPCAMode(m, i->Pin.Store.dst);
1975 return;
1976 case Pin_StoreC:
1977 mapReg(m, &i->Pin.StoreC.src);
1978 mapReg(m, &i->Pin.StoreC.dst);
1979 return;
1980 case Pin_Set:
1981 mapReg(m, &i->Pin.Set.dst);
1982 return;
1983 case Pin_MfCR:
1984 mapReg(m, &i->Pin.MfCR.dst);
1985 return;
1986 case Pin_MFence:
1987 return;
1988 case Pin_FpUnary:
1989 mapReg(m, &i->Pin.FpUnary.dst);
1990 mapReg(m, &i->Pin.FpUnary.src);
1991 return;
1992 case Pin_FpBinary:
1993 mapReg(m, &i->Pin.FpBinary.dst);
1994 mapReg(m, &i->Pin.FpBinary.srcL);
1995 mapReg(m, &i->Pin.FpBinary.srcR);
1996 return;
1997 case Pin_FpMulAcc:
1998 mapReg(m, &i->Pin.FpMulAcc.dst);
1999 mapReg(m, &i->Pin.FpMulAcc.srcML);
2000 mapReg(m, &i->Pin.FpMulAcc.srcMR);
2001 mapReg(m, &i->Pin.FpMulAcc.srcAcc);
2002 return;
2003 case Pin_FpLdSt:
2004 mapReg(m, &i->Pin.FpLdSt.reg);
2005 mapRegs_PPCAMode(m, i->Pin.FpLdSt.addr);
2006 return;
2007 case Pin_FpSTFIW:
2008 mapReg(m, &i->Pin.FpSTFIW.addr);
2009 mapReg(m, &i->Pin.FpSTFIW.data);
2010 return;
2011 case Pin_FpRSP:
2012 mapReg(m, &i->Pin.FpRSP.dst);
2013 mapReg(m, &i->Pin.FpRSP.src);
2014 return;
2015 case Pin_FpCftI:
2016 mapReg(m, &i->Pin.FpCftI.dst);
2017 mapReg(m, &i->Pin.FpCftI.src);
2018 return;
2019 case Pin_FpCMov:
2020 mapReg(m, &i->Pin.FpCMov.dst);
2021 mapReg(m, &i->Pin.FpCMov.src);
2022 return;
2023 case Pin_FpLdFPSCR:
2024 mapReg(m, &i->Pin.FpLdFPSCR.src);
2025 return;
2026 case Pin_FpCmp:
2027 mapReg(m, &i->Pin.FpCmp.dst);
2028 mapReg(m, &i->Pin.FpCmp.srcL);
2029 mapReg(m, &i->Pin.FpCmp.srcR);
2030 return;
2031 case Pin_RdWrLR:
2032 mapReg(m, &i->Pin.RdWrLR.gpr);
2033 return;
2034 case Pin_AvLdSt:
2035 mapReg(m, &i->Pin.AvLdSt.reg);
2036 mapRegs_PPCAMode(m, i->Pin.AvLdSt.addr);
2037 return;
2038 case Pin_AvUnary:
2039 mapReg(m, &i->Pin.AvUnary.dst);
2040 mapReg(m, &i->Pin.AvUnary.src);
2041 return;
2042 case Pin_AvBinary:
2043 mapReg(m, &i->Pin.AvBinary.dst);
2044 mapReg(m, &i->Pin.AvBinary.srcL);
2045 mapReg(m, &i->Pin.AvBinary.srcR);
2046 return;
2047 case Pin_AvBin8x16:
2048 mapReg(m, &i->Pin.AvBin8x16.dst);
2049 mapReg(m, &i->Pin.AvBin8x16.srcL);
2050 mapReg(m, &i->Pin.AvBin8x16.srcR);
2051 return;
2052 case Pin_AvBin16x8:
2053 mapReg(m, &i->Pin.AvBin16x8.dst);
2054 mapReg(m, &i->Pin.AvBin16x8.srcL);
2055 mapReg(m, &i->Pin.AvBin16x8.srcR);
2056 return;
2057 case Pin_AvBin32x4:
2058 mapReg(m, &i->Pin.AvBin32x4.dst);
2059 mapReg(m, &i->Pin.AvBin32x4.srcL);
2060 mapReg(m, &i->Pin.AvBin32x4.srcR);
2061 return;
2062 case Pin_AvBin32Fx4:
2063 mapReg(m, &i->Pin.AvBin32Fx4.dst);
2064 mapReg(m, &i->Pin.AvBin32Fx4.srcL);
2065 mapReg(m, &i->Pin.AvBin32Fx4.srcR);
2066 return;
2067 case Pin_AvUn32Fx4:
2068 mapReg(m, &i->Pin.AvUn32Fx4.dst);
2069 mapReg(m, &i->Pin.AvUn32Fx4.src);
2070 return;
2071 case Pin_AvPerm:
2072 mapReg(m, &i->Pin.AvPerm.dst);
2073 mapReg(m, &i->Pin.AvPerm.srcL);
2074 mapReg(m, &i->Pin.AvPerm.srcR);
2075 mapReg(m, &i->Pin.AvPerm.ctl);
2076 return;
2077 case Pin_AvSel:
2078 mapReg(m, &i->Pin.AvSel.dst);
2079 mapReg(m, &i->Pin.AvSel.srcL);
2080 mapReg(m, &i->Pin.AvSel.srcR);
2081 mapReg(m, &i->Pin.AvSel.ctl);
2082 return;
2083 case Pin_AvShlDbl:
2084 mapReg(m, &i->Pin.AvShlDbl.dst);
2085 mapReg(m, &i->Pin.AvShlDbl.srcL);
2086 mapReg(m, &i->Pin.AvShlDbl.srcR);
2087 return;
2088 case Pin_AvSplat:
2089 mapReg(m, &i->Pin.AvSplat.dst);
2090 mapRegs_PPCVI5s(m, i->Pin.AvSplat.src);
2091 return;
2092 case Pin_AvCMov:
2093 mapReg(m, &i->Pin.AvCMov.dst);
2094 mapReg(m, &i->Pin.AvCMov.src);
2095 return;
2096 case Pin_AvLdVSCR:
2097 mapReg(m, &i->Pin.AvLdVSCR.src);
2098 return;
2099
2100 default:
2101 ppPPCInstr(i, mode64);
2102 vpanic("mapRegs_PPCInstr");
2103 }
2104 }
2105
2106 /* Figure out if i represents a reg-reg move, and if so assign the
2107 source and destination to *src and *dst. If in doubt say No. Used
2108 by the register allocator to do move coalescing.
2109 */
isMove_PPCInstr(PPCInstr * i,HReg * src,HReg * dst)2110 Bool isMove_PPCInstr ( PPCInstr* i, HReg* src, HReg* dst )
2111 {
2112 /* Moves between integer regs */
2113 if (i->tag == Pin_Alu) {
2114 // or Rd,Rs,Rs == mr Rd,Rs
2115 if (i->Pin.Alu.op != Palu_OR)
2116 return False;
2117 if (i->Pin.Alu.srcR->tag != Prh_Reg)
2118 return False;
2119 if (i->Pin.Alu.srcR->Prh.Reg.reg != i->Pin.Alu.srcL)
2120 return False;
2121 *src = i->Pin.Alu.srcL;
2122 *dst = i->Pin.Alu.dst;
2123 return True;
2124 }
2125 /* Moves between FP regs */
2126 if (i->tag == Pin_FpUnary) {
2127 if (i->Pin.FpUnary.op != Pfp_MOV)
2128 return False;
2129 *src = i->Pin.FpUnary.src;
2130 *dst = i->Pin.FpUnary.dst;
2131 return True;
2132 }
2133 return False;
2134 }
2135
2136
2137 /* Generate ppc spill/reload instructions under the direction of the
2138 register allocator. Note it's critical these don't write the
2139 condition codes. */
2140
genSpill_PPC(HInstr ** i1,HInstr ** i2,HReg rreg,Int offsetB,Bool mode64)2141 void genSpill_PPC ( /*OUT*/HInstr** i1, /*OUT*/HInstr** i2,
2142 HReg rreg, Int offsetB, Bool mode64 )
2143 {
2144 PPCAMode* am;
2145 vassert(!hregIsVirtual(rreg));
2146 *i1 = *i2 = NULL;
2147 am = PPCAMode_IR( offsetB, GuestStatePtr(mode64) );
2148 switch (hregClass(rreg)) {
2149 case HRcInt64:
2150 vassert(mode64);
2151 *i1 = PPCInstr_Store( 8, am, rreg, mode64 );
2152 return;
2153 case HRcInt32:
2154 vassert(!mode64);
2155 *i1 = PPCInstr_Store( 4, am, rreg, mode64 );
2156 return;
2157 case HRcFlt64:
2158 *i1 = PPCInstr_FpLdSt ( False/*store*/, 8, rreg, am );
2159 return;
2160 case HRcVec128:
2161 // XXX: GPR30 used as spill register to kludge AltiVec
2162 // AMode_IR
2163 *i1 = PPCInstr_AvLdSt ( False/*store*/, 16, rreg, am );
2164 return;
2165 default:
2166 ppHRegClass(hregClass(rreg));
2167 vpanic("genSpill_PPC: unimplemented regclass");
2168 }
2169 }
2170
genReload_PPC(HInstr ** i1,HInstr ** i2,HReg rreg,Int offsetB,Bool mode64)2171 void genReload_PPC ( /*OUT*/HInstr** i1, /*OUT*/HInstr** i2,
2172 HReg rreg, Int offsetB, Bool mode64 )
2173 {
2174 PPCAMode* am;
2175 vassert(!hregIsVirtual(rreg));
2176 *i1 = *i2 = NULL;
2177 am = PPCAMode_IR( offsetB, GuestStatePtr(mode64) );
2178 switch (hregClass(rreg)) {
2179 case HRcInt64:
2180 vassert(mode64);
2181 *i1 = PPCInstr_Load( 8, rreg, am, mode64 );
2182 return;
2183 case HRcInt32:
2184 vassert(!mode64);
2185 *i1 = PPCInstr_Load( 4, rreg, am, mode64 );
2186 return;
2187 case HRcFlt64:
2188 *i1 = PPCInstr_FpLdSt ( True/*load*/, 8, rreg, am );
2189 return;
2190 case HRcVec128:
2191 // XXX: GPR30 used as spill register to kludge AltiVec AMode_IR
2192 *i1 = PPCInstr_AvLdSt ( True/*load*/, 16, rreg, am );
2193 return;
2194 default:
2195 ppHRegClass(hregClass(rreg));
2196 vpanic("genReload_PPC: unimplemented regclass");
2197 }
2198 }
2199
2200
2201 /* --------- The ppc assembler (bleh.) --------- */
2202
iregNo(HReg r,Bool mode64)2203 static UInt iregNo ( HReg r, Bool mode64 )
2204 {
2205 UInt n;
2206 vassert(hregClass(r) == mode64 ? HRcInt64 : HRcInt32);
2207 vassert(!hregIsVirtual(r));
2208 n = hregNumber(r);
2209 vassert(n <= 32);
2210 return n;
2211 }
2212
fregNo(HReg fr)2213 static UInt fregNo ( HReg fr )
2214 {
2215 UInt n;
2216 vassert(hregClass(fr) == HRcFlt64);
2217 vassert(!hregIsVirtual(fr));
2218 n = hregNumber(fr);
2219 vassert(n <= 32);
2220 return n;
2221 }
2222
vregNo(HReg v)2223 static UInt vregNo ( HReg v )
2224 {
2225 UInt n;
2226 vassert(hregClass(v) == HRcVec128);
2227 vassert(!hregIsVirtual(v));
2228 n = hregNumber(v);
2229 vassert(n <= 32);
2230 return n;
2231 }
2232
2233 /* Emit 32bit instruction big-endianly */
emit32(UChar * p,UInt w32)2234 static UChar* emit32 ( UChar* p, UInt w32 )
2235 {
2236 *p++ = toUChar((w32 >> 24) & 0x000000FF);
2237 *p++ = toUChar((w32 >> 16) & 0x000000FF);
2238 *p++ = toUChar((w32 >> 8) & 0x000000FF);
2239 *p++ = toUChar((w32) & 0x000000FF);
2240 return p;
2241 }
2242
2243 /* The following mkForm[...] functions refer to ppc instruction forms
2244 as per PPC32 p576
2245 */
2246
mkFormD(UChar * p,UInt opc1,UInt r1,UInt r2,UInt imm)2247 static UChar* mkFormD ( UChar* p, UInt opc1,
2248 UInt r1, UInt r2, UInt imm )
2249 {
2250 UInt theInstr;
2251 vassert(opc1 < 0x40);
2252 vassert(r1 < 0x20);
2253 vassert(r2 < 0x20);
2254 imm = imm & 0xFFFF;
2255 theInstr = ((opc1<<26) | (r1<<21) | (r2<<16) | (imm));
2256 return emit32(p, theInstr);
2257 }
2258
mkFormMD(UChar * p,UInt opc1,UInt r1,UInt r2,UInt imm1,UInt imm2,UInt opc2)2259 static UChar* mkFormMD ( UChar* p, UInt opc1, UInt r1, UInt r2,
2260 UInt imm1, UInt imm2, UInt opc2 )
2261 {
2262 UInt theInstr;
2263 vassert(opc1 < 0x40);
2264 vassert(r1 < 0x20);
2265 vassert(r2 < 0x20);
2266 vassert(imm1 < 0x40);
2267 vassert(imm2 < 0x40);
2268 vassert(opc2 < 0x08);
2269 imm2 = ((imm2 & 0x1F) << 1) | (imm2 >> 5);
2270 theInstr = ((opc1<<26) | (r1<<21) | (r2<<16) |
2271 ((imm1 & 0x1F)<<11) | (imm2<<5) |
2272 (opc2<<2) | ((imm1 >> 5)<<1));
2273 return emit32(p, theInstr);
2274 }
2275
mkFormX(UChar * p,UInt opc1,UInt r1,UInt r2,UInt r3,UInt opc2,UInt b0)2276 static UChar* mkFormX ( UChar* p, UInt opc1, UInt r1, UInt r2,
2277 UInt r3, UInt opc2, UInt b0 )
2278 {
2279 UInt theInstr;
2280 vassert(opc1 < 0x40);
2281 vassert(r1 < 0x20);
2282 vassert(r2 < 0x20);
2283 vassert(r3 < 0x20);
2284 vassert(opc2 < 0x400);
2285 vassert(b0 < 0x2);
2286 theInstr = ((opc1<<26) | (r1<<21) | (r2<<16) |
2287 (r3<<11) | (opc2<<1) | (b0));
2288 return emit32(p, theInstr);
2289 }
2290
mkFormXO(UChar * p,UInt opc1,UInt r1,UInt r2,UInt r3,UInt b10,UInt opc2,UInt b0)2291 static UChar* mkFormXO ( UChar* p, UInt opc1, UInt r1, UInt r2,
2292 UInt r3, UInt b10, UInt opc2, UInt b0 )
2293 {
2294 UInt theInstr;
2295 vassert(opc1 < 0x40);
2296 vassert(r1 < 0x20);
2297 vassert(r2 < 0x20);
2298 vassert(r3 < 0x20);
2299 vassert(b10 < 0x2);
2300 vassert(opc2 < 0x200);
2301 vassert(b0 < 0x2);
2302 theInstr = ((opc1<<26) | (r1<<21) | (r2<<16) |
2303 (r3<<11) | (b10 << 10) | (opc2<<1) | (b0));
2304 return emit32(p, theInstr);
2305 }
2306
mkFormXL(UChar * p,UInt opc1,UInt f1,UInt f2,UInt f3,UInt opc2,UInt b0)2307 static UChar* mkFormXL ( UChar* p, UInt opc1, UInt f1, UInt f2,
2308 UInt f3, UInt opc2, UInt b0 )
2309 {
2310 UInt theInstr;
2311 vassert(opc1 < 0x40);
2312 vassert(f1 < 0x20);
2313 vassert(f2 < 0x20);
2314 vassert(f3 < 0x20);
2315 vassert(opc2 < 0x400);
2316 vassert(b0 < 0x2);
2317 theInstr = ((opc1<<26) | (f1<<21) | (f2<<16) |
2318 (f3<<11) | (opc2<<1) | (b0));
2319 return emit32(p, theInstr);
2320 }
2321
2322 // Note: for split field ops, give mnemonic arg
mkFormXFX(UChar * p,UInt r1,UInt f2,UInt opc2)2323 static UChar* mkFormXFX ( UChar* p, UInt r1, UInt f2, UInt opc2 )
2324 {
2325 UInt theInstr;
2326 vassert(r1 < 0x20);
2327 vassert(f2 < 0x20);
2328 vassert(opc2 < 0x400);
2329 switch (opc2) {
2330 case 144: // mtcrf
2331 vassert(f2 < 0x100);
2332 f2 = f2 << 1;
2333 break;
2334 case 339: // mfspr
2335 case 371: // mftb
2336 case 467: // mtspr
2337 vassert(f2 < 0x400);
2338 // re-arrange split field
2339 f2 = ((f2>>5) & 0x1F) | ((f2 & 0x1F)<<5);
2340 break;
2341 default: vpanic("mkFormXFX(ppch)");
2342 }
2343 theInstr = ((31<<26) | (r1<<21) | (f2<<11) | (opc2<<1));
2344 return emit32(p, theInstr);
2345 }
2346
2347 // Only used by mtfsf
mkFormXFL(UChar * p,UInt FM,UInt freg)2348 static UChar* mkFormXFL ( UChar* p, UInt FM, UInt freg )
2349 {
2350 UInt theInstr;
2351 vassert(FM < 0x100);
2352 vassert(freg < 0x20);
2353 theInstr = ((63<<26) | (FM<<17) | (freg<<11) | (711<<1));
2354 return emit32(p, theInstr);
2355 }
2356
mkFormXS(UChar * p,UInt opc1,UInt r1,UInt r2,UInt imm,UInt opc2,UInt b0)2357 static UChar* mkFormXS ( UChar* p, UInt opc1, UInt r1, UInt r2,
2358 UInt imm, UInt opc2, UInt b0 )
2359 {
2360 UInt theInstr;
2361 vassert(opc1 < 0x40);
2362 vassert(r1 < 0x20);
2363 vassert(r2 < 0x20);
2364 vassert(imm < 0x40);
2365 vassert(opc2 < 0x400);
2366 vassert(b0 < 0x2);
2367 theInstr = ((opc1<<26) | (r1<<21) | (r2<<16) |
2368 ((imm & 0x1F)<<11) | (opc2<<2) | ((imm>>5)<<1) | (b0));
2369 return emit32(p, theInstr);
2370 }
2371
2372
2373 #if 0
2374 // 'b'
2375 static UChar* mkFormI ( UChar* p, UInt LI, UInt AA, UInt LK )
2376 {
2377 UInt theInstr;
2378 vassert(LI < 0x1000000);
2379 vassert(AA < 0x2);
2380 vassert(LK < 0x2);
2381 theInstr = ((18<<26) | (LI<<2) | (AA<<1) | (LK));
2382 return emit32(p, theInstr);
2383 }
2384 #endif
2385
2386 // 'bc'
mkFormB(UChar * p,UInt BO,UInt BI,UInt BD,UInt AA,UInt LK)2387 static UChar* mkFormB ( UChar* p, UInt BO, UInt BI,
2388 UInt BD, UInt AA, UInt LK )
2389 {
2390 UInt theInstr;
2391 vassert(BO < 0x20);
2392 vassert(BI < 0x20);
2393 vassert(BD < 0x4000);
2394 vassert(AA < 0x2);
2395 vassert(LK < 0x2);
2396 theInstr = ((16<<26) | (BO<<21) | (BI<<16) |
2397 (BD<<2) | (AA<<1) | (LK));
2398 return emit32(p, theInstr);
2399 }
2400
2401 // rotates
mkFormM(UChar * p,UInt opc1,UInt r1,UInt r2,UInt f3,UInt MB,UInt ME,UInt Rc)2402 static UChar* mkFormM ( UChar* p, UInt opc1, UInt r1, UInt r2,
2403 UInt f3, UInt MB, UInt ME, UInt Rc )
2404 {
2405 UInt theInstr;
2406 vassert(opc1 < 0x40);
2407 vassert(r1 < 0x20);
2408 vassert(r2 < 0x20);
2409 vassert(f3 < 0x20);
2410 vassert(MB < 0x20);
2411 vassert(ME < 0x20);
2412 vassert(Rc < 0x2);
2413 theInstr = ((opc1<<26) | (r1<<21) | (r2<<16) |
2414 (f3<<11) | (MB<<6) | (ME<<1) | (Rc));
2415 return emit32(p, theInstr);
2416 }
2417
mkFormA(UChar * p,UInt opc1,UInt r1,UInt r2,UInt r3,UInt r4,UInt opc2,UInt b0)2418 static UChar* mkFormA ( UChar* p, UInt opc1, UInt r1, UInt r2,
2419 UInt r3, UInt r4, UInt opc2, UInt b0 )
2420 {
2421 UInt theInstr;
2422 vassert(opc1 < 0x40);
2423 vassert(r1 < 0x20);
2424 vassert(r2 < 0x20);
2425 vassert(r3 < 0x20);
2426 vassert(r4 < 0x20);
2427 vassert(opc2 < 0x20);
2428 vassert(b0 < 0x2 );
2429 theInstr = ((opc1<<26) | (r1<<21) | (r2<<16) | (r3<<11) |
2430 (r4<<6) | (opc2<<1) | (b0));
2431 return emit32(p, theInstr);
2432 }
2433
doAMode_IR(UChar * p,UInt opc1,UInt rSD,PPCAMode * am,Bool mode64)2434 static UChar* doAMode_IR ( UChar* p, UInt opc1, UInt rSD,
2435 PPCAMode* am, Bool mode64 )
2436 {
2437 UInt rA, idx;
2438 vassert(am->tag == Pam_IR);
2439 vassert(am->Pam.IR.index < 0x10000);
2440
2441 rA = iregNo(am->Pam.IR.base, mode64);
2442 idx = am->Pam.IR.index;
2443
2444 if (opc1 == 58 || opc1 == 62) { // ld/std: mode64 only
2445 vassert(mode64);
2446 /* stay sane with DS form: lowest 2 bits must be 00. This
2447 should be guaranteed to us by iselWordExpr_AMode. */
2448 vassert(0 == (idx & 3));
2449 }
2450 p = mkFormD(p, opc1, rSD, rA, idx);
2451 return p;
2452 }
2453
doAMode_RR(UChar * p,UInt opc1,UInt opc2,UInt rSD,PPCAMode * am,Bool mode64)2454 static UChar* doAMode_RR ( UChar* p, UInt opc1, UInt opc2,
2455 UInt rSD, PPCAMode* am, Bool mode64 )
2456 {
2457 UInt rA, rB;
2458 vassert(am->tag == Pam_RR);
2459
2460 rA = iregNo(am->Pam.RR.base, mode64);
2461 rB = iregNo(am->Pam.RR.index, mode64);
2462
2463 p = mkFormX(p, opc1, rSD, rA, rB, opc2, 0);
2464 return p;
2465 }
2466
2467
2468 /* Load imm to r_dst */
mkLoadImm(UChar * p,UInt r_dst,ULong imm,Bool mode64)2469 static UChar* mkLoadImm ( UChar* p, UInt r_dst, ULong imm, Bool mode64 )
2470 {
2471 vassert(r_dst < 0x20);
2472
2473 if (!mode64) {
2474 /* In 32-bit mode, make sure the top 32 bits of imm are a sign
2475 extension of the bottom 32 bits, so that the range tests
2476 below work correctly. */
2477 UInt u32 = (UInt)imm;
2478 Int s32 = (Int)u32;
2479 Long s64 = (Long)s32;
2480 imm = (ULong)s64;
2481 }
2482
2483 if (imm >= 0xFFFFFFFFFFFF8000ULL || imm < 0x8000) {
2484 // sign-extendable from 16 bits
2485
2486 // addi r_dst,0,imm => li r_dst,imm
2487 p = mkFormD(p, 14, r_dst, 0, imm & 0xFFFF);
2488 } else {
2489 if (imm >= 0xFFFFFFFF80000000ULL || imm < 0x80000000ULL) {
2490 // sign-extendable from 32 bits
2491
2492 // addis r_dst,r0,(imm>>16) => lis r_dst, (imm>>16)
2493 p = mkFormD(p, 15, r_dst, 0, (imm>>16) & 0xFFFF);
2494 // ori r_dst, r_dst, (imm & 0xFFFF)
2495 p = mkFormD(p, 24, r_dst, r_dst, imm & 0xFFFF);
2496 } else {
2497 // full 64bit immediate load: 5 (five!) insns.
2498 vassert(mode64);
2499
2500 // load high word
2501
2502 // lis r_dst, (imm>>48) & 0xFFFF
2503 p = mkFormD(p, 15, r_dst, 0, (imm>>48) & 0xFFFF);
2504
2505 // ori r_dst, r_dst, (imm>>32) & 0xFFFF
2506 if ((imm>>32) & 0xFFFF)
2507 p = mkFormD(p, 24, r_dst, r_dst, (imm>>32) & 0xFFFF);
2508
2509 // shift r_dst low word to high word => rldicr
2510 p = mkFormMD(p, 30, r_dst, r_dst, 32, 31, 1);
2511
2512 // load low word
2513
2514 // oris r_dst, r_dst, (imm>>16) & 0xFFFF
2515 if ((imm>>16) & 0xFFFF)
2516 p = mkFormD(p, 25, r_dst, r_dst, (imm>>16) & 0xFFFF);
2517
2518 // ori r_dst, r_dst, (imm) & 0xFFFF
2519 if (imm & 0xFFFF)
2520 p = mkFormD(p, 24, r_dst, r_dst, imm & 0xFFFF);
2521 }
2522 }
2523 return p;
2524 }
2525
2526 /* Move r_dst to r_src */
mkMoveReg(UChar * p,UInt r_dst,UInt r_src)2527 static UChar* mkMoveReg ( UChar* p, UInt r_dst, UInt r_src )
2528 {
2529 vassert(r_dst < 0x20);
2530 vassert(r_src < 0x20);
2531
2532 if (r_dst != r_src) {
2533 /* or r_dst, r_src, r_src */
2534 p = mkFormX(p, 31, r_src, r_dst, r_src, 444, 0 );
2535 }
2536 return p;
2537 }
2538
mkFormVX(UChar * p,UInt opc1,UInt r1,UInt r2,UInt r3,UInt opc2)2539 static UChar* mkFormVX ( UChar* p, UInt opc1, UInt r1, UInt r2,
2540 UInt r3, UInt opc2 )
2541 {
2542 UInt theInstr;
2543 vassert(opc1 < 0x40);
2544 vassert(r1 < 0x20);
2545 vassert(r2 < 0x20);
2546 vassert(r3 < 0x20);
2547 vassert(opc2 < 0x800);
2548 theInstr = ((opc1<<26) | (r1<<21) | (r2<<16) | (r3<<11) | opc2);
2549 return emit32(p, theInstr);
2550 }
2551
mkFormVXR(UChar * p,UInt opc1,UInt r1,UInt r2,UInt r3,UInt Rc,UInt opc2)2552 static UChar* mkFormVXR ( UChar* p, UInt opc1, UInt r1, UInt r2,
2553 UInt r3, UInt Rc, UInt opc2 )
2554 {
2555 UInt theInstr;
2556 vassert(opc1 < 0x40);
2557 vassert(r1 < 0x20);
2558 vassert(r2 < 0x20);
2559 vassert(r3 < 0x20);
2560 vassert(Rc < 0x2);
2561 vassert(opc2 < 0x400);
2562 theInstr = ((opc1<<26) | (r1<<21) | (r2<<16) |
2563 (r3<<11) | (Rc<<10) | opc2);
2564 return emit32(p, theInstr);
2565 }
2566
mkFormVA(UChar * p,UInt opc1,UInt r1,UInt r2,UInt r3,UInt r4,UInt opc2)2567 static UChar* mkFormVA ( UChar* p, UInt opc1, UInt r1, UInt r2,
2568 UInt r3, UInt r4, UInt opc2 )
2569 {
2570 UInt theInstr;
2571 vassert(opc1 < 0x40);
2572 vassert(r1 < 0x20);
2573 vassert(r2 < 0x20);
2574 vassert(r3 < 0x20);
2575 vassert(r4 < 0x20);
2576 vassert(opc2 < 0x40);
2577 theInstr = ((opc1<<26) | (r1<<21) | (r2<<16) |
2578 (r3<<11) | (r4<<6) | opc2);
2579 return emit32(p, theInstr);
2580 }
2581
2582
2583
2584 /* Emit an instruction into buf and return the number of bytes used.
2585 Note that buf is not the insn's final place, and therefore it is
2586 imperative to emit position-independent code.
2587
2588 Note, dispatch should always be NULL since ppc32/64 backends
2589 use a call-return scheme to get from the dispatcher to generated
2590 code and back.
2591 */
emit_PPCInstr(UChar * buf,Int nbuf,PPCInstr * i,Bool mode64,void * dispatch)2592 Int emit_PPCInstr ( UChar* buf, Int nbuf, PPCInstr* i,
2593 Bool mode64, void* dispatch )
2594 {
2595 UChar* p = &buf[0];
2596 UChar* ptmp = p;
2597 vassert(nbuf >= 32);
2598
2599 if (0) {
2600 vex_printf("asm ");ppPPCInstr(i, mode64); vex_printf("\n");
2601 }
2602
2603 switch (i->tag) {
2604
2605 case Pin_LI:
2606 p = mkLoadImm(p, iregNo(i->Pin.LI.dst, mode64),
2607 i->Pin.LI.imm64, mode64);
2608 goto done;
2609
2610 case Pin_Alu: {
2611 PPCRH* srcR = i->Pin.Alu.srcR;
2612 Bool immR = toBool(srcR->tag == Prh_Imm);
2613 UInt r_dst = iregNo(i->Pin.Alu.dst, mode64);
2614 UInt r_srcL = iregNo(i->Pin.Alu.srcL, mode64);
2615 UInt r_srcR = immR ? (-1)/*bogus*/ :
2616 iregNo(srcR->Prh.Reg.reg, mode64);
2617
2618 switch (i->Pin.Alu.op) {
2619 case Palu_ADD:
2620 if (immR) {
2621 /* addi (PPC32 p350) */
2622 vassert(srcR->Prh.Imm.syned);
2623 vassert(srcR->Prh.Imm.imm16 != 0x8000);
2624 p = mkFormD(p, 14, r_dst, r_srcL, srcR->Prh.Imm.imm16);
2625 } else {
2626 /* add (PPC32 p347) */
2627 p = mkFormXO(p, 31, r_dst, r_srcL, r_srcR, 0, 266, 0);
2628 }
2629 break;
2630
2631 case Palu_SUB:
2632 if (immR) {
2633 /* addi (PPC32 p350), but with negated imm */
2634 vassert(srcR->Prh.Imm.syned);
2635 vassert(srcR->Prh.Imm.imm16 != 0x8000);
2636 p = mkFormD(p, 14, r_dst, r_srcL, (- srcR->Prh.Imm.imm16));
2637 } else {
2638 /* subf (PPC32 p537), with args the "wrong" way round */
2639 p = mkFormXO(p, 31, r_dst, r_srcR, r_srcL, 0, 40, 0);
2640 }
2641 break;
2642
2643 case Palu_AND:
2644 if (immR) {
2645 /* andi. (PPC32 p358) */
2646 vassert(!srcR->Prh.Imm.syned);
2647 p = mkFormD(p, 28, r_srcL, r_dst, srcR->Prh.Imm.imm16);
2648 } else {
2649 /* and (PPC32 p356) */
2650 p = mkFormX(p, 31, r_srcL, r_dst, r_srcR, 28, 0);
2651 }
2652 break;
2653
2654 case Palu_OR:
2655 if (immR) {
2656 /* ori (PPC32 p497) */
2657 vassert(!srcR->Prh.Imm.syned);
2658 p = mkFormD(p, 24, r_srcL, r_dst, srcR->Prh.Imm.imm16);
2659 } else {
2660 /* or (PPC32 p495) */
2661 p = mkFormX(p, 31, r_srcL, r_dst, r_srcR, 444, 0);
2662 }
2663 break;
2664
2665 case Palu_XOR:
2666 if (immR) {
2667 /* xori (PPC32 p550) */
2668 vassert(!srcR->Prh.Imm.syned);
2669 p = mkFormD(p, 26, r_srcL, r_dst, srcR->Prh.Imm.imm16);
2670 } else {
2671 /* xor (PPC32 p549) */
2672 p = mkFormX(p, 31, r_srcL, r_dst, r_srcR, 316, 0);
2673 }
2674 break;
2675
2676 default:
2677 goto bad;
2678 }
2679 goto done;
2680 }
2681
2682 case Pin_Shft: {
2683 PPCRH* srcR = i->Pin.Shft.srcR;
2684 Bool sz32 = i->Pin.Shft.sz32;
2685 Bool immR = toBool(srcR->tag == Prh_Imm);
2686 UInt r_dst = iregNo(i->Pin.Shft.dst, mode64);
2687 UInt r_srcL = iregNo(i->Pin.Shft.srcL, mode64);
2688 UInt r_srcR = immR ? (-1)/*bogus*/ :
2689 iregNo(srcR->Prh.Reg.reg, mode64);
2690 if (!mode64)
2691 vassert(sz32);
2692
2693 switch (i->Pin.Shft.op) {
2694 case Pshft_SHL:
2695 if (sz32) {
2696 if (immR) {
2697 /* rd = rs << n, 1 <= n <= 31
2698 is
2699 rlwinm rd,rs,n,0,31-n (PPC32 p501)
2700 */
2701 UInt n = srcR->Prh.Imm.imm16;
2702 vassert(!srcR->Prh.Imm.syned);
2703 vassert(n > 0 && n < 32);
2704 p = mkFormM(p, 21, r_srcL, r_dst, n, 0, 31-n, 0);
2705 } else {
2706 /* slw (PPC32 p505) */
2707 p = mkFormX(p, 31, r_srcL, r_dst, r_srcR, 24, 0);
2708 }
2709 } else {
2710 if (immR) {
2711 /* rd = rs << n, 1 <= n <= 63
2712 is
2713 rldicr rd,rs,n,63-n (PPC64 p559)
2714 */
2715 UInt n = srcR->Prh.Imm.imm16;
2716 vassert(!srcR->Prh.Imm.syned);
2717 vassert(n > 0 && n < 64);
2718 p = mkFormMD(p, 30, r_srcL, r_dst, n, 63-n, 1);
2719 } else {
2720 /* sld (PPC64 p568) */
2721 p = mkFormX(p, 31, r_srcL, r_dst, r_srcR, 27, 0);
2722 }
2723 }
2724 break;
2725
2726 case Pshft_SHR:
2727 if (sz32) {
2728 if (immR) {
2729 /* rd = rs >>u n, 1 <= n <= 31
2730 is
2731 rlwinm rd,rs,32-n,n,31 (PPC32 p501)
2732 */
2733 UInt n = srcR->Prh.Imm.imm16;
2734 vassert(!srcR->Prh.Imm.syned);
2735 vassert(n > 0 && n < 32);
2736 p = mkFormM(p, 21, r_srcL, r_dst, 32-n, n, 31, 0);
2737 } else {
2738 /* srw (PPC32 p508) */
2739 p = mkFormX(p, 31, r_srcL, r_dst, r_srcR, 536, 0);
2740 }
2741 } else {
2742 if (immR) {
2743 /* rd = rs >>u n, 1 <= n <= 63
2744 is
2745 rldicl rd,rs,64-n,n (PPC64 p558)
2746 */
2747 UInt n = srcR->Prh.Imm.imm16;
2748 vassert(!srcR->Prh.Imm.syned);
2749 vassert(n > 0 && n < 64);
2750 p = mkFormMD(p, 30, r_srcL, r_dst, 64-n, n, 0);
2751 } else {
2752 /* srd (PPC64 p574) */
2753 p = mkFormX(p, 31, r_srcL, r_dst, r_srcR, 539, 0);
2754 }
2755 }
2756 break;
2757
2758 case Pshft_SAR:
2759 if (sz32) {
2760 if (immR) {
2761 /* srawi (PPC32 p507) */
2762 UInt n = srcR->Prh.Imm.imm16;
2763 vassert(!srcR->Prh.Imm.syned);
2764 /* In 64-bit mode, we allow right shifts by zero bits
2765 as that is a handy way to sign extend the lower 32
2766 bits into the upper 32 bits. */
2767 if (mode64)
2768 vassert(n >= 0 && n < 32);
2769 else
2770 vassert(n > 0 && n < 32);
2771 p = mkFormX(p, 31, r_srcL, r_dst, n, 824, 0);
2772 } else {
2773 /* sraw (PPC32 p506) */
2774 p = mkFormX(p, 31, r_srcL, r_dst, r_srcR, 792, 0);
2775 }
2776 } else {
2777 if (immR) {
2778 /* sradi (PPC64 p571) */
2779 UInt n = srcR->Prh.Imm.imm16;
2780 vassert(!srcR->Prh.Imm.syned);
2781 vassert(n > 0 && n < 64);
2782 p = mkFormXS(p, 31, r_srcL, r_dst, n, 413, 0);
2783 } else {
2784 /* srad (PPC32 p570) */
2785 p = mkFormX(p, 31, r_srcL, r_dst, r_srcR, 794, 0);
2786 }
2787 }
2788 break;
2789
2790 default:
2791 goto bad;
2792 }
2793 goto done;
2794 }
2795
2796 case Pin_AddSubC: {
2797 Bool isAdd = i->Pin.AddSubC.isAdd;
2798 Bool setC = i->Pin.AddSubC.setC;
2799 UInt r_srcL = iregNo(i->Pin.AddSubC.srcL, mode64);
2800 UInt r_srcR = iregNo(i->Pin.AddSubC.srcR, mode64);
2801 UInt r_dst = iregNo(i->Pin.AddSubC.dst, mode64);
2802
2803 if (isAdd) {
2804 if (setC) /* addc (PPC32 p348) */
2805 p = mkFormXO(p, 31, r_dst, r_srcL, r_srcR, 0, 10, 0);
2806 else /* adde (PPC32 p349) */
2807 p = mkFormXO(p, 31, r_dst, r_srcL, r_srcR, 0, 138, 0);
2808 } else {
2809 /* subfX, with args the "wrong" way round */
2810 if (setC) /* subfc (PPC32 p538) */
2811 p = mkFormXO(p, 31, r_dst, r_srcR, r_srcL, 0, 8, 0);
2812 else /* subfe (PPC32 p539) */
2813 p = mkFormXO(p, 31, r_dst, r_srcR, r_srcL, 0, 136, 0);
2814 }
2815 goto done;
2816 }
2817
2818 case Pin_Cmp: {
2819 Bool syned = i->Pin.Cmp.syned;
2820 Bool sz32 = i->Pin.Cmp.sz32;
2821 UInt fld1 = i->Pin.Cmp.crfD << 2;
2822 UInt r_srcL = iregNo(i->Pin.Cmp.srcL, mode64);
2823 UInt r_srcR, imm_srcR;
2824 PPCRH* srcR = i->Pin.Cmp.srcR;
2825
2826 if (!mode64) // cmp double word invalid for mode32
2827 vassert(sz32);
2828 else if (!sz32) // mode64 && cmp64: set L=1
2829 fld1 |= 1;
2830
2831 switch (srcR->tag) {
2832 case Prh_Imm:
2833 vassert(syned == srcR->Prh.Imm.syned);
2834 imm_srcR = srcR->Prh.Imm.imm16;
2835 if (syned) { // cmpw/di (signed) (PPC32 p368)
2836 vassert(imm_srcR != 0x8000);
2837 p = mkFormD(p, 11, fld1, r_srcL, imm_srcR);
2838 } else { // cmplw/di (unsigned) (PPC32 p370)
2839 p = mkFormD(p, 10, fld1, r_srcL, imm_srcR);
2840 }
2841 break;
2842 case Prh_Reg:
2843 r_srcR = iregNo(srcR->Prh.Reg.reg, mode64);
2844 if (syned) // cmpwi (signed) (PPC32 p367)
2845 p = mkFormX(p, 31, fld1, r_srcL, r_srcR, 0, 0);
2846 else // cmplwi (unsigned) (PPC32 p379)
2847 p = mkFormX(p, 31, fld1, r_srcL, r_srcR, 32, 0);
2848 break;
2849 default:
2850 goto bad;
2851 }
2852 goto done;
2853 }
2854
2855 case Pin_Unary: {
2856 UInt r_dst = iregNo(i->Pin.Unary.dst, mode64);
2857 UInt r_src = iregNo(i->Pin.Unary.src, mode64);
2858
2859 switch (i->Pin.Unary.op) {
2860 case Pun_NOT: // nor r_dst,r_src,r_src
2861 p = mkFormX(p, 31, r_src, r_dst, r_src, 124, 0);
2862 break;
2863 case Pun_NEG: // neg r_dst,r_src
2864 p = mkFormXO(p, 31, r_dst, r_src, 0, 0, 104, 0);
2865 break;
2866 case Pun_CLZ32: // cntlzw r_dst, r_src
2867 p = mkFormX(p, 31, r_src, r_dst, 0, 26, 0);
2868 break;
2869 case Pun_CLZ64: // cntlzd r_dst, r_src
2870 vassert(mode64);
2871 p = mkFormX(p, 31, r_src, r_dst, 0, 58, 0);
2872 break;
2873 case Pun_EXTSW: // extsw r_dst, r_src
2874 vassert(mode64);
2875 p = mkFormX(p, 31, r_src, r_dst, 0, 986, 0);
2876 break;
2877 default: goto bad;
2878 }
2879 goto done;
2880 }
2881
2882 case Pin_MulL: {
2883 Bool syned = i->Pin.MulL.syned;
2884 Bool sz32 = i->Pin.MulL.sz32;
2885 UInt r_dst = iregNo(i->Pin.MulL.dst, mode64);
2886 UInt r_srcL = iregNo(i->Pin.MulL.srcL, mode64);
2887 UInt r_srcR = iregNo(i->Pin.MulL.srcR, mode64);
2888
2889 if (!mode64)
2890 vassert(sz32);
2891
2892 if (i->Pin.MulL.hi) {
2893 // mul hi words, must consider sign
2894 if (sz32) {
2895 if (syned) // mulhw r_dst,r_srcL,r_srcR
2896 p = mkFormXO(p, 31, r_dst, r_srcL, r_srcR, 0, 75, 0);
2897 else // mulhwu r_dst,r_srcL,r_srcR
2898 p = mkFormXO(p, 31, r_dst, r_srcL, r_srcR, 0, 11, 0);
2899 } else {
2900 if (syned) // mulhd r_dst,r_srcL,r_srcR
2901 p = mkFormXO(p, 31, r_dst, r_srcL, r_srcR, 0, 73, 0);
2902 else // mulhdu r_dst,r_srcL,r_srcR
2903 p = mkFormXO(p, 31, r_dst, r_srcL, r_srcR, 0, 9, 0);
2904 }
2905 } else {
2906 // mul low word, sign is irrelevant
2907 vassert(!i->Pin.MulL.syned);
2908 if (sz32) // mullw r_dst,r_srcL,r_srcR
2909 p = mkFormXO(p, 31, r_dst, r_srcL, r_srcR, 0, 235, 0);
2910 else // mulld r_dst,r_srcL,r_srcR
2911 p = mkFormXO(p, 31, r_dst, r_srcL, r_srcR, 0, 233, 0);
2912 }
2913 goto done;
2914 }
2915
2916 case Pin_Div: {
2917 Bool syned = i->Pin.Div.syned;
2918 Bool sz32 = i->Pin.Div.sz32;
2919 UInt r_dst = iregNo(i->Pin.Div.dst, mode64);
2920 UInt r_srcL = iregNo(i->Pin.Div.srcL, mode64);
2921 UInt r_srcR = iregNo(i->Pin.Div.srcR, mode64);
2922
2923 if (!mode64)
2924 vassert(sz32);
2925
2926 if (sz32) {
2927 if (syned) // divw r_dst,r_srcL,r_srcR
2928 p = mkFormXO(p, 31, r_dst, r_srcL, r_srcR, 0, 491, 0);
2929 else // divwu r_dst,r_srcL,r_srcR
2930 p = mkFormXO(p, 31, r_dst, r_srcL, r_srcR, 0, 459, 0);
2931 } else {
2932 if (syned) // divd r_dst,r_srcL,r_srcR
2933 p = mkFormXO(p, 31, r_dst, r_srcL, r_srcR, 0, 489, 0);
2934 else // divdu r_dst,r_srcL,r_srcR
2935 p = mkFormXO(p, 31, r_dst, r_srcL, r_srcR, 0, 457, 0);
2936 }
2937 goto done;
2938 }
2939
2940 case Pin_Call: {
2941 PPCCondCode cond = i->Pin.Call.cond;
2942 UInt r_dst = 10;
2943 /* As per detailed comment for Pin_Call in
2944 getRegUsage_PPCInstr above, %r10 is used as an address temp */
2945
2946 /* jump over the following insns if condition does not hold */
2947 if (cond.test != Pct_ALWAYS) {
2948 /* jmp fwds if !condition */
2949 /* don't know how many bytes to jump over yet...
2950 make space for a jump instruction and fill in later. */
2951 ptmp = p; /* fill in this bit later */
2952 p += 4; // p += 4
2953 }
2954
2955 /* load target to r_dst */ // p += 4|8|20
2956 p = mkLoadImm(p, r_dst, i->Pin.Call.target, mode64);
2957
2958 /* mtspr 9,r_dst => move r_dst to count register */
2959 p = mkFormXFX(p, r_dst, 9, 467); // p += 4
2960
2961 /* bctrl => branch to count register (and save to lr) */
2962 p = mkFormXL(p, 19, Pct_ALWAYS, 0, 0, 528, 1); // p += 4
2963
2964 /* Fix up the conditional jump, if there was one. */
2965 if (cond.test != Pct_ALWAYS) {
2966 Int delta = p - ptmp;
2967 vassert(delta >= 16 && delta <= 32);
2968 /* bc !ct,cf,delta */
2969 mkFormB(ptmp, invertCondTest(cond.test),
2970 cond.flag, (delta>>2), 0, 0);
2971 }
2972 goto done;
2973 }
2974
2975 case Pin_Goto: {
2976 UInt trc = 0;
2977 UChar r_ret = 3; /* Put target addr into %r3 */
2978 PPCCondCode cond = i->Pin.Goto.cond;
2979 UInt r_dst;
2980 ULong imm_dst;
2981
2982 vassert(dispatch == NULL);
2983
2984 /* First off, if this is conditional, create a conditional
2985 jump over the rest of it. */
2986 if (cond.test != Pct_ALWAYS) {
2987 /* jmp fwds if !condition */
2988 /* don't know how many bytes to jump over yet...
2989 make space for a jump instruction and fill in later. */
2990 ptmp = p; /* fill in this bit later */
2991 p += 4;
2992 }
2993
2994 // cond succeeds...
2995
2996 /* If a non-boring, set GuestStatePtr appropriately. */
2997 switch (i->Pin.Goto.jk) {
2998 case Ijk_ClientReq: trc = VEX_TRC_JMP_CLIENTREQ; break;
2999 case Ijk_Sys_syscall: trc = VEX_TRC_JMP_SYS_SYSCALL; break;
3000 case Ijk_Yield: trc = VEX_TRC_JMP_YIELD; break;
3001 case Ijk_YieldNoRedir: trc = VEX_TRC_JMP_YIELD_NOREDIR; break;
3002 case Ijk_EmWarn: trc = VEX_TRC_JMP_EMWARN; break;
3003 case Ijk_EmFail: trc = VEX_TRC_JMP_EMFAIL; break;
3004 case Ijk_MapFail: trc = VEX_TRC_JMP_MAPFAIL; break;
3005 case Ijk_NoDecode: trc = VEX_TRC_JMP_NODECODE; break;
3006 case Ijk_TInval: trc = VEX_TRC_JMP_TINVAL; break;
3007 case Ijk_NoRedir: trc = VEX_TRC_JMP_NOREDIR; break;
3008 case Ijk_SigTRAP: trc = VEX_TRC_JMP_SIGTRAP; break;
3009 case Ijk_SigBUS: trc = VEX_TRC_JMP_SIGBUS; break;
3010 case Ijk_Ret:
3011 case Ijk_Call:
3012 case Ijk_Boring:
3013 break;
3014 default:
3015 ppIRJumpKind(i->Pin.Goto.jk);
3016 vpanic("emit_PPCInstr.Pin_Goto: unknown jump kind");
3017 }
3018 if (trc !=0) {
3019 vassert(trc < 0x10000);
3020 /* addi r31,0,trc */
3021 p = mkFormD(p, 14, 31, 0, trc); // p += 4
3022 }
3023
3024 /* Get the destination address into %r_ret */
3025 if (i->Pin.Goto.dst->tag == Pri_Imm) {
3026 imm_dst = i->Pin.Goto.dst->Pri.Imm;
3027 p = mkLoadImm(p, r_ret, imm_dst, mode64); // p += 4|8|20
3028 } else {
3029 vassert(i->Pin.Goto.dst->tag == Pri_Reg);
3030 r_dst = iregNo(i->Pin.Goto.dst->Pri.Reg, mode64);
3031 p = mkMoveReg(p, r_ret, r_dst); // p += 4
3032 }
3033
3034 /* blr */
3035 p = mkFormXL(p, 19, Pct_ALWAYS, 0, 0, 16, 0); // p += 4
3036
3037 /* Fix up the conditional jump, if there was one. */
3038 if (cond.test != Pct_ALWAYS) {
3039 Int delta = p - ptmp;
3040 vassert(delta >= 12 && delta <= 32);
3041 /* bc !ct,cf,delta */
3042 mkFormB(ptmp, invertCondTest(cond.test),
3043 cond.flag, delta>>2, 0, 0);
3044 }
3045 goto done;
3046 }
3047
3048 case Pin_CMov: {
3049 UInt r_dst, r_src;
3050 ULong imm_src;
3051 PPCCondCode cond;
3052 vassert(i->Pin.CMov.cond.test != Pct_ALWAYS);
3053
3054 r_dst = iregNo(i->Pin.CMov.dst, mode64);
3055 cond = i->Pin.CMov.cond;
3056
3057 /* branch (if cond fails) over move instrs */
3058 if (cond.test != Pct_ALWAYS) {
3059 /* don't know how many bytes to jump over yet...
3060 make space for a jump instruction and fill in later. */
3061 ptmp = p; /* fill in this bit later */
3062 p += 4;
3063 }
3064
3065 // cond true: move src => dst
3066 switch (i->Pin.CMov.src->tag) {
3067 case Pri_Imm:
3068 imm_src = i->Pin.CMov.src->Pri.Imm;
3069 p = mkLoadImm(p, r_dst, imm_src, mode64); // p += 4|8|20
3070 break;
3071 case Pri_Reg:
3072 r_src = iregNo(i->Pin.CMov.src->Pri.Reg, mode64);
3073 p = mkMoveReg(p, r_dst, r_src); // p += 4
3074 break;
3075 default: goto bad;
3076 }
3077
3078 /* Fix up the conditional jump, if there was one. */
3079 if (cond.test != Pct_ALWAYS) {
3080 Int delta = p - ptmp;
3081 vassert(delta >= 8 && delta <= 24);
3082 /* bc !ct,cf,delta */
3083 mkFormB(ptmp, invertCondTest(cond.test),
3084 cond.flag, (delta>>2), 0, 0);
3085 }
3086 goto done;
3087 }
3088
3089 case Pin_Load: {
3090 PPCAMode* am_addr = i->Pin.Load.src;
3091 UInt r_dst = iregNo(i->Pin.Load.dst, mode64);
3092 UInt opc1, opc2, sz = i->Pin.Load.sz;
3093 switch (am_addr->tag) {
3094 case Pam_IR:
3095 if (mode64 && (sz == 4 || sz == 8)) {
3096 /* should be guaranteed to us by iselWordExpr_AMode */
3097 vassert(0 == (am_addr->Pam.IR.index & 3));
3098 }
3099 switch(sz) {
3100 case 1: opc1 = 34; break;
3101 case 2: opc1 = 40; break;
3102 case 4: opc1 = 32; break;
3103 case 8: opc1 = 58; vassert(mode64); break;
3104 default: goto bad;
3105 }
3106 p = doAMode_IR(p, opc1, r_dst, am_addr, mode64);
3107 goto done;
3108 case Pam_RR:
3109 switch(sz) {
3110 case 1: opc2 = 87; break;
3111 case 2: opc2 = 279; break;
3112 case 4: opc2 = 23; break;
3113 case 8: opc2 = 21; vassert(mode64); break;
3114 default: goto bad;
3115 }
3116 p = doAMode_RR(p, 31, opc2, r_dst, am_addr, mode64);
3117 goto done;
3118 default:
3119 goto bad;
3120 }
3121 }
3122
3123 case Pin_LoadL: {
3124 if (i->Pin.LoadL.sz == 4) {
3125 p = mkFormX(p, 31, iregNo(i->Pin.LoadL.dst, mode64),
3126 0, iregNo(i->Pin.LoadL.src, mode64), 20, 0);
3127 goto done;
3128 }
3129 if (i->Pin.LoadL.sz == 8 && mode64) {
3130 p = mkFormX(p, 31, iregNo(i->Pin.LoadL.dst, mode64),
3131 0, iregNo(i->Pin.LoadL.src, mode64), 84, 0);
3132 goto done;
3133 }
3134 goto bad;
3135 }
3136
3137 case Pin_Set: {
3138 /* Make the destination register be 1 or 0, depending on whether
3139 the relevant condition holds. */
3140 UInt r_dst = iregNo(i->Pin.Set.dst, mode64);
3141 PPCCondCode cond = i->Pin.Set.cond;
3142 UInt rot_imm, r_tmp;
3143
3144 if (cond.test == Pct_ALWAYS) {
3145 // Just load 1 to dst => li dst,1
3146 p = mkFormD(p, 14, r_dst, 0, 1);
3147 } else {
3148 rot_imm = 1 + cond.flag;
3149 r_tmp = 0; // Not set in getAllocable, so no need to declare.
3150
3151 // r_tmp = CR => mfcr r_tmp
3152 p = mkFormX(p, 31, r_tmp, 0, 0, 19, 0);
3153
3154 // r_dst = flag (rotate left and mask)
3155 // => rlwinm r_dst,r_tmp,rot_imm,31,31
3156 p = mkFormM(p, 21, r_tmp, r_dst, rot_imm, 31, 31, 0);
3157
3158 if (cond.test == Pct_FALSE) {
3159 // flip bit => xori r_dst,r_dst,1
3160 p = mkFormD(p, 26, r_dst, r_dst, 1);
3161 }
3162 }
3163 goto done;
3164 }
3165
3166 case Pin_MfCR:
3167 // mfcr dst
3168 p = mkFormX(p, 31, iregNo(i->Pin.MfCR.dst, mode64), 0, 0, 19, 0);
3169 goto done;
3170
3171 case Pin_MFence: {
3172 p = mkFormX(p, 31, 0, 0, 0, 598, 0); // sync, PPC32 p616
3173 // CAB: Should this be isync?
3174 // p = mkFormXL(p, 19, 0, 0, 0, 150, 0); // isync, PPC32 p467
3175 goto done;
3176 }
3177
3178 case Pin_Store: {
3179 PPCAMode* am_addr = i->Pin.Store.dst;
3180 UInt r_src = iregNo(i->Pin.Store.src, mode64);
3181 UInt opc1, opc2, sz = i->Pin.Store.sz;
3182 switch (i->Pin.Store.dst->tag) {
3183 case Pam_IR:
3184 if (mode64 && (sz == 4 || sz == 8)) {
3185 /* should be guaranteed to us by iselWordExpr_AMode */
3186 vassert(0 == (am_addr->Pam.IR.index & 3));
3187 }
3188 switch(sz) {
3189 case 1: opc1 = 38; break;
3190 case 2: opc1 = 44; break;
3191 case 4: opc1 = 36; break;
3192 case 8: vassert(mode64);
3193 opc1 = 62; break;
3194 default:
3195 goto bad;
3196 }
3197 p = doAMode_IR(p, opc1, r_src, am_addr, mode64);
3198 goto done;
3199 case Pam_RR:
3200 switch(sz) {
3201 case 1: opc2 = 215; break;
3202 case 2: opc2 = 407; break;
3203 case 4: opc2 = 151; break;
3204 case 8: vassert(mode64);
3205 opc2 = 149; break;
3206 default:
3207 goto bad;
3208 }
3209 p = doAMode_RR(p, 31, opc2, r_src, am_addr, mode64);
3210 goto done;
3211 default:
3212 goto bad;
3213 }
3214 goto done;
3215 }
3216
3217 case Pin_StoreC: {
3218 if (i->Pin.StoreC.sz == 4) {
3219 p = mkFormX(p, 31, iregNo(i->Pin.StoreC.src, mode64),
3220 0, iregNo(i->Pin.StoreC.dst, mode64), 150, 1);
3221 goto done;
3222 }
3223 if (i->Pin.StoreC.sz == 8 && mode64) {
3224 p = mkFormX(p, 31, iregNo(i->Pin.StoreC.src, mode64),
3225 0, iregNo(i->Pin.StoreC.dst, mode64), 214, 1);
3226 goto done;
3227 }
3228 goto bad;
3229 }
3230
3231 case Pin_FpUnary: {
3232 UInt fr_dst = fregNo(i->Pin.FpUnary.dst);
3233 UInt fr_src = fregNo(i->Pin.FpUnary.src);
3234 switch (i->Pin.FpUnary.op) {
3235 case Pfp_RSQRTE: // frsqrtre, PPC32 p424
3236 p = mkFormA( p, 63, fr_dst, 0, fr_src, 0, 26, 0 );
3237 break;
3238 case Pfp_RES: // fres, PPC32 p421
3239 p = mkFormA( p, 59, fr_dst, 0, fr_src, 0, 24, 0 );
3240 break;
3241 case Pfp_SQRT: // fsqrt, PPC32 p427
3242 p = mkFormA( p, 63, fr_dst, 0, fr_src, 0, 22, 0 );
3243 break;
3244 case Pfp_ABS: // fabs, PPC32 p399
3245 p = mkFormX(p, 63, fr_dst, 0, fr_src, 264, 0);
3246 break;
3247 case Pfp_NEG: // fneg, PPC32 p416
3248 p = mkFormX(p, 63, fr_dst, 0, fr_src, 40, 0);
3249 break;
3250 case Pfp_MOV: // fmr, PPC32 p410
3251 p = mkFormX(p, 63, fr_dst, 0, fr_src, 72, 0);
3252 break;
3253 case Pfp_FRIM: // frim, PPC ISA 2.05 p137
3254 p = mkFormX(p, 63, fr_dst, 0, fr_src, 488, 0);
3255 break;
3256 case Pfp_FRIP: // frip, PPC ISA 2.05 p137
3257 p = mkFormX(p, 63, fr_dst, 0, fr_src, 456, 0);
3258 break;
3259 case Pfp_FRIN: // frin, PPC ISA 2.05 p137
3260 p = mkFormX(p, 63, fr_dst, 0, fr_src, 392, 0);
3261 break;
3262 case Pfp_FRIZ: // friz, PPC ISA 2.05 p137
3263 p = mkFormX(p, 63, fr_dst, 0, fr_src, 424, 0);
3264 break;
3265 default:
3266 goto bad;
3267 }
3268 goto done;
3269 }
3270
3271 case Pin_FpBinary: {
3272 UInt fr_dst = fregNo(i->Pin.FpBinary.dst);
3273 UInt fr_srcL = fregNo(i->Pin.FpBinary.srcL);
3274 UInt fr_srcR = fregNo(i->Pin.FpBinary.srcR);
3275 switch (i->Pin.FpBinary.op) {
3276 case Pfp_ADDD: // fadd, PPC32 p400
3277 p = mkFormA( p, 63, fr_dst, fr_srcL, fr_srcR, 0, 21, 0 );
3278 break;
3279 case Pfp_ADDS: // fadds, PPC32 p401
3280 p = mkFormA( p, 59, fr_dst, fr_srcL, fr_srcR, 0, 21, 0 );
3281 break;
3282 case Pfp_SUBD: // fsub, PPC32 p429
3283 p = mkFormA( p, 63, fr_dst, fr_srcL, fr_srcR, 0, 20, 0 );
3284 break;
3285 case Pfp_SUBS: // fsubs, PPC32 p430
3286 p = mkFormA( p, 59, fr_dst, fr_srcL, fr_srcR, 0, 20, 0 );
3287 break;
3288 case Pfp_MULD: // fmul, PPC32 p413
3289 p = mkFormA( p, 63, fr_dst, fr_srcL, 0, fr_srcR, 25, 0 );
3290 break;
3291 case Pfp_MULS: // fmuls, PPC32 p414
3292 p = mkFormA( p, 59, fr_dst, fr_srcL, 0, fr_srcR, 25, 0 );
3293 break;
3294 case Pfp_DIVD: // fdiv, PPC32 p406
3295 p = mkFormA( p, 63, fr_dst, fr_srcL, fr_srcR, 0, 18, 0 );
3296 break;
3297 case Pfp_DIVS: // fdivs, PPC32 p407
3298 p = mkFormA( p, 59, fr_dst, fr_srcL, fr_srcR, 0, 18, 0 );
3299 break;
3300 default:
3301 goto bad;
3302 }
3303 goto done;
3304 }
3305
3306 case Pin_FpMulAcc: {
3307 UInt fr_dst = fregNo(i->Pin.FpMulAcc.dst);
3308 UInt fr_srcML = fregNo(i->Pin.FpMulAcc.srcML);
3309 UInt fr_srcMR = fregNo(i->Pin.FpMulAcc.srcMR);
3310 UInt fr_srcAcc = fregNo(i->Pin.FpMulAcc.srcAcc);
3311 switch (i->Pin.FpMulAcc.op) {
3312 case Pfp_MADDD: // fmadd, PPC32 p408
3313 p = mkFormA( p, 63, fr_dst, fr_srcML, fr_srcAcc, fr_srcMR, 29, 0 );
3314 break;
3315 case Pfp_MADDS: // fmadds, PPC32 p409
3316 p = mkFormA( p, 59, fr_dst, fr_srcML, fr_srcAcc, fr_srcMR, 29, 0 );
3317 break;
3318 case Pfp_MSUBD: // fmsub, PPC32 p411
3319 p = mkFormA( p, 63, fr_dst, fr_srcML, fr_srcAcc, fr_srcMR, 28, 0 );
3320 break;
3321 case Pfp_MSUBS: // fmsubs, PPC32 p412
3322 p = mkFormA( p, 59, fr_dst, fr_srcML, fr_srcAcc, fr_srcMR, 28, 0 );
3323 break;
3324 default:
3325 goto bad;
3326 }
3327 goto done;
3328 }
3329
3330 case Pin_FpLdSt: {
3331 PPCAMode* am_addr = i->Pin.FpLdSt.addr;
3332 UInt f_reg = fregNo(i->Pin.FpLdSt.reg);
3333 Bool idxd = toBool(i->Pin.FpLdSt.addr->tag == Pam_RR);
3334 UChar sz = i->Pin.FpLdSt.sz;
3335 UInt opc;
3336 vassert(sz == 4 || sz == 8);
3337
3338 if (i->Pin.FpLdSt.isLoad) { // Load from memory
3339 if (idxd) { // lf[s|d]x, PPC32 p444|440
3340 opc = (sz == 4) ? 535 : 599;
3341 p = doAMode_RR(p, 31, opc, f_reg, am_addr, mode64);
3342 } else { // lf[s|d], PPC32 p441|437
3343 opc = (sz == 4) ? 48 : 50;
3344 p = doAMode_IR(p, opc, f_reg, am_addr, mode64);
3345 }
3346 } else { // Store to memory
3347 if (idxd) { // stf[s|d]x, PPC32 p521|516
3348 opc = (sz == 4) ? 663 : 727;
3349 p = doAMode_RR(p, 31, opc, f_reg, am_addr, mode64);
3350 } else { // stf[s|d], PPC32 p518|513
3351 opc = (sz == 4) ? 52 : 54;
3352 p = doAMode_IR(p, opc, f_reg, am_addr, mode64);
3353 }
3354 }
3355 goto done;
3356 }
3357
3358 case Pin_FpSTFIW: {
3359 UInt ir_addr = iregNo(i->Pin.FpSTFIW.addr, mode64);
3360 UInt fr_data = fregNo(i->Pin.FpSTFIW.data);
3361 // stfiwx (store fp64[lo32] as int32), PPC32 p517
3362 // Use rA==0, so that EA == rB == ir_addr
3363 p = mkFormX(p, 31, fr_data, 0/*rA=0*/, ir_addr, 983, 0);
3364 goto done;
3365 }
3366
3367 case Pin_FpRSP: {
3368 UInt fr_dst = fregNo(i->Pin.FpRSP.dst);
3369 UInt fr_src = fregNo(i->Pin.FpRSP.src);
3370 // frsp, PPC32 p423
3371 p = mkFormX(p, 63, fr_dst, 0, fr_src, 12, 0);
3372 goto done;
3373 }
3374
3375 case Pin_FpCftI: {
3376 UInt fr_dst = fregNo(i->Pin.FpCftI.dst);
3377 UInt fr_src = fregNo(i->Pin.FpCftI.src);
3378 if (i->Pin.FpCftI.fromI == False && i->Pin.FpCftI.int32 == True) {
3379 // fctiw (conv f64 to i32), PPC32 p404
3380 p = mkFormX(p, 63, fr_dst, 0, fr_src, 14, 0);
3381 goto done;
3382 }
3383 if (i->Pin.FpCftI.fromI == False && i->Pin.FpCftI.int32 == False) {
3384 // fctid (conv f64 to i64), PPC64 p437
3385 p = mkFormX(p, 63, fr_dst, 0, fr_src, 814, 0);
3386 goto done;
3387 }
3388 if (i->Pin.FpCftI.fromI == True && i->Pin.FpCftI.int32 == False) {
3389 // fcfid (conv i64 to f64), PPC64 p434
3390 p = mkFormX(p, 63, fr_dst, 0, fr_src, 846, 0);
3391 goto done;
3392 }
3393 goto bad;
3394 }
3395
3396 case Pin_FpCMov: {
3397 UInt fr_dst = fregNo(i->Pin.FpCMov.dst);
3398 UInt fr_src = fregNo(i->Pin.FpCMov.src);
3399 PPCCondCode cc = i->Pin.FpCMov.cond;
3400
3401 if (fr_dst == fr_src) goto done;
3402
3403 vassert(cc.test != Pct_ALWAYS);
3404
3405 /* jmp fwds if !condition */
3406 if (cc.test != Pct_ALWAYS) {
3407 /* bc !ct,cf,n_bytes>>2 */
3408 p = mkFormB(p, invertCondTest(cc.test), cc.flag, 8>>2, 0, 0);
3409 }
3410
3411 // fmr, PPC32 p410
3412 p = mkFormX(p, 63, fr_dst, 0, fr_src, 72, 0);
3413 goto done;
3414 }
3415
3416 case Pin_FpLdFPSCR: {
3417 UInt fr_src = fregNo(i->Pin.FpLdFPSCR.src);
3418 p = mkFormXFL(p, 0xFF, fr_src); // mtfsf, PPC32 p480
3419 goto done;
3420 }
3421
3422 case Pin_FpCmp: {
3423 UChar crfD = 1;
3424 UInt r_dst = iregNo(i->Pin.FpCmp.dst, mode64);
3425 UInt fr_srcL = fregNo(i->Pin.FpCmp.srcL);
3426 UInt fr_srcR = fregNo(i->Pin.FpCmp.srcR);
3427 vassert(crfD < 8);
3428 // fcmpo, PPC32 p402
3429 p = mkFormX(p, 63, crfD<<2, fr_srcL, fr_srcR, 32, 0);
3430
3431 // mfcr (mv CR to r_dst), PPC32 p467
3432 p = mkFormX(p, 31, r_dst, 0, 0, 19, 0);
3433
3434 // rlwinm r_dst,r_dst,8,28,31, PPC32 p501
3435 // => rotate field 1 to bottomw of word, masking out upper 28
3436 p = mkFormM(p, 21, r_dst, r_dst, 8, 28, 31, 0);
3437 goto done;
3438 }
3439
3440 case Pin_RdWrLR: {
3441 UInt reg = iregNo(i->Pin.RdWrLR.gpr, mode64);
3442 /* wrLR==True ? mtlr r4 : mflr r4 */
3443 p = mkFormXFX(p, reg, 8, (i->Pin.RdWrLR.wrLR==True) ? 467 : 339);
3444 goto done;
3445 }
3446
3447
3448 /* AltiVec */
3449 case Pin_AvLdSt: {
3450 UInt opc2, v_reg, r_idx, r_base;
3451 UChar sz = i->Pin.AvLdSt.sz;
3452 Bool idxd = toBool(i->Pin.AvLdSt.addr->tag == Pam_RR);
3453 vassert(sz == 1 || sz == 2 || sz == 4 || sz == 16);
3454
3455 v_reg = vregNo(i->Pin.AvLdSt.reg);
3456 r_base = iregNo(i->Pin.AvLdSt.addr->Pam.RR.base, mode64);
3457
3458 // Only have AltiVec AMode_RR: kludge AMode_IR
3459 if (!idxd) {
3460 r_idx = 30; // XXX: Using r30 as temp
3461 p = mkLoadImm(p, r_idx,
3462 i->Pin.AvLdSt.addr->Pam.IR.index, mode64);
3463 } else {
3464 r_idx = iregNo(i->Pin.AvLdSt.addr->Pam.RR.index, mode64);
3465 }
3466
3467 if (i->Pin.FpLdSt.isLoad) { // Load from memory (1,2,4,16)
3468 opc2 = (sz==1) ? 7 : (sz==2) ? 39 : (sz==4) ? 71 : 103;
3469 p = mkFormX(p, 31, v_reg, r_idx, r_base, opc2, 0);
3470 } else { // Store to memory (1,2,4,16)
3471 opc2 = (sz==1) ? 135 : (sz==2) ? 167 : (sz==4) ? 199 : 231;
3472 p = mkFormX(p, 31, v_reg, r_idx, r_base, opc2, 0);
3473 }
3474 goto done;
3475 }
3476
3477 case Pin_AvUnary: {
3478 UInt v_dst = vregNo(i->Pin.AvUnary.dst);
3479 UInt v_src = vregNo(i->Pin.AvUnary.src);
3480 UInt opc2;
3481 switch (i->Pin.AvUnary.op) {
3482 case Pav_MOV: opc2 = 1156; break; // vor vD,vS,vS
3483 case Pav_NOT: opc2 = 1284; break; // vnor vD,vS,vS
3484 case Pav_UNPCKH8S: opc2 = 526; break; // vupkhsb
3485 case Pav_UNPCKH16S: opc2 = 590; break; // vupkhsh
3486 case Pav_UNPCKL8S: opc2 = 654; break; // vupklsb
3487 case Pav_UNPCKL16S: opc2 = 718; break; // vupklsh
3488 case Pav_UNPCKHPIX: opc2 = 846; break; // vupkhpx
3489 case Pav_UNPCKLPIX: opc2 = 974; break; // vupklpx
3490 default:
3491 goto bad;
3492 }
3493 switch (i->Pin.AvUnary.op) {
3494 case Pav_MOV:
3495 case Pav_NOT:
3496 p = mkFormVX( p, 4, v_dst, v_src, v_src, opc2 );
3497 break;
3498 default:
3499 p = mkFormVX( p, 4, v_dst, 0, v_src, opc2 );
3500 break;
3501 }
3502 goto done;
3503 }
3504
3505 case Pin_AvBinary: {
3506 UInt v_dst = vregNo(i->Pin.AvBinary.dst);
3507 UInt v_srcL = vregNo(i->Pin.AvBinary.srcL);
3508 UInt v_srcR = vregNo(i->Pin.AvBinary.srcR);
3509 UInt opc2;
3510 if (i->Pin.AvBinary.op == Pav_SHL) {
3511 p = mkFormVX( p, 4, v_dst, v_srcL, v_srcR, 1036 ); // vslo
3512 p = mkFormVX( p, 4, v_dst, v_dst, v_srcR, 452 ); // vsl
3513 goto done;
3514 }
3515 if (i->Pin.AvBinary.op == Pav_SHR) {
3516 p = mkFormVX( p, 4, v_dst, v_srcL, v_srcR, 1100 ); // vsro
3517 p = mkFormVX( p, 4, v_dst, v_dst, v_srcR, 708 ); // vsr
3518 goto done;
3519 }
3520 switch (i->Pin.AvBinary.op) {
3521 /* Bitwise */
3522 case Pav_AND: opc2 = 1028; break; // vand
3523 case Pav_OR: opc2 = 1156; break; // vor
3524 case Pav_XOR: opc2 = 1220; break; // vxor
3525 default:
3526 goto bad;
3527 }
3528 p = mkFormVX( p, 4, v_dst, v_srcL, v_srcR, opc2 );
3529 goto done;
3530 }
3531
3532 case Pin_AvBin8x16: {
3533 UInt v_dst = vregNo(i->Pin.AvBin8x16.dst);
3534 UInt v_srcL = vregNo(i->Pin.AvBin8x16.srcL);
3535 UInt v_srcR = vregNo(i->Pin.AvBin8x16.srcR);
3536 UInt opc2;
3537 switch (i->Pin.AvBin8x16.op) {
3538
3539 case Pav_ADDU: opc2 = 0; break; // vaddubm
3540 case Pav_QADDU: opc2 = 512; break; // vaddubs
3541 case Pav_QADDS: opc2 = 768; break; // vaddsbs
3542
3543 case Pav_SUBU: opc2 = 1024; break; // vsububm
3544 case Pav_QSUBU: opc2 = 1536; break; // vsububs
3545 case Pav_QSUBS: opc2 = 1792; break; // vsubsbs
3546
3547 case Pav_OMULU: opc2 = 8; break; // vmuloub
3548 case Pav_OMULS: opc2 = 264; break; // vmulosb
3549 case Pav_EMULU: opc2 = 520; break; // vmuleub
3550 case Pav_EMULS: opc2 = 776; break; // vmulesb
3551
3552 case Pav_AVGU: opc2 = 1026; break; // vavgub
3553 case Pav_AVGS: opc2 = 1282; break; // vavgsb
3554 case Pav_MAXU: opc2 = 2; break; // vmaxub
3555 case Pav_MAXS: opc2 = 258; break; // vmaxsb
3556 case Pav_MINU: opc2 = 514; break; // vminub
3557 case Pav_MINS: opc2 = 770; break; // vminsb
3558
3559 case Pav_CMPEQU: opc2 = 6; break; // vcmpequb
3560 case Pav_CMPGTU: opc2 = 518; break; // vcmpgtub
3561 case Pav_CMPGTS: opc2 = 774; break; // vcmpgtsb
3562
3563 case Pav_SHL: opc2 = 260; break; // vslb
3564 case Pav_SHR: opc2 = 516; break; // vsrb
3565 case Pav_SAR: opc2 = 772; break; // vsrab
3566 case Pav_ROTL: opc2 = 4; break; // vrlb
3567
3568 case Pav_MRGHI: opc2 = 12; break; // vmrghb
3569 case Pav_MRGLO: opc2 = 268; break; // vmrglb
3570
3571 default:
3572 goto bad;
3573 }
3574 p = mkFormVX( p, 4, v_dst, v_srcL, v_srcR, opc2 );
3575 goto done;
3576 }
3577
3578 case Pin_AvBin16x8: {
3579 UInt v_dst = vregNo(i->Pin.AvBin16x8.dst);
3580 UInt v_srcL = vregNo(i->Pin.AvBin16x8.srcL);
3581 UInt v_srcR = vregNo(i->Pin.AvBin16x8.srcR);
3582 UInt opc2;
3583 switch (i->Pin.AvBin16x8.op) {
3584
3585 case Pav_ADDU: opc2 = 64; break; // vadduhm
3586 case Pav_QADDU: opc2 = 576; break; // vadduhs
3587 case Pav_QADDS: opc2 = 832; break; // vaddshs
3588
3589 case Pav_SUBU: opc2 = 1088; break; // vsubuhm
3590 case Pav_QSUBU: opc2 = 1600; break; // vsubuhs
3591 case Pav_QSUBS: opc2 = 1856; break; // vsubshs
3592
3593 case Pav_OMULU: opc2 = 72; break; // vmulouh
3594 case Pav_OMULS: opc2 = 328; break; // vmulosh
3595 case Pav_EMULU: opc2 = 584; break; // vmuleuh
3596 case Pav_EMULS: opc2 = 840; break; // vmulesh
3597
3598 case Pav_AVGU: opc2 = 1090; break; // vavguh
3599 case Pav_AVGS: opc2 = 1346; break; // vavgsh
3600 case Pav_MAXU: opc2 = 66; break; // vmaxuh
3601 case Pav_MAXS: opc2 = 322; break; // vmaxsh
3602 case Pav_MINS: opc2 = 834; break; // vminsh
3603 case Pav_MINU: opc2 = 578; break; // vminuh
3604
3605 case Pav_CMPEQU: opc2 = 70; break; // vcmpequh
3606 case Pav_CMPGTU: opc2 = 582; break; // vcmpgtuh
3607 case Pav_CMPGTS: opc2 = 838; break; // vcmpgtsh
3608
3609 case Pav_SHL: opc2 = 324; break; // vslh
3610 case Pav_SHR: opc2 = 580; break; // vsrh
3611 case Pav_SAR: opc2 = 836; break; // vsrah
3612 case Pav_ROTL: opc2 = 68; break; // vrlh
3613
3614 case Pav_PACKUU: opc2 = 14; break; // vpkuhum
3615 case Pav_QPACKUU: opc2 = 142; break; // vpkuhus
3616 case Pav_QPACKSU: opc2 = 270; break; // vpkshus
3617 case Pav_QPACKSS: opc2 = 398; break; // vpkshss
3618 case Pav_PACKPXL: opc2 = 782; break; // vpkpx
3619
3620 case Pav_MRGHI: opc2 = 76; break; // vmrghh
3621 case Pav_MRGLO: opc2 = 332; break; // vmrglh
3622
3623 default:
3624 goto bad;
3625 }
3626 p = mkFormVX( p, 4, v_dst, v_srcL, v_srcR, opc2 );
3627 goto done;
3628 }
3629
3630 case Pin_AvBin32x4: {
3631 UInt v_dst = vregNo(i->Pin.AvBin32x4.dst);
3632 UInt v_srcL = vregNo(i->Pin.AvBin32x4.srcL);
3633 UInt v_srcR = vregNo(i->Pin.AvBin32x4.srcR);
3634 UInt opc2;
3635 switch (i->Pin.AvBin32x4.op) {
3636
3637 case Pav_ADDU: opc2 = 128; break; // vadduwm
3638 case Pav_QADDU: opc2 = 640; break; // vadduws
3639 case Pav_QADDS: opc2 = 896; break; // vaddsws
3640
3641 case Pav_SUBU: opc2 = 1152; break; // vsubuwm
3642 case Pav_QSUBU: opc2 = 1664; break; // vsubuws
3643 case Pav_QSUBS: opc2 = 1920; break; // vsubsws
3644
3645 case Pav_AVGU: opc2 = 1154; break; // vavguw
3646 case Pav_AVGS: opc2 = 1410; break; // vavgsw
3647
3648 case Pav_MAXU: opc2 = 130; break; // vmaxuw
3649 case Pav_MAXS: opc2 = 386; break; // vmaxsw
3650
3651 case Pav_MINS: opc2 = 898; break; // vminsw
3652 case Pav_MINU: opc2 = 642; break; // vminuw
3653
3654 case Pav_CMPEQU: opc2 = 134; break; // vcmpequw
3655 case Pav_CMPGTS: opc2 = 902; break; // vcmpgtsw
3656 case Pav_CMPGTU: opc2 = 646; break; // vcmpgtuw
3657
3658 case Pav_SHL: opc2 = 388; break; // vslw
3659 case Pav_SHR: opc2 = 644; break; // vsrw
3660 case Pav_SAR: opc2 = 900; break; // vsraw
3661 case Pav_ROTL: opc2 = 132; break; // vrlw
3662
3663 case Pav_PACKUU: opc2 = 78; break; // vpkuwum
3664 case Pav_QPACKUU: opc2 = 206; break; // vpkuwus
3665 case Pav_QPACKSU: opc2 = 334; break; // vpkswus
3666 case Pav_QPACKSS: opc2 = 462; break; // vpkswss
3667
3668 case Pav_MRGHI: opc2 = 140; break; // vmrghw
3669 case Pav_MRGLO: opc2 = 396; break; // vmrglw
3670
3671 default:
3672 goto bad;
3673 }
3674 p = mkFormVX( p, 4, v_dst, v_srcL, v_srcR, opc2 );
3675 goto done;
3676 }
3677
3678 case Pin_AvBin32Fx4: {
3679 UInt v_dst = vregNo(i->Pin.AvBin32Fx4.dst);
3680 UInt v_srcL = vregNo(i->Pin.AvBin32Fx4.srcL);
3681 UInt v_srcR = vregNo(i->Pin.AvBin32Fx4.srcR);
3682 switch (i->Pin.AvBin32Fx4.op) {
3683
3684 case Pavfp_ADDF:
3685 p = mkFormVX( p, 4, v_dst, v_srcL, v_srcR, 10 ); // vaddfp
3686 break;
3687 case Pavfp_SUBF:
3688 p = mkFormVX( p, 4, v_dst, v_srcL, v_srcR, 74 ); // vsubfp
3689 break;
3690 case Pavfp_MAXF:
3691 p = mkFormVX( p, 4, v_dst, v_srcL, v_srcR, 1034 ); // vmaxfp
3692 break;
3693 case Pavfp_MINF:
3694 p = mkFormVX( p, 4, v_dst, v_srcL, v_srcR, 1098 ); // vminfp
3695 break;
3696
3697 case Pavfp_MULF: {
3698 /* Make a vmulfp from a vmaddfp:
3699 load -0.0 (0x8000_0000) to each 32-bit word of vB
3700 this makes the add a noop.
3701 */
3702 UInt vB = 29; // XXX: Using v29 for temp do not change
3703 // without also changing
3704 // getRegUsage_PPCInstr
3705 UInt konst = 0x1F;
3706
3707 // Better way to load -0.0 (0x80000000) ?
3708 // vspltisw vB,0x1F (0x1F => each word of vB)
3709 p = mkFormVX( p, 4, vB, konst, 0, 908 );
3710
3711 // vslw vB,vB,vB (each word of vB = (0x1F << 0x1F) = 0x80000000
3712 p = mkFormVX( p, 4, vB, vB, vB, 388 );
3713
3714 // Finally, do the multiply:
3715 p = mkFormVA( p, 4, v_dst, v_srcL, vB, v_srcR, 46 );
3716 break;
3717 }
3718 case Pavfp_CMPEQF: // vcmpeqfp
3719 p = mkFormVXR( p, 4, v_dst, v_srcL, v_srcR, 0, 198 );
3720 break;
3721 case Pavfp_CMPGTF: // vcmpgtfp
3722 p = mkFormVXR( p, 4, v_dst, v_srcL, v_srcR, 0, 710 );
3723 break;
3724 case Pavfp_CMPGEF: // vcmpgefp
3725 p = mkFormVXR( p, 4, v_dst, v_srcL, v_srcR, 0, 454 );
3726 break;
3727
3728 default:
3729 goto bad;
3730 }
3731 goto done;
3732 }
3733
3734 case Pin_AvUn32Fx4: {
3735 UInt v_dst = vregNo(i->Pin.AvUn32Fx4.dst);
3736 UInt v_src = vregNo(i->Pin.AvUn32Fx4.src);
3737 UInt opc2;
3738 switch (i->Pin.AvUn32Fx4.op) {
3739 case Pavfp_RCPF: opc2 = 266; break; // vrefp
3740 case Pavfp_RSQRTF: opc2 = 330; break; // vrsqrtefp
3741 case Pavfp_CVTU2F: opc2 = 778; break; // vcfux
3742 case Pavfp_CVTS2F: opc2 = 842; break; // vcfsx
3743 case Pavfp_QCVTF2U: opc2 = 906; break; // vctuxs
3744 case Pavfp_QCVTF2S: opc2 = 970; break; // vctsxs
3745 case Pavfp_ROUNDM: opc2 = 714; break; // vrfim
3746 case Pavfp_ROUNDP: opc2 = 650; break; // vrfip
3747 case Pavfp_ROUNDN: opc2 = 522; break; // vrfin
3748 case Pavfp_ROUNDZ: opc2 = 586; break; // vrfiz
3749 default:
3750 goto bad;
3751 }
3752 p = mkFormVX( p, 4, v_dst, 0, v_src, opc2 );
3753 goto done;
3754 }
3755
3756 case Pin_AvPerm: { // vperm
3757 UInt v_dst = vregNo(i->Pin.AvPerm.dst);
3758 UInt v_srcL = vregNo(i->Pin.AvPerm.srcL);
3759 UInt v_srcR = vregNo(i->Pin.AvPerm.srcR);
3760 UInt v_ctl = vregNo(i->Pin.AvPerm.ctl);
3761 p = mkFormVA( p, 4, v_dst, v_srcL, v_srcR, v_ctl, 43 );
3762 goto done;
3763 }
3764
3765 case Pin_AvSel: { // vsel
3766 UInt v_ctl = vregNo(i->Pin.AvSel.ctl);
3767 UInt v_dst = vregNo(i->Pin.AvSel.dst);
3768 UInt v_srcL = vregNo(i->Pin.AvSel.srcL);
3769 UInt v_srcR = vregNo(i->Pin.AvSel.srcR);
3770 p = mkFormVA( p, 4, v_dst, v_srcL, v_srcR, v_ctl, 42 );
3771 goto done;
3772 }
3773
3774 case Pin_AvShlDbl: { // vsldoi
3775 UInt shift = i->Pin.AvShlDbl.shift;
3776 UInt v_dst = vregNo(i->Pin.AvShlDbl.dst);
3777 UInt v_srcL = vregNo(i->Pin.AvShlDbl.srcL);
3778 UInt v_srcR = vregNo(i->Pin.AvShlDbl.srcR);
3779 vassert(shift <= 0xF);
3780 p = mkFormVA( p, 4, v_dst, v_srcL, v_srcR, shift, 44 );
3781 goto done;
3782 }
3783
3784 case Pin_AvSplat: { // vsplt(is)(b,h,w)
3785 UInt v_dst = vregNo(i->Pin.AvShlDbl.dst);
3786 UChar sz = i->Pin.AvSplat.sz;
3787 UInt v_src, opc2;
3788 vassert(sz == 8 || sz == 16 || sz == 32);
3789
3790 if (i->Pin.AvSplat.src->tag == Pvi_Imm) {
3791 Char simm5;
3792 opc2 = (sz == 8) ? 780 : (sz == 16) ? 844 : 908; // 8,16,32
3793 /* expects 5-bit-signed-imm */
3794 simm5 = i->Pin.AvSplat.src->Pvi.Imm5s;
3795 vassert(simm5 >= -16 && simm5 <= 15);
3796 simm5 = simm5 & 0x1F;
3797 p = mkFormVX( p, 4, v_dst, (UInt)simm5, 0, opc2 );
3798 }
3799 else { // Pri_Reg
3800 UInt lowest_lane;
3801 opc2 = (sz == 8) ? 524 : (sz == 16) ? 588 : 652; // 8,16,32
3802 vassert(hregClass(i->Pin.AvSplat.src->Pvi.Reg) == HRcVec128);
3803 v_src = vregNo(i->Pin.AvSplat.src->Pvi.Reg);
3804 lowest_lane = (128/sz)-1;
3805 p = mkFormVX( p, 4, v_dst, lowest_lane, v_src, opc2 );
3806 }
3807 goto done;
3808 }
3809
3810 case Pin_AvCMov: {
3811 UInt v_dst = vregNo(i->Pin.AvCMov.dst);
3812 UInt v_src = vregNo(i->Pin.AvCMov.src);
3813 PPCCondCode cc = i->Pin.AvCMov.cond;
3814
3815 if (v_dst == v_src) goto done;
3816
3817 vassert(cc.test != Pct_ALWAYS);
3818
3819 /* jmp fwds 2 insns if !condition */
3820 if (cc.test != Pct_ALWAYS) {
3821 /* bc !ct,cf,n_bytes>>2 */
3822 p = mkFormB(p, invertCondTest(cc.test), cc.flag, 8>>2, 0, 0);
3823 }
3824 /* vmr */
3825 p = mkFormVX( p, 4, v_dst, v_src, v_src, 1156 );
3826 goto done;
3827 }
3828
3829 case Pin_AvLdVSCR: { // mtvscr
3830 UInt v_src = vregNo(i->Pin.AvLdVSCR.src);
3831 p = mkFormVX( p, 4, 0, 0, v_src, 1604 );
3832 goto done;
3833 }
3834
3835 default:
3836 goto bad;
3837 }
3838
3839 bad:
3840 vex_printf("\n=> ");
3841 ppPPCInstr(i, mode64);
3842 vpanic("emit_PPCInstr");
3843 /*NOTREACHED*/
3844
3845 done:
3846 vassert(p - &buf[0] <= 32);
3847 return p - &buf[0];
3848 }
3849
3850 /*---------------------------------------------------------------*/
3851 /*--- end host_ppc_defs.c ---*/
3852 /*---------------------------------------------------------------*/
3853