drd/tests/tsan_thread_wrappers_pthread.h: Fix MyThread::ThreadBody()
[valgrind.git] / VEX / priv / host_ppc_defs.c
blobf4b52e408aa7676119180f99b6f6a9f8130dbc3e
2 /*---------------------------------------------------------------*/
3 /*--- begin host_ppc_defs.c ---*/
4 /*---------------------------------------------------------------*/
6 /*
7 This file is part of Valgrind, a dynamic binary instrumentation
8 framework.
10 Copyright (C) 2004-2017 OpenWorks LLP
11 info@open-works.net
13 This program is free software; you can redistribute it and/or
14 modify it under the terms of the GNU General Public License as
15 published by the Free Software Foundation; either version 2 of the
16 License, or (at your option) any later version.
18 This program is distributed in the hope that it will be useful, but
19 WITHOUT ANY WARRANTY; without even the implied warranty of
20 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
21 General Public License for more details.
23 You should have received a copy of the GNU General Public License
24 along with this program; if not, write to the Free Software
25 Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
26 02110-1301, USA.
28 The GNU General Public License is contained in the file COPYING.
30 Neither the names of the U.S. Department of Energy nor the
31 University of California nor the names of its contributors may be
32 used to endorse or promote products derived from this software
33 without prior written permission.
36 #include "libvex_basictypes.h"
37 #include "libvex.h"
38 #include "libvex_trc_values.h"
40 #include "main_util.h"
41 #include "host_generic_regs.h"
42 #include "host_ppc_defs.h"
45 /* --------- Registers. --------- */
47 const RRegUniverse* getRRegUniverse_PPC ( Bool mode64 )
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;
55 /* Handy shorthand, nothing more */
56 RRegUniverse* ru = &rRegUniverse_PPC;
58 /* This isn't thread-safe. Sigh. */
59 UInt howNeeded = mode64 ? 2 : 1;
60 if (LIKELY(rRegUniverse_PPC_initted == howNeeded))
61 return ru;
63 RRegUniverse__init(ru);
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->allocable_start[(mode64) ? HRcInt64 : HRcInt32] = ru->size;
72 // GPR14 and above are callee save. List them first.
73 ru->regs[ru->size++] = hregPPC_GPR14(mode64);
74 ru->regs[ru->size++] = hregPPC_GPR15(mode64);
75 ru->regs[ru->size++] = hregPPC_GPR16(mode64);
76 ru->regs[ru->size++] = hregPPC_GPR17(mode64);
77 ru->regs[ru->size++] = hregPPC_GPR18(mode64);
78 ru->regs[ru->size++] = hregPPC_GPR19(mode64);
79 ru->regs[ru->size++] = hregPPC_GPR20(mode64);
80 ru->regs[ru->size++] = hregPPC_GPR21(mode64);
81 ru->regs[ru->size++] = hregPPC_GPR22(mode64);
82 ru->regs[ru->size++] = hregPPC_GPR23(mode64);
83 ru->regs[ru->size++] = hregPPC_GPR24(mode64);
84 ru->regs[ru->size++] = hregPPC_GPR25(mode64);
85 ru->regs[ru->size++] = hregPPC_GPR26(mode64);
86 ru->regs[ru->size++] = hregPPC_GPR27(mode64);
87 ru->regs[ru->size++] = hregPPC_GPR28(mode64);
89 // Caller save registers now.
90 ru->regs[ru->size++] = hregPPC_GPR3(mode64);
91 ru->regs[ru->size++] = hregPPC_GPR4(mode64);
92 ru->regs[ru->size++] = hregPPC_GPR5(mode64);
93 ru->regs[ru->size++] = hregPPC_GPR6(mode64);
94 ru->regs[ru->size++] = hregPPC_GPR7(mode64);
95 ru->regs[ru->size++] = hregPPC_GPR8(mode64);
96 ru->regs[ru->size++] = hregPPC_GPR9(mode64);
97 ru->regs[ru->size++] = hregPPC_GPR10(mode64);
98 if (!mode64) {
99 /* in mode64:
100 r11 used for calls by ptr / env ptr for some langs
101 r12 used for exception handling and global linkage code */
102 ru->regs[ru->size++] = hregPPC_GPR11(mode64);
103 ru->regs[ru->size++] = hregPPC_GPR12(mode64);
105 // GPR13 = thread specific pointer
106 ru->allocable_end[(mode64) ? HRcInt64 : HRcInt32] = ru->size - 1;
107 // GPR29 is reserved for the dispatcher
108 // GPR30 is reserved as AltiVec spill reg temporary
109 // GPR31 is reserved for the GuestStatePtr
111 /* Don't waste the reg-allocs's time trawling through zillions of
112 FP registers - they mostly will never be used. We'll tolerate
113 the occasional extra spill instead. */
114 /* For both ppc32-linux and ppc64-linux, f14-f31 are callee save.
115 So use them. */
116 ru->allocable_start[HRcFlt64] = ru->size;
117 ru->regs[ru->size++] = hregPPC_FPR14(mode64);
118 ru->regs[ru->size++] = hregPPC_FPR15(mode64);
119 ru->regs[ru->size++] = hregPPC_FPR16(mode64);
120 ru->regs[ru->size++] = hregPPC_FPR17(mode64);
121 ru->regs[ru->size++] = hregPPC_FPR18(mode64);
122 ru->regs[ru->size++] = hregPPC_FPR19(mode64);
123 ru->regs[ru->size++] = hregPPC_FPR20(mode64);
124 ru->regs[ru->size++] = hregPPC_FPR21(mode64);
125 ru->allocable_end[HRcFlt64] = ru->size - 1;
127 /* Same deal re Altivec */
128 /* For both ppc32-linux and ppc64-linux, v20-v31 are callee save.
129 So use them. */
130 /* NB, vr29 is used as a scratch temporary -- do not allocate */
131 ru->allocable_start[HRcVec128] = ru->size;
132 ru->regs[ru->size++] = hregPPC_VR20(mode64);
133 ru->regs[ru->size++] = hregPPC_VR21(mode64);
134 ru->regs[ru->size++] = hregPPC_VR22(mode64);
135 ru->regs[ru->size++] = hregPPC_VR23(mode64);
136 ru->regs[ru->size++] = hregPPC_VR24(mode64);
137 ru->regs[ru->size++] = hregPPC_VR25(mode64);
138 ru->regs[ru->size++] = hregPPC_VR26(mode64);
139 ru->regs[ru->size++] = hregPPC_VR27(mode64);
140 ru->allocable_end[HRcVec128] = ru->size - 1;
141 ru->allocable = ru->size;
143 /* And other regs, not available to the allocator. */
144 ru->regs[ru->size++] = hregPPC_GPR1(mode64);
145 ru->regs[ru->size++] = hregPPC_GPR29(mode64);
146 ru->regs[ru->size++] = hregPPC_GPR30(mode64);
147 ru->regs[ru->size++] = hregPPC_GPR31(mode64);
148 ru->regs[ru->size++] = hregPPC_VR29(mode64);
150 rRegUniverse_PPC_initted = howNeeded;
152 RRegUniverse__check_is_sane(ru);
153 return ru;
157 UInt ppHRegPPC ( HReg reg )
159 Int r;
160 static const HChar* ireg32_names[32]
161 = { "%r0", "%r1", "%r2", "%r3",
162 "%r4", "%r5", "%r6", "%r7",
163 "%r8", "%r9", "%r10", "%r11",
164 "%r12", "%r13", "%r14", "%r15",
165 "%r16", "%r17", "%r18", "%r19",
166 "%r20", "%r21", "%r22", "%r23",
167 "%r24", "%r25", "%r26", "%r27",
168 "%r28", "%r29", "%r30", "%r31" };
169 /* Be generic for all virtual regs. */
170 if (hregIsVirtual(reg)) {
171 return ppHReg(reg);
173 /* But specific for real regs. */
174 switch (hregClass(reg)) {
175 case HRcInt64:
176 r = hregEncoding(reg);
177 vassert(r >= 0 && r < 32);
178 return vex_printf("%s", ireg32_names[r]);
179 case HRcInt32:
180 r = hregEncoding(reg);
181 vassert(r >= 0 && r < 32);
182 return vex_printf("%s", ireg32_names[r]);
183 case HRcFlt64:
184 r = hregEncoding(reg);
185 vassert(r >= 0 && r < 32);
186 return vex_printf("%%fr%d", r);
187 case HRcVec128:
188 r = hregEncoding(reg);
189 vassert(r >= 0 && r < 32);
190 return vex_printf("%%v%d", r);
191 default:
192 vpanic("ppHRegPPC");
197 /* --------- Condition codes, Intel encoding. --------- */
199 const HChar* showPPCCondCode ( PPCCondCode cond )
201 if (cond.test == Pct_ALWAYS) return "always";
203 switch (cond.flag) {
204 case Pcf_7SO:
205 return (cond.test == Pct_TRUE) ? "cr7.so=1" : "cr7.so=0";
206 case Pcf_7EQ:
207 return (cond.test == Pct_TRUE) ? "cr7.eq=1" : "cr7.eq=0";
208 case Pcf_7GT:
209 return (cond.test == Pct_TRUE) ? "cr7.gt=1" : "cr7.gt=0";
210 case Pcf_7LT:
211 return (cond.test == Pct_TRUE) ? "cr7.lt=1" : "cr7.lt=0";
212 case Pcf_NONE:
213 return "no-flag";
214 default: vpanic("ppPPCCondCode");
218 /* construct condition code */
219 PPCCondCode mk_PPCCondCode ( PPCCondTest test, PPCCondFlag flag )
221 PPCCondCode cc;
222 cc.flag = flag;
223 cc.test = test;
224 if (test == Pct_ALWAYS) {
225 vassert(flag == Pcf_NONE);
226 } else {
227 vassert(flag != Pcf_NONE);
229 return cc;
232 /* false->true, true->false */
233 PPCCondTest invertCondTest ( PPCCondTest ct )
235 vassert(ct != Pct_ALWAYS);
236 return (ct == Pct_TRUE) ? Pct_FALSE : Pct_TRUE;
240 /* --------- PPCAMode: memory address expressions. --------- */
242 PPCAMode* PPCAMode_IR ( Int idx, HReg base ) {
243 PPCAMode* am = LibVEX_Alloc_inline(sizeof(PPCAMode));
244 vassert(idx >= -0x8000 && idx < 0x8000);
245 am->tag = Pam_IR;
246 am->Pam.IR.base = base;
247 am->Pam.IR.index = idx;
248 return am;
250 PPCAMode* PPCAMode_RR ( HReg idx, HReg base ) {
251 PPCAMode* am = LibVEX_Alloc_inline(sizeof(PPCAMode));
252 am->tag = Pam_RR;
253 am->Pam.RR.base = base;
254 am->Pam.RR.index = idx;
255 return am;
258 PPCAMode* dopyPPCAMode ( PPCAMode* am ) {
259 switch (am->tag) {
260 case Pam_IR:
261 return PPCAMode_IR( am->Pam.IR.index, am->Pam.IR.base );
262 case Pam_RR:
263 return PPCAMode_RR( am->Pam.RR.index, am->Pam.RR.base );
264 default:
265 vpanic("dopyPPCAMode");
269 void ppPPCAMode ( PPCAMode* am ) {
270 switch (am->tag) {
271 case Pam_IR:
272 if (am->Pam.IR.index == 0)
273 vex_printf("0(");
274 else
275 vex_printf("%d(", (Int)am->Pam.IR.index);
276 ppHRegPPC(am->Pam.IR.base);
277 vex_printf(")");
278 return;
279 case Pam_RR:
280 ppHRegPPC(am->Pam.RR.base);
281 vex_printf(",");
282 ppHRegPPC(am->Pam.RR.index);
283 return;
284 default:
285 vpanic("ppPPCAMode");
289 static void addRegUsage_PPCAMode ( HRegUsage* u, PPCAMode* am ) {
290 switch (am->tag) {
291 case Pam_IR:
292 addHRegUse(u, HRmRead, am->Pam.IR.base);
293 return;
294 case Pam_RR:
295 addHRegUse(u, HRmRead, am->Pam.RR.base);
296 addHRegUse(u, HRmRead, am->Pam.RR.index);
297 return;
298 default:
299 vpanic("addRegUsage_PPCAMode");
303 static void mapRegs_PPCAMode ( HRegRemap* m, PPCAMode* am ) {
304 switch (am->tag) {
305 case Pam_IR:
306 am->Pam.IR.base = lookupHRegRemap(m, am->Pam.IR.base);
307 return;
308 case Pam_RR:
309 am->Pam.RR.base = lookupHRegRemap(m, am->Pam.RR.base);
310 am->Pam.RR.index = lookupHRegRemap(m, am->Pam.RR.index);
311 return;
312 default:
313 vpanic("mapRegs_PPCAMode");
317 /* --------- Operand, which can be a reg or a u16/s16. --------- */
319 PPCRH* PPCRH_Imm ( Bool syned, UShort imm16 ) {
320 PPCRH* op = LibVEX_Alloc_inline(sizeof(PPCRH));
321 op->tag = Prh_Imm;
322 op->Prh.Imm.syned = syned;
323 op->Prh.Imm.imm16 = imm16;
324 /* If this is a signed value, ensure it's not -32768, so that we
325 are guaranteed always to be able to negate if needed. */
326 if (syned)
327 vassert(imm16 != 0x8000);
328 vassert(syned == True || syned == False);
329 return op;
331 PPCRH* PPCRH_Reg ( HReg reg ) {
332 PPCRH* op = LibVEX_Alloc_inline(sizeof(PPCRH));
333 op->tag = Prh_Reg;
334 op->Prh.Reg.reg = reg;
335 return op;
338 void ppPPCRH ( PPCRH* op ) {
339 switch (op->tag) {
340 case Prh_Imm:
341 if (op->Prh.Imm.syned)
342 vex_printf("%d", (Int)(Short)op->Prh.Imm.imm16);
343 else
344 vex_printf("%u", (UInt)(UShort)op->Prh.Imm.imm16);
345 return;
346 case Prh_Reg:
347 ppHRegPPC(op->Prh.Reg.reg);
348 return;
349 default:
350 vpanic("ppPPCRH");
354 /* An PPCRH can only be used in a "read" context (what would it mean
355 to write or modify a literal?) and so we enumerate its registers
356 accordingly. */
357 static void addRegUsage_PPCRH ( HRegUsage* u, PPCRH* op ) {
358 switch (op->tag) {
359 case Prh_Imm:
360 return;
361 case Prh_Reg:
362 addHRegUse(u, HRmRead, op->Prh.Reg.reg);
363 return;
364 default:
365 vpanic("addRegUsage_PPCRH");
369 static void mapRegs_PPCRH ( HRegRemap* m, PPCRH* op ) {
370 switch (op->tag) {
371 case Prh_Imm:
372 return;
373 case Prh_Reg:
374 op->Prh.Reg.reg = lookupHRegRemap(m, op->Prh.Reg.reg);
375 return;
376 default:
377 vpanic("mapRegs_PPCRH");
382 /* --------- Operand, which can be a reg or a u32/64. --------- */
384 PPCRI* PPCRI_Imm ( ULong imm64 ) {
385 PPCRI* op = LibVEX_Alloc_inline(sizeof(PPCRI));
386 op->tag = Pri_Imm;
387 op->Pri.Imm = imm64;
388 return op;
390 PPCRI* PPCRI_Reg ( HReg reg ) {
391 PPCRI* op = LibVEX_Alloc_inline(sizeof(PPCRI));
392 op->tag = Pri_Reg;
393 op->Pri.Reg = reg;
394 return op;
397 void ppPPCRI ( PPCRI* dst ) {
398 switch (dst->tag) {
399 case Pri_Imm:
400 vex_printf("0x%llx", dst->Pri.Imm);
401 break;
402 case Pri_Reg:
403 ppHRegPPC(dst->Pri.Reg);
404 break;
405 default:
406 vpanic("ppPPCRI");
410 /* An PPCRI can only be used in a "read" context (what would it
411 mean to write or modify a literal?) and so we enumerate its
412 registers accordingly. */
413 static void addRegUsage_PPCRI ( HRegUsage* u, PPCRI* dst ) {
414 switch (dst->tag) {
415 case Pri_Imm:
416 return;
417 case Pri_Reg:
418 addHRegUse(u, HRmRead, dst->Pri.Reg);
419 return;
420 default:
421 vpanic("addRegUsage_PPCRI");
425 static void mapRegs_PPCRI ( HRegRemap* m, PPCRI* dst ) {
426 switch (dst->tag) {
427 case Pri_Imm:
428 return;
429 case Pri_Reg:
430 dst->Pri.Reg = lookupHRegRemap(m, dst->Pri.Reg);
431 return;
432 default:
433 vpanic("mapRegs_PPCRI");
438 /* --------- Operand, which can be a vector reg or a simm5. --------- */
440 PPCVI5s* PPCVI5s_Imm ( Char simm5 ) {
441 PPCVI5s* op = LibVEX_Alloc_inline(sizeof(PPCVI5s));
442 op->tag = Pvi_Imm;
443 op->Pvi.Imm5s = simm5;
444 vassert(simm5 >= -16 && simm5 <= 15);
445 return op;
447 PPCVI5s* PPCVI5s_Reg ( HReg reg ) {
448 PPCVI5s* op = LibVEX_Alloc_inline(sizeof(PPCVI5s));
449 op->tag = Pvi_Reg;
450 op->Pvi.Reg = reg;
451 vassert(hregClass(reg) == HRcVec128);
452 return op;
455 void ppPPCVI5s ( PPCVI5s* src ) {
456 switch (src->tag) {
457 case Pvi_Imm:
458 vex_printf("%d", (Int)src->Pvi.Imm5s);
459 break;
460 case Pvi_Reg:
461 ppHRegPPC(src->Pvi.Reg);
462 break;
463 default:
464 vpanic("ppPPCVI5s");
468 /* An PPCVI5s can only be used in a "read" context (what would it
469 mean to write or modify a literal?) and so we enumerate its
470 registers accordingly. */
471 static void addRegUsage_PPCVI5s ( HRegUsage* u, PPCVI5s* dst ) {
472 switch (dst->tag) {
473 case Pvi_Imm:
474 return;
475 case Pvi_Reg:
476 addHRegUse(u, HRmRead, dst->Pvi.Reg);
477 return;
478 default:
479 vpanic("addRegUsage_PPCVI5s");
483 static void mapRegs_PPCVI5s ( HRegRemap* m, PPCVI5s* dst ) {
484 switch (dst->tag) {
485 case Pvi_Imm:
486 return;
487 case Pvi_Reg:
488 dst->Pvi.Reg = lookupHRegRemap(m, dst->Pvi.Reg);
489 return;
490 default:
491 vpanic("mapRegs_PPCVI5s");
496 /* --------- Instructions. --------- */
498 const HChar* showPPCUnaryOp ( PPCUnaryOp op ) {
499 switch (op) {
500 case Pun_NOT: return "not";
501 case Pun_NEG: return "neg";
502 case Pun_CLZ32: return "cntlzw";
503 case Pun_CLZ64: return "cntlzd";
504 case Pun_EXTSW: return "extsw";
505 case Pun_POP32: return "popcntw";
506 case Pun_POP64: return "popcntd";
507 default: vpanic("showPPCUnaryOp");
511 const HChar* showPPCAluOp ( PPCAluOp op, Bool immR ) {
512 switch (op) {
513 case Palu_ADD: return immR ? "addi" : "add";
514 case Palu_SUB: return immR ? "subi" : "sub";
515 case Palu_AND: return immR ? "andi." : "and";
516 case Palu_OR: return immR ? "ori" : "or";
517 case Palu_XOR: return immR ? "xori" : "xor";
518 default: vpanic("showPPCAluOp");
522 const HChar* showPPCShftOp ( PPCShftOp op, Bool immR, Bool sz32 ) {
523 switch (op) {
524 case Pshft_SHL: return sz32 ? (immR ? "slwi" : "slw") :
525 (immR ? "sldi" : "sld");
526 case Pshft_SHR: return sz32 ? (immR ? "srwi" : "srw") :
527 (immR ? "srdi" : "srd");
528 case Pshft_SAR: return sz32 ? (immR ? "srawi" : "sraw") :
529 (immR ? "sradi" : "srad");
530 default: vpanic("showPPCShftOp");
534 const HChar* showPPCFpOp ( PPCFpOp op ) {
535 switch (op) {
536 case Pfp_ADDD: return "fadd";
537 case Pfp_SUBD: return "fsub";
538 case Pfp_MULD: return "fmul";
539 case Pfp_DIVD: return "fdiv";
540 case Pfp_MADDD: return "fmadd";
541 case Pfp_MSUBD: return "fmsub";
542 case Pfp_MADDS: return "fmadds";
543 case Pfp_MSUBS: return "fmsubs";
544 case Pfp_ADDS: return "fadds";
545 case Pfp_SUBS: return "fsubs";
546 case Pfp_MULS: return "fmuls";
547 case Pfp_DIVS: return "fdivs";
548 case Pfp_SQRT: return "fsqrt";
549 case Pfp_ABS: return "fabs";
550 case Pfp_NEG: return "fneg";
551 case Pfp_MOV: return "fmr";
552 case Pfp_RES: return "fres";
553 case Pfp_RSQRTE: return "frsqrte";
554 case Pfp_FRIM: return "frim";
555 case Pfp_FRIN: return "frin";
556 case Pfp_FRIP: return "frip";
557 case Pfp_FRIZ: return "friz";
558 case Pfp_FPADDQ: return "xsaddqp";
559 case Pfp_FPSUBQ: return "xsubqp";
560 case Pfp_FPMULQ: return "xsmulqp";
561 case Pfp_FPDIVQ: return "xsdivqp";
562 case Pfp_FPMULADDQ: return "xsmaddqp";
563 case Pfp_FPMULSUBQ: return "xsmsubqp";
564 case Pfp_FPNEGMULADDQ: return "xsnmaddqp";
565 case Pfp_FPNEGMULSUBQ: return "xsnmsubqp";
566 case Pfp_FPADDQRNDODD: return "xsaddqpo";
567 case Pfp_FPSUBQRNDODD: return "xsubqpo";
568 case Pfp_FPMULQRNDODD: return "xsmulqpo";
569 case Pfp_FPDIVQRNDODD: return "xsaddqpo";
570 case Pfp_FPMULADDQRNDODD: return "xsmaddqpo";
571 case Pfp_FPMULSUBQRNDODD: return "xsmsubqpo";
572 case Pfp_FPNEGMULADDQRNDODD: return "xsnmaddqpo";
573 case Pfp_FPNEGMULSUBQRNDODD: return "xsnmsubqpo";
574 case Pfp_FPQTOD: return "xscvqpdp";
575 case Pfp_FPQTODRNDODD: return "xscvqpdpo";
576 case Pfp_FPDTOQ: return "xscvdpqp";
577 case Pfp_IDSTOQ: return "xscvsdqp";
578 case Pfp_IDUTOQ: return "xscvudqp";
579 case Pfp_TRUNCFPQTOISD: return "xscvqpsdz";
580 case Pfp_TRUNCFPQTOISW: return "xscvqpswz";
581 case Pfp_TRUNCFPQTOIUD: return "xscvqpudz";
582 case Pfp_TRUNCFPQTOIUW: return "xscvqpuwz";
583 case Pfp_DFPADD: return "dadd";
584 case Pfp_DFPADDQ: return "daddq";
585 case Pfp_DFPSUB: return "dsub";
586 case Pfp_DFPSUBQ: return "dsubq";
587 case Pfp_DFPMUL: return "dmul";
588 case Pfp_DFPMULQ: return "dmulq";
589 case Pfp_DFPDIV: return "ddivd";
590 case Pfp_DFPDIVQ: return "ddivq";
591 case Pfp_DCTDP: return "dctdp";
592 case Pfp_DRSP: return "drsp";
593 case Pfp_DCTFIX: return "dctfix";
594 case Pfp_DCFFIX: return "dcffix";
595 case Pfp_DCTQPQ: return "dctqpq";
596 case Pfp_DCFFIXQ: return "dcffixq";
597 case Pfp_DQUA: return "dqua";
598 case Pfp_DQUAQ: return "dquaq";
599 case Pfp_DXEX: return "dxex";
600 case Pfp_DXEXQ: return "dxexq";
601 case Pfp_DIEX: return "diex";
602 case Pfp_DIEXQ: return "diexq";
603 case Pfp_RRDTR: return "rrdtr";
604 default: vpanic("showPPCFpOp");
608 const HChar* showPPCAvOp ( PPCAvOp op ) {
609 switch (op) {
611 /* Unary */
612 case Pav_MOV: return "vmr"; /* Mov */
614 case Pav_AND: return "vand"; /* Bitwise */
615 case Pav_OR: return "vor";
616 case Pav_XOR: return "vxor";
617 case Pav_NOT: return "vnot";
619 case Pav_UNPCKH8S: return "vupkhsb"; /* Unpack */
620 case Pav_UNPCKH16S: return "vupkhsh";
621 case Pav_UNPCKL8S: return "vupklsb";
622 case Pav_UNPCKL16S: return "vupklsh";
623 case Pav_UNPCKHPIX: return "vupkhpx";
624 case Pav_UNPCKLPIX: return "vupklpx";
626 /* Integer binary */
627 case Pav_ADDU: return "vaddu_m"; // b,h,w,dw
628 case Pav_QADDU: return "vaddu_s"; // b,h,w,dw
629 case Pav_QADDS: return "vadds_s"; // b,h,w,dw
631 case Pav_SUBU: return "vsubu_m"; // b,h,w,dw
632 case Pav_QSUBU: return "vsubu_s"; // b,h,w,dw
633 case Pav_QSUBS: return "vsubs_s"; // b,h,w,dw
635 case Pav_MULU: return "vmulu"; // w
636 case Pav_OMULU: return "vmulou"; // b,h,w
637 case Pav_OMULS: return "vmulos"; // b,h,w
638 case Pav_EMULU: return "vmuleu"; // b,h,w
639 case Pav_EMULS: return "vmules"; // b,h,w
641 case Pav_AVGU: return "vavgu"; // b,h,w
642 case Pav_AVGS: return "vavgs"; // b,h,w
644 case Pav_MAXU: return "vmaxu"; // b,h,w
645 case Pav_MAXS: return "vmaxs"; // b,h,w
647 case Pav_MINU: return "vminu"; // b,h,w
648 case Pav_MINS: return "vmins"; // b,h,w
650 /* Compare (always affects CR field 6) */
651 case Pav_CMPEQU: return "vcmpequ"; // b,h,w
652 case Pav_CMPGTU: return "vcmpgtu"; // b,h,w
653 case Pav_CMPGTS: return "vcmpgts"; // b,h,w
655 /* Shift */
656 case Pav_SHL: return "vsl"; // ' ',b,h,w,dw
657 case Pav_SHR: return "vsr"; // ' ',b,h,w,dw
658 case Pav_SAR: return "vsra"; // b,h,w,dw
659 case Pav_ROTL: return "vrl"; // b,h,w,dw
661 /* Pack */
662 case Pav_PACKUU: return "vpku_um"; // h,w,dw
663 case Pav_QPACKUU: return "vpku_us"; // h,w
664 case Pav_QPACKSU: return "vpks_us"; // h,w
665 case Pav_QPACKSS: return "vpks_ss"; // h,w
666 case Pav_PACKPXL: return "vpkpx";
668 /* Merge */
669 case Pav_MRGHI: return "vmrgh"; // b,h,w
670 case Pav_MRGLO: return "vmrgl"; // b,h,w
672 /* Concatenation */
673 case Pav_CATODD: return "vmrgow"; // w
674 case Pav_CATEVEN: return "vmrgew"; // w
676 /* SHA */
677 case Pav_SHA256: return "vshasigmaw"; // w
678 case Pav_SHA512: return "vshasigmaw"; // dw
680 /* BCD */
681 case Pav_BCDAdd: return "bcdadd."; // qw
682 case Pav_BCDSub: return "bcdsub."; // qw
683 case Pav_I128StoBCD128: return "bcdcfsq."; //qw
684 case Pav_BCD128toI128S: return "bcdctsq."; //qw
686 /* I128 mult by 10 */
687 case Pav_MulI128by10: return "vmul10uq"; //qw
688 case Pav_MulI128by10Carry: return "vmul10cuq"; //qw
689 case Pav_MulI128by10E: return "vmul10euq"; //qw
690 case Pav_MulI128by10ECarry: return "vmul10ecuq"; //qw
692 /* F128 to I128 signed */
693 case Pav_F128toI128S: return "xsrqpi|x"; //qw
695 /* F128 round to F128 */
696 case Pav_ROUNDFPQ: return "xsrqpxp";
698 /* Polynomial arith */
699 case Pav_POLYMULADD: return "vpmsum"; // b, h, w, d
701 /* Cipher */
702 case Pav_CIPHERV128: case Pav_CIPHERLV128:
703 case Pav_NCIPHERV128: case Pav_NCIPHERLV128:
704 case Pav_CIPHERSUBV128: return "v_cipher_"; // qw
706 /* zero count */
707 case Pav_ZEROCNTBYTE: case Pav_ZEROCNTWORD:
708 case Pav_ZEROCNTHALF: case Pav_ZEROCNTDBL:
709 return "vclz_"; // b, h, w, d
711 /* trailing zero count */
712 case Pav_TRAILINGZEROCNTBYTE: case Pav_TRAILINGZEROCNTWORD:
713 case Pav_TRAILINGZEROCNTHALF: case Pav_TRAILINGZEROCNTDBL:
714 return "vctz_"; // b, h, w, d
716 /* vector gather (byte-by-byte bit matrix transpose) */
717 case Pav_BITMTXXPOSE:
718 return "vgbbd";
720 /* Vector Half-precision format to single precision conversion */
721 case Pav_F16toF32x4:
722 return"xvcvhpsp";
724 /* Vector Single-precision format to Half-precision conversion */
725 case Pav_F32toF16x4:
726 return"xvcvsphp";
728 /* Vector Half-precision format to Double precision conversion */
729 case Pav_F16toF64x2:
730 return"xvcvhpdp";
732 /* Vector Half-precision format to Double precision conversion */
733 case Pav_F64toF16x2:
734 return"xvcvdphp";
736 default: vpanic("showPPCAvOp");
740 const HChar* showPPCAvFpOp ( PPCAvFpOp op ) {
741 switch (op) {
742 /* Floating Point Binary */
743 case Pavfp_ADDF: return "vaddfp";
744 case Pavfp_SUBF: return "vsubfp";
745 case Pavfp_MULF: return "vmaddfp";
746 case Pavfp_MAXF: return "vmaxfp";
747 case Pavfp_MINF: return "vminfp";
748 case Pavfp_CMPEQF: return "vcmpeqfp";
749 case Pavfp_CMPGTF: return "vcmpgtfp";
750 case Pavfp_CMPGEF: return "vcmpgefp";
752 /* Floating Point Unary */
753 case Pavfp_RCPF: return "vrefp";
754 case Pavfp_RSQRTF: return "vrsqrtefp";
755 case Pavfp_CVTU2F: return "vcfux";
756 case Pavfp_CVTS2F: return "vcfsx";
757 case Pavfp_QCVTF2U: return "vctuxs";
758 case Pavfp_QCVTF2S: return "vctsxs";
759 case Pavfp_ROUNDM: return "vrfim";
760 case Pavfp_ROUNDP: return "vrfip";
761 case Pavfp_ROUNDN: return "vrfin";
762 case Pavfp_ROUNDZ: return "vrfiz";
764 default: vpanic("showPPCAvFpOp");
768 PPCInstr* PPCInstr_LI ( HReg dst, ULong imm64, Bool mode64 )
770 PPCInstr* i = LibVEX_Alloc_inline(sizeof(PPCInstr));
771 i->tag = Pin_LI;
772 i->Pin.LI.dst = dst;
773 i->Pin.LI.imm64 = imm64;
774 if (!mode64)
775 vassert( (Long)imm64 == (Long)(Int)(UInt)imm64 );
776 return i;
778 PPCInstr* PPCInstr_Alu ( PPCAluOp op, HReg dst,
779 HReg srcL, PPCRH* srcR ) {
780 PPCInstr* i = LibVEX_Alloc_inline(sizeof(PPCInstr));
781 i->tag = Pin_Alu;
782 i->Pin.Alu.op = op;
783 i->Pin.Alu.dst = dst;
784 i->Pin.Alu.srcL = srcL;
785 i->Pin.Alu.srcR = srcR;
786 return i;
788 PPCInstr* PPCInstr_Shft ( PPCShftOp op, Bool sz32,
789 HReg dst, HReg srcL, PPCRH* srcR ) {
790 PPCInstr* i = LibVEX_Alloc_inline(sizeof(PPCInstr));
791 i->tag = Pin_Shft;
792 i->Pin.Shft.op = op;
793 i->Pin.Shft.sz32 = sz32;
794 i->Pin.Shft.dst = dst;
795 i->Pin.Shft.srcL = srcL;
796 i->Pin.Shft.srcR = srcR;
797 return i;
799 PPCInstr* PPCInstr_AddSubC ( Bool isAdd, Bool setC,
800 HReg dst, HReg srcL, HReg srcR ) {
801 PPCInstr* i = LibVEX_Alloc_inline(sizeof(PPCInstr));
802 i->tag = Pin_AddSubC;
803 i->Pin.AddSubC.isAdd = isAdd;
804 i->Pin.AddSubC.setC = setC;
805 i->Pin.AddSubC.dst = dst;
806 i->Pin.AddSubC.srcL = srcL;
807 i->Pin.AddSubC.srcR = srcR;
808 return i;
810 PPCInstr* PPCInstr_Cmp ( Bool syned, Bool sz32,
811 UInt crfD, HReg srcL, PPCRH* srcR ) {
812 PPCInstr* i = LibVEX_Alloc_inline(sizeof(PPCInstr));
813 i->tag = Pin_Cmp;
814 i->Pin.Cmp.syned = syned;
815 i->Pin.Cmp.sz32 = sz32;
816 i->Pin.Cmp.crfD = crfD;
817 i->Pin.Cmp.srcL = srcL;
818 i->Pin.Cmp.srcR = srcR;
819 return i;
821 PPCInstr* PPCInstr_Unary ( PPCUnaryOp op, HReg dst, HReg src ) {
822 PPCInstr* i = LibVEX_Alloc_inline(sizeof(PPCInstr));
823 i->tag = Pin_Unary;
824 i->Pin.Unary.op = op;
825 i->Pin.Unary.dst = dst;
826 i->Pin.Unary.src = src;
827 return i;
829 PPCInstr* PPCInstr_MulL ( Bool syned, Bool hi, Bool sz32,
830 HReg dst, HReg srcL, HReg srcR ) {
831 PPCInstr* i = LibVEX_Alloc_inline(sizeof(PPCInstr));
832 i->tag = Pin_MulL;
833 i->Pin.MulL.syned = syned;
834 i->Pin.MulL.hi = hi;
835 i->Pin.MulL.sz32 = sz32;
836 i->Pin.MulL.dst = dst;
837 i->Pin.MulL.srcL = srcL;
838 i->Pin.MulL.srcR = srcR;
839 /* if doing the low word, the signedness is irrelevant, but tie it
840 down anyway. */
841 if (!hi) vassert(!syned);
842 return i;
844 PPCInstr* PPCInstr_Div ( Bool extended, Bool syned, Bool sz32,
845 HReg dst, HReg srcL, HReg srcR ) {
846 PPCInstr* i = LibVEX_Alloc_inline(sizeof(PPCInstr));
847 i->tag = Pin_Div;
848 i->Pin.Div.extended = extended;
849 i->Pin.Div.syned = syned;
850 i->Pin.Div.sz32 = sz32;
851 i->Pin.Div.dst = dst;
852 i->Pin.Div.srcL = srcL;
853 i->Pin.Div.srcR = srcR;
854 return i;
856 PPCInstr* PPCInstr_Call ( PPCCondCode cond,
857 Addr64 target, UInt argiregs, RetLoc rloc ) {
858 UInt mask;
859 PPCInstr* i = LibVEX_Alloc_inline(sizeof(PPCInstr));
860 i->tag = Pin_Call;
861 i->Pin.Call.cond = cond;
862 i->Pin.Call.target = target;
863 i->Pin.Call.argiregs = argiregs;
864 i->Pin.Call.rloc = rloc;
865 /* Only r3 .. r10 inclusive may be used as arg regs. Hence: */
866 mask = (1<<3)|(1<<4)|(1<<5)|(1<<6)|(1<<7)|(1<<8)|(1<<9)|(1<<10);
867 vassert(0 == (argiregs & ~mask));
868 vassert(is_sane_RetLoc(rloc));
869 return i;
871 PPCInstr* PPCInstr_XDirect ( Addr64 dstGA, PPCAMode* amCIA,
872 PPCCondCode cond, Bool toFastEP ) {
873 PPCInstr* i = LibVEX_Alloc_inline(sizeof(PPCInstr));
874 i->tag = Pin_XDirect;
875 i->Pin.XDirect.dstGA = dstGA;
876 i->Pin.XDirect.amCIA = amCIA;
877 i->Pin.XDirect.cond = cond;
878 i->Pin.XDirect.toFastEP = toFastEP;
879 return i;
881 PPCInstr* PPCInstr_XIndir ( HReg dstGA, PPCAMode* amCIA,
882 PPCCondCode cond ) {
883 PPCInstr* i = LibVEX_Alloc_inline(sizeof(PPCInstr));
884 i->tag = Pin_XIndir;
885 i->Pin.XIndir.dstGA = dstGA;
886 i->Pin.XIndir.amCIA = amCIA;
887 i->Pin.XIndir.cond = cond;
888 return i;
890 PPCInstr* PPCInstr_XAssisted ( HReg dstGA, PPCAMode* amCIA,
891 PPCCondCode cond, IRJumpKind jk ) {
892 PPCInstr* i = LibVEX_Alloc_inline(sizeof(PPCInstr));
893 i->tag = Pin_XAssisted;
894 i->Pin.XAssisted.dstGA = dstGA;
895 i->Pin.XAssisted.amCIA = amCIA;
896 i->Pin.XAssisted.cond = cond;
897 i->Pin.XAssisted.jk = jk;
898 return i;
900 PPCInstr* PPCInstr_CMov ( PPCCondCode cond,
901 HReg dst, PPCRI* src ) {
902 PPCInstr* i = LibVEX_Alloc_inline(sizeof(PPCInstr));
903 i->tag = Pin_CMov;
904 i->Pin.CMov.cond = cond;
905 i->Pin.CMov.src = src;
906 i->Pin.CMov.dst = dst;
907 vassert(cond.test != Pct_ALWAYS);
908 return i;
910 PPCInstr* PPCInstr_Load ( UChar sz,
911 HReg dst, PPCAMode* src, Bool mode64 ) {
912 PPCInstr* i = LibVEX_Alloc_inline(sizeof(PPCInstr));
913 i->tag = Pin_Load;
914 i->Pin.Load.sz = sz;
915 i->Pin.Load.src = src;
916 i->Pin.Load.dst = dst;
917 vassert(sz == 1 || sz == 2 || sz == 4 || sz == 8);
918 if (sz == 8) vassert(mode64);
919 return i;
921 PPCInstr* PPCInstr_LoadL ( UChar sz,
922 HReg dst, HReg src, Bool mode64 )
924 PPCInstr* i = LibVEX_Alloc_inline(sizeof(PPCInstr));
925 i->tag = Pin_LoadL;
926 i->Pin.LoadL.sz = sz;
927 i->Pin.LoadL.src = src;
928 i->Pin.LoadL.dst = dst;
929 vassert(sz == 1 || sz == 2 || sz == 4 || sz == 8);
930 if (sz == 8) vassert(mode64);
931 return i;
933 PPCInstr* PPCInstr_Store ( UChar sz, PPCAMode* dst, HReg src,
934 Bool mode64 ) {
935 PPCInstr* i = LibVEX_Alloc_inline(sizeof(PPCInstr));
936 i->tag = Pin_Store;
937 i->Pin.Store.sz = sz;
938 i->Pin.Store.src = src;
939 i->Pin.Store.dst = dst;
940 vassert(sz == 1 || sz == 2 || sz == 4 || sz == 8);
941 if (sz == 8) vassert(mode64);
942 return i;
944 PPCInstr* PPCInstr_StoreC ( UChar sz, HReg dst, HReg src, Bool mode64 ) {
945 PPCInstr* i = LibVEX_Alloc_inline(sizeof(PPCInstr));
946 i->tag = Pin_StoreC;
947 i->Pin.StoreC.sz = sz;
948 i->Pin.StoreC.src = src;
949 i->Pin.StoreC.dst = dst;
950 vassert(sz == 1 || sz == 2 || sz == 4 || sz == 8);
951 if (sz == 8) vassert(mode64);
952 return i;
954 PPCInstr* PPCInstr_Set ( PPCCondCode cond, HReg dst ) {
955 PPCInstr* i = LibVEX_Alloc_inline(sizeof(PPCInstr));
956 i->tag = Pin_Set;
957 i->Pin.Set.cond = cond;
958 i->Pin.Set.dst = dst;
959 return i;
961 PPCInstr* PPCInstr_MfCR ( HReg dst )
963 PPCInstr* i = LibVEX_Alloc_inline(sizeof(PPCInstr));
964 i->tag = Pin_MfCR;
965 i->Pin.MfCR.dst = dst;
966 return i;
968 PPCInstr* PPCInstr_MFence ( void )
970 PPCInstr* i = LibVEX_Alloc_inline(sizeof(PPCInstr));
971 i->tag = Pin_MFence;
972 return i;
975 PPCInstr* PPCInstr_FpUnary ( PPCFpOp op, HReg dst, HReg src ) {
976 PPCInstr* i = LibVEX_Alloc_inline(sizeof(PPCInstr));
977 i->tag = Pin_FpUnary;
978 i->Pin.FpUnary.op = op;
979 i->Pin.FpUnary.dst = dst;
980 i->Pin.FpUnary.src = src;
981 return i;
983 PPCInstr* PPCInstr_FpBinary ( PPCFpOp op, HReg dst,
984 HReg srcL, HReg srcR ) {
985 PPCInstr* i = LibVEX_Alloc_inline(sizeof(PPCInstr));
986 i->tag = Pin_FpBinary;
987 i->Pin.FpBinary.op = op;
988 i->Pin.FpBinary.dst = dst;
989 i->Pin.FpBinary.srcL = srcL;
990 i->Pin.FpBinary.srcR = srcR;
991 return i;
993 PPCInstr* PPCInstr_Fp128Unary(PPCFpOp op, HReg dst, HReg src) {
994 PPCInstr* i = LibVEX_Alloc_inline( sizeof(PPCInstr) );
995 i->tag = Pin_Fp128Unary;
996 i->Pin.Fp128Unary.op = op;
997 i->Pin.Fp128Unary.dst = dst;
998 i->Pin.Fp128Unary.src = src;
999 return i;
1001 PPCInstr* PPCInstr_Fp128Binary(PPCFpOp op, HReg dst, HReg srcL, HReg srcR) {
1002 PPCInstr* i = LibVEX_Alloc_inline( sizeof(PPCInstr) );
1003 i->tag = Pin_Fp128Binary;
1004 i->Pin.Fp128Binary.op = op;
1005 i->Pin.Fp128Binary.dst = dst;
1006 i->Pin.Fp128Binary.srcL = srcL;
1007 i->Pin.Fp128Binary.srcR = srcR;
1008 return i;
1010 PPCInstr* PPCInstr_Fp128Trinary(PPCFpOp op, HReg dst, HReg srcL, HReg srcR) {
1011 PPCInstr* i = LibVEX_Alloc_inline( sizeof(PPCInstr) );
1012 i->tag = Pin_Fp128Trinary;
1013 i->Pin.Fp128Trinary.op = op;
1014 i->Pin.Fp128Trinary.dst = dst;
1015 i->Pin.Fp128Trinary.srcL = srcL;
1016 i->Pin.Fp128Trinary.srcR = srcR;
1017 return i;
1019 PPCInstr* PPCInstr_FpMulAcc ( PPCFpOp op, HReg dst, HReg srcML,
1020 HReg srcMR, HReg srcAcc )
1022 PPCInstr* i = LibVEX_Alloc_inline(sizeof(PPCInstr));
1023 i->tag = Pin_FpMulAcc;
1024 i->Pin.FpMulAcc.op = op;
1025 i->Pin.FpMulAcc.dst = dst;
1026 i->Pin.FpMulAcc.srcML = srcML;
1027 i->Pin.FpMulAcc.srcMR = srcMR;
1028 i->Pin.FpMulAcc.srcAcc = srcAcc;
1029 return i;
1031 PPCInstr* PPCInstr_FpLdSt ( Bool isLoad, UChar sz,
1032 HReg reg, PPCAMode* addr ) {
1033 PPCInstr* i = LibVEX_Alloc_inline(sizeof(PPCInstr));
1034 i->tag = Pin_FpLdSt;
1035 i->Pin.FpLdSt.isLoad = isLoad;
1036 i->Pin.FpLdSt.sz = sz;
1037 i->Pin.FpLdSt.reg = reg;
1038 i->Pin.FpLdSt.addr = addr;
1039 vassert(sz == 4 || sz == 8);
1040 return i;
1042 PPCInstr* PPCInstr_FpSTFIW ( HReg addr, HReg data )
1044 PPCInstr* i = LibVEX_Alloc_inline(sizeof(PPCInstr));
1045 i->tag = Pin_FpSTFIW;
1046 i->Pin.FpSTFIW.addr = addr;
1047 i->Pin.FpSTFIW.data = data;
1048 return i;
1050 PPCInstr* PPCInstr_FpRSP ( HReg dst, HReg src ) {
1051 PPCInstr* i = LibVEX_Alloc_inline(sizeof(PPCInstr));
1052 i->tag = Pin_FpRSP;
1053 i->Pin.FpRSP.dst = dst;
1054 i->Pin.FpRSP.src = src;
1055 return i;
1057 PPCInstr* PPCInstr_Dfp64Unary(PPCFpOp op, HReg dst, HReg src) {
1058 PPCInstr* i = LibVEX_Alloc_inline( sizeof(PPCInstr) );
1059 i->tag = Pin_Dfp64Unary;
1060 i->Pin.Dfp64Unary.op = op;
1061 i->Pin.Dfp64Unary.dst = dst;
1062 i->Pin.Dfp64Unary.src = src;
1063 return i;
1065 PPCInstr* PPCInstr_Dfp64Binary(PPCFpOp op, HReg dst, HReg srcL, HReg srcR) {
1066 PPCInstr* i = LibVEX_Alloc_inline( sizeof(PPCInstr) );
1067 i->tag = Pin_Dfp64Binary;
1068 i->Pin.Dfp64Binary.op = op;
1069 i->Pin.Dfp64Binary.dst = dst;
1070 i->Pin.Dfp64Binary.srcL = srcL;
1071 i->Pin.Dfp64Binary.srcR = srcR;
1072 return i;
1074 PPCInstr* PPCInstr_DfpShift ( PPCFpOp op, HReg dst, HReg src, PPCRI* shift ) {
1075 PPCInstr* i = LibVEX_Alloc_inline(sizeof(PPCInstr));
1076 i->tag = Pin_DfpShift;
1077 i->Pin.DfpShift.op = op;
1078 i->Pin.DfpShift.shift = shift;
1079 i->Pin.DfpShift.src = src;
1080 i->Pin.DfpShift.dst = dst;
1081 return i;
1083 PPCInstr* PPCInstr_Dfp128Unary(PPCFpOp op, HReg dst_hi, HReg dst_lo,
1084 HReg src_hi, HReg src_lo) {
1085 PPCInstr* i = LibVEX_Alloc_inline( sizeof(PPCInstr) );
1086 i->tag = Pin_Dfp128Unary;
1087 i->Pin.Dfp128Unary.op = op;
1088 i->Pin.Dfp128Unary.dst_hi = dst_hi;
1089 i->Pin.Dfp128Unary.dst_lo = dst_lo;
1090 i->Pin.Dfp128Unary.src_hi = src_hi;
1091 i->Pin.Dfp128Unary.src_lo = src_lo;
1092 return i;
1094 PPCInstr* PPCInstr_Dfp128Binary(PPCFpOp op, HReg dst_hi, HReg dst_lo,
1095 HReg srcR_hi, HReg srcR_lo) {
1096 /* dst is used to pass the srcL argument and return the result */
1097 PPCInstr* i = LibVEX_Alloc_inline( sizeof(PPCInstr) );
1098 i->tag = Pin_Dfp128Binary;
1099 i->Pin.Dfp128Binary.op = op;
1100 i->Pin.Dfp128Binary.dst_hi = dst_hi;
1101 i->Pin.Dfp128Binary.dst_lo = dst_lo;
1102 i->Pin.Dfp128Binary.srcR_hi = srcR_hi;
1103 i->Pin.Dfp128Binary.srcR_lo = srcR_lo;
1104 return i;
1106 PPCInstr* PPCInstr_DfpShift128 ( PPCFpOp op, HReg dst_hi, HReg dst_lo,
1107 HReg src_hi, HReg src_lo,
1108 PPCRI* shift ) {
1109 PPCInstr* i = LibVEX_Alloc_inline(sizeof(PPCInstr));
1110 i->tag = Pin_DfpShift128;
1111 i->Pin.DfpShift128.op = op;
1112 i->Pin.DfpShift128.shift = shift;
1113 i->Pin.DfpShift128.src_hi = src_hi;
1114 i->Pin.DfpShift128.src_lo = src_lo;
1115 i->Pin.DfpShift128.dst_hi = dst_hi;
1116 i->Pin.DfpShift128.dst_lo = dst_lo;
1117 return i;
1119 PPCInstr* PPCInstr_DfpRound ( HReg dst, HReg src, PPCRI* r_rmc ) {
1120 PPCInstr* i = LibVEX_Alloc_inline(sizeof(PPCInstr));
1121 i->tag = Pin_DfpRound;
1122 i->Pin.DfpRound.dst = dst;
1123 i->Pin.DfpRound.src = src;
1124 i->Pin.DfpRound.r_rmc = r_rmc;
1125 return i;
1127 PPCInstr* PPCInstr_DfpRound128 ( HReg dst_hi, HReg dst_lo, HReg src_hi,
1128 HReg src_lo, PPCRI* r_rmc ) {
1129 PPCInstr* i = LibVEX_Alloc_inline(sizeof(PPCInstr));
1130 i->tag = Pin_DfpRound128;
1131 i->Pin.DfpRound128.dst_hi = dst_hi;
1132 i->Pin.DfpRound128.dst_lo = dst_lo;
1133 i->Pin.DfpRound128.src_hi = src_hi;
1134 i->Pin.DfpRound128.src_lo = src_lo;
1135 i->Pin.DfpRound128.r_rmc = r_rmc;
1136 return i;
1138 PPCInstr* PPCInstr_DfpQuantize ( PPCFpOp op, HReg dst, HReg srcL, HReg srcR,
1139 PPCRI* rmc ) {
1140 PPCInstr* i = LibVEX_Alloc_inline(sizeof(PPCInstr));
1141 i->tag = Pin_DfpQuantize;
1142 i->Pin.DfpQuantize.op = op;
1143 i->Pin.DfpQuantize.dst = dst;
1144 i->Pin.DfpQuantize.srcL = srcL;
1145 i->Pin.DfpQuantize.srcR = srcR;
1146 i->Pin.DfpQuantize.rmc = rmc;
1147 return i;
1149 PPCInstr* PPCInstr_DfpQuantize128 ( PPCFpOp op, HReg dst_hi, HReg dst_lo,
1150 HReg src_hi, HReg src_lo, PPCRI* rmc ) {
1151 /* dst is used to pass left operand in and return result */
1152 PPCInstr* i = LibVEX_Alloc_inline(sizeof(PPCInstr));
1153 i->tag = Pin_DfpQuantize128;
1154 i->Pin.DfpQuantize128.op = op;
1155 i->Pin.DfpQuantize128.dst_hi = dst_hi;
1156 i->Pin.DfpQuantize128.dst_lo = dst_lo;
1157 i->Pin.DfpQuantize128.src_hi = src_hi;
1158 i->Pin.DfpQuantize128.src_lo = src_lo;
1159 i->Pin.DfpQuantize128.rmc = rmc;
1160 return i;
1162 PPCInstr* PPCInstr_DfpD128toD64 ( PPCFpOp op, HReg dst,
1163 HReg src_hi, HReg src_lo ) {
1164 PPCInstr* i = LibVEX_Alloc_inline(sizeof(PPCInstr));
1165 i->tag = Pin_DfpD128toD64;
1166 i->Pin.DfpD128toD64.op = op;
1167 i->Pin.DfpD128toD64.src_hi = src_hi;
1168 i->Pin.DfpD128toD64.src_lo = src_lo;
1169 i->Pin.DfpD128toD64.dst = dst;
1170 return i;
1172 PPCInstr* PPCInstr_DfpI64StoD128 ( PPCFpOp op, HReg dst_hi,
1173 HReg dst_lo, HReg src ) {
1174 PPCInstr* i = LibVEX_Alloc_inline(sizeof(PPCInstr));
1175 i->tag = Pin_DfpI64StoD128;
1176 i->Pin.DfpI64StoD128.op = op;
1177 i->Pin.DfpI64StoD128.src = src;
1178 i->Pin.DfpI64StoD128.dst_hi = dst_hi;
1179 i->Pin.DfpI64StoD128.dst_lo = dst_lo;
1180 return i;
1182 PPCInstr* PPCInstr_ExtractExpD128 ( PPCFpOp op, HReg dst,
1183 HReg src_hi, HReg src_lo ) {
1184 /* dst is used to pass the srcL argument */
1185 PPCInstr* i = LibVEX_Alloc_inline(sizeof(PPCInstr));
1186 i->tag = Pin_ExtractExpD128;
1187 i->Pin.ExtractExpD128.op = op;
1188 i->Pin.ExtractExpD128.dst = dst;
1189 i->Pin.ExtractExpD128.src_hi = src_hi;
1190 i->Pin.ExtractExpD128.src_lo = src_lo;
1191 return i;
1193 PPCInstr* PPCInstr_InsertExpD128 ( PPCFpOp op, HReg dst_hi, HReg dst_lo,
1194 HReg srcL, HReg srcR_hi, HReg srcR_lo ) {
1195 /* dst is used to pass the srcL argument */
1196 PPCInstr* i = LibVEX_Alloc_inline(sizeof(PPCInstr));
1197 i->tag = Pin_InsertExpD128;
1198 i->Pin.InsertExpD128.op = op;
1199 i->Pin.InsertExpD128.dst_hi = dst_hi;
1200 i->Pin.InsertExpD128.dst_lo = dst_lo;
1201 i->Pin.InsertExpD128.srcL = srcL;
1202 i->Pin.InsertExpD128.srcR_hi = srcR_hi;
1203 i->Pin.InsertExpD128.srcR_lo = srcR_lo;
1204 return i;
1206 PPCInstr* PPCInstr_Dfp64Cmp (/* UInt crfD,*/ HReg dst, HReg srcL, HReg srcR ) {
1207 PPCInstr* i = LibVEX_Alloc_inline(sizeof(PPCInstr));
1208 i->tag = Pin_Dfp64Cmp;
1209 i->Pin.Dfp64Cmp.dst = dst;
1210 i->Pin.Dfp64Cmp.srcL = srcL;
1211 i->Pin.Dfp64Cmp.srcR = srcR;
1212 return i;
1214 PPCInstr* PPCInstr_Dfp128Cmp ( HReg dst, HReg srcL_hi, HReg srcL_lo,
1215 HReg srcR_hi, HReg srcR_lo ) {
1216 PPCInstr* i = LibVEX_Alloc_inline(sizeof(PPCInstr));
1217 i->tag = Pin_Dfp128Cmp;
1218 i->Pin.Dfp128Cmp.dst = dst;
1219 i->Pin.Dfp128Cmp.srcL_hi = srcL_hi;
1220 i->Pin.Dfp128Cmp.srcL_lo = srcL_lo;
1221 i->Pin.Dfp128Cmp.srcR_hi = srcR_hi;
1222 i->Pin.Dfp128Cmp.srcR_lo = srcR_lo;
1223 return i;
1225 PPCInstr* PPCInstr_EvCheck ( PPCAMode* amCounter,
1226 PPCAMode* amFailAddr ) {
1227 PPCInstr* i = LibVEX_Alloc_inline(sizeof(PPCInstr));
1228 i->tag = Pin_EvCheck;
1229 i->Pin.EvCheck.amCounter = amCounter;
1230 i->Pin.EvCheck.amFailAddr = amFailAddr;
1231 return i;
1233 PPCInstr* PPCInstr_ProfInc ( void ) {
1234 PPCInstr* i = LibVEX_Alloc_inline(sizeof(PPCInstr));
1235 i->tag = Pin_ProfInc;
1236 return i;
1240 Valid combo | fromI | int32 | syned | flt64 |
1241 --------------------------------------------
1242 | n n n n |
1243 --------------------------------------------
1244 F64->I64U | n n n y |
1245 --------------------------------------------
1246 | n n y n |
1247 --------------------------------------------
1248 F64->I64S | n n y y |
1249 --------------------------------------------
1250 | n y n n |
1251 --------------------------------------------
1252 F64->I32U | n y n y |
1253 --------------------------------------------
1254 | n y y n |
1255 --------------------------------------------
1256 F64->I32S | n y y y |
1257 --------------------------------------------
1258 I64U->F32 | y n n n |
1259 --------------------------------------------
1260 I64U->F64 | y n n y |
1261 --------------------------------------------
1262 | y n y n |
1263 --------------------------------------------
1264 I64S->F64 | y n y y |
1265 --------------------------------------------
1266 | y y n n |
1267 --------------------------------------------
1268 | y y n y |
1269 --------------------------------------------
1270 | y y y n |
1271 --------------------------------------------
1272 | y y y y |
1273 --------------------------------------------
1275 PPCInstr* PPCInstr_FpCftI ( Bool fromI, Bool int32, Bool syned,
1276 Bool flt64, HReg dst, HReg src ) {
1277 Bool tmp = fromI | int32 | syned | flt64;
1278 vassert(tmp == True || tmp == False); // iow, no high bits set
1279 UShort conversion = 0;
1280 conversion = (fromI << 3) | (int32 << 2) | (syned << 1) | flt64;
1281 switch (conversion) {
1282 // Supported conversion operations
1283 case 1: case 3: case 5: case 7:
1284 case 8: case 9: case 11:
1285 break;
1286 default:
1287 vpanic("PPCInstr_FpCftI(ppc_host)");
1289 PPCInstr* i = LibVEX_Alloc_inline(sizeof(PPCInstr));
1290 i->tag = Pin_FpCftI;
1291 i->Pin.FpCftI.fromI = fromI;
1292 i->Pin.FpCftI.int32 = int32;
1293 i->Pin.FpCftI.syned = syned;
1294 i->Pin.FpCftI.flt64 = flt64;
1295 i->Pin.FpCftI.dst = dst;
1296 i->Pin.FpCftI.src = src;
1297 return i;
1299 PPCInstr* PPCInstr_FpCMov ( PPCCondCode cond, HReg dst, HReg src ) {
1300 PPCInstr* i = LibVEX_Alloc_inline(sizeof(PPCInstr));
1301 i->tag = Pin_FpCMov;
1302 i->Pin.FpCMov.cond = cond;
1303 i->Pin.FpCMov.dst = dst;
1304 i->Pin.FpCMov.src = src;
1305 vassert(cond.test != Pct_ALWAYS);
1306 return i;
1308 PPCInstr* PPCInstr_FpLdFPSCR ( HReg src, Bool dfp_rm ) {
1309 PPCInstr* i = LibVEX_Alloc_inline(sizeof(PPCInstr));
1310 i->tag = Pin_FpLdFPSCR;
1311 i->Pin.FpLdFPSCR.src = src;
1312 i->Pin.FpLdFPSCR.dfp_rm = dfp_rm ? 1 : 0;
1313 return i;
1315 PPCInstr* PPCInstr_FpCmp ( HReg dst, HReg srcL, HReg srcR ) {
1316 PPCInstr* i = LibVEX_Alloc_inline(sizeof(PPCInstr));
1317 i->tag = Pin_FpCmp;
1318 i->Pin.FpCmp.dst = dst;
1319 i->Pin.FpCmp.srcL = srcL;
1320 i->Pin.FpCmp.srcR = srcR;
1321 return i;
1324 /* Read/Write Link Register */
1325 PPCInstr* PPCInstr_RdWrLR ( Bool wrLR, HReg gpr ) {
1326 PPCInstr* i = LibVEX_Alloc_inline(sizeof(PPCInstr));
1327 i->tag = Pin_RdWrLR;
1328 i->Pin.RdWrLR.wrLR = wrLR;
1329 i->Pin.RdWrLR.gpr = gpr;
1330 return i;
1333 /* AltiVec */
1334 PPCInstr* PPCInstr_AvLdSt ( Bool isLoad, UChar sz,
1335 HReg reg, PPCAMode* addr ) {
1336 PPCInstr* i = LibVEX_Alloc_inline(sizeof(PPCInstr));
1337 i->tag = Pin_AvLdSt;
1338 i->Pin.AvLdSt.isLoad = isLoad;
1339 i->Pin.AvLdSt.sz = sz;
1340 i->Pin.AvLdSt.reg = reg;
1341 i->Pin.AvLdSt.addr = addr;
1342 return i;
1344 PPCInstr* PPCInstr_AvUnary ( PPCAvOp op, HReg dst, HReg src ) {
1345 PPCInstr* i = LibVEX_Alloc_inline(sizeof(PPCInstr));
1346 i->tag = Pin_AvUnary;
1347 i->Pin.AvUnary.op = op;
1348 i->Pin.AvUnary.dst = dst;
1349 i->Pin.AvUnary.src = src;
1350 return i;
1352 PPCInstr* PPCInstr_AvBinary ( PPCAvOp op, HReg dst,
1353 HReg srcL, HReg srcR ) {
1354 PPCInstr* i = LibVEX_Alloc_inline(sizeof(PPCInstr));
1355 i->tag = Pin_AvBinary;
1356 i->Pin.AvBinary.op = op;
1357 i->Pin.AvBinary.dst = dst;
1358 i->Pin.AvBinary.srcL = srcL;
1359 i->Pin.AvBinary.srcR = srcR;
1360 return i;
1362 PPCInstr* PPCInstr_AvBinaryInt ( PPCAvOp op, HReg dst,
1363 HReg src, PPCRI* val ) {
1364 PPCInstr* i = LibVEX_Alloc_inline(sizeof(PPCInstr));
1365 i->tag = Pin_AvBinaryInt;
1366 i->Pin.AvBinaryInt.op = op;
1367 i->Pin.AvBinaryInt.dst = dst;
1368 i->Pin.AvBinaryInt.src = src;
1369 i->Pin.AvBinaryInt.val = val;
1370 return i;
1372 PPCInstr* PPCInstr_AvBin8x16 ( PPCAvOp op, HReg dst,
1373 HReg srcL, HReg srcR ) {
1374 PPCInstr* i = LibVEX_Alloc_inline(sizeof(PPCInstr));
1375 i->tag = Pin_AvBin8x16;
1376 i->Pin.AvBin8x16.op = op;
1377 i->Pin.AvBin8x16.dst = dst;
1378 i->Pin.AvBin8x16.srcL = srcL;
1379 i->Pin.AvBin8x16.srcR = srcR;
1380 return i;
1382 PPCInstr* PPCInstr_AvBin16x8 ( PPCAvOp op, HReg dst,
1383 HReg srcL, HReg srcR ) {
1384 PPCInstr* i = LibVEX_Alloc_inline(sizeof(PPCInstr));
1385 i->tag = Pin_AvBin16x8;
1386 i->Pin.AvBin16x8.op = op;
1387 i->Pin.AvBin16x8.dst = dst;
1388 i->Pin.AvBin16x8.srcL = srcL;
1389 i->Pin.AvBin16x8.srcR = srcR;
1390 return i;
1392 PPCInstr* PPCInstr_AvBin32x4 ( PPCAvOp op, HReg dst,
1393 HReg srcL, HReg srcR ) {
1394 PPCInstr* i = LibVEX_Alloc_inline(sizeof(PPCInstr));
1395 i->tag = Pin_AvBin32x4;
1396 i->Pin.AvBin32x4.op = op;
1397 i->Pin.AvBin32x4.dst = dst;
1398 i->Pin.AvBin32x4.srcL = srcL;
1399 i->Pin.AvBin32x4.srcR = srcR;
1400 return i;
1402 PPCInstr* PPCInstr_AvBin64x2 ( PPCAvOp op, HReg dst,
1403 HReg srcL, HReg srcR ) {
1404 PPCInstr* i = LibVEX_Alloc_inline(sizeof(PPCInstr));
1405 i->tag = Pin_AvBin64x2;
1406 i->Pin.AvBin64x2.op = op;
1407 i->Pin.AvBin64x2.dst = dst;
1408 i->Pin.AvBin64x2.srcL = srcL;
1409 i->Pin.AvBin64x2.srcR = srcR;
1410 return i;
1413 PPCInstr* PPCInstr_AvBin32Fx4 ( PPCAvFpOp op, HReg dst,
1414 HReg srcL, HReg srcR ) {
1415 PPCInstr* i = LibVEX_Alloc_inline(sizeof(PPCInstr));
1416 i->tag = Pin_AvBin32Fx4;
1417 i->Pin.AvBin32Fx4.op = op;
1418 i->Pin.AvBin32Fx4.dst = dst;
1419 i->Pin.AvBin32Fx4.srcL = srcL;
1420 i->Pin.AvBin32Fx4.srcR = srcR;
1421 return i;
1423 PPCInstr* PPCInstr_AvUn32Fx4 ( PPCAvFpOp op, HReg dst, HReg src ) {
1424 PPCInstr* i = LibVEX_Alloc_inline(sizeof(PPCInstr));
1425 i->tag = Pin_AvUn32Fx4;
1426 i->Pin.AvUn32Fx4.op = op;
1427 i->Pin.AvUn32Fx4.dst = dst;
1428 i->Pin.AvUn32Fx4.src = src;
1429 return i;
1431 PPCInstr* PPCInstr_AvPerm ( HReg dst, HReg srcL, HReg srcR, HReg ctl ) {
1432 PPCInstr* i = LibVEX_Alloc_inline(sizeof(PPCInstr));
1433 i->tag = Pin_AvPerm;
1434 i->Pin.AvPerm.dst = dst;
1435 i->Pin.AvPerm.srcL = srcL;
1436 i->Pin.AvPerm.srcR = srcR;
1437 i->Pin.AvPerm.ctl = ctl;
1438 return i;
1441 PPCInstr* PPCInstr_AvSel ( HReg ctl, HReg dst, HReg srcL, HReg srcR ) {
1442 PPCInstr* i = LibVEX_Alloc_inline(sizeof(PPCInstr));
1443 i->tag = Pin_AvSel;
1444 i->Pin.AvSel.ctl = ctl;
1445 i->Pin.AvSel.dst = dst;
1446 i->Pin.AvSel.srcL = srcL;
1447 i->Pin.AvSel.srcR = srcR;
1448 return i;
1450 PPCInstr* PPCInstr_AvSh ( Bool shLeft, HReg dst, PPCAMode* addr ) {
1451 PPCInstr* i = LibVEX_Alloc_inline(sizeof(PPCInstr));
1452 i->tag = Pin_AvSh;
1453 i->Pin.AvSh.shLeft = shLeft;
1454 i->Pin.AvSh.dst = dst;
1455 i->Pin.AvSh.addr = addr;
1456 return i;
1458 PPCInstr* PPCInstr_AvShlDbl ( UChar shift, HReg dst,
1459 HReg srcL, HReg srcR ) {
1460 PPCInstr* i = LibVEX_Alloc_inline(sizeof(PPCInstr));
1461 i->tag = Pin_AvShlDbl;
1462 i->Pin.AvShlDbl.shift = shift;
1463 i->Pin.AvShlDbl.dst = dst;
1464 i->Pin.AvShlDbl.srcL = srcL;
1465 i->Pin.AvShlDbl.srcR = srcR;
1466 return i;
1468 PPCInstr* PPCInstr_AvSplat ( UChar sz, HReg dst, PPCVI5s* src ) {
1469 PPCInstr* i = LibVEX_Alloc_inline(sizeof(PPCInstr));
1470 i->tag = Pin_AvSplat;
1471 i->Pin.AvSplat.sz = sz;
1472 i->Pin.AvSplat.dst = dst;
1473 i->Pin.AvSplat.src = src;
1474 return i;
1476 PPCInstr* PPCInstr_AvCMov ( PPCCondCode cond, HReg dst, HReg src ) {
1477 PPCInstr* i = LibVEX_Alloc_inline(sizeof(PPCInstr));
1478 i->tag = Pin_AvCMov;
1479 i->Pin.AvCMov.cond = cond;
1480 i->Pin.AvCMov.dst = dst;
1481 i->Pin.AvCMov.src = src;
1482 vassert(cond.test != Pct_ALWAYS);
1483 return i;
1485 PPCInstr* PPCInstr_AvLdVSCR ( HReg src ) {
1486 PPCInstr* i = LibVEX_Alloc_inline(sizeof(PPCInstr));
1487 i->tag = Pin_AvLdVSCR;
1488 i->Pin.AvLdVSCR.src = src;
1489 return i;
1491 PPCInstr* PPCInstr_AvCipherV128Unary ( PPCAvOp op, HReg dst, HReg src ) {
1492 PPCInstr* i = LibVEX_Alloc_inline(sizeof(PPCInstr));
1493 i->tag = Pin_AvCipherV128Unary;
1494 i->Pin.AvCipherV128Unary.op = op;
1495 i->Pin.AvCipherV128Unary.dst = dst;
1496 i->Pin.AvCipherV128Unary.src = src;
1497 return i;
1499 PPCInstr* PPCInstr_AvCipherV128Binary ( PPCAvOp op, HReg dst,
1500 HReg srcL, HReg srcR ) {
1501 PPCInstr* i = LibVEX_Alloc_inline(sizeof(PPCInstr));
1502 i->tag = Pin_AvCipherV128Binary;
1503 i->Pin.AvCipherV128Binary.op = op;
1504 i->Pin.AvCipherV128Binary.dst = dst;
1505 i->Pin.AvCipherV128Binary.srcL = srcL;
1506 i->Pin.AvCipherV128Binary.srcR = srcR;
1507 return i;
1509 PPCInstr* PPCInstr_AvHashV128Binary ( PPCAvOp op, HReg dst,
1510 HReg src, PPCRI* s_field ) {
1511 PPCInstr* i = LibVEX_Alloc_inline(sizeof(PPCInstr));
1512 i->tag = Pin_AvHashV128Binary;
1513 i->Pin.AvHashV128Binary.op = op;
1514 i->Pin.AvHashV128Binary.dst = dst;
1515 i->Pin.AvHashV128Binary.src = src;
1516 i->Pin.AvHashV128Binary.s_field = s_field;
1517 return i;
1519 PPCInstr* PPCInstr_AvBCDV128Binary ( PPCAvOp op, HReg dst,
1520 HReg src1, HReg src2 ) {
1521 PPCInstr* i = LibVEX_Alloc_inline(sizeof(PPCInstr));
1522 i->tag = Pin_AvBCDV128Binary;
1523 i->Pin.AvBCDV128Binary.op = op;
1524 i->Pin.AvBCDV128Binary.dst = dst;
1525 i->Pin.AvBCDV128Binary.src1 = src1;
1526 i->Pin.AvBCDV128Binary.src2 = src2;
1527 return i;
1531 /* Pretty Print instructions */
1532 static void ppLoadImm ( HReg dst, ULong imm, Bool mode64 ) {
1533 vex_printf("li_word ");
1534 ppHRegPPC(dst);
1535 if (!mode64) {
1536 vex_printf(",0x%08x", (UInt)imm);
1537 } else {
1538 vex_printf(",0x%016llx", imm);
1542 static void ppMovReg ( HReg dst, HReg src ) {
1543 if (!sameHReg(dst, src)) {
1544 vex_printf("mr ");
1545 ppHRegPPC(dst);
1546 vex_printf(",");
1547 ppHRegPPC(src);
1551 void ppPPCInstr ( const PPCInstr* i, Bool mode64 )
1553 switch (i->tag) {
1554 case Pin_LI:
1555 ppLoadImm(i->Pin.LI.dst, i->Pin.LI.imm64, mode64);
1556 break;
1557 case Pin_Alu: {
1558 HReg r_srcL = i->Pin.Alu.srcL;
1559 PPCRH* rh_srcR = i->Pin.Alu.srcR;
1560 /* special-case "mr" */
1561 if (i->Pin.Alu.op == Palu_OR && // or Rd,Rs,Rs == mr Rd,Rs
1562 rh_srcR->tag == Prh_Reg &&
1563 sameHReg(rh_srcR->Prh.Reg.reg, r_srcL)) {
1564 vex_printf("mr ");
1565 ppHRegPPC(i->Pin.Alu.dst);
1566 vex_printf(",");
1567 ppHRegPPC(r_srcL);
1568 return;
1570 /* special-case "li" */
1571 if (i->Pin.Alu.op == Palu_ADD && // addi Rd,0,imm == li Rd,imm
1572 rh_srcR->tag == Prh_Imm &&
1573 hregEncoding(r_srcL) == 0) {
1574 vex_printf("li ");
1575 ppHRegPPC(i->Pin.Alu.dst);
1576 vex_printf(",");
1577 ppPPCRH(rh_srcR);
1578 return;
1580 /* generic */
1581 vex_printf("%s ", showPPCAluOp(i->Pin.Alu.op,
1582 toBool(rh_srcR->tag == Prh_Imm)));
1583 ppHRegPPC(i->Pin.Alu.dst);
1584 vex_printf(",");
1585 ppHRegPPC(r_srcL);
1586 vex_printf(",");
1587 ppPPCRH(rh_srcR);
1588 return;
1590 case Pin_Shft: {
1591 HReg r_srcL = i->Pin.Shft.srcL;
1592 PPCRH* rh_srcR = i->Pin.Shft.srcR;
1593 vex_printf("%s ", showPPCShftOp(i->Pin.Shft.op,
1594 toBool(rh_srcR->tag == Prh_Imm),
1595 i->Pin.Shft.sz32));
1596 ppHRegPPC(i->Pin.Shft.dst);
1597 vex_printf(",");
1598 ppHRegPPC(r_srcL);
1599 vex_printf(",");
1600 ppPPCRH(rh_srcR);
1601 return;
1603 case Pin_AddSubC:
1604 vex_printf("%s%s ",
1605 i->Pin.AddSubC.isAdd ? "add" : "sub",
1606 i->Pin.AddSubC.setC ? "c" : "e");
1607 ppHRegPPC(i->Pin.AddSubC.dst);
1608 vex_printf(",");
1609 ppHRegPPC(i->Pin.AddSubC.srcL);
1610 vex_printf(",");
1611 ppHRegPPC(i->Pin.AddSubC.srcR);
1612 return;
1613 case Pin_Cmp:
1614 vex_printf("%s%c%s %%cr%u,",
1615 i->Pin.Cmp.syned ? "cmp" : "cmpl",
1616 i->Pin.Cmp.sz32 ? 'w' : 'd',
1617 i->Pin.Cmp.srcR->tag == Prh_Imm ? "i" : "",
1618 i->Pin.Cmp.crfD);
1619 ppHRegPPC(i->Pin.Cmp.srcL);
1620 vex_printf(",");
1621 ppPPCRH(i->Pin.Cmp.srcR);
1622 return;
1623 case Pin_Unary:
1624 vex_printf("%s ", showPPCUnaryOp(i->Pin.Unary.op));
1625 ppHRegPPC(i->Pin.Unary.dst);
1626 vex_printf(",");
1627 ppHRegPPC(i->Pin.Unary.src);
1628 return;
1629 case Pin_MulL:
1630 vex_printf("mul%c%c%s ",
1631 i->Pin.MulL.hi ? 'h' : 'l',
1632 i->Pin.MulL.sz32 ? 'w' : 'd',
1633 i->Pin.MulL.hi ? (i->Pin.MulL.syned ? "s" : "u") : "");
1634 ppHRegPPC(i->Pin.MulL.dst);
1635 vex_printf(",");
1636 ppHRegPPC(i->Pin.MulL.srcL);
1637 vex_printf(",");
1638 ppHRegPPC(i->Pin.MulL.srcR);
1639 return;
1640 case Pin_Div:
1641 vex_printf("div%c%s%s ",
1642 i->Pin.Div.sz32 ? 'w' : 'd',
1643 i->Pin.Div.extended ? "e" : "",
1644 i->Pin.Div.syned ? "" : "u");
1645 ppHRegPPC(i->Pin.Div.dst);
1646 vex_printf(",");
1647 ppHRegPPC(i->Pin.Div.srcL);
1648 vex_printf(",");
1649 ppHRegPPC(i->Pin.Div.srcR);
1650 return;
1651 case Pin_Call: {
1652 Int n;
1653 vex_printf("call: ");
1654 if (i->Pin.Call.cond.test != Pct_ALWAYS) {
1655 vex_printf("if (%s) ", showPPCCondCode(i->Pin.Call.cond));
1657 vex_printf("{ ");
1658 ppLoadImm(hregPPC_GPR10(mode64), i->Pin.Call.target, mode64);
1659 vex_printf(" ; mtctr r10 ; bctrl [");
1660 for (n = 0; n < 32; n++) {
1661 if (i->Pin.Call.argiregs & (1<<n)) {
1662 vex_printf("r%d", n);
1663 if ((i->Pin.Call.argiregs >> n) > 1)
1664 vex_printf(",");
1667 vex_printf(",");
1668 ppRetLoc(i->Pin.Call.rloc);
1669 vex_printf("] }");
1670 break;
1672 case Pin_XDirect:
1673 vex_printf("(xDirect) ");
1674 vex_printf("if (%s) { ",
1675 showPPCCondCode(i->Pin.XDirect.cond));
1676 if (mode64) {
1677 vex_printf("imm64 r30,0x%llx; ", i->Pin.XDirect.dstGA);
1678 vex_printf("std r30,");
1679 } else {
1680 vex_printf("imm32 r30,0x%llx; ", i->Pin.XDirect.dstGA);
1681 vex_printf("stw r30,");
1683 ppPPCAMode(i->Pin.XDirect.amCIA);
1684 vex_printf("; ");
1685 if (mode64) {
1686 vex_printf("imm64-fixed5 r30,$disp_cp_chain_me_to_%sEP; ",
1687 i->Pin.XDirect.toFastEP ? "fast" : "slow");
1688 } else {
1689 vex_printf("imm32-fixed2 r30,$disp_cp_chain_me_to_%sEP; ",
1690 i->Pin.XDirect.toFastEP ? "fast" : "slow");
1692 vex_printf("mtctr r30; bctrl }");
1693 return;
1694 case Pin_XIndir:
1695 vex_printf("(xIndir) ");
1696 vex_printf("if (%s) { ",
1697 showPPCCondCode(i->Pin.XIndir.cond));
1698 vex_printf("%s ", mode64 ? "std" : "stw");
1699 ppHRegPPC(i->Pin.XIndir.dstGA);
1700 vex_printf(",");
1701 ppPPCAMode(i->Pin.XIndir.amCIA);
1702 vex_printf("; ");
1703 vex_printf("imm%s r30,$disp_cp_xindir; ", mode64 ? "64" : "32");
1704 vex_printf("mtctr r30; bctr }");
1705 return;
1706 case Pin_XAssisted:
1707 vex_printf("(xAssisted) ");
1708 vex_printf("if (%s) { ",
1709 showPPCCondCode(i->Pin.XAssisted.cond));
1710 vex_printf("%s ", mode64 ? "std" : "stw");
1711 ppHRegPPC(i->Pin.XAssisted.dstGA);
1712 vex_printf(",");
1713 ppPPCAMode(i->Pin.XAssisted.amCIA);
1714 vex_printf("; ");
1715 vex_printf("li r31,$IRJumpKind_to_TRCVAL(%d); ",
1716 (Int)i->Pin.XAssisted.jk);
1717 vex_printf("imm%s r30,$disp_cp_xindir; ", mode64 ? "64" : "32");
1718 vex_printf("mtctr r30; bctr }");
1719 return;
1720 case Pin_CMov:
1721 vex_printf("cmov (%s) ", showPPCCondCode(i->Pin.CMov.cond));
1722 ppHRegPPC(i->Pin.CMov.dst);
1723 vex_printf(",");
1724 ppPPCRI(i->Pin.CMov.src);
1725 vex_printf(": ");
1726 if (i->Pin.CMov.cond.test != Pct_ALWAYS) {
1727 vex_printf("if (%s) ", showPPCCondCode(i->Pin.CMov.cond));
1729 vex_printf("{ ");
1730 if (i->Pin.CMov.src->tag == Pri_Imm) {
1731 ppLoadImm(i->Pin.CMov.dst, i->Pin.CMov.src->Pri.Imm, mode64);
1732 } else {
1733 ppMovReg(i->Pin.CMov.dst, i->Pin.CMov.src->Pri.Reg);
1735 vex_printf(" }");
1736 return;
1737 case Pin_Load: {
1738 Bool idxd = toBool(i->Pin.Load.src->tag == Pam_RR);
1739 UChar sz = i->Pin.Load.sz;
1740 HChar c_sz = sz==1 ? 'b' : sz==2 ? 'h' : sz==4 ? 'w' : 'd';
1741 vex_printf("l%c%s%s ", c_sz, sz==8 ? "" : "z", idxd ? "x" : "" );
1742 ppHRegPPC(i->Pin.Load.dst);
1743 vex_printf(",");
1744 ppPPCAMode(i->Pin.Load.src);
1745 return;
1747 case Pin_LoadL: {
1748 UChar sz = i->Pin.LoadL.sz;
1749 HChar c_sz = sz==1 ? 'b' : sz==2 ? 'h' : sz==4 ? 'w' : 'd';
1750 vex_printf("l%carx ", c_sz);
1751 ppHRegPPC(i->Pin.LoadL.dst);
1752 vex_printf(",%%r0,");
1753 ppHRegPPC(i->Pin.LoadL.src);
1754 return;
1756 case Pin_Store: {
1757 UChar sz = i->Pin.Store.sz;
1758 Bool idxd = toBool(i->Pin.Store.dst->tag == Pam_RR);
1759 HChar c_sz = sz==1 ? 'b' : sz==2 ? 'h' : sz==4 ? 'w' : /*8*/ 'd';
1760 vex_printf("st%c%s ", c_sz, idxd ? "x" : "" );
1761 ppHRegPPC(i->Pin.Store.src);
1762 vex_printf(",");
1763 ppPPCAMode(i->Pin.Store.dst);
1764 return;
1766 case Pin_StoreC: {
1767 UChar sz = i->Pin.StoreC.sz;
1768 HChar c_sz = sz==1 ? 'b' : sz==2 ? 'h' : sz==4 ? 'w' : 'd';
1769 vex_printf("st%ccx. ", c_sz);
1770 ppHRegPPC(i->Pin.StoreC.src);
1771 vex_printf(",%%r0,");
1772 ppHRegPPC(i->Pin.StoreC.dst);
1773 return;
1775 case Pin_Set: {
1776 PPCCondCode cc = i->Pin.Set.cond;
1777 vex_printf("set (%s),", showPPCCondCode(cc));
1778 ppHRegPPC(i->Pin.Set.dst);
1779 if (cc.test == Pct_ALWAYS) {
1780 vex_printf(": { li ");
1781 ppHRegPPC(i->Pin.Set.dst);
1782 vex_printf(",1 }");
1783 } else {
1784 vex_printf(": { mfcr r0 ; rlwinm ");
1785 ppHRegPPC(i->Pin.Set.dst);
1786 vex_printf(",r0,%u,31,31", cc.flag+1);
1787 if (cc.test == Pct_FALSE) {
1788 vex_printf("; xori ");
1789 ppHRegPPC(i->Pin.Set.dst);
1790 vex_printf(",");
1791 ppHRegPPC(i->Pin.Set.dst);
1792 vex_printf(",1");
1794 vex_printf(" }");
1796 return;
1798 case Pin_MfCR:
1799 vex_printf("mfcr ");
1800 ppHRegPPC(i->Pin.MfCR.dst);
1801 break;
1802 case Pin_MFence:
1803 vex_printf("mfence (=sync)");
1804 return;
1806 case Pin_FpUnary:
1807 vex_printf("%s ", showPPCFpOp(i->Pin.FpUnary.op));
1808 ppHRegPPC(i->Pin.FpUnary.dst);
1809 vex_printf(",");
1810 ppHRegPPC(i->Pin.FpUnary.src);
1811 return;
1812 case Pin_FpBinary:
1813 vex_printf("%s ", showPPCFpOp(i->Pin.FpBinary.op));
1814 ppHRegPPC(i->Pin.FpBinary.dst);
1815 vex_printf(",");
1816 ppHRegPPC(i->Pin.FpBinary.srcL);
1817 vex_printf(",");
1818 ppHRegPPC(i->Pin.FpBinary.srcR);
1819 return;
1820 case Pin_Fp128Unary:
1821 vex_printf("%s ", showPPCFpOp(i->Pin.Fp128Unary.op));
1822 ppHRegPPC(i->Pin.Fp128Unary.dst);
1823 vex_printf(",");
1824 ppHRegPPC(i->Pin.Fp128Unary.src);
1825 return;
1826 case Pin_Fp128Binary:
1827 vex_printf("%s ", showPPCFpOp(i->Pin.Fp128Binary.op));
1828 ppHRegPPC(i->Pin.Fp128Binary.dst);
1829 vex_printf(",");
1830 ppHRegPPC(i->Pin.Fp128Binary.srcL);
1831 vex_printf(",");
1832 ppHRegPPC(i->Pin.Fp128Binary.srcR);
1833 return;
1834 case Pin_Fp128Trinary:
1835 vex_printf("%s ", showPPCFpOp(i->Pin.Fp128Trinary.op));
1836 ppHRegPPC(i->Pin.Fp128Trinary.dst);
1837 vex_printf(",");
1838 ppHRegPPC(i->Pin.Fp128Trinary.srcL);
1839 vex_printf(",");
1840 ppHRegPPC(i->Pin.Fp128Trinary.srcR);
1841 return;
1842 case Pin_FpMulAcc:
1843 vex_printf("%s ", showPPCFpOp(i->Pin.FpMulAcc.op));
1844 ppHRegPPC(i->Pin.FpMulAcc.dst);
1845 vex_printf(",");
1846 ppHRegPPC(i->Pin.FpMulAcc.srcML);
1847 vex_printf(",");
1848 ppHRegPPC(i->Pin.FpMulAcc.srcMR);
1849 vex_printf(",");
1850 ppHRegPPC(i->Pin.FpMulAcc.srcAcc);
1851 return;
1852 case Pin_FpLdSt: {
1853 UChar sz = i->Pin.FpLdSt.sz;
1854 Bool idxd = toBool(i->Pin.FpLdSt.addr->tag == Pam_RR);
1855 if (i->Pin.FpLdSt.isLoad) {
1856 vex_printf("lf%c%s ",
1857 (sz==4 ? 's' : 'd'),
1858 idxd ? "x" : "" );
1859 ppHRegPPC(i->Pin.FpLdSt.reg);
1860 vex_printf(",");
1861 ppPPCAMode(i->Pin.FpLdSt.addr);
1862 } else {
1863 vex_printf("stf%c%s ",
1864 (sz==4 ? 's' : 'd'),
1865 idxd ? "x" : "" );
1866 ppHRegPPC(i->Pin.FpLdSt.reg);
1867 vex_printf(",");
1868 ppPPCAMode(i->Pin.FpLdSt.addr);
1870 return;
1872 case Pin_FpSTFIW:
1873 vex_printf("stfiwz ");
1874 ppHRegPPC(i->Pin.FpSTFIW.data);
1875 vex_printf(",0(");
1876 ppHRegPPC(i->Pin.FpSTFIW.addr);
1877 vex_printf(")");
1878 return;
1879 case Pin_FpRSP:
1880 vex_printf("frsp ");
1881 ppHRegPPC(i->Pin.FpRSP.dst);
1882 vex_printf(",");
1883 ppHRegPPC(i->Pin.FpRSP.src);
1884 return;
1885 case Pin_FpCftI: {
1886 const HChar* str = "fc?????";
1887 /* Note that "fcfids" is missing from below. That instruction would
1888 * satisfy the predicate:
1889 * (i->Pin.FpCftI.fromI == True && i->Pin.FpCftI.int32 == False)
1890 * which would go into a final "else" clause to make this if-else
1891 * block balanced. But we're able to implement fcfids by leveraging
1892 * the fcfid implementation, so it wasn't necessary to include it here.
1894 if (i->Pin.FpCftI.fromI == False && i->Pin.FpCftI.int32 == False)
1895 if (i->Pin.FpCftI.syned == True)
1896 str = "fctid";
1897 else
1898 str = "fctidu";
1899 else if (i->Pin.FpCftI.fromI == False && i->Pin.FpCftI.int32 == True)
1900 if (i->Pin.FpCftI.syned == True)
1901 str = "fctiw";
1902 else
1903 str = "fctiwu";
1904 else if (i->Pin.FpCftI.fromI == True && i->Pin.FpCftI.int32 == False) {
1905 if (i->Pin.FpCftI.syned == True) {
1906 str = "fcfid";
1907 } else {
1908 if (i->Pin.FpCftI.flt64 == True)
1909 str = "fcfidu";
1910 else
1911 str = "fcfidus";
1914 vex_printf("%s ", str);
1915 ppHRegPPC(i->Pin.FpCftI.dst);
1916 vex_printf(",");
1917 ppHRegPPC(i->Pin.FpCftI.src);
1918 return;
1920 case Pin_FpCMov:
1921 vex_printf("fpcmov (%s) ", showPPCCondCode(i->Pin.FpCMov.cond));
1922 ppHRegPPC(i->Pin.FpCMov.dst);
1923 vex_printf(",");
1924 ppHRegPPC(i->Pin.FpCMov.src);
1925 vex_printf(": ");
1926 vex_printf("if (fr_dst != fr_src) { ");
1927 if (i->Pin.FpCMov.cond.test != Pct_ALWAYS) {
1928 vex_printf("if (%s) { ", showPPCCondCode(i->Pin.FpCMov.cond));
1930 vex_printf("fmr ");
1931 ppHRegPPC(i->Pin.FpCMov.dst);
1932 vex_printf(",");
1933 ppHRegPPC(i->Pin.FpCMov.src);
1934 if (i->Pin.FpCMov.cond.test != Pct_ALWAYS)
1935 vex_printf(" }");
1936 vex_printf(" }");
1937 return;
1938 case Pin_FpLdFPSCR:
1939 vex_printf("mtfsf 0xFF,");
1940 ppHRegPPC(i->Pin.FpLdFPSCR.src);
1941 vex_printf(",0, %s", i->Pin.FpLdFPSCR.dfp_rm ? "1" : "0");
1942 return;
1943 case Pin_FpCmp:
1944 vex_printf("fcmpo %%cr1,");
1945 ppHRegPPC(i->Pin.FpCmp.srcL);
1946 vex_printf(",");
1947 ppHRegPPC(i->Pin.FpCmp.srcR);
1948 vex_printf("; mfcr ");
1949 ppHRegPPC(i->Pin.FpCmp.dst);
1950 vex_printf("; rlwinm ");
1951 ppHRegPPC(i->Pin.FpCmp.dst);
1952 vex_printf(",");
1953 ppHRegPPC(i->Pin.FpCmp.dst);
1954 vex_printf(",8,28,31");
1955 return;
1957 case Pin_RdWrLR:
1958 vex_printf("%s ", i->Pin.RdWrLR.wrLR ? "mtlr" : "mflr");
1959 ppHRegPPC(i->Pin.RdWrLR.gpr);
1960 return;
1962 case Pin_AvLdSt: {
1963 UChar sz = i->Pin.AvLdSt.sz;
1964 const HChar* str_size;
1965 if (i->Pin.AvLdSt.addr->tag == Pam_IR) {
1966 ppLoadImm(hregPPC_GPR30(mode64),
1967 i->Pin.AvLdSt.addr->Pam.IR.index, mode64);
1968 vex_printf(" ; ");
1970 str_size = sz==1 ? "eb" : sz==2 ? "eh" : sz==4 ? "ew" : "";
1971 if (i->Pin.AvLdSt.isLoad)
1972 vex_printf("lv%sx ", str_size);
1973 else
1974 vex_printf("stv%sx ", str_size);
1975 ppHRegPPC(i->Pin.AvLdSt.reg);
1976 vex_printf(",");
1977 if (i->Pin.AvLdSt.addr->tag == Pam_IR)
1978 vex_printf("%%r30");
1979 else
1980 ppHRegPPC(i->Pin.AvLdSt.addr->Pam.RR.index);
1981 vex_printf(",");
1982 ppHRegPPC(i->Pin.AvLdSt.addr->Pam.RR.base);
1983 return;
1985 case Pin_AvUnary:
1986 vex_printf("%s ", showPPCAvOp(i->Pin.AvUnary.op));
1987 ppHRegPPC(i->Pin.AvUnary.dst);
1988 vex_printf(",");
1989 ppHRegPPC(i->Pin.AvUnary.src);
1990 return;
1991 case Pin_AvBinary:
1992 vex_printf("%s ", showPPCAvOp(i->Pin.AvBinary.op));
1993 ppHRegPPC(i->Pin.AvBinary.dst);
1994 vex_printf(",");
1995 ppHRegPPC(i->Pin.AvBinary.srcL);
1996 vex_printf(",");
1997 ppHRegPPC(i->Pin.AvBinary.srcR);
1998 return;
1999 case Pin_AvBinaryInt:
2000 vex_printf("%s ", showPPCAvOp(i->Pin.AvBinaryInt.op));
2001 ppHRegPPC(i->Pin.AvBinaryInt.dst);
2002 vex_printf(",");
2003 ppHRegPPC(i->Pin.AvBinaryInt.src);
2004 vex_printf(",");
2005 ppPPCRI(i->Pin.AvBinaryInt.val);
2006 return;
2007 case Pin_AvBin8x16:
2008 vex_printf("%s(b) ", showPPCAvOp(i->Pin.AvBin8x16.op));
2009 ppHRegPPC(i->Pin.AvBin8x16.dst);
2010 vex_printf(",");
2011 ppHRegPPC(i->Pin.AvBin8x16.srcL);
2012 vex_printf(",");
2013 ppHRegPPC(i->Pin.AvBin8x16.srcR);
2014 return;
2015 case Pin_AvBin16x8:
2016 vex_printf("%s(h) ", showPPCAvOp(i->Pin.AvBin16x8.op));
2017 ppHRegPPC(i->Pin.AvBin16x8.dst);
2018 vex_printf(",");
2019 ppHRegPPC(i->Pin.AvBin16x8.srcL);
2020 vex_printf(",");
2021 ppHRegPPC(i->Pin.AvBin16x8.srcR);
2022 return;
2023 case Pin_AvBin32x4:
2024 vex_printf("%s(w) ", showPPCAvOp(i->Pin.AvBin32x4.op));
2025 ppHRegPPC(i->Pin.AvBin32x4.dst);
2026 vex_printf(",");
2027 ppHRegPPC(i->Pin.AvBin32x4.srcL);
2028 vex_printf(",");
2029 ppHRegPPC(i->Pin.AvBin32x4.srcR);
2030 return;
2031 case Pin_AvBin64x2:
2032 vex_printf("%s(w) ", showPPCAvOp(i->Pin.AvBin64x2.op));
2033 ppHRegPPC(i->Pin.AvBin64x2.dst);
2034 vex_printf(",");
2035 ppHRegPPC(i->Pin.AvBin64x2.srcL);
2036 vex_printf(",");
2037 ppHRegPPC(i->Pin.AvBin64x2.srcR);
2038 return;
2039 case Pin_AvBin32Fx4:
2040 vex_printf("%s ", showPPCAvFpOp(i->Pin.AvBin32Fx4.op));
2041 ppHRegPPC(i->Pin.AvBin32Fx4.dst);
2042 vex_printf(",");
2043 ppHRegPPC(i->Pin.AvBin32Fx4.srcL);
2044 vex_printf(",");
2045 ppHRegPPC(i->Pin.AvBin32Fx4.srcR);
2046 return;
2047 case Pin_AvUn32Fx4:
2048 vex_printf("%s ", showPPCAvFpOp(i->Pin.AvUn32Fx4.op));
2049 ppHRegPPC(i->Pin.AvUn32Fx4.dst);
2050 vex_printf(",");
2051 ppHRegPPC(i->Pin.AvUn32Fx4.src);
2052 return;
2053 case Pin_AvPerm:
2054 vex_printf("vperm ");
2055 ppHRegPPC(i->Pin.AvPerm.dst);
2056 vex_printf(",");
2057 ppHRegPPC(i->Pin.AvPerm.srcL);
2058 vex_printf(",");
2059 ppHRegPPC(i->Pin.AvPerm.srcR);
2060 vex_printf(",");
2061 ppHRegPPC(i->Pin.AvPerm.ctl);
2062 return;
2064 case Pin_AvSel:
2065 vex_printf("vsel ");
2066 ppHRegPPC(i->Pin.AvSel.dst);
2067 vex_printf(",");
2068 ppHRegPPC(i->Pin.AvSel.srcL);
2069 vex_printf(",");
2070 ppHRegPPC(i->Pin.AvSel.srcR);
2071 vex_printf(",");
2072 ppHRegPPC(i->Pin.AvSel.ctl);
2073 return;
2075 case Pin_AvSh:
2076 /* This only generates the following instructions with RA
2077 * register number set to 0.
2079 if (i->Pin.AvSh.addr->tag == Pam_IR) {
2080 ppLoadImm(hregPPC_GPR30(mode64),
2081 i->Pin.AvSh.addr->Pam.IR.index, mode64);
2082 vex_printf(" ; ");
2085 if (i->Pin.AvSh.shLeft)
2086 vex_printf("lvsl ");
2087 else
2088 vex_printf("lvsr ");
2090 ppHRegPPC(i->Pin.AvSh.dst);
2091 if (i->Pin.AvSh.addr->tag == Pam_IR)
2092 vex_printf("%%r30");
2093 else
2094 ppHRegPPC(i->Pin.AvSh.addr->Pam.RR.index);
2095 vex_printf(",");
2096 ppHRegPPC(i->Pin.AvSh.addr->Pam.RR.base);
2097 return;
2099 case Pin_AvShlDbl:
2100 vex_printf("vsldoi ");
2101 ppHRegPPC(i->Pin.AvShlDbl.dst);
2102 vex_printf(",");
2103 ppHRegPPC(i->Pin.AvShlDbl.srcL);
2104 vex_printf(",");
2105 ppHRegPPC(i->Pin.AvShlDbl.srcR);
2106 vex_printf(",%d", i->Pin.AvShlDbl.shift);
2107 return;
2109 case Pin_AvSplat: {
2110 UChar sz = i->Pin.AvSplat.sz;
2111 HChar ch_sz = toUChar( (sz == 8) ? 'b' : (sz == 16) ? 'h' : 'w' );
2112 vex_printf("vsplt%s%c ",
2113 i->Pin.AvSplat.src->tag == Pvi_Imm ? "is" : "", ch_sz);
2114 ppHRegPPC(i->Pin.AvSplat.dst);
2115 vex_printf(",");
2116 ppPPCVI5s(i->Pin.AvSplat.src);
2117 if (i->Pin.AvSplat.src->tag == Pvi_Reg)
2118 vex_printf(", %d", (128/sz)-1); /* louis lane */
2119 return;
2122 case Pin_AvCMov:
2123 vex_printf("avcmov (%s) ", showPPCCondCode(i->Pin.AvCMov.cond));
2124 ppHRegPPC(i->Pin.AvCMov.dst);
2125 vex_printf(",");
2126 ppHRegPPC(i->Pin.AvCMov.src);
2127 vex_printf(": ");
2128 vex_printf("if (v_dst != v_src) { ");
2129 if (i->Pin.AvCMov.cond.test != Pct_ALWAYS) {
2130 vex_printf("if (%s) { ", showPPCCondCode(i->Pin.AvCMov.cond));
2132 vex_printf("vmr ");
2133 ppHRegPPC(i->Pin.AvCMov.dst);
2134 vex_printf(",");
2135 ppHRegPPC(i->Pin.AvCMov.src);
2136 if (i->Pin.FpCMov.cond.test != Pct_ALWAYS)
2137 vex_printf(" }");
2138 vex_printf(" }");
2139 return;
2141 case Pin_AvLdVSCR:
2142 vex_printf("mtvscr ");
2143 ppHRegPPC(i->Pin.AvLdVSCR.src);
2144 return;
2146 case Pin_AvCipherV128Unary:
2147 vex_printf("%s(w) ", showPPCAvOp(i->Pin.AvCipherV128Unary.op));
2148 ppHRegPPC(i->Pin.AvCipherV128Unary.dst);
2149 vex_printf(",");
2150 ppHRegPPC(i->Pin.AvCipherV128Unary.src);
2151 return;
2153 case Pin_AvCipherV128Binary:
2154 vex_printf("%s(w) ", showPPCAvOp(i->Pin.AvCipherV128Binary.op));
2155 ppHRegPPC(i->Pin.AvCipherV128Binary.dst);
2156 vex_printf(",");
2157 ppHRegPPC(i->Pin.AvCipherV128Binary.srcL);
2158 vex_printf(",");
2159 ppHRegPPC(i->Pin.AvCipherV128Binary.srcR);
2160 return;
2162 case Pin_AvHashV128Binary:
2163 vex_printf("%s(w) ", showPPCAvOp(i->Pin.AvHashV128Binary.op));
2164 ppHRegPPC(i->Pin.AvHashV128Binary.dst);
2165 vex_printf(",");
2166 ppHRegPPC(i->Pin.AvHashV128Binary.src);
2167 vex_printf(",");
2168 ppPPCRI(i->Pin.AvHashV128Binary.s_field);
2169 return;
2171 case Pin_AvBCDV128Binary:
2172 vex_printf("%s(w) ", showPPCAvOp(i->Pin.AvBCDV128Binary.op));
2173 ppHRegPPC(i->Pin.AvBCDV128Binary.dst);
2174 vex_printf(",");
2175 ppHRegPPC(i->Pin.AvBCDV128Binary.src1);
2176 vex_printf(",");
2177 ppHRegPPC(i->Pin.AvBCDV128Binary.src2);
2178 return;
2180 case Pin_Dfp64Unary:
2181 vex_printf("%s ", showPPCFpOp(i->Pin.Dfp64Unary.op));
2182 ppHRegPPC(i->Pin.Dfp64Unary.dst);
2183 vex_printf(",");
2184 ppHRegPPC(i->Pin.Dfp64Unary.src);
2185 return;
2187 case Pin_Dfp64Binary:
2188 vex_printf("%s ", showPPCFpOp(i->Pin.Dfp64Binary.op));
2189 ppHRegPPC(i->Pin.Dfp64Binary.dst);
2190 vex_printf(",");
2191 ppHRegPPC(i->Pin.Dfp64Binary.srcL);
2192 vex_printf(",");
2193 ppHRegPPC(i->Pin.Dfp64Binary.srcR);
2194 return;
2196 case Pin_DfpShift:
2197 vex_printf("%s ", showPPCFpOp(i->Pin.DfpShift.op));
2198 ppHRegPPC(i->Pin.DfpShift.dst);
2199 vex_printf(",");
2200 ppHRegPPC(i->Pin.DfpShift.src);
2201 vex_printf(",");
2202 ppPPCRI(i->Pin.DfpShift.shift);
2203 return;
2205 case Pin_Dfp128Unary:
2206 vex_printf("%s ", showPPCFpOp(i->Pin.Dfp128Unary.op));
2207 ppHRegPPC(i->Pin.Dfp128Unary.dst_hi);
2208 vex_printf(",");
2209 ppHRegPPC(i->Pin.Dfp128Unary.src_hi);
2210 return;
2212 case Pin_Dfp128Binary:
2213 vex_printf("%s ", showPPCFpOp(i->Pin.Dfp128Binary.op));
2214 ppHRegPPC(i->Pin.Dfp128Binary.dst_hi);
2215 vex_printf(",");
2216 ppHRegPPC(i->Pin.Dfp128Binary.srcR_hi);
2217 return;
2219 case Pin_DfpShift128:
2220 vex_printf("%s ", showPPCFpOp(i->Pin.DfpShift128.op));
2221 ppHRegPPC(i->Pin.DfpShift128.dst_hi);
2222 vex_printf(",");
2223 ppHRegPPC(i->Pin.DfpShift128.src_hi);
2224 vex_printf(",");
2225 ppPPCRI(i->Pin.DfpShift128.shift);
2226 return;
2228 case Pin_DfpRound:
2229 vex_printf("drintx ");
2230 ppHRegPPC(i->Pin.DfpRound.dst);
2231 vex_printf(",");
2232 ppHRegPPC(i->Pin.DfpRound.src);
2233 vex_printf(",");
2234 ppPPCRI(i->Pin.DfpRound.r_rmc); /* R in bit 3 and RMC in bits 2:0 */
2235 return;
2237 case Pin_DfpRound128:
2238 vex_printf("drintxq ");
2239 ppHRegPPC(i->Pin.DfpRound128.dst_hi);
2240 vex_printf(",");
2241 ppHRegPPC(i->Pin.DfpRound128.src_hi);
2242 vex_printf(",");
2243 ppPPCRI(i->Pin.DfpRound128.r_rmc); /* R in bit 3 and RMC in bits 2:0 */
2244 return;
2246 case Pin_DfpQuantize:
2247 vex_printf("%s ", showPPCFpOp(i->Pin.DfpQuantize.op));
2248 ppHRegPPC(i->Pin.DfpQuantize.dst);
2249 vex_printf(",");
2250 ppHRegPPC(i->Pin.DfpQuantize.srcL);
2251 vex_printf(",");
2252 ppHRegPPC(i->Pin.DfpQuantize.srcR);
2253 vex_printf(",");
2254 ppPPCRI(i->Pin.DfpQuantize.rmc);
2255 return;
2257 case Pin_DfpQuantize128:
2258 /* Dst is used to pass in left source and return result */
2259 vex_printf("dquaq ");
2260 ppHRegPPC(i->Pin.DfpQuantize128.dst_hi);
2261 vex_printf(",");
2262 ppHRegPPC(i->Pin.DfpQuantize128.dst_hi);
2263 vex_printf(",");
2264 ppHRegPPC(i->Pin.DfpQuantize128.src_hi);
2265 vex_printf(",");
2266 ppPPCRI(i->Pin.DfpQuantize128.rmc);
2267 return;
2269 case Pin_DfpD128toD64:
2270 vex_printf("%s ", showPPCFpOp(i->Pin.DfpD128toD64.op));
2271 ppHRegPPC(i->Pin.DfpD128toD64.dst);
2272 vex_printf(",");
2273 ppHRegPPC(i->Pin.DfpD128toD64.src_hi);
2274 vex_printf(",");
2275 return;
2277 case Pin_DfpI64StoD128:
2278 vex_printf("%s ", showPPCFpOp(i->Pin.DfpI64StoD128.op));
2279 ppHRegPPC(i->Pin.DfpI64StoD128.dst_hi);
2280 vex_printf(",");
2281 ppHRegPPC(i->Pin.DfpI64StoD128.src);
2282 vex_printf(",");
2283 return;
2284 case Pin_ExtractExpD128:
2285 vex_printf("dxexq ");
2286 ppHRegPPC(i->Pin.ExtractExpD128.dst);
2287 vex_printf(",");
2288 ppHRegPPC(i->Pin.ExtractExpD128.src_hi);
2289 return;
2290 case Pin_InsertExpD128:
2291 vex_printf("diexq ");
2292 ppHRegPPC(i->Pin.InsertExpD128.dst_hi);
2293 vex_printf(",");
2294 ppHRegPPC(i->Pin.InsertExpD128.srcL);
2295 vex_printf(",");
2296 ppHRegPPC(i->Pin.InsertExpD128.srcR_hi);
2297 return;
2298 case Pin_Dfp64Cmp:
2299 vex_printf("dcmpo %%cr1,");
2300 ppHRegPPC(i->Pin.Dfp64Cmp.srcL);
2301 vex_printf(",");
2302 ppHRegPPC(i->Pin.Dfp64Cmp.srcR);
2303 vex_printf("; mfcr ");
2304 ppHRegPPC(i->Pin.Dfp64Cmp.dst);
2305 vex_printf("; rlwinm ");
2306 ppHRegPPC(i->Pin.Dfp64Cmp.dst);
2307 vex_printf(",");
2308 ppHRegPPC(i->Pin.Dfp64Cmp.dst);
2309 vex_printf(",8,28,31");
2310 return;
2311 case Pin_Dfp128Cmp:
2312 vex_printf("dcmpoq %%cr1,");
2313 ppHRegPPC(i->Pin.Dfp128Cmp.srcL_hi);
2314 vex_printf(",");
2315 ppHRegPPC(i->Pin.Dfp128Cmp.srcR_hi);
2316 vex_printf("; mfcr ");
2317 ppHRegPPC(i->Pin.Dfp128Cmp.dst);
2318 vex_printf("; rlwinm ");
2319 ppHRegPPC(i->Pin.Dfp128Cmp.dst);
2320 vex_printf(",");
2321 ppHRegPPC(i->Pin.Dfp128Cmp.dst);
2322 vex_printf(",8,28,31");
2323 return;
2324 case Pin_EvCheck:
2325 /* Note that the counter dec is 32 bit even in 64-bit mode. */
2326 vex_printf("(evCheck) ");
2327 vex_printf("lwz r30,");
2328 ppPPCAMode(i->Pin.EvCheck.amCounter);
2329 vex_printf("; addic. r30,r30,-1; ");
2330 vex_printf("stw r30,");
2331 ppPPCAMode(i->Pin.EvCheck.amCounter);
2332 vex_printf("; bge nofail; lwz r30,");
2333 ppPPCAMode(i->Pin.EvCheck.amFailAddr);
2334 vex_printf("; mtctr r30; bctr; nofail:");
2335 return;
2336 case Pin_ProfInc:
2337 if (mode64) {
2338 vex_printf("(profInc) imm64-fixed5 r30,$NotKnownYet; ");
2339 vex_printf("ld r29,(r30); addi r29,r29,1; std r29,(r30)");
2340 } else {
2341 vex_printf("(profInc) imm32-fixed2 r30,$NotKnownYet; ");
2342 vex_printf("lwz r29,4(r30); addic. r29,r29,1; stw r29,4(r30)");
2343 vex_printf("lwz r29,0(r30); addze r29,r29; stw r29,0(r30)");
2345 break;
2346 default:
2347 vex_printf("\nppPPCInstr: No such tag(%d)\n", (Int)i->tag);
2348 vpanic("ppPPCInstr");
2352 /* --------- Helpers for register allocation. --------- */
2354 void getRegUsage_PPCInstr ( HRegUsage* u, const PPCInstr* i, Bool mode64 )
2356 initHRegUsage(u);
2357 switch (i->tag) {
2358 case Pin_LI:
2359 addHRegUse(u, HRmWrite, i->Pin.LI.dst);
2360 break;
2361 case Pin_Alu:
2362 addHRegUse(u, HRmRead, i->Pin.Alu.srcL);
2363 addRegUsage_PPCRH(u, i->Pin.Alu.srcR);
2364 addHRegUse(u, HRmWrite, i->Pin.Alu.dst);
2366 // or Rd,Rs,Rs == mr Rd,Rs
2367 if ((i->Pin.Alu.op == Palu_OR)
2368 && (i->Pin.Alu.srcR->tag == Prh_Reg)
2369 && sameHReg(i->Pin.Alu.srcR->Prh.Reg.reg, i->Pin.Alu.srcL)) {
2370 u->isRegRegMove = True;
2371 u->regMoveSrc = i->Pin.Alu.srcL;
2372 u->regMoveDst = i->Pin.Alu.dst;
2374 return;
2375 case Pin_Shft:
2376 addHRegUse(u, HRmRead, i->Pin.Shft.srcL);
2377 addRegUsage_PPCRH(u, i->Pin.Shft.srcR);
2378 addHRegUse(u, HRmWrite, i->Pin.Shft.dst);
2379 return;
2380 case Pin_AddSubC:
2381 addHRegUse(u, HRmWrite, i->Pin.AddSubC.dst);
2382 addHRegUse(u, HRmRead, i->Pin.AddSubC.srcL);
2383 addHRegUse(u, HRmRead, i->Pin.AddSubC.srcR);
2384 return;
2385 case Pin_Cmp:
2386 addHRegUse(u, HRmRead, i->Pin.Cmp.srcL);
2387 addRegUsage_PPCRH(u, i->Pin.Cmp.srcR);
2388 return;
2389 case Pin_Unary:
2390 addHRegUse(u, HRmWrite, i->Pin.Unary.dst);
2391 addHRegUse(u, HRmRead, i->Pin.Unary.src);
2392 return;
2393 case Pin_MulL:
2394 addHRegUse(u, HRmWrite, i->Pin.MulL.dst);
2395 addHRegUse(u, HRmRead, i->Pin.MulL.srcL);
2396 addHRegUse(u, HRmRead, i->Pin.MulL.srcR);
2397 return;
2398 case Pin_Div:
2399 addHRegUse(u, HRmWrite, i->Pin.Div.dst);
2400 addHRegUse(u, HRmRead, i->Pin.Div.srcL);
2401 addHRegUse(u, HRmRead, i->Pin.Div.srcR);
2402 return;
2403 case Pin_Call: {
2404 UInt argir;
2405 /* This is a bit subtle. */
2406 /* First off, claim it trashes all the caller-saved regs
2407 which fall within the register allocator's jurisdiction.
2408 These I believe to be:
2409 mode32: r3 to r12
2410 mode64: r3 to r10
2412 /* XXXXXXXXXXXXXXXXX BUG! This doesn't say anything about the FP
2413 or Altivec registers. We get away with this ONLY because
2414 getAllocatableRegs_PPC gives the allocator callee-saved fp
2415 and Altivec regs, and no caller-save ones. */
2416 addHRegUse(u, HRmWrite, hregPPC_GPR3(mode64));
2417 addHRegUse(u, HRmWrite, hregPPC_GPR4(mode64));
2418 addHRegUse(u, HRmWrite, hregPPC_GPR5(mode64));
2419 addHRegUse(u, HRmWrite, hregPPC_GPR6(mode64));
2420 addHRegUse(u, HRmWrite, hregPPC_GPR7(mode64));
2421 addHRegUse(u, HRmWrite, hregPPC_GPR8(mode64));
2422 addHRegUse(u, HRmWrite, hregPPC_GPR9(mode64));
2423 addHRegUse(u, HRmWrite, hregPPC_GPR10(mode64));
2424 if (!mode64) {
2425 addHRegUse(u, HRmWrite, hregPPC_GPR11(mode64));
2426 addHRegUse(u, HRmWrite, hregPPC_GPR12(mode64));
2429 /* Now we have to state any parameter-carrying registers
2430 which might be read. This depends on the argiregs field. */
2431 argir = i->Pin.Call.argiregs;
2432 if (argir &(1<<10)) addHRegUse(u, HRmRead, hregPPC_GPR10(mode64));
2433 if (argir & (1<<9)) addHRegUse(u, HRmRead, hregPPC_GPR9(mode64));
2434 if (argir & (1<<8)) addHRegUse(u, HRmRead, hregPPC_GPR8(mode64));
2435 if (argir & (1<<7)) addHRegUse(u, HRmRead, hregPPC_GPR7(mode64));
2436 if (argir & (1<<6)) addHRegUse(u, HRmRead, hregPPC_GPR6(mode64));
2437 if (argir & (1<<5)) addHRegUse(u, HRmRead, hregPPC_GPR5(mode64));
2438 if (argir & (1<<4)) addHRegUse(u, HRmRead, hregPPC_GPR4(mode64));
2439 if (argir & (1<<3)) addHRegUse(u, HRmRead, hregPPC_GPR3(mode64));
2441 vassert(0 == (argir & ~((1<<3)|(1<<4)|(1<<5)|(1<<6)
2442 |(1<<7)|(1<<8)|(1<<9)|(1<<10))));
2444 /* Finally, there is the issue that the insn trashes a
2445 register because the literal target address has to be
2446 loaded into a register. %r10 seems a suitable victim.
2447 (Can't use %r0, as some insns interpret it as value zero). */
2448 addHRegUse(u, HRmWrite, hregPPC_GPR10(mode64));
2449 /* Upshot of this is that the assembler really must use %r10,
2450 and no other, as a destination temporary. */
2451 return;
2453 /* XDirect/XIndir/XAssisted are also a bit subtle. They
2454 conditionally exit the block. Hence we only need to list (1)
2455 the registers that they read, and (2) the registers that they
2456 write in the case where the block is not exited. (2) is empty,
2457 hence only (1) is relevant here. */
2458 case Pin_XDirect:
2459 addRegUsage_PPCAMode(u, i->Pin.XDirect.amCIA);
2460 return;
2461 case Pin_XIndir:
2462 addHRegUse(u, HRmRead, i->Pin.XIndir.dstGA);
2463 addRegUsage_PPCAMode(u, i->Pin.XIndir.amCIA);
2464 return;
2465 case Pin_XAssisted:
2466 addHRegUse(u, HRmRead, i->Pin.XAssisted.dstGA);
2467 addRegUsage_PPCAMode(u, i->Pin.XAssisted.amCIA);
2468 return;
2469 case Pin_CMov:
2470 addRegUsage_PPCRI(u, i->Pin.CMov.src);
2471 addHRegUse(u, HRmWrite, i->Pin.CMov.dst);
2472 return;
2473 case Pin_Load:
2474 addRegUsage_PPCAMode(u, i->Pin.Load.src);
2475 addHRegUse(u, HRmWrite, i->Pin.Load.dst);
2476 return;
2477 case Pin_LoadL:
2478 addHRegUse(u, HRmRead, i->Pin.LoadL.src);
2479 addHRegUse(u, HRmWrite, i->Pin.LoadL.dst);
2480 return;
2481 case Pin_Store:
2482 addHRegUse(u, HRmRead, i->Pin.Store.src);
2483 addRegUsage_PPCAMode(u, i->Pin.Store.dst);
2484 return;
2485 case Pin_StoreC:
2486 addHRegUse(u, HRmRead, i->Pin.StoreC.src);
2487 addHRegUse(u, HRmRead, i->Pin.StoreC.dst);
2488 return;
2489 case Pin_Set:
2490 addHRegUse(u, HRmWrite, i->Pin.Set.dst);
2491 return;
2492 case Pin_MfCR:
2493 addHRegUse(u, HRmWrite, i->Pin.MfCR.dst);
2494 return;
2495 case Pin_MFence:
2496 return;
2498 case Pin_FpUnary:
2499 addHRegUse(u, HRmWrite, i->Pin.FpUnary.dst);
2500 addHRegUse(u, HRmRead, i->Pin.FpUnary.src);
2502 if (i->Pin.FpUnary.op == Pfp_MOV) {
2503 u->isRegRegMove = True;
2504 u->regMoveSrc = i->Pin.FpUnary.src;
2505 u->regMoveDst = i->Pin.FpUnary.dst;
2507 return;
2508 case Pin_FpBinary:
2509 addHRegUse(u, HRmWrite, i->Pin.FpBinary.dst);
2510 addHRegUse(u, HRmRead, i->Pin.FpBinary.srcL);
2511 addHRegUse(u, HRmRead, i->Pin.FpBinary.srcR);
2512 return;
2514 case Pin_Fp128Unary:
2515 addHRegUse(u, HRmWrite, i->Pin.Fp128Unary.dst);
2516 addHRegUse(u, HRmRead, i->Pin.Fp128Unary.src);
2517 return;
2518 case Pin_Fp128Binary:
2519 addHRegUse(u, HRmWrite, i->Pin.Fp128Binary.dst);
2520 addHRegUse(u, HRmRead, i->Pin.Fp128Binary.srcL);
2521 addHRegUse(u, HRmRead, i->Pin.Fp128Binary.srcR);
2522 return;
2523 case Pin_Fp128Trinary:
2524 addHRegUse(u, HRmModify, i->Pin.Fp128Trinary.dst);
2525 addHRegUse(u, HRmRead, i->Pin.Fp128Trinary.srcL);
2526 addHRegUse(u, HRmRead, i->Pin.Fp128Trinary.srcR);
2527 return;
2528 case Pin_FpMulAcc:
2529 addHRegUse(u, HRmWrite, i->Pin.FpMulAcc.dst);
2530 addHRegUse(u, HRmRead, i->Pin.FpMulAcc.srcML);
2531 addHRegUse(u, HRmRead, i->Pin.FpMulAcc.srcMR);
2532 addHRegUse(u, HRmRead, i->Pin.FpMulAcc.srcAcc);
2533 return;
2534 case Pin_FpLdSt:
2535 addHRegUse(u, (i->Pin.FpLdSt.isLoad ? HRmWrite : HRmRead),
2536 i->Pin.FpLdSt.reg);
2537 addRegUsage_PPCAMode(u, i->Pin.FpLdSt.addr);
2538 return;
2539 case Pin_FpSTFIW:
2540 addHRegUse(u, HRmRead, i->Pin.FpSTFIW.addr);
2541 addHRegUse(u, HRmRead, i->Pin.FpSTFIW.data);
2542 return;
2543 case Pin_FpRSP:
2544 addHRegUse(u, HRmWrite, i->Pin.FpRSP.dst);
2545 addHRegUse(u, HRmRead, i->Pin.FpRSP.src);
2546 return;
2547 case Pin_FpCftI:
2548 addHRegUse(u, HRmWrite, i->Pin.FpCftI.dst);
2549 addHRegUse(u, HRmRead, i->Pin.FpCftI.src);
2550 return;
2551 case Pin_FpCMov:
2552 addHRegUse(u, HRmModify, i->Pin.FpCMov.dst);
2553 addHRegUse(u, HRmRead, i->Pin.FpCMov.src);
2554 return;
2555 case Pin_FpLdFPSCR:
2556 addHRegUse(u, HRmRead, i->Pin.FpLdFPSCR.src);
2557 return;
2558 case Pin_FpCmp:
2559 addHRegUse(u, HRmWrite, i->Pin.FpCmp.dst);
2560 addHRegUse(u, HRmRead, i->Pin.FpCmp.srcL);
2561 addHRegUse(u, HRmRead, i->Pin.FpCmp.srcR);
2562 return;
2564 case Pin_RdWrLR:
2565 addHRegUse(u, (i->Pin.RdWrLR.wrLR ? HRmRead : HRmWrite),
2566 i->Pin.RdWrLR.gpr);
2567 return;
2569 case Pin_AvLdSt:
2570 addHRegUse(u, (i->Pin.AvLdSt.isLoad ? HRmWrite : HRmRead),
2571 i->Pin.AvLdSt.reg);
2572 if (i->Pin.AvLdSt.addr->tag == Pam_IR)
2573 addHRegUse(u, HRmWrite, hregPPC_GPR30(mode64));
2574 addRegUsage_PPCAMode(u, i->Pin.AvLdSt.addr);
2575 return;
2576 case Pin_AvUnary:
2577 addHRegUse(u, HRmWrite, i->Pin.AvUnary.dst);
2578 addHRegUse(u, HRmRead, i->Pin.AvUnary.src);
2579 return;
2580 case Pin_AvBinary:
2581 if (i->Pin.AvBinary.op == Pav_XOR
2582 && sameHReg(i->Pin.AvBinary.dst, i->Pin.AvBinary.srcL)
2583 && sameHReg(i->Pin.AvBinary.dst, i->Pin.AvBinary.srcR)) {
2584 /* reg-alloc needs to understand 'xor r,r,r' as a write of r */
2585 /* (as opposed to a rite of passage :-) */
2586 addHRegUse(u, HRmWrite, i->Pin.AvBinary.dst);
2587 } else {
2588 addHRegUse(u, HRmWrite, i->Pin.AvBinary.dst);
2589 addHRegUse(u, HRmRead, i->Pin.AvBinary.srcL);
2590 addHRegUse(u, HRmRead, i->Pin.AvBinary.srcR);
2592 return;
2593 case Pin_AvBinaryInt:
2594 addHRegUse(u, HRmWrite, i->Pin.AvBinaryInt.dst);
2595 addHRegUse(u, HRmRead, i->Pin.AvBinaryInt.src);
2596 return;
2597 case Pin_AvBin8x16:
2598 addHRegUse(u, HRmWrite, i->Pin.AvBin8x16.dst);
2599 addHRegUse(u, HRmRead, i->Pin.AvBin8x16.srcL);
2600 addHRegUse(u, HRmRead, i->Pin.AvBin8x16.srcR);
2601 return;
2602 case Pin_AvBin16x8:
2603 addHRegUse(u, HRmWrite, i->Pin.AvBin16x8.dst);
2604 addHRegUse(u, HRmRead, i->Pin.AvBin16x8.srcL);
2605 addHRegUse(u, HRmRead, i->Pin.AvBin16x8.srcR);
2606 return;
2607 case Pin_AvBin32x4:
2608 addHRegUse(u, HRmWrite, i->Pin.AvBin32x4.dst);
2609 addHRegUse(u, HRmRead, i->Pin.AvBin32x4.srcL);
2610 addHRegUse(u, HRmRead, i->Pin.AvBin32x4.srcR);
2611 return;
2612 case Pin_AvBin64x2:
2613 addHRegUse(u, HRmWrite, i->Pin.AvBin64x2.dst);
2614 addHRegUse(u, HRmRead, i->Pin.AvBin64x2.srcL);
2615 addHRegUse(u, HRmRead, i->Pin.AvBin64x2.srcR);
2616 return;
2617 case Pin_AvBin32Fx4:
2618 addHRegUse(u, HRmWrite, i->Pin.AvBin32Fx4.dst);
2619 addHRegUse(u, HRmRead, i->Pin.AvBin32Fx4.srcL);
2620 addHRegUse(u, HRmRead, i->Pin.AvBin32Fx4.srcR);
2621 if (i->Pin.AvBin32Fx4.op == Pavfp_MULF)
2622 addHRegUse(u, HRmWrite, hregPPC_VR29(mode64));
2623 return;
2624 case Pin_AvUn32Fx4:
2625 addHRegUse(u, HRmWrite, i->Pin.AvUn32Fx4.dst);
2626 addHRegUse(u, HRmRead, i->Pin.AvUn32Fx4.src);
2627 return;
2628 case Pin_AvPerm:
2629 addHRegUse(u, HRmWrite, i->Pin.AvPerm.dst);
2630 addHRegUse(u, HRmRead, i->Pin.AvPerm.srcL);
2631 addHRegUse(u, HRmRead, i->Pin.AvPerm.srcR);
2632 addHRegUse(u, HRmRead, i->Pin.AvPerm.ctl);
2633 return;
2634 case Pin_AvSel:
2635 addHRegUse(u, HRmWrite, i->Pin.AvSel.dst);
2636 addHRegUse(u, HRmRead, i->Pin.AvSel.ctl);
2637 addHRegUse(u, HRmRead, i->Pin.AvSel.srcL);
2638 addHRegUse(u, HRmRead, i->Pin.AvSel.srcR);
2639 return;
2640 case Pin_AvSh:
2641 addHRegUse(u, HRmWrite, i->Pin.AvSh.dst);
2642 if (i->Pin.AvSh.addr->tag == Pam_IR)
2643 addHRegUse(u, HRmWrite, hregPPC_GPR30(mode64));
2644 addRegUsage_PPCAMode(u, i->Pin.AvSh.addr);
2645 return;
2646 case Pin_AvShlDbl:
2647 addHRegUse(u, HRmWrite, i->Pin.AvShlDbl.dst);
2648 addHRegUse(u, HRmRead, i->Pin.AvShlDbl.srcL);
2649 addHRegUse(u, HRmRead, i->Pin.AvShlDbl.srcR);
2650 return;
2651 case Pin_AvSplat:
2652 addHRegUse(u, HRmWrite, i->Pin.AvSplat.dst);
2653 addRegUsage_PPCVI5s(u, i->Pin.AvSplat.src);
2654 return;
2655 case Pin_AvCMov:
2656 addHRegUse(u, HRmModify, i->Pin.AvCMov.dst);
2657 addHRegUse(u, HRmRead, i->Pin.AvCMov.src);
2658 return;
2659 case Pin_AvLdVSCR:
2660 addHRegUse(u, HRmRead, i->Pin.AvLdVSCR.src);
2661 return;
2662 case Pin_AvCipherV128Unary:
2663 addHRegUse(u, HRmWrite, i->Pin.AvCipherV128Unary.dst);
2664 addHRegUse(u, HRmRead, i->Pin.AvCipherV128Unary.src);
2665 return;
2666 case Pin_AvCipherV128Binary:
2667 addHRegUse(u, HRmWrite, i->Pin.AvCipherV128Binary.dst);
2668 addHRegUse(u, HRmRead, i->Pin.AvCipherV128Binary.srcL);
2669 addHRegUse(u, HRmRead, i->Pin.AvCipherV128Binary.srcR);
2670 return;
2671 case Pin_AvHashV128Binary:
2672 addHRegUse(u, HRmWrite, i->Pin.AvHashV128Binary.dst);
2673 addHRegUse(u, HRmRead, i->Pin.AvHashV128Binary.src);
2674 addRegUsage_PPCRI(u, i->Pin.AvHashV128Binary.s_field);
2675 return;
2676 case Pin_AvBCDV128Binary:
2677 addHRegUse(u, HRmWrite, i->Pin.AvBCDV128Binary.dst);
2678 addHRegUse(u, HRmRead, i->Pin.AvBCDV128Binary.src1);
2679 addHRegUse(u, HRmRead, i->Pin.AvBCDV128Binary.src2);
2680 return;
2681 case Pin_Dfp64Unary:
2682 addHRegUse(u, HRmWrite, i->Pin.Dfp64Unary.dst);
2683 addHRegUse(u, HRmRead, i->Pin.Dfp64Unary.src);
2684 return;
2685 case Pin_Dfp64Binary:
2686 addHRegUse(u, HRmWrite, i->Pin.Dfp64Binary.dst);
2687 addHRegUse(u, HRmRead, i->Pin.Dfp64Binary.srcL);
2688 addHRegUse(u, HRmRead, i->Pin.Dfp64Binary.srcR);
2689 return;
2690 case Pin_DfpShift:
2691 addRegUsage_PPCRI(u, i->Pin.DfpShift.shift);
2692 addHRegUse(u, HRmWrite, i->Pin.DfpShift.src);
2693 addHRegUse(u, HRmWrite, i->Pin.DfpShift.dst);
2694 return;
2695 case Pin_Dfp128Unary:
2696 addHRegUse(u, HRmWrite, i->Pin.Dfp128Unary.dst_hi);
2697 addHRegUse(u, HRmWrite, i->Pin.Dfp128Unary.dst_lo);
2698 addHRegUse(u, HRmRead, i->Pin.Dfp128Unary.src_hi);
2699 addHRegUse(u, HRmRead, i->Pin.Dfp128Unary.src_lo);
2700 return;
2701 case Pin_Dfp128Binary:
2702 addHRegUse(u, HRmWrite, i->Pin.Dfp128Binary.dst_hi);
2703 addHRegUse(u, HRmWrite, i->Pin.Dfp128Binary.dst_lo);
2704 addHRegUse(u, HRmRead, i->Pin.Dfp128Binary.srcR_hi);
2705 addHRegUse(u, HRmRead, i->Pin.Dfp128Binary.srcR_lo);
2706 return;
2707 case Pin_DfpRound:
2708 addHRegUse(u, HRmWrite, i->Pin.DfpRound.dst);
2709 addHRegUse(u, HRmRead, i->Pin.DfpRound.src);
2710 return;
2711 case Pin_DfpRound128:
2712 addHRegUse(u, HRmWrite, i->Pin.DfpRound128.dst_hi);
2713 addHRegUse(u, HRmWrite, i->Pin.DfpRound128.dst_lo);
2714 addHRegUse(u, HRmRead, i->Pin.DfpRound128.src_hi);
2715 addHRegUse(u, HRmRead, i->Pin.DfpRound128.src_lo);
2716 return;
2717 case Pin_DfpQuantize:
2718 addRegUsage_PPCRI(u, i->Pin.DfpQuantize.rmc);
2719 addHRegUse(u, HRmWrite, i->Pin.DfpQuantize.dst);
2720 addHRegUse(u, HRmRead, i->Pin.DfpQuantize.srcL);
2721 addHRegUse(u, HRmRead, i->Pin.DfpQuantize.srcR);
2722 return;
2723 case Pin_DfpQuantize128:
2724 addHRegUse(u, HRmWrite, i->Pin.DfpQuantize128.dst_hi);
2725 addHRegUse(u, HRmWrite, i->Pin.DfpQuantize128.dst_lo);
2726 addHRegUse(u, HRmRead, i->Pin.DfpQuantize128.src_hi);
2727 addHRegUse(u, HRmRead, i->Pin.DfpQuantize128.src_lo);
2728 return;
2729 case Pin_DfpShift128:
2730 addRegUsage_PPCRI(u, i->Pin.DfpShift128.shift);
2731 addHRegUse(u, HRmWrite, i->Pin.DfpShift128.src_hi);
2732 addHRegUse(u, HRmWrite, i->Pin.DfpShift128.src_lo);
2733 addHRegUse(u, HRmWrite, i->Pin.DfpShift128.dst_hi);
2734 addHRegUse(u, HRmWrite, i->Pin.DfpShift128.dst_lo);
2735 return;
2736 case Pin_DfpD128toD64:
2737 addHRegUse(u, HRmWrite, i->Pin.DfpD128toD64.src_hi);
2738 addHRegUse(u, HRmWrite, i->Pin.DfpD128toD64.src_lo);
2739 addHRegUse(u, HRmWrite, i->Pin.DfpD128toD64.dst);
2740 return;
2741 case Pin_DfpI64StoD128:
2742 addHRegUse(u, HRmWrite, i->Pin.DfpI64StoD128.src);
2743 addHRegUse(u, HRmWrite, i->Pin.DfpI64StoD128.dst_hi);
2744 addHRegUse(u, HRmWrite, i->Pin.DfpI64StoD128.dst_lo);
2745 return;
2746 case Pin_ExtractExpD128:
2747 addHRegUse(u, HRmWrite, i->Pin.ExtractExpD128.dst);
2748 addHRegUse(u, HRmRead, i->Pin.ExtractExpD128.src_hi);
2749 addHRegUse(u, HRmRead, i->Pin.ExtractExpD128.src_lo);
2750 return;
2751 case Pin_InsertExpD128:
2752 addHRegUse(u, HRmWrite, i->Pin.InsertExpD128.dst_hi);
2753 addHRegUse(u, HRmWrite, i->Pin.InsertExpD128.dst_lo);
2754 addHRegUse(u, HRmRead, i->Pin.InsertExpD128.srcL);
2755 addHRegUse(u, HRmRead, i->Pin.InsertExpD128.srcR_hi);
2756 addHRegUse(u, HRmRead, i->Pin.InsertExpD128.srcR_lo);
2757 return;
2758 case Pin_Dfp64Cmp:
2759 addHRegUse(u, HRmWrite, i->Pin.Dfp64Cmp.dst);
2760 addHRegUse(u, HRmRead, i->Pin.Dfp64Cmp.srcL);
2761 addHRegUse(u, HRmRead, i->Pin.Dfp64Cmp.srcR);
2762 return;
2763 case Pin_Dfp128Cmp:
2764 addHRegUse(u, HRmWrite, i->Pin.Dfp128Cmp.dst);
2765 addHRegUse(u, HRmRead, i->Pin.Dfp128Cmp.srcL_hi);
2766 addHRegUse(u, HRmRead, i->Pin.Dfp128Cmp.srcL_lo);
2767 addHRegUse(u, HRmRead, i->Pin.Dfp128Cmp.srcR_hi);
2768 addHRegUse(u, HRmRead, i->Pin.Dfp128Cmp.srcR_lo);
2769 return;
2770 case Pin_EvCheck:
2771 /* We expect both amodes only to mention the GSP (r31), so this
2772 is in fact pointless, since GSP isn't allocatable, but
2773 anyway.. */
2774 addRegUsage_PPCAMode(u, i->Pin.EvCheck.amCounter);
2775 addRegUsage_PPCAMode(u, i->Pin.EvCheck.amFailAddr);
2776 addHRegUse(u, HRmWrite, hregPPC_GPR30(mode64)); /* also unavail to RA */
2777 return;
2778 case Pin_ProfInc:
2779 addHRegUse(u, HRmWrite, hregPPC_GPR29(mode64));
2780 addHRegUse(u, HRmWrite, hregPPC_GPR30(mode64));
2781 return;
2782 default:
2783 ppPPCInstr(i, mode64);
2784 vpanic("getRegUsage_PPCInstr");
2788 /* local helper */
2789 static void mapReg( HRegRemap* m, HReg* r )
2791 *r = lookupHRegRemap(m, *r);
2794 void mapRegs_PPCInstr ( HRegRemap* m, PPCInstr* i, Bool mode64 )
2796 switch (i->tag) {
2797 case Pin_LI:
2798 mapReg(m, &i->Pin.LI.dst);
2799 return;
2800 case Pin_Alu:
2801 mapReg(m, &i->Pin.Alu.dst);
2802 mapReg(m, &i->Pin.Alu.srcL);
2803 mapRegs_PPCRH(m, i->Pin.Alu.srcR);
2804 return;
2805 case Pin_Shft:
2806 mapReg(m, &i->Pin.Shft.dst);
2807 mapReg(m, &i->Pin.Shft.srcL);
2808 mapRegs_PPCRH(m, i->Pin.Shft.srcR);
2809 return;
2810 case Pin_AddSubC:
2811 mapReg(m, &i->Pin.AddSubC.dst);
2812 mapReg(m, &i->Pin.AddSubC.srcL);
2813 mapReg(m, &i->Pin.AddSubC.srcR);
2814 return;
2815 case Pin_Cmp:
2816 mapReg(m, &i->Pin.Cmp.srcL);
2817 mapRegs_PPCRH(m, i->Pin.Cmp.srcR);
2818 return;
2819 case Pin_Unary:
2820 mapReg(m, &i->Pin.Unary.dst);
2821 mapReg(m, &i->Pin.Unary.src);
2822 return;
2823 case Pin_MulL:
2824 mapReg(m, &i->Pin.MulL.dst);
2825 mapReg(m, &i->Pin.MulL.srcL);
2826 mapReg(m, &i->Pin.MulL.srcR);
2827 return;
2828 case Pin_Div:
2829 mapReg(m, &i->Pin.Div.dst);
2830 mapReg(m, &i->Pin.Div.srcL);
2831 mapReg(m, &i->Pin.Div.srcR);
2832 return;
2833 case Pin_Call:
2834 return;
2835 case Pin_XDirect:
2836 mapRegs_PPCAMode(m, i->Pin.XDirect.amCIA);
2837 return;
2838 case Pin_XIndir:
2839 mapReg(m, &i->Pin.XIndir.dstGA);
2840 mapRegs_PPCAMode(m, i->Pin.XIndir.amCIA);
2841 return;
2842 case Pin_XAssisted:
2843 mapReg(m, &i->Pin.XAssisted.dstGA);
2844 mapRegs_PPCAMode(m, i->Pin.XAssisted.amCIA);
2845 return;
2846 case Pin_CMov:
2847 mapRegs_PPCRI(m, i->Pin.CMov.src);
2848 mapReg(m, &i->Pin.CMov.dst);
2849 return;
2850 case Pin_Load:
2851 mapRegs_PPCAMode(m, i->Pin.Load.src);
2852 mapReg(m, &i->Pin.Load.dst);
2853 return;
2854 case Pin_LoadL:
2855 mapReg(m, &i->Pin.LoadL.src);
2856 mapReg(m, &i->Pin.LoadL.dst);
2857 return;
2858 case Pin_Store:
2859 mapReg(m, &i->Pin.Store.src);
2860 mapRegs_PPCAMode(m, i->Pin.Store.dst);
2861 return;
2862 case Pin_StoreC:
2863 mapReg(m, &i->Pin.StoreC.src);
2864 mapReg(m, &i->Pin.StoreC.dst);
2865 return;
2866 case Pin_Set:
2867 mapReg(m, &i->Pin.Set.dst);
2868 return;
2869 case Pin_MfCR:
2870 mapReg(m, &i->Pin.MfCR.dst);
2871 return;
2872 case Pin_MFence:
2873 return;
2874 case Pin_FpUnary:
2875 mapReg(m, &i->Pin.FpUnary.dst);
2876 mapReg(m, &i->Pin.FpUnary.src);
2877 return;
2878 case Pin_FpBinary:
2879 mapReg(m, &i->Pin.FpBinary.dst);
2880 mapReg(m, &i->Pin.FpBinary.srcL);
2881 mapReg(m, &i->Pin.FpBinary.srcR);
2882 return;
2883 case Pin_Fp128Unary:
2884 mapReg(m, &i->Pin.Fp128Unary.dst);
2885 mapReg(m, &i->Pin.Fp128Unary.src);
2886 return;
2887 case Pin_Fp128Binary:
2888 mapReg(m, &i->Pin.Fp128Binary.dst);
2889 mapReg(m, &i->Pin.Fp128Binary.srcL);
2890 mapReg(m, &i->Pin.Fp128Binary.srcR);
2891 return;
2892 case Pin_Fp128Trinary:
2893 mapReg(m, &i->Pin.Fp128Trinary.dst);
2894 mapReg(m, &i->Pin.Fp128Trinary.srcL);
2895 mapReg(m, &i->Pin.Fp128Trinary.srcR);
2896 return;
2897 case Pin_FpMulAcc:
2898 mapReg(m, &i->Pin.FpMulAcc.dst);
2899 mapReg(m, &i->Pin.FpMulAcc.srcML);
2900 mapReg(m, &i->Pin.FpMulAcc.srcMR);
2901 mapReg(m, &i->Pin.FpMulAcc.srcAcc);
2902 return;
2903 case Pin_FpLdSt:
2904 mapReg(m, &i->Pin.FpLdSt.reg);
2905 mapRegs_PPCAMode(m, i->Pin.FpLdSt.addr);
2906 return;
2907 case Pin_FpSTFIW:
2908 mapReg(m, &i->Pin.FpSTFIW.addr);
2909 mapReg(m, &i->Pin.FpSTFIW.data);
2910 return;
2911 case Pin_FpRSP:
2912 mapReg(m, &i->Pin.FpRSP.dst);
2913 mapReg(m, &i->Pin.FpRSP.src);
2914 return;
2915 case Pin_FpCftI:
2916 mapReg(m, &i->Pin.FpCftI.dst);
2917 mapReg(m, &i->Pin.FpCftI.src);
2918 return;
2919 case Pin_FpCMov:
2920 mapReg(m, &i->Pin.FpCMov.dst);
2921 mapReg(m, &i->Pin.FpCMov.src);
2922 return;
2923 case Pin_FpLdFPSCR:
2924 mapReg(m, &i->Pin.FpLdFPSCR.src);
2925 return;
2926 case Pin_FpCmp:
2927 mapReg(m, &i->Pin.FpCmp.dst);
2928 mapReg(m, &i->Pin.FpCmp.srcL);
2929 mapReg(m, &i->Pin.FpCmp.srcR);
2930 return;
2931 case Pin_RdWrLR:
2932 mapReg(m, &i->Pin.RdWrLR.gpr);
2933 return;
2934 case Pin_AvLdSt:
2935 mapReg(m, &i->Pin.AvLdSt.reg);
2936 mapRegs_PPCAMode(m, i->Pin.AvLdSt.addr);
2937 return;
2938 case Pin_AvUnary:
2939 mapReg(m, &i->Pin.AvUnary.dst);
2940 mapReg(m, &i->Pin.AvUnary.src);
2941 return;
2942 case Pin_AvBinary:
2943 mapReg(m, &i->Pin.AvBinary.dst);
2944 mapReg(m, &i->Pin.AvBinary.srcL);
2945 mapReg(m, &i->Pin.AvBinary.srcR);
2946 return;
2947 case Pin_AvBinaryInt:
2948 mapReg(m, &i->Pin.AvBinaryInt.dst);
2949 mapReg(m, &i->Pin.AvBinaryInt.src);
2950 return;
2951 case Pin_AvBin8x16:
2952 mapReg(m, &i->Pin.AvBin8x16.dst);
2953 mapReg(m, &i->Pin.AvBin8x16.srcL);
2954 mapReg(m, &i->Pin.AvBin8x16.srcR);
2955 return;
2956 case Pin_AvBin16x8:
2957 mapReg(m, &i->Pin.AvBin16x8.dst);
2958 mapReg(m, &i->Pin.AvBin16x8.srcL);
2959 mapReg(m, &i->Pin.AvBin16x8.srcR);
2960 return;
2961 case Pin_AvBin32x4:
2962 mapReg(m, &i->Pin.AvBin32x4.dst);
2963 mapReg(m, &i->Pin.AvBin32x4.srcL);
2964 mapReg(m, &i->Pin.AvBin32x4.srcR);
2965 return;
2966 case Pin_AvBin64x2:
2967 mapReg(m, &i->Pin.AvBin64x2.dst);
2968 mapReg(m, &i->Pin.AvBin64x2.srcL);
2969 mapReg(m, &i->Pin.AvBin64x2.srcR);
2970 return;
2971 case Pin_AvBin32Fx4:
2972 mapReg(m, &i->Pin.AvBin32Fx4.dst);
2973 mapReg(m, &i->Pin.AvBin32Fx4.srcL);
2974 mapReg(m, &i->Pin.AvBin32Fx4.srcR);
2975 return;
2976 case Pin_AvUn32Fx4:
2977 mapReg(m, &i->Pin.AvUn32Fx4.dst);
2978 mapReg(m, &i->Pin.AvUn32Fx4.src);
2979 return;
2980 case Pin_AvPerm:
2981 mapReg(m, &i->Pin.AvPerm.dst);
2982 mapReg(m, &i->Pin.AvPerm.srcL);
2983 mapReg(m, &i->Pin.AvPerm.srcR);
2984 mapReg(m, &i->Pin.AvPerm.ctl);
2985 return;
2986 case Pin_AvSel:
2987 mapReg(m, &i->Pin.AvSel.dst);
2988 mapReg(m, &i->Pin.AvSel.srcL);
2989 mapReg(m, &i->Pin.AvSel.srcR);
2990 mapReg(m, &i->Pin.AvSel.ctl);
2991 return;
2992 case Pin_AvSh:
2993 mapReg(m, &i->Pin.AvSh.dst);
2994 mapRegs_PPCAMode(m, i->Pin.AvSh.addr);
2995 return;
2996 case Pin_AvShlDbl:
2997 mapReg(m, &i->Pin.AvShlDbl.dst);
2998 mapReg(m, &i->Pin.AvShlDbl.srcL);
2999 mapReg(m, &i->Pin.AvShlDbl.srcR);
3000 return;
3001 case Pin_AvSplat:
3002 mapReg(m, &i->Pin.AvSplat.dst);
3003 mapRegs_PPCVI5s(m, i->Pin.AvSplat.src);
3004 return;
3005 case Pin_AvCMov:
3006 mapReg(m, &i->Pin.AvCMov.dst);
3007 mapReg(m, &i->Pin.AvCMov.src);
3008 return;
3009 case Pin_AvLdVSCR:
3010 mapReg(m, &i->Pin.AvLdVSCR.src);
3011 return;
3012 case Pin_AvCipherV128Unary:
3013 mapReg(m, &i->Pin.AvCipherV128Unary.dst);
3014 mapReg(m, &i->Pin.AvCipherV128Unary.src);
3015 return;
3016 case Pin_AvCipherV128Binary:
3017 mapReg(m, &i->Pin.AvCipherV128Binary.dst);
3018 mapReg(m, &i->Pin.AvCipherV128Binary.srcL);
3019 mapReg(m, &i->Pin.AvCipherV128Binary.srcR);
3020 return;
3021 case Pin_AvHashV128Binary:
3022 mapRegs_PPCRI(m, i->Pin.AvHashV128Binary.s_field);
3023 mapReg(m, &i->Pin.AvHashV128Binary.dst);
3024 mapReg(m, &i->Pin.AvHashV128Binary.src);
3025 return;
3026 case Pin_AvBCDV128Binary:
3027 mapReg(m, &i->Pin.AvBCDV128Binary.dst);
3028 mapReg(m, &i->Pin.AvBCDV128Binary.src1);
3029 mapReg(m, &i->Pin.AvBCDV128Binary.src2);
3030 return;
3031 case Pin_Dfp64Unary:
3032 mapReg(m, &i->Pin.Dfp64Unary.dst);
3033 mapReg(m, &i->Pin.Dfp64Unary.src);
3034 return;
3035 case Pin_Dfp64Binary:
3036 mapReg(m, &i->Pin.Dfp64Binary.dst);
3037 mapReg(m, &i->Pin.Dfp64Binary.srcL);
3038 mapReg(m, &i->Pin.Dfp64Binary.srcR);
3039 return;
3040 case Pin_DfpShift:
3041 mapRegs_PPCRI(m, i->Pin.DfpShift.shift);
3042 mapReg(m, &i->Pin.DfpShift.src);
3043 mapReg(m, &i->Pin.DfpShift.dst);
3044 return;
3045 case Pin_Dfp128Unary:
3046 mapReg(m, &i->Pin.Dfp128Unary.dst_hi);
3047 mapReg(m, &i->Pin.Dfp128Unary.dst_lo);
3048 mapReg(m, &i->Pin.Dfp128Unary.src_hi);
3049 mapReg(m, &i->Pin.Dfp128Unary.src_lo);
3050 return;
3051 case Pin_Dfp128Binary:
3052 mapReg(m, &i->Pin.Dfp128Binary.dst_hi);
3053 mapReg(m, &i->Pin.Dfp128Binary.dst_lo);
3054 mapReg(m, &i->Pin.Dfp128Binary.srcR_hi);
3055 mapReg(m, &i->Pin.Dfp128Binary.srcR_lo);
3056 return;
3057 case Pin_DfpShift128:
3058 mapRegs_PPCRI(m, i->Pin.DfpShift128.shift);
3059 mapReg(m, &i->Pin.DfpShift128.src_hi);
3060 mapReg(m, &i->Pin.DfpShift128.src_lo);
3061 mapReg(m, &i->Pin.DfpShift128.dst_hi);
3062 mapReg(m, &i->Pin.DfpShift128.dst_lo);
3063 return;
3064 case Pin_DfpRound:
3065 mapReg(m, &i->Pin.DfpRound.dst);
3066 mapReg(m, &i->Pin.DfpRound.src);
3067 return;
3068 case Pin_DfpRound128:
3069 mapReg(m, &i->Pin.DfpRound128.dst_hi);
3070 mapReg(m, &i->Pin.DfpRound128.dst_lo);
3071 mapReg(m, &i->Pin.DfpRound128.src_hi);
3072 mapReg(m, &i->Pin.DfpRound128.src_lo);
3073 return;
3074 case Pin_DfpQuantize:
3075 mapRegs_PPCRI(m, i->Pin.DfpQuantize.rmc);
3076 mapReg(m, &i->Pin.DfpQuantize.dst);
3077 mapReg(m, &i->Pin.DfpQuantize.srcL);
3078 mapReg(m, &i->Pin.DfpQuantize.srcR);
3079 return;
3080 case Pin_DfpQuantize128:
3081 mapRegs_PPCRI(m, i->Pin.DfpQuantize128.rmc);
3082 mapReg(m, &i->Pin.DfpQuantize128.dst_hi);
3083 mapReg(m, &i->Pin.DfpQuantize128.dst_lo);
3084 mapReg(m, &i->Pin.DfpQuantize128.src_hi);
3085 mapReg(m, &i->Pin.DfpQuantize128.src_lo);
3086 return;
3087 case Pin_DfpD128toD64:
3088 mapReg(m, &i->Pin.DfpD128toD64.src_hi);
3089 mapReg(m, &i->Pin.DfpD128toD64.src_lo);
3090 mapReg(m, &i->Pin.DfpD128toD64.dst);
3091 return;
3092 case Pin_DfpI64StoD128:
3093 mapReg(m, &i->Pin.DfpI64StoD128.src);
3094 mapReg(m, &i->Pin.DfpI64StoD128.dst_hi);
3095 mapReg(m, &i->Pin.DfpI64StoD128.dst_lo);
3096 return;
3097 case Pin_ExtractExpD128:
3098 mapReg(m, &i->Pin.ExtractExpD128.dst);
3099 mapReg(m, &i->Pin.ExtractExpD128.src_hi);
3100 mapReg(m, &i->Pin.ExtractExpD128.src_lo);
3101 return;
3102 case Pin_InsertExpD128:
3103 mapReg(m, &i->Pin.InsertExpD128.dst_hi);
3104 mapReg(m, &i->Pin.InsertExpD128.dst_lo);
3105 mapReg(m, &i->Pin.InsertExpD128.srcL);
3106 mapReg(m, &i->Pin.InsertExpD128.srcR_hi);
3107 mapReg(m, &i->Pin.InsertExpD128.srcR_lo);
3108 return;
3109 case Pin_Dfp64Cmp:
3110 mapReg(m, &i->Pin.Dfp64Cmp.dst);
3111 mapReg(m, &i->Pin.Dfp64Cmp.srcL);
3112 mapReg(m, &i->Pin.Dfp64Cmp.srcR);
3113 return;
3114 case Pin_Dfp128Cmp:
3115 mapReg(m, &i->Pin.Dfp128Cmp.dst);
3116 mapReg(m, &i->Pin.Dfp128Cmp.srcL_hi);
3117 mapReg(m, &i->Pin.Dfp128Cmp.srcL_lo);
3118 mapReg(m, &i->Pin.Dfp128Cmp.srcR_hi);
3119 mapReg(m, &i->Pin.Dfp128Cmp.srcR_lo);
3120 return;
3121 case Pin_EvCheck:
3122 /* We expect both amodes only to mention the GSP (r31), so this
3123 is in fact pointless, since GSP isn't allocatable, but
3124 anyway.. */
3125 mapRegs_PPCAMode(m, i->Pin.EvCheck.amCounter);
3126 mapRegs_PPCAMode(m, i->Pin.EvCheck.amFailAddr);
3127 return;
3128 case Pin_ProfInc:
3129 /* hardwires r29 and r30 -- nothing to modify. */
3130 return;
3131 default:
3132 ppPPCInstr(i, mode64);
3133 vpanic("mapRegs_PPCInstr");
3137 /* Generate ppc spill/reload instructions under the direction of the
3138 register allocator. Note it's critical these don't write the
3139 condition codes. */
3141 void genSpill_PPC ( /*OUT*/HInstr** i1, /*OUT*/HInstr** i2,
3142 HReg rreg, Int offsetB, Bool mode64 )
3144 PPCAMode* am;
3145 vassert(!hregIsVirtual(rreg));
3146 *i1 = *i2 = NULL;
3147 am = PPCAMode_IR( offsetB, GuestStatePtr(mode64) );
3148 switch (hregClass(rreg)) {
3149 case HRcInt64:
3150 vassert(mode64);
3151 *i1 = PPCInstr_Store( 8, am, rreg, mode64 );
3152 return;
3153 case HRcInt32:
3154 vassert(!mode64);
3155 *i1 = PPCInstr_Store( 4, am, rreg, mode64 );
3156 return;
3157 case HRcFlt64:
3158 *i1 = PPCInstr_FpLdSt ( False/*store*/, 8, rreg, am );
3159 return;
3160 case HRcVec128:
3161 // XXX: GPR30 used as spill register to kludge AltiVec
3162 // AMode_IR
3163 *i1 = PPCInstr_AvLdSt ( False/*store*/, 16, rreg, am );
3164 return;
3165 default:
3166 ppHRegClass(hregClass(rreg));
3167 vpanic("genSpill_PPC: unimplemented regclass");
3171 void genReload_PPC ( /*OUT*/HInstr** i1, /*OUT*/HInstr** i2,
3172 HReg rreg, Int offsetB, Bool mode64 )
3174 PPCAMode* am;
3175 vassert(!hregIsVirtual(rreg));
3176 *i1 = *i2 = NULL;
3177 am = PPCAMode_IR( offsetB, GuestStatePtr(mode64) );
3178 switch (hregClass(rreg)) {
3179 case HRcInt64:
3180 vassert(mode64);
3181 *i1 = PPCInstr_Load( 8, rreg, am, mode64 );
3182 return;
3183 case HRcInt32:
3184 vassert(!mode64);
3185 *i1 = PPCInstr_Load( 4, rreg, am, mode64 );
3186 return;
3187 case HRcFlt64:
3188 *i1 = PPCInstr_FpLdSt ( True/*load*/, 8, rreg, am );
3189 return;
3190 case HRcVec128:
3191 // XXX: GPR30 used as spill register to kludge AltiVec AMode_IR
3192 *i1 = PPCInstr_AvLdSt ( True/*load*/, 16, rreg, am );
3193 return;
3194 default:
3195 ppHRegClass(hregClass(rreg));
3196 vpanic("genReload_PPC: unimplemented regclass");
3200 PPCInstr* genMove_PPC(HReg from, HReg to, Bool mode64)
3202 switch (hregClass(from)) {
3203 case HRcInt32:
3204 case HRcInt64:
3205 return PPCInstr_Alu(Palu_OR, to, from, PPCRH_Reg(from));
3206 case HRcFlt64:
3207 return PPCInstr_FpUnary(Pfp_MOV, to, from);
3208 default:
3209 ppHRegClass(hregClass(from));
3210 vpanic("genMove_PPC: unimplemented regclass");
3215 /* --------- The ppc assembler (bleh.) --------- */
3217 inline static UInt iregEnc ( HReg r, Bool mode64 )
3219 UInt n;
3220 vassert(hregClass(r) == (mode64 ? HRcInt64 : HRcInt32));
3221 vassert(!hregIsVirtual(r));
3222 n = hregEncoding(r);
3223 vassert(n <= 32);
3224 return n;
3227 inline static UInt fregEnc ( HReg fr )
3229 UInt n;
3230 vassert(hregClass(fr) == HRcFlt64);
3231 vassert(!hregIsVirtual(fr));
3232 n = hregEncoding(fr);
3233 vassert(n <= 32);
3234 return n;
3237 inline static UInt vregEnc ( HReg v )
3239 UInt n;
3240 vassert(hregClass(v) == HRcVec128);
3241 vassert(!hregIsVirtual(v));
3242 n = hregEncoding(v);
3243 vassert(n <= 32);
3244 return n;
3247 /* Emit an instruction ppc-endianly */
3248 static UChar* emit32 ( UChar* p, UInt w32, VexEndness endness_host )
3250 if (endness_host == VexEndnessBE) {
3251 *p++ = toUChar((w32 >> 24) & 0x000000FF);
3252 *p++ = toUChar((w32 >> 16) & 0x000000FF);
3253 *p++ = toUChar((w32 >> 8) & 0x000000FF);
3254 *p++ = toUChar((w32) & 0x000000FF);
3255 } else {
3256 *p++ = toUChar((w32) & 0x000000FF);
3257 *p++ = toUChar((w32 >> 8) & 0x000000FF);
3258 *p++ = toUChar((w32 >> 16) & 0x000000FF);
3259 *p++ = toUChar((w32 >> 24) & 0x000000FF);
3261 return p;
3264 /* Fetch an instruction ppc-endianly */
3265 static UInt fetch32 ( UChar* p, VexEndness endness_host )
3267 UInt w32 = 0;
3268 if (endness_host == VexEndnessBE) {
3269 w32 |= ((0xFF & (UInt)p[0]) << 24);
3270 w32 |= ((0xFF & (UInt)p[1]) << 16);
3271 w32 |= ((0xFF & (UInt)p[2]) << 8);
3272 w32 |= ((0xFF & (UInt)p[3]) << 0);
3273 } else {
3274 w32 |= ((0xFF & (UInt)p[3]) << 24);
3275 w32 |= ((0xFF & (UInt)p[2]) << 16);
3276 w32 |= ((0xFF & (UInt)p[1]) << 8);
3277 w32 |= ((0xFF & (UInt)p[0]) << 0);
3279 return w32;
3282 /* The following mkForm[...] functions refer to ppc instruction forms
3283 as per PPC32 p576
3286 static UChar* mkFormD ( UChar* p, UInt opc1,
3287 UInt r1, UInt r2, UInt imm, VexEndness endness_host )
3289 UInt theInstr;
3290 vassert(opc1 < 0x40);
3291 vassert(r1 < 0x20);
3292 vassert(r2 < 0x20);
3293 imm = imm & 0xFFFF;
3294 theInstr = ((opc1<<26) | (r1<<21) | (r2<<16) | (imm));
3295 return emit32(p, theInstr, endness_host);
3298 static UChar* mkFormMD ( UChar* p, UInt opc1, UInt r1, UInt r2,
3299 UInt imm1, UInt imm2, UInt opc2,
3300 VexEndness endness_host )
3302 UInt theInstr;
3303 vassert(opc1 < 0x40);
3304 vassert(r1 < 0x20);
3305 vassert(r2 < 0x20);
3306 vassert(imm1 < 0x40);
3307 vassert(imm2 < 0x40);
3308 vassert(opc2 < 0x08);
3309 imm2 = ((imm2 & 0x1F) << 1) | (imm2 >> 5);
3310 theInstr = ((opc1<<26) | (r1<<21) | (r2<<16) |
3311 ((imm1 & 0x1F)<<11) | (imm2<<5) |
3312 (opc2<<2) | ((imm1 >> 5)<<1));
3313 return emit32(p, theInstr, endness_host);
3316 static UChar* mkFormX ( UChar* p, UInt opc1, UInt r1, UInt r2,
3317 UInt r3, UInt opc2, UInt b0, VexEndness endness_host )
3319 UInt theInstr;
3320 vassert(opc1 < 0x40);
3321 vassert(r1 < 0x20);
3322 vassert(r2 < 0x20);
3323 vassert(r3 < 0x20);
3324 vassert(opc2 < 0x400);
3325 vassert(b0 < 0x2);
3326 theInstr = ((opc1<<26) | (r1<<21) | (r2<<16) |
3327 (r3<<11) | (opc2<<1) | (b0));
3328 return emit32(p, theInstr, endness_host);
3331 static UChar* mkFormXO ( UChar* p, UInt opc1, UInt r1, UInt r2,
3332 UInt r3, UInt b10, UInt opc2, UInt b0,
3333 VexEndness endness_host )
3335 UInt theInstr;
3336 vassert(opc1 < 0x40);
3337 vassert(r1 < 0x20);
3338 vassert(r2 < 0x20);
3339 vassert(r3 < 0x20);
3340 vassert(b10 < 0x2);
3341 vassert(opc2 < 0x200);
3342 vassert(b0 < 0x2);
3343 theInstr = ((opc1<<26) | (r1<<21) | (r2<<16) |
3344 (r3<<11) | (b10 << 10) | (opc2<<1) | (b0));
3345 return emit32(p, theInstr, endness_host);
3348 static UChar* mkFormXL ( UChar* p, UInt opc1, UInt f1, UInt f2,
3349 UInt f3, UInt opc2, UInt b0, VexEndness endness_host )
3351 UInt theInstr;
3352 vassert(opc1 < 0x40);
3353 vassert(f1 < 0x20);
3354 vassert(f2 < 0x20);
3355 vassert(f3 < 0x20);
3356 vassert(opc2 < 0x400);
3357 vassert(b0 < 0x2);
3358 theInstr = ((opc1<<26) | (f1<<21) | (f2<<16) |
3359 (f3<<11) | (opc2<<1) | (b0));
3360 return emit32(p, theInstr, endness_host);
3363 // Note: for split field ops, give mnemonic arg
3364 static UChar* mkFormXFX ( UChar* p, UInt r1, UInt f2, UInt opc2,
3365 VexEndness endness_host )
3367 UInt theInstr;
3368 vassert(r1 < 0x20);
3369 vassert(f2 < 0x20);
3370 vassert(opc2 < 0x400);
3371 switch (opc2) {
3372 case 144: // mtcrf
3373 vassert(f2 < 0x100);
3374 f2 = f2 << 1;
3375 break;
3376 case 339: // mfspr
3377 case 371: // mftb
3378 case 467: // mtspr
3379 vassert(f2 < 0x400);
3380 // re-arrange split field
3381 f2 = ((f2>>5) & 0x1F) | ((f2 & 0x1F)<<5);
3382 break;
3383 default: vpanic("mkFormXFX(ppch)");
3385 theInstr = ((31<<26) | (r1<<21) | (f2<<11) | (opc2<<1));
3386 return emit32(p, theInstr, endness_host);
3389 // Only used by mtfsf
3390 static UChar* mkFormXFL ( UChar* p, UInt FM, UInt freg, UInt dfp_rm,
3391 VexEndness endness_host )
3393 UInt theInstr;
3394 vassert(FM < 0x100);
3395 vassert(freg < 0x20);
3396 theInstr = ((63<<26) | (FM<<17) | (dfp_rm<<16) | (freg<<11) | (711<<1));
3397 return emit32(p, theInstr, endness_host);
3400 static UChar* mkFormXS ( UChar* p, UInt opc1, UInt r1, UInt r2,
3401 UInt imm, UInt opc2, UInt b0,
3402 VexEndness endness_host )
3404 UInt theInstr;
3405 vassert(opc1 < 0x40);
3406 vassert(r1 < 0x20);
3407 vassert(r2 < 0x20);
3408 vassert(imm < 0x40);
3409 vassert(opc2 < 0x400);
3410 vassert(b0 < 0x2);
3411 theInstr = ((opc1<<26) | (r1<<21) | (r2<<16) |
3412 ((imm & 0x1F)<<11) | (opc2<<2) | ((imm>>5)<<1) | (b0));
3413 return emit32(p, theInstr, endness_host);
3417 #if 0
3418 // 'b'
3419 static UChar* mkFormI ( UChar* p, UInt LI, UInt AA, UInt LK,
3420 VexEndness endness_host )
3422 UInt theInstr;
3423 vassert(LI < 0x1000000);
3424 vassert(AA < 0x2);
3425 vassert(LK < 0x2);
3426 theInstr = ((18<<26) | (LI<<2) | (AA<<1) | (LK));
3427 return emit32(p, theInstr, endness_host);
3429 #endif
3431 // 'bc'
3432 static UChar* mkFormB ( UChar* p, UInt BO, UInt BI,
3433 UInt BD, UInt AA, UInt LK, VexEndness endness_host )
3435 UInt theInstr;
3436 vassert(BO < 0x20);
3437 vassert(BI < 0x20);
3438 vassert(BD < 0x4000);
3439 vassert(AA < 0x2);
3440 vassert(LK < 0x2);
3441 theInstr = ((16<<26) | (BO<<21) | (BI<<16) |
3442 (BD<<2) | (AA<<1) | (LK));
3443 return emit32(p, theInstr, endness_host);
3446 // rotates
3447 static UChar* mkFormM ( UChar* p, UInt opc1, UInt r1, UInt r2,
3448 UInt f3, UInt MB, UInt ME, UInt Rc,
3449 VexEndness endness_host )
3451 UInt theInstr;
3452 vassert(opc1 < 0x40);
3453 vassert(r1 < 0x20);
3454 vassert(r2 < 0x20);
3455 vassert(f3 < 0x20);
3456 vassert(MB < 0x20);
3457 vassert(ME < 0x20);
3458 vassert(Rc < 0x2);
3459 theInstr = ((opc1<<26) | (r1<<21) | (r2<<16) |
3460 (f3<<11) | (MB<<6) | (ME<<1) | (Rc));
3461 return emit32(p, theInstr, endness_host);
3464 static UChar* mkFormA ( UChar* p, UInt opc1, UInt r1, UInt r2,
3465 UInt r3, UInt r4, UInt opc2, UInt b0,
3466 VexEndness endness_host )
3468 UInt theInstr;
3469 vassert(opc1 < 0x40);
3470 vassert(r1 < 0x20);
3471 vassert(r2 < 0x20);
3472 vassert(r3 < 0x20);
3473 vassert(r4 < 0x20);
3474 vassert(opc2 < 0x20);
3475 vassert(b0 < 0x2 );
3476 theInstr = ((opc1<<26) | (r1<<21) | (r2<<16) | (r3<<11) |
3477 (r4<<6) | (opc2<<1) | (b0));
3478 return emit32(p, theInstr, endness_host);
3481 static UChar* mkFormZ22 ( UChar* p, UInt opc1, UInt r1, UInt r2,
3482 UInt constant, UInt opc2, UInt b0,
3483 VexEndness endness_host)
3485 UInt theInstr;
3486 vassert(opc1 < 0x40);
3487 vassert(r1 < 0x20);
3488 vassert(r2 < 0x20);
3489 vassert(constant < 0x40); /* 6 bit constant */
3490 vassert(opc2 < 0x200); /* 9 bit field */
3491 vassert(b0 < 0x2);
3492 theInstr = ((opc1<<26) | (r1<<21) | (r2<<16) |
3493 (constant<<10) | (opc2<<1) | (b0));
3494 return emit32(p, theInstr, endness_host);
3497 static UChar* mkFormZ23 ( UChar* p, UInt opc1, UInt r1, UInt r2,
3498 UInt r3, UInt rmc, UInt opc2, UInt b0,
3499 VexEndness endness_host)
3501 UInt theInstr;
3502 vassert(opc1 < 0x40);
3503 vassert(r1 < 0x20);
3504 vassert(r2 < 0x20);
3505 vassert(r3 < 0x20);
3506 vassert(rmc < 0x4);
3507 vassert(opc2 < 0x100);
3508 vassert(b0 < 0x2);
3509 theInstr = ((opc1<<26) | (r1<<21) | (r2<<16) |
3510 (r3<<11) | (rmc<<9) | (opc2<<1) | (b0));
3511 return emit32(p, theInstr, endness_host);
3514 static UChar* doAMode_IR ( UChar* p, UInt opc1, UInt rSD,
3515 PPCAMode* am, Bool mode64, VexEndness endness_host )
3517 UInt rA, idx;
3518 vassert(am->tag == Pam_IR);
3519 vassert(am->Pam.IR.index < 0x10000);
3521 rA = iregEnc(am->Pam.IR.base, mode64);
3522 idx = am->Pam.IR.index;
3524 if (opc1 == 58 || opc1 == 62) { // ld/std: mode64 only
3525 vassert(mode64);
3526 /* stay sane with DS form: lowest 2 bits must be 00. This
3527 should be guaranteed to us by iselWordExpr_AMode. */
3528 vassert(0 == (idx & 3));
3530 p = mkFormD(p, opc1, rSD, rA, idx, endness_host);
3531 return p;
3534 static UChar* doAMode_RR ( UChar* p, UInt opc1, UInt opc2,
3535 UInt rSD, PPCAMode* am, Bool mode64,
3536 VexEndness endness_host )
3538 UInt rA, rB;
3539 vassert(am->tag == Pam_RR);
3541 rA = iregEnc(am->Pam.RR.base, mode64);
3542 rB = iregEnc(am->Pam.RR.index, mode64);
3544 p = mkFormX(p, opc1, rSD, rA, rB, opc2, 0, endness_host);
3545 return p;
3549 /* Load imm to r_dst */
3550 static UChar* mkLoadImm ( UChar* p, UInt r_dst, ULong imm, Bool mode64,
3551 VexEndness endness_host )
3553 vassert(r_dst < 0x20);
3555 if (!mode64) {
3556 /* In 32-bit mode, make sure the top 32 bits of imm are a sign
3557 extension of the bottom 32 bits, so that the range tests
3558 below work correctly. */
3559 UInt u32 = (UInt)imm;
3560 Int s32 = (Int)u32;
3561 Long s64 = (Long)s32;
3562 imm = (ULong)s64;
3565 if (imm >= 0xFFFFFFFFFFFF8000ULL || imm < 0x8000) {
3566 // sign-extendable from 16 bits
3568 // addi r_dst,0,imm => li r_dst,imm
3569 p = mkFormD(p, 14, r_dst, 0, imm & 0xFFFF, endness_host);
3570 } else {
3571 if (imm >= 0xFFFFFFFF80000000ULL || imm < 0x80000000ULL) {
3572 // sign-extendable from 32 bits
3574 // addis r_dst,r0,(imm>>16) => lis r_dst, (imm>>16)
3575 p = mkFormD(p, 15, r_dst, 0, (imm>>16) & 0xFFFF, endness_host);
3576 // ori r_dst, r_dst, (imm & 0xFFFF)
3577 p = mkFormD(p, 24, r_dst, r_dst, imm & 0xFFFF, endness_host);
3578 } else {
3579 // full 64bit immediate load: 5 (five!) insns.
3580 vassert(mode64);
3582 // load high word
3584 // lis r_dst, (imm>>48) & 0xFFFF
3585 p = mkFormD(p, 15, r_dst, 0, (imm>>48) & 0xFFFF, endness_host);
3587 // ori r_dst, r_dst, (imm>>32) & 0xFFFF
3588 if ((imm>>32) & 0xFFFF)
3589 p = mkFormD(p, 24, r_dst, r_dst, (imm>>32) & 0xFFFF, endness_host);
3591 // shift r_dst low word to high word => rldicr
3592 p = mkFormMD(p, 30, r_dst, r_dst, 32, 31, 1, endness_host);
3594 // load low word
3596 // oris r_dst, r_dst, (imm>>16) & 0xFFFF
3597 if ((imm>>16) & 0xFFFF)
3598 p = mkFormD(p, 25, r_dst, r_dst, (imm>>16) & 0xFFFF, endness_host);
3600 // ori r_dst, r_dst, (imm) & 0xFFFF
3601 if (imm & 0xFFFF)
3602 p = mkFormD(p, 24, r_dst, r_dst, imm & 0xFFFF, endness_host);
3605 return p;
3608 /* A simplified version of mkLoadImm that always generates 2 or 5
3609 instructions (32 or 64 bits respectively) even if it could generate
3610 fewer. This is needed for generating fixed sized patchable
3611 sequences. */
3612 static UChar* mkLoadImm_EXACTLY2or5 ( UChar* p,
3613 UInt r_dst, ULong imm, Bool mode64,
3614 VexEndness endness_host )
3616 vassert(r_dst < 0x20);
3618 if (!mode64) {
3619 /* In 32-bit mode, make sure the top 32 bits of imm are a sign
3620 extension of the bottom 32 bits. (Probably unnecessary.) */
3621 UInt u32 = (UInt)imm;
3622 Int s32 = (Int)u32;
3623 Long s64 = (Long)s32;
3624 imm = (ULong)s64;
3627 if (!mode64) {
3628 // addis r_dst,r0,(imm>>16) => lis r_dst, (imm>>16)
3629 p = mkFormD(p, 15, r_dst, 0, (imm>>16) & 0xFFFF, endness_host);
3630 // ori r_dst, r_dst, (imm & 0xFFFF)
3631 p = mkFormD(p, 24, r_dst, r_dst, imm & 0xFFFF, endness_host);
3633 } else {
3634 // full 64bit immediate load: 5 (five!) insns.
3636 // load high word
3637 // lis r_dst, (imm>>48) & 0xFFFF
3638 p = mkFormD(p, 15, r_dst, 0, (imm>>48) & 0xFFFF, endness_host);
3640 // ori r_dst, r_dst, (imm>>32) & 0xFFFF
3641 p = mkFormD(p, 24, r_dst, r_dst, (imm>>32) & 0xFFFF, endness_host);
3643 // shift r_dst low word to high word => rldicr
3644 p = mkFormMD(p, 30, r_dst, r_dst, 32, 31, 1, endness_host);
3646 // load low word
3647 // oris r_dst, r_dst, (imm>>16) & 0xFFFF
3648 p = mkFormD(p, 25, r_dst, r_dst, (imm>>16) & 0xFFFF, endness_host);
3650 // ori r_dst, r_dst, (imm) & 0xFFFF
3651 p = mkFormD(p, 24, r_dst, r_dst, imm & 0xFFFF, endness_host);
3653 return p;
3656 /* Checks whether the sequence of bytes at p was indeed created
3657 by mkLoadImm_EXACTLY2or5 with the given parameters. */
3658 static Bool isLoadImm_EXACTLY2or5 ( UChar* p_to_check,
3659 UInt r_dst, ULong imm, Bool mode64,
3660 VexEndness endness_host )
3662 vassert(r_dst < 0x20);
3664 if (!mode64) {
3665 /* In 32-bit mode, make sure the top 32 bits of imm are a sign
3666 extension of the bottom 32 bits. (Probably unnecessary.) */
3667 UInt u32 = (UInt)imm;
3668 Int s32 = (Int)u32;
3669 Long s64 = (Long)s32;
3670 imm = (ULong)s64;
3673 if (!mode64) {
3674 UInt expect[2] = { 0, 0 };
3675 UChar* p = (UChar*)&expect[0];
3676 // addis r_dst,r0,(imm>>16) => lis r_dst, (imm>>16)
3677 p = mkFormD(p, 15, r_dst, 0, (imm>>16) & 0xFFFF, endness_host);
3678 // ori r_dst, r_dst, (imm & 0xFFFF)
3679 p = mkFormD(p, 24, r_dst, r_dst, imm & 0xFFFF, endness_host);
3680 vassert(p == (UChar*)&expect[2]);
3682 return fetch32(p_to_check + 0, endness_host) == expect[0]
3683 && fetch32(p_to_check + 4, endness_host) == expect[1];
3685 } else {
3686 UInt expect[5] = { 0, 0, 0, 0, 0 };
3687 UChar* p = (UChar*)&expect[0];
3688 // full 64bit immediate load: 5 (five!) insns.
3690 // load high word
3691 // lis r_dst, (imm>>48) & 0xFFFF
3692 p = mkFormD(p, 15, r_dst, 0, (imm>>48) & 0xFFFF, endness_host);
3694 // ori r_dst, r_dst, (imm>>32) & 0xFFFF
3695 p = mkFormD(p, 24, r_dst, r_dst, (imm>>32) & 0xFFFF, endness_host);
3697 // shift r_dst low word to high word => rldicr
3698 p = mkFormMD(p, 30, r_dst, r_dst, 32, 31, 1, endness_host);
3700 // load low word
3701 // oris r_dst, r_dst, (imm>>16) & 0xFFFF
3702 p = mkFormD(p, 25, r_dst, r_dst, (imm>>16) & 0xFFFF, endness_host);
3704 // ori r_dst, r_dst, (imm) & 0xFFFF
3705 p = mkFormD(p, 24, r_dst, r_dst, imm & 0xFFFF, endness_host);
3707 vassert(p == (UChar*)&expect[5]);
3709 return fetch32(p_to_check + 0, endness_host) == expect[0]
3710 && fetch32(p_to_check + 4, endness_host) == expect[1]
3711 && fetch32(p_to_check + 8, endness_host) == expect[2]
3712 && fetch32(p_to_check + 12, endness_host) == expect[3]
3713 && fetch32(p_to_check + 16, endness_host) == expect[4];
3718 /* Generate a machine-word sized load or store. Simplified version of
3719 the Pin_Load and Pin_Store cases below. */
3720 static UChar* do_load_or_store_machine_word (
3721 UChar* p, Bool isLoad,
3722 UInt reg, PPCAMode* am, Bool mode64, VexEndness endness_host )
3724 if (isLoad) {
3725 UInt opc1, sz = mode64 ? 8 : 4;
3726 switch (am->tag) {
3727 case Pam_IR:
3728 if (mode64) {
3729 vassert(0 == (am->Pam.IR.index & 3));
3731 switch (sz) {
3732 case 4: opc1 = 32; vassert(!mode64); break;
3733 case 8: opc1 = 58; vassert(mode64); break;
3734 default: vassert(0);
3736 p = doAMode_IR(p, opc1, reg, am, mode64, endness_host);
3737 break;
3738 case Pam_RR:
3739 /* we could handle this case, but we don't expect to ever
3740 need to. */
3741 vassert(0);
3742 default:
3743 vassert(0);
3745 } else /*store*/ {
3746 UInt opc1, sz = mode64 ? 8 : 4;
3747 switch (am->tag) {
3748 case Pam_IR:
3749 if (mode64) {
3750 vassert(0 == (am->Pam.IR.index & 3));
3752 switch (sz) {
3753 case 4: opc1 = 36; vassert(!mode64); break;
3754 case 8: opc1 = 62; vassert(mode64); break;
3755 default: vassert(0);
3757 p = doAMode_IR(p, opc1, reg, am, mode64, endness_host);
3758 break;
3759 case Pam_RR:
3760 /* we could handle this case, but we don't expect to ever
3761 need to. */
3762 vassert(0);
3763 default:
3764 vassert(0);
3767 return p;
3770 /* Generate a 32-bit sized load or store. Simplified version of
3771 do_load_or_store_machine_word above. */
3772 static UChar* do_load_or_store_word32 (
3773 UChar* p, Bool isLoad,
3774 UInt reg, PPCAMode* am, Bool mode64, VexEndness endness_host )
3776 if (isLoad) {
3777 UInt opc1;
3778 switch (am->tag) {
3779 case Pam_IR:
3780 if (mode64) {
3781 vassert(0 == (am->Pam.IR.index & 3));
3783 opc1 = 32;
3784 p = doAMode_IR(p, opc1, reg, am, mode64, endness_host);
3785 break;
3786 case Pam_RR:
3787 /* we could handle this case, but we don't expect to ever
3788 need to. */
3789 vassert(0);
3790 default:
3791 vassert(0);
3793 } else /*store*/ {
3794 UInt opc1;
3795 switch (am->tag) {
3796 case Pam_IR:
3797 if (mode64) {
3798 vassert(0 == (am->Pam.IR.index & 3));
3800 opc1 = 36;
3801 p = doAMode_IR(p, opc1, reg, am, mode64, endness_host);
3802 break;
3803 case Pam_RR:
3804 /* we could handle this case, but we don't expect to ever
3805 need to. */
3806 vassert(0);
3807 default:
3808 vassert(0);
3811 return p;
3814 /* Move r_dst to r_src */
3815 static UChar* mkMoveReg ( UChar* p, UInt r_dst, UInt r_src,
3816 VexEndness endness_host )
3818 vassert(r_dst < 0x20);
3819 vassert(r_src < 0x20);
3821 if (r_dst != r_src) {
3822 /* or r_dst, r_src, r_src */
3823 p = mkFormX(p, 31, r_src, r_dst, r_src, 444, 0, endness_host );
3825 return p;
3828 static UChar* mkFormVX ( UChar* p, UInt opc1, UInt r1, UInt r2,
3829 UInt r3, UInt opc2, VexEndness endness_host )
3831 UInt theInstr;
3832 vassert(opc1 < 0x40);
3833 vassert(r1 < 0x20);
3834 vassert(r2 < 0x20);
3835 vassert(r3 < 0x20);
3836 vassert(opc2 < 0x800);
3837 theInstr = ((opc1<<26) | (r1<<21) | (r2<<16) | (r3<<11) | opc2);
3838 return emit32(p, theInstr, endness_host);
3841 static UChar* mkFormVSXRND ( UChar* p, UInt opc1, UInt R, UInt r1,
3842 UInt r2, UInt RMC, UInt opc2, UChar EX,
3843 VexEndness endness_host )
3845 /* The register mapping is all done using VR register numbers for the
3846 * V128 support. This means that the operands for this instruction have
3847 * been loaded into a VR register. The 32 VR registers map to VSR registers
3848 * 32 to 63. For these instructions, the hardware adds 32 to the source
3849 * and destination register numbers. Do not need to adjust the register
3850 * numbers for these instructions.
3853 UInt theInstr;
3855 vassert(opc1 < 0x40);
3856 vassert(r1 < 0x20);
3857 vassert(r2 < 0x20);
3858 vassert(opc2 < 0x100);
3859 vassert(EX < 0x2);
3860 vassert(R < 0x2);
3861 vassert(RMC < 0x4);
3863 theInstr = ((opc1<<26) | (r1<<21) | (R<<16) | (r2<<11) | (RMC<<9) |
3864 (opc2 << 1) | EX);
3865 return emit32(p, theInstr, endness_host);
3868 static UChar* mkFormVX_BX_TX ( UChar* p, UInt opc1, UInt r1, UInt r2,
3869 UInt r3, UInt opc2, VexEndness endness_host )
3871 /* The register mapping is all done using VR register numbers for the
3872 * V128 support. This means that the operands for this instruction have
3873 * been loaded into a VR register. The 32 VR registers map to VSR registers
3874 * 32 to 63. So to make the issued instruction reference the
3875 * corresponding VR register we have to add 32 to the source and
3876 * destination operand numbers, then load the new operand number into the
3877 * correct bit fields.
3879 * r1 = 32xTX + T; r3 = 32xBX + B;
3880 * TX is bit 0, BX is bit 1, T is in bits [25:21], B is in bit [14:11]
3881 * opc2 is in bits [10:2]
3883 UInt T, TX, B, BX;
3885 UInt theInstr;
3887 r1 += 32; // adjust the VSR register number to map to the VR number
3888 r3 += 32;
3890 vassert(opc1 < 0x40);
3891 vassert(r1 < 0x40);
3892 vassert(r2 < 0x20);
3893 vassert(r3 < 0x40);
3894 vassert(opc2 < 0x800);
3896 T = r1 & 0x1F;
3897 TX = r1 >> 5;
3898 B = r3 & 0x1F;
3899 BX = r3 >> 5;
3900 theInstr = ((opc1<<26) | (T<<21) | (r2<<16) | (B<<11) | (opc2<<2)
3901 | (BX<<1) | TX);
3902 return emit32(p, theInstr, endness_host);
3905 static UChar* mkFormVXR0 ( UChar* p, UInt opc1, UInt r1, UInt r2,
3906 UInt r3, UInt opc2, UChar R0,
3907 VexEndness endness_host )
3909 /* The register mapping is all done using VR register numbers for the
3910 * V128 support. This means that the operands for this instruction have
3911 * been loaded into a VR register. The 32 VR registers map to VSR registers
3912 * 32 to 63. For these instructions, the hardware adds 32 to the source
3913 * and destination register numbers. Do not need to adjust the register
3914 * numbers for these instructions.
3917 UInt theInstr;
3919 vassert(opc1 < 0x40);
3920 vassert(r1 < 0x20); // register numbers are between 0 and 31 (5-bits)
3921 vassert(r2 < 0x20);
3922 vassert(r3 < 0x20);
3923 vassert(opc2 < 0x800);
3924 vassert(R0 < 0x2);
3926 theInstr = ((opc1<<26) | (r1<<21) | (r2<<16) | (r3<<11) | (opc2<<1) | R0);
3927 return emit32(p, theInstr, endness_host);
3930 static UChar* mkFormVXI ( UChar* p, UInt opc1, UInt r1, UInt r2,
3931 UInt r3, UInt opc2, VexEndness endness_host )
3933 UInt theInstr;
3934 vassert(opc1 < 0x40);
3935 vassert(r1 < 0x20);
3936 vassert(r2 < 0x20);
3937 vassert(r3 < 0x20);
3938 vassert(opc2 < 0x27);
3939 theInstr = ((opc1<<26) | (r1<<21) | (r2<<16) | (r3<<11) | opc2<<1);
3940 return emit32(p, theInstr, endness_host);
3943 static UChar* mkFormVXR ( UChar* p, UInt opc1, UInt r1, UInt r2,
3944 UInt r3, UInt Rc, UInt opc2,
3945 VexEndness endness_host )
3947 UInt theInstr;
3948 vassert(opc1 < 0x40);
3949 vassert(r1 < 0x20);
3950 vassert(r2 < 0x20);
3951 vassert(r3 < 0x20);
3952 vassert(Rc < 0x2);
3953 vassert(opc2 < 0x400);
3954 theInstr = ((opc1<<26) | (r1<<21) | (r2<<16) |
3955 (r3<<11) | (Rc<<10) | opc2);
3956 return emit32(p, theInstr, endness_host);
3959 static UChar* mkFormVA ( UChar* p, UInt opc1, UInt r1, UInt r2,
3960 UInt r3, UInt r4, UInt opc2, VexEndness endness_host )
3962 UInt theInstr;
3963 vassert(opc1 < 0x40);
3964 vassert(r1 < 0x20);
3965 vassert(r2 < 0x20);
3966 vassert(r3 < 0x20);
3967 vassert(r4 < 0x20);
3968 vassert(opc2 < 0x40);
3969 theInstr = ((opc1<<26) | (r1<<21) | (r2<<16) |
3970 (r3<<11) | (r4<<6) | opc2);
3971 return emit32(p, theInstr, endness_host);
3976 /* Emit an instruction into buf and return the number of bytes used.
3977 Note that buf is not the insn's final place, and therefore it is
3978 imperative to emit position-independent code. If the emitted
3979 instruction was a profiler inc, set *is_profInc to True, else leave
3980 it unchanged.
3982 Int emit_PPCInstr ( /*MB_MOD*/Bool* is_profInc,
3983 UChar* buf, Int nbuf, const PPCInstr* i,
3984 Bool mode64, VexEndness endness_host,
3985 const void* disp_cp_chain_me_to_slowEP,
3986 const void* disp_cp_chain_me_to_fastEP,
3987 const void* disp_cp_xindir,
3988 const void* disp_cp_xassisted)
3990 UChar* p = &buf[0];
3991 vassert(nbuf >= 32);
3993 if (0) {
3994 vex_printf("asm ");ppPPCInstr(i, mode64); vex_printf("\n");
3997 switch (i->tag) {
3999 case Pin_LI:
4000 p = mkLoadImm(p, iregEnc(i->Pin.LI.dst, mode64),
4001 i->Pin.LI.imm64, mode64, endness_host);
4002 goto done;
4004 case Pin_Alu: {
4005 PPCRH* srcR = i->Pin.Alu.srcR;
4006 Bool immR = toBool(srcR->tag == Prh_Imm);
4007 UInt r_dst = iregEnc(i->Pin.Alu.dst, mode64);
4008 UInt r_srcL = iregEnc(i->Pin.Alu.srcL, mode64);
4009 UInt r_srcR = immR ? (-1)/*bogus*/ :
4010 iregEnc(srcR->Prh.Reg.reg, mode64);
4012 switch (i->Pin.Alu.op) {
4013 case Palu_ADD:
4014 if (immR) {
4015 /* addi (PPC32 p350) */
4016 vassert(srcR->Prh.Imm.syned);
4017 vassert(srcR->Prh.Imm.imm16 != 0x8000);
4018 p = mkFormD(p, 14, r_dst, r_srcL, srcR->Prh.Imm.imm16, endness_host);
4019 } else {
4020 /* add (PPC32 p347) */
4021 p = mkFormXO(p, 31, r_dst, r_srcL, r_srcR, 0, 266, 0, endness_host);
4023 break;
4025 case Palu_SUB:
4026 if (immR) {
4027 /* addi (PPC32 p350), but with negated imm */
4028 vassert(srcR->Prh.Imm.syned);
4029 vassert(srcR->Prh.Imm.imm16 != 0x8000);
4030 p = mkFormD(p, 14, r_dst, r_srcL, (- srcR->Prh.Imm.imm16),
4031 endness_host);
4032 } else {
4033 /* subf (PPC32 p537), with args the "wrong" way round */
4034 p = mkFormXO(p, 31, r_dst, r_srcR, r_srcL, 0, 40, 0, endness_host);
4036 break;
4038 case Palu_AND:
4039 if (immR) {
4040 /* andi. (PPC32 p358) */
4041 vassert(!srcR->Prh.Imm.syned);
4042 p = mkFormD(p, 28, r_srcL, r_dst, srcR->Prh.Imm.imm16, endness_host);
4043 } else {
4044 /* and (PPC32 p356) */
4045 p = mkFormX(p, 31, r_srcL, r_dst, r_srcR, 28, 0, endness_host);
4047 break;
4049 case Palu_OR:
4050 if (immR) {
4051 /* ori (PPC32 p497) */
4052 vassert(!srcR->Prh.Imm.syned);
4053 p = mkFormD(p, 24, r_srcL, r_dst, srcR->Prh.Imm.imm16, endness_host);
4054 } else {
4055 /* or (PPC32 p495) */
4056 p = mkFormX(p, 31, r_srcL, r_dst, r_srcR, 444, 0, endness_host);
4058 break;
4060 case Palu_XOR:
4061 if (immR) {
4062 /* xori (PPC32 p550) */
4063 vassert(!srcR->Prh.Imm.syned);
4064 p = mkFormD(p, 26, r_srcL, r_dst, srcR->Prh.Imm.imm16, endness_host);
4065 } else {
4066 /* xor (PPC32 p549) */
4067 p = mkFormX(p, 31, r_srcL, r_dst, r_srcR, 316, 0, endness_host);
4069 break;
4071 default:
4072 goto bad;
4074 goto done;
4077 case Pin_Shft: {
4078 PPCRH* srcR = i->Pin.Shft.srcR;
4079 Bool sz32 = i->Pin.Shft.sz32;
4080 Bool immR = toBool(srcR->tag == Prh_Imm);
4081 UInt r_dst = iregEnc(i->Pin.Shft.dst, mode64);
4082 UInt r_srcL = iregEnc(i->Pin.Shft.srcL, mode64);
4083 UInt r_srcR = immR ? (-1)/*bogus*/ :
4084 iregEnc(srcR->Prh.Reg.reg, mode64);
4085 if (!mode64)
4086 vassert(sz32);
4088 switch (i->Pin.Shft.op) {
4089 case Pshft_SHL:
4090 if (sz32) {
4091 if (immR) {
4092 /* rd = rs << n, 1 <= n <= 31
4094 rlwinm rd,rs,n,0,31-n (PPC32 p501)
4096 UInt n = srcR->Prh.Imm.imm16;
4097 vassert(!srcR->Prh.Imm.syned);
4098 vassert(n > 0 && n < 32);
4099 p = mkFormM(p, 21, r_srcL, r_dst, n, 0, 31-n, 0, endness_host);
4100 } else {
4101 /* slw (PPC32 p505) */
4102 p = mkFormX(p, 31, r_srcL, r_dst, r_srcR, 24, 0, endness_host);
4104 } else {
4105 if (immR) {
4106 /* rd = rs << n, 1 <= n <= 63
4108 rldicr rd,rs,n,63-n (PPC64 p559)
4110 UInt n = srcR->Prh.Imm.imm16;
4111 vassert(!srcR->Prh.Imm.syned);
4112 vassert(n > 0 && n < 64);
4113 p = mkFormMD(p, 30, r_srcL, r_dst, n, 63-n, 1, endness_host);
4114 } else {
4115 /* sld (PPC64 p568) */
4116 p = mkFormX(p, 31, r_srcL, r_dst, r_srcR, 27, 0, endness_host);
4119 break;
4121 case Pshft_SHR:
4122 if (sz32) {
4123 if (immR) {
4124 /* rd = rs >>u n, 1 <= n <= 31
4126 rlwinm rd,rs,32-n,n,31 (PPC32 p501)
4128 UInt n = srcR->Prh.Imm.imm16;
4129 vassert(!srcR->Prh.Imm.syned);
4130 vassert(n > 0 && n < 32);
4131 p = mkFormM(p, 21, r_srcL, r_dst, 32-n, n, 31, 0, endness_host);
4132 } else {
4133 /* srw (PPC32 p508) */
4134 p = mkFormX(p, 31, r_srcL, r_dst, r_srcR, 536, 0, endness_host);
4136 } else {
4137 if (immR) {
4138 /* rd = rs >>u n, 1 <= n <= 63
4140 rldicl rd,rs,64-n,n (PPC64 p558)
4142 UInt n = srcR->Prh.Imm.imm16;
4143 vassert(!srcR->Prh.Imm.syned);
4144 vassert(n > 0 && n < 64);
4145 p = mkFormMD(p, 30, r_srcL, r_dst, 64-n, n, 0, endness_host);
4146 } else {
4147 /* srd (PPC64 p574) */
4148 p = mkFormX(p, 31, r_srcL, r_dst, r_srcR, 539, 0, endness_host);
4151 break;
4153 case Pshft_SAR:
4154 if (sz32) {
4155 if (immR) {
4156 /* srawi (PPC32 p507) */
4157 UInt n = srcR->Prh.Imm.imm16;
4158 vassert(!srcR->Prh.Imm.syned);
4159 /* In 64-bit mode, we allow right shifts by zero bits
4160 as that is a handy way to sign extend the lower 32
4161 bits into the upper 32 bits. */
4162 if (mode64)
4163 vassert(n >= 0 && n < 32);
4164 else
4165 vassert(n > 0 && n < 32);
4166 p = mkFormX(p, 31, r_srcL, r_dst, n, 824, 0, endness_host);
4167 } else {
4168 /* sraw (PPC32 p506) */
4169 p = mkFormX(p, 31, r_srcL, r_dst, r_srcR, 792, 0, endness_host);
4171 } else {
4172 if (immR) {
4173 /* sradi (PPC64 p571) */
4174 UInt n = srcR->Prh.Imm.imm16;
4175 vassert(!srcR->Prh.Imm.syned);
4176 vassert(n > 0 && n < 64);
4177 p = mkFormXS(p, 31, r_srcL, r_dst, n, 413, 0, endness_host);
4178 } else {
4179 /* srad (PPC32 p570) */
4180 p = mkFormX(p, 31, r_srcL, r_dst, r_srcR, 794, 0, endness_host);
4183 break;
4185 default:
4186 goto bad;
4188 goto done;
4191 case Pin_AddSubC: {
4192 Bool isAdd = i->Pin.AddSubC.isAdd;
4193 Bool setC = i->Pin.AddSubC.setC;
4194 UInt r_srcL = iregEnc(i->Pin.AddSubC.srcL, mode64);
4195 UInt r_srcR = iregEnc(i->Pin.AddSubC.srcR, mode64);
4196 UInt r_dst = iregEnc(i->Pin.AddSubC.dst, mode64);
4198 if (isAdd) {
4199 if (setC) /* addc (PPC32 p348) */
4200 p = mkFormXO(p, 31, r_dst, r_srcL, r_srcR, 0, 10, 0, endness_host);
4201 else /* adde (PPC32 p349) */
4202 p = mkFormXO(p, 31, r_dst, r_srcL, r_srcR, 0, 138, 0, endness_host);
4203 } else {
4204 /* subfX, with args the "wrong" way round */
4205 if (setC) /* subfc (PPC32 p538) */
4206 p = mkFormXO(p, 31, r_dst, r_srcR, r_srcL, 0, 8, 0, endness_host);
4207 else /* subfe (PPC32 p539) */
4208 p = mkFormXO(p, 31, r_dst, r_srcR, r_srcL, 0, 136, 0, endness_host);
4210 goto done;
4213 case Pin_Cmp: {
4214 Bool syned = i->Pin.Cmp.syned;
4215 Bool sz32 = i->Pin.Cmp.sz32;
4216 UInt fld1 = i->Pin.Cmp.crfD << 2;
4217 UInt r_srcL = iregEnc(i->Pin.Cmp.srcL, mode64);
4218 UInt r_srcR, imm_srcR;
4219 PPCRH* srcR = i->Pin.Cmp.srcR;
4221 if (!mode64) // cmp double word invalid for mode32
4222 vassert(sz32);
4223 else if (!sz32) // mode64 && cmp64: set L=1
4224 fld1 |= 1;
4226 switch (srcR->tag) {
4227 case Prh_Imm:
4228 vassert(syned == srcR->Prh.Imm.syned);
4229 imm_srcR = srcR->Prh.Imm.imm16;
4230 if (syned) { // cmpw/di (signed) (PPC32 p368)
4231 vassert(imm_srcR != 0x8000);
4232 p = mkFormD(p, 11, fld1, r_srcL, imm_srcR, endness_host);
4233 } else { // cmplw/di (unsigned) (PPC32 p370)
4234 p = mkFormD(p, 10, fld1, r_srcL, imm_srcR, endness_host);
4236 break;
4237 case Prh_Reg:
4238 r_srcR = iregEnc(srcR->Prh.Reg.reg, mode64);
4239 if (syned) // cmpwi (signed) (PPC32 p367)
4240 p = mkFormX(p, 31, fld1, r_srcL, r_srcR, 0, 0, endness_host);
4241 else // cmplwi (unsigned) (PPC32 p379)
4242 p = mkFormX(p, 31, fld1, r_srcL, r_srcR, 32, 0, endness_host);
4243 break;
4244 default:
4245 goto bad;
4247 goto done;
4250 case Pin_Unary: {
4251 UInt r_dst = iregEnc(i->Pin.Unary.dst, mode64);
4252 UInt r_src = iregEnc(i->Pin.Unary.src, mode64);
4254 switch (i->Pin.Unary.op) {
4255 case Pun_NOT: // nor r_dst,r_src,r_src
4256 p = mkFormX(p, 31, r_src, r_dst, r_src, 124, 0, endness_host);
4257 break;
4258 case Pun_NEG: // neg r_dst,r_src
4259 p = mkFormXO(p, 31, r_dst, r_src, 0, 0, 104, 0, endness_host);
4260 break;
4261 case Pun_CLZ32: // cntlzw r_dst, r_src
4262 p = mkFormX(p, 31, r_src, r_dst, 0, 26, 0, endness_host);
4263 break;
4264 case Pun_CLZ64: // cntlzd r_dst, r_src
4265 vassert(mode64);
4266 p = mkFormX(p, 31, r_src, r_dst, 0, 58, 0, endness_host);
4267 break;
4268 case Pun_EXTSW: // extsw r_dst, r_src
4269 vassert(mode64);
4270 p = mkFormX(p, 31, r_src, r_dst, 0, 986, 0, endness_host);
4271 break;
4272 case Pun_POP32: // popcntw r_dst, r_src
4273 p = mkFormX(p, 31, r_src, r_dst, 0, 378, 0, endness_host);
4274 break;
4275 case Pun_POP64: // popcntd r_dst, r_src
4276 vassert(mode64);
4277 p = mkFormX(p, 31, r_src, r_dst, 0, 506, 0, endness_host);
4278 break;
4279 default:
4280 goto bad;
4282 goto done;
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);
4292 if (!mode64)
4293 vassert(sz32);
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);
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);
4319 goto done;
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);
4329 if (!mode64)
4330 vassert(sz32);
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);
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);
4363 goto done;
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;
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 */
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
4392 /* load target to r_dst */ // p += 4|8|20
4393 p = mkLoadImm(p, r_dst, i->Pin.Call.target, mode64, endness_host);
4395 /* mtspr 9,r_dst => move r_dst to count register */
4396 p = mkFormXFX(p, r_dst, 9, 467, endness_host); // p += 4
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
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);
4409 goto done;
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);
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);
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
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 --- */
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);
4469 goto done;
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);
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);
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
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);
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);
4517 goto done;
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);
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
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");
4566 vassert(trcval != 0);
4567 p = mkLoadImm(p, /*r*/31, trcval, mode64, endness_host);
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);
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);
4586 goto done;
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);
4595 r_dst = iregEnc(i->Pin.CMov.dst, mode64);
4596 cond = i->Pin.CMov.cond;
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;
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;
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);
4628 goto done;
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));
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;
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;
4658 p = doAMode_RR(p, 31, opc2, r_dst, am_addr, mode64, endness_host);
4659 goto done;
4660 default:
4661 goto bad;
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;
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;
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;
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;
4686 goto bad;
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;
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.
4704 // r_tmp = CR => mfcr r_tmp
4705 p = mkFormX(p, 31, r_tmp, 0, 0, 19, 0, endness_host);
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);
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);
4716 goto done;
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;
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;
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));
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;
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;
4763 p = doAMode_RR(p, 31, opc2, r_src, am_addr, mode64, endness_host);
4764 goto done;
4765 default:
4766 goto bad;
4768 goto done;
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;
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;
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;
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;
4793 goto bad;
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;
4833 goto done;
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;
4868 goto done;
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.
4880 UInt fr_dst = vregEnc(i->Pin.Fp128Unary.dst);
4881 UInt fr_src = vregEnc(i->Pin.Fp128Unary.src);
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;
4920 goto done;
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);
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.
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;
4992 goto done;
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);
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.
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;
5040 goto done;
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;
5068 goto done;
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);
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);
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);
5096 goto done;
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;
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;
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;
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;
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;
5156 goto bad;
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;
5164 if (fr_dst == fr_src) goto done;
5166 vassert(cc.test != Pct_ALWAYS);
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);
5175 // fmr, PPC32 p410
5176 p = mkFormX(p, 63, fr_dst, 0, fr_src, 72, 0, endness_host);
5177 goto done;
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;
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);
5195 // mfcr (mv CR to r_dst), PPC32 p467
5196 p = mkFormX(p, 31, r_dst, 0, 0, 19, 0, endness_host);
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;
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;
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);
5220 v_reg = vregEnc(i->Pin.AvLdSt.reg);
5221 r_base = iregEnc(i->Pin.AvLdSt.addr->Pam.RR.base, mode64);
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);
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);
5239 goto done;
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 */
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
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
5274 default:
5275 goto bad;
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:
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.
5287 /* Scatter the four F16 values in the Vector register */
5288 p = mkFormVX( p, 4, v_dst, 0, v_src, 590, endness_host );// vupkhsh
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.
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 );
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.
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;
5335 goto done;
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;
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;
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;
5364 p = mkFormVX( p, 4, v_dst, v_srcL, v_srcR, opc2, endness_host );
5365 goto done;
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);
5373 switch (i->Pin.AvBinaryInt.op) {
5374 /* BCD */
5375 case Pav_I128StoBCD128: // bcdcfsq
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 );
5382 break;
5384 case Pav_F128toI128S: // xsrqpi, xsrqpix
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.
5400 p = mkFormVSXRND( p, 63, R, dst, src, RMC, opc2, EX,
5401 endness_host );
5403 break;
5405 case Pav_ROUNDFPQ: // xsrqpxp
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 );
5414 break;
5416 default:
5417 goto bad;
5420 goto done;
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) {
5430 case Pav_ADDU: opc2 = 0; break; // vaddubm
5431 case Pav_QADDU: opc2 = 512; break; // vaddubs
5432 case Pav_QADDS: opc2 = 768; break; // vaddsbs
5434 case Pav_SUBU: opc2 = 1024; break; // vsububm
5435 case Pav_QSUBU: opc2 = 1536; break; // vsububs
5436 case Pav_QSUBS: opc2 = 1792; break; // vsubsbs
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
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
5450 case Pav_CMPEQU: opc2 = 6; break; // vcmpequb
5451 case Pav_CMPGTU: opc2 = 518; break; // vcmpgtub
5452 case Pav_CMPGTS: opc2 = 774; break; // vcmpgtsb
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
5459 case Pav_MRGHI: opc2 = 12; break; // vmrghb
5460 case Pav_MRGLO: opc2 = 268; break; // vmrglb
5462 case Pav_POLYMULADD: opc2 = 1032; break; // vpmsumb
5464 default:
5465 goto bad;
5467 p = mkFormVX( p, 4, v_dst, v_srcL, v_srcR, opc2, endness_host );
5468 goto done;
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) {
5478 case Pav_ADDU: opc2 = 64; break; // vadduhm
5479 case Pav_QADDU: opc2 = 576; break; // vadduhs
5480 case Pav_QADDS: opc2 = 832; break; // vaddshs
5482 case Pav_SUBU: opc2 = 1088; break; // vsubuhm
5483 case Pav_QSUBU: opc2 = 1600; break; // vsubuhs
5484 case Pav_QSUBS: opc2 = 1856; break; // vsubshs
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
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
5498 case Pav_CMPEQU: opc2 = 70; break; // vcmpequh
5499 case Pav_CMPGTU: opc2 = 582; break; // vcmpgtuh
5500 case Pav_CMPGTS: opc2 = 838; break; // vcmpgtsh
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
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
5513 case Pav_MRGHI: opc2 = 76; break; // vmrghh
5514 case Pav_MRGLO: opc2 = 332; break; // vmrglh
5516 case Pav_POLYMULADD: opc2 = 1224; break; // vpmsumh
5518 default:
5519 goto bad;
5521 p = mkFormVX( p, 4, v_dst, v_srcL, v_srcR, opc2, endness_host );
5522 goto done;
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) {
5532 case Pav_ADDU: opc2 = 128; break; // vadduwm
5533 case Pav_QADDU: opc2 = 640; break; // vadduws
5534 case Pav_QADDS: opc2 = 896; break; // vaddsws
5536 case Pav_SUBU: opc2 = 1152; break; // vsubuwm
5537 case Pav_QSUBU: opc2 = 1664; break; // vsubuws
5538 case Pav_QSUBS: opc2 = 1920; break; // vsubsws
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
5546 case Pav_AVGU: opc2 = 1154; break; // vavguw
5547 case Pav_AVGS: opc2 = 1410; break; // vavgsw
5549 case Pav_MAXU: opc2 = 130; break; // vmaxuw
5550 case Pav_MAXS: opc2 = 386; break; // vmaxsw
5552 case Pav_MINS: opc2 = 898; break; // vminsw
5553 case Pav_MINU: opc2 = 642; break; // vminuw
5555 case Pav_CMPEQU: opc2 = 134; break; // vcmpequw
5556 case Pav_CMPGTS: opc2 = 902; break; // vcmpgtsw
5557 case Pav_CMPGTU: opc2 = 646; break; // vcmpgtuw
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
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
5569 case Pav_MRGHI: opc2 = 140; break; // vmrghw
5570 case Pav_MRGLO: opc2 = 396; break; // vmrglw
5572 case Pav_CATODD: opc2 = 1676; break; // vmrgow
5573 case Pav_CATEVEN: opc2 = 1932; break; // vmrgew
5575 case Pav_POLYMULADD: opc2 = 1160; break; // vpmsumw
5577 default:
5578 goto bad;
5580 p = mkFormVX( p, 4, v_dst, v_srcL, v_srcR, opc2, endness_host );
5581 goto done;
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;
5612 p = mkFormVX( p, 4, v_dst, v_srcL, v_srcR, opc2, endness_host );
5613 goto done;
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;
5624 p = mkFormVX( p, 4, v_dst, v_src, 0, opc2, endness_host );
5625 goto done;
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;
5640 p = mkFormVX( p, 4, v_dst, v_srcL, v_srcR, opc2, endness_host );
5641 goto done;
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;
5654 p = mkFormVX( p, 4, v_dst, v_src, s_field->Pri.Imm, opc2, endness_host );
5655 goto done;
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.
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;
5671 p = mkFormVXR( p, 4, v_dst, v_src1, v_src2,
5672 0x1, ps | opc2, endness_host );
5673 goto done;
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) {
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;
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.
5699 UInt vB = 29; // XXX: Using v29 for temp do not change
5700 // without also changing
5701 // getRegUsage_PPCInstr
5702 UInt konst = 0x1F;
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 );
5708 // vslw vB,vB,vB (each word of vB = (0x1F << 0x1F) = 0x80000000
5709 p = mkFormVX( p, 4, vB, vB, vB, 388, endness_host );
5711 // Finally, do the multiply:
5712 p = mkFormVA( p, 4, v_dst, v_srcL, vB, v_srcR, 46, endness_host );
5713 break;
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;
5725 default:
5726 goto bad;
5728 goto done;
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;
5749 p = mkFormVX( p, 4, v_dst, 0, v_src, opc2, endness_host );
5750 goto done;
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;
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;
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;
5776 r_base = iregEnc(i->Pin.AvSh.addr->Pam.RR.base, mode64);
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);
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;
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;
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);
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 );
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 );
5828 goto done;
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;
5836 if (v_dst == v_src) goto done;
5838 vassert(cc.test != Pct_ALWAYS);
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);
5846 /* vmr */
5847 p = mkFormVX( p, 4, v_dst, v_src, v_src, 1156, endness_host );
5848 goto done;
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;
5857 case Pin_Dfp64Unary: {
5858 UInt fr_dst = fregEnc( i->Pin.FpUnary.dst );
5859 UInt fr_src = fregEnc( i->Pin.FpUnary.src );
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;
5884 goto done;
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;
5914 goto done;
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;
5922 shift = i->Pin.DfpShift.shift->Pri.Imm;
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;
5935 goto done;
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);
5943 switch (i->Pin.ExtractExpD128.op) {
5944 case Pfp_DXEXQ:
5945 /* Setup the upper and lower registers of the source operand
5946 * register pair.
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 );
5952 /* The instruction will put the 64-bit result in
5953 * register 10.
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;
5961 goto done;
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);
5968 /* Do instruction with 128-bit source operands in registers (10,11)
5969 * and (12,13).
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 );
5975 p = mkFormX( p, 63, 10, 0, 12, 258, 0, endness_host );
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.
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;
5989 goto done;
5992 case Pin_Dfp128Binary: {
5993 /* dst is used to supply the left source operand and return
5994 * the result.
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 );
6001 /* Setup the upper and lower registers of the source operand
6002 * register pair.
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 );
6009 /* Do instruction with 128-bit source operands in registers (10,11)
6010 * and (12,13).
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;
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.
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;
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;
6045 shift = i->Pin.DfpShift128.shift->Pri.Imm;
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);
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.
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.
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;
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.
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;
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;
6083 r_rmc = i->Pin.DfpRound.r_rmc->Pri.Imm;
6084 r = (r_rmc & 0x8) >> 3;
6085 rmc = r_rmc & 0x3;
6087 // drintx
6088 p = mkFormZ23(p, 59, fr_dst, r, fr_src, rmc, 99, 0, endness_host);
6089 goto done;
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;
6099 r_rmc = i->Pin.DfpRound128.r_rmc->Pri.Imm;
6100 r = (r_rmc & 0x8) >> 3;
6101 rmc = r_rmc & 0x3;
6103 /* Setup the upper and lower registers of the source operand
6104 * register pair.
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);
6109 /* Do drintx instruction with 128-bit source operands in
6110 * registers (12,13).
6112 p = mkFormZ23(p, 63, 10, r, 12, rmc, 99, 0, endness_host);
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.
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;
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;
6129 rmc = i->Pin.DfpQuantize.rmc->Pri.Imm;
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;
6141 goto done;
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;
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.
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);
6161 /* Do dquaq instruction with 128-bit source operands in
6162 * registers (12,13).
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;
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.
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;
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 );
6190 /* Setup the upper and lower registers of the source operand
6191 * register pair.
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 );
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;
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;
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 );
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;
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;
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);
6240 /* The left operand is a single F64 value, the right is an F128
6241 * register pair.
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 );
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.
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;
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);
6266 // mfcr (mv CR to r_dst)
6267 p = mkFormX(p, 31, r_dst, 0, 0, 19, 0, endness_host);
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;
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.
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);
6292 p = mkFormX(p, 63, crfD<<2, 10, 12, 130, 0, endness_host);
6294 // mfcr (mv CR to r_dst)
6295 p = mkFormX(p, 31, r_dst, 0, 0, 19, 0, endness_host);
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;
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:
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: */
6339 /* Crosscheck */
6340 vassert(evCheckSzB_PPC() == (UChar*)p - (UChar*)p0);
6341 goto done;
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)
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);
6380 /* Tell the caller .. */
6381 vassert(!(*is_profInc));
6382 *is_profInc = True;
6383 goto done;
6386 default:
6387 goto bad;
6390 bad:
6391 vex_printf("\n=> ");
6392 ppPPCInstr(i, mode64);
6393 vpanic("emit_PPCInstr");
6394 /*NOTREACHED*/
6396 done:
6397 vassert(p - &buf[0] <= 64);
6398 return p - &buf[0];
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. */
6405 Int evCheckSzB_PPC (void)
6407 return 28;
6411 /* NB: what goes on here has to be very closely coordinated with the
6412 emitInstr case for XDirect, above. */
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 )
6419 if (mode64) {
6420 vassert((endness_host == VexEndnessBE) ||
6421 (endness_host == VexEndnessLE));
6422 } else {
6423 vassert(endness_host == VexEndnessBE);
6426 /* What we're expecting to see is:
6427 imm32/64-fixed r30, disp_cp_chain_me_to_EXPECTED
6428 mtctr r30
6429 bctrl
6431 <8 or 20 bytes generated by mkLoadImm_EXACTLY2or5>
6432 7F C9 03 A6
6433 4E 80 04 21
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
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.
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);
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;
6465 /* NB: what goes on here has to be very closely coordinated with the
6466 emitInstr case for XDirect, above. */
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 )
6473 if (mode64) {
6474 vassert((endness_host == VexEndnessBE) ||
6475 (endness_host == VexEndnessLE));
6476 } else {
6477 vassert(endness_host == VexEndnessBE);
6480 /* What we're expecting to see is:
6481 imm32/64-fixed r30, place_to_jump_to_EXPECTED
6482 mtctr r30
6483 bctr
6485 <8 or 20 bytes generated by mkLoadImm_EXACTLY2or5>
6486 7F C9 03 A6
6487 4E 80 04 20
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
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.
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);
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;
6519 /* Patch the counter address into a profile inc point, as previously
6520 created by the Pin_ProfInc case for emit_PPCInstr. */
6521 VexInvalRange patchProfInc_PPC ( VexEndness endness_host,
6522 void* place_to_patch,
6523 const ULong* location_of_counter,
6524 Bool mode64 )
6526 if (mode64) {
6527 vassert((endness_host == VexEndnessBE) ||
6528 (endness_host == VexEndnessLE));
6529 } else {
6530 vassert(endness_host == VexEndnessBE);
6533 UChar* p = (UChar*)place_to_patch;
6534 vassert(0 == (3 & (HWord)p));
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);
6565 VexInvalRange vir = {(HWord)place_to_patch, len};
6566 return vir;
6570 /*---------------------------------------------------------------*/
6571 /*--- end host_ppc_defs.c ---*/
6572 /*---------------------------------------------------------------*/