2 /*---------------------------------------------------------------*/
3 /*--- begin host_ppc_defs.c ---*/
4 /*---------------------------------------------------------------*/
7 This file is part of Valgrind, a dynamic binary instrumentation
10 Copyright (C) 2004-2010 OpenWorks LLP
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.
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.
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
28 The GNU General Public License is contained in the file COPYING.
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.
36 #include "libvex_basictypes.h"
38 #include "libvex_trc_values.h"
40 #include "main_util.h"
41 #include "host_generic_regs.h"
42 #include "host_ppc_defs.h"
45 /* --------- Registers. --------- */
47 void ppHRegPPC ( HReg reg )
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)) {
64 /* But specific for real regs. */
65 switch (hregClass(reg)) {
68 vassert(r >= 0 && r < 32);
69 vex_printf("%s", ireg32_names[r]);
73 vassert(r >= 0 && r < 32);
74 vex_printf("%s", ireg32_names[r]);
78 vassert(r >= 0 && r < 32);
79 vex_printf("%%fr%d", r);
83 vassert(r >= 0 && r < 32);
84 vex_printf("%%v%d", r);
92 #define MkHRegGPR(_n, _mode64) \
93 mkHReg(_n, _mode64 ? HRcInt64 : HRcInt32, False)
95 HReg hregPPC_GPR0 ( Bool mode64 ) { return MkHRegGPR( 0, mode64); }
96 HReg hregPPC_GPR1 ( Bool mode64 ) { return MkHRegGPR( 1, mode64); }
97 HReg hregPPC_GPR2 ( Bool mode64 ) { return MkHRegGPR( 2, mode64); }
98 HReg hregPPC_GPR3 ( Bool mode64 ) { return MkHRegGPR( 3, mode64); }
99 HReg hregPPC_GPR4 ( Bool mode64 ) { return MkHRegGPR( 4, mode64); }
100 HReg hregPPC_GPR5 ( Bool mode64 ) { return MkHRegGPR( 5, mode64); }
101 HReg hregPPC_GPR6 ( Bool mode64 ) { return MkHRegGPR( 6, mode64); }
102 HReg hregPPC_GPR7 ( Bool mode64 ) { return MkHRegGPR( 7, mode64); }
103 HReg hregPPC_GPR8 ( Bool mode64 ) { return MkHRegGPR( 8, mode64); }
104 HReg hregPPC_GPR9 ( Bool mode64 ) { return MkHRegGPR( 9, mode64); }
105 HReg hregPPC_GPR10 ( Bool mode64 ) { return MkHRegGPR(10, mode64); }
106 HReg hregPPC_GPR11 ( Bool mode64 ) { return MkHRegGPR(11, mode64); }
107 HReg hregPPC_GPR12 ( Bool mode64 ) { return MkHRegGPR(12, mode64); }
108 HReg hregPPC_GPR13 ( Bool mode64 ) { return MkHRegGPR(13, mode64); }
109 HReg hregPPC_GPR14 ( Bool mode64 ) { return MkHRegGPR(14, mode64); }
110 HReg hregPPC_GPR15 ( Bool mode64 ) { return MkHRegGPR(15, mode64); }
111 HReg hregPPC_GPR16 ( Bool mode64 ) { return MkHRegGPR(16, mode64); }
112 HReg hregPPC_GPR17 ( Bool mode64 ) { return MkHRegGPR(17, mode64); }
113 HReg hregPPC_GPR18 ( Bool mode64 ) { return MkHRegGPR(18, mode64); }
114 HReg hregPPC_GPR19 ( Bool mode64 ) { return MkHRegGPR(19, mode64); }
115 HReg hregPPC_GPR20 ( Bool mode64 ) { return MkHRegGPR(20, mode64); }
116 HReg hregPPC_GPR21 ( Bool mode64 ) { return MkHRegGPR(21, mode64); }
117 HReg hregPPC_GPR22 ( Bool mode64 ) { return MkHRegGPR(22, mode64); }
118 HReg hregPPC_GPR23 ( Bool mode64 ) { return MkHRegGPR(23, mode64); }
119 HReg hregPPC_GPR24 ( Bool mode64 ) { return MkHRegGPR(24, mode64); }
120 HReg hregPPC_GPR25 ( Bool mode64 ) { return MkHRegGPR(25, mode64); }
121 HReg hregPPC_GPR26 ( Bool mode64 ) { return MkHRegGPR(26, mode64); }
122 HReg hregPPC_GPR27 ( Bool mode64 ) { return MkHRegGPR(27, mode64); }
123 HReg hregPPC_GPR28 ( Bool mode64 ) { return MkHRegGPR(28, mode64); }
124 HReg hregPPC_GPR29 ( Bool mode64 ) { return MkHRegGPR(29, mode64); }
125 HReg hregPPC_GPR30 ( Bool mode64 ) { return MkHRegGPR(30, mode64); }
126 HReg hregPPC_GPR31 ( Bool mode64 ) { return MkHRegGPR(31, mode64); }
130 HReg hregPPC_FPR0 ( void ) { return mkHReg( 0, HRcFlt64, False); }
131 HReg hregPPC_FPR1 ( void ) { return mkHReg( 1, HRcFlt64, False); }
132 HReg hregPPC_FPR2 ( void ) { return mkHReg( 2, HRcFlt64, False); }
133 HReg hregPPC_FPR3 ( void ) { return mkHReg( 3, HRcFlt64, False); }
134 HReg hregPPC_FPR4 ( void ) { return mkHReg( 4, HRcFlt64, False); }
135 HReg hregPPC_FPR5 ( void ) { return mkHReg( 5, HRcFlt64, False); }
136 HReg hregPPC_FPR6 ( void ) { return mkHReg( 6, HRcFlt64, False); }
137 HReg hregPPC_FPR7 ( void ) { return mkHReg( 7, HRcFlt64, False); }
138 HReg hregPPC_FPR8 ( void ) { return mkHReg( 8, HRcFlt64, False); }
139 HReg hregPPC_FPR9 ( void ) { return mkHReg( 9, HRcFlt64, False); }
140 HReg hregPPC_FPR10 ( void ) { return mkHReg(10, HRcFlt64, False); }
141 HReg hregPPC_FPR11 ( void ) { return mkHReg(11, HRcFlt64, False); }
142 HReg hregPPC_FPR12 ( void ) { return mkHReg(12, HRcFlt64, False); }
143 HReg hregPPC_FPR13 ( void ) { return mkHReg(13, HRcFlt64, False); }
144 HReg hregPPC_FPR14 ( void ) { return mkHReg(14, HRcFlt64, False); }
145 HReg hregPPC_FPR15 ( void ) { return mkHReg(15, HRcFlt64, False); }
146 HReg hregPPC_FPR16 ( void ) { return mkHReg(16, HRcFlt64, False); }
147 HReg hregPPC_FPR17 ( void ) { return mkHReg(17, HRcFlt64, False); }
148 HReg hregPPC_FPR18 ( void ) { return mkHReg(18, HRcFlt64, False); }
149 HReg hregPPC_FPR19 ( void ) { return mkHReg(19, HRcFlt64, False); }
150 HReg hregPPC_FPR20 ( void ) { return mkHReg(20, HRcFlt64, False); }
151 HReg hregPPC_FPR21 ( void ) { return mkHReg(21, HRcFlt64, False); }
152 HReg hregPPC_FPR22 ( void ) { return mkHReg(22, HRcFlt64, False); }
153 HReg hregPPC_FPR23 ( void ) { return mkHReg(23, HRcFlt64, False); }
154 HReg hregPPC_FPR24 ( void ) { return mkHReg(24, HRcFlt64, False); }
155 HReg hregPPC_FPR25 ( void ) { return mkHReg(25, HRcFlt64, False); }
156 HReg hregPPC_FPR26 ( void ) { return mkHReg(26, HRcFlt64, False); }
157 HReg hregPPC_FPR27 ( void ) { return mkHReg(27, HRcFlt64, False); }
158 HReg hregPPC_FPR28 ( void ) { return mkHReg(28, HRcFlt64, False); }
159 HReg hregPPC_FPR29 ( void ) { return mkHReg(29, HRcFlt64, False); }
160 HReg hregPPC_FPR30 ( void ) { return mkHReg(30, HRcFlt64, False); }
161 HReg hregPPC_FPR31 ( void ) { return mkHReg(31, HRcFlt64, False); }
163 HReg hregPPC_VR0 ( void ) { return mkHReg( 0, HRcVec128, False); }
164 HReg hregPPC_VR1 ( void ) { return mkHReg( 1, HRcVec128, False); }
165 HReg hregPPC_VR2 ( void ) { return mkHReg( 2, HRcVec128, False); }
166 HReg hregPPC_VR3 ( void ) { return mkHReg( 3, HRcVec128, False); }
167 HReg hregPPC_VR4 ( void ) { return mkHReg( 4, HRcVec128, False); }
168 HReg hregPPC_VR5 ( void ) { return mkHReg( 5, HRcVec128, False); }
169 HReg hregPPC_VR6 ( void ) { return mkHReg( 6, HRcVec128, False); }
170 HReg hregPPC_VR7 ( void ) { return mkHReg( 7, HRcVec128, False); }
171 HReg hregPPC_VR8 ( void ) { return mkHReg( 8, HRcVec128, False); }
172 HReg hregPPC_VR9 ( void ) { return mkHReg( 9, HRcVec128, False); }
173 HReg hregPPC_VR10 ( void ) { return mkHReg(10, HRcVec128, False); }
174 HReg hregPPC_VR11 ( void ) { return mkHReg(11, HRcVec128, False); }
175 HReg hregPPC_VR12 ( void ) { return mkHReg(12, HRcVec128, False); }
176 HReg hregPPC_VR13 ( void ) { return mkHReg(13, HRcVec128, False); }
177 HReg hregPPC_VR14 ( void ) { return mkHReg(14, HRcVec128, False); }
178 HReg hregPPC_VR15 ( void ) { return mkHReg(15, HRcVec128, False); }
179 HReg hregPPC_VR16 ( void ) { return mkHReg(16, HRcVec128, False); }
180 HReg hregPPC_VR17 ( void ) { return mkHReg(17, HRcVec128, False); }
181 HReg hregPPC_VR18 ( void ) { return mkHReg(18, HRcVec128, False); }
182 HReg hregPPC_VR19 ( void ) { return mkHReg(19, HRcVec128, False); }
183 HReg hregPPC_VR20 ( void ) { return mkHReg(20, HRcVec128, False); }
184 HReg hregPPC_VR21 ( void ) { return mkHReg(21, HRcVec128, False); }
185 HReg hregPPC_VR22 ( void ) { return mkHReg(22, HRcVec128, False); }
186 HReg hregPPC_VR23 ( void ) { return mkHReg(23, HRcVec128, False); }
187 HReg hregPPC_VR24 ( void ) { return mkHReg(24, HRcVec128, False); }
188 HReg hregPPC_VR25 ( void ) { return mkHReg(25, HRcVec128, False); }
189 HReg hregPPC_VR26 ( void ) { return mkHReg(26, HRcVec128, False); }
190 HReg hregPPC_VR27 ( void ) { return mkHReg(27, HRcVec128, False); }
191 HReg hregPPC_VR28 ( void ) { return mkHReg(28, HRcVec128, False); }
192 HReg hregPPC_VR29 ( void ) { return mkHReg(29, HRcVec128, False); }
193 HReg hregPPC_VR30 ( void ) { return mkHReg(30, HRcVec128, False); }
194 HReg hregPPC_VR31 ( void ) { return mkHReg(31, HRcVec128, False); }
196 void getAllocableRegs_PPC ( Int* nregs, HReg** arr, Bool mode64 )
200 *nregs = (32-9) + (32-24) + (32-24);
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);
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);
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
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.
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();
257 /* Same deal re Altivec */
258 /* For both ppc32-linux and ppc64-linux, v20-v31 are callee save.
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();
270 vassert(i == *nregs);
274 /* --------- Condition codes, Intel encoding. --------- */
276 HChar* showPPCCondCode ( PPCCondCode cond )
278 if (cond.test == Pct_ALWAYS) return "always";
282 return (cond.test == Pct_TRUE) ? "cr7.so=1" : "cr7.so=0";
284 return (cond.test == Pct_TRUE) ? "cr7.eq=1" : "cr7.eq=0";
286 return (cond.test == Pct_TRUE) ? "cr7.gt=1" : "cr7.gt=0";
288 return (cond.test == Pct_TRUE) ? "cr7.lt=1" : "cr7.lt=0";
291 default: vpanic("ppPPCCondCode");
295 /* construct condition code */
296 PPCCondCode mk_PPCCondCode ( PPCCondTest test, PPCCondFlag flag )
301 if (test == Pct_ALWAYS) {
302 vassert(flag == Pcf_NONE);
304 vassert(flag != Pcf_NONE);
309 /* false->true, true->false */
310 PPCCondTest invertCondTest ( PPCCondTest ct )
312 vassert(ct != Pct_ALWAYS);
313 return (ct == Pct_TRUE) ? Pct_FALSE : Pct_TRUE;
317 /* --------- PPCAMode: memory address expressions. --------- */
319 PPCAMode* PPCAMode_IR ( Int idx, HReg base ) {
320 PPCAMode* am = LibVEX_Alloc(sizeof(PPCAMode));
321 vassert(idx >= -0x8000 && idx < 0x8000);
323 am->Pam.IR.base = base;
324 am->Pam.IR.index = idx;
327 PPCAMode* PPCAMode_RR ( HReg idx, HReg base ) {
328 PPCAMode* am = LibVEX_Alloc(sizeof(PPCAMode));
330 am->Pam.RR.base = base;
331 am->Pam.RR.index = idx;
335 PPCAMode* dopyPPCAMode ( PPCAMode* am ) {
338 return PPCAMode_IR( am->Pam.IR.index, am->Pam.IR.base );
340 return PPCAMode_RR( am->Pam.RR.index, am->Pam.RR.base );
342 vpanic("dopyPPCAMode");
346 void ppPPCAMode ( PPCAMode* am ) {
349 if (am->Pam.IR.index == 0)
352 vex_printf("%d(", (Int)am->Pam.IR.index);
353 ppHRegPPC(am->Pam.IR.base);
357 ppHRegPPC(am->Pam.RR.base);
359 ppHRegPPC(am->Pam.RR.index);
362 vpanic("ppPPCAMode");
366 static void addRegUsage_PPCAMode ( HRegUsage* u, PPCAMode* am ) {
369 addHRegUse(u, HRmRead, am->Pam.IR.base);
372 addHRegUse(u, HRmRead, am->Pam.RR.base);
373 addHRegUse(u, HRmRead, am->Pam.RR.index);
376 vpanic("addRegUsage_PPCAMode");
380 static void mapRegs_PPCAMode ( HRegRemap* m, PPCAMode* am ) {
383 am->Pam.IR.base = lookupHRegRemap(m, am->Pam.IR.base);
386 am->Pam.RR.base = lookupHRegRemap(m, am->Pam.RR.base);
387 am->Pam.RR.index = lookupHRegRemap(m, am->Pam.RR.index);
390 vpanic("mapRegs_PPCAMode");
394 /* --------- Operand, which can be a reg or a u16/s16. --------- */
396 PPCRH* PPCRH_Imm ( Bool syned, UShort imm16 ) {
397 PPCRH* op = LibVEX_Alloc(sizeof(PPCRH));
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. */
404 vassert(imm16 != 0x8000);
405 vassert(syned == True || syned == False);
408 PPCRH* PPCRH_Reg ( HReg reg ) {
409 PPCRH* op = LibVEX_Alloc(sizeof(PPCRH));
411 op->Prh.Reg.reg = reg;
415 void ppPPCRH ( PPCRH* op ) {
418 if (op->Prh.Imm.syned)
419 vex_printf("%d", (Int)(Short)op->Prh.Imm.imm16);
421 vex_printf("%u", (UInt)(UShort)op->Prh.Imm.imm16);
424 ppHRegPPC(op->Prh.Reg.reg);
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
434 static void addRegUsage_PPCRH ( HRegUsage* u, PPCRH* op ) {
439 addHRegUse(u, HRmRead, op->Prh.Reg.reg);
442 vpanic("addRegUsage_PPCRH");
446 static void mapRegs_PPCRH ( HRegRemap* m, PPCRH* op ) {
451 op->Prh.Reg.reg = lookupHRegRemap(m, op->Prh.Reg.reg);
454 vpanic("mapRegs_PPCRH");
459 /* --------- Operand, which can be a reg or a u32/64. --------- */
461 PPCRI* PPCRI_Imm ( ULong imm64 ) {
462 PPCRI* op = LibVEX_Alloc(sizeof(PPCRI));
467 PPCRI* PPCRI_Reg ( HReg reg ) {
468 PPCRI* op = LibVEX_Alloc(sizeof(PPCRI));
474 void ppPPCRI ( PPCRI* dst ) {
477 vex_printf("0x%llx", dst->Pri.Imm);
480 ppHRegPPC(dst->Pri.Reg);
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. */
490 static void addRegUsage_PPCRI ( HRegUsage* u, PPCRI* dst ) {
495 addHRegUse(u, HRmRead, dst->Pri.Reg);
498 vpanic("addRegUsage_PPCRI");
502 static void mapRegs_PPCRI ( HRegRemap* m, PPCRI* dst ) {
507 dst->Pri.Reg = lookupHRegRemap(m, dst->Pri.Reg);
510 vpanic("mapRegs_PPCRI");
515 /* --------- Operand, which can be a vector reg or a simm5. --------- */
517 PPCVI5s* PPCVI5s_Imm ( Char simm5 ) {
518 PPCVI5s* op = LibVEX_Alloc(sizeof(PPCVI5s));
520 op->Pvi.Imm5s = simm5;
521 vassert(simm5 >= -16 && simm5 <= 15);
524 PPCVI5s* PPCVI5s_Reg ( HReg reg ) {
525 PPCVI5s* op = LibVEX_Alloc(sizeof(PPCVI5s));
528 vassert(hregClass(reg) == HRcVec128);
532 void ppPPCVI5s ( PPCVI5s* src ) {
535 vex_printf("%d", (Int)src->Pvi.Imm5s);
538 ppHRegPPC(src->Pvi.Reg);
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. */
548 static void addRegUsage_PPCVI5s ( HRegUsage* u, PPCVI5s* dst ) {
553 addHRegUse(u, HRmRead, dst->Pvi.Reg);
556 vpanic("addRegUsage_PPCVI5s");
560 static void mapRegs_PPCVI5s ( HRegRemap* m, PPCVI5s* dst ) {
565 dst->Pvi.Reg = lookupHRegRemap(m, dst->Pvi.Reg);
568 vpanic("mapRegs_PPCVI5s");
573 /* --------- Instructions. --------- */
575 HChar* showPPCUnaryOp ( PPCUnaryOp 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");
586 HChar* showPPCAluOp ( PPCAluOp op, Bool immR ) {
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");
597 HChar* showPPCShftOp ( PPCShftOp op, Bool immR, Bool sz32 ) {
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");
609 HChar* showPPCFpOp ( PPCFpOp 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");
637 HChar* showPPCAvOp ( PPCAvOp op ) {
641 case Pav_MOV: return "vmr"; /* Mov */
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";
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";
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
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
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
669 case Pav_AVGU: return "vavgu"; // b,h,w
670 case Pav_AVGS: return "vavgs"; // b,h,w
672 case Pav_MAXU: return "vmaxu"; // b,h,w
673 case Pav_MAXS: return "vmaxs"; // b,h,w
675 case Pav_MINU: return "vminu"; // b,h,w
676 case Pav_MINS: return "vmins"; // b,h,w
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
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
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";
697 case Pav_MRGHI: return "vmrgh"; // b,h,w
698 case Pav_MRGLO: return "vmrgl"; // b,h,w
700 default: vpanic("showPPCAvOp");
704 HChar* showPPCAvFpOp ( PPCAvFpOp 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";
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";
728 default: vpanic("showPPCAvFpOp");
732 PPCInstr* PPCInstr_LI ( HReg dst, ULong imm64, Bool mode64 )
734 PPCInstr* i = LibVEX_Alloc(sizeof(PPCInstr));
737 i->Pin.LI.imm64 = imm64;
739 vassert( (Long)imm64 == (Long)(Int)(UInt)imm64 );
742 PPCInstr* PPCInstr_Alu ( PPCAluOp op, HReg dst,
743 HReg srcL, PPCRH* srcR ) {
744 PPCInstr* i = LibVEX_Alloc(sizeof(PPCInstr));
747 i->Pin.Alu.dst = dst;
748 i->Pin.Alu.srcL = srcL;
749 i->Pin.Alu.srcR = srcR;
752 PPCInstr* PPCInstr_Shft ( PPCShftOp op, Bool sz32,
753 HReg dst, HReg srcL, PPCRH* srcR ) {
754 PPCInstr* i = LibVEX_Alloc(sizeof(PPCInstr));
757 i->Pin.Shft.sz32 = sz32;
758 i->Pin.Shft.dst = dst;
759 i->Pin.Shft.srcL = srcL;
760 i->Pin.Shft.srcR = 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;
774 PPCInstr* PPCInstr_Cmp ( Bool syned, Bool sz32,
775 UInt crfD, HReg srcL, PPCRH* srcR ) {
776 PPCInstr* i = LibVEX_Alloc(sizeof(PPCInstr));
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;
785 PPCInstr* PPCInstr_Unary ( PPCUnaryOp op, HReg dst, HReg src ) {
786 PPCInstr* i = LibVEX_Alloc(sizeof(PPCInstr));
788 i->Pin.Unary.op = op;
789 i->Pin.Unary.dst = dst;
790 i->Pin.Unary.src = src;
793 PPCInstr* PPCInstr_MulL ( Bool syned, Bool hi, Bool sz32,
794 HReg dst, HReg srcL, HReg srcR ) {
795 PPCInstr* i = LibVEX_Alloc(sizeof(PPCInstr));
797 i->Pin.MulL.syned = syned;
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
805 if (!hi) vassert(!syned);
808 PPCInstr* PPCInstr_Div ( Bool syned, Bool sz32,
809 HReg dst, HReg srcL, HReg srcR ) {
810 PPCInstr* i = LibVEX_Alloc(sizeof(PPCInstr));
812 i->Pin.Div.syned = syned;
813 i->Pin.Div.sz32 = sz32;
814 i->Pin.Div.dst = dst;
815 i->Pin.Div.srcL = srcL;
816 i->Pin.Div.srcR = srcR;
819 PPCInstr* PPCInstr_Call ( PPCCondCode cond,
820 Addr64 target, UInt argiregs ) {
822 PPCInstr* i = LibVEX_Alloc(sizeof(PPCInstr));
824 i->Pin.Call.cond = cond;
825 i->Pin.Call.target = target;
826 i->Pin.Call.argiregs = argiregs;
827 /* Only r3 .. r10 inclusive may be used as arg regs. Hence: */
828 mask = (1<<3)|(1<<4)|(1<<5)|(1<<6)|(1<<7)|(1<<8)|(1<<9)|(1<<10);
829 vassert(0 == (argiregs & ~mask));
832 PPCInstr* PPCInstr_Goto ( IRJumpKind jk,
833 PPCCondCode cond, PPCRI* dst ) {
834 PPCInstr* i = LibVEX_Alloc(sizeof(PPCInstr));
836 i->Pin.Goto.cond = cond;
837 i->Pin.Goto.dst = dst;
841 PPCInstr* PPCInstr_CMov ( PPCCondCode cond,
842 HReg dst, PPCRI* src ) {
843 PPCInstr* i = LibVEX_Alloc(sizeof(PPCInstr));
845 i->Pin.CMov.cond = cond;
846 i->Pin.CMov.src = src;
847 i->Pin.CMov.dst = dst;
848 vassert(cond.test != Pct_ALWAYS);
851 PPCInstr* PPCInstr_Load ( UChar sz,
852 HReg dst, PPCAMode* src, Bool mode64 ) {
853 PPCInstr* i = LibVEX_Alloc(sizeof(PPCInstr));
856 i->Pin.Load.src = src;
857 i->Pin.Load.dst = dst;
858 vassert(sz == 1 || sz == 2 || sz == 4 || sz == 8);
859 if (sz == 8) vassert(mode64);
862 PPCInstr* PPCInstr_LoadL ( UChar sz,
863 HReg dst, HReg src, Bool mode64 )
865 PPCInstr* i = LibVEX_Alloc(sizeof(PPCInstr));
867 i->Pin.LoadL.sz = sz;
868 i->Pin.LoadL.src = src;
869 i->Pin.LoadL.dst = dst;
870 vassert(sz == 4 || sz == 8);
871 if (sz == 8) vassert(mode64);
874 PPCInstr* PPCInstr_Store ( UChar sz, PPCAMode* dst, HReg src,
876 PPCInstr* i = LibVEX_Alloc(sizeof(PPCInstr));
878 i->Pin.Store.sz = sz;
879 i->Pin.Store.src = src;
880 i->Pin.Store.dst = dst;
881 vassert(sz == 1 || sz == 2 || sz == 4 || sz == 8);
882 if (sz == 8) vassert(mode64);
885 PPCInstr* PPCInstr_StoreC ( UChar sz, HReg dst, HReg src, Bool mode64 ) {
886 PPCInstr* i = LibVEX_Alloc(sizeof(PPCInstr));
888 i->Pin.StoreC.sz = sz;
889 i->Pin.StoreC.src = src;
890 i->Pin.StoreC.dst = dst;
891 vassert(sz == 4 || sz == 8);
892 if (sz == 8) vassert(mode64);
895 PPCInstr* PPCInstr_Set ( PPCCondCode cond, HReg dst ) {
896 PPCInstr* i = LibVEX_Alloc(sizeof(PPCInstr));
898 i->Pin.Set.cond = cond;
899 i->Pin.Set.dst = dst;
902 PPCInstr* PPCInstr_MfCR ( HReg dst )
904 PPCInstr* i = LibVEX_Alloc(sizeof(PPCInstr));
906 i->Pin.MfCR.dst = dst;
909 PPCInstr* PPCInstr_MFence ( void )
911 PPCInstr* i = LibVEX_Alloc(sizeof(PPCInstr));
916 PPCInstr* PPCInstr_FpUnary ( PPCFpOp op, HReg dst, HReg src ) {
917 PPCInstr* i = LibVEX_Alloc(sizeof(PPCInstr));
918 i->tag = Pin_FpUnary;
919 i->Pin.FpUnary.op = op;
920 i->Pin.FpUnary.dst = dst;
921 i->Pin.FpUnary.src = src;
924 PPCInstr* PPCInstr_FpBinary ( PPCFpOp op, HReg dst,
925 HReg srcL, HReg srcR ) {
926 PPCInstr* i = LibVEX_Alloc(sizeof(PPCInstr));
927 i->tag = Pin_FpBinary;
928 i->Pin.FpBinary.op = op;
929 i->Pin.FpBinary.dst = dst;
930 i->Pin.FpBinary.srcL = srcL;
931 i->Pin.FpBinary.srcR = srcR;
934 PPCInstr* PPCInstr_FpMulAcc ( PPCFpOp op, HReg dst, HReg srcML,
935 HReg srcMR, HReg srcAcc )
937 PPCInstr* i = LibVEX_Alloc(sizeof(PPCInstr));
938 i->tag = Pin_FpMulAcc;
939 i->Pin.FpMulAcc.op = op;
940 i->Pin.FpMulAcc.dst = dst;
941 i->Pin.FpMulAcc.srcML = srcML;
942 i->Pin.FpMulAcc.srcMR = srcMR;
943 i->Pin.FpMulAcc.srcAcc = srcAcc;
946 PPCInstr* PPCInstr_FpLdSt ( Bool isLoad, UChar sz,
947 HReg reg, PPCAMode* addr ) {
948 PPCInstr* i = LibVEX_Alloc(sizeof(PPCInstr));
950 i->Pin.FpLdSt.isLoad = isLoad;
951 i->Pin.FpLdSt.sz = sz;
952 i->Pin.FpLdSt.reg = reg;
953 i->Pin.FpLdSt.addr = addr;
954 vassert(sz == 4 || sz == 8);
957 PPCInstr* PPCInstr_FpSTFIW ( HReg addr, HReg data )
959 PPCInstr* i = LibVEX_Alloc(sizeof(PPCInstr));
960 i->tag = Pin_FpSTFIW;
961 i->Pin.FpSTFIW.addr = addr;
962 i->Pin.FpSTFIW.data = data;
965 PPCInstr* PPCInstr_FpRSP ( HReg dst, HReg src ) {
966 PPCInstr* i = LibVEX_Alloc(sizeof(PPCInstr));
968 i->Pin.FpRSP.dst = dst;
969 i->Pin.FpRSP.src = src;
974 Valid combo | fromI | int32 | syned | flt64 |
975 --------------------------------------------
977 --------------------------------------------
978 F64->I64U | n n n y |
979 --------------------------------------------
981 --------------------------------------------
982 F64->I64S | n n y y |
983 --------------------------------------------
985 --------------------------------------------
986 F64->I32U | n y n y |
987 --------------------------------------------
989 --------------------------------------------
990 F64->I32S | n y y y |
991 --------------------------------------------
992 I64U->F32 | y n n n |
993 --------------------------------------------
994 I64U->F64 | y n n y |
995 --------------------------------------------
997 --------------------------------------------
998 I64S->F64 | y n y y |
999 --------------------------------------------
1001 --------------------------------------------
1003 --------------------------------------------
1005 --------------------------------------------
1007 --------------------------------------------
1009 PPCInstr* PPCInstr_FpCftI ( Bool fromI, Bool int32, Bool syned,
1010 Bool flt64, HReg dst, HReg src ) {
1011 Bool tmp = fromI | int32 | syned | flt64;
1012 vassert(tmp == True || tmp == False); // iow, no high bits set
1013 UShort conversion = 0;
1014 conversion = (fromI << 3) | (int32 << 2) | (syned << 1) | flt64;
1015 switch (conversion) {
1016 // Supported conversion operations
1017 case 1: case 3: case 5: case 7:
1018 case 8: case 9: case 11:
1021 vpanic("PPCInstr_FpCftI(ppc_host)");
1023 PPCInstr* i = LibVEX_Alloc(sizeof(PPCInstr));
1024 i->tag = Pin_FpCftI;
1025 i->Pin.FpCftI.fromI = fromI;
1026 i->Pin.FpCftI.int32 = int32;
1027 i->Pin.FpCftI.syned = syned;
1028 i->Pin.FpCftI.flt64 = flt64;
1029 i->Pin.FpCftI.dst = dst;
1030 i->Pin.FpCftI.src = src;
1033 PPCInstr* PPCInstr_FpCMov ( PPCCondCode cond, HReg dst, HReg src ) {
1034 PPCInstr* i = LibVEX_Alloc(sizeof(PPCInstr));
1035 i->tag = Pin_FpCMov;
1036 i->Pin.FpCMov.cond = cond;
1037 i->Pin.FpCMov.dst = dst;
1038 i->Pin.FpCMov.src = src;
1039 vassert(cond.test != Pct_ALWAYS);
1042 PPCInstr* PPCInstr_FpLdFPSCR ( HReg src ) {
1043 PPCInstr* i = LibVEX_Alloc(sizeof(PPCInstr));
1044 i->tag = Pin_FpLdFPSCR;
1045 i->Pin.FpLdFPSCR.src = src;
1048 PPCInstr* PPCInstr_FpCmp ( HReg dst, HReg srcL, HReg srcR ) {
1049 PPCInstr* i = LibVEX_Alloc(sizeof(PPCInstr));
1051 i->Pin.FpCmp.dst = dst;
1052 i->Pin.FpCmp.srcL = srcL;
1053 i->Pin.FpCmp.srcR = srcR;
1057 /* Read/Write Link Register */
1058 PPCInstr* PPCInstr_RdWrLR ( Bool wrLR, HReg gpr ) {
1059 PPCInstr* i = LibVEX_Alloc(sizeof(PPCInstr));
1060 i->tag = Pin_RdWrLR;
1061 i->Pin.RdWrLR.wrLR = wrLR;
1062 i->Pin.RdWrLR.gpr = gpr;
1067 PPCInstr* PPCInstr_AvLdSt ( Bool isLoad, UChar sz,
1068 HReg reg, PPCAMode* addr ) {
1069 PPCInstr* i = LibVEX_Alloc(sizeof(PPCInstr));
1070 i->tag = Pin_AvLdSt;
1071 i->Pin.AvLdSt.isLoad = isLoad;
1072 i->Pin.AvLdSt.sz = sz;
1073 i->Pin.AvLdSt.reg = reg;
1074 i->Pin.AvLdSt.addr = addr;
1077 PPCInstr* PPCInstr_AvUnary ( PPCAvOp op, HReg dst, HReg src ) {
1078 PPCInstr* i = LibVEX_Alloc(sizeof(PPCInstr));
1079 i->tag = Pin_AvUnary;
1080 i->Pin.AvUnary.op = op;
1081 i->Pin.AvUnary.dst = dst;
1082 i->Pin.AvUnary.src = src;
1085 PPCInstr* PPCInstr_AvBinary ( PPCAvOp op, HReg dst,
1086 HReg srcL, HReg srcR ) {
1087 PPCInstr* i = LibVEX_Alloc(sizeof(PPCInstr));
1088 i->tag = Pin_AvBinary;
1089 i->Pin.AvBinary.op = op;
1090 i->Pin.AvBinary.dst = dst;
1091 i->Pin.AvBinary.srcL = srcL;
1092 i->Pin.AvBinary.srcR = srcR;
1095 PPCInstr* PPCInstr_AvBin8x16 ( PPCAvOp op, HReg dst,
1096 HReg srcL, HReg srcR ) {
1097 PPCInstr* i = LibVEX_Alloc(sizeof(PPCInstr));
1098 i->tag = Pin_AvBin8x16;
1099 i->Pin.AvBin8x16.op = op;
1100 i->Pin.AvBin8x16.dst = dst;
1101 i->Pin.AvBin8x16.srcL = srcL;
1102 i->Pin.AvBin8x16.srcR = srcR;
1105 PPCInstr* PPCInstr_AvBin16x8 ( PPCAvOp op, HReg dst,
1106 HReg srcL, HReg srcR ) {
1107 PPCInstr* i = LibVEX_Alloc(sizeof(PPCInstr));
1108 i->tag = Pin_AvBin16x8;
1109 i->Pin.AvBin16x8.op = op;
1110 i->Pin.AvBin16x8.dst = dst;
1111 i->Pin.AvBin16x8.srcL = srcL;
1112 i->Pin.AvBin16x8.srcR = srcR;
1115 PPCInstr* PPCInstr_AvBin32x4 ( PPCAvOp op, HReg dst,
1116 HReg srcL, HReg srcR ) {
1117 PPCInstr* i = LibVEX_Alloc(sizeof(PPCInstr));
1118 i->tag = Pin_AvBin32x4;
1119 i->Pin.AvBin32x4.op = op;
1120 i->Pin.AvBin32x4.dst = dst;
1121 i->Pin.AvBin32x4.srcL = srcL;
1122 i->Pin.AvBin32x4.srcR = srcR;
1125 PPCInstr* PPCInstr_AvBin32Fx4 ( PPCAvFpOp op, HReg dst,
1126 HReg srcL, HReg srcR ) {
1127 PPCInstr* i = LibVEX_Alloc(sizeof(PPCInstr));
1128 i->tag = Pin_AvBin32Fx4;
1129 i->Pin.AvBin32Fx4.op = op;
1130 i->Pin.AvBin32Fx4.dst = dst;
1131 i->Pin.AvBin32Fx4.srcL = srcL;
1132 i->Pin.AvBin32Fx4.srcR = srcR;
1135 PPCInstr* PPCInstr_AvUn32Fx4 ( PPCAvFpOp op, HReg dst, HReg src ) {
1136 PPCInstr* i = LibVEX_Alloc(sizeof(PPCInstr));
1137 i->tag = Pin_AvUn32Fx4;
1138 i->Pin.AvUn32Fx4.op = op;
1139 i->Pin.AvUn32Fx4.dst = dst;
1140 i->Pin.AvUn32Fx4.src = src;
1143 PPCInstr* PPCInstr_AvPerm ( HReg dst, HReg srcL, HReg srcR, HReg ctl ) {
1144 PPCInstr* i = LibVEX_Alloc(sizeof(PPCInstr));
1145 i->tag = Pin_AvPerm;
1146 i->Pin.AvPerm.dst = dst;
1147 i->Pin.AvPerm.srcL = srcL;
1148 i->Pin.AvPerm.srcR = srcR;
1149 i->Pin.AvPerm.ctl = ctl;
1152 PPCInstr* PPCInstr_AvSel ( HReg ctl, HReg dst, HReg srcL, HReg srcR ) {
1153 PPCInstr* i = LibVEX_Alloc(sizeof(PPCInstr));
1155 i->Pin.AvSel.ctl = ctl;
1156 i->Pin.AvSel.dst = dst;
1157 i->Pin.AvSel.srcL = srcL;
1158 i->Pin.AvSel.srcR = srcR;
1161 PPCInstr* PPCInstr_AvShlDbl ( UChar shift, HReg dst,
1162 HReg srcL, HReg srcR ) {
1163 PPCInstr* i = LibVEX_Alloc(sizeof(PPCInstr));
1164 i->tag = Pin_AvShlDbl;
1165 i->Pin.AvShlDbl.shift = shift;
1166 i->Pin.AvShlDbl.dst = dst;
1167 i->Pin.AvShlDbl.srcL = srcL;
1168 i->Pin.AvShlDbl.srcR = srcR;
1171 PPCInstr* PPCInstr_AvSplat ( UChar sz, HReg dst, PPCVI5s* src ) {
1172 PPCInstr* i = LibVEX_Alloc(sizeof(PPCInstr));
1173 i->tag = Pin_AvSplat;
1174 i->Pin.AvSplat.sz = sz;
1175 i->Pin.AvSplat.dst = dst;
1176 i->Pin.AvSplat.src = src;
1179 PPCInstr* PPCInstr_AvCMov ( PPCCondCode cond, HReg dst, HReg src ) {
1180 PPCInstr* i = LibVEX_Alloc(sizeof(PPCInstr));
1181 i->tag = Pin_AvCMov;
1182 i->Pin.AvCMov.cond = cond;
1183 i->Pin.AvCMov.dst = dst;
1184 i->Pin.AvCMov.src = src;
1185 vassert(cond.test != Pct_ALWAYS);
1188 PPCInstr* PPCInstr_AvLdVSCR ( HReg src ) {
1189 PPCInstr* i = LibVEX_Alloc(sizeof(PPCInstr));
1190 i->tag = Pin_AvLdVSCR;
1191 i->Pin.AvLdVSCR.src = src;
1196 /* Pretty Print instructions */
1197 static void ppLoadImm ( HReg dst, ULong imm, Bool mode64 ) {
1198 vex_printf("li_word ");
1201 vex_printf(",0x%08x", (UInt)imm);
1203 vex_printf(",0x%016llx", imm);
1207 static void ppMovReg ( HReg dst, HReg src ) {
1208 if (hregNumber(dst) != hregNumber(src)) {
1216 void ppPPCInstr ( PPCInstr* i, Bool mode64 )
1220 ppLoadImm(i->Pin.LI.dst, i->Pin.LI.imm64, mode64);
1223 HReg r_srcL = i->Pin.Alu.srcL;
1224 PPCRH* rh_srcR = i->Pin.Alu.srcR;
1225 /* special-case "mr" */
1226 if (i->Pin.Alu.op == Palu_OR && // or Rd,Rs,Rs == mr Rd,Rs
1227 rh_srcR->tag == Prh_Reg &&
1228 rh_srcR->Prh.Reg.reg == r_srcL) {
1230 ppHRegPPC(i->Pin.Alu.dst);
1235 /* special-case "li" */
1236 if (i->Pin.Alu.op == Palu_ADD && // addi Rd,0,imm == li Rd,imm
1237 rh_srcR->tag == Prh_Imm &&
1238 hregNumber(r_srcL) == 0) {
1240 ppHRegPPC(i->Pin.Alu.dst);
1246 vex_printf("%s ", showPPCAluOp(i->Pin.Alu.op,
1247 toBool(rh_srcR->tag == Prh_Imm)));
1248 ppHRegPPC(i->Pin.Alu.dst);
1256 HReg r_srcL = i->Pin.Shft.srcL;
1257 PPCRH* rh_srcR = i->Pin.Shft.srcR;
1258 vex_printf("%s ", showPPCShftOp(i->Pin.Shft.op,
1259 toBool(rh_srcR->tag == Prh_Imm),
1261 ppHRegPPC(i->Pin.Shft.dst);
1270 i->Pin.AddSubC.isAdd ? "add" : "sub",
1271 i->Pin.AddSubC.setC ? "c" : "e");
1272 ppHRegPPC(i->Pin.AddSubC.dst);
1274 ppHRegPPC(i->Pin.AddSubC.srcL);
1276 ppHRegPPC(i->Pin.AddSubC.srcR);
1279 vex_printf("%s%c%s %%cr%u,",
1280 i->Pin.Cmp.syned ? "cmp" : "cmpl",
1281 i->Pin.Cmp.sz32 ? 'w' : 'd',
1282 i->Pin.Cmp.srcR->tag == Prh_Imm ? "i" : "",
1284 ppHRegPPC(i->Pin.Cmp.srcL);
1286 ppPPCRH(i->Pin.Cmp.srcR);
1289 vex_printf("%s ", showPPCUnaryOp(i->Pin.Unary.op));
1290 ppHRegPPC(i->Pin.Unary.dst);
1292 ppHRegPPC(i->Pin.Unary.src);
1295 vex_printf("mul%c%c%s ",
1296 i->Pin.MulL.hi ? 'h' : 'l',
1297 i->Pin.MulL.sz32 ? 'w' : 'd',
1298 i->Pin.MulL.hi ? (i->Pin.MulL.syned ? "s" : "u") : "");
1299 ppHRegPPC(i->Pin.MulL.dst);
1301 ppHRegPPC(i->Pin.MulL.srcL);
1303 ppHRegPPC(i->Pin.MulL.srcR);
1306 vex_printf("div%c%s ",
1307 i->Pin.Div.sz32 ? 'w' : 'd',
1308 i->Pin.Div.syned ? "" : "u");
1309 ppHRegPPC(i->Pin.Div.dst);
1311 ppHRegPPC(i->Pin.Div.srcL);
1313 ppHRegPPC(i->Pin.Div.srcR);
1317 vex_printf("call: ");
1318 if (i->Pin.Call.cond.test != Pct_ALWAYS) {
1319 vex_printf("if (%s) ", showPPCCondCode(i->Pin.Call.cond));
1322 ppLoadImm(hregPPC_GPR10(mode64), i->Pin.Call.target, mode64);
1323 vex_printf(" ; mtctr r10 ; bctrl [");
1324 for (n = 0; n < 32; n++) {
1325 if (i->Pin.Call.argiregs & (1<<n)) {
1326 vex_printf("r%d", n);
1327 if ((i->Pin.Call.argiregs >> n) > 1)
1335 vex_printf("goto: ");
1336 if (i->Pin.Goto.cond.test != Pct_ALWAYS) {
1337 vex_printf("if (%s) ", showPPCCondCode(i->Pin.Goto.cond));
1340 if (i->Pin.Goto.jk != Ijk_Boring
1341 && i->Pin.Goto.jk != Ijk_Call
1342 && i->Pin.Goto.jk != Ijk_Ret) {
1343 vex_printf("li %%r31,$");
1344 ppIRJumpKind(i->Pin.Goto.jk);
1347 if (i->Pin.Goto.dst->tag == Pri_Imm) {
1348 ppLoadImm(hregPPC_GPR3(mode64), i->Pin.Goto.dst->Pri.Imm,
1351 ppMovReg(hregPPC_GPR3(mode64), i->Pin.Goto.dst->Pri.Reg);
1353 vex_printf(" ; blr }");
1356 vex_printf("cmov (%s) ", showPPCCondCode(i->Pin.CMov.cond));
1357 ppHRegPPC(i->Pin.CMov.dst);
1359 ppPPCRI(i->Pin.CMov.src);
1361 if (i->Pin.CMov.cond.test != Pct_ALWAYS) {
1362 vex_printf("if (%s) ", showPPCCondCode(i->Pin.CMov.cond));
1365 if (i->Pin.CMov.src->tag == Pri_Imm) {
1366 ppLoadImm(i->Pin.CMov.dst, i->Pin.CMov.src->Pri.Imm, mode64);
1368 ppMovReg(i->Pin.CMov.dst, i->Pin.CMov.src->Pri.Reg);
1373 Bool idxd = toBool(i->Pin.Load.src->tag == Pam_RR);
1374 UChar sz = i->Pin.Load.sz;
1375 UChar c_sz = sz==1 ? 'b' : sz==2 ? 'h' : sz==4 ? 'w' : 'd';
1376 vex_printf("l%c%s%s ", c_sz, sz==8 ? "" : "z", idxd ? "x" : "" );
1377 ppHRegPPC(i->Pin.Load.dst);
1379 ppPPCAMode(i->Pin.Load.src);
1383 vex_printf("l%carx ", i->Pin.LoadL.sz==4 ? 'w' : 'd');
1384 ppHRegPPC(i->Pin.LoadL.dst);
1385 vex_printf(",%%r0,");
1386 ppHRegPPC(i->Pin.LoadL.src);
1389 UChar sz = i->Pin.Store.sz;
1390 Bool idxd = toBool(i->Pin.Store.dst->tag == Pam_RR);
1391 UChar c_sz = sz==1 ? 'b' : sz==2 ? 'h' : sz==4 ? 'w' : /*8*/ 'd';
1392 vex_printf("st%c%s ", c_sz, idxd ? "x" : "" );
1393 ppHRegPPC(i->Pin.Store.src);
1395 ppPPCAMode(i->Pin.Store.dst);
1399 vex_printf("st%ccx. ", i->Pin.StoreC.sz==4 ? 'w' : 'd');
1400 ppHRegPPC(i->Pin.StoreC.src);
1401 vex_printf(",%%r0,");
1402 ppHRegPPC(i->Pin.StoreC.dst);
1405 PPCCondCode cc = i->Pin.Set.cond;
1406 vex_printf("set (%s),", showPPCCondCode(cc));
1407 ppHRegPPC(i->Pin.Set.dst);
1408 if (cc.test == Pct_ALWAYS) {
1409 vex_printf(": { li ");
1410 ppHRegPPC(i->Pin.Set.dst);
1413 vex_printf(": { mfcr r0 ; rlwinm ");
1414 ppHRegPPC(i->Pin.Set.dst);
1415 vex_printf(",r0,%u,31,31", cc.flag+1);
1416 if (cc.test == Pct_FALSE) {
1417 vex_printf("; xori ");
1418 ppHRegPPC(i->Pin.Set.dst);
1420 ppHRegPPC(i->Pin.Set.dst);
1428 vex_printf("mfcr ");
1429 ppHRegPPC(i->Pin.MfCR.dst);
1432 vex_printf("mfence (=sync)");
1436 vex_printf("%s ", showPPCFpOp(i->Pin.FpUnary.op));
1437 ppHRegPPC(i->Pin.FpUnary.dst);
1439 ppHRegPPC(i->Pin.FpUnary.src);
1442 vex_printf("%s ", showPPCFpOp(i->Pin.FpBinary.op));
1443 ppHRegPPC(i->Pin.FpBinary.dst);
1445 ppHRegPPC(i->Pin.FpBinary.srcL);
1447 ppHRegPPC(i->Pin.FpBinary.srcR);
1450 vex_printf("%s ", showPPCFpOp(i->Pin.FpMulAcc.op));
1451 ppHRegPPC(i->Pin.FpMulAcc.dst);
1453 ppHRegPPC(i->Pin.FpMulAcc.srcML);
1455 ppHRegPPC(i->Pin.FpMulAcc.srcMR);
1457 ppHRegPPC(i->Pin.FpMulAcc.srcAcc);
1460 UChar sz = i->Pin.FpLdSt.sz;
1461 Bool idxd = toBool(i->Pin.FpLdSt.addr->tag == Pam_RR);
1462 if (i->Pin.FpLdSt.isLoad) {
1463 vex_printf("lf%c%s ",
1464 (sz==4 ? 's' : 'd'),
1466 ppHRegPPC(i->Pin.FpLdSt.reg);
1468 ppPPCAMode(i->Pin.FpLdSt.addr);
1470 vex_printf("stf%c%s ",
1471 (sz==4 ? 's' : 'd'),
1473 ppHRegPPC(i->Pin.FpLdSt.reg);
1475 ppPPCAMode(i->Pin.FpLdSt.addr);
1480 vex_printf("stfiwz ");
1481 ppHRegPPC(i->Pin.FpSTFIW.data);
1483 ppHRegPPC(i->Pin.FpSTFIW.addr);
1487 vex_printf("frsp ");
1488 ppHRegPPC(i->Pin.FpRSP.dst);
1490 ppHRegPPC(i->Pin.FpRSP.src);
1493 HChar* str = "fc?????";
1494 if (i->Pin.FpCftI.fromI == False && i->Pin.FpCftI.int32 == False)
1497 if (i->Pin.FpCftI.fromI == False && i->Pin.FpCftI.int32 == True)
1500 if (i->Pin.FpCftI.fromI == True && i->Pin.FpCftI.int32 == False) {
1501 if (i->Pin.FpCftI.syned == True)
1503 else if (i->Pin.FpCftI.flt64 == True)
1508 vex_printf("%s ", str);
1509 ppHRegPPC(i->Pin.FpCftI.dst);
1511 ppHRegPPC(i->Pin.FpCftI.src);
1515 vex_printf("fpcmov (%s) ", showPPCCondCode(i->Pin.FpCMov.cond));
1516 ppHRegPPC(i->Pin.FpCMov.dst);
1518 ppHRegPPC(i->Pin.FpCMov.src);
1520 vex_printf("if (fr_dst != fr_src) { ");
1521 if (i->Pin.FpCMov.cond.test != Pct_ALWAYS) {
1522 vex_printf("if (%s) { ", showPPCCondCode(i->Pin.FpCMov.cond));
1525 ppHRegPPC(i->Pin.FpCMov.dst);
1527 ppHRegPPC(i->Pin.FpCMov.src);
1528 if (i->Pin.FpCMov.cond.test != Pct_ALWAYS)
1533 vex_printf("mtfsf 0xFF,");
1534 ppHRegPPC(i->Pin.FpLdFPSCR.src);
1537 vex_printf("fcmpo %%cr1,");
1538 ppHRegPPC(i->Pin.FpCmp.srcL);
1540 ppHRegPPC(i->Pin.FpCmp.srcR);
1541 vex_printf("; mfcr ");
1542 ppHRegPPC(i->Pin.FpCmp.dst);
1543 vex_printf("; rlwinm ");
1544 ppHRegPPC(i->Pin.FpCmp.dst);
1546 ppHRegPPC(i->Pin.FpCmp.dst);
1547 vex_printf(",8,28,31");
1551 vex_printf("%s ", i->Pin.RdWrLR.wrLR ? "mtlr" : "mflr");
1552 ppHRegPPC(i->Pin.RdWrLR.gpr);
1556 UChar sz = i->Pin.AvLdSt.sz;
1558 if (i->Pin.AvLdSt.addr->tag == Pam_IR) {
1559 ppLoadImm(hregPPC_GPR30(mode64),
1560 i->Pin.AvLdSt.addr->Pam.RR.index, mode64);
1563 str_size = sz==1 ? "eb" : sz==2 ? "eh" : sz==4 ? "ew" : "";
1564 if (i->Pin.AvLdSt.isLoad)
1565 vex_printf("lv%sx ", str_size);
1567 vex_printf("stv%sx ", str_size);
1568 ppHRegPPC(i->Pin.AvLdSt.reg);
1570 if (i->Pin.AvLdSt.addr->tag == Pam_IR)
1571 vex_printf("%%r30");
1573 ppHRegPPC(i->Pin.AvLdSt.addr->Pam.RR.index);
1575 ppHRegPPC(i->Pin.AvLdSt.addr->Pam.RR.base);
1579 vex_printf("%s ", showPPCAvOp(i->Pin.AvUnary.op));
1580 ppHRegPPC(i->Pin.AvUnary.dst);
1582 ppHRegPPC(i->Pin.AvUnary.src);
1585 vex_printf("%s ", showPPCAvOp(i->Pin.AvBinary.op));
1586 ppHRegPPC(i->Pin.AvBinary.dst);
1588 ppHRegPPC(i->Pin.AvBinary.srcL);
1590 ppHRegPPC(i->Pin.AvBinary.srcR);
1593 vex_printf("%s(b) ", showPPCAvOp(i->Pin.AvBin8x16.op));
1594 ppHRegPPC(i->Pin.AvBin8x16.dst);
1596 ppHRegPPC(i->Pin.AvBin8x16.srcL);
1598 ppHRegPPC(i->Pin.AvBin8x16.srcR);
1601 vex_printf("%s(h) ", showPPCAvOp(i->Pin.AvBin16x8.op));
1602 ppHRegPPC(i->Pin.AvBin16x8.dst);
1604 ppHRegPPC(i->Pin.AvBin16x8.srcL);
1606 ppHRegPPC(i->Pin.AvBin16x8.srcR);
1609 vex_printf("%s(w) ", showPPCAvOp(i->Pin.AvBin32x4.op));
1610 ppHRegPPC(i->Pin.AvBin32x4.dst);
1612 ppHRegPPC(i->Pin.AvBin32x4.srcL);
1614 ppHRegPPC(i->Pin.AvBin32x4.srcR);
1616 case Pin_AvBin32Fx4:
1617 vex_printf("%s ", showPPCAvFpOp(i->Pin.AvBin32Fx4.op));
1618 ppHRegPPC(i->Pin.AvBin32Fx4.dst);
1620 ppHRegPPC(i->Pin.AvBin32Fx4.srcL);
1622 ppHRegPPC(i->Pin.AvBin32Fx4.srcR);
1625 vex_printf("%s ", showPPCAvFpOp(i->Pin.AvUn32Fx4.op));
1626 ppHRegPPC(i->Pin.AvUn32Fx4.dst);
1628 ppHRegPPC(i->Pin.AvUn32Fx4.src);
1631 vex_printf("vperm ");
1632 ppHRegPPC(i->Pin.AvPerm.dst);
1634 ppHRegPPC(i->Pin.AvPerm.srcL);
1636 ppHRegPPC(i->Pin.AvPerm.srcR);
1638 ppHRegPPC(i->Pin.AvPerm.ctl);
1642 vex_printf("vsel ");
1643 ppHRegPPC(i->Pin.AvSel.dst);
1645 ppHRegPPC(i->Pin.AvSel.srcL);
1647 ppHRegPPC(i->Pin.AvSel.srcR);
1649 ppHRegPPC(i->Pin.AvSel.ctl);
1653 vex_printf("vsldoi ");
1654 ppHRegPPC(i->Pin.AvShlDbl.dst);
1656 ppHRegPPC(i->Pin.AvShlDbl.srcL);
1658 ppHRegPPC(i->Pin.AvShlDbl.srcR);
1659 vex_printf(",%d", i->Pin.AvShlDbl.shift);
1663 UChar sz = i->Pin.AvSplat.sz;
1664 UChar ch_sz = toUChar( (sz == 8) ? 'b' : (sz == 16) ? 'h' : 'w' );
1665 vex_printf("vsplt%s%c ",
1666 i->Pin.AvSplat.src->tag == Pvi_Imm ? "is" : "", ch_sz);
1667 ppHRegPPC(i->Pin.AvSplat.dst);
1669 ppPPCVI5s(i->Pin.AvSplat.src);
1670 if (i->Pin.AvSplat.src->tag == Pvi_Reg)
1671 vex_printf(", %d", (128/sz)-1); /* louis lane */
1676 vex_printf("avcmov (%s) ", showPPCCondCode(i->Pin.AvCMov.cond));
1677 ppHRegPPC(i->Pin.AvCMov.dst);
1679 ppHRegPPC(i->Pin.AvCMov.src);
1681 vex_printf("if (v_dst != v_src) { ");
1682 if (i->Pin.AvCMov.cond.test != Pct_ALWAYS) {
1683 vex_printf("if (%s) { ", showPPCCondCode(i->Pin.AvCMov.cond));
1686 ppHRegPPC(i->Pin.AvCMov.dst);
1688 ppHRegPPC(i->Pin.AvCMov.src);
1689 if (i->Pin.FpCMov.cond.test != Pct_ALWAYS)
1695 vex_printf("mtvscr ");
1696 ppHRegPPC(i->Pin.AvLdVSCR.src);
1700 vex_printf("\nppPPCInstr: No such tag(%d)\n", (Int)i->tag);
1701 vpanic("ppPPCInstr");
1705 /* --------- Helpers for register allocation. --------- */
1707 void getRegUsage_PPCInstr ( HRegUsage* u, PPCInstr* i, Bool mode64 )
1712 addHRegUse(u, HRmWrite, i->Pin.LI.dst);
1715 addHRegUse(u, HRmRead, i->Pin.Alu.srcL);
1716 addRegUsage_PPCRH(u, i->Pin.Alu.srcR);
1717 addHRegUse(u, HRmWrite, i->Pin.Alu.dst);
1720 addHRegUse(u, HRmRead, i->Pin.Shft.srcL);
1721 addRegUsage_PPCRH(u, i->Pin.Shft.srcR);
1722 addHRegUse(u, HRmWrite, i->Pin.Shft.dst);
1725 addHRegUse(u, HRmWrite, i->Pin.AddSubC.dst);
1726 addHRegUse(u, HRmRead, i->Pin.AddSubC.srcL);
1727 addHRegUse(u, HRmRead, i->Pin.AddSubC.srcR);
1730 addHRegUse(u, HRmRead, i->Pin.Cmp.srcL);
1731 addRegUsage_PPCRH(u, i->Pin.Cmp.srcR);
1734 addHRegUse(u, HRmWrite, i->Pin.Unary.dst);
1735 addHRegUse(u, HRmRead, i->Pin.Unary.src);
1738 addHRegUse(u, HRmWrite, i->Pin.MulL.dst);
1739 addHRegUse(u, HRmRead, i->Pin.MulL.srcL);
1740 addHRegUse(u, HRmRead, i->Pin.MulL.srcR);
1743 addHRegUse(u, HRmWrite, i->Pin.Div.dst);
1744 addHRegUse(u, HRmRead, i->Pin.Div.srcL);
1745 addHRegUse(u, HRmRead, i->Pin.Div.srcR);
1749 /* This is a bit subtle. */
1750 /* First off, claim it trashes all the caller-saved regs
1751 which fall within the register allocator's jurisdiction.
1752 These I believe to be:
1756 /* XXXXXXXXXXXXXXXXX BUG! This doesn't say anything about the FP
1757 or Altivec registers. We get away with this ONLY because
1758 getAllocatableRegs_PPC gives the allocator callee-saved fp
1759 and Altivec regs, and no caller-save ones. */
1760 addHRegUse(u, HRmWrite, hregPPC_GPR3(mode64));
1761 addHRegUse(u, HRmWrite, hregPPC_GPR4(mode64));
1762 addHRegUse(u, HRmWrite, hregPPC_GPR5(mode64));
1763 addHRegUse(u, HRmWrite, hregPPC_GPR6(mode64));
1764 addHRegUse(u, HRmWrite, hregPPC_GPR7(mode64));
1765 addHRegUse(u, HRmWrite, hregPPC_GPR8(mode64));
1766 addHRegUse(u, HRmWrite, hregPPC_GPR9(mode64));
1767 addHRegUse(u, HRmWrite, hregPPC_GPR10(mode64));
1769 addHRegUse(u, HRmWrite, hregPPC_GPR11(mode64));
1770 addHRegUse(u, HRmWrite, hregPPC_GPR12(mode64));
1773 /* Now we have to state any parameter-carrying registers
1774 which might be read. This depends on the argiregs field. */
1775 argir = i->Pin.Call.argiregs;
1776 if (argir &(1<<10)) addHRegUse(u, HRmRead, hregPPC_GPR10(mode64));
1777 if (argir & (1<<9)) addHRegUse(u, HRmRead, hregPPC_GPR9(mode64));
1778 if (argir & (1<<8)) addHRegUse(u, HRmRead, hregPPC_GPR8(mode64));
1779 if (argir & (1<<7)) addHRegUse(u, HRmRead, hregPPC_GPR7(mode64));
1780 if (argir & (1<<6)) addHRegUse(u, HRmRead, hregPPC_GPR6(mode64));
1781 if (argir & (1<<5)) addHRegUse(u, HRmRead, hregPPC_GPR5(mode64));
1782 if (argir & (1<<4)) addHRegUse(u, HRmRead, hregPPC_GPR4(mode64));
1783 if (argir & (1<<3)) addHRegUse(u, HRmRead, hregPPC_GPR3(mode64));
1785 vassert(0 == (argir & ~((1<<3)|(1<<4)|(1<<5)|(1<<6)
1786 |(1<<7)|(1<<8)|(1<<9)|(1<<10))));
1788 /* Finally, there is the issue that the insn trashes a
1789 register because the literal target address has to be
1790 loaded into a register. %r10 seems a suitable victim.
1791 (Can't use %r0, as some insns interpret it as value zero). */
1792 addHRegUse(u, HRmWrite, hregPPC_GPR10(mode64));
1793 /* Upshot of this is that the assembler really must use %r10,
1794 and no other, as a destination temporary. */
1798 addRegUsage_PPCRI(u, i->Pin.Goto.dst);
1799 /* GPR3 holds destination address from Pin_Goto */
1800 addHRegUse(u, HRmWrite, hregPPC_GPR3(mode64));
1801 if (i->Pin.Goto.jk != Ijk_Boring
1802 && i->Pin.Goto.jk != Ijk_Call
1803 && i->Pin.Goto.jk != Ijk_Ret)
1804 /* note, this is irrelevant since the guest state pointer
1805 register is not actually available to the allocator.
1807 addHRegUse(u, HRmWrite, GuestStatePtr(mode64));
1810 addRegUsage_PPCRI(u, i->Pin.CMov.src);
1811 addHRegUse(u, HRmWrite, i->Pin.CMov.dst);
1814 addRegUsage_PPCAMode(u, i->Pin.Load.src);
1815 addHRegUse(u, HRmWrite, i->Pin.Load.dst);
1818 addHRegUse(u, HRmRead, i->Pin.LoadL.src);
1819 addHRegUse(u, HRmWrite, i->Pin.LoadL.dst);
1822 addHRegUse(u, HRmRead, i->Pin.Store.src);
1823 addRegUsage_PPCAMode(u, i->Pin.Store.dst);
1826 addHRegUse(u, HRmRead, i->Pin.StoreC.src);
1827 addHRegUse(u, HRmRead, i->Pin.StoreC.dst);
1830 addHRegUse(u, HRmWrite, i->Pin.Set.dst);
1833 addHRegUse(u, HRmWrite, i->Pin.MfCR.dst);
1839 addHRegUse(u, HRmWrite, i->Pin.FpUnary.dst);
1840 addHRegUse(u, HRmRead, i->Pin.FpUnary.src);
1843 addHRegUse(u, HRmWrite, i->Pin.FpBinary.dst);
1844 addHRegUse(u, HRmRead, i->Pin.FpBinary.srcL);
1845 addHRegUse(u, HRmRead, i->Pin.FpBinary.srcR);
1848 addHRegUse(u, HRmWrite, i->Pin.FpMulAcc.dst);
1849 addHRegUse(u, HRmRead, i->Pin.FpMulAcc.srcML);
1850 addHRegUse(u, HRmRead, i->Pin.FpMulAcc.srcMR);
1851 addHRegUse(u, HRmRead, i->Pin.FpMulAcc.srcAcc);
1854 addHRegUse(u, (i->Pin.FpLdSt.isLoad ? HRmWrite : HRmRead),
1856 addRegUsage_PPCAMode(u, i->Pin.FpLdSt.addr);
1859 addHRegUse(u, HRmRead, i->Pin.FpSTFIW.addr);
1860 addHRegUse(u, HRmRead, i->Pin.FpSTFIW.data);
1863 addHRegUse(u, HRmWrite, i->Pin.FpRSP.dst);
1864 addHRegUse(u, HRmRead, i->Pin.FpRSP.src);
1867 addHRegUse(u, HRmWrite, i->Pin.FpCftI.dst);
1868 addHRegUse(u, HRmRead, i->Pin.FpCftI.src);
1871 addHRegUse(u, HRmModify, i->Pin.FpCMov.dst);
1872 addHRegUse(u, HRmRead, i->Pin.FpCMov.src);
1875 addHRegUse(u, HRmRead, i->Pin.FpLdFPSCR.src);
1878 addHRegUse(u, HRmWrite, i->Pin.FpCmp.dst);
1879 addHRegUse(u, HRmRead, i->Pin.FpCmp.srcL);
1880 addHRegUse(u, HRmRead, i->Pin.FpCmp.srcR);
1884 addHRegUse(u, (i->Pin.RdWrLR.wrLR ? HRmRead : HRmWrite),
1889 addHRegUse(u, (i->Pin.AvLdSt.isLoad ? HRmWrite : HRmRead),
1891 if (i->Pin.AvLdSt.addr->tag == Pam_IR)
1892 addHRegUse(u, HRmWrite, hregPPC_GPR30(mode64));
1893 addRegUsage_PPCAMode(u, i->Pin.AvLdSt.addr);
1896 addHRegUse(u, HRmWrite, i->Pin.AvUnary.dst);
1897 addHRegUse(u, HRmRead, i->Pin.AvUnary.src);
1900 if (i->Pin.AvBinary.op == Pav_XOR
1901 && i->Pin.AvBinary.dst == i->Pin.AvBinary.srcL
1902 && i->Pin.AvBinary.dst == i->Pin.AvBinary.srcR) {
1903 /* reg-alloc needs to understand 'xor r,r,r' as a write of r */
1904 /* (as opposed to a rite of passage :-) */
1905 addHRegUse(u, HRmWrite, i->Pin.AvBinary.dst);
1907 addHRegUse(u, HRmWrite, i->Pin.AvBinary.dst);
1908 addHRegUse(u, HRmRead, i->Pin.AvBinary.srcL);
1909 addHRegUse(u, HRmRead, i->Pin.AvBinary.srcR);
1913 addHRegUse(u, HRmWrite, i->Pin.AvBin8x16.dst);
1914 addHRegUse(u, HRmRead, i->Pin.AvBin8x16.srcL);
1915 addHRegUse(u, HRmRead, i->Pin.AvBin8x16.srcR);
1918 addHRegUse(u, HRmWrite, i->Pin.AvBin16x8.dst);
1919 addHRegUse(u, HRmRead, i->Pin.AvBin16x8.srcL);
1920 addHRegUse(u, HRmRead, i->Pin.AvBin16x8.srcR);
1923 addHRegUse(u, HRmWrite, i->Pin.AvBin32x4.dst);
1924 addHRegUse(u, HRmRead, i->Pin.AvBin32x4.srcL);
1925 addHRegUse(u, HRmRead, i->Pin.AvBin32x4.srcR);
1927 case Pin_AvBin32Fx4:
1928 addHRegUse(u, HRmWrite, i->Pin.AvBin32Fx4.dst);
1929 addHRegUse(u, HRmRead, i->Pin.AvBin32Fx4.srcL);
1930 addHRegUse(u, HRmRead, i->Pin.AvBin32Fx4.srcR);
1931 if (i->Pin.AvBin32Fx4.op == Pavfp_MULF)
1932 addHRegUse(u, HRmWrite, hregPPC_VR29());
1935 addHRegUse(u, HRmWrite, i->Pin.AvUn32Fx4.dst);
1936 addHRegUse(u, HRmRead, i->Pin.AvUn32Fx4.src);
1939 addHRegUse(u, HRmWrite, i->Pin.AvPerm.dst);
1940 addHRegUse(u, HRmRead, i->Pin.AvPerm.srcL);
1941 addHRegUse(u, HRmRead, i->Pin.AvPerm.srcR);
1942 addHRegUse(u, HRmRead, i->Pin.AvPerm.ctl);
1945 addHRegUse(u, HRmWrite, i->Pin.AvSel.dst);
1946 addHRegUse(u, HRmRead, i->Pin.AvSel.ctl);
1947 addHRegUse(u, HRmRead, i->Pin.AvSel.srcL);
1948 addHRegUse(u, HRmRead, i->Pin.AvSel.srcR);
1951 addHRegUse(u, HRmWrite, i->Pin.AvShlDbl.dst);
1952 addHRegUse(u, HRmRead, i->Pin.AvShlDbl.srcL);
1953 addHRegUse(u, HRmRead, i->Pin.AvShlDbl.srcR);
1956 addHRegUse(u, HRmWrite, i->Pin.AvSplat.dst);
1957 addRegUsage_PPCVI5s(u, i->Pin.AvSplat.src);
1960 addHRegUse(u, HRmModify, i->Pin.AvCMov.dst);
1961 addHRegUse(u, HRmRead, i->Pin.AvCMov.src);
1964 addHRegUse(u, HRmRead, i->Pin.AvLdVSCR.src);
1968 ppPPCInstr(i, mode64);
1969 vpanic("getRegUsage_PPCInstr");
1974 static void mapReg( HRegRemap* m, HReg* r )
1976 *r = lookupHRegRemap(m, *r);
1979 void mapRegs_PPCInstr ( HRegRemap* m, PPCInstr* i, Bool mode64 )
1983 mapReg(m, &i->Pin.LI.dst);
1986 mapReg(m, &i->Pin.Alu.dst);
1987 mapReg(m, &i->Pin.Alu.srcL);
1988 mapRegs_PPCRH(m, i->Pin.Alu.srcR);
1991 mapReg(m, &i->Pin.Shft.dst);
1992 mapReg(m, &i->Pin.Shft.srcL);
1993 mapRegs_PPCRH(m, i->Pin.Shft.srcR);
1996 mapReg(m, &i->Pin.AddSubC.dst);
1997 mapReg(m, &i->Pin.AddSubC.srcL);
1998 mapReg(m, &i->Pin.AddSubC.srcR);
2001 mapReg(m, &i->Pin.Cmp.srcL);
2002 mapRegs_PPCRH(m, i->Pin.Cmp.srcR);
2005 mapReg(m, &i->Pin.Unary.dst);
2006 mapReg(m, &i->Pin.Unary.src);
2009 mapReg(m, &i->Pin.MulL.dst);
2010 mapReg(m, &i->Pin.MulL.srcL);
2011 mapReg(m, &i->Pin.MulL.srcR);
2014 mapReg(m, &i->Pin.Div.dst);
2015 mapReg(m, &i->Pin.Div.srcL);
2016 mapReg(m, &i->Pin.Div.srcR);
2021 mapRegs_PPCRI(m, i->Pin.Goto.dst);
2024 mapRegs_PPCRI(m, i->Pin.CMov.src);
2025 mapReg(m, &i->Pin.CMov.dst);
2028 mapRegs_PPCAMode(m, i->Pin.Load.src);
2029 mapReg(m, &i->Pin.Load.dst);
2032 mapReg(m, &i->Pin.LoadL.src);
2033 mapReg(m, &i->Pin.LoadL.dst);
2036 mapReg(m, &i->Pin.Store.src);
2037 mapRegs_PPCAMode(m, i->Pin.Store.dst);
2040 mapReg(m, &i->Pin.StoreC.src);
2041 mapReg(m, &i->Pin.StoreC.dst);
2044 mapReg(m, &i->Pin.Set.dst);
2047 mapReg(m, &i->Pin.MfCR.dst);
2052 mapReg(m, &i->Pin.FpUnary.dst);
2053 mapReg(m, &i->Pin.FpUnary.src);
2056 mapReg(m, &i->Pin.FpBinary.dst);
2057 mapReg(m, &i->Pin.FpBinary.srcL);
2058 mapReg(m, &i->Pin.FpBinary.srcR);
2061 mapReg(m, &i->Pin.FpMulAcc.dst);
2062 mapReg(m, &i->Pin.FpMulAcc.srcML);
2063 mapReg(m, &i->Pin.FpMulAcc.srcMR);
2064 mapReg(m, &i->Pin.FpMulAcc.srcAcc);
2067 mapReg(m, &i->Pin.FpLdSt.reg);
2068 mapRegs_PPCAMode(m, i->Pin.FpLdSt.addr);
2071 mapReg(m, &i->Pin.FpSTFIW.addr);
2072 mapReg(m, &i->Pin.FpSTFIW.data);
2075 mapReg(m, &i->Pin.FpRSP.dst);
2076 mapReg(m, &i->Pin.FpRSP.src);
2079 mapReg(m, &i->Pin.FpCftI.dst);
2080 mapReg(m, &i->Pin.FpCftI.src);
2083 mapReg(m, &i->Pin.FpCMov.dst);
2084 mapReg(m, &i->Pin.FpCMov.src);
2087 mapReg(m, &i->Pin.FpLdFPSCR.src);
2090 mapReg(m, &i->Pin.FpCmp.dst);
2091 mapReg(m, &i->Pin.FpCmp.srcL);
2092 mapReg(m, &i->Pin.FpCmp.srcR);
2095 mapReg(m, &i->Pin.RdWrLR.gpr);
2098 mapReg(m, &i->Pin.AvLdSt.reg);
2099 mapRegs_PPCAMode(m, i->Pin.AvLdSt.addr);
2102 mapReg(m, &i->Pin.AvUnary.dst);
2103 mapReg(m, &i->Pin.AvUnary.src);
2106 mapReg(m, &i->Pin.AvBinary.dst);
2107 mapReg(m, &i->Pin.AvBinary.srcL);
2108 mapReg(m, &i->Pin.AvBinary.srcR);
2111 mapReg(m, &i->Pin.AvBin8x16.dst);
2112 mapReg(m, &i->Pin.AvBin8x16.srcL);
2113 mapReg(m, &i->Pin.AvBin8x16.srcR);
2116 mapReg(m, &i->Pin.AvBin16x8.dst);
2117 mapReg(m, &i->Pin.AvBin16x8.srcL);
2118 mapReg(m, &i->Pin.AvBin16x8.srcR);
2121 mapReg(m, &i->Pin.AvBin32x4.dst);
2122 mapReg(m, &i->Pin.AvBin32x4.srcL);
2123 mapReg(m, &i->Pin.AvBin32x4.srcR);
2125 case Pin_AvBin32Fx4:
2126 mapReg(m, &i->Pin.AvBin32Fx4.dst);
2127 mapReg(m, &i->Pin.AvBin32Fx4.srcL);
2128 mapReg(m, &i->Pin.AvBin32Fx4.srcR);
2131 mapReg(m, &i->Pin.AvUn32Fx4.dst);
2132 mapReg(m, &i->Pin.AvUn32Fx4.src);
2135 mapReg(m, &i->Pin.AvPerm.dst);
2136 mapReg(m, &i->Pin.AvPerm.srcL);
2137 mapReg(m, &i->Pin.AvPerm.srcR);
2138 mapReg(m, &i->Pin.AvPerm.ctl);
2141 mapReg(m, &i->Pin.AvSel.dst);
2142 mapReg(m, &i->Pin.AvSel.srcL);
2143 mapReg(m, &i->Pin.AvSel.srcR);
2144 mapReg(m, &i->Pin.AvSel.ctl);
2147 mapReg(m, &i->Pin.AvShlDbl.dst);
2148 mapReg(m, &i->Pin.AvShlDbl.srcL);
2149 mapReg(m, &i->Pin.AvShlDbl.srcR);
2152 mapReg(m, &i->Pin.AvSplat.dst);
2153 mapRegs_PPCVI5s(m, i->Pin.AvSplat.src);
2156 mapReg(m, &i->Pin.AvCMov.dst);
2157 mapReg(m, &i->Pin.AvCMov.src);
2160 mapReg(m, &i->Pin.AvLdVSCR.src);
2164 ppPPCInstr(i, mode64);
2165 vpanic("mapRegs_PPCInstr");
2169 /* Figure out if i represents a reg-reg move, and if so assign the
2170 source and destination to *src and *dst. If in doubt say No. Used
2171 by the register allocator to do move coalescing.
2173 Bool isMove_PPCInstr ( PPCInstr* i, HReg* src, HReg* dst )
2175 /* Moves between integer regs */
2176 if (i->tag == Pin_Alu) {
2177 // or Rd,Rs,Rs == mr Rd,Rs
2178 if (i->Pin.Alu.op != Palu_OR)
2180 if (i->Pin.Alu.srcR->tag != Prh_Reg)
2182 if (i->Pin.Alu.srcR->Prh.Reg.reg != i->Pin.Alu.srcL)
2184 *src = i->Pin.Alu.srcL;
2185 *dst = i->Pin.Alu.dst;
2188 /* Moves between FP regs */
2189 if (i->tag == Pin_FpUnary) {
2190 if (i->Pin.FpUnary.op != Pfp_MOV)
2192 *src = i->Pin.FpUnary.src;
2193 *dst = i->Pin.FpUnary.dst;
2200 /* Generate ppc spill/reload instructions under the direction of the
2201 register allocator. Note it's critical these don't write the
2204 void genSpill_PPC ( /*OUT*/HInstr** i1, /*OUT*/HInstr** i2,
2205 HReg rreg, Int offsetB, Bool mode64 )
2208 vassert(!hregIsVirtual(rreg));
2210 am = PPCAMode_IR( offsetB, GuestStatePtr(mode64) );
2211 switch (hregClass(rreg)) {
2214 *i1 = PPCInstr_Store( 8, am, rreg, mode64 );
2218 *i1 = PPCInstr_Store( 4, am, rreg, mode64 );
2221 *i1 = PPCInstr_FpLdSt ( False/*store*/, 8, rreg, am );
2224 // XXX: GPR30 used as spill register to kludge AltiVec
2226 *i1 = PPCInstr_AvLdSt ( False/*store*/, 16, rreg, am );
2229 ppHRegClass(hregClass(rreg));
2230 vpanic("genSpill_PPC: unimplemented regclass");
2234 void genReload_PPC ( /*OUT*/HInstr** i1, /*OUT*/HInstr** i2,
2235 HReg rreg, Int offsetB, Bool mode64 )
2238 vassert(!hregIsVirtual(rreg));
2240 am = PPCAMode_IR( offsetB, GuestStatePtr(mode64) );
2241 switch (hregClass(rreg)) {
2244 *i1 = PPCInstr_Load( 8, rreg, am, mode64 );
2248 *i1 = PPCInstr_Load( 4, rreg, am, mode64 );
2251 *i1 = PPCInstr_FpLdSt ( True/*load*/, 8, rreg, am );
2254 // XXX: GPR30 used as spill register to kludge AltiVec AMode_IR
2255 *i1 = PPCInstr_AvLdSt ( True/*load*/, 16, rreg, am );
2258 ppHRegClass(hregClass(rreg));
2259 vpanic("genReload_PPC: unimplemented regclass");
2264 /* --------- The ppc assembler (bleh.) --------- */
2266 static UInt iregNo ( HReg r, Bool mode64 )
2269 vassert(hregClass(r) == mode64 ? HRcInt64 : HRcInt32);
2270 vassert(!hregIsVirtual(r));
2276 static UInt fregNo ( HReg fr )
2279 vassert(hregClass(fr) == HRcFlt64);
2280 vassert(!hregIsVirtual(fr));
2286 static UInt vregNo ( HReg v )
2289 vassert(hregClass(v) == HRcVec128);
2290 vassert(!hregIsVirtual(v));
2296 /* Emit 32bit instruction big-endianly */
2297 static UChar* emit32 ( UChar* p, UInt w32 )
2299 *p++ = toUChar((w32 >> 24) & 0x000000FF);
2300 *p++ = toUChar((w32 >> 16) & 0x000000FF);
2301 *p++ = toUChar((w32 >> 8) & 0x000000FF);
2302 *p++ = toUChar((w32) & 0x000000FF);
2306 /* The following mkForm[...] functions refer to ppc instruction forms
2310 static UChar* mkFormD ( UChar* p, UInt opc1,
2311 UInt r1, UInt r2, UInt imm )
2314 vassert(opc1 < 0x40);
2318 theInstr = ((opc1<<26) | (r1<<21) | (r2<<16) | (imm));
2319 return emit32(p, theInstr);
2322 static UChar* mkFormMD ( UChar* p, UInt opc1, UInt r1, UInt r2,
2323 UInt imm1, UInt imm2, UInt opc2 )
2326 vassert(opc1 < 0x40);
2329 vassert(imm1 < 0x40);
2330 vassert(imm2 < 0x40);
2331 vassert(opc2 < 0x08);
2332 imm2 = ((imm2 & 0x1F) << 1) | (imm2 >> 5);
2333 theInstr = ((opc1<<26) | (r1<<21) | (r2<<16) |
2334 ((imm1 & 0x1F)<<11) | (imm2<<5) |
2335 (opc2<<2) | ((imm1 >> 5)<<1));
2336 return emit32(p, theInstr);
2339 static UChar* mkFormX ( UChar* p, UInt opc1, UInt r1, UInt r2,
2340 UInt r3, UInt opc2, UInt b0 )
2343 vassert(opc1 < 0x40);
2347 vassert(opc2 < 0x400);
2349 theInstr = ((opc1<<26) | (r1<<21) | (r2<<16) |
2350 (r3<<11) | (opc2<<1) | (b0));
2351 return emit32(p, theInstr);
2354 static UChar* mkFormXO ( UChar* p, UInt opc1, UInt r1, UInt r2,
2355 UInt r3, UInt b10, UInt opc2, UInt b0 )
2358 vassert(opc1 < 0x40);
2363 vassert(opc2 < 0x200);
2365 theInstr = ((opc1<<26) | (r1<<21) | (r2<<16) |
2366 (r3<<11) | (b10 << 10) | (opc2<<1) | (b0));
2367 return emit32(p, theInstr);
2370 static UChar* mkFormXL ( UChar* p, UInt opc1, UInt f1, UInt f2,
2371 UInt f3, UInt opc2, UInt b0 )
2374 vassert(opc1 < 0x40);
2378 vassert(opc2 < 0x400);
2380 theInstr = ((opc1<<26) | (f1<<21) | (f2<<16) |
2381 (f3<<11) | (opc2<<1) | (b0));
2382 return emit32(p, theInstr);
2385 // Note: for split field ops, give mnemonic arg
2386 static UChar* mkFormXFX ( UChar* p, UInt r1, UInt f2, UInt opc2 )
2391 vassert(opc2 < 0x400);
2394 vassert(f2 < 0x100);
2400 vassert(f2 < 0x400);
2401 // re-arrange split field
2402 f2 = ((f2>>5) & 0x1F) | ((f2 & 0x1F)<<5);
2404 default: vpanic("mkFormXFX(ppch)");
2406 theInstr = ((31<<26) | (r1<<21) | (f2<<11) | (opc2<<1));
2407 return emit32(p, theInstr);
2410 // Only used by mtfsf
2411 static UChar* mkFormXFL ( UChar* p, UInt FM, UInt freg )
2414 vassert(FM < 0x100);
2415 vassert(freg < 0x20);
2416 theInstr = ((63<<26) | (FM<<17) | (freg<<11) | (711<<1));
2417 return emit32(p, theInstr);
2420 static UChar* mkFormXS ( UChar* p, UInt opc1, UInt r1, UInt r2,
2421 UInt imm, UInt opc2, UInt b0 )
2424 vassert(opc1 < 0x40);
2427 vassert(imm < 0x40);
2428 vassert(opc2 < 0x400);
2430 theInstr = ((opc1<<26) | (r1<<21) | (r2<<16) |
2431 ((imm & 0x1F)<<11) | (opc2<<2) | ((imm>>5)<<1) | (b0));
2432 return emit32(p, theInstr);
2438 static UChar* mkFormI ( UChar* p, UInt LI, UInt AA, UInt LK )
2441 vassert(LI < 0x1000000);
2444 theInstr = ((18<<26) | (LI<<2) | (AA<<1) | (LK));
2445 return emit32(p, theInstr);
2450 static UChar* mkFormB ( UChar* p, UInt BO, UInt BI,
2451 UInt BD, UInt AA, UInt LK )
2456 vassert(BD < 0x4000);
2459 theInstr = ((16<<26) | (BO<<21) | (BI<<16) |
2460 (BD<<2) | (AA<<1) | (LK));
2461 return emit32(p, theInstr);
2465 static UChar* mkFormM ( UChar* p, UInt opc1, UInt r1, UInt r2,
2466 UInt f3, UInt MB, UInt ME, UInt Rc )
2469 vassert(opc1 < 0x40);
2476 theInstr = ((opc1<<26) | (r1<<21) | (r2<<16) |
2477 (f3<<11) | (MB<<6) | (ME<<1) | (Rc));
2478 return emit32(p, theInstr);
2481 static UChar* mkFormA ( UChar* p, UInt opc1, UInt r1, UInt r2,
2482 UInt r3, UInt r4, UInt opc2, UInt b0 )
2485 vassert(opc1 < 0x40);
2490 vassert(opc2 < 0x20);
2492 theInstr = ((opc1<<26) | (r1<<21) | (r2<<16) | (r3<<11) |
2493 (r4<<6) | (opc2<<1) | (b0));
2494 return emit32(p, theInstr);
2497 static UChar* doAMode_IR ( UChar* p, UInt opc1, UInt rSD,
2498 PPCAMode* am, Bool mode64 )
2501 vassert(am->tag == Pam_IR);
2502 vassert(am->Pam.IR.index < 0x10000);
2504 rA = iregNo(am->Pam.IR.base, mode64);
2505 idx = am->Pam.IR.index;
2507 if (opc1 == 58 || opc1 == 62) { // ld/std: mode64 only
2509 /* stay sane with DS form: lowest 2 bits must be 00. This
2510 should be guaranteed to us by iselWordExpr_AMode. */
2511 vassert(0 == (idx & 3));
2513 p = mkFormD(p, opc1, rSD, rA, idx);
2517 static UChar* doAMode_RR ( UChar* p, UInt opc1, UInt opc2,
2518 UInt rSD, PPCAMode* am, Bool mode64 )
2521 vassert(am->tag == Pam_RR);
2523 rA = iregNo(am->Pam.RR.base, mode64);
2524 rB = iregNo(am->Pam.RR.index, mode64);
2526 p = mkFormX(p, opc1, rSD, rA, rB, opc2, 0);
2531 /* Load imm to r_dst */
2532 static UChar* mkLoadImm ( UChar* p, UInt r_dst, ULong imm, Bool mode64 )
2534 vassert(r_dst < 0x20);
2537 /* In 32-bit mode, make sure the top 32 bits of imm are a sign
2538 extension of the bottom 32 bits, so that the range tests
2539 below work correctly. */
2540 UInt u32 = (UInt)imm;
2542 Long s64 = (Long)s32;
2546 if (imm >= 0xFFFFFFFFFFFF8000ULL || imm < 0x8000) {
2547 // sign-extendable from 16 bits
2549 // addi r_dst,0,imm => li r_dst,imm
2550 p = mkFormD(p, 14, r_dst, 0, imm & 0xFFFF);
2552 if (imm >= 0xFFFFFFFF80000000ULL || imm < 0x80000000ULL) {
2553 // sign-extendable from 32 bits
2555 // addis r_dst,r0,(imm>>16) => lis r_dst, (imm>>16)
2556 p = mkFormD(p, 15, r_dst, 0, (imm>>16) & 0xFFFF);
2557 // ori r_dst, r_dst, (imm & 0xFFFF)
2558 p = mkFormD(p, 24, r_dst, r_dst, imm & 0xFFFF);
2560 // full 64bit immediate load: 5 (five!) insns.
2565 // lis r_dst, (imm>>48) & 0xFFFF
2566 p = mkFormD(p, 15, r_dst, 0, (imm>>48) & 0xFFFF);
2568 // ori r_dst, r_dst, (imm>>32) & 0xFFFF
2569 if ((imm>>32) & 0xFFFF)
2570 p = mkFormD(p, 24, r_dst, r_dst, (imm>>32) & 0xFFFF);
2572 // shift r_dst low word to high word => rldicr
2573 p = mkFormMD(p, 30, r_dst, r_dst, 32, 31, 1);
2577 // oris r_dst, r_dst, (imm>>16) & 0xFFFF
2578 if ((imm>>16) & 0xFFFF)
2579 p = mkFormD(p, 25, r_dst, r_dst, (imm>>16) & 0xFFFF);
2581 // ori r_dst, r_dst, (imm) & 0xFFFF
2583 p = mkFormD(p, 24, r_dst, r_dst, imm & 0xFFFF);
2589 /* Move r_dst to r_src */
2590 static UChar* mkMoveReg ( UChar* p, UInt r_dst, UInt r_src )
2592 vassert(r_dst < 0x20);
2593 vassert(r_src < 0x20);
2595 if (r_dst != r_src) {
2596 /* or r_dst, r_src, r_src */
2597 p = mkFormX(p, 31, r_src, r_dst, r_src, 444, 0 );
2602 static UChar* mkFormVX ( UChar* p, UInt opc1, UInt r1, UInt r2,
2603 UInt r3, UInt opc2 )
2606 vassert(opc1 < 0x40);
2610 vassert(opc2 < 0x800);
2611 theInstr = ((opc1<<26) | (r1<<21) | (r2<<16) | (r3<<11) | opc2);
2612 return emit32(p, theInstr);
2615 static UChar* mkFormVXR ( UChar* p, UInt opc1, UInt r1, UInt r2,
2616 UInt r3, UInt Rc, UInt opc2 )
2619 vassert(opc1 < 0x40);
2624 vassert(opc2 < 0x400);
2625 theInstr = ((opc1<<26) | (r1<<21) | (r2<<16) |
2626 (r3<<11) | (Rc<<10) | opc2);
2627 return emit32(p, theInstr);
2630 static UChar* mkFormVA ( UChar* p, UInt opc1, UInt r1, UInt r2,
2631 UInt r3, UInt r4, UInt opc2 )
2634 vassert(opc1 < 0x40);
2639 vassert(opc2 < 0x40);
2640 theInstr = ((opc1<<26) | (r1<<21) | (r2<<16) |
2641 (r3<<11) | (r4<<6) | opc2);
2642 return emit32(p, theInstr);
2647 /* Emit an instruction into buf and return the number of bytes used.
2648 Note that buf is not the insn's final place, and therefore it is
2649 imperative to emit position-independent code.
2651 Note, dispatch should always be NULL since ppc32/64 backends
2652 use a call-return scheme to get from the dispatcher to generated
2655 Int emit_PPCInstr ( UChar* buf, Int nbuf, PPCInstr* i,
2656 Bool mode64, void* dispatch )
2660 vassert(nbuf >= 32);
2663 vex_printf("asm ");ppPPCInstr(i, mode64); vex_printf("\n");
2669 p = mkLoadImm(p, iregNo(i->Pin.LI.dst, mode64),
2670 i->Pin.LI.imm64, mode64);
2674 PPCRH* srcR = i->Pin.Alu.srcR;
2675 Bool immR = toBool(srcR->tag == Prh_Imm);
2676 UInt r_dst = iregNo(i->Pin.Alu.dst, mode64);
2677 UInt r_srcL = iregNo(i->Pin.Alu.srcL, mode64);
2678 UInt r_srcR = immR ? (-1)/*bogus*/ :
2679 iregNo(srcR->Prh.Reg.reg, mode64);
2681 switch (i->Pin.Alu.op) {
2684 /* addi (PPC32 p350) */
2685 vassert(srcR->Prh.Imm.syned);
2686 vassert(srcR->Prh.Imm.imm16 != 0x8000);
2687 p = mkFormD(p, 14, r_dst, r_srcL, srcR->Prh.Imm.imm16);
2689 /* add (PPC32 p347) */
2690 p = mkFormXO(p, 31, r_dst, r_srcL, r_srcR, 0, 266, 0);
2696 /* addi (PPC32 p350), but with negated imm */
2697 vassert(srcR->Prh.Imm.syned);
2698 vassert(srcR->Prh.Imm.imm16 != 0x8000);
2699 p = mkFormD(p, 14, r_dst, r_srcL, (- srcR->Prh.Imm.imm16));
2701 /* subf (PPC32 p537), with args the "wrong" way round */
2702 p = mkFormXO(p, 31, r_dst, r_srcR, r_srcL, 0, 40, 0);
2708 /* andi. (PPC32 p358) */
2709 vassert(!srcR->Prh.Imm.syned);
2710 p = mkFormD(p, 28, r_srcL, r_dst, srcR->Prh.Imm.imm16);
2712 /* and (PPC32 p356) */
2713 p = mkFormX(p, 31, r_srcL, r_dst, r_srcR, 28, 0);
2719 /* ori (PPC32 p497) */
2720 vassert(!srcR->Prh.Imm.syned);
2721 p = mkFormD(p, 24, r_srcL, r_dst, srcR->Prh.Imm.imm16);
2723 /* or (PPC32 p495) */
2724 p = mkFormX(p, 31, r_srcL, r_dst, r_srcR, 444, 0);
2730 /* xori (PPC32 p550) */
2731 vassert(!srcR->Prh.Imm.syned);
2732 p = mkFormD(p, 26, r_srcL, r_dst, srcR->Prh.Imm.imm16);
2734 /* xor (PPC32 p549) */
2735 p = mkFormX(p, 31, r_srcL, r_dst, r_srcR, 316, 0);
2746 PPCRH* srcR = i->Pin.Shft.srcR;
2747 Bool sz32 = i->Pin.Shft.sz32;
2748 Bool immR = toBool(srcR->tag == Prh_Imm);
2749 UInt r_dst = iregNo(i->Pin.Shft.dst, mode64);
2750 UInt r_srcL = iregNo(i->Pin.Shft.srcL, mode64);
2751 UInt r_srcR = immR ? (-1)/*bogus*/ :
2752 iregNo(srcR->Prh.Reg.reg, mode64);
2756 switch (i->Pin.Shft.op) {
2760 /* rd = rs << n, 1 <= n <= 31
2762 rlwinm rd,rs,n,0,31-n (PPC32 p501)
2764 UInt n = srcR->Prh.Imm.imm16;
2765 vassert(!srcR->Prh.Imm.syned);
2766 vassert(n > 0 && n < 32);
2767 p = mkFormM(p, 21, r_srcL, r_dst, n, 0, 31-n, 0);
2769 /* slw (PPC32 p505) */
2770 p = mkFormX(p, 31, r_srcL, r_dst, r_srcR, 24, 0);
2774 /* rd = rs << n, 1 <= n <= 63
2776 rldicr rd,rs,n,63-n (PPC64 p559)
2778 UInt n = srcR->Prh.Imm.imm16;
2779 vassert(!srcR->Prh.Imm.syned);
2780 vassert(n > 0 && n < 64);
2781 p = mkFormMD(p, 30, r_srcL, r_dst, n, 63-n, 1);
2783 /* sld (PPC64 p568) */
2784 p = mkFormX(p, 31, r_srcL, r_dst, r_srcR, 27, 0);
2792 /* rd = rs >>u n, 1 <= n <= 31
2794 rlwinm rd,rs,32-n,n,31 (PPC32 p501)
2796 UInt n = srcR->Prh.Imm.imm16;
2797 vassert(!srcR->Prh.Imm.syned);
2798 vassert(n > 0 && n < 32);
2799 p = mkFormM(p, 21, r_srcL, r_dst, 32-n, n, 31, 0);
2801 /* srw (PPC32 p508) */
2802 p = mkFormX(p, 31, r_srcL, r_dst, r_srcR, 536, 0);
2806 /* rd = rs >>u n, 1 <= n <= 63
2808 rldicl rd,rs,64-n,n (PPC64 p558)
2810 UInt n = srcR->Prh.Imm.imm16;
2811 vassert(!srcR->Prh.Imm.syned);
2812 vassert(n > 0 && n < 64);
2813 p = mkFormMD(p, 30, r_srcL, r_dst, 64-n, n, 0);
2815 /* srd (PPC64 p574) */
2816 p = mkFormX(p, 31, r_srcL, r_dst, r_srcR, 539, 0);
2824 /* srawi (PPC32 p507) */
2825 UInt n = srcR->Prh.Imm.imm16;
2826 vassert(!srcR->Prh.Imm.syned);
2827 /* In 64-bit mode, we allow right shifts by zero bits
2828 as that is a handy way to sign extend the lower 32
2829 bits into the upper 32 bits. */
2831 vassert(n >= 0 && n < 32);
2833 vassert(n > 0 && n < 32);
2834 p = mkFormX(p, 31, r_srcL, r_dst, n, 824, 0);
2836 /* sraw (PPC32 p506) */
2837 p = mkFormX(p, 31, r_srcL, r_dst, r_srcR, 792, 0);
2841 /* sradi (PPC64 p571) */
2842 UInt n = srcR->Prh.Imm.imm16;
2843 vassert(!srcR->Prh.Imm.syned);
2844 vassert(n > 0 && n < 64);
2845 p = mkFormXS(p, 31, r_srcL, r_dst, n, 413, 0);
2847 /* srad (PPC32 p570) */
2848 p = mkFormX(p, 31, r_srcL, r_dst, r_srcR, 794, 0);
2860 Bool isAdd = i->Pin.AddSubC.isAdd;
2861 Bool setC = i->Pin.AddSubC.setC;
2862 UInt r_srcL = iregNo(i->Pin.AddSubC.srcL, mode64);
2863 UInt r_srcR = iregNo(i->Pin.AddSubC.srcR, mode64);
2864 UInt r_dst = iregNo(i->Pin.AddSubC.dst, mode64);
2867 if (setC) /* addc (PPC32 p348) */
2868 p = mkFormXO(p, 31, r_dst, r_srcL, r_srcR, 0, 10, 0);
2869 else /* adde (PPC32 p349) */
2870 p = mkFormXO(p, 31, r_dst, r_srcL, r_srcR, 0, 138, 0);
2872 /* subfX, with args the "wrong" way round */
2873 if (setC) /* subfc (PPC32 p538) */
2874 p = mkFormXO(p, 31, r_dst, r_srcR, r_srcL, 0, 8, 0);
2875 else /* subfe (PPC32 p539) */
2876 p = mkFormXO(p, 31, r_dst, r_srcR, r_srcL, 0, 136, 0);
2882 Bool syned = i->Pin.Cmp.syned;
2883 Bool sz32 = i->Pin.Cmp.sz32;
2884 UInt fld1 = i->Pin.Cmp.crfD << 2;
2885 UInt r_srcL = iregNo(i->Pin.Cmp.srcL, mode64);
2886 UInt r_srcR, imm_srcR;
2887 PPCRH* srcR = i->Pin.Cmp.srcR;
2889 if (!mode64) // cmp double word invalid for mode32
2891 else if (!sz32) // mode64 && cmp64: set L=1
2894 switch (srcR->tag) {
2896 vassert(syned == srcR->Prh.Imm.syned);
2897 imm_srcR = srcR->Prh.Imm.imm16;
2898 if (syned) { // cmpw/di (signed) (PPC32 p368)
2899 vassert(imm_srcR != 0x8000);
2900 p = mkFormD(p, 11, fld1, r_srcL, imm_srcR);
2901 } else { // cmplw/di (unsigned) (PPC32 p370)
2902 p = mkFormD(p, 10, fld1, r_srcL, imm_srcR);
2906 r_srcR = iregNo(srcR->Prh.Reg.reg, mode64);
2907 if (syned) // cmpwi (signed) (PPC32 p367)
2908 p = mkFormX(p, 31, fld1, r_srcL, r_srcR, 0, 0);
2909 else // cmplwi (unsigned) (PPC32 p379)
2910 p = mkFormX(p, 31, fld1, r_srcL, r_srcR, 32, 0);
2919 UInt r_dst = iregNo(i->Pin.Unary.dst, mode64);
2920 UInt r_src = iregNo(i->Pin.Unary.src, mode64);
2922 switch (i->Pin.Unary.op) {
2923 case Pun_NOT: // nor r_dst,r_src,r_src
2924 p = mkFormX(p, 31, r_src, r_dst, r_src, 124, 0);
2926 case Pun_NEG: // neg r_dst,r_src
2927 p = mkFormXO(p, 31, r_dst, r_src, 0, 0, 104, 0);
2929 case Pun_CLZ32: // cntlzw r_dst, r_src
2930 p = mkFormX(p, 31, r_src, r_dst, 0, 26, 0);
2932 case Pun_CLZ64: // cntlzd r_dst, r_src
2934 p = mkFormX(p, 31, r_src, r_dst, 0, 58, 0);
2936 case Pun_EXTSW: // extsw r_dst, r_src
2938 p = mkFormX(p, 31, r_src, r_dst, 0, 986, 0);
2946 Bool syned = i->Pin.MulL.syned;
2947 Bool sz32 = i->Pin.MulL.sz32;
2948 UInt r_dst = iregNo(i->Pin.MulL.dst, mode64);
2949 UInt r_srcL = iregNo(i->Pin.MulL.srcL, mode64);
2950 UInt r_srcR = iregNo(i->Pin.MulL.srcR, mode64);
2955 if (i->Pin.MulL.hi) {
2956 // mul hi words, must consider sign
2958 if (syned) // mulhw r_dst,r_srcL,r_srcR
2959 p = mkFormXO(p, 31, r_dst, r_srcL, r_srcR, 0, 75, 0);
2960 else // mulhwu r_dst,r_srcL,r_srcR
2961 p = mkFormXO(p, 31, r_dst, r_srcL, r_srcR, 0, 11, 0);
2963 if (syned) // mulhd r_dst,r_srcL,r_srcR
2964 p = mkFormXO(p, 31, r_dst, r_srcL, r_srcR, 0, 73, 0);
2965 else // mulhdu r_dst,r_srcL,r_srcR
2966 p = mkFormXO(p, 31, r_dst, r_srcL, r_srcR, 0, 9, 0);
2969 // mul low word, sign is irrelevant
2970 vassert(!i->Pin.MulL.syned);
2971 if (sz32) // mullw r_dst,r_srcL,r_srcR
2972 p = mkFormXO(p, 31, r_dst, r_srcL, r_srcR, 0, 235, 0);
2973 else // mulld r_dst,r_srcL,r_srcR
2974 p = mkFormXO(p, 31, r_dst, r_srcL, r_srcR, 0, 233, 0);
2980 Bool syned = i->Pin.Div.syned;
2981 Bool sz32 = i->Pin.Div.sz32;
2982 UInt r_dst = iregNo(i->Pin.Div.dst, mode64);
2983 UInt r_srcL = iregNo(i->Pin.Div.srcL, mode64);
2984 UInt r_srcR = iregNo(i->Pin.Div.srcR, mode64);
2990 if (syned) // divw r_dst,r_srcL,r_srcR
2991 p = mkFormXO(p, 31, r_dst, r_srcL, r_srcR, 0, 491, 0);
2992 else // divwu r_dst,r_srcL,r_srcR
2993 p = mkFormXO(p, 31, r_dst, r_srcL, r_srcR, 0, 459, 0);
2995 if (syned) // divd r_dst,r_srcL,r_srcR
2996 p = mkFormXO(p, 31, r_dst, r_srcL, r_srcR, 0, 489, 0);
2997 else // divdu r_dst,r_srcL,r_srcR
2998 p = mkFormXO(p, 31, r_dst, r_srcL, r_srcR, 0, 457, 0);
3004 PPCCondCode cond = i->Pin.Call.cond;
3006 /* As per detailed comment for Pin_Call in
3007 getRegUsage_PPCInstr above, %r10 is used as an address temp */
3009 /* jump over the following insns if condition does not hold */
3010 if (cond.test != Pct_ALWAYS) {
3011 /* jmp fwds if !condition */
3012 /* don't know how many bytes to jump over yet...
3013 make space for a jump instruction and fill in later. */
3014 ptmp = p; /* fill in this bit later */
3018 /* load target to r_dst */ // p += 4|8|20
3019 p = mkLoadImm(p, r_dst, i->Pin.Call.target, mode64);
3021 /* mtspr 9,r_dst => move r_dst to count register */
3022 p = mkFormXFX(p, r_dst, 9, 467); // p += 4
3024 /* bctrl => branch to count register (and save to lr) */
3025 p = mkFormXL(p, 19, Pct_ALWAYS, 0, 0, 528, 1); // p += 4
3027 /* Fix up the conditional jump, if there was one. */
3028 if (cond.test != Pct_ALWAYS) {
3029 Int delta = p - ptmp;
3030 vassert(delta >= 16 && delta <= 32);
3031 /* bc !ct,cf,delta */
3032 mkFormB(ptmp, invertCondTest(cond.test),
3033 cond.flag, (delta>>2), 0, 0);
3040 UChar r_ret = 3; /* Put target addr into %r3 */
3041 PPCCondCode cond = i->Pin.Goto.cond;
3045 vassert(dispatch == NULL);
3047 /* First off, if this is conditional, create a conditional
3048 jump over the rest of it. */
3049 if (cond.test != Pct_ALWAYS) {
3050 /* jmp fwds if !condition */
3051 /* don't know how many bytes to jump over yet...
3052 make space for a jump instruction and fill in later. */
3053 ptmp = p; /* fill in this bit later */
3059 /* If a non-boring, set GuestStatePtr appropriately. */
3060 switch (i->Pin.Goto.jk) {
3061 case Ijk_ClientReq: trc = VEX_TRC_JMP_CLIENTREQ; break;
3062 case Ijk_Sys_syscall: trc = VEX_TRC_JMP_SYS_SYSCALL; break;
3063 case Ijk_Yield: trc = VEX_TRC_JMP_YIELD; break;
3064 case Ijk_EmWarn: trc = VEX_TRC_JMP_EMWARN; break;
3065 case Ijk_EmFail: trc = VEX_TRC_JMP_EMFAIL; break;
3066 case Ijk_MapFail: trc = VEX_TRC_JMP_MAPFAIL; break;
3067 case Ijk_NoDecode: trc = VEX_TRC_JMP_NODECODE; break;
3068 case Ijk_TInval: trc = VEX_TRC_JMP_TINVAL; break;
3069 case Ijk_NoRedir: trc = VEX_TRC_JMP_NOREDIR; break;
3070 case Ijk_SigTRAP: trc = VEX_TRC_JMP_SIGTRAP; break;
3071 case Ijk_SigBUS: trc = VEX_TRC_JMP_SIGBUS; break;
3077 ppIRJumpKind(i->Pin.Goto.jk);
3078 vpanic("emit_PPCInstr.Pin_Goto: unknown jump kind");
3081 vassert(trc < 0x10000);
3082 /* addi r31,0,trc */
3083 p = mkFormD(p, 14, 31, 0, trc); // p += 4
3086 /* Get the destination address into %r_ret */
3087 if (i->Pin.Goto.dst->tag == Pri_Imm) {
3088 imm_dst = i->Pin.Goto.dst->Pri.Imm;
3089 p = mkLoadImm(p, r_ret, imm_dst, mode64); // p += 4|8|20
3091 vassert(i->Pin.Goto.dst->tag == Pri_Reg);
3092 r_dst = iregNo(i->Pin.Goto.dst->Pri.Reg, mode64);
3093 p = mkMoveReg(p, r_ret, r_dst); // p += 4
3097 p = mkFormXL(p, 19, Pct_ALWAYS, 0, 0, 16, 0); // p += 4
3099 /* Fix up the conditional jump, if there was one. */
3100 if (cond.test != Pct_ALWAYS) {
3101 Int delta = p - ptmp;
3102 vassert(delta >= 12 && delta <= 32);
3103 /* bc !ct,cf,delta */
3104 mkFormB(ptmp, invertCondTest(cond.test),
3105 cond.flag, delta>>2, 0, 0);
3114 vassert(i->Pin.CMov.cond.test != Pct_ALWAYS);
3116 r_dst = iregNo(i->Pin.CMov.dst, mode64);
3117 cond = i->Pin.CMov.cond;
3119 /* branch (if cond fails) over move instrs */
3120 if (cond.test != Pct_ALWAYS) {
3121 /* don't know how many bytes to jump over yet...
3122 make space for a jump instruction and fill in later. */
3123 ptmp = p; /* fill in this bit later */
3127 // cond true: move src => dst
3128 switch (i->Pin.CMov.src->tag) {
3130 imm_src = i->Pin.CMov.src->Pri.Imm;
3131 p = mkLoadImm(p, r_dst, imm_src, mode64); // p += 4|8|20
3134 r_src = iregNo(i->Pin.CMov.src->Pri.Reg, mode64);
3135 p = mkMoveReg(p, r_dst, r_src); // p += 4
3140 /* Fix up the conditional jump, if there was one. */
3141 if (cond.test != Pct_ALWAYS) {
3142 Int delta = p - ptmp;
3143 vassert(delta >= 8 && delta <= 24);
3144 /* bc !ct,cf,delta */
3145 mkFormB(ptmp, invertCondTest(cond.test),
3146 cond.flag, (delta>>2), 0, 0);
3152 PPCAMode* am_addr = i->Pin.Load.src;
3153 UInt r_dst = iregNo(i->Pin.Load.dst, mode64);
3154 UInt opc1, opc2, sz = i->Pin.Load.sz;
3155 switch (am_addr->tag) {
3157 if (mode64 && (sz == 4 || sz == 8)) {
3158 /* should be guaranteed to us by iselWordExpr_AMode */
3159 vassert(0 == (am_addr->Pam.IR.index & 3));
3162 case 1: opc1 = 34; break;
3163 case 2: opc1 = 40; break;
3164 case 4: opc1 = 32; break;
3165 case 8: opc1 = 58; vassert(mode64); break;
3168 p = doAMode_IR(p, opc1, r_dst, am_addr, mode64);
3172 case 1: opc2 = 87; break;
3173 case 2: opc2 = 279; break;
3174 case 4: opc2 = 23; break;
3175 case 8: opc2 = 21; vassert(mode64); break;
3178 p = doAMode_RR(p, 31, opc2, r_dst, am_addr, mode64);
3186 if (i->Pin.LoadL.sz == 4) {
3187 p = mkFormX(p, 31, iregNo(i->Pin.LoadL.dst, mode64),
3188 0, iregNo(i->Pin.LoadL.src, mode64), 20, 0);
3191 if (i->Pin.LoadL.sz == 8 && mode64) {
3192 p = mkFormX(p, 31, iregNo(i->Pin.LoadL.dst, mode64),
3193 0, iregNo(i->Pin.LoadL.src, mode64), 84, 0);
3200 /* Make the destination register be 1 or 0, depending on whether
3201 the relevant condition holds. */
3202 UInt r_dst = iregNo(i->Pin.Set.dst, mode64);
3203 PPCCondCode cond = i->Pin.Set.cond;
3204 UInt rot_imm, r_tmp;
3206 if (cond.test == Pct_ALWAYS) {
3207 // Just load 1 to dst => li dst,1
3208 p = mkFormD(p, 14, r_dst, 0, 1);
3210 vassert(cond.flag != Pcf_NONE);
3211 rot_imm = 1 + cond.flag;
3212 r_tmp = 0; // Not set in getAllocable, so no need to declare.
3214 // r_tmp = CR => mfcr r_tmp
3215 p = mkFormX(p, 31, r_tmp, 0, 0, 19, 0);
3217 // r_dst = flag (rotate left and mask)
3218 // => rlwinm r_dst,r_tmp,rot_imm,31,31
3219 p = mkFormM(p, 21, r_tmp, r_dst, rot_imm, 31, 31, 0);
3221 if (cond.test == Pct_FALSE) {
3222 // flip bit => xori r_dst,r_dst,1
3223 p = mkFormD(p, 26, r_dst, r_dst, 1);
3231 p = mkFormX(p, 31, iregNo(i->Pin.MfCR.dst, mode64), 0, 0, 19, 0);
3235 p = mkFormX(p, 31, 0, 0, 0, 598, 0); // sync, PPC32 p616
3236 // CAB: Should this be isync?
3237 // p = mkFormXL(p, 19, 0, 0, 0, 150, 0); // isync, PPC32 p467
3242 PPCAMode* am_addr = i->Pin.Store.dst;
3243 UInt r_src = iregNo(i->Pin.Store.src, mode64);
3244 UInt opc1, opc2, sz = i->Pin.Store.sz;
3245 switch (i->Pin.Store.dst->tag) {
3247 if (mode64 && (sz == 4 || sz == 8)) {
3248 /* should be guaranteed to us by iselWordExpr_AMode */
3249 vassert(0 == (am_addr->Pam.IR.index & 3));
3252 case 1: opc1 = 38; break;
3253 case 2: opc1 = 44; break;
3254 case 4: opc1 = 36; break;
3255 case 8: vassert(mode64);
3260 p = doAMode_IR(p, opc1, r_src, am_addr, mode64);
3264 case 1: opc2 = 215; break;
3265 case 2: opc2 = 407; break;
3266 case 4: opc2 = 151; break;
3267 case 8: vassert(mode64);
3272 p = doAMode_RR(p, 31, opc2, r_src, am_addr, mode64);
3281 if (i->Pin.StoreC.sz == 4) {
3282 p = mkFormX(p, 31, iregNo(i->Pin.StoreC.src, mode64),
3283 0, iregNo(i->Pin.StoreC.dst, mode64), 150, 1);
3286 if (i->Pin.StoreC.sz == 8 && mode64) {
3287 p = mkFormX(p, 31, iregNo(i->Pin.StoreC.src, mode64),
3288 0, iregNo(i->Pin.StoreC.dst, mode64), 214, 1);
3295 UInt fr_dst = fregNo(i->Pin.FpUnary.dst);
3296 UInt fr_src = fregNo(i->Pin.FpUnary.src);
3297 switch (i->Pin.FpUnary.op) {
3298 case Pfp_RSQRTE: // frsqrtre, PPC32 p424
3299 p = mkFormA( p, 63, fr_dst, 0, fr_src, 0, 26, 0 );
3301 case Pfp_RES: // fres, PPC32 p421
3302 p = mkFormA( p, 59, fr_dst, 0, fr_src, 0, 24, 0 );
3304 case Pfp_SQRT: // fsqrt, PPC32 p427
3305 p = mkFormA( p, 63, fr_dst, 0, fr_src, 0, 22, 0 );
3307 case Pfp_ABS: // fabs, PPC32 p399
3308 p = mkFormX(p, 63, fr_dst, 0, fr_src, 264, 0);
3310 case Pfp_NEG: // fneg, PPC32 p416
3311 p = mkFormX(p, 63, fr_dst, 0, fr_src, 40, 0);
3313 case Pfp_MOV: // fmr, PPC32 p410
3314 p = mkFormX(p, 63, fr_dst, 0, fr_src, 72, 0);
3316 case Pfp_FRIM: // frim, PPC ISA 2.05 p137
3317 p = mkFormX(p, 63, fr_dst, 0, fr_src, 488, 0);
3319 case Pfp_FRIP: // frip, PPC ISA 2.05 p137
3320 p = mkFormX(p, 63, fr_dst, 0, fr_src, 456, 0);
3322 case Pfp_FRIN: // frin, PPC ISA 2.05 p137
3323 p = mkFormX(p, 63, fr_dst, 0, fr_src, 392, 0);
3325 case Pfp_FRIZ: // friz, PPC ISA 2.05 p137
3326 p = mkFormX(p, 63, fr_dst, 0, fr_src, 424, 0);
3334 case Pin_FpBinary: {
3335 UInt fr_dst = fregNo(i->Pin.FpBinary.dst);
3336 UInt fr_srcL = fregNo(i->Pin.FpBinary.srcL);
3337 UInt fr_srcR = fregNo(i->Pin.FpBinary.srcR);
3338 switch (i->Pin.FpBinary.op) {
3339 case Pfp_ADDD: // fadd, PPC32 p400
3340 p = mkFormA( p, 63, fr_dst, fr_srcL, fr_srcR, 0, 21, 0 );
3342 case Pfp_ADDS: // fadds, PPC32 p401
3343 p = mkFormA( p, 59, fr_dst, fr_srcL, fr_srcR, 0, 21, 0 );
3345 case Pfp_SUBD: // fsub, PPC32 p429
3346 p = mkFormA( p, 63, fr_dst, fr_srcL, fr_srcR, 0, 20, 0 );
3348 case Pfp_SUBS: // fsubs, PPC32 p430
3349 p = mkFormA( p, 59, fr_dst, fr_srcL, fr_srcR, 0, 20, 0 );
3351 case Pfp_MULD: // fmul, PPC32 p413
3352 p = mkFormA( p, 63, fr_dst, fr_srcL, 0, fr_srcR, 25, 0 );
3354 case Pfp_MULS: // fmuls, PPC32 p414
3355 p = mkFormA( p, 59, fr_dst, fr_srcL, 0, fr_srcR, 25, 0 );
3357 case Pfp_DIVD: // fdiv, PPC32 p406
3358 p = mkFormA( p, 63, fr_dst, fr_srcL, fr_srcR, 0, 18, 0 );
3360 case Pfp_DIVS: // fdivs, PPC32 p407
3361 p = mkFormA( p, 59, fr_dst, fr_srcL, fr_srcR, 0, 18, 0 );
3369 case Pin_FpMulAcc: {
3370 UInt fr_dst = fregNo(i->Pin.FpMulAcc.dst);
3371 UInt fr_srcML = fregNo(i->Pin.FpMulAcc.srcML);
3372 UInt fr_srcMR = fregNo(i->Pin.FpMulAcc.srcMR);
3373 UInt fr_srcAcc = fregNo(i->Pin.FpMulAcc.srcAcc);
3374 switch (i->Pin.FpMulAcc.op) {
3375 case Pfp_MADDD: // fmadd, PPC32 p408
3376 p = mkFormA( p, 63, fr_dst, fr_srcML, fr_srcAcc, fr_srcMR, 29, 0 );
3378 case Pfp_MADDS: // fmadds, PPC32 p409
3379 p = mkFormA( p, 59, fr_dst, fr_srcML, fr_srcAcc, fr_srcMR, 29, 0 );
3381 case Pfp_MSUBD: // fmsub, PPC32 p411
3382 p = mkFormA( p, 63, fr_dst, fr_srcML, fr_srcAcc, fr_srcMR, 28, 0 );
3384 case Pfp_MSUBS: // fmsubs, PPC32 p412
3385 p = mkFormA( p, 59, fr_dst, fr_srcML, fr_srcAcc, fr_srcMR, 28, 0 );
3394 PPCAMode* am_addr = i->Pin.FpLdSt.addr;
3395 UInt f_reg = fregNo(i->Pin.FpLdSt.reg);
3396 Bool idxd = toBool(i->Pin.FpLdSt.addr->tag == Pam_RR);
3397 UChar sz = i->Pin.FpLdSt.sz;
3399 vassert(sz == 4 || sz == 8);
3401 if (i->Pin.FpLdSt.isLoad) { // Load from memory
3402 if (idxd) { // lf[s|d]x, PPC32 p444|440
3403 opc = (sz == 4) ? 535 : 599;
3404 p = doAMode_RR(p, 31, opc, f_reg, am_addr, mode64);
3405 } else { // lf[s|d], PPC32 p441|437
3406 opc = (sz == 4) ? 48 : 50;
3407 p = doAMode_IR(p, opc, f_reg, am_addr, mode64);
3409 } else { // Store to memory
3410 if (idxd) { // stf[s|d]x, PPC32 p521|516
3411 opc = (sz == 4) ? 663 : 727;
3412 p = doAMode_RR(p, 31, opc, f_reg, am_addr, mode64);
3413 } else { // stf[s|d], PPC32 p518|513
3414 opc = (sz == 4) ? 52 : 54;
3415 p = doAMode_IR(p, opc, f_reg, am_addr, mode64);
3422 UInt ir_addr = iregNo(i->Pin.FpSTFIW.addr, mode64);
3423 UInt fr_data = fregNo(i->Pin.FpSTFIW.data);
3424 // stfiwx (store fp64[lo32] as int32), PPC32 p517
3425 // Use rA==0, so that EA == rB == ir_addr
3426 p = mkFormX(p, 31, fr_data, 0/*rA=0*/, ir_addr, 983, 0);
3431 UInt fr_dst = fregNo(i->Pin.FpRSP.dst);
3432 UInt fr_src = fregNo(i->Pin.FpRSP.src);
3434 p = mkFormX(p, 63, fr_dst, 0, fr_src, 12, 0);
3439 UInt fr_dst = fregNo(i->Pin.FpCftI.dst);
3440 UInt fr_src = fregNo(i->Pin.FpCftI.src);
3441 if (i->Pin.FpCftI.fromI == False && i->Pin.FpCftI.int32 == True) {
3442 // fctiw (conv f64 to i32), PPC32 p404
3443 p = mkFormX(p, 63, fr_dst, 0, fr_src, 14, 0);
3446 if (i->Pin.FpCftI.fromI == False && i->Pin.FpCftI.int32 == False) {
3447 // fctid (conv f64 to i64), PPC64 p437
3448 p = mkFormX(p, 63, fr_dst, 0, fr_src, 814, 0);
3451 if (i->Pin.FpCftI.fromI == True && i->Pin.FpCftI.int32 == False) {
3452 if (i->Pin.FpCftI.syned == True) {
3453 // fcfid (conv i64 to f64), PPC64 p434
3454 p = mkFormX(p, 63, fr_dst, 0, fr_src, 846, 0);
3456 } else if (i->Pin.FpCftI.flt64 == True) {
3457 // fcfidu (conv u64 to f64)
3458 p = mkFormX(p, 63, fr_dst, 0, fr_src, 974, 0);
3461 // fcfidus (conv u64 to f32)
3462 p = mkFormX(p, 59, fr_dst, 0, fr_src, 974, 0);
3470 UInt fr_dst = fregNo(i->Pin.FpCMov.dst);
3471 UInt fr_src = fregNo(i->Pin.FpCMov.src);
3472 PPCCondCode cc = i->Pin.FpCMov.cond;
3474 if (fr_dst == fr_src) goto done;
3476 vassert(cc.test != Pct_ALWAYS);
3478 /* jmp fwds if !condition */
3479 if (cc.test != Pct_ALWAYS) {
3480 /* bc !ct,cf,n_bytes>>2 */
3481 p = mkFormB(p, invertCondTest(cc.test), cc.flag, 8>>2, 0, 0);
3485 p = mkFormX(p, 63, fr_dst, 0, fr_src, 72, 0);
3489 case Pin_FpLdFPSCR: {
3490 UInt fr_src = fregNo(i->Pin.FpLdFPSCR.src);
3491 p = mkFormXFL(p, 0xFF, fr_src); // mtfsf, PPC32 p480
3497 UInt r_dst = iregNo(i->Pin.FpCmp.dst, mode64);
3498 UInt fr_srcL = fregNo(i->Pin.FpCmp.srcL);
3499 UInt fr_srcR = fregNo(i->Pin.FpCmp.srcR);
3501 // fcmpo, PPC32 p402
3502 p = mkFormX(p, 63, crfD<<2, fr_srcL, fr_srcR, 32, 0);
3504 // mfcr (mv CR to r_dst), PPC32 p467
3505 p = mkFormX(p, 31, r_dst, 0, 0, 19, 0);
3507 // rlwinm r_dst,r_dst,8,28,31, PPC32 p501
3508 // => rotate field 1 to bottomw of word, masking out upper 28
3509 p = mkFormM(p, 21, r_dst, r_dst, 8, 28, 31, 0);
3514 UInt reg = iregNo(i->Pin.RdWrLR.gpr, mode64);
3515 /* wrLR==True ? mtlr r4 : mflr r4 */
3516 p = mkFormXFX(p, reg, 8, (i->Pin.RdWrLR.wrLR==True) ? 467 : 339);
3523 UInt opc2, v_reg, r_idx, r_base;
3524 UChar sz = i->Pin.AvLdSt.sz;
3525 Bool idxd = toBool(i->Pin.AvLdSt.addr->tag == Pam_RR);
3526 vassert(sz == 1 || sz == 2 || sz == 4 || sz == 16);
3528 v_reg = vregNo(i->Pin.AvLdSt.reg);
3529 r_base = iregNo(i->Pin.AvLdSt.addr->Pam.RR.base, mode64);
3531 // Only have AltiVec AMode_RR: kludge AMode_IR
3533 r_idx = 30; // XXX: Using r30 as temp
3534 p = mkLoadImm(p, r_idx,
3535 i->Pin.AvLdSt.addr->Pam.IR.index, mode64);
3537 r_idx = iregNo(i->Pin.AvLdSt.addr->Pam.RR.index, mode64);
3540 if (i->Pin.FpLdSt.isLoad) { // Load from memory (1,2,4,16)
3541 opc2 = (sz==1) ? 7 : (sz==2) ? 39 : (sz==4) ? 71 : 103;
3542 p = mkFormX(p, 31, v_reg, r_idx, r_base, opc2, 0);
3543 } else { // Store to memory (1,2,4,16)
3544 opc2 = (sz==1) ? 135 : (sz==2) ? 167 : (sz==4) ? 199 : 231;
3545 p = mkFormX(p, 31, v_reg, r_idx, r_base, opc2, 0);
3551 UInt v_dst = vregNo(i->Pin.AvUnary.dst);
3552 UInt v_src = vregNo(i->Pin.AvUnary.src);
3554 switch (i->Pin.AvUnary.op) {
3555 case Pav_MOV: opc2 = 1156; break; // vor vD,vS,vS
3556 case Pav_NOT: opc2 = 1284; break; // vnor vD,vS,vS
3557 case Pav_UNPCKH8S: opc2 = 526; break; // vupkhsb
3558 case Pav_UNPCKH16S: opc2 = 590; break; // vupkhsh
3559 case Pav_UNPCKL8S: opc2 = 654; break; // vupklsb
3560 case Pav_UNPCKL16S: opc2 = 718; break; // vupklsh
3561 case Pav_UNPCKHPIX: opc2 = 846; break; // vupkhpx
3562 case Pav_UNPCKLPIX: opc2 = 974; break; // vupklpx
3566 switch (i->Pin.AvUnary.op) {
3569 p = mkFormVX( p, 4, v_dst, v_src, v_src, opc2 );
3572 p = mkFormVX( p, 4, v_dst, 0, v_src, opc2 );
3578 case Pin_AvBinary: {
3579 UInt v_dst = vregNo(i->Pin.AvBinary.dst);
3580 UInt v_srcL = vregNo(i->Pin.AvBinary.srcL);
3581 UInt v_srcR = vregNo(i->Pin.AvBinary.srcR);
3583 if (i->Pin.AvBinary.op == Pav_SHL) {
3584 p = mkFormVX( p, 4, v_dst, v_srcL, v_srcR, 1036 ); // vslo
3585 p = mkFormVX( p, 4, v_dst, v_dst, v_srcR, 452 ); // vsl
3588 if (i->Pin.AvBinary.op == Pav_SHR) {
3589 p = mkFormVX( p, 4, v_dst, v_srcL, v_srcR, 1100 ); // vsro
3590 p = mkFormVX( p, 4, v_dst, v_dst, v_srcR, 708 ); // vsr
3593 switch (i->Pin.AvBinary.op) {
3595 case Pav_AND: opc2 = 1028; break; // vand
3596 case Pav_OR: opc2 = 1156; break; // vor
3597 case Pav_XOR: opc2 = 1220; break; // vxor
3601 p = mkFormVX( p, 4, v_dst, v_srcL, v_srcR, opc2 );
3605 case Pin_AvBin8x16: {
3606 UInt v_dst = vregNo(i->Pin.AvBin8x16.dst);
3607 UInt v_srcL = vregNo(i->Pin.AvBin8x16.srcL);
3608 UInt v_srcR = vregNo(i->Pin.AvBin8x16.srcR);
3610 switch (i->Pin.AvBin8x16.op) {
3612 case Pav_ADDU: opc2 = 0; break; // vaddubm
3613 case Pav_QADDU: opc2 = 512; break; // vaddubs
3614 case Pav_QADDS: opc2 = 768; break; // vaddsbs
3616 case Pav_SUBU: opc2 = 1024; break; // vsububm
3617 case Pav_QSUBU: opc2 = 1536; break; // vsububs
3618 case Pav_QSUBS: opc2 = 1792; break; // vsubsbs
3620 case Pav_OMULU: opc2 = 8; break; // vmuloub
3621 case Pav_OMULS: opc2 = 264; break; // vmulosb
3622 case Pav_EMULU: opc2 = 520; break; // vmuleub
3623 case Pav_EMULS: opc2 = 776; break; // vmulesb
3625 case Pav_AVGU: opc2 = 1026; break; // vavgub
3626 case Pav_AVGS: opc2 = 1282; break; // vavgsb
3627 case Pav_MAXU: opc2 = 2; break; // vmaxub
3628 case Pav_MAXS: opc2 = 258; break; // vmaxsb
3629 case Pav_MINU: opc2 = 514; break; // vminub
3630 case Pav_MINS: opc2 = 770; break; // vminsb
3632 case Pav_CMPEQU: opc2 = 6; break; // vcmpequb
3633 case Pav_CMPGTU: opc2 = 518; break; // vcmpgtub
3634 case Pav_CMPGTS: opc2 = 774; break; // vcmpgtsb
3636 case Pav_SHL: opc2 = 260; break; // vslb
3637 case Pav_SHR: opc2 = 516; break; // vsrb
3638 case Pav_SAR: opc2 = 772; break; // vsrab
3639 case Pav_ROTL: opc2 = 4; break; // vrlb
3641 case Pav_MRGHI: opc2 = 12; break; // vmrghb
3642 case Pav_MRGLO: opc2 = 268; break; // vmrglb
3647 p = mkFormVX( p, 4, v_dst, v_srcL, v_srcR, opc2 );
3651 case Pin_AvBin16x8: {
3652 UInt v_dst = vregNo(i->Pin.AvBin16x8.dst);
3653 UInt v_srcL = vregNo(i->Pin.AvBin16x8.srcL);
3654 UInt v_srcR = vregNo(i->Pin.AvBin16x8.srcR);
3656 switch (i->Pin.AvBin16x8.op) {
3658 case Pav_ADDU: opc2 = 64; break; // vadduhm
3659 case Pav_QADDU: opc2 = 576; break; // vadduhs
3660 case Pav_QADDS: opc2 = 832; break; // vaddshs
3662 case Pav_SUBU: opc2 = 1088; break; // vsubuhm
3663 case Pav_QSUBU: opc2 = 1600; break; // vsubuhs
3664 case Pav_QSUBS: opc2 = 1856; break; // vsubshs
3666 case Pav_OMULU: opc2 = 72; break; // vmulouh
3667 case Pav_OMULS: opc2 = 328; break; // vmulosh
3668 case Pav_EMULU: opc2 = 584; break; // vmuleuh
3669 case Pav_EMULS: opc2 = 840; break; // vmulesh
3671 case Pav_AVGU: opc2 = 1090; break; // vavguh
3672 case Pav_AVGS: opc2 = 1346; break; // vavgsh
3673 case Pav_MAXU: opc2 = 66; break; // vmaxuh
3674 case Pav_MAXS: opc2 = 322; break; // vmaxsh
3675 case Pav_MINS: opc2 = 834; break; // vminsh
3676 case Pav_MINU: opc2 = 578; break; // vminuh
3678 case Pav_CMPEQU: opc2 = 70; break; // vcmpequh
3679 case Pav_CMPGTU: opc2 = 582; break; // vcmpgtuh
3680 case Pav_CMPGTS: opc2 = 838; break; // vcmpgtsh
3682 case Pav_SHL: opc2 = 324; break; // vslh
3683 case Pav_SHR: opc2 = 580; break; // vsrh
3684 case Pav_SAR: opc2 = 836; break; // vsrah
3685 case Pav_ROTL: opc2 = 68; break; // vrlh
3687 case Pav_PACKUU: opc2 = 14; break; // vpkuhum
3688 case Pav_QPACKUU: opc2 = 142; break; // vpkuhus
3689 case Pav_QPACKSU: opc2 = 270; break; // vpkshus
3690 case Pav_QPACKSS: opc2 = 398; break; // vpkshss
3691 case Pav_PACKPXL: opc2 = 782; break; // vpkpx
3693 case Pav_MRGHI: opc2 = 76; break; // vmrghh
3694 case Pav_MRGLO: opc2 = 332; break; // vmrglh
3699 p = mkFormVX( p, 4, v_dst, v_srcL, v_srcR, opc2 );
3703 case Pin_AvBin32x4: {
3704 UInt v_dst = vregNo(i->Pin.AvBin32x4.dst);
3705 UInt v_srcL = vregNo(i->Pin.AvBin32x4.srcL);
3706 UInt v_srcR = vregNo(i->Pin.AvBin32x4.srcR);
3708 switch (i->Pin.AvBin32x4.op) {
3710 case Pav_ADDU: opc2 = 128; break; // vadduwm
3711 case Pav_QADDU: opc2 = 640; break; // vadduws
3712 case Pav_QADDS: opc2 = 896; break; // vaddsws
3714 case Pav_SUBU: opc2 = 1152; break; // vsubuwm
3715 case Pav_QSUBU: opc2 = 1664; break; // vsubuws
3716 case Pav_QSUBS: opc2 = 1920; break; // vsubsws
3718 case Pav_AVGU: opc2 = 1154; break; // vavguw
3719 case Pav_AVGS: opc2 = 1410; break; // vavgsw
3721 case Pav_MAXU: opc2 = 130; break; // vmaxuw
3722 case Pav_MAXS: opc2 = 386; break; // vmaxsw
3724 case Pav_MINS: opc2 = 898; break; // vminsw
3725 case Pav_MINU: opc2 = 642; break; // vminuw
3727 case Pav_CMPEQU: opc2 = 134; break; // vcmpequw
3728 case Pav_CMPGTS: opc2 = 902; break; // vcmpgtsw
3729 case Pav_CMPGTU: opc2 = 646; break; // vcmpgtuw
3731 case Pav_SHL: opc2 = 388; break; // vslw
3732 case Pav_SHR: opc2 = 644; break; // vsrw
3733 case Pav_SAR: opc2 = 900; break; // vsraw
3734 case Pav_ROTL: opc2 = 132; break; // vrlw
3736 case Pav_PACKUU: opc2 = 78; break; // vpkuwum
3737 case Pav_QPACKUU: opc2 = 206; break; // vpkuwus
3738 case Pav_QPACKSU: opc2 = 334; break; // vpkswus
3739 case Pav_QPACKSS: opc2 = 462; break; // vpkswss
3741 case Pav_MRGHI: opc2 = 140; break; // vmrghw
3742 case Pav_MRGLO: opc2 = 396; break; // vmrglw
3747 p = mkFormVX( p, 4, v_dst, v_srcL, v_srcR, opc2 );
3751 case Pin_AvBin32Fx4: {
3752 UInt v_dst = vregNo(i->Pin.AvBin32Fx4.dst);
3753 UInt v_srcL = vregNo(i->Pin.AvBin32Fx4.srcL);
3754 UInt v_srcR = vregNo(i->Pin.AvBin32Fx4.srcR);
3755 switch (i->Pin.AvBin32Fx4.op) {
3758 p = mkFormVX( p, 4, v_dst, v_srcL, v_srcR, 10 ); // vaddfp
3761 p = mkFormVX( p, 4, v_dst, v_srcL, v_srcR, 74 ); // vsubfp
3764 p = mkFormVX( p, 4, v_dst, v_srcL, v_srcR, 1034 ); // vmaxfp
3767 p = mkFormVX( p, 4, v_dst, v_srcL, v_srcR, 1098 ); // vminfp
3771 /* Make a vmulfp from a vmaddfp:
3772 load -0.0 (0x8000_0000) to each 32-bit word of vB
3773 this makes the add a noop.
3775 UInt vB = 29; // XXX: Using v29 for temp do not change
3776 // without also changing
3777 // getRegUsage_PPCInstr
3780 // Better way to load -0.0 (0x80000000) ?
3781 // vspltisw vB,0x1F (0x1F => each word of vB)
3782 p = mkFormVX( p, 4, vB, konst, 0, 908 );
3784 // vslw vB,vB,vB (each word of vB = (0x1F << 0x1F) = 0x80000000
3785 p = mkFormVX( p, 4, vB, vB, vB, 388 );
3787 // Finally, do the multiply:
3788 p = mkFormVA( p, 4, v_dst, v_srcL, vB, v_srcR, 46 );
3791 case Pavfp_CMPEQF: // vcmpeqfp
3792 p = mkFormVXR( p, 4, v_dst, v_srcL, v_srcR, 0, 198 );
3794 case Pavfp_CMPGTF: // vcmpgtfp
3795 p = mkFormVXR( p, 4, v_dst, v_srcL, v_srcR, 0, 710 );
3797 case Pavfp_CMPGEF: // vcmpgefp
3798 p = mkFormVXR( p, 4, v_dst, v_srcL, v_srcR, 0, 454 );
3807 case Pin_AvUn32Fx4: {
3808 UInt v_dst = vregNo(i->Pin.AvUn32Fx4.dst);
3809 UInt v_src = vregNo(i->Pin.AvUn32Fx4.src);
3811 switch (i->Pin.AvUn32Fx4.op) {
3812 case Pavfp_RCPF: opc2 = 266; break; // vrefp
3813 case Pavfp_RSQRTF: opc2 = 330; break; // vrsqrtefp
3814 case Pavfp_CVTU2F: opc2 = 778; break; // vcfux
3815 case Pavfp_CVTS2F: opc2 = 842; break; // vcfsx
3816 case Pavfp_QCVTF2U: opc2 = 906; break; // vctuxs
3817 case Pavfp_QCVTF2S: opc2 = 970; break; // vctsxs
3818 case Pavfp_ROUNDM: opc2 = 714; break; // vrfim
3819 case Pavfp_ROUNDP: opc2 = 650; break; // vrfip
3820 case Pavfp_ROUNDN: opc2 = 522; break; // vrfin
3821 case Pavfp_ROUNDZ: opc2 = 586; break; // vrfiz
3825 p = mkFormVX( p, 4, v_dst, 0, v_src, opc2 );
3829 case Pin_AvPerm: { // vperm
3830 UInt v_dst = vregNo(i->Pin.AvPerm.dst);
3831 UInt v_srcL = vregNo(i->Pin.AvPerm.srcL);
3832 UInt v_srcR = vregNo(i->Pin.AvPerm.srcR);
3833 UInt v_ctl = vregNo(i->Pin.AvPerm.ctl);
3834 p = mkFormVA( p, 4, v_dst, v_srcL, v_srcR, v_ctl, 43 );
3838 case Pin_AvSel: { // vsel
3839 UInt v_ctl = vregNo(i->Pin.AvSel.ctl);
3840 UInt v_dst = vregNo(i->Pin.AvSel.dst);
3841 UInt v_srcL = vregNo(i->Pin.AvSel.srcL);
3842 UInt v_srcR = vregNo(i->Pin.AvSel.srcR);
3843 p = mkFormVA( p, 4, v_dst, v_srcL, v_srcR, v_ctl, 42 );
3847 case Pin_AvShlDbl: { // vsldoi
3848 UInt shift = i->Pin.AvShlDbl.shift;
3849 UInt v_dst = vregNo(i->Pin.AvShlDbl.dst);
3850 UInt v_srcL = vregNo(i->Pin.AvShlDbl.srcL);
3851 UInt v_srcR = vregNo(i->Pin.AvShlDbl.srcR);
3852 vassert(shift <= 0xF);
3853 p = mkFormVA( p, 4, v_dst, v_srcL, v_srcR, shift, 44 );
3857 case Pin_AvSplat: { // vsplt(is)(b,h,w)
3858 UInt v_dst = vregNo(i->Pin.AvShlDbl.dst);
3859 UChar sz = i->Pin.AvSplat.sz;
3861 vassert(sz == 8 || sz == 16 || sz == 32);
3863 if (i->Pin.AvSplat.src->tag == Pvi_Imm) {
3865 opc2 = (sz == 8) ? 780 : (sz == 16) ? 844 : 908; // 8,16,32
3866 /* expects 5-bit-signed-imm */
3867 simm5 = i->Pin.AvSplat.src->Pvi.Imm5s;
3868 vassert(simm5 >= -16 && simm5 <= 15);
3869 simm5 = simm5 & 0x1F;
3870 p = mkFormVX( p, 4, v_dst, (UInt)simm5, 0, opc2 );
3874 opc2 = (sz == 8) ? 524 : (sz == 16) ? 588 : 652; // 8,16,32
3875 vassert(hregClass(i->Pin.AvSplat.src->Pvi.Reg) == HRcVec128);
3876 v_src = vregNo(i->Pin.AvSplat.src->Pvi.Reg);
3877 lowest_lane = (128/sz)-1;
3878 p = mkFormVX( p, 4, v_dst, lowest_lane, v_src, opc2 );
3884 UInt v_dst = vregNo(i->Pin.AvCMov.dst);
3885 UInt v_src = vregNo(i->Pin.AvCMov.src);
3886 PPCCondCode cc = i->Pin.AvCMov.cond;
3888 if (v_dst == v_src) goto done;
3890 vassert(cc.test != Pct_ALWAYS);
3892 /* jmp fwds 2 insns if !condition */
3893 if (cc.test != Pct_ALWAYS) {
3894 /* bc !ct,cf,n_bytes>>2 */
3895 p = mkFormB(p, invertCondTest(cc.test), cc.flag, 8>>2, 0, 0);
3898 p = mkFormVX( p, 4, v_dst, v_src, v_src, 1156 );
3902 case Pin_AvLdVSCR: { // mtvscr
3903 UInt v_src = vregNo(i->Pin.AvLdVSCR.src);
3904 p = mkFormVX( p, 4, 0, 0, v_src, 1604 );
3913 vex_printf("\n=> ");
3914 ppPPCInstr(i, mode64);
3915 vpanic("emit_PPCInstr");
3919 vassert(p - &buf[0] <= 32);
3923 /*---------------------------------------------------------------*/
3924 /*--- end host_ppc_defs.c ---*/
3925 /*---------------------------------------------------------------*/