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