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