2 /*---------------------------------------------------------------*/
3 /*--- begin host_ppc_defs.c ---*/
4 /*---------------------------------------------------------------*/
7 This file is part of Valgrind, a dynamic binary instrumentation
10 Copyright (C) 2004-2017 OpenWorks LLP
13 This program is free software; you can redistribute it and/or
14 modify it under the terms of the GNU General Public License as
15 published by the Free Software Foundation; either version 2 of the
16 License, or (at your option) any later version.
18 This program is distributed in the hope that it will be useful, but
19 WITHOUT ANY WARRANTY; without even the implied warranty of
20 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
21 General Public License for more details.
23 You should have received a copy of the GNU General Public License
24 along with this program; if not, see <http://www.gnu.org/licenses/>.
26 The GNU General Public License is contained in the file COPYING.
28 Neither the names of the U.S. Department of Energy nor the
29 University of California nor the names of its contributors may be
30 used to endorse or promote products derived from this software
31 without prior written permission.
34 #include "libvex_basictypes.h"
36 #include "libvex_trc_values.h"
38 #include "main_util.h"
39 #include "host_generic_regs.h"
40 #include "host_ppc_defs.h"
43 /* --------- Registers. --------- */
45 const RRegUniverse
* getRRegUniverse_PPC ( Bool mode64
)
47 /* The real-register universe is a big constant, so we just want to
48 initialise it once. rRegUniverse_PPC_initted values: 0=not initted,
49 1=initted for 32-bit-mode, 2=initted for 64-bit-mode */
50 static RRegUniverse rRegUniverse_PPC
;
51 static UInt rRegUniverse_PPC_initted
= 0;
53 /* Handy shorthand, nothing more */
54 RRegUniverse
* ru
= &rRegUniverse_PPC
;
56 /* This isn't thread-safe. Sigh. */
57 UInt howNeeded
= mode64
? 2 : 1;
58 if (LIKELY(rRegUniverse_PPC_initted
== howNeeded
))
61 RRegUniverse__init(ru
);
63 /* Add the registers. The initial segment of this array must be
64 those available for allocation by reg-alloc, and those that
65 follow are not available for allocation. */
66 // GPR0 = scratch reg where poss. - some ops interpret as value zero
67 // GPR1 = stack pointer
69 ru
->allocable_start
[(mode64
) ? HRcInt64
: HRcInt32
] = ru
->size
;
70 // GPR14 and above are callee save. List them first.
71 ru
->regs
[ru
->size
++] = hregPPC_GPR14(mode64
);
72 ru
->regs
[ru
->size
++] = hregPPC_GPR15(mode64
);
73 ru
->regs
[ru
->size
++] = hregPPC_GPR16(mode64
);
74 ru
->regs
[ru
->size
++] = hregPPC_GPR17(mode64
);
75 ru
->regs
[ru
->size
++] = hregPPC_GPR18(mode64
);
76 ru
->regs
[ru
->size
++] = hregPPC_GPR19(mode64
);
77 ru
->regs
[ru
->size
++] = hregPPC_GPR20(mode64
);
78 ru
->regs
[ru
->size
++] = hregPPC_GPR21(mode64
);
79 ru
->regs
[ru
->size
++] = hregPPC_GPR22(mode64
);
80 ru
->regs
[ru
->size
++] = hregPPC_GPR23(mode64
);
81 ru
->regs
[ru
->size
++] = hregPPC_GPR24(mode64
);
82 ru
->regs
[ru
->size
++] = hregPPC_GPR25(mode64
);
83 ru
->regs
[ru
->size
++] = hregPPC_GPR26(mode64
);
84 ru
->regs
[ru
->size
++] = hregPPC_GPR27(mode64
);
85 ru
->regs
[ru
->size
++] = hregPPC_GPR28(mode64
);
87 // Caller save registers now.
88 ru
->regs
[ru
->size
++] = hregPPC_GPR3(mode64
);
89 ru
->regs
[ru
->size
++] = hregPPC_GPR4(mode64
);
90 ru
->regs
[ru
->size
++] = hregPPC_GPR5(mode64
);
91 ru
->regs
[ru
->size
++] = hregPPC_GPR6(mode64
);
92 ru
->regs
[ru
->size
++] = hregPPC_GPR7(mode64
);
93 ru
->regs
[ru
->size
++] = hregPPC_GPR8(mode64
);
94 ru
->regs
[ru
->size
++] = hregPPC_GPR9(mode64
);
95 ru
->regs
[ru
->size
++] = hregPPC_GPR10(mode64
);
98 r11 used for calls by ptr / env ptr for some langs
99 r12 used for exception handling and global linkage code */
100 ru
->regs
[ru
->size
++] = hregPPC_GPR11(mode64
);
101 ru
->regs
[ru
->size
++] = hregPPC_GPR12(mode64
);
103 // GPR13 = thread specific pointer
104 ru
->allocable_end
[(mode64
) ? HRcInt64
: HRcInt32
] = ru
->size
- 1;
105 // GPR29 is reserved for the dispatcher
106 // GPR30 is reserved as AltiVec spill reg temporary
107 // GPR31 is reserved for the GuestStatePtr
109 /* Don't waste the reg-allocs's time trawling through zillions of
110 FP registers - they mostly will never be used. We'll tolerate
111 the occasional extra spill instead. */
112 /* For both ppc32-linux and ppc64-linux, f14-f31 are callee save.
114 ru
->allocable_start
[HRcFlt64
] = ru
->size
;
115 ru
->regs
[ru
->size
++] = hregPPC_FPR14(mode64
);
116 ru
->regs
[ru
->size
++] = hregPPC_FPR15(mode64
);
117 ru
->regs
[ru
->size
++] = hregPPC_FPR16(mode64
);
118 ru
->regs
[ru
->size
++] = hregPPC_FPR17(mode64
);
119 ru
->regs
[ru
->size
++] = hregPPC_FPR18(mode64
);
120 ru
->regs
[ru
->size
++] = hregPPC_FPR19(mode64
);
121 ru
->regs
[ru
->size
++] = hregPPC_FPR20(mode64
);
122 ru
->regs
[ru
->size
++] = hregPPC_FPR21(mode64
);
123 ru
->allocable_end
[HRcFlt64
] = ru
->size
- 1;
125 /* Same deal re Altivec */
126 /* For both ppc32-linux and ppc64-linux, v20-v31 are callee save.
128 /* NB, vr29 is used as a scratch temporary -- do not allocate */
129 ru
->allocable_start
[HRcVec128
] = ru
->size
;
130 ru
->regs
[ru
->size
++] = hregPPC_VR20(mode64
);
131 ru
->regs
[ru
->size
++] = hregPPC_VR21(mode64
);
132 ru
->regs
[ru
->size
++] = hregPPC_VR22(mode64
);
133 ru
->regs
[ru
->size
++] = hregPPC_VR23(mode64
);
134 ru
->regs
[ru
->size
++] = hregPPC_VR24(mode64
);
135 ru
->regs
[ru
->size
++] = hregPPC_VR25(mode64
);
136 ru
->regs
[ru
->size
++] = hregPPC_VR26(mode64
);
137 ru
->regs
[ru
->size
++] = hregPPC_VR27(mode64
);
138 ru
->allocable_end
[HRcVec128
] = ru
->size
- 1;
139 ru
->allocable
= ru
->size
;
141 /* And other regs, not available to the allocator. */
142 ru
->regs
[ru
->size
++] = hregPPC_GPR1(mode64
);
143 ru
->regs
[ru
->size
++] = hregPPC_GPR29(mode64
);
144 ru
->regs
[ru
->size
++] = hregPPC_GPR30(mode64
);
145 ru
->regs
[ru
->size
++] = hregPPC_GPR31(mode64
);
146 ru
->regs
[ru
->size
++] = hregPPC_VR29(mode64
);
148 rRegUniverse_PPC_initted
= howNeeded
;
150 RRegUniverse__check_is_sane(ru
);
155 UInt
ppHRegPPC ( HReg reg
)
158 static const HChar
* ireg32_names
[32]
159 = { "%r0", "%r1", "%r2", "%r3",
160 "%r4", "%r5", "%r6", "%r7",
161 "%r8", "%r9", "%r10", "%r11",
162 "%r12", "%r13", "%r14", "%r15",
163 "%r16", "%r17", "%r18", "%r19",
164 "%r20", "%r21", "%r22", "%r23",
165 "%r24", "%r25", "%r26", "%r27",
166 "%r28", "%r29", "%r30", "%r31" };
167 /* Be generic for all virtual regs. */
168 if (hregIsVirtual(reg
)) {
171 /* But specific for real regs. */
172 switch (hregClass(reg
)) {
174 r
= hregEncoding(reg
);
175 vassert(r
>= 0 && r
< 32);
176 return vex_printf("%s", ireg32_names
[r
]);
178 r
= hregEncoding(reg
);
179 vassert(r
>= 0 && r
< 32);
180 return vex_printf("%s", ireg32_names
[r
]);
182 r
= hregEncoding(reg
);
183 vassert(r
>= 0 && r
< 32);
184 return vex_printf("%%fr%d", r
);
186 r
= hregEncoding(reg
);
187 vassert(r
>= 0 && r
< 32);
188 return vex_printf("%%v%d", r
);
195 /* --------- Condition codes, Intel encoding. --------- */
197 const HChar
* showPPCCondCode ( PPCCondCode cond
)
199 if (cond
.test
== Pct_ALWAYS
) return "always";
203 return (cond
.test
== Pct_TRUE
) ? "cr7.so=1" : "cr7.so=0";
205 return (cond
.test
== Pct_TRUE
) ? "cr7.eq=1" : "cr7.eq=0";
207 return (cond
.test
== Pct_TRUE
) ? "cr7.gt=1" : "cr7.gt=0";
209 return (cond
.test
== Pct_TRUE
) ? "cr7.lt=1" : "cr7.lt=0";
212 default: vpanic("ppPPCCondCode");
216 /* construct condition code */
217 PPCCondCode
mk_PPCCondCode ( PPCCondTest test
, PPCCondFlag flag
)
222 if (test
== Pct_ALWAYS
) {
223 vassert(flag
== Pcf_NONE
);
225 vassert(flag
!= Pcf_NONE
);
230 /* false->true, true->false */
231 PPCCondTest
invertCondTest ( PPCCondTest ct
)
233 vassert(ct
!= Pct_ALWAYS
);
234 return (ct
== Pct_TRUE
) ? Pct_FALSE
: Pct_TRUE
;
238 /* --------- PPCAMode: memory address expressions. --------- */
240 PPCAMode
* PPCAMode_IR ( Int idx
, HReg base
) {
241 PPCAMode
* am
= LibVEX_Alloc_inline(sizeof(PPCAMode
));
242 vassert(idx
>= -0x8000 && idx
< 0x8000);
244 am
->Pam
.IR
.base
= base
;
245 am
->Pam
.IR
.index
= idx
;
248 PPCAMode
* PPCAMode_RR ( HReg idx
, HReg base
) {
249 PPCAMode
* am
= LibVEX_Alloc_inline(sizeof(PPCAMode
));
251 am
->Pam
.RR
.base
= base
;
252 am
->Pam
.RR
.index
= idx
;
256 PPCAMode
* dopyPPCAMode ( PPCAMode
* am
) {
259 return PPCAMode_IR( am
->Pam
.IR
.index
, am
->Pam
.IR
.base
);
261 return PPCAMode_RR( am
->Pam
.RR
.index
, am
->Pam
.RR
.base
);
263 vpanic("dopyPPCAMode");
267 void ppPPCAMode ( PPCAMode
* am
) {
270 if (am
->Pam
.IR
.index
== 0)
273 vex_printf("%d(", (Int
)am
->Pam
.IR
.index
);
274 ppHRegPPC(am
->Pam
.IR
.base
);
278 ppHRegPPC(am
->Pam
.RR
.base
);
280 ppHRegPPC(am
->Pam
.RR
.index
);
283 vpanic("ppPPCAMode");
287 static void addRegUsage_PPCAMode ( HRegUsage
* u
, PPCAMode
* am
) {
290 addHRegUse(u
, HRmRead
, am
->Pam
.IR
.base
);
293 addHRegUse(u
, HRmRead
, am
->Pam
.RR
.base
);
294 addHRegUse(u
, HRmRead
, am
->Pam
.RR
.index
);
297 vpanic("addRegUsage_PPCAMode");
301 static void mapRegs_PPCAMode ( HRegRemap
* m
, PPCAMode
* am
) {
304 am
->Pam
.IR
.base
= lookupHRegRemap(m
, am
->Pam
.IR
.base
);
307 am
->Pam
.RR
.base
= lookupHRegRemap(m
, am
->Pam
.RR
.base
);
308 am
->Pam
.RR
.index
= lookupHRegRemap(m
, am
->Pam
.RR
.index
);
311 vpanic("mapRegs_PPCAMode");
315 /* --------- Operand, which can be a reg or a u16/s16. --------- */
317 PPCRH
* PPCRH_Imm ( Bool syned
, UShort imm16
) {
318 PPCRH
* op
= LibVEX_Alloc_inline(sizeof(PPCRH
));
320 op
->Prh
.Imm
.syned
= syned
;
321 op
->Prh
.Imm
.imm16
= imm16
;
322 /* If this is a signed value, ensure it's not -32768, so that we
323 are guaranteed always to be able to negate if needed. */
325 vassert(imm16
!= 0x8000);
326 vassert(syned
== True
|| syned
== False
);
329 PPCRH
* PPCRH_Reg ( HReg reg
) {
330 PPCRH
* op
= LibVEX_Alloc_inline(sizeof(PPCRH
));
332 op
->Prh
.Reg
.reg
= reg
;
336 void ppPPCRH ( PPCRH
* op
) {
339 if (op
->Prh
.Imm
.syned
)
340 vex_printf("%d", (Int
)(Short
)op
->Prh
.Imm
.imm16
);
342 vex_printf("%u", (UInt
)(UShort
)op
->Prh
.Imm
.imm16
);
345 ppHRegPPC(op
->Prh
.Reg
.reg
);
352 /* An PPCRH can only be used in a "read" context (what would it mean
353 to write or modify a literal?) and so we enumerate its registers
355 static void addRegUsage_PPCRH ( HRegUsage
* u
, PPCRH
* op
) {
360 addHRegUse(u
, HRmRead
, op
->Prh
.Reg
.reg
);
363 vpanic("addRegUsage_PPCRH");
367 static void mapRegs_PPCRH ( HRegRemap
* m
, PPCRH
* op
) {
372 op
->Prh
.Reg
.reg
= lookupHRegRemap(m
, op
->Prh
.Reg
.reg
);
375 vpanic("mapRegs_PPCRH");
380 /* --------- Operand, which can be a reg or a u32/64. --------- */
382 PPCRI
* PPCRI_Imm ( ULong imm64
) {
383 PPCRI
* op
= LibVEX_Alloc_inline(sizeof(PPCRI
));
388 PPCRI
* PPCRI_Reg ( HReg reg
) {
389 PPCRI
* op
= LibVEX_Alloc_inline(sizeof(PPCRI
));
395 void ppPPCRI ( PPCRI
* dst
) {
398 vex_printf("0x%llx", dst
->Pri
.Imm
);
401 ppHRegPPC(dst
->Pri
.Reg
);
408 /* An PPCRI can only be used in a "read" context (what would it
409 mean to write or modify a literal?) and so we enumerate its
410 registers accordingly. */
411 static void addRegUsage_PPCRI ( HRegUsage
* u
, PPCRI
* dst
) {
416 addHRegUse(u
, HRmRead
, dst
->Pri
.Reg
);
419 vpanic("addRegUsage_PPCRI");
423 static void mapRegs_PPCRI ( HRegRemap
* m
, PPCRI
* dst
) {
428 dst
->Pri
.Reg
= lookupHRegRemap(m
, dst
->Pri
.Reg
);
431 vpanic("mapRegs_PPCRI");
436 /* --------- Operand, which can be a vector reg or a simm5. --------- */
438 PPCVI5s
* PPCVI5s_Imm ( Char simm5
) {
439 PPCVI5s
* op
= LibVEX_Alloc_inline(sizeof(PPCVI5s
));
441 op
->Pvi
.Imm5s
= simm5
;
442 vassert(simm5
>= -16 && simm5
<= 15);
445 PPCVI5s
* PPCVI5s_Reg ( HReg reg
) {
446 PPCVI5s
* op
= LibVEX_Alloc_inline(sizeof(PPCVI5s
));
449 vassert(hregClass(reg
) == HRcVec128
);
453 void ppPPCVI5s ( PPCVI5s
* src
) {
456 vex_printf("%d", (Int
)src
->Pvi
.Imm5s
);
459 ppHRegPPC(src
->Pvi
.Reg
);
466 /* An PPCVI5s can only be used in a "read" context (what would it
467 mean to write or modify a literal?) and so we enumerate its
468 registers accordingly. */
469 static void addRegUsage_PPCVI5s ( HRegUsage
* u
, PPCVI5s
* dst
) {
474 addHRegUse(u
, HRmRead
, dst
->Pvi
.Reg
);
477 vpanic("addRegUsage_PPCVI5s");
481 static void mapRegs_PPCVI5s ( HRegRemap
* m
, PPCVI5s
* dst
) {
486 dst
->Pvi
.Reg
= lookupHRegRemap(m
, dst
->Pvi
.Reg
);
489 vpanic("mapRegs_PPCVI5s");
494 /* --------- Instructions. --------- */
496 const HChar
* showPPCUnaryOp ( PPCUnaryOp op
) {
498 case Pun_NOT
: return "not";
499 case Pun_NEG
: return "neg";
500 case Pun_CLZ32
: return "cntlzw";
501 case Pun_CLZ64
: return "cntlzd";
502 case Pun_EXTSW
: return "extsw";
503 case Pun_POP32
: return "popcntw";
504 case Pun_POP64
: return "popcntd";
505 default: vpanic("showPPCUnaryOp");
509 const HChar
* showPPCAluOp ( PPCAluOp op
, Bool immR
) {
511 case Palu_ADD
: return immR
? "addi" : "add";
512 case Palu_SUB
: return immR
? "subi" : "sub";
513 case Palu_AND
: return immR
? "andi." : "and";
514 case Palu_OR
: return immR
? "ori" : "or";
515 case Palu_XOR
: return immR
? "xori" : "xor";
516 default: vpanic("showPPCAluOp");
520 const HChar
* showPPCShftOp ( PPCShftOp op
, Bool immR
, Bool sz32
) {
522 case Pshft_SHL
: return sz32
? (immR
? "slwi" : "slw") :
523 (immR
? "sldi" : "sld");
524 case Pshft_SHR
: return sz32
? (immR
? "srwi" : "srw") :
525 (immR
? "srdi" : "srd");
526 case Pshft_SAR
: return sz32
? (immR
? "srawi" : "sraw") :
527 (immR
? "sradi" : "srad");
528 default: vpanic("showPPCShftOp");
532 const HChar
* showPPCFpOp ( PPCFpOp op
) {
534 case Pfp_ADDD
: return "fadd";
535 case Pfp_SUBD
: return "fsub";
536 case Pfp_MULD
: return "fmul";
537 case Pfp_DIVD
: return "fdiv";
538 case Pfp_MADDD
: return "fmadd";
539 case Pfp_MSUBD
: return "fmsub";
540 case Pfp_MADDS
: return "fmadds";
541 case Pfp_MSUBS
: return "fmsubs";
542 case Pfp_ADDS
: return "fadds";
543 case Pfp_SUBS
: return "fsubs";
544 case Pfp_MULS
: return "fmuls";
545 case Pfp_DIVS
: return "fdivs";
546 case Pfp_SQRT
: return "fsqrt";
547 case Pfp_ABS
: return "fabs";
548 case Pfp_NEG
: return "fneg";
549 case Pfp_MOV
: return "fmr";
550 case Pfp_RES
: return "fres";
551 case Pfp_RSQRTE
: return "frsqrte";
552 case Pfp_FRIM
: return "frim";
553 case Pfp_FRIN
: return "frin";
554 case Pfp_FRIP
: return "frip";
555 case Pfp_FRIZ
: return "friz";
556 case Pfp_FPADDQ
: return "xsaddqp";
557 case Pfp_FPSUBQ
: return "xsubqp";
558 case Pfp_FPMULQ
: return "xsmulqp";
559 case Pfp_FPDIVQ
: return "xsdivqp";
560 case Pfp_FPMULADDQ
: return "xsmaddqp";
561 case Pfp_FPMULSUBQ
: return "xsmsubqp";
562 case Pfp_FPNEGMULADDQ
: return "xsnmaddqp";
563 case Pfp_FPNEGMULSUBQ
: return "xsnmsubqp";
564 case Pfp_FPADDQRNDODD
: return "xsaddqpo";
565 case Pfp_FPSUBQRNDODD
: return "xsubqpo";
566 case Pfp_FPMULQRNDODD
: return "xsmulqpo";
567 case Pfp_FPDIVQRNDODD
: return "xsaddqpo";
568 case Pfp_FPMULADDQRNDODD
: return "xsmaddqpo";
569 case Pfp_FPMULSUBQRNDODD
: return "xsmsubqpo";
570 case Pfp_FPNEGMULADDQRNDODD
: return "xsnmaddqpo";
571 case Pfp_FPNEGMULSUBQRNDODD
: return "xsnmsubqpo";
572 case Pfp_FPQTOD
: return "xscvqpdp";
573 case Pfp_FPQTODRNDODD
: return "xscvqpdpo";
574 case Pfp_FPDTOQ
: return "xscvdpqp";
575 case Pfp_IDSTOQ
: return "xscvsdqp";
576 case Pfp_IDUTOQ
: return "xscvudqp";
577 case Pfp_IQSTOQ
: return "xscvsqqp";
578 case Pfp_IQUTOQ
: return "xscvuqqp";
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_DFPTOIQ
: return "dctfixqq";
592 case Pfp_IQUTODFP
: return "dcffixqq";
593 case Pfp_DCTDP
: return "dctdp";
594 case Pfp_DRSP
: return "drsp";
595 case Pfp_DCTFIX
: return "dctfix";
596 case Pfp_DCFFIX
: return "dcffix";
597 case Pfp_DCTQPQ
: return "dctqpq";
598 case Pfp_DCFFIXQ
: return "dcffixq";
599 case Pfp_DQUA
: return "dqua";
600 case Pfp_DQUAQ
: return "dquaq";
601 case Pfp_DXEX
: return "dxex";
602 case Pfp_DXEXQ
: return "dxexq";
603 case Pfp_DIEX
: return "diex";
604 case Pfp_DIEXQ
: return "diexq";
605 case Pfp_RRDTR
: return "rrdtr";
606 default: vpanic("showPPCFpOp");
610 const HChar
* showPPCAvOp ( PPCAvOp op
) {
614 case Pav_MOV
: return "vmr"; /* Mov */
616 case Pav_AND
: return "vand"; /* Bitwise */
617 case Pav_OR
: return "vor";
618 case Pav_XOR
: return "vxor";
619 case Pav_NOT
: return "vnot";
621 case Pav_UNPCKH8S
: return "vupkhsb"; /* Unpack */
622 case Pav_UNPCKH16S
: return "vupkhsh";
623 case Pav_UNPCKL8S
: return "vupklsb";
624 case Pav_UNPCKL16S
: return "vupklsh";
625 case Pav_UNPCKHPIX
: return "vupkhpx";
626 case Pav_UNPCKLPIX
: return "vupklpx";
629 case Pav_ADDU
: return "vaddu_m"; // b,h,w,dw
630 case Pav_QADDU
: return "vaddu_s"; // b,h,w,dw
631 case Pav_QADDS
: return "vadds_s"; // b,h,w,dw
633 case Pav_SUBU
: return "vsubu_m"; // b,h,w,dw
634 case Pav_QSUBU
: return "vsubu_s"; // b,h,w,dw
635 case Pav_QSUBS
: return "vsubs_s"; // b,h,w,dw
637 case Pav_MULU
: return "vmulu"; // w
638 case Pav_OMULU
: return "vmulou"; // b,h,w
639 case Pav_OMULS
: return "vmulos"; // b,h,w
640 case Pav_EMULU
: return "vmuleu"; // b,h,w
641 case Pav_EMULS
: return "vmules"; // b,h,w
643 case Pav_AVGU
: return "vavgu"; // b,h,w
644 case Pav_AVGS
: return "vavgs"; // b,h,w
646 case Pav_MAXU
: return "vmaxu"; // b,h,w
647 case Pav_MAXS
: return "vmaxs"; // b,h,w
649 case Pav_MINU
: return "vminu"; // b,h,w
650 case Pav_MINS
: return "vmins"; // b,h,w
652 /* Compare (always affects CR field 6) */
653 case Pav_CMPEQU
: return "vcmpequ"; // b,h,w
654 case Pav_CMPGTU
: return "vcmpgtu"; // b,h,w
655 case Pav_CMPGTS
: return "vcmpgts"; // b,h,w
658 case Pav_SHL
: return "vsl"; // ' ',b,h,w,dw
659 case Pav_SHR
: return "vsr"; // ' ',b,h,w,dw
660 case Pav_SAR
: return "vsra"; // b,h,w,dw
661 case Pav_ROTL
: return "vrl"; // b,h,w,dw
664 case Pav_PACKUU
: return "vpku_um"; // h,w,dw
665 case Pav_QPACKUU
: return "vpku_us"; // h,w
666 case Pav_QPACKSU
: return "vpks_us"; // h,w
667 case Pav_QPACKSS
: return "vpks_ss"; // h,w
668 case Pav_PACKPXL
: return "vpkpx";
671 case Pav_MRGHI
: return "vmrgh"; // b,h,w
672 case Pav_MRGLO
: return "vmrgl"; // b,h,w
675 case Pav_CATODD
: return "vmrgow"; // w
676 case Pav_CATEVEN
: return "vmrgew"; // w
679 case Pav_SHA256
: return "vshasigmaw"; // w
680 case Pav_SHA512
: return "vshasigmaw"; // dw
683 case Pav_BCDAdd
: return "bcdadd."; // qw
684 case Pav_BCDSub
: return "bcdsub."; // qw
685 case Pav_I128StoBCD128
: return "bcdcfsq."; //qw
686 case Pav_BCD128toI128S
: return "bcdctsq."; //qw
688 /* I128 mult by 10 */
689 case Pav_MulI128by10
: return "vmul10uq"; //qw
690 case Pav_MulI128by10Carry
: return "vmul10cuq"; //qw
691 case Pav_MulI128by10E
: return "vmul10euq"; //qw
692 case Pav_MulI128by10ECarry
: return "vmul10ecuq"; //qw
694 /* F128 to I128 signed */
695 case Pav_F128toI128S
: return "xsrqpi|x"; //qw
697 /* F128 round to F128 */
698 case Pav_ROUNDFPQ
: return "xsrqpxp";
700 /* Polynomial arith */
701 case Pav_POLYMULADD
: return "vpmsum"; // b, h, w, d
704 case Pav_CIPHERV128
: case Pav_CIPHERLV128
:
705 case Pav_NCIPHERV128
: case Pav_NCIPHERLV128
:
706 case Pav_CIPHERSUBV128
: return "v_cipher_"; // qw
709 case Pav_ZEROCNTBYTE
: case Pav_ZEROCNTWORD
:
710 case Pav_ZEROCNTHALF
: case Pav_ZEROCNTDBL
:
711 return "vclz_"; // b, h, w, d
713 /* trailing zero count */
714 case Pav_TRAILINGZEROCNTBYTE
: case Pav_TRAILINGZEROCNTWORD
:
715 case Pav_TRAILINGZEROCNTHALF
: case Pav_TRAILINGZEROCNTDBL
:
716 return "vctz_"; // b, h, w, d
718 /* vector gather (byte-by-byte bit matrix transpose) */
719 case Pav_BITMTXXPOSE
:
722 /* Vector Half-precision format to single precision conversion */
726 /* Vector Single-precision format to Half-precision conversion */
730 /* Vector Half-precision format to Double precision conversion */
734 /* Vector Half-precision format to Double precision conversion */
738 default: vpanic("showPPCAvOp");
742 const HChar
* showPPCAvOpBin128 ( PPCAvOpBin128 op
) {
747 /* Vector Divide Signed Quadword VX-form */
766 default: vpanic("showPPCAvOpBin128");
770 const HChar
* showPPCAvOpTri128 ( PPCAvOpTri128 op
) {
772 /* Vector Quadword VX-form */
774 case Pav_2xMultU64Add128CarryOut
:
777 default: vpanic("showPPCAvOpTri128");
781 const HChar
* showPPCAvFpOp ( PPCAvFpOp op
) {
783 /* Floating Point Binary */
784 case Pavfp_ADDF
: return "vaddfp";
785 case Pavfp_SUBF
: return "vsubfp";
786 case Pavfp_MULF
: return "vmaddfp";
787 case Pavfp_MAXF
: return "vmaxfp";
788 case Pavfp_MINF
: return "vminfp";
789 case Pavfp_CMPEQF
: return "vcmpeqfp";
790 case Pavfp_CMPGTF
: return "vcmpgtfp";
791 case Pavfp_CMPGEF
: return "vcmpgefp";
793 /* Floating Point Unary */
794 case Pavfp_RCPF
: return "vrefp";
795 case Pavfp_RSQRTF
: return "vrsqrtefp";
796 case Pavfp_Log2
: return "vlogefp";
797 case Pavfp_Exp2
: return "vexptefp";
798 case Pavfp_CVTU2F
: return "vcfux";
799 case Pavfp_CVTS2F
: return "vcfsx";
800 case Pavfp_QCVTF2U
: return "vctuxs";
801 case Pavfp_QCVTF2S
: return "vctsxs";
802 case Pavfp_ROUNDM
: return "vrfim";
803 case Pavfp_ROUNDP
: return "vrfip";
804 case Pavfp_ROUNDN
: return "vrfin";
805 case Pavfp_ROUNDZ
: return "vrfiz";
807 default: vpanic("showPPCAvFpOp");
811 const HChar
* showXFormUnary994 ( PPCXFormUnary994 op
) {
813 /* Vector Quadword VX-form */
820 default: vpanic("showXFormUnary994");
824 PPCInstr
* PPCInstr_LI ( HReg dst
, ULong imm64
, Bool mode64
)
826 PPCInstr
* i
= LibVEX_Alloc_inline(sizeof(PPCInstr
));
829 i
->Pin
.LI
.imm64
= imm64
;
831 vassert( (Long
)imm64
== (Long
)(Int
)(UInt
)imm64
);
834 PPCInstr
* PPCInstr_Alu ( PPCAluOp op
, HReg dst
,
835 HReg srcL
, PPCRH
* srcR
) {
836 PPCInstr
* i
= LibVEX_Alloc_inline(sizeof(PPCInstr
));
839 i
->Pin
.Alu
.dst
= dst
;
840 i
->Pin
.Alu
.srcL
= srcL
;
841 i
->Pin
.Alu
.srcR
= srcR
;
844 PPCInstr
* PPCInstr_Shft ( PPCShftOp op
, Bool sz32
,
845 HReg dst
, HReg srcL
, PPCRH
* srcR
) {
846 PPCInstr
* i
= LibVEX_Alloc_inline(sizeof(PPCInstr
));
849 i
->Pin
.Shft
.sz32
= sz32
;
850 i
->Pin
.Shft
.dst
= dst
;
851 i
->Pin
.Shft
.srcL
= srcL
;
852 i
->Pin
.Shft
.srcR
= srcR
;
855 PPCInstr
* PPCInstr_AddSubC ( Bool isAdd
, Bool setC
,
856 HReg dst
, HReg srcL
, HReg srcR
) {
857 PPCInstr
* i
= LibVEX_Alloc_inline(sizeof(PPCInstr
));
858 i
->tag
= Pin_AddSubC
;
859 i
->Pin
.AddSubC
.isAdd
= isAdd
;
860 i
->Pin
.AddSubC
.setC
= setC
;
861 i
->Pin
.AddSubC
.dst
= dst
;
862 i
->Pin
.AddSubC
.srcL
= srcL
;
863 i
->Pin
.AddSubC
.srcR
= srcR
;
866 PPCInstr
* PPCInstr_Cmp ( Bool syned
, Bool sz32
,
867 UInt crfD
, HReg srcL
, PPCRH
* srcR
) {
868 PPCInstr
* i
= LibVEX_Alloc_inline(sizeof(PPCInstr
));
870 i
->Pin
.Cmp
.syned
= syned
;
871 i
->Pin
.Cmp
.sz32
= sz32
;
872 i
->Pin
.Cmp
.crfD
= crfD
;
873 i
->Pin
.Cmp
.srcL
= srcL
;
874 i
->Pin
.Cmp
.srcR
= srcR
;
877 PPCInstr
* PPCInstr_Unary ( PPCUnaryOp op
, HReg dst
, HReg src
) {
878 PPCInstr
* i
= LibVEX_Alloc_inline(sizeof(PPCInstr
));
880 i
->Pin
.Unary
.op
= op
;
881 i
->Pin
.Unary
.dst
= dst
;
882 i
->Pin
.Unary
.src
= src
;
885 PPCInstr
* PPCInstr_MulL ( Bool syned
, Bool hi
, Bool sz32
,
886 HReg dst
, HReg srcL
, HReg srcR
) {
887 PPCInstr
* i
= LibVEX_Alloc_inline(sizeof(PPCInstr
));
889 i
->Pin
.MulL
.syned
= syned
;
891 i
->Pin
.MulL
.sz32
= sz32
;
892 i
->Pin
.MulL
.dst
= dst
;
893 i
->Pin
.MulL
.srcL
= srcL
;
894 i
->Pin
.MulL
.srcR
= srcR
;
895 /* if doing the low word, the signedness is irrelevant, but tie it
897 if (!hi
) vassert(!syned
);
900 PPCInstr
* PPCInstr_Div ( Bool extended
, Bool syned
, Bool sz32
,
901 HReg dst
, HReg srcL
, HReg srcR
) {
902 PPCInstr
* i
= LibVEX_Alloc_inline(sizeof(PPCInstr
));
904 i
->Pin
.Div
.extended
= extended
;
905 i
->Pin
.Div
.syned
= syned
;
906 i
->Pin
.Div
.sz32
= sz32
;
907 i
->Pin
.Div
.dst
= dst
;
908 i
->Pin
.Div
.srcL
= srcL
;
909 i
->Pin
.Div
.srcR
= srcR
;
912 PPCInstr
* PPCInstr_Call ( PPCCondCode cond
,
913 Addr64 target
, UInt argiregs
, RetLoc rloc
) {
915 PPCInstr
* i
= LibVEX_Alloc_inline(sizeof(PPCInstr
));
917 i
->Pin
.Call
.cond
= cond
;
918 i
->Pin
.Call
.target
= target
;
919 i
->Pin
.Call
.argiregs
= argiregs
;
920 i
->Pin
.Call
.rloc
= rloc
;
921 /* Only r3 .. r10 inclusive may be used as arg regs. Hence: */
922 mask
= (1<<3)|(1<<4)|(1<<5)|(1<<6)|(1<<7)|(1<<8)|(1<<9)|(1<<10);
923 vassert(0 == (argiregs
& ~mask
));
924 vassert(is_sane_RetLoc(rloc
));
927 PPCInstr
* PPCInstr_XDirect ( Addr64 dstGA
, PPCAMode
* amCIA
,
928 PPCCondCode cond
, Bool toFastEP
) {
929 PPCInstr
* i
= LibVEX_Alloc_inline(sizeof(PPCInstr
));
930 i
->tag
= Pin_XDirect
;
931 i
->Pin
.XDirect
.dstGA
= dstGA
;
932 i
->Pin
.XDirect
.amCIA
= amCIA
;
933 i
->Pin
.XDirect
.cond
= cond
;
934 i
->Pin
.XDirect
.toFastEP
= toFastEP
;
937 PPCInstr
* PPCInstr_XIndir ( HReg dstGA
, PPCAMode
* amCIA
,
939 PPCInstr
* i
= LibVEX_Alloc_inline(sizeof(PPCInstr
));
941 i
->Pin
.XIndir
.dstGA
= dstGA
;
942 i
->Pin
.XIndir
.amCIA
= amCIA
;
943 i
->Pin
.XIndir
.cond
= cond
;
946 PPCInstr
* PPCInstr_XAssisted ( HReg dstGA
, PPCAMode
* amCIA
,
947 PPCCondCode cond
, IRJumpKind jk
) {
948 PPCInstr
* i
= LibVEX_Alloc_inline(sizeof(PPCInstr
));
949 i
->tag
= Pin_XAssisted
;
950 i
->Pin
.XAssisted
.dstGA
= dstGA
;
951 i
->Pin
.XAssisted
.amCIA
= amCIA
;
952 i
->Pin
.XAssisted
.cond
= cond
;
953 i
->Pin
.XAssisted
.jk
= jk
;
956 PPCInstr
* PPCInstr_CMov ( PPCCondCode cond
,
957 HReg dst
, PPCRI
* src
) {
958 PPCInstr
* i
= LibVEX_Alloc_inline(sizeof(PPCInstr
));
960 i
->Pin
.CMov
.cond
= cond
;
961 i
->Pin
.CMov
.src
= src
;
962 i
->Pin
.CMov
.dst
= dst
;
963 vassert(cond
.test
!= Pct_ALWAYS
);
966 PPCInstr
* PPCInstr_Load ( UChar sz
,
967 HReg dst
, PPCAMode
* src
, Bool mode64
) {
968 PPCInstr
* i
= LibVEX_Alloc_inline(sizeof(PPCInstr
));
971 i
->Pin
.Load
.src
= src
;
972 i
->Pin
.Load
.dst
= dst
;
973 vassert(sz
== 1 || sz
== 2 || sz
== 4 || sz
== 8);
974 if (sz
== 8) vassert(mode64
);
977 PPCInstr
* PPCInstr_LoadL ( UChar sz
,
978 HReg dst
, HReg src
, Bool mode64
)
980 PPCInstr
* i
= LibVEX_Alloc_inline(sizeof(PPCInstr
));
982 i
->Pin
.LoadL
.sz
= sz
;
983 i
->Pin
.LoadL
.src
= src
;
984 i
->Pin
.LoadL
.dst
= dst
;
985 vassert(sz
== 1 || sz
== 2 || sz
== 4 || sz
== 8);
986 if (sz
== 8) vassert(mode64
);
989 PPCInstr
* PPCInstr_Store ( UChar sz
, PPCAMode
* dst
, HReg src
,
991 PPCInstr
* i
= LibVEX_Alloc_inline(sizeof(PPCInstr
));
993 i
->Pin
.Store
.sz
= sz
;
994 i
->Pin
.Store
.src
= src
;
995 i
->Pin
.Store
.dst
= dst
;
996 vassert(sz
== 1 || sz
== 2 || sz
== 4 || sz
== 8);
997 if (sz
== 8) vassert(mode64
);
1000 PPCInstr
* PPCInstr_StoreC ( UChar sz
, HReg dst
, HReg src
, Bool mode64
) {
1001 PPCInstr
* i
= LibVEX_Alloc_inline(sizeof(PPCInstr
));
1002 i
->tag
= Pin_StoreC
;
1003 i
->Pin
.StoreC
.sz
= sz
;
1004 i
->Pin
.StoreC
.src
= src
;
1005 i
->Pin
.StoreC
.dst
= dst
;
1006 vassert(sz
== 1 || sz
== 2 || sz
== 4 || sz
== 8);
1007 if (sz
== 8) vassert(mode64
);
1010 PPCInstr
* PPCInstr_Set ( PPCCondCode cond
, HReg dst
) {
1011 PPCInstr
* i
= LibVEX_Alloc_inline(sizeof(PPCInstr
));
1013 i
->Pin
.Set
.cond
= cond
;
1014 i
->Pin
.Set
.dst
= dst
;
1017 PPCInstr
* PPCInstr_MfCR ( HReg dst
)
1019 PPCInstr
* i
= LibVEX_Alloc_inline(sizeof(PPCInstr
));
1021 i
->Pin
.MfCR
.dst
= dst
;
1024 PPCInstr
* PPCInstr_MFence ( void )
1026 PPCInstr
* i
= LibVEX_Alloc_inline(sizeof(PPCInstr
));
1027 i
->tag
= Pin_MFence
;
1031 PPCInstr
* PPCInstr_FpUnary ( PPCFpOp op
, HReg dst
, HReg src
) {
1032 PPCInstr
* i
= LibVEX_Alloc_inline(sizeof(PPCInstr
));
1033 i
->tag
= Pin_FpUnary
;
1034 i
->Pin
.FpUnary
.op
= op
;
1035 i
->Pin
.FpUnary
.dst
= dst
;
1036 i
->Pin
.FpUnary
.src
= src
;
1039 PPCInstr
* PPCInstr_FpBinary ( PPCFpOp op
, HReg dst
,
1040 HReg srcL
, HReg srcR
) {
1041 PPCInstr
* i
= LibVEX_Alloc_inline(sizeof(PPCInstr
));
1042 i
->tag
= Pin_FpBinary
;
1043 i
->Pin
.FpBinary
.op
= op
;
1044 i
->Pin
.FpBinary
.dst
= dst
;
1045 i
->Pin
.FpBinary
.srcL
= srcL
;
1046 i
->Pin
.FpBinary
.srcR
= srcR
;
1049 PPCInstr
* PPCInstr_Fp128Unary(PPCFpOp op
, HReg dst
, HReg src
) {
1050 PPCInstr
* i
= LibVEX_Alloc_inline( sizeof(PPCInstr
) );
1051 i
->tag
= Pin_Fp128Unary
;
1052 i
->Pin
.Fp128Unary
.op
= op
;
1053 i
->Pin
.Fp128Unary
.dst
= dst
;
1054 i
->Pin
.Fp128Unary
.src
= src
;
1057 PPCInstr
* PPCInstr_Fp128Binary(PPCFpOp op
, HReg dst
, HReg srcL
, HReg srcR
) {
1058 PPCInstr
* i
= LibVEX_Alloc_inline( sizeof(PPCInstr
) );
1059 i
->tag
= Pin_Fp128Binary
;
1060 i
->Pin
.Fp128Binary
.op
= op
;
1061 i
->Pin
.Fp128Binary
.dst
= dst
;
1062 i
->Pin
.Fp128Binary
.srcL
= srcL
;
1063 i
->Pin
.Fp128Binary
.srcR
= srcR
;
1066 PPCInstr
* PPCInstr_Fp128Ternary(PPCFpOp op
, HReg dst
, HReg srcL
, HReg srcR
) {
1067 PPCInstr
* i
= LibVEX_Alloc_inline( sizeof(PPCInstr
) );
1068 i
->tag
= Pin_Fp128Ternary
;
1069 i
->Pin
.Fp128Ternary
.op
= op
;
1070 i
->Pin
.Fp128Ternary
.dst
= dst
;
1071 i
->Pin
.Fp128Ternary
.srcL
= srcL
;
1072 i
->Pin
.Fp128Ternary
.srcR
= srcR
;
1075 PPCInstr
* PPCInstr_FpMulAcc ( PPCFpOp op
, HReg dst
, HReg srcML
,
1076 HReg srcMR
, HReg srcAcc
)
1078 PPCInstr
* i
= LibVEX_Alloc_inline(sizeof(PPCInstr
));
1079 i
->tag
= Pin_FpMulAcc
;
1080 i
->Pin
.FpMulAcc
.op
= op
;
1081 i
->Pin
.FpMulAcc
.dst
= dst
;
1082 i
->Pin
.FpMulAcc
.srcML
= srcML
;
1083 i
->Pin
.FpMulAcc
.srcMR
= srcMR
;
1084 i
->Pin
.FpMulAcc
.srcAcc
= srcAcc
;
1087 PPCInstr
* PPCInstr_FpLdSt ( Bool isLoad
, UChar sz
,
1088 HReg reg
, PPCAMode
* addr
) {
1089 PPCInstr
* i
= LibVEX_Alloc_inline(sizeof(PPCInstr
));
1090 i
->tag
= Pin_FpLdSt
;
1091 i
->Pin
.FpLdSt
.isLoad
= isLoad
;
1092 i
->Pin
.FpLdSt
.sz
= sz
;
1093 i
->Pin
.FpLdSt
.reg
= reg
;
1094 i
->Pin
.FpLdSt
.addr
= addr
;
1095 vassert(sz
== 4 || sz
== 8);
1098 PPCInstr
* PPCInstr_FpSTFIW ( HReg addr
, HReg data
)
1100 PPCInstr
* i
= LibVEX_Alloc_inline(sizeof(PPCInstr
));
1101 i
->tag
= Pin_FpSTFIW
;
1102 i
->Pin
.FpSTFIW
.addr
= addr
;
1103 i
->Pin
.FpSTFIW
.data
= data
;
1106 PPCInstr
* PPCInstr_FpRSP ( HReg dst
, HReg src
) {
1107 PPCInstr
* i
= LibVEX_Alloc_inline(sizeof(PPCInstr
));
1109 i
->Pin
.FpRSP
.dst
= dst
;
1110 i
->Pin
.FpRSP
.src
= src
;
1113 PPCInstr
* PPCInstr_Dfp64Unary(PPCFpOp op
, HReg dst
, HReg src
) {
1114 PPCInstr
* i
= LibVEX_Alloc_inline( sizeof(PPCInstr
) );
1115 i
->tag
= Pin_Dfp64Unary
;
1116 i
->Pin
.Dfp64Unary
.op
= op
;
1117 i
->Pin
.Dfp64Unary
.dst
= dst
;
1118 i
->Pin
.Dfp64Unary
.src
= src
;
1121 PPCInstr
* PPCInstr_Dfp64Binary(PPCFpOp op
, HReg dst
, HReg srcL
, HReg srcR
) {
1122 PPCInstr
* i
= LibVEX_Alloc_inline( sizeof(PPCInstr
) );
1123 i
->tag
= Pin_Dfp64Binary
;
1124 i
->Pin
.Dfp64Binary
.op
= op
;
1125 i
->Pin
.Dfp64Binary
.dst
= dst
;
1126 i
->Pin
.Dfp64Binary
.srcL
= srcL
;
1127 i
->Pin
.Dfp64Binary
.srcR
= srcR
;
1130 PPCInstr
* PPCInstr_DfpShift ( PPCFpOp op
, HReg dst
, HReg src
, PPCRI
* shift
) {
1131 PPCInstr
* i
= LibVEX_Alloc_inline(sizeof(PPCInstr
));
1132 i
->tag
= Pin_DfpShift
;
1133 i
->Pin
.DfpShift
.op
= op
;
1134 i
->Pin
.DfpShift
.shift
= shift
;
1135 i
->Pin
.DfpShift
.src
= src
;
1136 i
->Pin
.DfpShift
.dst
= dst
;
1139 PPCInstr
* PPCInstr_Dfp128Unary(PPCFpOp op
, HReg dst_hi
, HReg dst_lo
,
1140 HReg src_hi
, HReg src_lo
) {
1141 PPCInstr
* i
= LibVEX_Alloc_inline( sizeof(PPCInstr
) );
1142 i
->tag
= Pin_Dfp128Unary
;
1143 i
->Pin
.Dfp128Unary
.op
= op
;
1144 i
->Pin
.Dfp128Unary
.dst_hi
= dst_hi
;
1145 i
->Pin
.Dfp128Unary
.dst_lo
= dst_lo
;
1146 i
->Pin
.Dfp128Unary
.src_hi
= src_hi
;
1147 i
->Pin
.Dfp128Unary
.src_lo
= src_lo
;
1150 PPCInstr
* PPCInstr_Dfp128Binary(PPCFpOp op
, HReg dst_hi
, HReg dst_lo
,
1151 HReg srcR_hi
, HReg srcR_lo
) {
1152 /* dst is used to pass the srcL argument and return the result */
1153 PPCInstr
* i
= LibVEX_Alloc_inline( sizeof(PPCInstr
) );
1154 i
->tag
= Pin_Dfp128Binary
;
1155 i
->Pin
.Dfp128Binary
.op
= op
;
1156 i
->Pin
.Dfp128Binary
.dst_hi
= dst_hi
;
1157 i
->Pin
.Dfp128Binary
.dst_lo
= dst_lo
;
1158 i
->Pin
.Dfp128Binary
.srcR_hi
= srcR_hi
;
1159 i
->Pin
.Dfp128Binary
.srcR_lo
= srcR_lo
;
1162 PPCInstr
* PPCInstr_DfpShift128 ( PPCFpOp op
, HReg dst_hi
, HReg dst_lo
,
1163 HReg src_hi
, HReg src_lo
,
1165 PPCInstr
* i
= LibVEX_Alloc_inline(sizeof(PPCInstr
));
1166 i
->tag
= Pin_DfpShift128
;
1167 i
->Pin
.DfpShift128
.op
= op
;
1168 i
->Pin
.DfpShift128
.shift
= shift
;
1169 i
->Pin
.DfpShift128
.src_hi
= src_hi
;
1170 i
->Pin
.DfpShift128
.src_lo
= src_lo
;
1171 i
->Pin
.DfpShift128
.dst_hi
= dst_hi
;
1172 i
->Pin
.DfpShift128
.dst_lo
= dst_lo
;
1175 PPCInstr
* PPCInstr_DfpRound ( HReg dst
, HReg src
, PPCRI
* r_rmc
) {
1176 PPCInstr
* i
= LibVEX_Alloc_inline(sizeof(PPCInstr
));
1177 i
->tag
= Pin_DfpRound
;
1178 i
->Pin
.DfpRound
.dst
= dst
;
1179 i
->Pin
.DfpRound
.src
= src
;
1180 i
->Pin
.DfpRound
.r_rmc
= r_rmc
;
1183 PPCInstr
* PPCInstr_DfpRound128 ( HReg dst_hi
, HReg dst_lo
, HReg src_hi
,
1184 HReg src_lo
, PPCRI
* r_rmc
) {
1185 PPCInstr
* i
= LibVEX_Alloc_inline(sizeof(PPCInstr
));
1186 i
->tag
= Pin_DfpRound128
;
1187 i
->Pin
.DfpRound128
.dst_hi
= dst_hi
;
1188 i
->Pin
.DfpRound128
.dst_lo
= dst_lo
;
1189 i
->Pin
.DfpRound128
.src_hi
= src_hi
;
1190 i
->Pin
.DfpRound128
.src_lo
= src_lo
;
1191 i
->Pin
.DfpRound128
.r_rmc
= r_rmc
;
1194 PPCInstr
* PPCInstr_DfpQuantize ( PPCFpOp op
, HReg dst
, HReg srcL
, HReg srcR
,
1196 PPCInstr
* i
= LibVEX_Alloc_inline(sizeof(PPCInstr
));
1197 i
->tag
= Pin_DfpQuantize
;
1198 i
->Pin
.DfpQuantize
.op
= op
;
1199 i
->Pin
.DfpQuantize
.dst
= dst
;
1200 i
->Pin
.DfpQuantize
.srcL
= srcL
;
1201 i
->Pin
.DfpQuantize
.srcR
= srcR
;
1202 i
->Pin
.DfpQuantize
.rmc
= rmc
;
1205 PPCInstr
* PPCInstr_DfpQuantize128 ( PPCFpOp op
, HReg dst_hi
, HReg dst_lo
,
1206 HReg src_hi
, HReg src_lo
, PPCRI
* rmc
) {
1207 /* dst is used to pass left operand in and return result */
1208 PPCInstr
* i
= LibVEX_Alloc_inline(sizeof(PPCInstr
));
1209 i
->tag
= Pin_DfpQuantize128
;
1210 i
->Pin
.DfpQuantize128
.op
= op
;
1211 i
->Pin
.DfpQuantize128
.dst_hi
= dst_hi
;
1212 i
->Pin
.DfpQuantize128
.dst_lo
= dst_lo
;
1213 i
->Pin
.DfpQuantize128
.src_hi
= src_hi
;
1214 i
->Pin
.DfpQuantize128
.src_lo
= src_lo
;
1215 i
->Pin
.DfpQuantize128
.rmc
= rmc
;
1218 PPCInstr
* PPCInstr_DfpD128toD64 ( PPCFpOp op
, HReg dst
,
1219 HReg src_hi
, HReg src_lo
) {
1220 PPCInstr
* i
= LibVEX_Alloc_inline(sizeof(PPCInstr
));
1221 i
->tag
= Pin_DfpD128toD64
;
1222 i
->Pin
.DfpD128toD64
.op
= op
;
1223 i
->Pin
.DfpD128toD64
.src_hi
= src_hi
;
1224 i
->Pin
.DfpD128toD64
.src_lo
= src_lo
;
1225 i
->Pin
.DfpD128toD64
.dst
= dst
;
1228 PPCInstr
* PPCInstr_DfpI64StoD128 ( PPCFpOp op
, HReg dst_hi
,
1229 HReg dst_lo
, HReg src
) {
1230 PPCInstr
* i
= LibVEX_Alloc_inline(sizeof(PPCInstr
));
1231 i
->tag
= Pin_DfpI64StoD128
;
1232 i
->Pin
.DfpI64StoD128
.op
= op
;
1233 i
->Pin
.DfpI64StoD128
.src
= src
;
1234 i
->Pin
.DfpI64StoD128
.dst_hi
= dst_hi
;
1235 i
->Pin
.DfpI64StoD128
.dst_lo
= dst_lo
;
1238 PPCInstr
* PPCInstr_ExtractExpD128 ( PPCFpOp op
, HReg dst
,
1239 HReg src_hi
, HReg src_lo
) {
1240 /* dst is used to pass the srcL argument */
1241 PPCInstr
* i
= LibVEX_Alloc_inline(sizeof(PPCInstr
));
1242 i
->tag
= Pin_ExtractExpD128
;
1243 i
->Pin
.ExtractExpD128
.op
= op
;
1244 i
->Pin
.ExtractExpD128
.dst
= dst
;
1245 i
->Pin
.ExtractExpD128
.src_hi
= src_hi
;
1246 i
->Pin
.ExtractExpD128
.src_lo
= src_lo
;
1249 PPCInstr
* PPCInstr_InsertExpD128 ( PPCFpOp op
, HReg dst_hi
, HReg dst_lo
,
1250 HReg srcL
, HReg srcR_hi
, HReg srcR_lo
) {
1251 /* dst is used to pass the srcL argument */
1252 PPCInstr
* i
= LibVEX_Alloc_inline(sizeof(PPCInstr
));
1253 i
->tag
= Pin_InsertExpD128
;
1254 i
->Pin
.InsertExpD128
.op
= op
;
1255 i
->Pin
.InsertExpD128
.dst_hi
= dst_hi
;
1256 i
->Pin
.InsertExpD128
.dst_lo
= dst_lo
;
1257 i
->Pin
.InsertExpD128
.srcL
= srcL
;
1258 i
->Pin
.InsertExpD128
.srcR_hi
= srcR_hi
;
1259 i
->Pin
.InsertExpD128
.srcR_lo
= srcR_lo
;
1262 PPCInstr
* PPCInstr_Dfp64Cmp (/* UInt crfD,*/ HReg dst
, HReg srcL
, HReg srcR
) {
1263 PPCInstr
* i
= LibVEX_Alloc_inline(sizeof(PPCInstr
));
1264 i
->tag
= Pin_Dfp64Cmp
;
1265 i
->Pin
.Dfp64Cmp
.dst
= dst
;
1266 i
->Pin
.Dfp64Cmp
.srcL
= srcL
;
1267 i
->Pin
.Dfp64Cmp
.srcR
= srcR
;
1270 PPCInstr
* PPCInstr_Dfp128Cmp ( HReg dst
, HReg srcL_hi
, HReg srcL_lo
,
1271 HReg srcR_hi
, HReg srcR_lo
) {
1272 PPCInstr
* i
= LibVEX_Alloc_inline(sizeof(PPCInstr
));
1273 i
->tag
= Pin_Dfp128Cmp
;
1274 i
->Pin
.Dfp128Cmp
.dst
= dst
;
1275 i
->Pin
.Dfp128Cmp
.srcL_hi
= srcL_hi
;
1276 i
->Pin
.Dfp128Cmp
.srcL_lo
= srcL_lo
;
1277 i
->Pin
.Dfp128Cmp
.srcR_hi
= srcR_hi
;
1278 i
->Pin
.Dfp128Cmp
.srcR_lo
= srcR_lo
;
1281 PPCInstr
* PPCInstr_EvCheck ( PPCAMode
* amCounter
,
1282 PPCAMode
* amFailAddr
) {
1283 PPCInstr
* i
= LibVEX_Alloc_inline(sizeof(PPCInstr
));
1284 i
->tag
= Pin_EvCheck
;
1285 i
->Pin
.EvCheck
.amCounter
= amCounter
;
1286 i
->Pin
.EvCheck
.amFailAddr
= amFailAddr
;
1289 PPCInstr
* PPCInstr_ProfInc ( void ) {
1290 PPCInstr
* i
= LibVEX_Alloc_inline(sizeof(PPCInstr
));
1291 i
->tag
= Pin_ProfInc
;
1296 Valid combo | fromI | int32 | syned | flt64 |
1297 --------------------------------------------
1299 --------------------------------------------
1300 F64->I64U | n n n y |
1301 --------------------------------------------
1303 --------------------------------------------
1304 F64->I64S | n n y y |
1305 --------------------------------------------
1307 --------------------------------------------
1308 F64->I32U | n y n y |
1309 --------------------------------------------
1311 --------------------------------------------
1312 F64->I32S | n y y y |
1313 --------------------------------------------
1314 I64U->F32 | y n n n |
1315 --------------------------------------------
1316 I64U->F64 | y n n y |
1317 --------------------------------------------
1319 --------------------------------------------
1320 I64S->F64 | y n y y |
1321 --------------------------------------------
1323 --------------------------------------------
1325 --------------------------------------------
1327 --------------------------------------------
1329 --------------------------------------------
1331 PPCInstr
* PPCInstr_FpCftI ( Bool fromI
, Bool int32
, Bool syned
,
1332 Bool flt64
, HReg dst
, HReg src
) {
1333 Bool tmp
= fromI
| int32
| syned
| flt64
;
1334 vassert(tmp
== True
|| tmp
== False
); // iow, no high bits set
1335 UShort conversion
= 0;
1336 conversion
= (fromI
<< 3) | (int32
<< 2) | (syned
<< 1) | flt64
;
1337 switch (conversion
) {
1338 // Supported conversion operations
1339 case 1: case 3: case 5: case 7:
1340 case 8: case 9: case 11:
1343 vpanic("PPCInstr_FpCftI(ppc_host)");
1345 PPCInstr
* i
= LibVEX_Alloc_inline(sizeof(PPCInstr
));
1346 i
->tag
= Pin_FpCftI
;
1347 i
->Pin
.FpCftI
.fromI
= fromI
;
1348 i
->Pin
.FpCftI
.int32
= int32
;
1349 i
->Pin
.FpCftI
.syned
= syned
;
1350 i
->Pin
.FpCftI
.flt64
= flt64
;
1351 i
->Pin
.FpCftI
.dst
= dst
;
1352 i
->Pin
.FpCftI
.src
= src
;
1355 PPCInstr
* PPCInstr_FpCMov ( PPCCondCode cond
, HReg dst
, HReg src
) {
1356 PPCInstr
* i
= LibVEX_Alloc_inline(sizeof(PPCInstr
));
1357 i
->tag
= Pin_FpCMov
;
1358 i
->Pin
.FpCMov
.cond
= cond
;
1359 i
->Pin
.FpCMov
.dst
= dst
;
1360 i
->Pin
.FpCMov
.src
= src
;
1361 vassert(cond
.test
!= Pct_ALWAYS
);
1364 PPCInstr
* PPCInstr_FpLdFPSCR ( HReg src
, Bool dfp_rm
) {
1365 PPCInstr
* i
= LibVEX_Alloc_inline(sizeof(PPCInstr
));
1366 i
->tag
= Pin_FpLdFPSCR
;
1367 i
->Pin
.FpLdFPSCR
.src
= src
;
1368 i
->Pin
.FpLdFPSCR
.dfp_rm
= dfp_rm
? 1 : 0;
1371 PPCInstr
* PPCInstr_FpCmp ( HReg dst
, HReg srcL
, HReg srcR
) {
1372 PPCInstr
* i
= LibVEX_Alloc_inline(sizeof(PPCInstr
));
1374 i
->Pin
.FpCmp
.dst
= dst
;
1375 i
->Pin
.FpCmp
.srcL
= srcL
;
1376 i
->Pin
.FpCmp
.srcR
= srcR
;
1380 /* Read/Write Link Register */
1381 PPCInstr
* PPCInstr_RdWrLR ( Bool wrLR
, HReg gpr
) {
1382 PPCInstr
* i
= LibVEX_Alloc_inline(sizeof(PPCInstr
));
1383 i
->tag
= Pin_RdWrLR
;
1384 i
->Pin
.RdWrLR
.wrLR
= wrLR
;
1385 i
->Pin
.RdWrLR
.gpr
= gpr
;
1390 PPCInstr
* PPCInstr_AvLdSt ( Bool isLoad
, UChar sz
,
1391 HReg reg
, PPCAMode
* addr
) {
1392 PPCInstr
* i
= LibVEX_Alloc_inline(sizeof(PPCInstr
));
1393 i
->tag
= Pin_AvLdSt
;
1394 i
->Pin
.AvLdSt
.isLoad
= isLoad
;
1395 i
->Pin
.AvLdSt
.sz
= sz
;
1396 i
->Pin
.AvLdSt
.reg
= reg
;
1397 i
->Pin
.AvLdSt
.addr
= addr
;
1400 PPCInstr
* PPCInstr_AvUnary ( PPCAvOp op
, HReg dst
, HReg src
) {
1401 PPCInstr
* i
= LibVEX_Alloc_inline(sizeof(PPCInstr
));
1402 i
->tag
= Pin_AvUnary
;
1403 i
->Pin
.AvUnary
.op
= op
;
1404 i
->Pin
.AvUnary
.dst
= dst
;
1405 i
->Pin
.AvUnary
.src
= src
;
1408 PPCInstr
* PPCInstr_AvBinary ( PPCAvOp op
, HReg dst
,
1409 HReg srcL
, HReg srcR
) {
1410 PPCInstr
* i
= LibVEX_Alloc_inline(sizeof(PPCInstr
));
1411 i
->tag
= Pin_AvBinary
;
1412 i
->Pin
.AvBinary
.op
= op
;
1413 i
->Pin
.AvBinary
.dst
= dst
;
1414 i
->Pin
.AvBinary
.srcL
= srcL
;
1415 i
->Pin
.AvBinary
.srcR
= srcR
;
1418 PPCInstr
* PPCInstr_AvBinaryInt ( PPCAvOp op
, HReg dst
,
1419 HReg src
, PPCRI
* val
) {
1420 PPCInstr
* i
= LibVEX_Alloc_inline(sizeof(PPCInstr
));
1421 i
->tag
= Pin_AvBinaryInt
;
1422 i
->Pin
.AvBinaryInt
.op
= op
;
1423 i
->Pin
.AvBinaryInt
.dst
= dst
;
1424 i
->Pin
.AvBinaryInt
.src
= src
;
1425 i
->Pin
.AvBinaryInt
.val
= val
;
1428 PPCInstr
* PPCInstr_AvBinaryInt128 ( PPCAvOpBin128 op
, HReg dst
,
1429 HReg src1
, HReg src2
) {
1430 PPCInstr
* i
= LibVEX_Alloc_inline(sizeof(PPCInstr
));
1431 i
->tag
= Pin_AvBinaryInt128
;
1432 i
->Pin
.AvBinaryInt128
.op
= op
;
1433 i
->Pin
.AvBinaryInt128
.dst
= dst
;
1434 i
->Pin
.AvBinaryInt128
.src1
= src1
;
1435 i
->Pin
.AvBinaryInt128
.src2
= src2
;
1438 PPCInstr
* PPCInstr_AvTernaryInt128 ( PPCAvOpTri128 op
, HReg dst
,
1439 HReg src1
, HReg src2
, HReg src3
) {
1440 PPCInstr
* i
= LibVEX_Alloc_inline(sizeof(PPCInstr
));
1441 i
->tag
= Pin_AvTernaryInt128
;
1442 i
->Pin
.AvTernaryInt128
.op
= op
;
1443 i
->Pin
.AvTernaryInt128
.dst
= dst
;
1444 i
->Pin
.AvTernaryInt128
.src1
= src1
;
1445 i
->Pin
.AvTernaryInt128
.src2
= src2
;
1446 i
->Pin
.AvTernaryInt128
.src3
= src3
;
1449 PPCInstr
* PPCInstr_AvBin8x16 ( PPCAvOp op
, HReg dst
,
1450 HReg srcL
, HReg srcR
) {
1451 PPCInstr
* i
= LibVEX_Alloc_inline(sizeof(PPCInstr
));
1452 i
->tag
= Pin_AvBin8x16
;
1453 i
->Pin
.AvBin8x16
.op
= op
;
1454 i
->Pin
.AvBin8x16
.dst
= dst
;
1455 i
->Pin
.AvBin8x16
.srcL
= srcL
;
1456 i
->Pin
.AvBin8x16
.srcR
= srcR
;
1459 PPCInstr
* PPCInstr_AvBin16x8 ( PPCAvOp op
, HReg dst
,
1460 HReg srcL
, HReg srcR
) {
1461 PPCInstr
* i
= LibVEX_Alloc_inline(sizeof(PPCInstr
));
1462 i
->tag
= Pin_AvBin16x8
;
1463 i
->Pin
.AvBin16x8
.op
= op
;
1464 i
->Pin
.AvBin16x8
.dst
= dst
;
1465 i
->Pin
.AvBin16x8
.srcL
= srcL
;
1466 i
->Pin
.AvBin16x8
.srcR
= srcR
;
1469 PPCInstr
* PPCInstr_AvBin32x4 ( PPCAvOp op
, HReg dst
,
1470 HReg srcL
, HReg srcR
) {
1471 PPCInstr
* i
= LibVEX_Alloc_inline(sizeof(PPCInstr
));
1472 i
->tag
= Pin_AvBin32x4
;
1473 i
->Pin
.AvBin32x4
.op
= op
;
1474 i
->Pin
.AvBin32x4
.dst
= dst
;
1475 i
->Pin
.AvBin32x4
.srcL
= srcL
;
1476 i
->Pin
.AvBin32x4
.srcR
= srcR
;
1479 PPCInstr
* PPCInstr_AvBin64x2 ( PPCAvOp op
, HReg dst
,
1480 HReg srcL
, HReg srcR
) {
1481 PPCInstr
* i
= LibVEX_Alloc_inline(sizeof(PPCInstr
));
1482 i
->tag
= Pin_AvBin64x2
;
1483 i
->Pin
.AvBin64x2
.op
= op
;
1484 i
->Pin
.AvBin64x2
.dst
= dst
;
1485 i
->Pin
.AvBin64x2
.srcL
= srcL
;
1486 i
->Pin
.AvBin64x2
.srcR
= srcR
;
1490 PPCInstr
* PPCInstr_AvBin32Fx4 ( PPCAvFpOp op
, HReg dst
,
1491 HReg srcL
, HReg srcR
) {
1492 PPCInstr
* i
= LibVEX_Alloc_inline(sizeof(PPCInstr
));
1493 i
->tag
= Pin_AvBin32Fx4
;
1494 i
->Pin
.AvBin32Fx4
.op
= op
;
1495 i
->Pin
.AvBin32Fx4
.dst
= dst
;
1496 i
->Pin
.AvBin32Fx4
.srcL
= srcL
;
1497 i
->Pin
.AvBin32Fx4
.srcR
= srcR
;
1500 PPCInstr
* PPCInstr_AvUn32Fx4 ( PPCAvFpOp op
, HReg dst
, HReg src
) {
1501 PPCInstr
* i
= LibVEX_Alloc_inline(sizeof(PPCInstr
));
1502 i
->tag
= Pin_AvUn32Fx4
;
1503 i
->Pin
.AvUn32Fx4
.op
= op
;
1504 i
->Pin
.AvUn32Fx4
.dst
= dst
;
1505 i
->Pin
.AvUn32Fx4
.src
= src
;
1508 PPCInstr
* PPCInstr_AvPerm ( HReg dst
, HReg srcL
, HReg srcR
, HReg ctl
) {
1509 PPCInstr
* i
= LibVEX_Alloc_inline(sizeof(PPCInstr
));
1510 i
->tag
= Pin_AvPerm
;
1511 i
->Pin
.AvPerm
.dst
= dst
;
1512 i
->Pin
.AvPerm
.srcL
= srcL
;
1513 i
->Pin
.AvPerm
.srcR
= srcR
;
1514 i
->Pin
.AvPerm
.ctl
= ctl
;
1518 PPCInstr
* PPCInstr_AvSel ( HReg ctl
, HReg dst
, HReg srcL
, HReg srcR
) {
1519 PPCInstr
* i
= LibVEX_Alloc_inline(sizeof(PPCInstr
));
1521 i
->Pin
.AvSel
.ctl
= ctl
;
1522 i
->Pin
.AvSel
.dst
= dst
;
1523 i
->Pin
.AvSel
.srcL
= srcL
;
1524 i
->Pin
.AvSel
.srcR
= srcR
;
1527 PPCInstr
* PPCInstr_AvSh ( Bool shLeft
, HReg dst
, PPCAMode
* addr
) {
1528 PPCInstr
* i
= LibVEX_Alloc_inline(sizeof(PPCInstr
));
1530 i
->Pin
.AvSh
.shLeft
= shLeft
;
1531 i
->Pin
.AvSh
.dst
= dst
;
1532 i
->Pin
.AvSh
.addr
= addr
;
1535 PPCInstr
* PPCInstr_AvShlDbl ( UChar shift
, HReg dst
,
1536 HReg srcL
, HReg srcR
) {
1537 PPCInstr
* i
= LibVEX_Alloc_inline(sizeof(PPCInstr
));
1538 i
->tag
= Pin_AvShlDbl
;
1539 i
->Pin
.AvShlDbl
.shift
= shift
;
1540 i
->Pin
.AvShlDbl
.dst
= dst
;
1541 i
->Pin
.AvShlDbl
.srcL
= srcL
;
1542 i
->Pin
.AvShlDbl
.srcR
= srcR
;
1545 PPCInstr
* PPCInstr_AvSplat ( UChar sz
, HReg dst
, PPCVI5s
* src
) {
1546 PPCInstr
* i
= LibVEX_Alloc_inline(sizeof(PPCInstr
));
1547 i
->tag
= Pin_AvSplat
;
1548 i
->Pin
.AvSplat
.sz
= sz
;
1549 i
->Pin
.AvSplat
.dst
= dst
;
1550 i
->Pin
.AvSplat
.src
= src
;
1553 PPCInstr
* PPCInstr_AvCMov ( PPCCondCode cond
, HReg dst
, HReg src
) {
1554 PPCInstr
* i
= LibVEX_Alloc_inline(sizeof(PPCInstr
));
1555 i
->tag
= Pin_AvCMov
;
1556 i
->Pin
.AvCMov
.cond
= cond
;
1557 i
->Pin
.AvCMov
.dst
= dst
;
1558 i
->Pin
.AvCMov
.src
= src
;
1559 vassert(cond
.test
!= Pct_ALWAYS
);
1562 PPCInstr
* PPCInstr_AvLdVSCR ( HReg src
) {
1563 PPCInstr
* i
= LibVEX_Alloc_inline(sizeof(PPCInstr
));
1564 i
->tag
= Pin_AvLdVSCR
;
1565 i
->Pin
.AvLdVSCR
.src
= src
;
1568 PPCInstr
* PPCInstr_AvCipherV128Unary ( PPCAvOp op
, HReg dst
, HReg src
) {
1569 PPCInstr
* i
= LibVEX_Alloc_inline(sizeof(PPCInstr
));
1570 i
->tag
= Pin_AvCipherV128Unary
;
1571 i
->Pin
.AvCipherV128Unary
.op
= op
;
1572 i
->Pin
.AvCipherV128Unary
.dst
= dst
;
1573 i
->Pin
.AvCipherV128Unary
.src
= src
;
1576 PPCInstr
* PPCInstr_AvCipherV128Binary ( PPCAvOp op
, HReg dst
,
1577 HReg srcL
, HReg srcR
) {
1578 PPCInstr
* i
= LibVEX_Alloc_inline(sizeof(PPCInstr
));
1579 i
->tag
= Pin_AvCipherV128Binary
;
1580 i
->Pin
.AvCipherV128Binary
.op
= op
;
1581 i
->Pin
.AvCipherV128Binary
.dst
= dst
;
1582 i
->Pin
.AvCipherV128Binary
.srcL
= srcL
;
1583 i
->Pin
.AvCipherV128Binary
.srcR
= srcR
;
1586 PPCInstr
* PPCInstr_AvHashV128Binary ( PPCAvOp op
, HReg dst
,
1587 HReg src
, PPCRI
* s_field
) {
1588 PPCInstr
* i
= LibVEX_Alloc_inline(sizeof(PPCInstr
));
1589 i
->tag
= Pin_AvHashV128Binary
;
1590 i
->Pin
.AvHashV128Binary
.op
= op
;
1591 i
->Pin
.AvHashV128Binary
.dst
= dst
;
1592 i
->Pin
.AvHashV128Binary
.src
= src
;
1593 i
->Pin
.AvHashV128Binary
.s_field
= s_field
;
1596 PPCInstr
* PPCInstr_AvBCDV128Binary ( PPCAvOp op
, HReg dst
,
1597 HReg src1
, HReg src2
) {
1598 PPCInstr
* i
= LibVEX_Alloc_inline(sizeof(PPCInstr
));
1599 i
->tag
= Pin_AvBCDV128Binary
;
1600 i
->Pin
.AvBCDV128Binary
.op
= op
;
1601 i
->Pin
.AvBCDV128Binary
.dst
= dst
;
1602 i
->Pin
.AvBCDV128Binary
.src1
= src1
;
1603 i
->Pin
.AvBCDV128Binary
.src2
= src2
;
1606 PPCInstr
* PPCInstr_XFormUnary994 ( PPCXFormUnary994 op
, HReg reg0
, HReg reg1
,
1608 /* This is used to issue istructions with opc1=63, opc2=994. The specific
1609 instruction is given in bits[11:15], the VRA field, of the instruction.
1610 Currently only used for dcffixqq and dctfixqq instructions. */
1611 PPCInstr
* i
= LibVEX_Alloc_inline(sizeof(PPCInstr
));
1612 i
->tag
= Pin_XFormUnary994
;
1613 i
->Pin
.XFormUnary994
.op
= op
;
1614 i
->Pin
.XFormUnary994
.reg0
= reg0
;
1615 i
->Pin
.XFormUnary994
.reg1
= reg1
;
1616 i
->Pin
.XFormUnary994
.reg2
= reg2
;
1620 /* Pretty Print instructions */
1621 static void ppLoadImm ( HReg dst
, ULong imm
, Bool mode64
) {
1622 vex_printf("li_word ");
1625 vex_printf(",0x%08x", (UInt
)imm
);
1627 vex_printf(",0x%016llx", imm
);
1631 static void ppMovReg ( HReg dst
, HReg src
) {
1632 if (!sameHReg(dst
, src
)) {
1640 void ppPPCInstr ( const PPCInstr
* i
, Bool mode64
)
1644 ppLoadImm(i
->Pin
.LI
.dst
, i
->Pin
.LI
.imm64
, mode64
);
1647 HReg r_srcL
= i
->Pin
.Alu
.srcL
;
1648 PPCRH
* rh_srcR
= i
->Pin
.Alu
.srcR
;
1649 /* special-case "mr" */
1650 if (i
->Pin
.Alu
.op
== Palu_OR
&& // or Rd,Rs,Rs == mr Rd,Rs
1651 rh_srcR
->tag
== Prh_Reg
&&
1652 sameHReg(rh_srcR
->Prh
.Reg
.reg
, r_srcL
)) {
1654 ppHRegPPC(i
->Pin
.Alu
.dst
);
1659 /* special-case "li" */
1660 if (i
->Pin
.Alu
.op
== Palu_ADD
&& // addi Rd,0,imm == li Rd,imm
1661 rh_srcR
->tag
== Prh_Imm
&&
1662 hregEncoding(r_srcL
) == 0) {
1664 ppHRegPPC(i
->Pin
.Alu
.dst
);
1670 vex_printf("%s ", showPPCAluOp(i
->Pin
.Alu
.op
,
1671 toBool(rh_srcR
->tag
== Prh_Imm
)));
1672 ppHRegPPC(i
->Pin
.Alu
.dst
);
1680 HReg r_srcL
= i
->Pin
.Shft
.srcL
;
1681 PPCRH
* rh_srcR
= i
->Pin
.Shft
.srcR
;
1682 vex_printf("%s ", showPPCShftOp(i
->Pin
.Shft
.op
,
1683 toBool(rh_srcR
->tag
== Prh_Imm
),
1685 ppHRegPPC(i
->Pin
.Shft
.dst
);
1694 i
->Pin
.AddSubC
.isAdd
? "add" : "sub",
1695 i
->Pin
.AddSubC
.setC
? "c" : "e");
1696 ppHRegPPC(i
->Pin
.AddSubC
.dst
);
1698 ppHRegPPC(i
->Pin
.AddSubC
.srcL
);
1700 ppHRegPPC(i
->Pin
.AddSubC
.srcR
);
1703 vex_printf("%s%c%s %%cr%u,",
1704 i
->Pin
.Cmp
.syned
? "cmp" : "cmpl",
1705 i
->Pin
.Cmp
.sz32
? 'w' : 'd',
1706 i
->Pin
.Cmp
.srcR
->tag
== Prh_Imm
? "i" : "",
1708 ppHRegPPC(i
->Pin
.Cmp
.srcL
);
1710 ppPPCRH(i
->Pin
.Cmp
.srcR
);
1713 vex_printf("%s ", showPPCUnaryOp(i
->Pin
.Unary
.op
));
1714 ppHRegPPC(i
->Pin
.Unary
.dst
);
1716 ppHRegPPC(i
->Pin
.Unary
.src
);
1719 vex_printf("mul%c%c%s ",
1720 i
->Pin
.MulL
.hi
? 'h' : 'l',
1721 i
->Pin
.MulL
.sz32
? 'w' : 'd',
1722 i
->Pin
.MulL
.hi
? (i
->Pin
.MulL
.syned
? "s" : "u") : "");
1723 ppHRegPPC(i
->Pin
.MulL
.dst
);
1725 ppHRegPPC(i
->Pin
.MulL
.srcL
);
1727 ppHRegPPC(i
->Pin
.MulL
.srcR
);
1730 vex_printf("div%c%s%s ",
1731 i
->Pin
.Div
.sz32
? 'w' : 'd',
1732 i
->Pin
.Div
.extended
? "e" : "",
1733 i
->Pin
.Div
.syned
? "" : "u");
1734 ppHRegPPC(i
->Pin
.Div
.dst
);
1736 ppHRegPPC(i
->Pin
.Div
.srcL
);
1738 ppHRegPPC(i
->Pin
.Div
.srcR
);
1742 vex_printf("call: ");
1743 if (i
->Pin
.Call
.cond
.test
!= Pct_ALWAYS
) {
1744 vex_printf("if (%s) ", showPPCCondCode(i
->Pin
.Call
.cond
));
1747 ppLoadImm(hregPPC_GPR10(mode64
), i
->Pin
.Call
.target
, mode64
);
1748 vex_printf(" ; mtctr r10 ; bctrl [");
1749 for (n
= 0; n
< 32; n
++) {
1750 if (i
->Pin
.Call
.argiregs
& (1<<n
)) {
1751 vex_printf("r%d", n
);
1752 if ((i
->Pin
.Call
.argiregs
>> n
) > 1)
1757 ppRetLoc(i
->Pin
.Call
.rloc
);
1762 vex_printf("(xDirect) ");
1763 vex_printf("if (%s) { ",
1764 showPPCCondCode(i
->Pin
.XDirect
.cond
));
1766 vex_printf("imm64 r30,0x%llx; ", i
->Pin
.XDirect
.dstGA
);
1767 vex_printf("std r30,");
1769 vex_printf("imm32 r30,0x%llx; ", i
->Pin
.XDirect
.dstGA
);
1770 vex_printf("stw r30,");
1772 ppPPCAMode(i
->Pin
.XDirect
.amCIA
);
1775 vex_printf("imm64-fixed5 r30,$disp_cp_chain_me_to_%sEP; ",
1776 i
->Pin
.XDirect
.toFastEP
? "fast" : "slow");
1778 vex_printf("imm32-fixed2 r30,$disp_cp_chain_me_to_%sEP; ",
1779 i
->Pin
.XDirect
.toFastEP
? "fast" : "slow");
1781 vex_printf("mtctr r30; bctrl }");
1784 vex_printf("(xIndir) ");
1785 vex_printf("if (%s) { ",
1786 showPPCCondCode(i
->Pin
.XIndir
.cond
));
1787 vex_printf("%s ", mode64
? "std" : "stw");
1788 ppHRegPPC(i
->Pin
.XIndir
.dstGA
);
1790 ppPPCAMode(i
->Pin
.XIndir
.amCIA
);
1792 vex_printf("imm%s r30,$disp_cp_xindir; ", mode64
? "64" : "32");
1793 vex_printf("mtctr r30; bctr }");
1796 vex_printf("(xAssisted) ");
1797 vex_printf("if (%s) { ",
1798 showPPCCondCode(i
->Pin
.XAssisted
.cond
));
1799 vex_printf("%s ", mode64
? "std" : "stw");
1800 ppHRegPPC(i
->Pin
.XAssisted
.dstGA
);
1802 ppPPCAMode(i
->Pin
.XAssisted
.amCIA
);
1804 vex_printf("li r31,$IRJumpKind_to_TRCVAL(%d); ",
1805 (Int
)i
->Pin
.XAssisted
.jk
);
1806 vex_printf("imm%s r30,$disp_cp_xindir; ", mode64
? "64" : "32");
1807 vex_printf("mtctr r30; bctr }");
1810 vex_printf("cmov (%s) ", showPPCCondCode(i
->Pin
.CMov
.cond
));
1811 ppHRegPPC(i
->Pin
.CMov
.dst
);
1813 ppPPCRI(i
->Pin
.CMov
.src
);
1815 if (i
->Pin
.CMov
.cond
.test
!= Pct_ALWAYS
) {
1816 vex_printf("if (%s) ", showPPCCondCode(i
->Pin
.CMov
.cond
));
1819 if (i
->Pin
.CMov
.src
->tag
== Pri_Imm
) {
1820 ppLoadImm(i
->Pin
.CMov
.dst
, i
->Pin
.CMov
.src
->Pri
.Imm
, mode64
);
1822 ppMovReg(i
->Pin
.CMov
.dst
, i
->Pin
.CMov
.src
->Pri
.Reg
);
1827 Bool idxd
= toBool(i
->Pin
.Load
.src
->tag
== Pam_RR
);
1828 UChar sz
= i
->Pin
.Load
.sz
;
1829 HChar c_sz
= sz
==1 ? 'b' : sz
==2 ? 'h' : sz
==4 ? 'w' : 'd';
1830 vex_printf("l%c%s%s ", c_sz
, sz
==8 ? "" : "z", idxd
? "x" : "" );
1831 ppHRegPPC(i
->Pin
.Load
.dst
);
1833 ppPPCAMode(i
->Pin
.Load
.src
);
1837 UChar sz
= i
->Pin
.LoadL
.sz
;
1838 HChar c_sz
= sz
==1 ? 'b' : sz
==2 ? 'h' : sz
==4 ? 'w' : 'd';
1839 vex_printf("l%carx ", c_sz
);
1840 ppHRegPPC(i
->Pin
.LoadL
.dst
);
1841 vex_printf(",%%r0,");
1842 ppHRegPPC(i
->Pin
.LoadL
.src
);
1846 UChar sz
= i
->Pin
.Store
.sz
;
1847 Bool idxd
= toBool(i
->Pin
.Store
.dst
->tag
== Pam_RR
);
1848 HChar c_sz
= sz
==1 ? 'b' : sz
==2 ? 'h' : sz
==4 ? 'w' : /*8*/ 'd';
1849 vex_printf("st%c%s ", c_sz
, idxd
? "x" : "" );
1850 ppHRegPPC(i
->Pin
.Store
.src
);
1852 ppPPCAMode(i
->Pin
.Store
.dst
);
1856 UChar sz
= i
->Pin
.StoreC
.sz
;
1857 HChar c_sz
= sz
==1 ? 'b' : sz
==2 ? 'h' : sz
==4 ? 'w' : 'd';
1858 vex_printf("st%ccx. ", c_sz
);
1859 ppHRegPPC(i
->Pin
.StoreC
.src
);
1860 vex_printf(",%%r0,");
1861 ppHRegPPC(i
->Pin
.StoreC
.dst
);
1865 PPCCondCode cc
= i
->Pin
.Set
.cond
;
1866 vex_printf("set (%s),", showPPCCondCode(cc
));
1867 ppHRegPPC(i
->Pin
.Set
.dst
);
1868 if (cc
.test
== Pct_ALWAYS
) {
1869 vex_printf(": { li ");
1870 ppHRegPPC(i
->Pin
.Set
.dst
);
1873 vex_printf(": { mfcr r0 ; rlwinm ");
1874 ppHRegPPC(i
->Pin
.Set
.dst
);
1875 vex_printf(",r0,%u,31,31", cc
.flag
+1);
1876 if (cc
.test
== Pct_FALSE
) {
1877 vex_printf("; xori ");
1878 ppHRegPPC(i
->Pin
.Set
.dst
);
1880 ppHRegPPC(i
->Pin
.Set
.dst
);
1888 vex_printf("mfcr ");
1889 ppHRegPPC(i
->Pin
.MfCR
.dst
);
1892 vex_printf("mfence (=sync)");
1896 vex_printf("%s ", showPPCFpOp(i
->Pin
.FpUnary
.op
));
1897 ppHRegPPC(i
->Pin
.FpUnary
.dst
);
1899 ppHRegPPC(i
->Pin
.FpUnary
.src
);
1902 vex_printf("%s ", showPPCFpOp(i
->Pin
.FpBinary
.op
));
1903 ppHRegPPC(i
->Pin
.FpBinary
.dst
);
1905 ppHRegPPC(i
->Pin
.FpBinary
.srcL
);
1907 ppHRegPPC(i
->Pin
.FpBinary
.srcR
);
1909 case Pin_Fp128Unary
:
1910 vex_printf("%s ", showPPCFpOp(i
->Pin
.Fp128Unary
.op
));
1911 ppHRegPPC(i
->Pin
.Fp128Unary
.dst
);
1913 ppHRegPPC(i
->Pin
.Fp128Unary
.src
);
1915 case Pin_Fp128Binary
:
1916 vex_printf("%s ", showPPCFpOp(i
->Pin
.Fp128Binary
.op
));
1917 ppHRegPPC(i
->Pin
.Fp128Binary
.dst
);
1919 ppHRegPPC(i
->Pin
.Fp128Binary
.srcL
);
1921 ppHRegPPC(i
->Pin
.Fp128Binary
.srcR
);
1923 case Pin_Fp128Ternary
:
1924 vex_printf("%s ", showPPCFpOp(i
->Pin
.Fp128Ternary
.op
));
1925 ppHRegPPC(i
->Pin
.Fp128Ternary
.dst
);
1927 ppHRegPPC(i
->Pin
.Fp128Ternary
.srcL
);
1929 ppHRegPPC(i
->Pin
.Fp128Ternary
.srcR
);
1932 vex_printf("%s ", showPPCFpOp(i
->Pin
.FpMulAcc
.op
));
1933 ppHRegPPC(i
->Pin
.FpMulAcc
.dst
);
1935 ppHRegPPC(i
->Pin
.FpMulAcc
.srcML
);
1937 ppHRegPPC(i
->Pin
.FpMulAcc
.srcMR
);
1939 ppHRegPPC(i
->Pin
.FpMulAcc
.srcAcc
);
1942 UChar sz
= i
->Pin
.FpLdSt
.sz
;
1943 Bool idxd
= toBool(i
->Pin
.FpLdSt
.addr
->tag
== Pam_RR
);
1944 if (i
->Pin
.FpLdSt
.isLoad
) {
1945 vex_printf("lf%c%s ",
1946 (sz
==4 ? 's' : 'd'),
1948 ppHRegPPC(i
->Pin
.FpLdSt
.reg
);
1950 ppPPCAMode(i
->Pin
.FpLdSt
.addr
);
1952 vex_printf("stf%c%s ",
1953 (sz
==4 ? 's' : 'd'),
1955 ppHRegPPC(i
->Pin
.FpLdSt
.reg
);
1957 ppPPCAMode(i
->Pin
.FpLdSt
.addr
);
1962 vex_printf("stfiwz ");
1963 ppHRegPPC(i
->Pin
.FpSTFIW
.data
);
1965 ppHRegPPC(i
->Pin
.FpSTFIW
.addr
);
1969 vex_printf("frsp ");
1970 ppHRegPPC(i
->Pin
.FpRSP
.dst
);
1972 ppHRegPPC(i
->Pin
.FpRSP
.src
);
1975 const HChar
* str
= "fc?????";
1976 /* Note that "fcfids" is missing from below. That instruction would
1977 * satisfy the predicate:
1978 * (i->Pin.FpCftI.fromI == True && i->Pin.FpCftI.int32 == False)
1979 * which would go into a final "else" clause to make this if-else
1980 * block balanced. But we're able to implement fcfids by leveraging
1981 * the fcfid implementation, so it wasn't necessary to include it here.
1983 if (i
->Pin
.FpCftI
.fromI
== False
&& i
->Pin
.FpCftI
.int32
== False
)
1984 if (i
->Pin
.FpCftI
.syned
== True
)
1988 else if (i
->Pin
.FpCftI
.fromI
== False
&& i
->Pin
.FpCftI
.int32
== True
)
1989 if (i
->Pin
.FpCftI
.syned
== True
)
1993 else if (i
->Pin
.FpCftI
.fromI
== True
&& i
->Pin
.FpCftI
.int32
== False
) {
1994 if (i
->Pin
.FpCftI
.syned
== True
) {
1997 if (i
->Pin
.FpCftI
.flt64
== True
)
2003 vex_printf("%s ", str
);
2004 ppHRegPPC(i
->Pin
.FpCftI
.dst
);
2006 ppHRegPPC(i
->Pin
.FpCftI
.src
);
2010 vex_printf("fpcmov (%s) ", showPPCCondCode(i
->Pin
.FpCMov
.cond
));
2011 ppHRegPPC(i
->Pin
.FpCMov
.dst
);
2013 ppHRegPPC(i
->Pin
.FpCMov
.src
);
2015 vex_printf("if (fr_dst != fr_src) { ");
2016 if (i
->Pin
.FpCMov
.cond
.test
!= Pct_ALWAYS
) {
2017 vex_printf("if (%s) { ", showPPCCondCode(i
->Pin
.FpCMov
.cond
));
2020 ppHRegPPC(i
->Pin
.FpCMov
.dst
);
2022 ppHRegPPC(i
->Pin
.FpCMov
.src
);
2023 if (i
->Pin
.FpCMov
.cond
.test
!= Pct_ALWAYS
)
2028 vex_printf("mtfsf 0xFF,");
2029 ppHRegPPC(i
->Pin
.FpLdFPSCR
.src
);
2030 vex_printf(",0, %s", i
->Pin
.FpLdFPSCR
.dfp_rm
? "1" : "0");
2033 vex_printf("fcmpo %%cr1,");
2034 ppHRegPPC(i
->Pin
.FpCmp
.srcL
);
2036 ppHRegPPC(i
->Pin
.FpCmp
.srcR
);
2037 vex_printf("; mfcr ");
2038 ppHRegPPC(i
->Pin
.FpCmp
.dst
);
2039 vex_printf("; rlwinm ");
2040 ppHRegPPC(i
->Pin
.FpCmp
.dst
);
2042 ppHRegPPC(i
->Pin
.FpCmp
.dst
);
2043 vex_printf(",8,28,31");
2047 vex_printf("%s ", i
->Pin
.RdWrLR
.wrLR
? "mtlr" : "mflr");
2048 ppHRegPPC(i
->Pin
.RdWrLR
.gpr
);
2052 UChar sz
= i
->Pin
.AvLdSt
.sz
;
2053 const HChar
* str_size
;
2054 if (i
->Pin
.AvLdSt
.addr
->tag
== Pam_IR
) {
2055 ppLoadImm(hregPPC_GPR30(mode64
),
2056 i
->Pin
.AvLdSt
.addr
->Pam
.IR
.index
, mode64
);
2059 str_size
= sz
==1 ? "eb" : sz
==2 ? "eh" : sz
==4 ? "ew" : "";
2060 if (i
->Pin
.AvLdSt
.isLoad
)
2061 vex_printf("lv%sx ", str_size
);
2063 vex_printf("stv%sx ", str_size
);
2064 ppHRegPPC(i
->Pin
.AvLdSt
.reg
);
2066 if (i
->Pin
.AvLdSt
.addr
->tag
== Pam_IR
)
2067 vex_printf("%%r30");
2069 ppHRegPPC(i
->Pin
.AvLdSt
.addr
->Pam
.RR
.index
);
2071 ppHRegPPC(i
->Pin
.AvLdSt
.addr
->Pam
.RR
.base
);
2075 vex_printf("%s ", showPPCAvOp(i
->Pin
.AvUnary
.op
));
2076 ppHRegPPC(i
->Pin
.AvUnary
.dst
);
2078 ppHRegPPC(i
->Pin
.AvUnary
.src
);
2081 vex_printf("%s ", showPPCAvOp(i
->Pin
.AvBinary
.op
));
2082 ppHRegPPC(i
->Pin
.AvBinary
.dst
);
2084 ppHRegPPC(i
->Pin
.AvBinary
.srcL
);
2086 ppHRegPPC(i
->Pin
.AvBinary
.srcR
);
2088 case Pin_AvBinaryInt
:
2089 vex_printf("%s ", showPPCAvOp(i
->Pin
.AvBinaryInt
.op
));
2090 ppHRegPPC(i
->Pin
.AvBinaryInt
.dst
);
2092 ppHRegPPC(i
->Pin
.AvBinaryInt
.src
);
2094 ppPPCRI(i
->Pin
.AvBinaryInt
.val
);
2096 case Pin_AvBinaryInt128
:
2097 vex_printf("%s ", showPPCAvOpBin128(i
->Pin
.AvBinaryInt128
.op
));
2098 ppHRegPPC(i
->Pin
.AvBinaryInt128
.dst
);
2100 ppHRegPPC(i
->Pin
.AvBinaryInt128
.src1
);
2102 ppHRegPPC(i
->Pin
.AvBinaryInt128
.src2
);
2104 case Pin_AvTernaryInt128
:
2105 vex_printf("%s ", showPPCAvOpTri128(i
->Pin
.AvTernaryInt128
.op
));
2106 ppHRegPPC(i
->Pin
.AvTernaryInt128
.dst
);
2108 ppHRegPPC(i
->Pin
.AvTernaryInt128
.src1
);
2110 ppHRegPPC(i
->Pin
.AvTernaryInt128
.src2
);
2112 ppHRegPPC(i
->Pin
.AvTernaryInt128
.src3
);
2115 vex_printf("%s(b) ", showPPCAvOp(i
->Pin
.AvBin8x16
.op
));
2116 ppHRegPPC(i
->Pin
.AvBin8x16
.dst
);
2118 ppHRegPPC(i
->Pin
.AvBin8x16
.srcL
);
2120 ppHRegPPC(i
->Pin
.AvBin8x16
.srcR
);
2123 vex_printf("%s(h) ", showPPCAvOp(i
->Pin
.AvBin16x8
.op
));
2124 ppHRegPPC(i
->Pin
.AvBin16x8
.dst
);
2126 ppHRegPPC(i
->Pin
.AvBin16x8
.srcL
);
2128 ppHRegPPC(i
->Pin
.AvBin16x8
.srcR
);
2131 vex_printf("%s(w) ", showPPCAvOp(i
->Pin
.AvBin32x4
.op
));
2132 ppHRegPPC(i
->Pin
.AvBin32x4
.dst
);
2134 ppHRegPPC(i
->Pin
.AvBin32x4
.srcL
);
2136 ppHRegPPC(i
->Pin
.AvBin32x4
.srcR
);
2139 vex_printf("%s(w) ", showPPCAvOp(i
->Pin
.AvBin64x2
.op
));
2140 ppHRegPPC(i
->Pin
.AvBin64x2
.dst
);
2142 ppHRegPPC(i
->Pin
.AvBin64x2
.srcL
);
2144 ppHRegPPC(i
->Pin
.AvBin64x2
.srcR
);
2146 case Pin_AvBin32Fx4
:
2147 vex_printf("%s ", showPPCAvFpOp(i
->Pin
.AvBin32Fx4
.op
));
2148 ppHRegPPC(i
->Pin
.AvBin32Fx4
.dst
);
2150 ppHRegPPC(i
->Pin
.AvBin32Fx4
.srcL
);
2152 ppHRegPPC(i
->Pin
.AvBin32Fx4
.srcR
);
2155 vex_printf("%s ", showPPCAvFpOp(i
->Pin
.AvUn32Fx4
.op
));
2156 ppHRegPPC(i
->Pin
.AvUn32Fx4
.dst
);
2158 ppHRegPPC(i
->Pin
.AvUn32Fx4
.src
);
2161 vex_printf("vperm ");
2162 ppHRegPPC(i
->Pin
.AvPerm
.dst
);
2164 ppHRegPPC(i
->Pin
.AvPerm
.srcL
);
2166 ppHRegPPC(i
->Pin
.AvPerm
.srcR
);
2168 ppHRegPPC(i
->Pin
.AvPerm
.ctl
);
2172 vex_printf("vsel ");
2173 ppHRegPPC(i
->Pin
.AvSel
.dst
);
2175 ppHRegPPC(i
->Pin
.AvSel
.srcL
);
2177 ppHRegPPC(i
->Pin
.AvSel
.srcR
);
2179 ppHRegPPC(i
->Pin
.AvSel
.ctl
);
2183 /* This only generates the following instructions with RA
2184 * register number set to 0.
2186 if (i
->Pin
.AvSh
.addr
->tag
== Pam_IR
) {
2187 ppLoadImm(hregPPC_GPR30(mode64
),
2188 i
->Pin
.AvSh
.addr
->Pam
.IR
.index
, mode64
);
2192 if (i
->Pin
.AvSh
.shLeft
)
2193 vex_printf("lvsl ");
2195 vex_printf("lvsr ");
2197 ppHRegPPC(i
->Pin
.AvSh
.dst
);
2198 if (i
->Pin
.AvSh
.addr
->tag
== Pam_IR
)
2199 vex_printf("%%r30");
2201 ppHRegPPC(i
->Pin
.AvSh
.addr
->Pam
.RR
.index
);
2203 ppHRegPPC(i
->Pin
.AvSh
.addr
->Pam
.RR
.base
);
2207 vex_printf("vsldoi ");
2208 ppHRegPPC(i
->Pin
.AvShlDbl
.dst
);
2210 ppHRegPPC(i
->Pin
.AvShlDbl
.srcL
);
2212 ppHRegPPC(i
->Pin
.AvShlDbl
.srcR
);
2213 vex_printf(",%d", i
->Pin
.AvShlDbl
.shift
);
2217 UChar sz
= i
->Pin
.AvSplat
.sz
;
2218 HChar ch_sz
= toUChar( (sz
== 8) ? 'b' : (sz
== 16) ? 'h' : 'w' );
2219 vex_printf("vsplt%s%c ",
2220 i
->Pin
.AvSplat
.src
->tag
== Pvi_Imm
? "is" : "", ch_sz
);
2221 ppHRegPPC(i
->Pin
.AvSplat
.dst
);
2223 ppPPCVI5s(i
->Pin
.AvSplat
.src
);
2224 if (i
->Pin
.AvSplat
.src
->tag
== Pvi_Reg
)
2225 vex_printf(", %d", (128/sz
)-1); /* louis lane */
2230 vex_printf("avcmov (%s) ", showPPCCondCode(i
->Pin
.AvCMov
.cond
));
2231 ppHRegPPC(i
->Pin
.AvCMov
.dst
);
2233 ppHRegPPC(i
->Pin
.AvCMov
.src
);
2235 vex_printf("if (v_dst != v_src) { ");
2236 if (i
->Pin
.AvCMov
.cond
.test
!= Pct_ALWAYS
) {
2237 vex_printf("if (%s) { ", showPPCCondCode(i
->Pin
.AvCMov
.cond
));
2240 ppHRegPPC(i
->Pin
.AvCMov
.dst
);
2242 ppHRegPPC(i
->Pin
.AvCMov
.src
);
2243 if (i
->Pin
.FpCMov
.cond
.test
!= Pct_ALWAYS
)
2249 vex_printf("mtvscr ");
2250 ppHRegPPC(i
->Pin
.AvLdVSCR
.src
);
2253 case Pin_AvCipherV128Unary
:
2254 vex_printf("%s(w) ", showPPCAvOp(i
->Pin
.AvCipherV128Unary
.op
));
2255 ppHRegPPC(i
->Pin
.AvCipherV128Unary
.dst
);
2257 ppHRegPPC(i
->Pin
.AvCipherV128Unary
.src
);
2260 case Pin_AvCipherV128Binary
:
2261 vex_printf("%s(w) ", showPPCAvOp(i
->Pin
.AvCipherV128Binary
.op
));
2262 ppHRegPPC(i
->Pin
.AvCipherV128Binary
.dst
);
2264 ppHRegPPC(i
->Pin
.AvCipherV128Binary
.srcL
);
2266 ppHRegPPC(i
->Pin
.AvCipherV128Binary
.srcR
);
2269 case Pin_AvHashV128Binary
:
2270 vex_printf("%s(w) ", showPPCAvOp(i
->Pin
.AvHashV128Binary
.op
));
2271 ppHRegPPC(i
->Pin
.AvHashV128Binary
.dst
);
2273 ppHRegPPC(i
->Pin
.AvHashV128Binary
.src
);
2275 ppPPCRI(i
->Pin
.AvHashV128Binary
.s_field
);
2278 case Pin_AvBCDV128Binary
:
2279 vex_printf("%s(w) ", showPPCAvOp(i
->Pin
.AvBCDV128Binary
.op
));
2280 ppHRegPPC(i
->Pin
.AvBCDV128Binary
.dst
);
2282 ppHRegPPC(i
->Pin
.AvBCDV128Binary
.src1
);
2284 ppHRegPPC(i
->Pin
.AvBCDV128Binary
.src2
);
2287 case Pin_Dfp64Unary
:
2288 vex_printf("%s ", showPPCFpOp(i
->Pin
.Dfp64Unary
.op
));
2289 ppHRegPPC(i
->Pin
.Dfp64Unary
.dst
);
2291 ppHRegPPC(i
->Pin
.Dfp64Unary
.src
);
2294 case Pin_Dfp64Binary
:
2295 vex_printf("%s ", showPPCFpOp(i
->Pin
.Dfp64Binary
.op
));
2296 ppHRegPPC(i
->Pin
.Dfp64Binary
.dst
);
2298 ppHRegPPC(i
->Pin
.Dfp64Binary
.srcL
);
2300 ppHRegPPC(i
->Pin
.Dfp64Binary
.srcR
);
2304 vex_printf("%s ", showPPCFpOp(i
->Pin
.DfpShift
.op
));
2305 ppHRegPPC(i
->Pin
.DfpShift
.dst
);
2307 ppHRegPPC(i
->Pin
.DfpShift
.src
);
2309 ppPPCRI(i
->Pin
.DfpShift
.shift
);
2312 case Pin_Dfp128Unary
:
2313 vex_printf("%s ", showPPCFpOp(i
->Pin
.Dfp128Unary
.op
));
2314 ppHRegPPC(i
->Pin
.Dfp128Unary
.dst_hi
);
2316 ppHRegPPC(i
->Pin
.Dfp128Unary
.src_hi
);
2319 case Pin_Dfp128Binary
:
2320 vex_printf("%s ", showPPCFpOp(i
->Pin
.Dfp128Binary
.op
));
2321 ppHRegPPC(i
->Pin
.Dfp128Binary
.dst_hi
);
2323 ppHRegPPC(i
->Pin
.Dfp128Binary
.srcR_hi
);
2326 case Pin_DfpShift128
:
2327 vex_printf("%s ", showPPCFpOp(i
->Pin
.DfpShift128
.op
));
2328 ppHRegPPC(i
->Pin
.DfpShift128
.dst_hi
);
2330 ppHRegPPC(i
->Pin
.DfpShift128
.src_hi
);
2332 ppPPCRI(i
->Pin
.DfpShift128
.shift
);
2336 vex_printf("drintx ");
2337 ppHRegPPC(i
->Pin
.DfpRound
.dst
);
2339 ppHRegPPC(i
->Pin
.DfpRound
.src
);
2341 ppPPCRI(i
->Pin
.DfpRound
.r_rmc
); /* R in bit 3 and RMC in bits 2:0 */
2344 case Pin_DfpRound128
:
2345 vex_printf("drintxq ");
2346 ppHRegPPC(i
->Pin
.DfpRound128
.dst_hi
);
2348 ppHRegPPC(i
->Pin
.DfpRound128
.src_hi
);
2350 ppPPCRI(i
->Pin
.DfpRound128
.r_rmc
); /* R in bit 3 and RMC in bits 2:0 */
2353 case Pin_DfpQuantize
:
2354 vex_printf("%s ", showPPCFpOp(i
->Pin
.DfpQuantize
.op
));
2355 ppHRegPPC(i
->Pin
.DfpQuantize
.dst
);
2357 ppHRegPPC(i
->Pin
.DfpQuantize
.srcL
);
2359 ppHRegPPC(i
->Pin
.DfpQuantize
.srcR
);
2361 ppPPCRI(i
->Pin
.DfpQuantize
.rmc
);
2364 case Pin_DfpQuantize128
:
2365 /* Dst is used to pass in left source and return result */
2366 vex_printf("dquaq ");
2367 ppHRegPPC(i
->Pin
.DfpQuantize128
.dst_hi
);
2369 ppHRegPPC(i
->Pin
.DfpQuantize128
.dst_hi
);
2371 ppHRegPPC(i
->Pin
.DfpQuantize128
.src_hi
);
2373 ppPPCRI(i
->Pin
.DfpQuantize128
.rmc
);
2376 case Pin_DfpD128toD64
:
2377 vex_printf("%s ", showPPCFpOp(i
->Pin
.DfpD128toD64
.op
));
2378 ppHRegPPC(i
->Pin
.DfpD128toD64
.dst
);
2380 ppHRegPPC(i
->Pin
.DfpD128toD64
.src_hi
);
2384 case Pin_DfpI64StoD128
:
2385 vex_printf("%s ", showPPCFpOp(i
->Pin
.DfpI64StoD128
.op
));
2386 ppHRegPPC(i
->Pin
.DfpI64StoD128
.dst_hi
);
2388 ppHRegPPC(i
->Pin
.DfpI64StoD128
.src
);
2391 case Pin_ExtractExpD128
:
2392 vex_printf("dxexq ");
2393 ppHRegPPC(i
->Pin
.ExtractExpD128
.dst
);
2395 ppHRegPPC(i
->Pin
.ExtractExpD128
.src_hi
);
2397 case Pin_InsertExpD128
:
2398 vex_printf("diexq ");
2399 ppHRegPPC(i
->Pin
.InsertExpD128
.dst_hi
);
2401 ppHRegPPC(i
->Pin
.InsertExpD128
.srcL
);
2403 ppHRegPPC(i
->Pin
.InsertExpD128
.srcR_hi
);
2406 vex_printf("dcmpo %%cr1,");
2407 ppHRegPPC(i
->Pin
.Dfp64Cmp
.srcL
);
2409 ppHRegPPC(i
->Pin
.Dfp64Cmp
.srcR
);
2410 vex_printf("; mfcr ");
2411 ppHRegPPC(i
->Pin
.Dfp64Cmp
.dst
);
2412 vex_printf("; rlwinm ");
2413 ppHRegPPC(i
->Pin
.Dfp64Cmp
.dst
);
2415 ppHRegPPC(i
->Pin
.Dfp64Cmp
.dst
);
2416 vex_printf(",8,28,31");
2419 vex_printf("dcmpoq %%cr1,");
2420 ppHRegPPC(i
->Pin
.Dfp128Cmp
.srcL_hi
);
2422 ppHRegPPC(i
->Pin
.Dfp128Cmp
.srcR_hi
);
2423 vex_printf("; mfcr ");
2424 ppHRegPPC(i
->Pin
.Dfp128Cmp
.dst
);
2425 vex_printf("; rlwinm ");
2426 ppHRegPPC(i
->Pin
.Dfp128Cmp
.dst
);
2428 ppHRegPPC(i
->Pin
.Dfp128Cmp
.dst
);
2429 vex_printf(",8,28,31");
2432 case Pin_XFormUnary994
:
2433 if (i
->Pin
.XFormUnary994
.op
== Px_DFPTOIQS
) {
2434 vex_printf("%s(w) ", showXFormUnary994(i
->Pin
.XFormUnary994
.op
));
2435 ppHRegPPC(i
->Pin
.XFormUnary994
.reg0
);
2437 ppHRegPPC(i
->Pin
.XFormUnary994
.reg1
);
2439 vex_printf("%s(w) ", showXFormUnary994(i
->Pin
.XFormUnary994
.op
));
2440 ppHRegPPC(i
->Pin
.XFormUnary994
.reg0
);
2442 ppHRegPPC(i
->Pin
.XFormUnary994
.reg2
);
2447 /* Note that the counter dec is 32 bit even in 64-bit mode. */
2448 vex_printf("(evCheck) ");
2449 vex_printf("lwz r30,");
2450 ppPPCAMode(i
->Pin
.EvCheck
.amCounter
);
2451 vex_printf("; addic. r30,r30,-1; ");
2452 vex_printf("stw r30,");
2453 ppPPCAMode(i
->Pin
.EvCheck
.amCounter
);
2454 vex_printf("; bge nofail; lwz r30,");
2455 ppPPCAMode(i
->Pin
.EvCheck
.amFailAddr
);
2456 vex_printf("; mtctr r30; bctr; nofail:");
2460 vex_printf("(profInc) imm64-fixed5 r30,$NotKnownYet; ");
2461 vex_printf("ld r29,(r30); addi r29,r29,1; std r29,(r30)");
2463 vex_printf("(profInc) imm32-fixed2 r30,$NotKnownYet; ");
2464 vex_printf("lwz r29,4(r30); addic. r29,r29,1; stw r29,4(r30)");
2465 vex_printf("lwz r29,0(r30); addze r29,r29; stw r29,0(r30)");
2469 vex_printf("\nppPPCInstr: No such tag(%d)\n", (Int
)i
->tag
);
2470 vpanic("ppPPCInstr");
2474 /* --------- Helpers for register allocation. --------- */
2476 void getRegUsage_PPCInstr ( HRegUsage
* u
, const PPCInstr
* i
, Bool mode64
)
2481 addHRegUse(u
, HRmWrite
, i
->Pin
.LI
.dst
);
2484 addHRegUse(u
, HRmRead
, i
->Pin
.Alu
.srcL
);
2485 addRegUsage_PPCRH(u
, i
->Pin
.Alu
.srcR
);
2486 addHRegUse(u
, HRmWrite
, i
->Pin
.Alu
.dst
);
2488 // or Rd,Rs,Rs == mr Rd,Rs
2489 if ((i
->Pin
.Alu
.op
== Palu_OR
)
2490 && (i
->Pin
.Alu
.srcR
->tag
== Prh_Reg
)
2491 && sameHReg(i
->Pin
.Alu
.srcR
->Prh
.Reg
.reg
, i
->Pin
.Alu
.srcL
)) {
2492 u
->isRegRegMove
= True
;
2493 u
->regMoveSrc
= i
->Pin
.Alu
.srcL
;
2494 u
->regMoveDst
= i
->Pin
.Alu
.dst
;
2498 addHRegUse(u
, HRmRead
, i
->Pin
.Shft
.srcL
);
2499 addRegUsage_PPCRH(u
, i
->Pin
.Shft
.srcR
);
2500 addHRegUse(u
, HRmWrite
, i
->Pin
.Shft
.dst
);
2503 addHRegUse(u
, HRmWrite
, i
->Pin
.AddSubC
.dst
);
2504 addHRegUse(u
, HRmRead
, i
->Pin
.AddSubC
.srcL
);
2505 addHRegUse(u
, HRmRead
, i
->Pin
.AddSubC
.srcR
);
2508 addHRegUse(u
, HRmRead
, i
->Pin
.Cmp
.srcL
);
2509 addRegUsage_PPCRH(u
, i
->Pin
.Cmp
.srcR
);
2512 addHRegUse(u
, HRmWrite
, i
->Pin
.Unary
.dst
);
2513 addHRegUse(u
, HRmRead
, i
->Pin
.Unary
.src
);
2516 addHRegUse(u
, HRmWrite
, i
->Pin
.MulL
.dst
);
2517 addHRegUse(u
, HRmRead
, i
->Pin
.MulL
.srcL
);
2518 addHRegUse(u
, HRmRead
, i
->Pin
.MulL
.srcR
);
2521 addHRegUse(u
, HRmWrite
, i
->Pin
.Div
.dst
);
2522 addHRegUse(u
, HRmRead
, i
->Pin
.Div
.srcL
);
2523 addHRegUse(u
, HRmRead
, i
->Pin
.Div
.srcR
);
2527 /* This is a bit subtle. */
2528 /* First off, claim it trashes all the caller-saved regs
2529 which fall within the register allocator's jurisdiction.
2530 These I believe to be:
2534 /* XXXXXXXXXXXXXXXXX BUG! This doesn't say anything about the FP
2535 or Altivec registers. We get away with this ONLY because
2536 getAllocatableRegs_PPC gives the allocator callee-saved fp
2537 and Altivec regs, and no caller-save ones. */
2538 addHRegUse(u
, HRmWrite
, hregPPC_GPR3(mode64
));
2539 addHRegUse(u
, HRmWrite
, hregPPC_GPR4(mode64
));
2540 addHRegUse(u
, HRmWrite
, hregPPC_GPR5(mode64
));
2541 addHRegUse(u
, HRmWrite
, hregPPC_GPR6(mode64
));
2542 addHRegUse(u
, HRmWrite
, hregPPC_GPR7(mode64
));
2543 addHRegUse(u
, HRmWrite
, hregPPC_GPR8(mode64
));
2544 addHRegUse(u
, HRmWrite
, hregPPC_GPR9(mode64
));
2545 addHRegUse(u
, HRmWrite
, hregPPC_GPR10(mode64
));
2547 addHRegUse(u
, HRmWrite
, hregPPC_GPR11(mode64
));
2548 addHRegUse(u
, HRmWrite
, hregPPC_GPR12(mode64
));
2551 /* Now we have to state any parameter-carrying registers
2552 which might be read. This depends on the argiregs field. */
2553 argir
= i
->Pin
.Call
.argiregs
;
2554 if (argir
&(1<<10)) addHRegUse(u
, HRmRead
, hregPPC_GPR10(mode64
));
2555 if (argir
& (1<<9)) addHRegUse(u
, HRmRead
, hregPPC_GPR9(mode64
));
2556 if (argir
& (1<<8)) addHRegUse(u
, HRmRead
, hregPPC_GPR8(mode64
));
2557 if (argir
& (1<<7)) addHRegUse(u
, HRmRead
, hregPPC_GPR7(mode64
));
2558 if (argir
& (1<<6)) addHRegUse(u
, HRmRead
, hregPPC_GPR6(mode64
));
2559 if (argir
& (1<<5)) addHRegUse(u
, HRmRead
, hregPPC_GPR5(mode64
));
2560 if (argir
& (1<<4)) addHRegUse(u
, HRmRead
, hregPPC_GPR4(mode64
));
2561 if (argir
& (1<<3)) addHRegUse(u
, HRmRead
, hregPPC_GPR3(mode64
));
2563 vassert(0 == (argir
& ~((1<<3)|(1<<4)|(1<<5)|(1<<6)
2564 |(1<<7)|(1<<8)|(1<<9)|(1<<10))));
2566 /* Finally, there is the issue that the insn trashes a
2567 register because the literal target address has to be
2568 loaded into a register. %r10 seems a suitable victim.
2569 (Can't use %r0, as some insns interpret it as value zero). */
2570 addHRegUse(u
, HRmWrite
, hregPPC_GPR10(mode64
));
2571 /* Upshot of this is that the assembler really must use %r10,
2572 and no other, as a destination temporary. */
2575 /* XDirect/XIndir/XAssisted are also a bit subtle. They
2576 conditionally exit the block. Hence we only need to list (1)
2577 the registers that they read, and (2) the registers that they
2578 write in the case where the block is not exited. (2) is empty,
2579 hence only (1) is relevant here. */
2581 addRegUsage_PPCAMode(u
, i
->Pin
.XDirect
.amCIA
);
2584 addHRegUse(u
, HRmRead
, i
->Pin
.XIndir
.dstGA
);
2585 addRegUsage_PPCAMode(u
, i
->Pin
.XIndir
.amCIA
);
2588 addHRegUse(u
, HRmRead
, i
->Pin
.XAssisted
.dstGA
);
2589 addRegUsage_PPCAMode(u
, i
->Pin
.XAssisted
.amCIA
);
2592 addRegUsage_PPCRI(u
, i
->Pin
.CMov
.src
);
2593 addHRegUse(u
, HRmModify
, i
->Pin
.CMov
.dst
);
2596 addRegUsage_PPCAMode(u
, i
->Pin
.Load
.src
);
2597 addHRegUse(u
, HRmWrite
, i
->Pin
.Load
.dst
);
2600 addHRegUse(u
, HRmRead
, i
->Pin
.LoadL
.src
);
2601 addHRegUse(u
, HRmWrite
, i
->Pin
.LoadL
.dst
);
2604 addHRegUse(u
, HRmRead
, i
->Pin
.Store
.src
);
2605 addRegUsage_PPCAMode(u
, i
->Pin
.Store
.dst
);
2608 addHRegUse(u
, HRmRead
, i
->Pin
.StoreC
.src
);
2609 addHRegUse(u
, HRmRead
, i
->Pin
.StoreC
.dst
);
2612 addHRegUse(u
, HRmWrite
, i
->Pin
.Set
.dst
);
2615 addHRegUse(u
, HRmWrite
, i
->Pin
.MfCR
.dst
);
2621 addHRegUse(u
, HRmWrite
, i
->Pin
.FpUnary
.dst
);
2622 addHRegUse(u
, HRmRead
, i
->Pin
.FpUnary
.src
);
2624 if (i
->Pin
.FpUnary
.op
== Pfp_MOV
) {
2625 u
->isRegRegMove
= True
;
2626 u
->regMoveSrc
= i
->Pin
.FpUnary
.src
;
2627 u
->regMoveDst
= i
->Pin
.FpUnary
.dst
;
2631 addHRegUse(u
, HRmWrite
, i
->Pin
.FpBinary
.dst
);
2632 addHRegUse(u
, HRmRead
, i
->Pin
.FpBinary
.srcL
);
2633 addHRegUse(u
, HRmRead
, i
->Pin
.FpBinary
.srcR
);
2636 case Pin_Fp128Unary
:
2637 addHRegUse(u
, HRmWrite
, i
->Pin
.Fp128Unary
.dst
);
2638 addHRegUse(u
, HRmRead
, i
->Pin
.Fp128Unary
.src
);
2640 case Pin_Fp128Binary
:
2641 addHRegUse(u
, HRmWrite
, i
->Pin
.Fp128Binary
.dst
);
2642 addHRegUse(u
, HRmRead
, i
->Pin
.Fp128Binary
.srcL
);
2643 addHRegUse(u
, HRmRead
, i
->Pin
.Fp128Binary
.srcR
);
2645 case Pin_Fp128Ternary
:
2646 addHRegUse(u
, HRmModify
, i
->Pin
.Fp128Ternary
.dst
);
2647 addHRegUse(u
, HRmRead
, i
->Pin
.Fp128Ternary
.srcL
);
2648 addHRegUse(u
, HRmRead
, i
->Pin
.Fp128Ternary
.srcR
);
2651 addHRegUse(u
, HRmWrite
, i
->Pin
.FpMulAcc
.dst
);
2652 addHRegUse(u
, HRmRead
, i
->Pin
.FpMulAcc
.srcML
);
2653 addHRegUse(u
, HRmRead
, i
->Pin
.FpMulAcc
.srcMR
);
2654 addHRegUse(u
, HRmRead
, i
->Pin
.FpMulAcc
.srcAcc
);
2657 addHRegUse(u
, (i
->Pin
.FpLdSt
.isLoad
? HRmWrite
: HRmRead
),
2659 addRegUsage_PPCAMode(u
, i
->Pin
.FpLdSt
.addr
);
2662 addHRegUse(u
, HRmRead
, i
->Pin
.FpSTFIW
.addr
);
2663 addHRegUse(u
, HRmRead
, i
->Pin
.FpSTFIW
.data
);
2666 addHRegUse(u
, HRmWrite
, i
->Pin
.FpRSP
.dst
);
2667 addHRegUse(u
, HRmRead
, i
->Pin
.FpRSP
.src
);
2670 addHRegUse(u
, HRmWrite
, i
->Pin
.FpCftI
.dst
);
2671 addHRegUse(u
, HRmRead
, i
->Pin
.FpCftI
.src
);
2674 addHRegUse(u
, HRmModify
, i
->Pin
.FpCMov
.dst
);
2675 addHRegUse(u
, HRmRead
, i
->Pin
.FpCMov
.src
);
2678 addHRegUse(u
, HRmRead
, i
->Pin
.FpLdFPSCR
.src
);
2681 addHRegUse(u
, HRmWrite
, i
->Pin
.FpCmp
.dst
);
2682 addHRegUse(u
, HRmRead
, i
->Pin
.FpCmp
.srcL
);
2683 addHRegUse(u
, HRmRead
, i
->Pin
.FpCmp
.srcR
);
2687 addHRegUse(u
, (i
->Pin
.RdWrLR
.wrLR
? HRmRead
: HRmWrite
),
2692 addHRegUse(u
, (i
->Pin
.AvLdSt
.isLoad
? HRmWrite
: HRmRead
),
2694 if (i
->Pin
.AvLdSt
.addr
->tag
== Pam_IR
)
2695 addHRegUse(u
, HRmWrite
, hregPPC_GPR30(mode64
));
2696 addRegUsage_PPCAMode(u
, i
->Pin
.AvLdSt
.addr
);
2699 addHRegUse(u
, HRmWrite
, i
->Pin
.AvUnary
.dst
);
2700 addHRegUse(u
, HRmRead
, i
->Pin
.AvUnary
.src
);
2703 if (i
->Pin
.AvBinary
.op
== Pav_XOR
2704 && sameHReg(i
->Pin
.AvBinary
.dst
, i
->Pin
.AvBinary
.srcL
)
2705 && sameHReg(i
->Pin
.AvBinary
.dst
, i
->Pin
.AvBinary
.srcR
)) {
2706 /* reg-alloc needs to understand 'xor r,r,r' as a write of r */
2707 /* (as opposed to a rite of passage :-) */
2708 addHRegUse(u
, HRmWrite
, i
->Pin
.AvBinary
.dst
);
2710 addHRegUse(u
, HRmWrite
, i
->Pin
.AvBinary
.dst
);
2711 addHRegUse(u
, HRmRead
, i
->Pin
.AvBinary
.srcL
);
2712 addHRegUse(u
, HRmRead
, i
->Pin
.AvBinary
.srcR
);
2715 case Pin_AvBinaryInt
:
2716 addHRegUse(u
, HRmWrite
, i
->Pin
.AvBinaryInt
.dst
);
2717 addHRegUse(u
, HRmRead
, i
->Pin
.AvBinaryInt
.src
);
2719 case Pin_AvBinaryInt128
:
2720 addHRegUse(u
, HRmWrite
, i
->Pin
.AvBinaryInt128
.dst
);
2721 addHRegUse(u
, HRmRead
, i
->Pin
.AvBinaryInt128
.src1
);
2722 addHRegUse(u
, HRmRead
, i
->Pin
.AvBinaryInt128
.src2
);
2724 case Pin_AvTernaryInt128
:
2725 addHRegUse(u
, HRmWrite
, i
->Pin
.AvTernaryInt128
.dst
);
2726 addHRegUse(u
, HRmRead
, i
->Pin
.AvTernaryInt128
.src1
);
2727 addHRegUse(u
, HRmRead
, i
->Pin
.AvTernaryInt128
.src2
);
2728 addHRegUse(u
, HRmRead
, i
->Pin
.AvTernaryInt128
.src3
);
2731 addHRegUse(u
, HRmWrite
, i
->Pin
.AvBin8x16
.dst
);
2732 addHRegUse(u
, HRmRead
, i
->Pin
.AvBin8x16
.srcL
);
2733 addHRegUse(u
, HRmRead
, i
->Pin
.AvBin8x16
.srcR
);
2736 addHRegUse(u
, HRmWrite
, i
->Pin
.AvBin16x8
.dst
);
2737 addHRegUse(u
, HRmRead
, i
->Pin
.AvBin16x8
.srcL
);
2738 addHRegUse(u
, HRmRead
, i
->Pin
.AvBin16x8
.srcR
);
2741 addHRegUse(u
, HRmWrite
, i
->Pin
.AvBin32x4
.dst
);
2742 addHRegUse(u
, HRmRead
, i
->Pin
.AvBin32x4
.srcL
);
2743 addHRegUse(u
, HRmRead
, i
->Pin
.AvBin32x4
.srcR
);
2746 addHRegUse(u
, HRmWrite
, i
->Pin
.AvBin64x2
.dst
);
2747 addHRegUse(u
, HRmRead
, i
->Pin
.AvBin64x2
.srcL
);
2748 addHRegUse(u
, HRmRead
, i
->Pin
.AvBin64x2
.srcR
);
2750 case Pin_AvBin32Fx4
:
2751 addHRegUse(u
, HRmWrite
, i
->Pin
.AvBin32Fx4
.dst
);
2752 addHRegUse(u
, HRmRead
, i
->Pin
.AvBin32Fx4
.srcL
);
2753 addHRegUse(u
, HRmRead
, i
->Pin
.AvBin32Fx4
.srcR
);
2754 if (i
->Pin
.AvBin32Fx4
.op
== Pavfp_MULF
)
2755 addHRegUse(u
, HRmWrite
, hregPPC_VR29(mode64
));
2758 addHRegUse(u
, HRmWrite
, i
->Pin
.AvUn32Fx4
.dst
);
2759 addHRegUse(u
, HRmRead
, i
->Pin
.AvUn32Fx4
.src
);
2762 addHRegUse(u
, HRmWrite
, i
->Pin
.AvPerm
.dst
);
2763 addHRegUse(u
, HRmRead
, i
->Pin
.AvPerm
.srcL
);
2764 addHRegUse(u
, HRmRead
, i
->Pin
.AvPerm
.srcR
);
2765 addHRegUse(u
, HRmRead
, i
->Pin
.AvPerm
.ctl
);
2768 addHRegUse(u
, HRmWrite
, i
->Pin
.AvSel
.dst
);
2769 addHRegUse(u
, HRmRead
, i
->Pin
.AvSel
.ctl
);
2770 addHRegUse(u
, HRmRead
, i
->Pin
.AvSel
.srcL
);
2771 addHRegUse(u
, HRmRead
, i
->Pin
.AvSel
.srcR
);
2774 addHRegUse(u
, HRmWrite
, i
->Pin
.AvSh
.dst
);
2775 if (i
->Pin
.AvSh
.addr
->tag
== Pam_IR
)
2776 addHRegUse(u
, HRmWrite
, hregPPC_GPR30(mode64
));
2777 addRegUsage_PPCAMode(u
, i
->Pin
.AvSh
.addr
);
2780 addHRegUse(u
, HRmWrite
, i
->Pin
.AvShlDbl
.dst
);
2781 addHRegUse(u
, HRmRead
, i
->Pin
.AvShlDbl
.srcL
);
2782 addHRegUse(u
, HRmRead
, i
->Pin
.AvShlDbl
.srcR
);
2785 addHRegUse(u
, HRmWrite
, i
->Pin
.AvSplat
.dst
);
2786 addRegUsage_PPCVI5s(u
, i
->Pin
.AvSplat
.src
);
2789 addHRegUse(u
, HRmModify
, i
->Pin
.AvCMov
.dst
);
2790 addHRegUse(u
, HRmRead
, i
->Pin
.AvCMov
.src
);
2793 addHRegUse(u
, HRmRead
, i
->Pin
.AvLdVSCR
.src
);
2795 case Pin_AvCipherV128Unary
:
2796 addHRegUse(u
, HRmWrite
, i
->Pin
.AvCipherV128Unary
.dst
);
2797 addHRegUse(u
, HRmRead
, i
->Pin
.AvCipherV128Unary
.src
);
2799 case Pin_AvCipherV128Binary
:
2800 addHRegUse(u
, HRmWrite
, i
->Pin
.AvCipherV128Binary
.dst
);
2801 addHRegUse(u
, HRmRead
, i
->Pin
.AvCipherV128Binary
.srcL
);
2802 addHRegUse(u
, HRmRead
, i
->Pin
.AvCipherV128Binary
.srcR
);
2804 case Pin_AvHashV128Binary
:
2805 addHRegUse(u
, HRmWrite
, i
->Pin
.AvHashV128Binary
.dst
);
2806 addHRegUse(u
, HRmRead
, i
->Pin
.AvHashV128Binary
.src
);
2807 addRegUsage_PPCRI(u
, i
->Pin
.AvHashV128Binary
.s_field
);
2809 case Pin_AvBCDV128Binary
:
2810 addHRegUse(u
, HRmWrite
, i
->Pin
.AvBCDV128Binary
.dst
);
2811 addHRegUse(u
, HRmRead
, i
->Pin
.AvBCDV128Binary
.src1
);
2812 addHRegUse(u
, HRmRead
, i
->Pin
.AvBCDV128Binary
.src2
);
2814 case Pin_Dfp64Unary
:
2815 addHRegUse(u
, HRmWrite
, i
->Pin
.Dfp64Unary
.dst
);
2816 addHRegUse(u
, HRmRead
, i
->Pin
.Dfp64Unary
.src
);
2818 case Pin_Dfp64Binary
:
2819 addHRegUse(u
, HRmWrite
, i
->Pin
.Dfp64Binary
.dst
);
2820 addHRegUse(u
, HRmRead
, i
->Pin
.Dfp64Binary
.srcL
);
2821 addHRegUse(u
, HRmRead
, i
->Pin
.Dfp64Binary
.srcR
);
2824 addRegUsage_PPCRI(u
, i
->Pin
.DfpShift
.shift
);
2825 addHRegUse(u
, HRmWrite
, i
->Pin
.DfpShift
.src
);
2826 addHRegUse(u
, HRmWrite
, i
->Pin
.DfpShift
.dst
);
2828 case Pin_Dfp128Unary
:
2829 addHRegUse(u
, HRmWrite
, i
->Pin
.Dfp128Unary
.dst_hi
);
2830 addHRegUse(u
, HRmWrite
, i
->Pin
.Dfp128Unary
.dst_lo
);
2831 addHRegUse(u
, HRmRead
, i
->Pin
.Dfp128Unary
.src_hi
);
2832 addHRegUse(u
, HRmRead
, i
->Pin
.Dfp128Unary
.src_lo
);
2834 case Pin_Dfp128Binary
:
2835 addHRegUse(u
, HRmWrite
, i
->Pin
.Dfp128Binary
.dst_hi
);
2836 addHRegUse(u
, HRmWrite
, i
->Pin
.Dfp128Binary
.dst_lo
);
2837 addHRegUse(u
, HRmRead
, i
->Pin
.Dfp128Binary
.srcR_hi
);
2838 addHRegUse(u
, HRmRead
, i
->Pin
.Dfp128Binary
.srcR_lo
);
2841 addHRegUse(u
, HRmWrite
, i
->Pin
.DfpRound
.dst
);
2842 addHRegUse(u
, HRmRead
, i
->Pin
.DfpRound
.src
);
2844 case Pin_DfpRound128
:
2845 addHRegUse(u
, HRmWrite
, i
->Pin
.DfpRound128
.dst_hi
);
2846 addHRegUse(u
, HRmWrite
, i
->Pin
.DfpRound128
.dst_lo
);
2847 addHRegUse(u
, HRmRead
, i
->Pin
.DfpRound128
.src_hi
);
2848 addHRegUse(u
, HRmRead
, i
->Pin
.DfpRound128
.src_lo
);
2850 case Pin_DfpQuantize
:
2851 addRegUsage_PPCRI(u
, i
->Pin
.DfpQuantize
.rmc
);
2852 addHRegUse(u
, HRmWrite
, i
->Pin
.DfpQuantize
.dst
);
2853 addHRegUse(u
, HRmRead
, i
->Pin
.DfpQuantize
.srcL
);
2854 addHRegUse(u
, HRmRead
, i
->Pin
.DfpQuantize
.srcR
);
2856 case Pin_DfpQuantize128
:
2857 addHRegUse(u
, HRmWrite
, i
->Pin
.DfpQuantize128
.dst_hi
);
2858 addHRegUse(u
, HRmWrite
, i
->Pin
.DfpQuantize128
.dst_lo
);
2859 addHRegUse(u
, HRmRead
, i
->Pin
.DfpQuantize128
.src_hi
);
2860 addHRegUse(u
, HRmRead
, i
->Pin
.DfpQuantize128
.src_lo
);
2862 case Pin_DfpShift128
:
2863 addRegUsage_PPCRI(u
, i
->Pin
.DfpShift128
.shift
);
2864 addHRegUse(u
, HRmWrite
, i
->Pin
.DfpShift128
.src_hi
);
2865 addHRegUse(u
, HRmWrite
, i
->Pin
.DfpShift128
.src_lo
);
2866 addHRegUse(u
, HRmWrite
, i
->Pin
.DfpShift128
.dst_hi
);
2867 addHRegUse(u
, HRmWrite
, i
->Pin
.DfpShift128
.dst_lo
);
2869 case Pin_DfpD128toD64
:
2870 addHRegUse(u
, HRmWrite
, i
->Pin
.DfpD128toD64
.src_hi
);
2871 addHRegUse(u
, HRmWrite
, i
->Pin
.DfpD128toD64
.src_lo
);
2872 addHRegUse(u
, HRmWrite
, i
->Pin
.DfpD128toD64
.dst
);
2874 case Pin_DfpI64StoD128
:
2875 addHRegUse(u
, HRmWrite
, i
->Pin
.DfpI64StoD128
.src
);
2876 addHRegUse(u
, HRmWrite
, i
->Pin
.DfpI64StoD128
.dst_hi
);
2877 addHRegUse(u
, HRmWrite
, i
->Pin
.DfpI64StoD128
.dst_lo
);
2879 case Pin_ExtractExpD128
:
2880 addHRegUse(u
, HRmWrite
, i
->Pin
.ExtractExpD128
.dst
);
2881 addHRegUse(u
, HRmRead
, i
->Pin
.ExtractExpD128
.src_hi
);
2882 addHRegUse(u
, HRmRead
, i
->Pin
.ExtractExpD128
.src_lo
);
2884 case Pin_InsertExpD128
:
2885 addHRegUse(u
, HRmWrite
, i
->Pin
.InsertExpD128
.dst_hi
);
2886 addHRegUse(u
, HRmWrite
, i
->Pin
.InsertExpD128
.dst_lo
);
2887 addHRegUse(u
, HRmRead
, i
->Pin
.InsertExpD128
.srcL
);
2888 addHRegUse(u
, HRmRead
, i
->Pin
.InsertExpD128
.srcR_hi
);
2889 addHRegUse(u
, HRmRead
, i
->Pin
.InsertExpD128
.srcR_lo
);
2892 addHRegUse(u
, HRmWrite
, i
->Pin
.Dfp64Cmp
.dst
);
2893 addHRegUse(u
, HRmRead
, i
->Pin
.Dfp64Cmp
.srcL
);
2894 addHRegUse(u
, HRmRead
, i
->Pin
.Dfp64Cmp
.srcR
);
2897 addHRegUse(u
, HRmWrite
, i
->Pin
.Dfp128Cmp
.dst
);
2898 addHRegUse(u
, HRmRead
, i
->Pin
.Dfp128Cmp
.srcL_hi
);
2899 addHRegUse(u
, HRmRead
, i
->Pin
.Dfp128Cmp
.srcL_lo
);
2900 addHRegUse(u
, HRmRead
, i
->Pin
.Dfp128Cmp
.srcR_hi
);
2901 addHRegUse(u
, HRmRead
, i
->Pin
.Dfp128Cmp
.srcR_lo
);
2903 case Pin_XFormUnary994
:
2904 if (i
->Pin
.XFormUnary994
.op
== Px_DFPTOIQS
) {
2905 addHRegUse(u
, HRmWrite
, i
->Pin
.XFormUnary994
.reg0
);
2906 addHRegUse(u
, HRmRead
, i
->Pin
.XFormUnary994
.reg1
);
2907 addHRegUse(u
, HRmRead
, i
->Pin
.XFormUnary994
.reg2
);
2909 addHRegUse(u
, HRmWrite
, i
->Pin
.XFormUnary994
.reg0
);
2910 addHRegUse(u
, HRmWrite
, i
->Pin
.XFormUnary994
.reg1
);
2911 addHRegUse(u
, HRmRead
, i
->Pin
.XFormUnary994
.reg2
);
2915 /* We expect both amodes only to mention the GSP (r31), so this
2916 is in fact pointless, since GSP isn't allocatable, but
2918 addRegUsage_PPCAMode(u
, i
->Pin
.EvCheck
.amCounter
);
2919 addRegUsage_PPCAMode(u
, i
->Pin
.EvCheck
.amFailAddr
);
2920 addHRegUse(u
, HRmWrite
, hregPPC_GPR30(mode64
)); /* also unavail to RA */
2923 addHRegUse(u
, HRmWrite
, hregPPC_GPR29(mode64
));
2924 addHRegUse(u
, HRmWrite
, hregPPC_GPR30(mode64
));
2927 ppPPCInstr(i
, mode64
);
2928 vpanic("getRegUsage_PPCInstr");
2933 static void mapReg( HRegRemap
* m
, HReg
* r
)
2935 *r
= lookupHRegRemap(m
, *r
);
2938 void mapRegs_PPCInstr ( HRegRemap
* m
, PPCInstr
* i
, Bool mode64
)
2942 mapReg(m
, &i
->Pin
.LI
.dst
);
2945 mapReg(m
, &i
->Pin
.Alu
.dst
);
2946 mapReg(m
, &i
->Pin
.Alu
.srcL
);
2947 mapRegs_PPCRH(m
, i
->Pin
.Alu
.srcR
);
2950 mapReg(m
, &i
->Pin
.Shft
.dst
);
2951 mapReg(m
, &i
->Pin
.Shft
.srcL
);
2952 mapRegs_PPCRH(m
, i
->Pin
.Shft
.srcR
);
2955 mapReg(m
, &i
->Pin
.AddSubC
.dst
);
2956 mapReg(m
, &i
->Pin
.AddSubC
.srcL
);
2957 mapReg(m
, &i
->Pin
.AddSubC
.srcR
);
2960 mapReg(m
, &i
->Pin
.Cmp
.srcL
);
2961 mapRegs_PPCRH(m
, i
->Pin
.Cmp
.srcR
);
2964 mapReg(m
, &i
->Pin
.Unary
.dst
);
2965 mapReg(m
, &i
->Pin
.Unary
.src
);
2968 mapReg(m
, &i
->Pin
.MulL
.dst
);
2969 mapReg(m
, &i
->Pin
.MulL
.srcL
);
2970 mapReg(m
, &i
->Pin
.MulL
.srcR
);
2973 mapReg(m
, &i
->Pin
.Div
.dst
);
2974 mapReg(m
, &i
->Pin
.Div
.srcL
);
2975 mapReg(m
, &i
->Pin
.Div
.srcR
);
2980 mapRegs_PPCAMode(m
, i
->Pin
.XDirect
.amCIA
);
2983 mapReg(m
, &i
->Pin
.XIndir
.dstGA
);
2984 mapRegs_PPCAMode(m
, i
->Pin
.XIndir
.amCIA
);
2987 mapReg(m
, &i
->Pin
.XAssisted
.dstGA
);
2988 mapRegs_PPCAMode(m
, i
->Pin
.XAssisted
.amCIA
);
2991 mapRegs_PPCRI(m
, i
->Pin
.CMov
.src
);
2992 mapReg(m
, &i
->Pin
.CMov
.dst
);
2995 mapRegs_PPCAMode(m
, i
->Pin
.Load
.src
);
2996 mapReg(m
, &i
->Pin
.Load
.dst
);
2999 mapReg(m
, &i
->Pin
.LoadL
.src
);
3000 mapReg(m
, &i
->Pin
.LoadL
.dst
);
3003 mapReg(m
, &i
->Pin
.Store
.src
);
3004 mapRegs_PPCAMode(m
, i
->Pin
.Store
.dst
);
3007 mapReg(m
, &i
->Pin
.StoreC
.src
);
3008 mapReg(m
, &i
->Pin
.StoreC
.dst
);
3011 mapReg(m
, &i
->Pin
.Set
.dst
);
3014 mapReg(m
, &i
->Pin
.MfCR
.dst
);
3019 mapReg(m
, &i
->Pin
.FpUnary
.dst
);
3020 mapReg(m
, &i
->Pin
.FpUnary
.src
);
3023 mapReg(m
, &i
->Pin
.FpBinary
.dst
);
3024 mapReg(m
, &i
->Pin
.FpBinary
.srcL
);
3025 mapReg(m
, &i
->Pin
.FpBinary
.srcR
);
3027 case Pin_Fp128Unary
:
3028 mapReg(m
, &i
->Pin
.Fp128Unary
.dst
);
3029 mapReg(m
, &i
->Pin
.Fp128Unary
.src
);
3031 case Pin_Fp128Binary
:
3032 mapReg(m
, &i
->Pin
.Fp128Binary
.dst
);
3033 mapReg(m
, &i
->Pin
.Fp128Binary
.srcL
);
3034 mapReg(m
, &i
->Pin
.Fp128Binary
.srcR
);
3036 case Pin_Fp128Ternary
:
3037 mapReg(m
, &i
->Pin
.Fp128Ternary
.dst
);
3038 mapReg(m
, &i
->Pin
.Fp128Ternary
.srcL
);
3039 mapReg(m
, &i
->Pin
.Fp128Ternary
.srcR
);
3042 mapReg(m
, &i
->Pin
.FpMulAcc
.dst
);
3043 mapReg(m
, &i
->Pin
.FpMulAcc
.srcML
);
3044 mapReg(m
, &i
->Pin
.FpMulAcc
.srcMR
);
3045 mapReg(m
, &i
->Pin
.FpMulAcc
.srcAcc
);
3048 mapReg(m
, &i
->Pin
.FpLdSt
.reg
);
3049 mapRegs_PPCAMode(m
, i
->Pin
.FpLdSt
.addr
);
3052 mapReg(m
, &i
->Pin
.FpSTFIW
.addr
);
3053 mapReg(m
, &i
->Pin
.FpSTFIW
.data
);
3056 mapReg(m
, &i
->Pin
.FpRSP
.dst
);
3057 mapReg(m
, &i
->Pin
.FpRSP
.src
);
3060 mapReg(m
, &i
->Pin
.FpCftI
.dst
);
3061 mapReg(m
, &i
->Pin
.FpCftI
.src
);
3064 mapReg(m
, &i
->Pin
.FpCMov
.dst
);
3065 mapReg(m
, &i
->Pin
.FpCMov
.src
);
3068 mapReg(m
, &i
->Pin
.FpLdFPSCR
.src
);
3071 mapReg(m
, &i
->Pin
.FpCmp
.dst
);
3072 mapReg(m
, &i
->Pin
.FpCmp
.srcL
);
3073 mapReg(m
, &i
->Pin
.FpCmp
.srcR
);
3076 mapReg(m
, &i
->Pin
.RdWrLR
.gpr
);
3079 mapReg(m
, &i
->Pin
.AvLdSt
.reg
);
3080 mapRegs_PPCAMode(m
, i
->Pin
.AvLdSt
.addr
);
3083 mapReg(m
, &i
->Pin
.AvUnary
.dst
);
3084 mapReg(m
, &i
->Pin
.AvUnary
.src
);
3087 mapReg(m
, &i
->Pin
.AvBinary
.dst
);
3088 mapReg(m
, &i
->Pin
.AvBinary
.srcL
);
3089 mapReg(m
, &i
->Pin
.AvBinary
.srcR
);
3091 case Pin_AvBinaryInt
:
3092 mapReg(m
, &i
->Pin
.AvBinaryInt
.dst
);
3093 mapReg(m
, &i
->Pin
.AvBinaryInt
.src
);
3095 case Pin_AvBinaryInt128
:
3096 mapReg(m
, &i
->Pin
.AvBinaryInt128
.dst
);
3097 mapReg(m
, &i
->Pin
.AvBinaryInt128
.src1
);
3098 mapReg(m
, &i
->Pin
.AvBinaryInt128
.src2
);
3100 case Pin_AvTernaryInt128
:
3101 mapReg(m
, &i
->Pin
.AvTernaryInt128
.dst
);
3102 mapReg(m
, &i
->Pin
.AvTernaryInt128
.src1
);
3103 mapReg(m
, &i
->Pin
.AvTernaryInt128
.src2
);
3104 mapReg(m
, &i
->Pin
.AvTernaryInt128
.src3
);
3107 mapReg(m
, &i
->Pin
.AvBin8x16
.dst
);
3108 mapReg(m
, &i
->Pin
.AvBin8x16
.srcL
);
3109 mapReg(m
, &i
->Pin
.AvBin8x16
.srcR
);
3112 mapReg(m
, &i
->Pin
.AvBin16x8
.dst
);
3113 mapReg(m
, &i
->Pin
.AvBin16x8
.srcL
);
3114 mapReg(m
, &i
->Pin
.AvBin16x8
.srcR
);
3117 mapReg(m
, &i
->Pin
.AvBin32x4
.dst
);
3118 mapReg(m
, &i
->Pin
.AvBin32x4
.srcL
);
3119 mapReg(m
, &i
->Pin
.AvBin32x4
.srcR
);
3122 mapReg(m
, &i
->Pin
.AvBin64x2
.dst
);
3123 mapReg(m
, &i
->Pin
.AvBin64x2
.srcL
);
3124 mapReg(m
, &i
->Pin
.AvBin64x2
.srcR
);
3126 case Pin_AvBin32Fx4
:
3127 mapReg(m
, &i
->Pin
.AvBin32Fx4
.dst
);
3128 mapReg(m
, &i
->Pin
.AvBin32Fx4
.srcL
);
3129 mapReg(m
, &i
->Pin
.AvBin32Fx4
.srcR
);
3132 mapReg(m
, &i
->Pin
.AvUn32Fx4
.dst
);
3133 mapReg(m
, &i
->Pin
.AvUn32Fx4
.src
);
3136 mapReg(m
, &i
->Pin
.AvPerm
.dst
);
3137 mapReg(m
, &i
->Pin
.AvPerm
.srcL
);
3138 mapReg(m
, &i
->Pin
.AvPerm
.srcR
);
3139 mapReg(m
, &i
->Pin
.AvPerm
.ctl
);
3142 mapReg(m
, &i
->Pin
.AvSel
.dst
);
3143 mapReg(m
, &i
->Pin
.AvSel
.srcL
);
3144 mapReg(m
, &i
->Pin
.AvSel
.srcR
);
3145 mapReg(m
, &i
->Pin
.AvSel
.ctl
);
3148 mapReg(m
, &i
->Pin
.AvSh
.dst
);
3149 mapRegs_PPCAMode(m
, i
->Pin
.AvSh
.addr
);
3152 mapReg(m
, &i
->Pin
.AvShlDbl
.dst
);
3153 mapReg(m
, &i
->Pin
.AvShlDbl
.srcL
);
3154 mapReg(m
, &i
->Pin
.AvShlDbl
.srcR
);
3157 mapReg(m
, &i
->Pin
.AvSplat
.dst
);
3158 mapRegs_PPCVI5s(m
, i
->Pin
.AvSplat
.src
);
3161 mapReg(m
, &i
->Pin
.AvCMov
.dst
);
3162 mapReg(m
, &i
->Pin
.AvCMov
.src
);
3165 mapReg(m
, &i
->Pin
.AvLdVSCR
.src
);
3167 case Pin_AvCipherV128Unary
:
3168 mapReg(m
, &i
->Pin
.AvCipherV128Unary
.dst
);
3169 mapReg(m
, &i
->Pin
.AvCipherV128Unary
.src
);
3171 case Pin_AvCipherV128Binary
:
3172 mapReg(m
, &i
->Pin
.AvCipherV128Binary
.dst
);
3173 mapReg(m
, &i
->Pin
.AvCipherV128Binary
.srcL
);
3174 mapReg(m
, &i
->Pin
.AvCipherV128Binary
.srcR
);
3176 case Pin_AvHashV128Binary
:
3177 mapRegs_PPCRI(m
, i
->Pin
.AvHashV128Binary
.s_field
);
3178 mapReg(m
, &i
->Pin
.AvHashV128Binary
.dst
);
3179 mapReg(m
, &i
->Pin
.AvHashV128Binary
.src
);
3181 case Pin_AvBCDV128Binary
:
3182 mapReg(m
, &i
->Pin
.AvBCDV128Binary
.dst
);
3183 mapReg(m
, &i
->Pin
.AvBCDV128Binary
.src1
);
3184 mapReg(m
, &i
->Pin
.AvBCDV128Binary
.src2
);
3186 case Pin_Dfp64Unary
:
3187 mapReg(m
, &i
->Pin
.Dfp64Unary
.dst
);
3188 mapReg(m
, &i
->Pin
.Dfp64Unary
.src
);
3190 case Pin_Dfp64Binary
:
3191 mapReg(m
, &i
->Pin
.Dfp64Binary
.dst
);
3192 mapReg(m
, &i
->Pin
.Dfp64Binary
.srcL
);
3193 mapReg(m
, &i
->Pin
.Dfp64Binary
.srcR
);
3196 mapRegs_PPCRI(m
, i
->Pin
.DfpShift
.shift
);
3197 mapReg(m
, &i
->Pin
.DfpShift
.src
);
3198 mapReg(m
, &i
->Pin
.DfpShift
.dst
);
3200 case Pin_Dfp128Unary
:
3201 mapReg(m
, &i
->Pin
.Dfp128Unary
.dst_hi
);
3202 mapReg(m
, &i
->Pin
.Dfp128Unary
.dst_lo
);
3203 mapReg(m
, &i
->Pin
.Dfp128Unary
.src_hi
);
3204 mapReg(m
, &i
->Pin
.Dfp128Unary
.src_lo
);
3206 case Pin_Dfp128Binary
:
3207 mapReg(m
, &i
->Pin
.Dfp128Binary
.dst_hi
);
3208 mapReg(m
, &i
->Pin
.Dfp128Binary
.dst_lo
);
3209 mapReg(m
, &i
->Pin
.Dfp128Binary
.srcR_hi
);
3210 mapReg(m
, &i
->Pin
.Dfp128Binary
.srcR_lo
);
3212 case Pin_DfpShift128
:
3213 mapRegs_PPCRI(m
, i
->Pin
.DfpShift128
.shift
);
3214 mapReg(m
, &i
->Pin
.DfpShift128
.src_hi
);
3215 mapReg(m
, &i
->Pin
.DfpShift128
.src_lo
);
3216 mapReg(m
, &i
->Pin
.DfpShift128
.dst_hi
);
3217 mapReg(m
, &i
->Pin
.DfpShift128
.dst_lo
);
3220 mapReg(m
, &i
->Pin
.DfpRound
.dst
);
3221 mapReg(m
, &i
->Pin
.DfpRound
.src
);
3223 case Pin_DfpRound128
:
3224 mapReg(m
, &i
->Pin
.DfpRound128
.dst_hi
);
3225 mapReg(m
, &i
->Pin
.DfpRound128
.dst_lo
);
3226 mapReg(m
, &i
->Pin
.DfpRound128
.src_hi
);
3227 mapReg(m
, &i
->Pin
.DfpRound128
.src_lo
);
3229 case Pin_DfpQuantize
:
3230 mapRegs_PPCRI(m
, i
->Pin
.DfpQuantize
.rmc
);
3231 mapReg(m
, &i
->Pin
.DfpQuantize
.dst
);
3232 mapReg(m
, &i
->Pin
.DfpQuantize
.srcL
);
3233 mapReg(m
, &i
->Pin
.DfpQuantize
.srcR
);
3235 case Pin_DfpQuantize128
:
3236 mapRegs_PPCRI(m
, i
->Pin
.DfpQuantize128
.rmc
);
3237 mapReg(m
, &i
->Pin
.DfpQuantize128
.dst_hi
);
3238 mapReg(m
, &i
->Pin
.DfpQuantize128
.dst_lo
);
3239 mapReg(m
, &i
->Pin
.DfpQuantize128
.src_hi
);
3240 mapReg(m
, &i
->Pin
.DfpQuantize128
.src_lo
);
3242 case Pin_DfpD128toD64
:
3243 mapReg(m
, &i
->Pin
.DfpD128toD64
.src_hi
);
3244 mapReg(m
, &i
->Pin
.DfpD128toD64
.src_lo
);
3245 mapReg(m
, &i
->Pin
.DfpD128toD64
.dst
);
3247 case Pin_DfpI64StoD128
:
3248 mapReg(m
, &i
->Pin
.DfpI64StoD128
.src
);
3249 mapReg(m
, &i
->Pin
.DfpI64StoD128
.dst_hi
);
3250 mapReg(m
, &i
->Pin
.DfpI64StoD128
.dst_lo
);
3252 case Pin_ExtractExpD128
:
3253 mapReg(m
, &i
->Pin
.ExtractExpD128
.dst
);
3254 mapReg(m
, &i
->Pin
.ExtractExpD128
.src_hi
);
3255 mapReg(m
, &i
->Pin
.ExtractExpD128
.src_lo
);
3257 case Pin_InsertExpD128
:
3258 mapReg(m
, &i
->Pin
.InsertExpD128
.dst_hi
);
3259 mapReg(m
, &i
->Pin
.InsertExpD128
.dst_lo
);
3260 mapReg(m
, &i
->Pin
.InsertExpD128
.srcL
);
3261 mapReg(m
, &i
->Pin
.InsertExpD128
.srcR_hi
);
3262 mapReg(m
, &i
->Pin
.InsertExpD128
.srcR_lo
);
3265 mapReg(m
, &i
->Pin
.Dfp64Cmp
.dst
);
3266 mapReg(m
, &i
->Pin
.Dfp64Cmp
.srcL
);
3267 mapReg(m
, &i
->Pin
.Dfp64Cmp
.srcR
);
3270 mapReg(m
, &i
->Pin
.Dfp128Cmp
.dst
);
3271 mapReg(m
, &i
->Pin
.Dfp128Cmp
.srcL_hi
);
3272 mapReg(m
, &i
->Pin
.Dfp128Cmp
.srcL_lo
);
3273 mapReg(m
, &i
->Pin
.Dfp128Cmp
.srcR_hi
);
3274 mapReg(m
, &i
->Pin
.Dfp128Cmp
.srcR_lo
);
3276 case Pin_XFormUnary994
:
3277 mapReg(m
, &i
->Pin
.XFormUnary994
.reg0
);
3278 mapReg(m
, &i
->Pin
.XFormUnary994
.reg1
);
3279 mapReg(m
, &i
->Pin
.XFormUnary994
.reg2
);
3282 /* We expect both amodes only to mention the GSP (r31), so this
3283 is in fact pointless, since GSP isn't allocatable, but
3285 mapRegs_PPCAMode(m
, i
->Pin
.EvCheck
.amCounter
);
3286 mapRegs_PPCAMode(m
, i
->Pin
.EvCheck
.amFailAddr
);
3289 /* hardwires r29 and r30 -- nothing to modify. */
3292 ppPPCInstr(i
, mode64
);
3293 vpanic("mapRegs_PPCInstr");
3297 /* Generate ppc spill/reload instructions under the direction of the
3298 register allocator. Note it's critical these don't write the
3301 void genSpill_PPC ( /*OUT*/HInstr
** i1
, /*OUT*/HInstr
** i2
,
3302 HReg rreg
, Int offsetB
, Bool mode64
)
3305 vassert(!hregIsVirtual(rreg
));
3307 am
= PPCAMode_IR( offsetB
, GuestStatePtr(mode64
) );
3308 switch (hregClass(rreg
)) {
3311 *i1
= PPCInstr_Store( 8, am
, rreg
, mode64
);
3315 *i1
= PPCInstr_Store( 4, am
, rreg
, mode64
);
3318 *i1
= PPCInstr_FpLdSt ( False
/*store*/, 8, rreg
, am
);
3321 // XXX: GPR30 used as spill register to kludge AltiVec
3323 *i1
= PPCInstr_AvLdSt ( False
/*store*/, 16, rreg
, am
);
3326 ppHRegClass(hregClass(rreg
));
3327 vpanic("genSpill_PPC: unimplemented regclass");
3331 void genReload_PPC ( /*OUT*/HInstr
** i1
, /*OUT*/HInstr
** i2
,
3332 HReg rreg
, Int offsetB
, Bool mode64
)
3335 vassert(!hregIsVirtual(rreg
));
3337 am
= PPCAMode_IR( offsetB
, GuestStatePtr(mode64
) );
3338 switch (hregClass(rreg
)) {
3341 *i1
= PPCInstr_Load( 8, rreg
, am
, mode64
);
3345 *i1
= PPCInstr_Load( 4, rreg
, am
, mode64
);
3348 *i1
= PPCInstr_FpLdSt ( True
/*load*/, 8, rreg
, am
);
3351 // XXX: GPR30 used as spill register to kludge AltiVec AMode_IR
3352 *i1
= PPCInstr_AvLdSt ( True
/*load*/, 16, rreg
, am
);
3355 ppHRegClass(hregClass(rreg
));
3356 vpanic("genReload_PPC: unimplemented regclass");
3360 PPCInstr
* genMove_PPC(HReg from
, HReg to
, Bool mode64
)
3362 switch (hregClass(from
)) {
3365 return PPCInstr_Alu(Palu_OR
, to
, from
, PPCRH_Reg(from
));
3367 return PPCInstr_FpUnary(Pfp_MOV
, to
, from
);
3369 ppHRegClass(hregClass(from
));
3370 vpanic("genMove_PPC: unimplemented regclass");
3375 /* --------- The ppc assembler (bleh.) --------- */
3377 inline static UInt
iregEnc ( HReg r
, Bool mode64
)
3380 vassert(hregClass(r
) == (mode64
? HRcInt64
: HRcInt32
));
3381 vassert(!hregIsVirtual(r
));
3382 n
= hregEncoding(r
);
3387 inline static UInt
fregEnc ( HReg fr
)
3390 vassert(hregClass(fr
) == HRcFlt64
);
3391 vassert(!hregIsVirtual(fr
));
3392 n
= hregEncoding(fr
);
3397 inline static UInt
vregEnc ( HReg v
)
3400 vassert(hregClass(v
) == HRcVec128
);
3401 vassert(!hregIsVirtual(v
));
3402 n
= hregEncoding(v
);
3407 /* Emit an instruction ppc-endianly */
3408 static UChar
* emit32 ( UChar
* p
, UInt w32
, VexEndness endness_host
)
3410 if (endness_host
== VexEndnessBE
) {
3411 *p
++ = toUChar((w32
>> 24) & 0x000000FF);
3412 *p
++ = toUChar((w32
>> 16) & 0x000000FF);
3413 *p
++ = toUChar((w32
>> 8) & 0x000000FF);
3414 *p
++ = toUChar((w32
) & 0x000000FF);
3416 *p
++ = toUChar((w32
) & 0x000000FF);
3417 *p
++ = toUChar((w32
>> 8) & 0x000000FF);
3418 *p
++ = toUChar((w32
>> 16) & 0x000000FF);
3419 *p
++ = toUChar((w32
>> 24) & 0x000000FF);
3424 /* Fetch an instruction ppc-endianly */
3425 static UInt
fetch32 ( UChar
* p
, VexEndness endness_host
)
3428 if (endness_host
== VexEndnessBE
) {
3429 w32
|= ((0xFF & (UInt
)p
[0]) << 24);
3430 w32
|= ((0xFF & (UInt
)p
[1]) << 16);
3431 w32
|= ((0xFF & (UInt
)p
[2]) << 8);
3432 w32
|= ((0xFF & (UInt
)p
[3]) << 0);
3434 w32
|= ((0xFF & (UInt
)p
[3]) << 24);
3435 w32
|= ((0xFF & (UInt
)p
[2]) << 16);
3436 w32
|= ((0xFF & (UInt
)p
[1]) << 8);
3437 w32
|= ((0xFF & (UInt
)p
[0]) << 0);
3442 /* The following mkForm[...] functions refer to ppc instruction forms
3446 static UChar
* mkFormD ( UChar
* p
, UInt opc1
,
3447 UInt r1
, UInt r2
, UInt imm
, VexEndness endness_host
)
3450 vassert(opc1
< 0x40);
3454 theInstr
= ((opc1
<<26) | (r1
<<21) | (r2
<<16) | (imm
));
3455 return emit32(p
, theInstr
, endness_host
);
3458 static UChar
* mkFormMD ( UChar
* p
, UInt opc1
, UInt r1
, UInt r2
,
3459 UInt imm1
, UInt imm2
, UInt opc2
,
3460 VexEndness endness_host
)
3463 vassert(opc1
< 0x40);
3466 vassert(imm1
< 0x40);
3467 vassert(imm2
< 0x40);
3468 vassert(opc2
< 0x08);
3469 imm2
= ((imm2
& 0x1F) << 1) | (imm2
>> 5);
3470 theInstr
= ((opc1
<<26) | (r1
<<21) | (r2
<<16) |
3471 ((imm1
& 0x1F)<<11) | (imm2
<<5) |
3472 (opc2
<<2) | ((imm1
>> 5)<<1));
3473 return emit32(p
, theInstr
, endness_host
);
3476 static UChar
* mkFormX ( UChar
* p
, UInt opc1
, UInt r1
, UInt r2
,
3477 UInt r3
, UInt opc2
, UInt b0
, VexEndness endness_host
)
3480 vassert(opc1
< 0x40);
3484 vassert(opc2
< 0x400);
3486 theInstr
= ((opc1
<<26) | (r1
<<21) | (r2
<<16) |
3487 (r3
<<11) | (opc2
<<1) | (b0
));
3488 return emit32(p
, theInstr
, endness_host
);
3491 static UChar
* mkFormXO ( UChar
* p
, UInt opc1
, UInt r1
, UInt r2
,
3492 UInt r3
, UInt b10
, UInt opc2
, UInt b0
,
3493 VexEndness endness_host
)
3496 vassert(opc1
< 0x40);
3501 vassert(opc2
< 0x200);
3503 theInstr
= ((opc1
<<26) | (r1
<<21) | (r2
<<16) |
3504 (r3
<<11) | (b10
<< 10) | (opc2
<<1) | (b0
));
3505 return emit32(p
, theInstr
, endness_host
);
3508 static UChar
* mkFormX994 ( UChar
* p
, UInt inst_sel
,
3509 UInt rdst
, UInt rsrc
, VexEndness endness_host
)
3511 /* This issues an X-Form instruction with opc1 = 63 and opc2 = 994. The
3512 specific instruction is given in bits[11:15]. */
3514 vassert(inst_sel
< 0x2);
3515 vassert(rdst
< 0x20);
3516 vassert(rsrc
< 0x20);
3517 theInstr
= ((63<<26) | (rdst
<<21) | (inst_sel
<<16) | (rsrc
<<11) | (994 << 1));
3518 return emit32(p
, theInstr
, endness_host
);
3521 static UChar
* mkFormXL ( UChar
* p
, UInt opc1
, UInt f1
, UInt f2
,
3522 UInt f3
, UInt opc2
, UInt b0
, VexEndness endness_host
)
3525 vassert(opc1
< 0x40);
3529 vassert(opc2
< 0x400);
3531 theInstr
= ((opc1
<<26) | (f1
<<21) | (f2
<<16) |
3532 (f3
<<11) | (opc2
<<1) | (b0
));
3533 return emit32(p
, theInstr
, endness_host
);
3536 // Note: for split field ops, give mnemonic arg
3537 static UChar
* mkFormXFX ( UChar
* p
, UInt r1
, UInt f2
, UInt opc2
,
3538 VexEndness endness_host
)
3543 vassert(opc2
< 0x400);
3546 vassert(f2
< 0x100);
3552 vassert(f2
< 0x400);
3553 // re-arrange split field
3554 f2
= ((f2
>>5) & 0x1F) | ((f2
& 0x1F)<<5);
3556 default: vpanic("mkFormXFX(ppch)");
3558 theInstr
= ((31<<26) | (r1
<<21) | (f2
<<11) | (opc2
<<1));
3559 return emit32(p
, theInstr
, endness_host
);
3562 // Only used by mtfsf
3563 static UChar
* mkFormXFL ( UChar
* p
, UInt FM
, UInt freg
, UInt dfp_rm
,
3564 VexEndness endness_host
)
3567 vassert(FM
< 0x100);
3568 vassert(freg
< 0x20);
3569 theInstr
= ((63<<26) | (FM
<<17) | (dfp_rm
<<16) | (freg
<<11) | (711<<1));
3570 return emit32(p
, theInstr
, endness_host
);
3573 static UChar
* mkFormXS ( UChar
* p
, UInt opc1
, UInt r1
, UInt r2
,
3574 UInt imm
, UInt opc2
, UInt b0
,
3575 VexEndness endness_host
)
3578 vassert(opc1
< 0x40);
3581 vassert(imm
< 0x40);
3582 vassert(opc2
< 0x400);
3584 theInstr
= ((opc1
<<26) | (r1
<<21) | (r2
<<16) |
3585 ((imm
& 0x1F)<<11) | (opc2
<<2) | ((imm
>>5)<<1) | (b0
));
3586 return emit32(p
, theInstr
, endness_host
);
3592 static UChar
* mkFormI ( UChar
* p
, UInt LI
, UInt AA
, UInt LK
,
3593 VexEndness endness_host
)
3596 vassert(LI
< 0x1000000);
3599 theInstr
= ((18<<26) | (LI
<<2) | (AA
<<1) | (LK
));
3600 return emit32(p
, theInstr
, endness_host
);
3605 static UChar
* mkFormB ( UChar
* p
, UInt BO
, UInt BI
,
3606 UInt BD
, UInt AA
, UInt LK
, VexEndness endness_host
)
3611 vassert(BD
< 0x4000);
3614 theInstr
= ((16<<26) | (BO
<<21) | (BI
<<16) |
3615 (BD
<<2) | (AA
<<1) | (LK
));
3616 return emit32(p
, theInstr
, endness_host
);
3620 static UChar
* mkFormM ( UChar
* p
, UInt opc1
, UInt r1
, UInt r2
,
3621 UInt f3
, UInt MB
, UInt ME
, UInt Rc
,
3622 VexEndness endness_host
)
3625 vassert(opc1
< 0x40);
3632 theInstr
= ((opc1
<<26) | (r1
<<21) | (r2
<<16) |
3633 (f3
<<11) | (MB
<<6) | (ME
<<1) | (Rc
));
3634 return emit32(p
, theInstr
, endness_host
);
3637 static UChar
* mkFormA ( UChar
* p
, UInt opc1
, UInt r1
, UInt r2
,
3638 UInt r3
, UInt r4
, UInt opc2
, UInt b0
,
3639 VexEndness endness_host
)
3642 vassert(opc1
< 0x40);
3647 vassert(opc2
< 0x20);
3649 theInstr
= ((opc1
<<26) | (r1
<<21) | (r2
<<16) | (r3
<<11) |
3650 (r4
<<6) | (opc2
<<1) | (b0
));
3651 return emit32(p
, theInstr
, endness_host
);
3654 static UChar
* mkFormZ22 ( UChar
* p
, UInt opc1
, UInt r1
, UInt r2
,
3655 UInt constant
, UInt opc2
, UInt b0
,
3656 VexEndness endness_host
)
3659 vassert(opc1
< 0x40);
3662 vassert(constant
< 0x40); /* 6 bit constant */
3663 vassert(opc2
< 0x200); /* 9 bit field */
3665 theInstr
= ((opc1
<<26) | (r1
<<21) | (r2
<<16) |
3666 (constant
<<10) | (opc2
<<1) | (b0
));
3667 return emit32(p
, theInstr
, endness_host
);
3670 static UChar
* mkFormZ23 ( UChar
* p
, UInt opc1
, UInt r1
, UInt r2
,
3671 UInt r3
, UInt rmc
, UInt opc2
, UInt b0
,
3672 VexEndness endness_host
)
3675 vassert(opc1
< 0x40);
3680 vassert(opc2
< 0x100);
3682 theInstr
= ((opc1
<<26) | (r1
<<21) | (r2
<<16) |
3683 (r3
<<11) | (rmc
<<9) | (opc2
<<1) | (b0
));
3684 return emit32(p
, theInstr
, endness_host
);
3687 static UChar
* doAMode_IR ( UChar
* p
, UInt opc1
, UInt rSD
,
3688 PPCAMode
* am
, Bool mode64
, VexEndness endness_host
)
3691 vassert(am
->tag
== Pam_IR
);
3692 vassert(am
->Pam
.IR
.index
< 0x10000);
3694 rA
= iregEnc(am
->Pam
.IR
.base
, mode64
);
3695 idx
= am
->Pam
.IR
.index
;
3697 if (opc1
== 58 || opc1
== 62) { // ld/std: mode64 only
3699 /* stay sane with DS form: lowest 2 bits must be 00. This
3700 should be guaranteed to us by iselWordExpr_AMode. */
3701 vassert(0 == (idx
& 3));
3703 p
= mkFormD(p
, opc1
, rSD
, rA
, idx
, endness_host
);
3707 static UChar
* doAMode_RR ( UChar
* p
, UInt opc1
, UInt opc2
,
3708 UInt rSD
, PPCAMode
* am
, Bool mode64
,
3709 VexEndness endness_host
)
3712 vassert(am
->tag
== Pam_RR
);
3714 rA
= iregEnc(am
->Pam
.RR
.base
, mode64
);
3715 rB
= iregEnc(am
->Pam
.RR
.index
, mode64
);
3717 p
= mkFormX(p
, opc1
, rSD
, rA
, rB
, opc2
, 0, endness_host
);
3722 /* Load imm to r_dst */
3723 static UChar
* mkLoadImm ( UChar
* p
, UInt r_dst
, ULong imm
, Bool mode64
,
3724 VexEndness endness_host
)
3726 vassert(r_dst
< 0x20);
3729 /* In 32-bit mode, make sure the top 32 bits of imm are a sign
3730 extension of the bottom 32 bits, so that the range tests
3731 below work correctly. */
3732 UInt u32
= (UInt
)imm
;
3734 Long s64
= (Long
)s32
;
3738 if (imm
>= 0xFFFFFFFFFFFF8000ULL
|| imm
< 0x8000) {
3739 // sign-extendable from 16 bits
3741 // addi r_dst,0,imm => li r_dst,imm
3742 p
= mkFormD(p
, 14, r_dst
, 0, imm
& 0xFFFF, endness_host
);
3744 if (imm
>= 0xFFFFFFFF80000000ULL
|| imm
< 0x80000000ULL
) {
3745 // sign-extendable from 32 bits
3747 // addis r_dst,r0,(imm>>16) => lis r_dst, (imm>>16)
3748 p
= mkFormD(p
, 15, r_dst
, 0, (imm
>>16) & 0xFFFF, endness_host
);
3749 // ori r_dst, r_dst, (imm & 0xFFFF)
3750 p
= mkFormD(p
, 24, r_dst
, r_dst
, imm
& 0xFFFF, endness_host
);
3752 // full 64bit immediate load: 5 (five!) insns.
3757 // lis r_dst, (imm>>48) & 0xFFFF
3758 p
= mkFormD(p
, 15, r_dst
, 0, (imm
>>48) & 0xFFFF, endness_host
);
3760 // ori r_dst, r_dst, (imm>>32) & 0xFFFF
3761 if ((imm
>>32) & 0xFFFF)
3762 p
= mkFormD(p
, 24, r_dst
, r_dst
, (imm
>>32) & 0xFFFF, endness_host
);
3764 // shift r_dst low word to high word => rldicr
3765 p
= mkFormMD(p
, 30, r_dst
, r_dst
, 32, 31, 1, endness_host
);
3769 // oris r_dst, r_dst, (imm>>16) & 0xFFFF
3770 if ((imm
>>16) & 0xFFFF)
3771 p
= mkFormD(p
, 25, r_dst
, r_dst
, (imm
>>16) & 0xFFFF, endness_host
);
3773 // ori r_dst, r_dst, (imm) & 0xFFFF
3775 p
= mkFormD(p
, 24, r_dst
, r_dst
, imm
& 0xFFFF, endness_host
);
3781 /* A simplified version of mkLoadImm that always generates 2 or 5
3782 instructions (32 or 64 bits respectively) even if it could generate
3783 fewer. This is needed for generating fixed sized patchable
3785 static UChar
* mkLoadImm_EXACTLY2or5 ( UChar
* p
,
3786 UInt r_dst
, ULong imm
, Bool mode64
,
3787 VexEndness endness_host
)
3789 vassert(r_dst
< 0x20);
3792 /* In 32-bit mode, make sure the top 32 bits of imm are a sign
3793 extension of the bottom 32 bits. (Probably unnecessary.) */
3794 UInt u32
= (UInt
)imm
;
3796 Long s64
= (Long
)s32
;
3801 // addis r_dst,r0,(imm>>16) => lis r_dst, (imm>>16)
3802 p
= mkFormD(p
, 15, r_dst
, 0, (imm
>>16) & 0xFFFF, endness_host
);
3803 // ori r_dst, r_dst, (imm & 0xFFFF)
3804 p
= mkFormD(p
, 24, r_dst
, r_dst
, imm
& 0xFFFF, endness_host
);
3807 // full 64bit immediate load: 5 (five!) insns.
3810 // lis r_dst, (imm>>48) & 0xFFFF
3811 p
= mkFormD(p
, 15, r_dst
, 0, (imm
>>48) & 0xFFFF, endness_host
);
3813 // ori r_dst, r_dst, (imm>>32) & 0xFFFF
3814 p
= mkFormD(p
, 24, r_dst
, r_dst
, (imm
>>32) & 0xFFFF, endness_host
);
3816 // shift r_dst low word to high word => rldicr
3817 p
= mkFormMD(p
, 30, r_dst
, r_dst
, 32, 31, 1, endness_host
);
3820 // oris r_dst, r_dst, (imm>>16) & 0xFFFF
3821 p
= mkFormD(p
, 25, r_dst
, r_dst
, (imm
>>16) & 0xFFFF, endness_host
);
3823 // ori r_dst, r_dst, (imm) & 0xFFFF
3824 p
= mkFormD(p
, 24, r_dst
, r_dst
, imm
& 0xFFFF, endness_host
);
3829 /* Checks whether the sequence of bytes at p was indeed created
3830 by mkLoadImm_EXACTLY2or5 with the given parameters. */
3831 static Bool
isLoadImm_EXACTLY2or5 ( UChar
* p_to_check
,
3832 UInt r_dst
, ULong imm
, Bool mode64
,
3833 VexEndness endness_host
)
3835 vassert(r_dst
< 0x20);
3838 /* In 32-bit mode, make sure the top 32 bits of imm are a sign
3839 extension of the bottom 32 bits. (Probably unnecessary.) */
3840 UInt u32
= (UInt
)imm
;
3842 Long s64
= (Long
)s32
;
3847 UInt expect
[2] = { 0, 0 };
3848 UChar
* p
= (UChar
*)&expect
[0];
3849 // addis r_dst,r0,(imm>>16) => lis r_dst, (imm>>16)
3850 p
= mkFormD(p
, 15, r_dst
, 0, (imm
>>16) & 0xFFFF, endness_host
);
3851 // ori r_dst, r_dst, (imm & 0xFFFF)
3852 p
= mkFormD(p
, 24, r_dst
, r_dst
, imm
& 0xFFFF, endness_host
);
3853 vassert(p
== (UChar
*)&expect
[2]);
3855 return fetch32(p_to_check
+ 0, endness_host
) == expect
[0]
3856 && fetch32(p_to_check
+ 4, endness_host
) == expect
[1];
3859 UInt expect
[5] = { 0, 0, 0, 0, 0 };
3860 UChar
* p
= (UChar
*)&expect
[0];
3861 // full 64bit immediate load: 5 (five!) insns.
3864 // lis r_dst, (imm>>48) & 0xFFFF
3865 p
= mkFormD(p
, 15, r_dst
, 0, (imm
>>48) & 0xFFFF, endness_host
);
3867 // ori r_dst, r_dst, (imm>>32) & 0xFFFF
3868 p
= mkFormD(p
, 24, r_dst
, r_dst
, (imm
>>32) & 0xFFFF, endness_host
);
3870 // shift r_dst low word to high word => rldicr
3871 p
= mkFormMD(p
, 30, r_dst
, r_dst
, 32, 31, 1, endness_host
);
3874 // oris r_dst, r_dst, (imm>>16) & 0xFFFF
3875 p
= mkFormD(p
, 25, r_dst
, r_dst
, (imm
>>16) & 0xFFFF, endness_host
);
3877 // ori r_dst, r_dst, (imm) & 0xFFFF
3878 p
= mkFormD(p
, 24, r_dst
, r_dst
, imm
& 0xFFFF, endness_host
);
3880 vassert(p
== (UChar
*)&expect
[5]);
3882 return fetch32(p_to_check
+ 0, endness_host
) == expect
[0]
3883 && fetch32(p_to_check
+ 4, endness_host
) == expect
[1]
3884 && fetch32(p_to_check
+ 8, endness_host
) == expect
[2]
3885 && fetch32(p_to_check
+ 12, endness_host
) == expect
[3]
3886 && fetch32(p_to_check
+ 16, endness_host
) == expect
[4];
3891 /* Generate a machine-word sized load or store. Simplified version of
3892 the Pin_Load and Pin_Store cases below. */
3893 static UChar
* do_load_or_store_machine_word (
3894 UChar
* p
, Bool isLoad
,
3895 UInt reg
, PPCAMode
* am
, Bool mode64
, VexEndness endness_host
)
3898 UInt opc1
, sz
= mode64
? 8 : 4;
3902 vassert(0 == (am
->Pam
.IR
.index
& 3));
3905 case 4: opc1
= 32; vassert(!mode64
); break;
3906 case 8: opc1
= 58; vassert(mode64
); break;
3907 default: vassert(0);
3909 p
= doAMode_IR(p
, opc1
, reg
, am
, mode64
, endness_host
);
3912 /* we could handle this case, but we don't expect to ever
3919 UInt opc1
, sz
= mode64
? 8 : 4;
3923 vassert(0 == (am
->Pam
.IR
.index
& 3));
3926 case 4: opc1
= 36; vassert(!mode64
); break;
3927 case 8: opc1
= 62; vassert(mode64
); break;
3928 default: vassert(0);
3930 p
= doAMode_IR(p
, opc1
, reg
, am
, mode64
, endness_host
);
3933 /* we could handle this case, but we don't expect to ever
3943 /* Generate a 32-bit sized load or store. Simplified version of
3944 do_load_or_store_machine_word above. */
3945 static UChar
* do_load_or_store_word32 (
3946 UChar
* p
, Bool isLoad
,
3947 UInt reg
, PPCAMode
* am
, Bool mode64
, VexEndness endness_host
)
3954 vassert(0 == (am
->Pam
.IR
.index
& 3));
3957 p
= doAMode_IR(p
, opc1
, reg
, am
, mode64
, endness_host
);
3960 /* we could handle this case, but we don't expect to ever
3971 vassert(0 == (am
->Pam
.IR
.index
& 3));
3974 p
= doAMode_IR(p
, opc1
, reg
, am
, mode64
, endness_host
);
3977 /* we could handle this case, but we don't expect to ever
3987 /* Move r_dst to r_src */
3988 static UChar
* mkMoveReg ( UChar
* p
, UInt r_dst
, UInt r_src
,
3989 VexEndness endness_host
)
3991 vassert(r_dst
< 0x20);
3992 vassert(r_src
< 0x20);
3994 if (r_dst
!= r_src
) {
3995 /* or r_dst, r_src, r_src */
3996 p
= mkFormX(p
, 31, r_src
, r_dst
, r_src
, 444, 0, endness_host
);
4001 static UChar
* mkFormVX ( UChar
* p
, UInt opc1
, UInt r1
, UInt r2
,
4002 UInt r3
, UInt opc2
, VexEndness endness_host
)
4005 vassert(opc1
< 0x40);
4009 vassert(opc2
< 0x800);
4010 theInstr
= ((opc1
<<26) | (r1
<<21) | (r2
<<16) | (r3
<<11) | opc2
);
4011 return emit32(p
, theInstr
, endness_host
);
4014 static UChar
* mkFormVSXRND ( UChar
* p
, UInt opc1
, UInt R
, UInt r1
,
4015 UInt r2
, UInt RMC
, UInt opc2
, UChar EX
,
4016 VexEndness endness_host
)
4018 /* The register mapping is all done using VR register numbers for the
4019 * V128 support. This means that the operands for this instruction have
4020 * been loaded into a VR register. The 32 VR registers map to VSR registers
4021 * 32 to 63. For these instructions, the hardware adds 32 to the source
4022 * and destination register numbers. Do not need to adjust the register
4023 * numbers for these instructions.
4028 vassert(opc1
< 0x40);
4031 vassert(opc2
< 0x100);
4036 theInstr
= ((opc1
<<26) | (r1
<<21) | (R
<<16) | (r2
<<11) | (RMC
<<9) |
4038 return emit32(p
, theInstr
, endness_host
);
4041 static UChar
* mkFormVX_BX_TX ( UChar
* p
, UInt opc1
, UInt r1
, UInt r2
,
4042 UInt r3
, UInt opc2
, VexEndness endness_host
)
4044 /* The register mapping is all done using VR register numbers for the
4045 * V128 support. This means that the operands for this instruction have
4046 * been loaded into a VR register. The 32 VR registers map to VSR registers
4047 * 32 to 63. So to make the issued instruction reference the
4048 * corresponding VR register we have to add 32 to the source and
4049 * destination operand numbers, then load the new operand number into the
4050 * correct bit fields.
4052 * r1 = 32xTX + T; r3 = 32xBX + B;
4053 * TX is bit 0, BX is bit 1, T is in bits [25:21], B is in bit [14:11]
4054 * opc2 is in bits [10:2]
4060 r1
+= 32; // adjust the VSR register number to map to the VR number
4063 vassert(opc1
< 0x40);
4067 vassert(opc2
< 0x800);
4073 theInstr
= ((opc1
<<26) | (T
<<21) | (r2
<<16) | (B
<<11) | (opc2
<<2)
4075 return emit32(p
, theInstr
, endness_host
);
4078 static UChar
* mkFormVXR0 ( UChar
* p
, UInt opc1
, UInt r1
, UInt r2
,
4079 UInt r3
, UInt opc2
, UChar R0
,
4080 VexEndness endness_host
)
4082 /* The register mapping is all done using VR register numbers for the
4083 * V128 support. This means that the operands for this instruction have
4084 * been loaded into a VR register. The 32 VR registers map to VSR registers
4085 * 32 to 63. For these instructions, the hardware adds 32 to the source
4086 * and destination register numbers. Do not need to adjust the register
4087 * numbers for these instructions.
4092 vassert(opc1
< 0x40);
4093 vassert(r1
< 0x20); // register numbers are between 0 and 31 (5-bits)
4096 vassert(opc2
< 0x800);
4099 theInstr
= ((opc1
<<26) | (r1
<<21) | (r2
<<16) | (r3
<<11) | (opc2
<<1) | R0
);
4100 return emit32(p
, theInstr
, endness_host
);
4103 static UChar
* mkFormVXI ( UChar
* p
, UInt opc1
, UInt r1
, UInt r2
,
4104 UInt r3
, UInt opc2
, VexEndness endness_host
)
4107 vassert(opc1
< 0x40);
4111 vassert(opc2
< 0x27);
4112 theInstr
= ((opc1
<<26) | (r1
<<21) | (r2
<<16) | (r3
<<11) | opc2
<<1);
4113 return emit32(p
, theInstr
, endness_host
);
4116 static UChar
* mkFormVXR ( UChar
* p
, UInt opc1
, UInt r1
, UInt r2
,
4117 UInt r3
, UInt Rc
, UInt opc2
,
4118 VexEndness endness_host
)
4121 vassert(opc1
< 0x40);
4126 vassert(opc2
< 0x400);
4127 theInstr
= ((opc1
<<26) | (r1
<<21) | (r2
<<16) |
4128 (r3
<<11) | (Rc
<<10) | opc2
);
4129 return emit32(p
, theInstr
, endness_host
);
4132 static UChar
* mkFormVA ( UChar
* p
, UInt opc1
, UInt r1
, UInt r2
,
4133 UInt r3
, UInt r4
, UInt opc2
, VexEndness endness_host
)
4136 vassert(opc1
< 0x40);
4141 vassert(opc2
< 0x40);
4142 theInstr
= ((opc1
<<26) | (r1
<<21) | (r2
<<16) |
4143 (r3
<<11) | (r4
<<6) | opc2
);
4144 return emit32(p
, theInstr
, endness_host
);
4149 /* Emit an instruction into buf and return the number of bytes used.
4150 Note that buf is not the insn's final place, and therefore it is
4151 imperative to emit position-independent code. If the emitted
4152 instruction was a profiler inc, set *is_profInc to True, else leave
4155 Int
emit_PPCInstr ( /*MB_MOD*/Bool
* is_profInc
,
4156 UChar
* buf
, Int nbuf
, const PPCInstr
* i
,
4157 Bool mode64
, VexEndness endness_host
,
4158 const void* disp_cp_chain_me_to_slowEP
,
4159 const void* disp_cp_chain_me_to_fastEP
,
4160 const void* disp_cp_xindir
,
4161 const void* disp_cp_xassisted
)
4164 vassert(nbuf
>= 32);
4167 vex_printf("asm ");ppPPCInstr(i
, mode64
); vex_printf("\n");
4173 p
= mkLoadImm(p
, iregEnc(i
->Pin
.LI
.dst
, mode64
),
4174 i
->Pin
.LI
.imm64
, mode64
, endness_host
);
4178 PPCRH
* srcR
= i
->Pin
.Alu
.srcR
;
4179 Bool immR
= toBool(srcR
->tag
== Prh_Imm
);
4180 UInt r_dst
= iregEnc(i
->Pin
.Alu
.dst
, mode64
);
4181 UInt r_srcL
= iregEnc(i
->Pin
.Alu
.srcL
, mode64
);
4182 UInt r_srcR
= immR
? (-1)/*bogus*/ :
4183 iregEnc(srcR
->Prh
.Reg
.reg
, mode64
);
4185 switch (i
->Pin
.Alu
.op
) {
4188 /* addi (PPC32 p350) */
4189 vassert(srcR
->Prh
.Imm
.syned
);
4190 vassert(srcR
->Prh
.Imm
.imm16
!= 0x8000);
4191 p
= mkFormD(p
, 14, r_dst
, r_srcL
, srcR
->Prh
.Imm
.imm16
, endness_host
);
4193 /* add (PPC32 p347) */
4194 p
= mkFormXO(p
, 31, r_dst
, r_srcL
, r_srcR
, 0, 266, 0, endness_host
);
4200 /* addi (PPC32 p350), but with negated imm */
4201 vassert(srcR
->Prh
.Imm
.syned
);
4202 vassert(srcR
->Prh
.Imm
.imm16
!= 0x8000);
4203 p
= mkFormD(p
, 14, r_dst
, r_srcL
, (- srcR
->Prh
.Imm
.imm16
),
4206 /* subf (PPC32 p537), with args the "wrong" way round */
4207 p
= mkFormXO(p
, 31, r_dst
, r_srcR
, r_srcL
, 0, 40, 0, endness_host
);
4213 /* andi. (PPC32 p358) */
4214 vassert(!srcR
->Prh
.Imm
.syned
);
4215 p
= mkFormD(p
, 28, r_srcL
, r_dst
, srcR
->Prh
.Imm
.imm16
, endness_host
);
4217 /* and (PPC32 p356) */
4218 p
= mkFormX(p
, 31, r_srcL
, r_dst
, r_srcR
, 28, 0, endness_host
);
4224 /* ori (PPC32 p497) */
4225 vassert(!srcR
->Prh
.Imm
.syned
);
4226 p
= mkFormD(p
, 24, r_srcL
, r_dst
, srcR
->Prh
.Imm
.imm16
, endness_host
);
4228 /* or (PPC32 p495) */
4229 p
= mkFormX(p
, 31, r_srcL
, r_dst
, r_srcR
, 444, 0, endness_host
);
4235 /* xori (PPC32 p550) */
4236 vassert(!srcR
->Prh
.Imm
.syned
);
4237 p
= mkFormD(p
, 26, r_srcL
, r_dst
, srcR
->Prh
.Imm
.imm16
, endness_host
);
4239 /* xor (PPC32 p549) */
4240 p
= mkFormX(p
, 31, r_srcL
, r_dst
, r_srcR
, 316, 0, endness_host
);
4251 PPCRH
* srcR
= i
->Pin
.Shft
.srcR
;
4252 Bool sz32
= i
->Pin
.Shft
.sz32
;
4253 Bool immR
= toBool(srcR
->tag
== Prh_Imm
);
4254 UInt r_dst
= iregEnc(i
->Pin
.Shft
.dst
, mode64
);
4255 UInt r_srcL
= iregEnc(i
->Pin
.Shft
.srcL
, mode64
);
4256 UInt r_srcR
= immR
? (-1)/*bogus*/ :
4257 iregEnc(srcR
->Prh
.Reg
.reg
, mode64
);
4261 switch (i
->Pin
.Shft
.op
) {
4265 /* rd = rs << n, 1 <= n <= 31
4267 rlwinm rd,rs,n,0,31-n (PPC32 p501)
4269 UInt n
= srcR
->Prh
.Imm
.imm16
;
4270 vassert(!srcR
->Prh
.Imm
.syned
);
4271 vassert(n
> 0 && n
< 32);
4272 p
= mkFormM(p
, 21, r_srcL
, r_dst
, n
, 0, 31-n
, 0, endness_host
);
4274 /* slw (PPC32 p505) */
4275 p
= mkFormX(p
, 31, r_srcL
, r_dst
, r_srcR
, 24, 0, endness_host
);
4279 /* rd = rs << n, 1 <= n <= 63
4281 rldicr rd,rs,n,63-n (PPC64 p559)
4283 UInt n
= srcR
->Prh
.Imm
.imm16
;
4284 vassert(!srcR
->Prh
.Imm
.syned
);
4285 vassert(n
> 0 && n
< 64);
4286 p
= mkFormMD(p
, 30, r_srcL
, r_dst
, n
, 63-n
, 1, endness_host
);
4288 /* sld (PPC64 p568) */
4289 p
= mkFormX(p
, 31, r_srcL
, r_dst
, r_srcR
, 27, 0, endness_host
);
4297 /* rd = rs >>u n, 1 <= n <= 31
4299 rlwinm rd,rs,32-n,n,31 (PPC32 p501)
4301 UInt n
= srcR
->Prh
.Imm
.imm16
;
4302 vassert(!srcR
->Prh
.Imm
.syned
);
4303 vassert(n
> 0 && n
< 32);
4304 p
= mkFormM(p
, 21, r_srcL
, r_dst
, 32-n
, n
, 31, 0, endness_host
);
4306 /* srw (PPC32 p508) */
4307 p
= mkFormX(p
, 31, r_srcL
, r_dst
, r_srcR
, 536, 0, endness_host
);
4311 /* rd = rs >>u n, 1 <= n <= 63
4313 rldicl rd,rs,64-n,n (PPC64 p558)
4315 UInt n
= srcR
->Prh
.Imm
.imm16
;
4316 vassert(!srcR
->Prh
.Imm
.syned
);
4317 vassert(n
> 0 && n
< 64);
4318 p
= mkFormMD(p
, 30, r_srcL
, r_dst
, 64-n
, n
, 0, endness_host
);
4320 /* srd (PPC64 p574) */
4321 p
= mkFormX(p
, 31, r_srcL
, r_dst
, r_srcR
, 539, 0, endness_host
);
4329 /* srawi (PPC32 p507) */
4330 UInt n
= srcR
->Prh
.Imm
.imm16
;
4331 vassert(!srcR
->Prh
.Imm
.syned
);
4332 /* In 64-bit mode, we allow right shifts by zero bits
4333 as that is a handy way to sign extend the lower 32
4334 bits into the upper 32 bits. */
4338 vassert(n
> 0 && n
< 32);
4339 p
= mkFormX(p
, 31, r_srcL
, r_dst
, n
, 824, 0, endness_host
);
4341 /* sraw (PPC32 p506) */
4342 p
= mkFormX(p
, 31, r_srcL
, r_dst
, r_srcR
, 792, 0, endness_host
);
4346 /* sradi (PPC64 p571) */
4347 UInt n
= srcR
->Prh
.Imm
.imm16
;
4348 vassert(!srcR
->Prh
.Imm
.syned
);
4349 vassert(n
> 0 && n
< 64);
4350 p
= mkFormXS(p
, 31, r_srcL
, r_dst
, n
, 413, 0, endness_host
);
4352 /* srad (PPC32 p570) */
4353 p
= mkFormX(p
, 31, r_srcL
, r_dst
, r_srcR
, 794, 0, endness_host
);
4365 Bool isAdd
= i
->Pin
.AddSubC
.isAdd
;
4366 Bool setC
= i
->Pin
.AddSubC
.setC
;
4367 UInt r_srcL
= iregEnc(i
->Pin
.AddSubC
.srcL
, mode64
);
4368 UInt r_srcR
= iregEnc(i
->Pin
.AddSubC
.srcR
, mode64
);
4369 UInt r_dst
= iregEnc(i
->Pin
.AddSubC
.dst
, mode64
);
4372 if (setC
) /* addc (PPC32 p348) */
4373 p
= mkFormXO(p
, 31, r_dst
, r_srcL
, r_srcR
, 0, 10, 0, endness_host
);
4374 else /* adde (PPC32 p349) */
4375 p
= mkFormXO(p
, 31, r_dst
, r_srcL
, r_srcR
, 0, 138, 0, endness_host
);
4377 /* subfX, with args the "wrong" way round */
4378 if (setC
) /* subfc (PPC32 p538) */
4379 p
= mkFormXO(p
, 31, r_dst
, r_srcR
, r_srcL
, 0, 8, 0, endness_host
);
4380 else /* subfe (PPC32 p539) */
4381 p
= mkFormXO(p
, 31, r_dst
, r_srcR
, r_srcL
, 0, 136, 0, endness_host
);
4387 Bool syned
= i
->Pin
.Cmp
.syned
;
4388 Bool sz32
= i
->Pin
.Cmp
.sz32
;
4389 UInt fld1
= i
->Pin
.Cmp
.crfD
<< 2;
4390 UInt r_srcL
= iregEnc(i
->Pin
.Cmp
.srcL
, mode64
);
4391 UInt r_srcR
, imm_srcR
;
4392 PPCRH
* srcR
= i
->Pin
.Cmp
.srcR
;
4394 if (!mode64
) // cmp double word invalid for mode32
4396 else if (!sz32
) // mode64 && cmp64: set L=1
4399 switch (srcR
->tag
) {
4401 vassert(syned
== srcR
->Prh
.Imm
.syned
);
4402 imm_srcR
= srcR
->Prh
.Imm
.imm16
;
4403 if (syned
) { // cmpw/di (signed) (PPC32 p368)
4404 vassert(imm_srcR
!= 0x8000);
4405 p
= mkFormD(p
, 11, fld1
, r_srcL
, imm_srcR
, endness_host
);
4406 } else { // cmplw/di (unsigned) (PPC32 p370)
4407 p
= mkFormD(p
, 10, fld1
, r_srcL
, imm_srcR
, endness_host
);
4411 r_srcR
= iregEnc(srcR
->Prh
.Reg
.reg
, mode64
);
4412 if (syned
) // cmpwi (signed) (PPC32 p367)
4413 p
= mkFormX(p
, 31, fld1
, r_srcL
, r_srcR
, 0, 0, endness_host
);
4414 else // cmplwi (unsigned) (PPC32 p379)
4415 p
= mkFormX(p
, 31, fld1
, r_srcL
, r_srcR
, 32, 0, endness_host
);
4424 UInt r_dst
= iregEnc(i
->Pin
.Unary
.dst
, mode64
);
4425 UInt r_src
= iregEnc(i
->Pin
.Unary
.src
, mode64
);
4427 switch (i
->Pin
.Unary
.op
) {
4428 case Pun_NOT
: // nor r_dst,r_src,r_src
4429 p
= mkFormX(p
, 31, r_src
, r_dst
, r_src
, 124, 0, endness_host
);
4431 case Pun_NEG
: // neg r_dst,r_src
4432 p
= mkFormXO(p
, 31, r_dst
, r_src
, 0, 0, 104, 0, endness_host
);
4434 case Pun_CLZ32
: // cntlzw r_dst, r_src
4435 p
= mkFormX(p
, 31, r_src
, r_dst
, 0, 26, 0, endness_host
);
4437 case Pun_CLZ64
: // cntlzd r_dst, r_src
4439 p
= mkFormX(p
, 31, r_src
, r_dst
, 0, 58, 0, endness_host
);
4441 case Pun_EXTSW
: // extsw r_dst, r_src
4443 p
= mkFormX(p
, 31, r_src
, r_dst
, 0, 986, 0, endness_host
);
4445 case Pun_POP32
: // popcntw r_dst, r_src
4446 p
= mkFormX(p
, 31, r_src
, r_dst
, 0, 378, 0, endness_host
);
4448 case Pun_POP64
: // popcntd r_dst, r_src
4450 p
= mkFormX(p
, 31, r_src
, r_dst
, 0, 506, 0, endness_host
);
4459 Bool syned
= i
->Pin
.MulL
.syned
;
4460 Bool sz32
= i
->Pin
.MulL
.sz32
;
4461 UInt r_dst
= iregEnc(i
->Pin
.MulL
.dst
, mode64
);
4462 UInt r_srcL
= iregEnc(i
->Pin
.MulL
.srcL
, mode64
);
4463 UInt r_srcR
= iregEnc(i
->Pin
.MulL
.srcR
, mode64
);
4468 if (i
->Pin
.MulL
.hi
) {
4469 // mul hi words, must consider sign
4471 if (syned
) // mulhw r_dst,r_srcL,r_srcR
4472 p
= mkFormXO(p
, 31, r_dst
, r_srcL
, r_srcR
, 0, 75, 0,
4474 else // mulhwu r_dst,r_srcL,r_srcR
4475 p
= mkFormXO(p
, 31, r_dst
, r_srcL
, r_srcR
, 0, 11, 0,
4478 if (syned
) // mulhd r_dst,r_srcL,r_srcR
4479 p
= mkFormXO(p
, 31, r_dst
, r_srcL
, r_srcR
, 0, 73, 0,
4481 else // mulhdu r_dst,r_srcL,r_srcR
4482 p
= mkFormXO(p
, 31, r_dst
, r_srcL
, r_srcR
, 0, 9, 0, endness_host
);
4485 // mul low word, sign is irrelevant
4486 vassert(!i
->Pin
.MulL
.syned
);
4487 if (sz32
) // mullw r_dst,r_srcL,r_srcR
4488 p
= mkFormXO(p
, 31, r_dst
, r_srcL
, r_srcR
, 0, 235, 0, endness_host
);
4489 else // mulld r_dst,r_srcL,r_srcR
4490 p
= mkFormXO(p
, 31, r_dst
, r_srcL
, r_srcR
, 0, 233, 0, endness_host
);
4496 Bool syned
= i
->Pin
.Div
.syned
;
4497 Bool sz32
= i
->Pin
.Div
.sz32
;
4498 UInt r_dst
= iregEnc(i
->Pin
.Div
.dst
, mode64
);
4499 UInt r_srcL
= iregEnc(i
->Pin
.Div
.srcL
, mode64
);
4500 UInt r_srcR
= iregEnc(i
->Pin
.Div
.srcR
, mode64
);
4505 if (i
->Pin
.Div
.extended
) {
4508 // divwe r_dst,r_srcL,r_srcR
4509 p
= mkFormXO(p
, 31, r_dst
, r_srcL
, r_srcR
, 0, 427, 0,
4512 // divweu r_dst,r_srcL,r_srcR
4513 p
= mkFormXO(p
, 31, r_dst
, r_srcL
, r_srcR
, 0, 395, 0,
4517 // divde r_dst,r_srcL,r_srcR
4518 p
= mkFormXO(p
, 31, r_dst
, r_srcL
, r_srcR
, 0, 425, 0,
4521 // divdeu r_dst,r_srcL,r_srcR
4522 p
= mkFormXO(p
, 31, r_dst
, r_srcL
, r_srcR
, 0, 393, 0,
4526 if (syned
) // divw r_dst,r_srcL,r_srcR
4527 p
= mkFormXO(p
, 31, r_dst
, r_srcL
, r_srcR
, 0, 491, 0, endness_host
);
4528 else // divwu r_dst,r_srcL,r_srcR
4529 p
= mkFormXO(p
, 31, r_dst
, r_srcL
, r_srcR
, 0, 459, 0, endness_host
);
4531 if (syned
) // divd r_dst,r_srcL,r_srcR
4532 p
= mkFormXO(p
, 31, r_dst
, r_srcL
, r_srcR
, 0, 489, 0, endness_host
);
4533 else // divdu r_dst,r_srcL,r_srcR
4534 p
= mkFormXO(p
, 31, r_dst
, r_srcL
, r_srcR
, 0, 457, 0, endness_host
);
4540 if (i
->Pin
.Call
.cond
.test
!= Pct_ALWAYS
4541 && i
->Pin
.Call
.rloc
.pri
!= RLPri_None
) {
4542 /* The call might not happen (it isn't unconditional) and it
4543 returns a result. In this case we will need to generate a
4544 control flow diamond to put 0x555..555 in the return
4545 register(s) in the case where the call doesn't happen. If
4546 this ever becomes necessary, maybe copy code from the ARM
4547 equivalent. Until that day, just give up. */
4550 PPCCondCode cond
= i
->Pin
.Call
.cond
;
4552 /* As per detailed comment for Pin_Call in
4553 getRegUsage_PPCInstr above, %r10 is used as an address temp */
4555 /* jump over the following insns if condition does not hold */
4557 if (cond
.test
!= Pct_ALWAYS
) {
4558 /* jmp fwds if !condition */
4559 /* don't know how many bytes to jump over yet...
4560 make space for a jump instruction and fill in later. */
4561 ptmp
= p
; /* fill in this bit later */
4565 /* load target to r_dst */ // p += 4|8|20
4566 p
= mkLoadImm(p
, r_dst
, i
->Pin
.Call
.target
, mode64
, endness_host
);
4568 /* mtspr 9,r_dst => move r_dst to count register */
4569 p
= mkFormXFX(p
, r_dst
, 9, 467, endness_host
); // p += 4
4571 /* bctrl => branch to count register (and save to lr) */
4572 p
= mkFormXL(p
, 19, Pct_ALWAYS
, 0, 0, 528, 1, endness_host
); // p += 4
4574 /* Fix up the conditional jump, if there was one. */
4575 if (cond
.test
!= Pct_ALWAYS
) {
4576 Int delta
= p
- ptmp
;
4577 vassert(delta
>= 16 && delta
<= 32);
4578 /* bc !ct,cf,delta */
4579 mkFormB(ptmp
, invertCondTest(cond
.test
),
4580 cond
.flag
, (delta
>>2), 0, 0, endness_host
);
4586 /* NB: what goes on here has to be very closely coordinated
4587 with the chainXDirect_PPC and unchainXDirect_PPC below. */
4588 /* We're generating chain-me requests here, so we need to be
4589 sure this is actually allowed -- no-redir translations
4590 can't use chain-me's. Hence: */
4591 vassert(disp_cp_chain_me_to_slowEP
!= NULL
);
4592 vassert(disp_cp_chain_me_to_fastEP
!= NULL
);
4594 /* First off, if this is conditional, create a conditional jump
4595 over the rest of it. Or at least, leave a space for it that
4596 we will shortly fill in. */
4598 if (i
->Pin
.XDirect
.cond
.test
!= Pct_ALWAYS
) {
4599 vassert(i
->Pin
.XDirect
.cond
.flag
!= Pcf_NONE
);
4603 vassert(i
->Pin
.XDirect
.cond
.flag
== Pcf_NONE
);
4606 /* Update the guest CIA. */
4607 /* imm32/64 r30, dstGA */
4608 if (!mode64
) vassert(0 == (((ULong
)i
->Pin
.XDirect
.dstGA
) >> 32));
4609 p
= mkLoadImm(p
, /*r*/30, (ULong
)i
->Pin
.XDirect
.dstGA
, mode64
,
4611 /* stw/std r30, amCIA */
4612 p
= do_load_or_store_machine_word(
4613 p
, False
/*!isLoad*/,
4614 /*r*/30, i
->Pin
.XDirect
.amCIA
, mode64
, endness_host
4617 /* --- FIRST PATCHABLE BYTE follows --- */
4618 /* VG_(disp_cp_chain_me_to_{slowEP,fastEP}) (where we're calling
4619 to) backs up the return address, so as to find the address of
4620 the first patchable byte. So: don't change the number of
4621 instructions (32-bit: 4, 64-bit: 7) below. */
4622 /* imm32/64-fixed r30, VG_(disp_cp_chain_me_to_{slowEP,fastEP} */
4623 const void* disp_cp_chain_me
4624 = i
->Pin
.XDirect
.toFastEP
? disp_cp_chain_me_to_fastEP
4625 : disp_cp_chain_me_to_slowEP
;
4626 p
= mkLoadImm_EXACTLY2or5(
4627 p
, /*r*/30, (Addr
)disp_cp_chain_me
, mode64
, endness_host
);
4629 p
= mkFormXFX(p
, /*r*/30, 9, 467, endness_host
);
4631 p
= mkFormXL(p
, 19, Pct_ALWAYS
, 0, 0, 528, 1, endness_host
);
4632 /* --- END of PATCHABLE BYTES --- */
4634 /* Fix up the conditional jump, if there was one. */
4635 if (i
->Pin
.XDirect
.cond
.test
!= Pct_ALWAYS
) {
4636 Int delta
= p
- ptmp
;
4637 vassert(delta
>= 16 && delta
<= 64 && 0 == (delta
& 3));
4638 /* bc !ct,cf,delta */
4639 mkFormB(ptmp
, invertCondTest(i
->Pin
.XDirect
.cond
.test
),
4640 i
->Pin
.XDirect
.cond
.flag
, (delta
>>2), 0, 0, endness_host
);
4646 /* We're generating transfers that could lead indirectly to a
4647 chain-me, so we need to be sure this is actually allowed --
4648 no-redir translations are not allowed to reach normal
4649 translations without going through the scheduler. That means
4650 no XDirects or XIndirs out from no-redir translations.
4652 vassert(disp_cp_xindir
!= NULL
);
4654 /* First off, if this is conditional, create a conditional jump
4655 over the rest of it. Or at least, leave a space for it that
4656 we will shortly fill in. */
4658 if (i
->Pin
.XIndir
.cond
.test
!= Pct_ALWAYS
) {
4659 vassert(i
->Pin
.XIndir
.cond
.flag
!= Pcf_NONE
);
4663 vassert(i
->Pin
.XIndir
.cond
.flag
== Pcf_NONE
);
4666 /* Update the guest CIA. */
4667 /* stw/std r-dstGA, amCIA */
4668 p
= do_load_or_store_machine_word(
4669 p
, False
/*!isLoad*/,
4670 iregEnc(i
->Pin
.XIndir
.dstGA
, mode64
),
4671 i
->Pin
.XIndir
.amCIA
, mode64
, endness_host
4674 /* imm32/64 r30, VG_(disp_cp_xindir) */
4675 p
= mkLoadImm(p
, /*r*/30, (ULong
)(Addr
)disp_cp_xindir
, mode64
,
4678 p
= mkFormXFX(p
, /*r*/30, 9, 467, endness_host
);
4680 p
= mkFormXL(p
, 19, Pct_ALWAYS
, 0, 0, 528, 0, endness_host
);
4682 /* Fix up the conditional jump, if there was one. */
4683 if (i
->Pin
.XIndir
.cond
.test
!= Pct_ALWAYS
) {
4684 Int delta
= p
- ptmp
;
4685 vassert(delta
>= 16 && delta
<= 32 && 0 == (delta
& 3));
4686 /* bc !ct,cf,delta */
4687 mkFormB(ptmp
, invertCondTest(i
->Pin
.XIndir
.cond
.test
),
4688 i
->Pin
.XIndir
.cond
.flag
, (delta
>>2), 0, 0, endness_host
);
4693 case Pin_XAssisted
: {
4694 /* First off, if this is conditional, create a conditional jump
4695 over the rest of it. Or at least, leave a space for it that
4696 we will shortly fill in. */
4698 if (i
->Pin
.XAssisted
.cond
.test
!= Pct_ALWAYS
) {
4699 vassert(i
->Pin
.XAssisted
.cond
.flag
!= Pcf_NONE
);
4703 vassert(i
->Pin
.XAssisted
.cond
.flag
== Pcf_NONE
);
4706 /* Update the guest CIA. */
4707 /* stw/std r-dstGA, amCIA */
4708 p
= do_load_or_store_machine_word(
4709 p
, False
/*!isLoad*/,
4710 iregEnc(i
->Pin
.XIndir
.dstGA
, mode64
),
4711 i
->Pin
.XIndir
.amCIA
, mode64
, endness_host
4714 /* imm32/64 r31, $magic_number */
4716 switch (i
->Pin
.XAssisted
.jk
) {
4717 case Ijk_ClientReq
: trcval
= VEX_TRC_JMP_CLIENTREQ
; break;
4718 case Ijk_Sys_syscall
: trcval
= VEX_TRC_JMP_SYS_SYSCALL
; break;
4719 //case Ijk_Sys_int128: trcval = VEX_TRC_JMP_SYS_INT128; break;
4720 //case Ijk_Yield: trcval = VEX_TRC_JMP_YIELD; break;
4721 case Ijk_EmWarn
: trcval
= VEX_TRC_JMP_EMWARN
; break;
4722 case Ijk_EmFail
: trcval
= VEX_TRC_JMP_EMFAIL
; break;
4723 //case Ijk_MapFail: trcval = VEX_TRC_JMP_MAPFAIL; break;
4724 case Ijk_NoDecode
: trcval
= VEX_TRC_JMP_NODECODE
; break;
4725 case Ijk_InvalICache
: trcval
= VEX_TRC_JMP_INVALICACHE
; break;
4726 case Ijk_NoRedir
: trcval
= VEX_TRC_JMP_NOREDIR
; break;
4727 case Ijk_SigTRAP
: trcval
= VEX_TRC_JMP_SIGTRAP
; break;
4728 //case Ijk_SigSEGV: trcval = VEX_TRC_JMP_SIGSEGV; break;
4729 case Ijk_SigBUS
: trcval
= VEX_TRC_JMP_SIGBUS
; break;
4730 case Ijk_Boring
: trcval
= VEX_TRC_JMP_BORING
; break;
4731 /* We don't expect to see the following being assisted. */
4736 ppIRJumpKind(i
->Pin
.XAssisted
.jk
);
4737 vpanic("emit_ARMInstr.Pin_XAssisted: unexpected jump kind");
4739 vassert(trcval
!= 0);
4740 p
= mkLoadImm(p
, /*r*/31, trcval
, mode64
, endness_host
);
4742 /* imm32/64 r30, VG_(disp_cp_xassisted) */
4743 p
= mkLoadImm(p
, /*r*/30,
4744 (ULong
)(Addr
)disp_cp_xassisted
, mode64
,
4747 p
= mkFormXFX(p
, /*r*/30, 9, 467, endness_host
);
4749 p
= mkFormXL(p
, 19, Pct_ALWAYS
, 0, 0, 528, 0, endness_host
);
4751 /* Fix up the conditional jump, if there was one. */
4752 if (i
->Pin
.XAssisted
.cond
.test
!= Pct_ALWAYS
) {
4753 Int delta
= p
- ptmp
;
4754 vassert(delta
>= 16 && delta
<= 32 && 0 == (delta
& 3));
4755 /* bc !ct,cf,delta */
4756 mkFormB(ptmp
, invertCondTest(i
->Pin
.XAssisted
.cond
.test
),
4757 i
->Pin
.XAssisted
.cond
.flag
, (delta
>>2), 0, 0, endness_host
);
4766 vassert(i
->Pin
.CMov
.cond
.test
!= Pct_ALWAYS
);
4768 r_dst
= iregEnc(i
->Pin
.CMov
.dst
, mode64
);
4769 cond
= i
->Pin
.CMov
.cond
;
4771 /* branch (if cond fails) over move instrs */
4773 if (cond
.test
!= Pct_ALWAYS
) {
4774 /* don't know how many bytes to jump over yet...
4775 make space for a jump instruction and fill in later. */
4776 ptmp
= p
; /* fill in this bit later */
4780 // cond true: move src => dst
4781 switch (i
->Pin
.CMov
.src
->tag
) {
4783 imm_src
= i
->Pin
.CMov
.src
->Pri
.Imm
;
4784 p
= mkLoadImm(p
, r_dst
, imm_src
, mode64
, endness_host
); // p += 4|8|20
4787 r_src
= iregEnc(i
->Pin
.CMov
.src
->Pri
.Reg
, mode64
);
4788 p
= mkMoveReg(p
, r_dst
, r_src
, endness_host
); // p += 4
4793 /* Fix up the conditional jump, if there was one. */
4794 if (cond
.test
!= Pct_ALWAYS
) {
4795 Int delta
= p
- ptmp
;
4796 vassert(delta
>= 8 && delta
<= 24);
4797 /* bc !ct,cf,delta */
4798 mkFormB(ptmp
, invertCondTest(cond
.test
),
4799 cond
.flag
, (delta
>>2), 0, 0, endness_host
);
4805 PPCAMode
* am_addr
= i
->Pin
.Load
.src
;
4806 UInt r_dst
= iregEnc(i
->Pin
.Load
.dst
, mode64
);
4807 UInt opc1
, opc2
, sz
= i
->Pin
.Load
.sz
;
4808 switch (am_addr
->tag
) {
4810 if (mode64
&& (sz
== 4 || sz
== 8)) {
4811 /* should be guaranteed to us by iselWordExpr_AMode */
4812 vassert(0 == (am_addr
->Pam
.IR
.index
& 3));
4815 case 1: opc1
= 34; break;
4816 case 2: opc1
= 40; break;
4817 case 4: opc1
= 32; break;
4818 case 8: opc1
= 58; vassert(mode64
); break;
4821 p
= doAMode_IR(p
, opc1
, r_dst
, am_addr
, mode64
, endness_host
);
4825 case 1: opc2
= 87; break;
4826 case 2: opc2
= 279; break;
4827 case 4: opc2
= 23; break;
4828 case 8: opc2
= 21; vassert(mode64
); break;
4831 p
= doAMode_RR(p
, 31, opc2
, r_dst
, am_addr
, mode64
, endness_host
);
4839 if (i
->Pin
.LoadL
.sz
== 1) {
4840 p
= mkFormX(p
, 31, iregEnc(i
->Pin
.LoadL
.dst
, mode64
),
4841 0, iregEnc(i
->Pin
.LoadL
.src
, mode64
), 52, 0, endness_host
);
4844 if (i
->Pin
.LoadL
.sz
== 2) {
4845 p
= mkFormX(p
, 31, iregEnc(i
->Pin
.LoadL
.dst
, mode64
),
4846 0, iregEnc(i
->Pin
.LoadL
.src
, mode64
), 116, 0, endness_host
);
4849 if (i
->Pin
.LoadL
.sz
== 4) {
4850 p
= mkFormX(p
, 31, iregEnc(i
->Pin
.LoadL
.dst
, mode64
),
4851 0, iregEnc(i
->Pin
.LoadL
.src
, mode64
), 20, 0, endness_host
);
4854 if (i
->Pin
.LoadL
.sz
== 8 && mode64
) {
4855 p
= mkFormX(p
, 31, iregEnc(i
->Pin
.LoadL
.dst
, mode64
),
4856 0, iregEnc(i
->Pin
.LoadL
.src
, mode64
), 84, 0, endness_host
);
4863 /* Make the destination register be 1 or 0, depending on whether
4864 the relevant condition holds. */
4865 UInt r_dst
= iregEnc(i
->Pin
.Set
.dst
, mode64
);
4866 PPCCondCode cond
= i
->Pin
.Set
.cond
;
4867 UInt rot_imm
, r_tmp
;
4869 if (cond
.test
== Pct_ALWAYS
) {
4870 // Just load 1 to dst => li dst,1
4871 p
= mkFormD(p
, 14, r_dst
, 0, 1, endness_host
);
4873 vassert(cond
.flag
!= Pcf_NONE
);
4874 rot_imm
= 1 + cond
.flag
;
4875 r_tmp
= 0; // Not set in getAllocable, so no need to declare.
4877 // r_tmp = CR => mfcr r_tmp
4878 p
= mkFormX(p
, 31, r_tmp
, 0, 0, 19, 0, endness_host
);
4880 // r_dst = flag (rotate left and mask)
4881 // => rlwinm r_dst,r_tmp,rot_imm,31,31
4882 p
= mkFormM(p
, 21, r_tmp
, r_dst
, rot_imm
, 31, 31, 0, endness_host
);
4884 if (cond
.test
== Pct_FALSE
) {
4885 // flip bit => xori r_dst,r_dst,1
4886 p
= mkFormD(p
, 26, r_dst
, r_dst
, 1, endness_host
);
4894 p
= mkFormX(p
, 31, iregEnc(i
->Pin
.MfCR
.dst
, mode64
), 0, 0, 19, 0,
4899 p
= mkFormX(p
, 31, 0, 0, 0, 598, 0, endness_host
); // sync, PPC32 p616
4900 // CAB: Should this be isync?
4901 // p = mkFormXL(p, 19, 0, 0, 0, 150, 0); // isync, PPC32 p467
4906 PPCAMode
* am_addr
= i
->Pin
.Store
.dst
;
4907 UInt r_src
= iregEnc(i
->Pin
.Store
.src
, mode64
);
4908 UInt opc1
, opc2
, sz
= i
->Pin
.Store
.sz
;
4909 switch (i
->Pin
.Store
.dst
->tag
) {
4911 if (mode64
&& (sz
== 4 || sz
== 8)) {
4912 /* should be guaranteed to us by iselWordExpr_AMode */
4913 vassert(0 == (am_addr
->Pam
.IR
.index
& 3));
4916 case 1: opc1
= 38; break;
4917 case 2: opc1
= 44; break;
4918 case 4: opc1
= 36; break;
4919 case 8: vassert(mode64
);
4924 p
= doAMode_IR(p
, opc1
, r_src
, am_addr
, mode64
, endness_host
);
4928 case 1: opc2
= 215; break;
4929 case 2: opc2
= 407; break;
4930 case 4: opc2
= 151; break;
4931 case 8: vassert(mode64
);
4936 p
= doAMode_RR(p
, 31, opc2
, r_src
, am_addr
, mode64
, endness_host
);
4941 // PJF Coverity may be right but I'd reather keep the unreachable code
4942 // "just in case" that conditions above ever change
4943 // coverity[UNREACHABLE:FALSE]
4948 if (i
->Pin
.StoreC
.sz
== 1) {
4949 p
= mkFormX(p
, 31, iregEnc(i
->Pin
.StoreC
.src
, mode64
),
4950 0, iregEnc(i
->Pin
.StoreC
.dst
, mode64
), 694, 1, endness_host
);
4953 if (i
->Pin
.StoreC
.sz
== 2) {
4954 p
= mkFormX(p
, 31, iregEnc(i
->Pin
.StoreC
.src
, mode64
),
4955 0, iregEnc(i
->Pin
.StoreC
.dst
, mode64
), 726, 1, endness_host
);
4959 if (i
->Pin
.StoreC
.sz
== 4) {
4960 p
= mkFormX(p
, 31, iregEnc(i
->Pin
.StoreC
.src
, mode64
),
4961 0, iregEnc(i
->Pin
.StoreC
.dst
, mode64
), 150, 1, endness_host
);
4964 if (i
->Pin
.StoreC
.sz
== 8 && mode64
) {
4965 p
= mkFormX(p
, 31, iregEnc(i
->Pin
.StoreC
.src
, mode64
),
4966 0, iregEnc(i
->Pin
.StoreC
.dst
, mode64
), 214, 1, endness_host
);
4973 UInt fr_dst
= fregEnc(i
->Pin
.FpUnary
.dst
);
4974 UInt fr_src
= fregEnc(i
->Pin
.FpUnary
.src
);
4975 switch (i
->Pin
.FpUnary
.op
) {
4976 case Pfp_RSQRTE
: // frsqrtre, PPC32 p424
4977 p
= mkFormA( p
, 63, fr_dst
, 0, fr_src
, 0, 26, 0, endness_host
);
4979 case Pfp_RES
: // fres, PPC32 p421
4980 p
= mkFormA( p
, 59, fr_dst
, 0, fr_src
, 0, 24, 0, endness_host
);
4982 case Pfp_SQRT
: // fsqrt, PPC32 p427
4983 p
= mkFormA( p
, 63, fr_dst
, 0, fr_src
, 0, 22, 0, endness_host
);
4985 case Pfp_ABS
: // fabs, PPC32 p399
4986 p
= mkFormX(p
, 63, fr_dst
, 0, fr_src
, 264, 0, endness_host
);
4988 case Pfp_NEG
: // fneg, PPC32 p416
4989 p
= mkFormX(p
, 63, fr_dst
, 0, fr_src
, 40, 0, endness_host
);
4991 case Pfp_MOV
: // fmr, PPC32 p410
4992 p
= mkFormX(p
, 63, fr_dst
, 0, fr_src
, 72, 0, endness_host
);
4994 case Pfp_FRIM
: // frim, PPC ISA 2.05 p137
4995 p
= mkFormX(p
, 63, fr_dst
, 0, fr_src
, 488, 0, endness_host
);
4997 case Pfp_FRIP
: // frip, PPC ISA 2.05 p137
4998 p
= mkFormX(p
, 63, fr_dst
, 0, fr_src
, 456, 0, endness_host
);
5000 case Pfp_FRIN
: // frin, PPC ISA 2.05 p137
5001 p
= mkFormX(p
, 63, fr_dst
, 0, fr_src
, 392, 0, endness_host
);
5003 case Pfp_FRIZ
: // friz, PPC ISA 2.05 p137
5004 p
= mkFormX(p
, 63, fr_dst
, 0, fr_src
, 424, 0, endness_host
);
5012 case Pin_FpBinary
: {
5013 UInt fr_dst
= fregEnc(i
->Pin
.FpBinary
.dst
);
5014 UInt fr_srcL
= fregEnc(i
->Pin
.FpBinary
.srcL
);
5015 UInt fr_srcR
= fregEnc(i
->Pin
.FpBinary
.srcR
);
5016 switch (i
->Pin
.FpBinary
.op
) {
5017 case Pfp_ADDD
: // fadd, PPC32 p400
5018 p
= mkFormA( p
, 63, fr_dst
, fr_srcL
, fr_srcR
, 0, 21, 0, endness_host
);
5020 case Pfp_ADDS
: // fadds, PPC32 p401
5021 p
= mkFormA( p
, 59, fr_dst
, fr_srcL
, fr_srcR
, 0, 21, 0, endness_host
);
5023 case Pfp_SUBD
: // fsub, PPC32 p429
5024 p
= mkFormA( p
, 63, fr_dst
, fr_srcL
, fr_srcR
, 0, 20, 0, endness_host
);
5026 case Pfp_SUBS
: // fsubs, PPC32 p430
5027 p
= mkFormA( p
, 59, fr_dst
, fr_srcL
, fr_srcR
, 0, 20, 0, endness_host
);
5029 case Pfp_MULD
: // fmul, PPC32 p413
5030 p
= mkFormA( p
, 63, fr_dst
, fr_srcL
, 0, fr_srcR
, 25, 0, endness_host
);
5032 case Pfp_MULS
: // fmuls, PPC32 p414
5033 p
= mkFormA( p
, 59, fr_dst
, fr_srcL
, 0, fr_srcR
, 25, 0, endness_host
);
5035 case Pfp_DIVD
: // fdiv, PPC32 p406
5036 p
= mkFormA( p
, 63, fr_dst
, fr_srcL
, fr_srcR
, 0, 18, 0, endness_host
);
5038 case Pfp_DIVS
: // fdivs, PPC32 p407
5039 p
= mkFormA( p
, 59, fr_dst
, fr_srcL
, fr_srcR
, 0, 18, 0, endness_host
);
5047 case Pin_Fp128Unary
: {
5048 /* Note Fp128 instructions use the vector scalar registers. The register
5049 * mapping for the V128 type assumes the a vector instruction. The
5050 * PPC hardware has a single register file that the vector scalar
5051 * registers and the vector registers map to. The 32 vector
5052 * registers instructions map to the same registers as the vector
5053 * scalar registers 32 to 63. mkFormVXR0 does the needed
5056 UInt fr_dst
= vregEnc(i
->Pin
.Fp128Unary
.dst
);
5057 UInt fr_src
= vregEnc(i
->Pin
.Fp128Unary
.src
);
5059 switch (i
->Pin
.Fp128Unary
.op
) {
5060 case Pfp_FPSQRTQ
: // xssqrtqp, use rounding specified by RN
5061 p
= mkFormVXR0( p
, 63, fr_dst
, 27, fr_src
, 804, 0, endness_host
);
5063 case Pfp_FPSQRTQRNDODD
: // xssqrtqpo, use rounding specified by RN
5064 p
= mkFormVXR0( p
, 63, fr_dst
, 27, fr_src
, 804, 1, endness_host
);
5066 case Pfp_FPQTOD
: // xscvqpdp, use rounding specified by RN
5067 p
= mkFormVXR0( p
, 63, fr_dst
, 20, fr_src
, 836, 0, endness_host
);
5069 case Pfp_FPQTODRNDODD
: // xscvqpdpo, use rounding specified by RN
5070 p
= mkFormVXR0( p
, 63, fr_dst
, 20, fr_src
, 836, 1, endness_host
);
5072 case Pfp_FPDTOQ
: // xscvdpqp
5073 p
= mkFormVXR0( p
, 63, fr_dst
, 22, fr_src
, 836, 0, endness_host
);
5075 case Pfp_IDSTOQ
: // xscvsdqp
5076 p
= mkFormVXR0( p
, 63, fr_dst
, 10, fr_src
, 836, 0, endness_host
);
5078 case Pfp_IDUTOQ
: // xscvudqp
5079 p
= mkFormVXR0( p
, 63, fr_dst
, 2, fr_src
, 836, 0, endness_host
);
5081 case Pfp_IQSTOQ
: // xscvsqqp
5082 p
= mkFormVXR0( p
, 63, fr_dst
, 11, fr_src
, 836, 0, endness_host
);
5084 case Pfp_IQUTOQ
: // xscvuqqp
5085 p
= mkFormVXR0( p
, 63, fr_dst
, 3, fr_src
, 836, 0, endness_host
);
5087 case Pfp_TRUNCFPQTOISQ
: // xscvqpsqz
5088 p
= mkFormVXR0( p
, 63, fr_dst
, 8, fr_src
, 836, 0, endness_host
);
5090 case Pfp_TRUNCFPQTOISD
: // xscvqpsdz
5091 p
= mkFormVXR0( p
, 63, fr_dst
, 25, fr_src
, 836, 0, endness_host
);
5093 case Pfp_TRUNCFPQTOISW
: // xscvqpswz
5094 p
= mkFormVXR0( p
, 63, fr_dst
, 9, fr_src
, 836, 0, endness_host
);
5096 case Pfp_TRUNCFPQTOIUQ
: // xscvqpuqz
5097 p
= mkFormVXR0( p
, 63, fr_dst
, 0, fr_src
, 836, 0, endness_host
);
5099 case Pfp_TRUNCFPQTOIUD
: // xscvqpudz
5100 p
= mkFormVXR0( p
, 63, fr_dst
, 17, fr_src
, 836, 0, endness_host
);
5102 case Pfp_TRUNCFPQTOIUW
: // xscvqpuwz
5103 p
= mkFormVXR0( p
, 63, fr_dst
, 1, fr_src
, 836, 0, endness_host
);
5111 case Pin_Fp128Binary
: {
5112 /* Note Fp128 instructions use the vector registers */
5113 UInt fr_dst
= vregEnc(i
->Pin
.Fp128Binary
.dst
);
5114 UInt fr_srcL
= vregEnc(i
->Pin
.Fp128Binary
.srcL
);
5115 UInt fr_srcR
= vregEnc(i
->Pin
.Fp128Binary
.srcR
);
5117 /* Note this issues a Vector scalar instruction. The register
5118 * mapping for the V128 type assumes the a vector instruction. The
5119 * PPC hardware has a single register file that the vector scalar
5120 * registers and the vector registers map to. The 32 vector
5121 * registers instructions map to the same registers as the vector
5122 * scalar registers 32 to 63. For these instructions the HW adds
5123 * 32 to the register numbers to access the VSRR register. No need
5124 * to adjust the numbers to map to the VR register that contians the
5128 switch (i
->Pin
.Fp128Binary
.op
) {
5129 case Pfp_FPADDQ
: // xsaddqp, use rounding specified by RN
5130 p
= mkFormVXR0( p
, 63, fr_dst
, fr_srcL
, fr_srcR
, 4, 0, endness_host
);
5132 case Pfp_FPADDQRNDODD
: // xsaddqpo, round to odd
5133 p
= mkFormVXR0( p
, 63, fr_dst
, fr_srcL
, fr_srcR
, 4, 1, endness_host
);
5135 case Pfp_FPSUBQ
: // xssubqp, use rounding specified by RN
5136 p
= mkFormVXR0( p
, 63, fr_dst
, fr_srcL
, fr_srcR
, 516, 0, endness_host
);
5138 case Pfp_FPSUBQRNDODD
: // xssubqpo, round to odd
5139 p
= mkFormVXR0( p
, 63, fr_dst
, fr_srcL
, fr_srcR
, 516, 1, endness_host
);
5141 case Pfp_FPMULQ
: // xsmulqp, use rounding specified by RN
5142 p
= mkFormVXR0( p
, 63, fr_dst
, fr_srcL
, fr_srcR
, 36, 0, endness_host
);
5144 case Pfp_FPMULQRNDODD
: // xsmulqpo, round to odd
5145 p
= mkFormVXR0( p
, 63, fr_dst
, fr_srcL
, fr_srcR
, 36, 1, endness_host
);
5147 case Pfp_FPDIVQ
: // xsdivqp, use rounding specified by RN
5148 p
= mkFormVXR0( p
, 63, fr_dst
, fr_srcL
, fr_srcR
, 548, 0, endness_host
);
5150 case Pfp_FPDIVQRNDODD
: // xsdivqpo, round to odd
5151 p
= mkFormVXR0( p
, 63, fr_dst
, fr_srcL
, fr_srcR
, 548, 1, endness_host
);
5153 case Pfp_FPMULADDQ
: // xsmaddqp, use rounding specified by RN
5154 p
= mkFormVXR0( p
, 63, fr_dst
, fr_srcL
, fr_srcR
, 388, 0, endness_host
);
5156 case Pfp_FPMULADDQRNDODD
: // xsmaddqpo, round to odd
5157 p
= mkFormVXR0( p
, 63, fr_dst
, fr_srcL
, fr_srcR
, 388, 1, endness_host
);
5159 case Pfp_FPMULSUBQ
: // xsmsubqp, use rounding specified by RN
5160 p
= mkFormVXR0( p
, 63, fr_dst
, fr_srcL
, fr_srcR
, 420, 0, endness_host
);
5162 case Pfp_FPMULSUBQRNDODD
: // xsmsubsqpo, round to odd
5163 p
= mkFormVXR0( p
, 63, fr_dst
, fr_srcL
, fr_srcR
, 420, 1, endness_host
);
5165 case Pfp_FPNEGMULADDQ
: // xsnmaddqp, use rounding specified by RN
5166 p
= mkFormVXR0( p
, 63, fr_dst
, fr_srcL
, fr_srcR
, 452, 0, endness_host
);
5168 case Pfp_FPNEGMULADDQRNDODD
: // xsnmaddqpo, round to odd
5169 p
= mkFormVXR0( p
, 63, fr_dst
, fr_srcL
, fr_srcR
, 452, 1, endness_host
);
5171 case Pfp_FPNEGMULSUBQ
: // xsnmsubqp, use rounding specified by RN
5172 p
= mkFormVXR0( p
, 63, fr_dst
, fr_srcL
, fr_srcR
, 484, 0, endness_host
);
5174 case Pfp_FPNEGMULSUBQRNDODD
: // xsnmsubsqpo, round to odd
5175 p
= mkFormVXR0( p
, 63, fr_dst
, fr_srcL
, fr_srcR
, 484, 1, endness_host
);
5183 case Pin_Fp128Ternary
: {
5184 /* Note Fp128 instructions use the vector registers */
5185 UInt fr_dst
= vregEnc(i
->Pin
.Fp128Binary
.dst
);
5186 UInt fr_srcL
= vregEnc(i
->Pin
.Fp128Binary
.srcL
);
5187 UInt fr_srcR
= vregEnc(i
->Pin
.Fp128Binary
.srcR
);
5189 /* Note this issues a Vector scalar instruction. The register
5190 * mapping for the V128 type assumes the a vector instruction. The
5191 * PPC hardware has a single register file that the vector scalar
5192 * registers and the vector registers map to. The 32 vector
5193 * registers instructions map to the same registers as the vector
5194 * scalar registers 32 to 63. For these instructions the HW adds
5195 * 32 to the register numbers to access the VSRR register. No need
5196 * to adjust the numbers to map to the VR register that contians the
5200 switch (i
->Pin
.Fp128Binary
.op
) {
5201 case Pfp_FPMULADDQ
: // xsmaddqp, use rounding specified by RN
5202 p
= mkFormVXR0( p
, 63, fr_dst
, fr_srcL
, fr_srcR
, 388, 0, endness_host
);
5204 case Pfp_FPMULADDQRNDODD
: // xsmaddqpo, round to odd
5205 p
= mkFormVXR0( p
, 63, fr_dst
, fr_srcL
, fr_srcR
, 388, 1, endness_host
);
5207 case Pfp_FPMULSUBQ
: // xsmsubqp, use rounding specified by RN
5208 p
= mkFormVXR0( p
, 63, fr_dst
, fr_srcL
, fr_srcR
, 420, 0, endness_host
);
5210 case Pfp_FPMULSUBQRNDODD
: // xsmsubsqpo, round to odd
5211 p
= mkFormVXR0( p
, 63, fr_dst
, fr_srcL
, fr_srcR
, 420, 1, endness_host
);
5213 case Pfp_FPNEGMULADDQ
: // xsnmaddqp, use rounding specified by RN
5214 p
= mkFormVXR0( p
, 63, fr_dst
, fr_srcL
, fr_srcR
, 452, 0, endness_host
);
5216 case Pfp_FPNEGMULADDQRNDODD
: // xsnmaddqpo, round to odd
5217 p
= mkFormVXR0( p
, 63, fr_dst
, fr_srcL
, fr_srcR
, 452, 1, endness_host
);
5219 case Pfp_FPNEGMULSUBQ
: // xsnmsubqp, use rounding specified by RN
5220 p
= mkFormVXR0( p
, 63, fr_dst
, fr_srcL
, fr_srcR
, 484, 0, endness_host
);
5222 case Pfp_FPNEGMULSUBQRNDODD
: // xsnmsubsqpo, round to odd
5223 p
= mkFormVXR0( p
, 63, fr_dst
, fr_srcL
, fr_srcR
, 484, 1, endness_host
);
5231 case Pin_FpMulAcc
: {
5232 UInt fr_dst
= fregEnc(i
->Pin
.FpMulAcc
.dst
);
5233 UInt fr_srcML
= fregEnc(i
->Pin
.FpMulAcc
.srcML
);
5234 UInt fr_srcMR
= fregEnc(i
->Pin
.FpMulAcc
.srcMR
);
5235 UInt fr_srcAcc
= fregEnc(i
->Pin
.FpMulAcc
.srcAcc
);
5236 switch (i
->Pin
.FpMulAcc
.op
) {
5237 case Pfp_MADDD
: // fmadd, PPC32 p408
5238 p
= mkFormA( p
, 63, fr_dst
, fr_srcML
, fr_srcAcc
, fr_srcMR
, 29, 0,
5241 case Pfp_MADDS
: // fmadds, PPC32 p409
5242 p
= mkFormA( p
, 59, fr_dst
, fr_srcML
, fr_srcAcc
, fr_srcMR
, 29, 0,
5245 case Pfp_MSUBD
: // fmsub, PPC32 p411
5246 p
= mkFormA( p
, 63, fr_dst
, fr_srcML
, fr_srcAcc
, fr_srcMR
, 28, 0,
5249 case Pfp_MSUBS
: // fmsubs, PPC32 p412
5250 p
= mkFormA( p
, 59, fr_dst
, fr_srcML
, fr_srcAcc
, fr_srcMR
, 28, 0,
5260 PPCAMode
* am_addr
= i
->Pin
.FpLdSt
.addr
;
5261 UInt f_reg
= fregEnc(i
->Pin
.FpLdSt
.reg
);
5262 Bool idxd
= toBool(i
->Pin
.FpLdSt
.addr
->tag
== Pam_RR
);
5263 UChar sz
= i
->Pin
.FpLdSt
.sz
;
5265 vassert(sz
== 4 || sz
== 8);
5267 if (i
->Pin
.FpLdSt
.isLoad
) { // Load from memory
5268 if (idxd
) { // lf[s|d]x, PPC32 p444|440
5269 opc
= (sz
== 4) ? 535 : 599;
5270 p
= doAMode_RR(p
, 31, opc
, f_reg
, am_addr
, mode64
, endness_host
);
5271 } else { // lf[s|d], PPC32 p441|437
5272 opc
= (sz
== 4) ? 48 : 50;
5273 p
= doAMode_IR(p
, opc
, f_reg
, am_addr
, mode64
, endness_host
);
5275 } else { // Store to memory
5276 if (idxd
) { // stf[s|d]x, PPC32 p521|516
5277 opc
= (sz
== 4) ? 663 : 727;
5278 p
= doAMode_RR(p
, 31, opc
, f_reg
, am_addr
, mode64
, endness_host
);
5279 } else { // stf[s|d], PPC32 p518|513
5280 opc
= (sz
== 4) ? 52 : 54;
5281 p
= doAMode_IR(p
, opc
, f_reg
, am_addr
, mode64
, endness_host
);
5288 UInt ir_addr
= iregEnc(i
->Pin
.FpSTFIW
.addr
, mode64
);
5289 UInt fr_data
= fregEnc(i
->Pin
.FpSTFIW
.data
);
5290 // stfiwx (store fp64[lo32] as int32), PPC32 p517
5291 // Use rA==0, so that EA == rB == ir_addr
5292 p
= mkFormX(p
, 31, fr_data
, 0/*rA=0*/, ir_addr
, 983, 0, endness_host
);
5297 UInt fr_dst
= fregEnc(i
->Pin
.FpRSP
.dst
);
5298 UInt fr_src
= fregEnc(i
->Pin
.FpRSP
.src
);
5300 p
= mkFormX(p
, 63, fr_dst
, 0, fr_src
, 12, 0, endness_host
);
5305 UInt fr_dst
= fregEnc(i
->Pin
.FpCftI
.dst
);
5306 UInt fr_src
= fregEnc(i
->Pin
.FpCftI
.src
);
5307 if (i
->Pin
.FpCftI
.fromI
== False
&& i
->Pin
.FpCftI
.int32
== True
) {
5308 if (i
->Pin
.FpCftI
.syned
== True
) {
5309 // fctiw (conv f64 to i32), PPC32 p404
5310 p
= mkFormX(p
, 63, fr_dst
, 0, fr_src
, 14, 0, endness_host
);
5313 // fctiwu (conv f64 to u32)
5314 p
= mkFormX(p
, 63, fr_dst
, 0, fr_src
, 142, 0, endness_host
);
5318 if (i
->Pin
.FpCftI
.fromI
== False
&& i
->Pin
.FpCftI
.int32
== False
) {
5319 if (i
->Pin
.FpCftI
.syned
== True
) {
5320 // fctid (conv f64 to i64), PPC64 p437
5321 p
= mkFormX(p
, 63, fr_dst
, 0, fr_src
, 814, 0, endness_host
);
5324 // fctidu (conv f64 to u64)
5325 p
= mkFormX(p
, 63, fr_dst
, 0, fr_src
, 942, 0, endness_host
);
5329 if (i
->Pin
.FpCftI
.fromI
== True
&& i
->Pin
.FpCftI
.int32
== False
) {
5330 if (i
->Pin
.FpCftI
.syned
== True
) {
5331 // fcfid (conv i64 to f64), PPC64 p434
5332 p
= mkFormX(p
, 63, fr_dst
, 0, fr_src
, 846, 0, endness_host
);
5334 } else if (i
->Pin
.FpCftI
.flt64
== True
) {
5335 // fcfidu (conv u64 to f64)
5336 p
= mkFormX(p
, 63, fr_dst
, 0, fr_src
, 974, 0, endness_host
);
5339 // fcfidus (conv u64 to f32)
5340 p
= mkFormX(p
, 59, fr_dst
, 0, fr_src
, 974, 0, endness_host
);
5348 UInt fr_dst
= fregEnc(i
->Pin
.FpCMov
.dst
);
5349 UInt fr_src
= fregEnc(i
->Pin
.FpCMov
.src
);
5350 PPCCondCode cc
= i
->Pin
.FpCMov
.cond
;
5352 if (fr_dst
== fr_src
) goto done
;
5354 vassert(cc
.test
!= Pct_ALWAYS
);
5356 /* jmp fwds if !condition */
5357 if (cc
.test
!= Pct_ALWAYS
) {
5358 /* bc !ct,cf,n_bytes>>2 */
5359 p
= mkFormB(p
, invertCondTest(cc
.test
), cc
.flag
, 8>>2, 0, 0,
5364 p
= mkFormX(p
, 63, fr_dst
, 0, fr_src
, 72, 0, endness_host
);
5368 case Pin_FpLdFPSCR
: {
5369 UInt fr_src
= fregEnc(i
->Pin
.FpLdFPSCR
.src
);
5370 p
= mkFormXFL(p
, 0xFF, fr_src
, i
->Pin
.FpLdFPSCR
.dfp_rm
, endness_host
); // mtfsf, PPC32 p480
5376 UInt r_dst
= iregEnc(i
->Pin
.FpCmp
.dst
, mode64
);
5377 UInt fr_srcL
= fregEnc(i
->Pin
.FpCmp
.srcL
);
5378 UInt fr_srcR
= fregEnc(i
->Pin
.FpCmp
.srcR
);
5380 // fcmpo, PPC32 p402
5381 p
= mkFormX(p
, 63, crfD
<<2, fr_srcL
, fr_srcR
, 32, 0, endness_host
);
5383 // mfcr (mv CR to r_dst), PPC32 p467
5384 p
= mkFormX(p
, 31, r_dst
, 0, 0, 19, 0, endness_host
);
5386 // rlwinm r_dst,r_dst,8,28,31, PPC32 p501
5387 // => rotate field 1 to bottomw of word, masking out upper 28
5388 p
= mkFormM(p
, 21, r_dst
, r_dst
, 8, 28, 31, 0, endness_host
);
5393 UInt reg
= iregEnc(i
->Pin
.RdWrLR
.gpr
, mode64
);
5394 /* wrLR==True ? mtlr r4 : mflr r4 */
5395 p
= mkFormXFX(p
, reg
, 8, (i
->Pin
.RdWrLR
.wrLR
==True
) ? 467 : 339,
5403 UInt opc2
, v_reg
, r_idx
, r_base
;
5404 UChar sz
= i
->Pin
.AvLdSt
.sz
;
5405 Bool idxd
= toBool(i
->Pin
.AvLdSt
.addr
->tag
== Pam_RR
);
5406 vassert(sz
== 1 || sz
== 2 || sz
== 4 || sz
== 16);
5408 v_reg
= vregEnc(i
->Pin
.AvLdSt
.reg
);
5409 r_base
= iregEnc(i
->Pin
.AvLdSt
.addr
->Pam
.RR
.base
, mode64
);
5411 // Only have AltiVec AMode_RR: kludge AMode_IR
5413 r_idx
= 30; // XXX: Using r30 as temp
5414 p
= mkLoadImm(p
, r_idx
,
5415 i
->Pin
.AvLdSt
.addr
->Pam
.IR
.index
, mode64
, endness_host
);
5417 r_idx
= iregEnc(i
->Pin
.AvLdSt
.addr
->Pam
.RR
.index
, mode64
);
5420 if (i
->Pin
.FpLdSt
.isLoad
) { // Load from memory (1,2,4,16)
5421 opc2
= (sz
==1) ? 7 : (sz
==2) ? 39 : (sz
==4) ? 71 : 103;
5422 p
= mkFormX(p
, 31, v_reg
, r_idx
, r_base
, opc2
, 0, endness_host
);
5423 } else { // Store to memory (1,2,4,16)
5424 opc2
= (sz
==1) ? 135 : (sz
==2) ? 167 : (sz
==4) ? 199 : 231;
5425 p
= mkFormX(p
, 31, v_reg
, r_idx
, r_base
, opc2
, 0, endness_host
);
5431 UInt v_dst
= vregEnc(i
->Pin
.AvUnary
.dst
);
5432 UInt v_src
= vregEnc(i
->Pin
.AvUnary
.src
);
5433 UInt opc2
= 0xFFFFFFFF, opc3
= 0xFFFFFFFF; /* invalid */
5435 switch (i
->Pin
.AvUnary
.op
) {
5436 case Pav_MOV
: opc2
= 1156; break; // vor vD,vS,vS
5437 case Pav_NOT
: opc2
= 1284; break; // vnor vD,vS,vS
5438 case Pav_UNPCKH8S
: opc2
= 526; break; // vupkhsb
5439 case Pav_UNPCKH16S
: opc2
= 590; break; // vupkhsh
5440 case Pav_UNPCKL8S
: opc2
= 654; break; // vupklsb
5441 case Pav_UNPCKL16S
: opc2
= 718; break; // vupklsh
5442 case Pav_UNPCKHPIX
: opc2
= 846; break; // vupkhpx
5443 case Pav_UNPCKLPIX
: opc2
= 974; break; // vupklpx
5445 case Pav_ZEROCNTBYTE
: opc2
= 1794; break; // vclzb
5446 case Pav_ZEROCNTHALF
: opc2
= 1858; break; // vclzh
5447 case Pav_ZEROCNTWORD
: opc2
= 1922; break; // vclzw
5448 case Pav_ZEROCNTDBL
: opc2
= 1986; break; // vclzd
5449 case Pav_TRAILINGZEROCNTBYTE
: opc2
= 1538; break; // vctzb
5450 case Pav_TRAILINGZEROCNTHALF
: opc2
= 1538; break; // vctzh
5451 case Pav_TRAILINGZEROCNTWORD
: opc2
= 1538; break; // vctzw
5452 case Pav_TRAILINGZEROCNTDBL
: opc2
= 1538; break; // vctzd
5453 case Pav_BITMTXXPOSE
: opc2
= 1292; break; // vgbbd
5454 case Pav_BCD128toI128S
: opc2
= 385; break; //bcdctsq.
5455 case Pav_MulI128by10
: opc2
= 513; break; // vmul10uq
5456 case Pav_MulI128by10Carry
: opc2
= 1; break; // vmul10cuq
5457 case Pav_F16toF64x2
: opc2
= 347; opc3
= 16; break; // xvcvhpdp
5458 case Pav_F64toF16x2
: opc2
= 347; opc3
= 17; break; // xvcvdphp
5459 case Pav_F16toF32x4
: opc2
= 475; opc3
= 24; break; // xvcvhpsp
5460 case Pav_F32toF16x4
: opc2
= 475; opc3
= 25; break; // xvcvsphp
5465 switch (i
->Pin
.AvUnary
.op
) {
5468 p
= mkFormVX( p
, 4, v_dst
, v_src
, v_src
, opc2
, endness_host
);
5470 case Pav_F16toF32x4
:
5472 /* I64 source has four 16-bit float values in the upper 64-bit
5473 * of the source vector register, lower 64-bits are undefined.
5475 /* Scatter the four F16 values in the Vector register */
5476 p
= mkFormVX( p
, 4, v_dst
, 0, v_src
, 590, endness_host
);// vupkhsh
5478 /* The layout of the vector register is now: S0F0 S1F1 S2F2 S3F3
5479 * where S is the sign extension of the 16-bit F value. We don't
5480 * care about the extended signs.
5483 /* Input, in v_dst, is now correct for the xvcvhpsp instruction */
5484 p
= mkFormVX_BX_TX( p
, 60, v_dst
, opc3
, v_dst
, opc2
,
5488 case Pav_F64toF16x2
:
5489 case Pav_F16toF64x2
:
5490 case Pav_F32toF16x4
:
5491 /* Note this issues a Vector scalar instruction. The register
5492 * mapping for the V128 type assumes the a vector instruction. The
5493 * PPC hardware has a single register file that the vector scalar
5494 * registers and the vector registers map to. The 32 vector registers
5495 * instructions map to the same registers as the vector scalar
5496 * registers 32 to 63. mkFormVX_BX_TX does the needed adjustment.
5498 p
= mkFormVX_BX_TX( p
, 60, v_dst
, opc3
, v_src
, opc2
, endness_host
);
5500 case Pav_BCD128toI128S
: // bcdctsq
5501 p
= mkFormVX( p
, 4, v_dst
, 0, v_src
, (1<<10 | 385), endness_host
);
5503 case Pav_MulI128by10
:
5504 case Pav_MulI128by10Carry
:
5505 p
= mkFormVX( p
, 4, v_dst
, v_src
, 0, opc2
, endness_host
);
5507 case Pav_TRAILINGZEROCNTBYTE
:
5508 p
= mkFormVX( p
, 4, v_dst
, 28, v_src
, opc2
, endness_host
);
5510 case Pav_TRAILINGZEROCNTHALF
:
5511 p
= mkFormVX( p
, 4, v_dst
, 29, v_src
, opc2
, endness_host
);
5513 case Pav_TRAILINGZEROCNTWORD
:
5514 p
= mkFormVX( p
, 4, v_dst
, 30, v_src
, opc2
, endness_host
);
5516 case Pav_TRAILINGZEROCNTDBL
:
5517 p
= mkFormVX( p
, 4, v_dst
, 31, v_src
, opc2
, endness_host
);
5520 p
= mkFormVX( p
, 4, v_dst
, 0, v_src
, opc2
, endness_host
);
5526 case Pin_AvBinary
: {
5527 UInt v_dst
= vregEnc(i
->Pin
.AvBinary
.dst
);
5528 UInt v_srcL
= vregEnc(i
->Pin
.AvBinary
.srcL
);
5529 UInt v_srcR
= vregEnc(i
->Pin
.AvBinary
.srcR
);
5531 if (i
->Pin
.AvBinary
.op
== Pav_SHL
) {
5532 p
= mkFormVX( p
, 4, v_dst
, v_srcL
, v_srcR
, 1036, endness_host
); // vslo
5533 p
= mkFormVX( p
, 4, v_dst
, v_dst
, v_srcR
, 452, endness_host
); // vsl
5536 if (i
->Pin
.AvBinary
.op
== Pav_SHR
) {
5537 p
= mkFormVX( p
, 4, v_dst
, v_srcL
, v_srcR
, 1100, endness_host
); // vsro
5538 p
= mkFormVX( p
, 4, v_dst
, v_dst
, v_srcR
, 708, endness_host
); // vsr
5541 switch (i
->Pin
.AvBinary
.op
) {
5543 case Pav_AND
: opc2
= 1028; break; // vand
5544 case Pav_OR
: opc2
= 1156; break; // vor
5545 case Pav_XOR
: opc2
= 1220; break; // vxor
5547 case Pav_MulI128by10E
: opc2
= 577; break; // vmul10euq
5548 case Pav_MulI128by10ECarry
: opc2
= 65; break; // vmul10ecuq
5552 p
= mkFormVX( p
, 4, v_dst
, v_srcL
, v_srcR
, opc2
, endness_host
);
5556 case Pin_AvBinaryInt
: {
5557 UInt ps
= i
->Pin
.AvBinaryInt
.val
->Pri
.Imm
;
5558 UInt dst
= vregEnc(i
->Pin
.AvBinaryInt
.dst
);
5559 UInt src
= vregEnc(i
->Pin
.AvBinaryInt
.src
);
5561 switch (i
->Pin
.AvBinaryInt
.op
) {
5563 case Pav_I128StoBCD128
: // bcdcfsq
5565 /* v_srcR actually contains the value of the one-bit ps field */
5567 p
= mkFormVX( p
, 4, dst
, 2, src
,
5568 (1 << 10 | (ps
<< 9) | opc2
), endness_host
);
5572 case Pav_F128toI128S
: // xsrqpi, xsrqpix
5576 UInt R
= (ps
>> 3) & 0x1;
5577 UInt RMC
= (ps
>> 1) & 0x3;
5578 /* Note this issues a Vector scalar instruction. The register
5579 * mapping for the V128 type assumes the a vector instruction. The
5580 * PPC hardware has a single register file that the vector scalar
5581 * registers and the vector registers map to. The 32 vector
5582 * registers instructions map to the same registers as the vector
5583 * scalar registers 32 to 63. For these instructions the HW adds
5584 * 32 to the register numbers to access the VSRR register. No need
5585 * to adjust the numbers to map to the VR register that contians
5588 p
= mkFormVSXRND( p
, 63, R
, dst
, src
, RMC
, opc2
, EX
,
5593 case Pav_ROUNDFPQ
: // xsrqpxp
5597 UInt RMC
= (ps
>> 1) & 0x3;
5598 UInt R
= (ps
>> 3) & 0x1;
5599 p
= mkFormVSXRND( p
, 63, R
, dst
, src
, RMC
, opc2
, EX
,
5611 case Pin_AvBinaryInt128
: {
5612 UInt dst
= vregEnc(i
->Pin
.AvBinaryInt128
.dst
);
5613 UInt src1
= vregEnc(i
->Pin
.AvBinaryInt128
.src1
);
5614 UInt src2
= vregEnc(i
->Pin
.AvBinaryInt128
.src2
);
5617 switch (i
->Pin
.AvBinaryInt128
.op
) {
5618 case Pav_DivS128
: opc2
= 267; break; //vdivsq
5619 case Pav_DivU128
: opc2
= 11; break; //vdivuq
5620 case Pav_DivU128E
: opc2
= 523; break; //vdiveuq
5621 case Pav_DivS128E
: opc2
= 779; break; //vdivesq
5622 case Pav_ModS128
: opc2
= 1803; break; //vmodsq
5623 case Pav_ModU128
: opc2
= 1547; break; //vmoduq
5628 p
= mkFormVX( p
, 4, dst
, src1
, src2
, opc2
, endness_host
);
5632 case Pin_AvTernaryInt128
: {
5633 UInt dst
= vregEnc(i
->Pin
.AvTernaryInt128
.dst
);
5634 UInt src1
= vregEnc(i
->Pin
.AvTernaryInt128
.src1
);
5635 UInt src2
= vregEnc(i
->Pin
.AvTernaryInt128
.src2
);
5636 UInt src3
= vregEnc(i
->Pin
.AvTernaryInt128
.src3
);
5639 switch (i
->Pin
.AvTernaryInt128
.op
) {
5640 case Pav_2xMultU64Add128CarryOut
: opc2
= 23; break; //vsumcud
5645 p
= mkFormVA( p
, 4, dst
, src1
, src2
, src3
, opc2
, endness_host
);
5649 case Pin_AvBin8x16
: {
5650 UInt v_dst
= vregEnc(i
->Pin
.AvBin8x16
.dst
);
5651 UInt v_srcL
= vregEnc(i
->Pin
.AvBin8x16
.srcL
);
5652 UInt v_srcR
= vregEnc(i
->Pin
.AvBin8x16
.srcR
);
5654 switch (i
->Pin
.AvBin8x16
.op
) {
5656 case Pav_ADDU
: opc2
= 0; break; // vaddubm
5657 case Pav_QADDU
: opc2
= 512; break; // vaddubs
5658 case Pav_QADDS
: opc2
= 768; break; // vaddsbs
5660 case Pav_SUBU
: opc2
= 1024; break; // vsububm
5661 case Pav_QSUBU
: opc2
= 1536; break; // vsububs
5662 case Pav_QSUBS
: opc2
= 1792; break; // vsubsbs
5664 case Pav_OMULU
: opc2
= 8; break; // vmuloub
5665 case Pav_OMULS
: opc2
= 264; break; // vmulosb
5666 case Pav_EMULU
: opc2
= 520; break; // vmuleub
5667 case Pav_EMULS
: opc2
= 776; break; // vmulesb
5669 case Pav_AVGU
: opc2
= 1026; break; // vavgub
5670 case Pav_AVGS
: opc2
= 1282; break; // vavgsb
5671 case Pav_MAXU
: opc2
= 2; break; // vmaxub
5672 case Pav_MAXS
: opc2
= 258; break; // vmaxsb
5673 case Pav_MINU
: opc2
= 514; break; // vminub
5674 case Pav_MINS
: opc2
= 770; break; // vminsb
5676 case Pav_CMPEQU
: opc2
= 6; break; // vcmpequb
5677 case Pav_CMPGTU
: opc2
= 518; break; // vcmpgtub
5678 case Pav_CMPGTS
: opc2
= 774; break; // vcmpgtsb
5680 case Pav_SHL
: opc2
= 260; break; // vslb
5681 case Pav_SHR
: opc2
= 516; break; // vsrb
5682 case Pav_SAR
: opc2
= 772; break; // vsrab
5683 case Pav_ROTL
: opc2
= 4; break; // vrlb
5685 case Pav_MRGHI
: opc2
= 12; break; // vmrghb
5686 case Pav_MRGLO
: opc2
= 268; break; // vmrglb
5688 case Pav_POLYMULADD
: opc2
= 1032; break; // vpmsumb
5693 p
= mkFormVX( p
, 4, v_dst
, v_srcL
, v_srcR
, opc2
, endness_host
);
5697 case Pin_AvBin16x8
: {
5698 UInt v_dst
= vregEnc(i
->Pin
.AvBin16x8
.dst
);
5699 UInt v_srcL
= vregEnc(i
->Pin
.AvBin16x8
.srcL
);
5700 UInt v_srcR
= vregEnc(i
->Pin
.AvBin16x8
.srcR
);
5702 switch (i
->Pin
.AvBin16x8
.op
) {
5704 case Pav_ADDU
: opc2
= 64; break; // vadduhm
5705 case Pav_QADDU
: opc2
= 576; break; // vadduhs
5706 case Pav_QADDS
: opc2
= 832; break; // vaddshs
5708 case Pav_SUBU
: opc2
= 1088; break; // vsubuhm
5709 case Pav_QSUBU
: opc2
= 1600; break; // vsubuhs
5710 case Pav_QSUBS
: opc2
= 1856; break; // vsubshs
5712 case Pav_OMULU
: opc2
= 72; break; // vmulouh
5713 case Pav_OMULS
: opc2
= 328; break; // vmulosh
5714 case Pav_EMULU
: opc2
= 584; break; // vmuleuh
5715 case Pav_EMULS
: opc2
= 840; break; // vmulesh
5717 case Pav_AVGU
: opc2
= 1090; break; // vavguh
5718 case Pav_AVGS
: opc2
= 1346; break; // vavgsh
5719 case Pav_MAXU
: opc2
= 66; break; // vmaxuh
5720 case Pav_MAXS
: opc2
= 322; break; // vmaxsh
5721 case Pav_MINS
: opc2
= 834; break; // vminsh
5722 case Pav_MINU
: opc2
= 578; break; // vminuh
5724 case Pav_CMPEQU
: opc2
= 70; break; // vcmpequh
5725 case Pav_CMPGTU
: opc2
= 582; break; // vcmpgtuh
5726 case Pav_CMPGTS
: opc2
= 838; break; // vcmpgtsh
5728 case Pav_SHL
: opc2
= 324; break; // vslh
5729 case Pav_SHR
: opc2
= 580; break; // vsrh
5730 case Pav_SAR
: opc2
= 836; break; // vsrah
5731 case Pav_ROTL
: opc2
= 68; break; // vrlh
5733 case Pav_PACKUU
: opc2
= 14; break; // vpkuhum
5734 case Pav_QPACKUU
: opc2
= 142; break; // vpkuhus
5735 case Pav_QPACKSU
: opc2
= 270; break; // vpkshus
5736 case Pav_QPACKSS
: opc2
= 398; break; // vpkshss
5737 case Pav_PACKPXL
: opc2
= 782; break; // vpkpx
5739 case Pav_MRGHI
: opc2
= 76; break; // vmrghh
5740 case Pav_MRGLO
: opc2
= 332; break; // vmrglh
5742 case Pav_POLYMULADD
: opc2
= 1224; break; // vpmsumh
5747 p
= mkFormVX( p
, 4, v_dst
, v_srcL
, v_srcR
, opc2
, endness_host
);
5751 case Pin_AvBin32x4
: {
5752 UInt v_dst
= vregEnc(i
->Pin
.AvBin32x4
.dst
);
5753 UInt v_srcL
= vregEnc(i
->Pin
.AvBin32x4
.srcL
);
5754 UInt v_srcR
= vregEnc(i
->Pin
.AvBin32x4
.srcR
);
5756 switch (i
->Pin
.AvBin32x4
.op
) {
5758 case Pav_ADDU
: opc2
= 128; break; // vadduwm
5759 case Pav_QADDU
: opc2
= 640; break; // vadduws
5760 case Pav_QADDS
: opc2
= 896; break; // vaddsws
5762 case Pav_SUBU
: opc2
= 1152; break; // vsubuwm
5763 case Pav_QSUBU
: opc2
= 1664; break; // vsubuws
5764 case Pav_QSUBS
: opc2
= 1920; break; // vsubsws
5766 case Pav_MULU
: opc2
= 137; break; // vmuluwm
5767 case Pav_OMULU
: opc2
= 136; break; // vmulouw
5768 case Pav_OMULS
: opc2
= 392; break; // vmulosw
5769 case Pav_EMULU
: opc2
= 648; break; // vmuleuw
5770 case Pav_EMULS
: opc2
= 904; break; // vmulesw
5772 case Pav_AVGU
: opc2
= 1154; break; // vavguw
5773 case Pav_AVGS
: opc2
= 1410; break; // vavgsw
5775 case Pav_MAXU
: opc2
= 130; break; // vmaxuw
5776 case Pav_MAXS
: opc2
= 386; break; // vmaxsw
5778 case Pav_MINS
: opc2
= 898; break; // vminsw
5779 case Pav_MINU
: opc2
= 642; break; // vminuw
5781 case Pav_CMPEQU
: opc2
= 134; break; // vcmpequw
5782 case Pav_CMPGTS
: opc2
= 902; break; // vcmpgtsw
5783 case Pav_CMPGTU
: opc2
= 646; break; // vcmpgtuw
5785 case Pav_SHL
: opc2
= 388; break; // vslw
5786 case Pav_SHR
: opc2
= 644; break; // vsrw
5787 case Pav_SAR
: opc2
= 900; break; // vsraw
5788 case Pav_ROTL
: opc2
= 132; break; // vrlw
5790 case Pav_PACKUU
: opc2
= 78; break; // vpkuwum
5791 case Pav_QPACKUU
: opc2
= 206; break; // vpkuwus
5792 case Pav_QPACKSU
: opc2
= 334; break; // vpkswus
5793 case Pav_QPACKSS
: opc2
= 462; break; // vpkswss
5795 case Pav_MRGHI
: opc2
= 140; break; // vmrghw
5796 case Pav_MRGLO
: opc2
= 396; break; // vmrglw
5798 case Pav_CATODD
: opc2
= 1676; break; // vmrgow
5799 case Pav_CATEVEN
: opc2
= 1932; break; // vmrgew
5801 case Pav_POLYMULADD
: opc2
= 1160; break; // vpmsumw
5806 p
= mkFormVX( p
, 4, v_dst
, v_srcL
, v_srcR
, opc2
, endness_host
);
5810 case Pin_AvBin64x2
: {
5811 UInt v_dst
= vregEnc(i
->Pin
.AvBin64x2
.dst
);
5812 UInt v_srcL
= vregEnc(i
->Pin
.AvBin64x2
.srcL
);
5813 UInt v_srcR
= vregEnc(i
->Pin
.AvBin64x2
.srcR
);
5815 switch (i
->Pin
.AvBin64x2
.op
) {
5816 case Pav_ADDU
: opc2
= 192; break; // vaddudm vector double add
5817 case Pav_SUBU
: opc2
= 1216; break; // vsubudm vector double add
5818 case Pav_MAXU
: opc2
= 194; break; // vmaxud vector double max
5819 case Pav_MAXS
: opc2
= 450; break; // vmaxsd vector double max
5820 case Pav_MINU
: opc2
= 706; break; // vminud vector double min
5821 case Pav_MINS
: opc2
= 962; break; // vminsd vector double min
5822 case Pav_CMPEQU
: opc2
= 199; break; // vcmpequd vector double compare
5823 case Pav_CMPGTU
: opc2
= 711; break; // vcmpgtud vector double compare
5824 case Pav_CMPGTS
: opc2
= 967; break; // vcmpgtsd vector double compare
5825 case Pav_SHL
: opc2
= 1476; break; // vsld
5826 case Pav_SHR
: opc2
= 1732; break; // vsrd
5827 case Pav_SAR
: opc2
= 964; break; // vsrad
5828 case Pav_ROTL
: opc2
= 196; break; // vrld
5829 case Pav_PACKUU
: opc2
= 1102; break; // vpkudum
5830 case Pav_QPACKUU
: opc2
= 1230; break; // vpkudus, vpksdus (emulated)
5831 case Pav_QPACKSS
: opc2
= 1486; break; // vpksdsm
5832 case Pav_MRGHI
: opc2
= 1614; break; // vmrghw
5833 case Pav_MRGLO
: opc2
= 1742; break; // vmrglw
5834 case Pav_POLYMULADD
: opc2
= 1096; break; // vpmsumd
5838 p
= mkFormVX( p
, 4, v_dst
, v_srcL
, v_srcR
, opc2
, endness_host
);
5841 case Pin_AvCipherV128Unary
: {
5842 UInt v_dst
= vregEnc(i
->Pin
.AvCipherV128Unary
.dst
);
5843 UInt v_src
= vregEnc(i
->Pin
.AvCipherV128Unary
.src
);
5845 switch (i
->Pin
.AvCipherV128Unary
.op
) {
5846 case Pav_CIPHERSUBV128
: opc2
= 1480; break; // vsbox
5850 p
= mkFormVX( p
, 4, v_dst
, v_src
, 0, opc2
, endness_host
);
5853 case Pin_AvCipherV128Binary
: {
5854 UInt v_dst
= vregEnc(i
->Pin
.AvCipherV128Binary
.dst
);
5855 UInt v_srcL
= vregEnc(i
->Pin
.AvCipherV128Binary
.srcL
);
5856 UInt v_srcR
= vregEnc(i
->Pin
.AvCipherV128Binary
.srcR
);
5858 switch (i
->Pin
.AvCipherV128Binary
.op
) {
5859 case Pav_CIPHERV128
: opc2
= 1288; break; // vcipher
5860 case Pav_CIPHERLV128
: opc2
= 1289; break; // vcipherlast
5861 case Pav_NCIPHERV128
: opc2
= 1352; break; // vncipher
5862 case Pav_NCIPHERLV128
: opc2
= 1353; break; // vncipherlast
5866 p
= mkFormVX( p
, 4, v_dst
, v_srcL
, v_srcR
, opc2
, endness_host
);
5869 case Pin_AvHashV128Binary
: {
5870 UInt v_dst
= vregEnc(i
->Pin
.AvHashV128Binary
.dst
);
5871 UInt v_src
= vregEnc(i
->Pin
.AvHashV128Binary
.src
);
5872 PPCRI
* s_field
= i
->Pin
.AvHashV128Binary
.s_field
;
5874 switch (i
->Pin
.AvHashV128Binary
.op
) {
5875 case Pav_SHA256
: opc2
= 1666; break; // vshasigmaw
5876 case Pav_SHA512
: opc2
= 1730; break; // vshasigmad
5880 p
= mkFormVX( p
, 4, v_dst
, v_src
, s_field
->Pri
.Imm
, opc2
, endness_host
);
5883 case Pin_AvBCDV128Binary
: {
5884 UInt v_dst
= vregEnc(i
->Pin
.AvBCDV128Binary
.dst
);
5885 UInt v_src1
= vregEnc(i
->Pin
.AvBCDV128Binary
.src1
);
5886 UInt v_src2
= vregEnc(i
->Pin
.AvBCDV128Binary
.src2
);
5887 UInt ps
= 0; /* Issue the instruction with ps=0. The IR code will
5888 * fix up the result if ps=1.
5891 switch (i
->Pin
.AvBCDV128Binary
.op
) {
5892 case Pav_BCDAdd
: opc2
= 1; break; // bcdadd
5893 case Pav_BCDSub
: opc2
= 65; break; // bcdsub
5897 p
= mkFormVXR( p
, 4, v_dst
, v_src1
, v_src2
,
5898 0x1, ps
| opc2
, endness_host
);
5901 case Pin_AvBin32Fx4
: {
5902 UInt v_dst
= vregEnc(i
->Pin
.AvBin32Fx4
.dst
);
5903 UInt v_srcL
= vregEnc(i
->Pin
.AvBin32Fx4
.srcL
);
5904 UInt v_srcR
= vregEnc(i
->Pin
.AvBin32Fx4
.srcR
);
5905 switch (i
->Pin
.AvBin32Fx4
.op
) {
5908 p
= mkFormVX( p
, 4, v_dst
, v_srcL
, v_srcR
, 10, endness_host
); // vaddfp
5911 p
= mkFormVX( p
, 4, v_dst
, v_srcL
, v_srcR
, 74, endness_host
); // vsubfp
5914 p
= mkFormVX( p
, 4, v_dst
, v_srcL
, v_srcR
, 1034, endness_host
); // vmaxfp
5917 p
= mkFormVX( p
, 4, v_dst
, v_srcL
, v_srcR
, 1098, endness_host
); // vminfp
5921 /* Make a vmulfp from a vmaddfp:
5922 load -0.0 (0x8000_0000) to each 32-bit word of vB
5923 this makes the add a noop.
5925 UInt vB
= 29; // XXX: Using v29 for temp do not change
5926 // without also changing
5927 // getRegUsage_PPCInstr
5930 // Better way to load -0.0 (0x80000000) ?
5931 // vspltisw vB,0x1F (0x1F => each word of vB)
5932 p
= mkFormVX( p
, 4, vB
, konst
, 0, 908, endness_host
);
5934 // vslw vB,vB,vB (each word of vB = (0x1F << 0x1F) = 0x80000000
5935 p
= mkFormVX( p
, 4, vB
, vB
, vB
, 388, endness_host
);
5937 // Finally, do the multiply:
5938 p
= mkFormVA( p
, 4, v_dst
, v_srcL
, vB
, v_srcR
, 46, endness_host
);
5941 case Pavfp_CMPEQF
: // vcmpeqfp
5942 p
= mkFormVXR( p
, 4, v_dst
, v_srcL
, v_srcR
, 0, 198, endness_host
);
5944 case Pavfp_CMPGTF
: // vcmpgtfp
5945 p
= mkFormVXR( p
, 4, v_dst
, v_srcL
, v_srcR
, 0, 710, endness_host
);
5947 case Pavfp_CMPGEF
: // vcmpgefp
5948 p
= mkFormVXR( p
, 4, v_dst
, v_srcL
, v_srcR
, 0, 454, endness_host
);
5957 case Pin_AvUn32Fx4
: {
5958 UInt v_dst
= vregEnc(i
->Pin
.AvUn32Fx4
.dst
);
5959 UInt v_src
= vregEnc(i
->Pin
.AvUn32Fx4
.src
);
5961 switch (i
->Pin
.AvUn32Fx4
.op
) {
5962 case Pavfp_RCPF
: opc2
= 266; break; // vrefp
5963 case Pavfp_RSQRTF
: opc2
= 330; break; // vrsqrtefp
5964 case Pavfp_Log2
: opc2
= 458; break; // vlogefp
5965 case Pavfp_Exp2
: opc2
= 394; break; // vexptefp
5966 case Pavfp_CVTU2F
: opc2
= 778; break; // vcfux
5967 case Pavfp_CVTS2F
: opc2
= 842; break; // vcfsx
5968 case Pavfp_QCVTF2U
: opc2
= 906; break; // vctuxs
5969 case Pavfp_QCVTF2S
: opc2
= 970; break; // vctsxs
5970 case Pavfp_ROUNDM
: opc2
= 714; break; // vrfim
5971 case Pavfp_ROUNDP
: opc2
= 650; break; // vrfip
5972 case Pavfp_ROUNDN
: opc2
= 522; break; // vrfin
5973 case Pavfp_ROUNDZ
: opc2
= 586; break; // vrfiz
5977 p
= mkFormVX( p
, 4, v_dst
, 0, v_src
, opc2
, endness_host
);
5981 case Pin_AvPerm
: { // vperm
5982 UInt v_dst
= vregEnc(i
->Pin
.AvPerm
.dst
);
5983 UInt v_srcL
= vregEnc(i
->Pin
.AvPerm
.srcL
);
5984 UInt v_srcR
= vregEnc(i
->Pin
.AvPerm
.srcR
);
5985 UInt v_ctl
= vregEnc(i
->Pin
.AvPerm
.ctl
);
5986 p
= mkFormVA( p
, 4, v_dst
, v_srcL
, v_srcR
, v_ctl
, 43, endness_host
);
5990 case Pin_AvSel
: { // vsel
5991 UInt v_ctl
= vregEnc(i
->Pin
.AvSel
.ctl
);
5992 UInt v_dst
= vregEnc(i
->Pin
.AvSel
.dst
);
5993 UInt v_srcL
= vregEnc(i
->Pin
.AvSel
.srcL
);
5994 UInt v_srcR
= vregEnc(i
->Pin
.AvSel
.srcR
);
5995 p
= mkFormVA( p
, 4, v_dst
, v_srcL
, v_srcR
, v_ctl
, 42, endness_host
);
5999 case Pin_AvSh
: { // vsl or vsr
6000 UInt v_dst
= vregEnc(i
->Pin
.AvSh
.dst
);
6001 Bool idxd
= toBool(i
->Pin
.AvSh
.addr
->tag
== Pam_RR
);
6004 r_base
= iregEnc(i
->Pin
.AvSh
.addr
->Pam
.RR
.base
, mode64
);
6007 r_idx
= 30; // XXX: Using r30 as temp
6008 p
= mkLoadImm(p
, r_idx
,
6009 i
->Pin
.AvSh
.addr
->Pam
.IR
.index
, mode64
, endness_host
);
6011 r_idx
= iregEnc(i
->Pin
.AvSh
.addr
->Pam
.RR
.index
, mode64
);
6014 if (i
->Pin
.AvSh
.shLeft
)
6016 p
= mkFormVXI( p
, 31, v_dst
, r_idx
, r_base
, 6, endness_host
);
6019 p
= mkFormVXI( p
, 31, v_dst
, r_idx
, r_base
, 38, endness_host
);
6023 case Pin_AvShlDbl
: { // vsldoi
6024 UInt shift
= i
->Pin
.AvShlDbl
.shift
;
6025 UInt v_dst
= vregEnc(i
->Pin
.AvShlDbl
.dst
);
6026 UInt v_srcL
= vregEnc(i
->Pin
.AvShlDbl
.srcL
);
6027 UInt v_srcR
= vregEnc(i
->Pin
.AvShlDbl
.srcR
);
6028 vassert(shift
<= 0xF);
6029 p
= mkFormVA( p
, 4, v_dst
, v_srcL
, v_srcR
, shift
, 44, endness_host
);
6033 case Pin_AvSplat
: { // vsplt(is)(b,h,w)
6034 UInt v_dst
= vregEnc(i
->Pin
.AvShlDbl
.dst
);
6035 UChar sz
= i
->Pin
.AvSplat
.sz
;
6037 vassert(sz
== 8 || sz
== 16 || sz
== 32);
6039 if (i
->Pin
.AvSplat
.src
->tag
== Pvi_Imm
) {
6041 opc2
= (sz
== 8) ? 780 : (sz
== 16) ? 844 : 908; // 8,16,32
6042 /* expects 5-bit-signed-imm */
6043 simm5
= i
->Pin
.AvSplat
.src
->Pvi
.Imm5s
;
6044 vassert(simm5
>= -16 && simm5
<= 15);
6045 simm5
= simm5
& 0x1F;
6046 p
= mkFormVX( p
, 4, v_dst
, (UInt
)simm5
, 0, opc2
, endness_host
);
6050 opc2
= (sz
== 8) ? 524 : (sz
== 16) ? 588 : 652; // 8,16,32
6051 vassert(hregClass(i
->Pin
.AvSplat
.src
->Pvi
.Reg
) == HRcVec128
);
6052 v_src
= vregEnc(i
->Pin
.AvSplat
.src
->Pvi
.Reg
);
6053 lowest_lane
= (128/sz
)-1;
6054 p
= mkFormVX( p
, 4, v_dst
, lowest_lane
, v_src
, opc2
, endness_host
);
6060 UInt v_dst
= vregEnc(i
->Pin
.AvCMov
.dst
);
6061 UInt v_src
= vregEnc(i
->Pin
.AvCMov
.src
);
6062 PPCCondCode cc
= i
->Pin
.AvCMov
.cond
;
6064 if (v_dst
== v_src
) goto done
;
6066 vassert(cc
.test
!= Pct_ALWAYS
);
6068 /* jmp fwds 2 insns if !condition */
6069 if (cc
.test
!= Pct_ALWAYS
) {
6070 /* bc !ct,cf,n_bytes>>2 */
6071 p
= mkFormB(p
, invertCondTest(cc
.test
), cc
.flag
, 8>>2, 0, 0,
6075 p
= mkFormVX( p
, 4, v_dst
, v_src
, v_src
, 1156, endness_host
);
6079 case Pin_AvLdVSCR
: { // mtvscr
6080 UInt v_src
= vregEnc(i
->Pin
.AvLdVSCR
.src
);
6081 p
= mkFormVX( p
, 4, 0, 0, v_src
, 1604, endness_host
);
6085 case Pin_Dfp64Unary
: {
6086 UInt fr_dst
= fregEnc( i
->Pin
.FpUnary
.dst
);
6087 UInt fr_src
= fregEnc( i
->Pin
.FpUnary
.src
);
6089 switch (i
->Pin
.Dfp64Unary
.op
) {
6090 case Pfp_MOV
: // fmr, PPC32 p410
6091 p
= mkFormX( p
, 63, fr_dst
, 0, fr_src
, 72, 0, endness_host
);
6093 case Pfp_DCTDP
: // D32 to D64
6094 p
= mkFormX( p
, 59, fr_dst
, 0, fr_src
, 258, 0, endness_host
);
6096 case Pfp_DRSP
: // D64 to D32
6097 p
= mkFormX( p
, 59, fr_dst
, 0, fr_src
, 770, 0, endness_host
);
6099 case Pfp_DCFFIX
: // I64 to D64 conversion
6100 /* ONLY WORKS ON POWER7 */
6101 p
= mkFormX( p
, 59, fr_dst
, 0, fr_src
, 802, 0, endness_host
);
6103 case Pfp_DCTFIX
: // D64 to I64 conversion
6104 p
= mkFormX( p
, 59, fr_dst
, 0, fr_src
, 290, 0, endness_host
);
6106 case Pfp_DXEX
: // Extract exponent
6107 p
= mkFormX( p
, 59, fr_dst
, 0, fr_src
, 354, 0, endness_host
);
6115 case Pin_Dfp64Binary
: {
6116 UInt fr_dst
= fregEnc( i
->Pin
.Dfp64Binary
.dst
);
6117 UInt fr_srcL
= fregEnc( i
->Pin
.Dfp64Binary
.srcL
);
6118 UInt fr_srcR
= fregEnc( i
->Pin
.Dfp64Binary
.srcR
);
6119 switch (i
->Pin
.Dfp64Binary
.op
) {
6120 case Pfp_DFPADD
: /* dadd, dfp add, use default RM from reg ignore mode
6121 * from the Iop instruction. */
6122 p
= mkFormX( p
, 59, fr_dst
, fr_srcL
, fr_srcR
, 2, 0, endness_host
);
6124 case Pfp_DFPSUB
: /* dsub, dfp subtract, use default RM from reg ignore
6125 * mode from the Iop instruction. */
6126 p
= mkFormX( p
, 59, fr_dst
, fr_srcL
, fr_srcR
, 514, 0, endness_host
);
6128 case Pfp_DFPMUL
: /* dmul, dfp multipy, use default RM from reg ignore
6129 * mode from the Iop instruction. */
6130 p
= mkFormX( p
, 59, fr_dst
, fr_srcL
, fr_srcR
, 34, 0, endness_host
);
6132 case Pfp_DFPDIV
: /* ddiv, dfp divide, use default RM from reg ignore
6133 * mode from the Iop instruction. */
6134 p
= mkFormX( p
, 59, fr_dst
, fr_srcL
, fr_srcR
, 546, 0, endness_host
);
6136 case Pfp_DIEX
: /* diex, insert exponent */
6137 p
= mkFormX( p
, 59, fr_dst
, fr_srcL
, fr_srcR
, 866, 0, endness_host
);
6145 case Pin_DfpShift
: {
6146 UInt fr_src
= fregEnc(i
->Pin
.DfpShift
.src
);
6147 UInt fr_dst
= fregEnc(i
->Pin
.DfpShift
.dst
);
6150 shift
= i
->Pin
.DfpShift
.shift
->Pri
.Imm
;
6152 switch (i
->Pin
.DfpShift
.op
) {
6153 case Pfp_DSCLI
: /* dscli, DFP shift left by fr_srcR */
6154 p
= mkFormZ22( p
, 59, fr_dst
, fr_src
, shift
, 66, 0, endness_host
);
6156 case Pfp_DSCRI
: /* dscri, DFP shift right by fr_srcR */
6157 p
= mkFormZ22( p
, 59, fr_dst
, fr_src
, shift
, 98, 0, endness_host
);
6160 vex_printf("ERROR: emit_PPCInstr default case\n");
6166 case Pin_ExtractExpD128
: {
6167 UInt fr_dst
= fregEnc(i
->Pin
.ExtractExpD128
.dst
);
6168 UInt fr_srcHi
= fregEnc(i
->Pin
.ExtractExpD128
.src_hi
);
6169 UInt fr_srcLo
= fregEnc(i
->Pin
.ExtractExpD128
.src_lo
);
6171 switch (i
->Pin
.ExtractExpD128
.op
) {
6173 /* Setup the upper and lower registers of the source operand
6176 p
= mkFormX( p
, 63, 12, 0, fr_srcHi
, 72, 0, endness_host
);
6177 p
= mkFormX( p
, 63, 13, 0, fr_srcLo
, 72, 0, endness_host
);
6178 p
= mkFormX( p
, 63, 10, 0, 12, 354, 0, endness_host
);
6180 /* The instruction will put the 64-bit result in
6183 p
= mkFormX(p
, 63, fr_dst
, 0, 10, 72, 0, endness_host
);
6186 vex_printf("Error: emit_PPCInstr case Pin_DfpExtractExp, case inst Default\n");
6191 case Pin_Dfp128Unary
: {
6192 UInt fr_dstHi
= fregEnc(i
->Pin
.Dfp128Unary
.dst_hi
);
6193 UInt fr_dstLo
= fregEnc(i
->Pin
.Dfp128Unary
.dst_lo
);
6194 UInt fr_srcLo
= fregEnc(i
->Pin
.Dfp128Unary
.src_lo
);
6196 /* Do instruction with 128-bit source operands in registers (10,11)
6199 switch (i
->Pin
.Dfp128Unary
.op
) {
6200 case Pfp_DCTQPQ
: // D64 to D128, srcLo holds 64 bit operand
6201 p
= mkFormX( p
, 63, 12, 0, fr_srcLo
, 72, 0, endness_host
);
6203 p
= mkFormX( p
, 63, 10, 0, 12, 258, 0, endness_host
);
6205 /* The instruction will put the 128-bit result in
6206 * registers (10,11). Note, the operand in the instruction only
6207 * reference the first of the two registers in the pair.
6209 p
= mkFormX(p
, 63, fr_dstHi
, 0, 10, 72, 0, endness_host
);
6210 p
= mkFormX(p
, 63, fr_dstLo
, 0, 11, 72, 0, endness_host
);
6213 vex_printf("Error: emit_PPCInstr case Pin_Dfp128Unary, case inst Default\
6220 case Pin_Dfp128Binary
: {
6221 /* dst is used to supply the left source operand and return
6224 UInt fr_dstHi
= fregEnc( i
->Pin
.Dfp128Binary
.dst_hi
);
6225 UInt fr_dstLo
= fregEnc( i
->Pin
.Dfp128Binary
.dst_lo
);
6226 UInt fr_srcRHi
= fregEnc( i
->Pin
.Dfp128Binary
.srcR_hi
);
6227 UInt fr_srcRLo
= fregEnc( i
->Pin
.Dfp128Binary
.srcR_lo
);
6229 /* Setup the upper and lower registers of the source operand
6232 p
= mkFormX( p
, 63, 10, 0, fr_dstHi
, 72, 0, endness_host
);
6233 p
= mkFormX( p
, 63, 11, 0, fr_dstLo
, 72, 0, endness_host
);
6234 p
= mkFormX( p
, 63, 12, 0, fr_srcRHi
, 72, 0, endness_host
);
6235 p
= mkFormX( p
, 63, 13, 0, fr_srcRLo
, 72, 0, endness_host
);
6237 /* Do instruction with 128-bit source operands in registers (10,11)
6240 switch (i
->Pin
.Dfp128Binary
.op
) {
6242 p
= mkFormX( p
, 63, 10, 10, 12, 2, 0, endness_host
);
6245 p
= mkFormX( p
, 63, 10, 10, 12, 514, 0, endness_host
);
6248 p
= mkFormX( p
, 63, 10, 10, 12, 34, 0, endness_host
);
6251 p
= mkFormX( p
, 63, 10, 10, 12, 546, 0, endness_host
);
6257 /* The instruction will put the 128-bit result in
6258 * registers (10,11). Note, the operand in the instruction only
6259 * reference the first of the two registers in the pair.
6261 p
= mkFormX(p
, 63, fr_dstHi
, 0, 10, 72, 0, endness_host
);
6262 p
= mkFormX(p
, 63, fr_dstLo
, 0, 11, 72, 0, endness_host
);
6266 case Pin_DfpShift128
: {
6267 UInt fr_src_hi
= fregEnc(i
->Pin
.DfpShift128
.src_hi
);
6268 UInt fr_src_lo
= fregEnc(i
->Pin
.DfpShift128
.src_lo
);
6269 UInt fr_dst_hi
= fregEnc(i
->Pin
.DfpShift128
.dst_hi
);
6270 UInt fr_dst_lo
= fregEnc(i
->Pin
.DfpShift128
.dst_lo
);
6273 shift
= i
->Pin
.DfpShift128
.shift
->Pri
.Imm
;
6275 /* setup source operand in register 12, 13 pair */
6276 p
= mkFormX(p
, 63, 12, 0, fr_src_hi
, 72, 0, endness_host
);
6277 p
= mkFormX(p
, 63, 13, 0, fr_src_lo
, 72, 0, endness_host
);
6279 /* execute instruction putting result in register 10, 11 pair */
6280 switch (i
->Pin
.DfpShift128
.op
) {
6281 case Pfp_DSCLIQ
: /* dscliq, DFP shift left, fr_srcR is the integer
6284 p
= mkFormZ22( p
, 63, 10, 12, shift
, 66, 0, endness_host
);
6286 case Pfp_DSCRIQ
: /* dscriq, DFP shift right, fr_srcR is the integer
6289 p
= mkFormZ22( p
, 63, 10, 12, shift
, 98, 0, endness_host
);
6292 vex_printf("ERROR: emit_PPCInstr quad default case %d \n",
6293 (Int
)i
->Pin
.DfpShift128
.op
);
6297 /* The instruction put the 128-bit result in registers (10,11).
6298 * Note, the operand in the instruction only reference the first of
6299 * the two registers in the pair.
6301 p
= mkFormX(p
, 63, fr_dst_hi
, 0, 10, 72, 0, endness_host
);
6302 p
= mkFormX(p
, 63, fr_dst_lo
, 0, 11, 72, 0, endness_host
);
6306 case Pin_DfpRound
: {
6307 UInt fr_dst
= fregEnc(i
->Pin
.DfpRound
.dst
);
6308 UInt fr_src
= fregEnc(i
->Pin
.DfpRound
.src
);
6311 r_rmc
= i
->Pin
.DfpRound
.r_rmc
->Pri
.Imm
;
6312 r
= (r_rmc
& 0x8) >> 3;
6316 p
= mkFormZ23(p
, 59, fr_dst
, r
, fr_src
, rmc
, 99, 0, endness_host
);
6320 case Pin_DfpRound128
: {
6321 UInt fr_dstHi
= fregEnc(i
->Pin
.DfpRound128
.dst_hi
);
6322 UInt fr_dstLo
= fregEnc(i
->Pin
.DfpRound128
.dst_lo
);
6323 UInt fr_srcHi
= fregEnc(i
->Pin
.DfpRound128
.src_hi
);
6324 UInt fr_srcLo
= fregEnc(i
->Pin
.DfpRound128
.src_lo
);
6327 r_rmc
= i
->Pin
.DfpRound128
.r_rmc
->Pri
.Imm
;
6328 r
= (r_rmc
& 0x8) >> 3;
6331 /* Setup the upper and lower registers of the source operand
6334 p
= mkFormX(p
, 63, 12, 0, fr_srcHi
, 72, 0, endness_host
);
6335 p
= mkFormX(p
, 63, 13, 0, fr_srcLo
, 72, 0, endness_host
);
6337 /* Do drintx instruction with 128-bit source operands in
6338 * registers (12,13).
6340 p
= mkFormZ23(p
, 63, 10, r
, 12, rmc
, 99, 0, endness_host
);
6342 /* The instruction will put the 128-bit result in
6343 * registers (10,11). Note, the operand in the instruction only
6344 * reference the first of the two registers in the pair.
6346 p
= mkFormX(p
, 63, fr_dstHi
, 0, 10, 72, 0, endness_host
);
6347 p
= mkFormX(p
, 63, fr_dstLo
, 0, 11, 72, 0, endness_host
);
6351 case Pin_DfpQuantize
: {
6352 UInt fr_dst
= fregEnc(i
->Pin
.DfpQuantize
.dst
);
6353 UInt fr_srcL
= fregEnc(i
->Pin
.DfpQuantize
.srcL
);
6354 UInt fr_srcR
= fregEnc(i
->Pin
.DfpQuantize
.srcR
);
6357 rmc
= i
->Pin
.DfpQuantize
.rmc
->Pri
.Imm
;
6359 switch (i
->Pin
.DfpQuantize
.op
) {
6361 p
= mkFormZ23(p
, 59, fr_dst
, fr_srcL
, fr_srcR
, rmc
, 3, 0, endness_host
);
6364 p
= mkFormZ23(p
, 59, fr_dst
, fr_srcL
, fr_srcR
, rmc
, 35, 0, endness_host
);
6372 case Pin_DfpQuantize128
: {
6373 UInt fr_dst_hi
= fregEnc(i
->Pin
.DfpQuantize128
.dst_hi
);
6374 UInt fr_dst_lo
= fregEnc(i
->Pin
.DfpQuantize128
.dst_lo
);
6375 UInt fr_src_hi
= fregEnc(i
->Pin
.DfpQuantize128
.src_hi
);
6376 UInt fr_src_lo
= fregEnc(i
->Pin
.DfpQuantize128
.src_lo
);
6379 rmc
= i
->Pin
.DfpQuantize128
.rmc
->Pri
.Imm
;
6380 /* Setup the upper and lower registers of the source operand
6381 * register pairs. Note, left source operand passed in via the
6382 * dst register pair.
6384 p
= mkFormX(p
, 63, 10, 0, fr_dst_hi
, 72, 0, endness_host
);
6385 p
= mkFormX(p
, 63, 11, 0, fr_dst_lo
, 72, 0, endness_host
);
6386 p
= mkFormX(p
, 63, 12, 0, fr_src_hi
, 72, 0, endness_host
);
6387 p
= mkFormX(p
, 63, 13, 0, fr_src_lo
, 72, 0, endness_host
);
6389 /* Do dquaq instruction with 128-bit source operands in
6390 * registers (12,13).
6392 switch (i
->Pin
.DfpQuantize128
.op
) {
6394 p
= mkFormZ23(p
, 63, 10, 10, 12, rmc
, 3, 0, endness_host
);
6397 p
= mkFormZ23(p
, 63, 10, 10, 12, rmc
, 35, 0, endness_host
);
6400 vpanic("Pin_DfpQuantize128: default case, couldn't find inst to issue \n");
6404 /* The instruction will put the 128-bit result in
6405 * registers (10,11). Note, the operand in the instruction only
6406 * reference the first of the two registers in the pair.
6408 p
= mkFormX(p
, 63, fr_dst_hi
, 0, 10, 72, 0, endness_host
);
6409 p
= mkFormX(p
, 63, fr_dst_lo
, 0, 11, 72, 0, endness_host
);
6413 case Pin_DfpD128toD64
: {
6414 UInt fr_dst
= fregEnc( i
->Pin
.DfpD128toD64
.dst
);
6415 UInt fr_srcHi
= fregEnc( i
->Pin
.DfpD128toD64
.src_hi
);
6416 UInt fr_srcLo
= fregEnc( i
->Pin
.DfpD128toD64
.src_lo
);
6418 /* Setup the upper and lower registers of the source operand
6421 p
= mkFormX( p
, 63, 10, 0, fr_dst
, 72, 0, endness_host
);
6422 p
= mkFormX( p
, 63, 12, 0, fr_srcHi
, 72, 0, endness_host
);
6423 p
= mkFormX( p
, 63, 13, 0, fr_srcLo
, 72, 0, endness_host
);
6425 /* Do instruction with 128-bit source operands in registers (10,11) */
6426 switch (i
->Pin
.Dfp128Binary
.op
) {
6428 p
= mkFormX( p
, 63, 10, 0, 12, 770, 0, endness_host
);
6431 p
= mkFormX( p
, 63, 10, 0, 12, 290, 0, endness_host
);
6437 /* The instruction will put the 64-bit result in registers 10. */
6438 p
= mkFormX(p
, 63, fr_dst
, 0, 10, 72, 0, endness_host
);
6442 case Pin_DfpI64StoD128
: {
6443 UInt fr_dstHi
= fregEnc( i
->Pin
.DfpI64StoD128
.dst_hi
);
6444 UInt fr_dstLo
= fregEnc( i
->Pin
.DfpI64StoD128
.dst_lo
);
6445 UInt fr_src
= fregEnc( i
->Pin
.DfpI64StoD128
.src
);
6447 switch (i
->Pin
.Dfp128Binary
.op
) {
6449 p
= mkFormX( p
, 63, 10, 11, fr_src
, 802, 0, endness_host
);
6455 /* The instruction will put the 64-bit result in registers 10, 11. */
6456 p
= mkFormX(p
, 63, fr_dstHi
, 0, 10, 72, 0, endness_host
);
6457 p
= mkFormX(p
, 63, fr_dstLo
, 0, 11, 72, 0, endness_host
);
6461 case Pin_InsertExpD128
: {
6462 UInt fr_dstHi
= fregEnc(i
->Pin
.InsertExpD128
.dst_hi
);
6463 UInt fr_dstLo
= fregEnc(i
->Pin
.InsertExpD128
.dst_lo
);
6464 UInt fr_srcL
= fregEnc(i
->Pin
.InsertExpD128
.srcL
);
6465 UInt fr_srcRHi
= fregEnc(i
->Pin
.InsertExpD128
.srcR_hi
);
6466 UInt fr_srcRLo
= fregEnc(i
->Pin
.InsertExpD128
.srcR_lo
);
6468 /* The left operand is a single F64 value, the right is an F128
6471 p
= mkFormX(p
, 63, 10, 0, fr_srcL
, 72, 0, endness_host
);
6472 p
= mkFormX(p
, 63, 12, 0, fr_srcRHi
, 72, 0, endness_host
);
6473 p
= mkFormX(p
, 63, 13, 0, fr_srcRLo
, 72, 0, endness_host
);
6474 p
= mkFormX(p
, 63, 10, 10, 12, 866, 0, endness_host
);
6476 /* The instruction will put the 128-bit result into
6477 * registers (10,11). Note, the operand in the instruction only
6478 * reference the first of the two registers in the pair.
6480 p
= mkFormX(p
, 63, fr_dstHi
, 0, 10, 72, 0, endness_host
);
6481 p
= mkFormX(p
, 63, fr_dstLo
, 0, 11, 72, 0, endness_host
);
6487 UInt r_dst
= iregEnc(i
->Pin
.Dfp64Cmp
.dst
, mode64
);
6488 UInt fr_srcL
= fregEnc(i
->Pin
.Dfp64Cmp
.srcL
);
6489 UInt fr_srcR
= fregEnc(i
->Pin
.Dfp64Cmp
.srcR
);
6492 p
= mkFormX(p
, 59, crfD
<<2, fr_srcL
, fr_srcR
, 130, 0, endness_host
);
6494 // mfcr (mv CR to r_dst)
6495 p
= mkFormX(p
, 31, r_dst
, 0, 0, 19, 0, endness_host
);
6497 // rlwinm r_dst,r_dst,8,28,31
6498 // => rotate field 1 to bottomw of word, masking out upper 28
6499 p
= mkFormM(p
, 21, r_dst
, r_dst
, 8, 28, 31, 0, endness_host
);
6503 case Pin_Dfp128Cmp
: {
6505 UInt r_dst
= iregEnc(i
->Pin
.Dfp128Cmp
.dst
, mode64
);
6506 UInt fr_srcL_hi
= fregEnc(i
->Pin
.Dfp128Cmp
.srcL_hi
);
6507 UInt fr_srcL_lo
= fregEnc(i
->Pin
.Dfp128Cmp
.srcL_lo
);
6508 UInt fr_srcR_hi
= fregEnc(i
->Pin
.Dfp128Cmp
.srcR_hi
);
6509 UInt fr_srcR_lo
= fregEnc(i
->Pin
.Dfp128Cmp
.srcR_lo
);
6512 /* Setup the upper and lower registers of the source operand
6515 p
= mkFormX(p
, 63, 10, 0, fr_srcL_hi
, 72, 0, endness_host
);
6516 p
= mkFormX(p
, 63, 11, 0, fr_srcL_lo
, 72, 0, endness_host
);
6517 p
= mkFormX(p
, 63, 12, 0, fr_srcR_hi
, 72, 0, endness_host
);
6518 p
= mkFormX(p
, 63, 13, 0, fr_srcR_lo
, 72, 0, endness_host
);
6520 p
= mkFormX(p
, 63, crfD
<<2, 10, 12, 130, 0, endness_host
);
6522 // mfcr (mv CR to r_dst)
6523 p
= mkFormX(p
, 31, r_dst
, 0, 0, 19, 0, endness_host
);
6525 // rlwinm r_dst,r_dst,8,28,31
6526 // => rotate field 1 to bottomw of word, masking out upper 28
6527 p
= mkFormM(p
, 21, r_dst
, r_dst
, 8, 28, 31, 0, endness_host
);
6531 case Pin_XFormUnary994
: {
6533 switch (i
->Pin
.XFormUnary994
.op
) {
6535 case Px_IQSTODFP
: // dcffixqq
6537 UInt dstHi
= fregEnc(i
->Pin
.XFormUnary994
.reg0
);
6538 UInt dstLo
= fregEnc(i
->Pin
.XFormUnary994
.reg1
);
6539 UInt src
= vregEnc(i
->Pin
.XFormUnary994
.reg2
);
6542 /* Do instruction, 128-bit integer source operand, result in two
6543 floating point registers VSR(10,11) */
6544 /* dcffixqq put result in VSR[10], VSR[11] dword 0 */
6545 p
= mkFormX994( p
, inst_sel
, 10, src
, endness_host
);
6547 /* Move results to destination floating point register pair.
6548 Floating point regs are VSR[0] to VSR[31] */
6549 p
= mkFormX( p
, 63, dstHi
, 0, 10, 72, 0, endness_host
);
6550 p
= mkFormX( p
, 63, dstLo
, 0, 11, 72, 0, endness_host
);
6554 case Px_DFPTOIQS
: // dctfixqq
6556 UInt dstVSR
= vregEnc(i
->Pin
.XFormUnary994
.reg0
);
6557 UInt srcHi
= fregEnc(i
->Pin
.XFormUnary994
.reg1
);
6558 UInt srcLo
= fregEnc(i
->Pin
.XFormUnary994
.reg2
);
6561 /* Setup the upper and lower registers of the source operand
6564 p
= mkFormX( p
, 63, 10, 0, srcHi
, 72, 0, endness_host
);
6565 p
= mkFormX( p
, 63, 11, 0, srcLo
, 72, 0, endness_host
);
6567 /* Do instruction, two 64-bit source operands in registers floating
6568 point registers VSR(10,11) */
6569 p
= mkFormX994( p
, inst_sel
, dstVSR
, 10, endness_host
);
6579 /* This requires a 32-bit dec/test in both 32- and 64-bit
6586 lwz/ld r30, amFailAddr
6592 /* lwz r30, amCounter */
6593 p
= do_load_or_store_word32(p
, True
/*isLoad*/, /*r*/30,
6594 i
->Pin
.EvCheck
.amCounter
, mode64
,
6596 /* addic. r30,r30,-1 */
6597 p
= emit32(p
, 0x37DEFFFF, endness_host
);
6598 /* stw r30, amCounter */
6599 p
= do_load_or_store_word32(p
, False
/*!isLoad*/, /*r*/30,
6600 i
->Pin
.EvCheck
.amCounter
, mode64
,
6603 p
= emit32(p
, 0x40800010, endness_host
);
6604 /* lwz/ld r30, amFailAddr */
6605 p
= do_load_or_store_machine_word(p
, True
/*isLoad*/, /*r*/30,
6606 i
->Pin
.EvCheck
.amFailAddr
, mode64
,
6609 p
= mkFormXFX(p
, /*r*/30, 9, 467, endness_host
);
6611 p
= mkFormXL(p
, 19, Pct_ALWAYS
, 0, 0, 528, 0, endness_host
);
6615 vassert(evCheckSzB_PPC() == (UChar
*)p
- (UChar
*)p0
);
6621 (ctrP is unknown now, so use 0x65556555(65556555) in the
6622 expectation that a later call to LibVEX_patchProfCtr
6623 will be used to fill in the immediate fields once the
6624 right value is known.)
6626 imm32-exactly r30, 0x65556555
6634 imm64-exactly r30, 0x6555655565556555
6640 p
= mkLoadImm_EXACTLY2or5(
6641 p
, /*r*/30, 0x6555655565556555ULL
, True
/*mode64*/, endness_host
);
6642 p
= emit32(p
, 0xEBBE0000, endness_host
);
6643 p
= emit32(p
, 0x3BBD0001, endness_host
);
6644 p
= emit32(p
, 0xFBBE0000, endness_host
);
6646 p
= mkLoadImm_EXACTLY2or5(
6647 p
, /*r*/30, 0x65556555ULL
, False
/*!mode64*/, endness_host
);
6648 p
= emit32(p
, 0x83BE0004, endness_host
);
6649 p
= emit32(p
, 0x37BD0001, endness_host
);
6650 p
= emit32(p
, 0x93BE0004, endness_host
);
6651 p
= emit32(p
, 0x83BE0000, endness_host
);
6652 p
= emit32(p
, 0x7FBD0194, endness_host
);
6653 p
= emit32(p
, 0x93BE0000, endness_host
);
6655 /* Tell the caller .. */
6656 vassert(!(*is_profInc
));
6666 vex_printf("\n=> ");
6667 ppPPCInstr(i
, mode64
);
6668 vpanic("emit_PPCInstr");
6672 vassert(p
- &buf
[0] <= 64);
6677 /* How big is an event check? See case for Pin_EvCheck in
6678 emit_PPCInstr just above. That crosschecks what this returns, so
6679 we can tell if we're inconsistent. */
6680 Int
evCheckSzB_PPC (void)
6686 /* NB: what goes on here has to be very closely coordinated with the
6687 emitInstr case for XDirect, above. */
6688 VexInvalRange
chainXDirect_PPC ( VexEndness endness_host
,
6689 void* place_to_chain
,
6690 const void* disp_cp_chain_me_EXPECTED
,
6691 const void* place_to_jump_to
,
6695 vassert((endness_host
== VexEndnessBE
) ||
6696 (endness_host
== VexEndnessLE
));
6698 vassert(endness_host
== VexEndnessBE
);
6701 /* What we're expecting to see is:
6702 imm32/64-fixed r30, disp_cp_chain_me_to_EXPECTED
6706 <8 or 20 bytes generated by mkLoadImm_EXACTLY2or5>
6710 UChar
* p
= (UChar
*)place_to_chain
;
6711 vassert(0 == (3 & (HWord
)p
));
6712 vassert(isLoadImm_EXACTLY2or5(p
, /*r*/30,
6713 (Addr
)disp_cp_chain_me_EXPECTED
,
6714 mode64
, endness_host
));
6715 vassert(fetch32(p
+ (mode64
? 20 : 8) + 0, endness_host
) == 0x7FC903A6);
6716 vassert(fetch32(p
+ (mode64
? 20 : 8) + 4, endness_host
) == 0x4E800421);
6717 /* And what we want to change it to is:
6718 imm32/64-fixed r30, place_to_jump_to
6722 <8 or 20 bytes generated by mkLoadImm_EXACTLY2or5>
6725 The replacement has the same length as the original.
6727 p
= mkLoadImm_EXACTLY2or5(p
, /*r*/30,
6728 (Addr
)place_to_jump_to
, mode64
,
6730 p
= emit32(p
, 0x7FC903A6, endness_host
);
6731 p
= emit32(p
, 0x4E800420, endness_host
);
6733 Int len
= p
- (UChar
*)place_to_chain
;
6734 vassert(len
== (mode64
? 28 : 16)); /* stay sane */
6735 VexInvalRange vir
= {(HWord
)place_to_chain
, len
};
6740 /* NB: what goes on here has to be very closely coordinated with the
6741 emitInstr case for XDirect, above. */
6742 VexInvalRange
unchainXDirect_PPC ( VexEndness endness_host
,
6743 void* place_to_unchain
,
6744 const void* place_to_jump_to_EXPECTED
,
6745 const void* disp_cp_chain_me
,
6749 vassert((endness_host
== VexEndnessBE
) ||
6750 (endness_host
== VexEndnessLE
));
6752 vassert(endness_host
== VexEndnessBE
);
6755 /* What we're expecting to see is:
6756 imm32/64-fixed r30, place_to_jump_to_EXPECTED
6760 <8 or 20 bytes generated by mkLoadImm_EXACTLY2or5>
6764 UChar
* p
= (UChar
*)place_to_unchain
;
6765 vassert(0 == (3 & (HWord
)p
));
6766 vassert(isLoadImm_EXACTLY2or5(p
, /*r*/30,
6767 (Addr
)place_to_jump_to_EXPECTED
,
6768 mode64
, endness_host
));
6769 vassert(fetch32(p
+ (mode64
? 20 : 8) + 0, endness_host
) == 0x7FC903A6);
6770 vassert(fetch32(p
+ (mode64
? 20 : 8) + 4, endness_host
) == 0x4E800420);
6771 /* And what we want to change it to is:
6772 imm32/64-fixed r30, disp_cp_chain_me
6776 <8 or 20 bytes generated by mkLoadImm_EXACTLY2or5>
6779 The replacement has the same length as the original.
6781 p
= mkLoadImm_EXACTLY2or5(p
, /*r*/30,
6782 (Addr
)disp_cp_chain_me
, mode64
,
6784 p
= emit32(p
, 0x7FC903A6, endness_host
);
6785 p
= emit32(p
, 0x4E800421, endness_host
);
6787 Int len
= p
- (UChar
*)place_to_unchain
;
6788 vassert(len
== (mode64
? 28 : 16)); /* stay sane */
6789 VexInvalRange vir
= {(HWord
)place_to_unchain
, len
};
6794 /* Patch the counter address into a profile inc point, as previously
6795 created by the Pin_ProfInc case for emit_PPCInstr. */
6796 VexInvalRange
patchProfInc_PPC ( VexEndness endness_host
,
6797 void* place_to_patch
,
6798 const ULong
* location_of_counter
,
6802 vassert((endness_host
== VexEndnessBE
) ||
6803 (endness_host
== VexEndnessLE
));
6805 vassert(endness_host
== VexEndnessBE
);
6808 UChar
* p
= (UChar
*)place_to_patch
;
6809 vassert(0 == (3 & (HWord
)p
));
6813 vassert(isLoadImm_EXACTLY2or5(p
, /*r*/30,
6814 0x6555655565556555ULL
, True
/*mode64*/,
6816 vassert(fetch32(p
+ 20, endness_host
) == 0xEBBE0000);
6817 vassert(fetch32(p
+ 24, endness_host
) == 0x3BBD0001);
6818 vassert(fetch32(p
+ 28, endness_host
) == 0xFBBE0000);
6819 p
= mkLoadImm_EXACTLY2or5(p
, /*r*/30,
6820 (Addr
)location_of_counter
,
6821 True
/*mode64*/, endness_host
);
6822 len
= p
- (UChar
*)place_to_patch
;
6825 vassert(isLoadImm_EXACTLY2or5(p
, /*r*/30,
6826 0x65556555ULL
, False
/*!mode64*/,
6828 vassert(fetch32(p
+ 8, endness_host
) == 0x83BE0004);
6829 vassert(fetch32(p
+ 12, endness_host
) == 0x37BD0001);
6830 vassert(fetch32(p
+ 16, endness_host
) == 0x93BE0004);
6831 vassert(fetch32(p
+ 20, endness_host
) == 0x83BE0000);
6832 vassert(fetch32(p
+ 24, endness_host
) == 0x7FBD0194);
6833 vassert(fetch32(p
+ 28, endness_host
) == 0x93BE0000);
6834 p
= mkLoadImm_EXACTLY2or5(p
, /*r*/30,
6835 (Addr
)location_of_counter
,
6836 False
/*!mode64*/, endness_host
);
6837 len
= p
- (UChar
*)place_to_patch
;
6840 VexInvalRange vir
= {(HWord
)place_to_patch
, len
};
6845 /*---------------------------------------------------------------*/
6846 /*--- end host_ppc_defs.c ---*/
6847 /*---------------------------------------------------------------*/