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