blob: dc70f2426b98693cf0f14b365ebda84c8ef451fa [file] [log] [blame]
cerionbcf8c3e2005-02-04 16:17:07 +00001
2/*---------------------------------------------------------------*/
sewardj752f9062010-05-03 21:38:49 +00003/*--- begin host_ppc_defs.c ---*/
cerionbcf8c3e2005-02-04 16:17:07 +00004/*---------------------------------------------------------------*/
5
6/*
sewardj752f9062010-05-03 21:38:49 +00007 This file is part of Valgrind, a dynamic binary instrumentation
8 framework.
cerionbcf8c3e2005-02-04 16:17:07 +00009
sewardj785952d2015-08-21 11:29:16 +000010 Copyright (C) 2004-2015 OpenWorks LLP
sewardj752f9062010-05-03 21:38:49 +000011 info@open-works.net
cerionbcf8c3e2005-02-04 16:17:07 +000012
sewardj752f9062010-05-03 21:38:49 +000013 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.
cerionbcf8c3e2005-02-04 16:17:07 +000017
sewardj752f9062010-05-03 21:38:49 +000018 This program is distributed in the hope that it will be useful, but
19 WITHOUT ANY WARRANTY; without even the implied warranty of
20 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
21 General Public License for more details.
22
23 You should have received a copy of the GNU General Public License
24 along with this program; if not, write to the Free Software
25 Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
sewardj7bd6ffe2005-08-03 16:07:36 +000026 02110-1301, USA.
27
sewardj752f9062010-05-03 21:38:49 +000028 The GNU General Public License is contained in the file COPYING.
cerionbcf8c3e2005-02-04 16:17:07 +000029
30 Neither the names of the U.S. Department of Energy nor the
31 University of California nor the names of its contributors may be
32 used to endorse or promote products derived from this software
33 without prior written permission.
cerionbcf8c3e2005-02-04 16:17:07 +000034*/
35
36#include "libvex_basictypes.h"
37#include "libvex.h"
38#include "libvex_trc_values.h"
39
sewardjcef7d3e2009-07-02 12:21:59 +000040#include "main_util.h"
41#include "host_generic_regs.h"
42#include "host_ppc_defs.h"
cerionbcf8c3e2005-02-04 16:17:07 +000043
44
45/* --------- Registers. --------- */
46
sewardja5b50222015-03-26 07:18:32 +000047const RRegUniverse* getRRegUniverse_PPC ( Bool mode64 )
48{
49 /* The real-register universe is a big constant, so we just want to
50 initialise it once. rRegUniverse_PPC_initted values: 0=not initted,
51 1=initted for 32-bit-mode, 2=initted for 64-bit-mode */
52 static RRegUniverse rRegUniverse_PPC;
53 static UInt rRegUniverse_PPC_initted = 0;
54
55 /* Handy shorthand, nothing more */
56 RRegUniverse* ru = &rRegUniverse_PPC;
57
58 /* This isn't thread-safe. Sigh. */
59 UInt howNeeded = mode64 ? 2 : 1;
60 if (LIKELY(rRegUniverse_PPC_initted == howNeeded))
61 return ru;
62
63 RRegUniverse__init(ru);
64
65 /* Add the registers. The initial segment of this array must be
66 those available for allocation by reg-alloc, and those that
67 follow are not available for allocation. */
68 // GPR0 = scratch reg where poss. - some ops interpret as value zero
69 // GPR1 = stack pointer
70 // GPR2 = TOC pointer
71 ru->regs[ru->size++] = hregPPC_GPR3(mode64);
72 ru->regs[ru->size++] = hregPPC_GPR4(mode64);
73 ru->regs[ru->size++] = hregPPC_GPR5(mode64);
74 ru->regs[ru->size++] = hregPPC_GPR6(mode64);
75 ru->regs[ru->size++] = hregPPC_GPR7(mode64);
76 ru->regs[ru->size++] = hregPPC_GPR8(mode64);
77 ru->regs[ru->size++] = hregPPC_GPR9(mode64);
78 ru->regs[ru->size++] = hregPPC_GPR10(mode64);
79 if (!mode64) {
80 /* in mode64:
81 r11 used for calls by ptr / env ptr for some langs
82 r12 used for exception handling and global linkage code */
83 ru->regs[ru->size++] = hregPPC_GPR11(mode64);
84 ru->regs[ru->size++] = hregPPC_GPR12(mode64);
85 }
86 // GPR13 = thread specific pointer
87 // GPR14 and above are callee save. Yay.
88 ru->regs[ru->size++] = hregPPC_GPR14(mode64);
89 ru->regs[ru->size++] = hregPPC_GPR15(mode64);
90 ru->regs[ru->size++] = hregPPC_GPR16(mode64);
91 ru->regs[ru->size++] = hregPPC_GPR17(mode64);
92 ru->regs[ru->size++] = hregPPC_GPR18(mode64);
93 ru->regs[ru->size++] = hregPPC_GPR19(mode64);
94 ru->regs[ru->size++] = hregPPC_GPR20(mode64);
95 ru->regs[ru->size++] = hregPPC_GPR21(mode64);
96 ru->regs[ru->size++] = hregPPC_GPR22(mode64);
97 ru->regs[ru->size++] = hregPPC_GPR23(mode64);
98 ru->regs[ru->size++] = hregPPC_GPR24(mode64);
99 ru->regs[ru->size++] = hregPPC_GPR25(mode64);
100 ru->regs[ru->size++] = hregPPC_GPR26(mode64);
101 ru->regs[ru->size++] = hregPPC_GPR27(mode64);
102 ru->regs[ru->size++] = hregPPC_GPR28(mode64);
103 // GPR29 is reserved for the dispatcher
104 // GPR30 is reserved as AltiVec spill reg temporary
105 // GPR31 is reserved for the GuestStatePtr
106
107 /* Don't waste the reg-allocs's time trawling through zillions of
108 FP registers - they mostly will never be used. We'll tolerate
109 the occasional extra spill instead. */
110 /* For both ppc32-linux and ppc64-linux, f14-f31 are callee save.
111 So use them. */
112 ru->regs[ru->size++] = hregPPC_FPR14(mode64);
113 ru->regs[ru->size++] = hregPPC_FPR15(mode64);
114 ru->regs[ru->size++] = hregPPC_FPR16(mode64);
115 ru->regs[ru->size++] = hregPPC_FPR17(mode64);
116 ru->regs[ru->size++] = hregPPC_FPR18(mode64);
117 ru->regs[ru->size++] = hregPPC_FPR19(mode64);
118 ru->regs[ru->size++] = hregPPC_FPR20(mode64);
119 ru->regs[ru->size++] = hregPPC_FPR21(mode64);
120
121 /* Same deal re Altivec */
122 /* For both ppc32-linux and ppc64-linux, v20-v31 are callee save.
123 So use them. */
124 /* NB, vr29 is used as a scratch temporary -- do not allocate */
125 ru->regs[ru->size++] = hregPPC_VR20(mode64);
126 ru->regs[ru->size++] = hregPPC_VR21(mode64);
127 ru->regs[ru->size++] = hregPPC_VR22(mode64);
128 ru->regs[ru->size++] = hregPPC_VR23(mode64);
129 ru->regs[ru->size++] = hregPPC_VR24(mode64);
130 ru->regs[ru->size++] = hregPPC_VR25(mode64);
131 ru->regs[ru->size++] = hregPPC_VR26(mode64);
132 ru->regs[ru->size++] = hregPPC_VR27(mode64);
133 ru->allocable = ru->size;
134
135 /* And other regs, not available to the allocator. */
136 ru->regs[ru->size++] = hregPPC_GPR1(mode64);
137 ru->regs[ru->size++] = hregPPC_GPR29(mode64);
138 ru->regs[ru->size++] = hregPPC_GPR30(mode64);
139 ru->regs[ru->size++] = hregPPC_GPR31(mode64);
140 ru->regs[ru->size++] = hregPPC_VR29(mode64);
141
142 rRegUniverse_PPC_initted = howNeeded;
143
144 RRegUniverse__check_is_sane(ru);
145 return ru;
146}
147
148
cerion5b2325f2005-12-23 00:55:09 +0000149void ppHRegPPC ( HReg reg )
cerioncd304492005-02-08 19:40:24 +0000150{
151 Int r;
florian55085f82012-11-21 00:36:55 +0000152 static const HChar* ireg32_names[32]
cerion5b2325f2005-12-23 00:55:09 +0000153 = { "%r0", "%r1", "%r2", "%r3",
154 "%r4", "%r5", "%r6", "%r7",
155 "%r8", "%r9", "%r10", "%r11",
156 "%r12", "%r13", "%r14", "%r15",
157 "%r16", "%r17", "%r18", "%r19",
158 "%r20", "%r21", "%r22", "%r23",
159 "%r24", "%r25", "%r26", "%r27",
160 "%r28", "%r29", "%r30", "%r31" };
cerioncd304492005-02-08 19:40:24 +0000161 /* Be generic for all virtual regs. */
162 if (hregIsVirtual(reg)) {
163 ppHReg(reg);
164 return;
165 }
166 /* But specific for real regs. */
167 switch (hregClass(reg)) {
cerionf0de28c2005-12-13 20:21:11 +0000168 case HRcInt64:
sewardja5b50222015-03-26 07:18:32 +0000169 r = hregEncoding(reg);
cerionf0de28c2005-12-13 20:21:11 +0000170 vassert(r >= 0 && r < 32);
171 vex_printf("%s", ireg32_names[r]);
172 return;
cerionb85e8bb2005-02-16 08:54:33 +0000173 case HRcInt32:
sewardja5b50222015-03-26 07:18:32 +0000174 r = hregEncoding(reg);
cerionb85e8bb2005-02-16 08:54:33 +0000175 vassert(r >= 0 && r < 32);
176 vex_printf("%s", ireg32_names[r]);
177 return;
178 case HRcFlt64:
sewardja5b50222015-03-26 07:18:32 +0000179 r = hregEncoding(reg);
cerion094d1392005-06-20 13:45:57 +0000180 vassert(r >= 0 && r < 32);
181 vex_printf("%%fr%d", r);
cerionb85e8bb2005-02-16 08:54:33 +0000182 return;
cerionc3d8bdc2005-06-28 18:06:23 +0000183 case HRcVec128:
sewardja5b50222015-03-26 07:18:32 +0000184 r = hregEncoding(reg);
cerionc3d8bdc2005-06-28 18:06:23 +0000185 vassert(r >= 0 && r < 32);
186 vex_printf("%%v%d", r);
187 return;
cerionb85e8bb2005-02-16 08:54:33 +0000188 default:
cerion5b2325f2005-12-23 00:55:09 +0000189 vpanic("ppHRegPPC");
cerioncd304492005-02-08 19:40:24 +0000190 }
cerionbcf8c3e2005-02-04 16:17:07 +0000191}
192
cerionf0de28c2005-12-13 20:21:11 +0000193
cerion2c49e032005-02-09 17:29:49 +0000194/* --------- Condition codes, Intel encoding. --------- */
195
florian55085f82012-11-21 00:36:55 +0000196const HChar* showPPCCondCode ( PPCCondCode cond )
cerion2c49e032005-02-09 17:29:49 +0000197{
cerionab9132d2005-02-15 15:46:59 +0000198 if (cond.test == Pct_ALWAYS) return "always";
199
200 switch (cond.flag) {
cerion5b2325f2005-12-23 00:55:09 +0000201 case Pcf_7SO:
202 return (cond.test == Pct_TRUE) ? "cr7.so=1" : "cr7.so=0";
203 case Pcf_7EQ:
204 return (cond.test == Pct_TRUE) ? "cr7.eq=1" : "cr7.eq=0";
205 case Pcf_7GT:
206 return (cond.test == Pct_TRUE) ? "cr7.gt=1" : "cr7.gt=0";
207 case Pcf_7LT:
208 return (cond.test == Pct_TRUE) ? "cr7.lt=1" : "cr7.lt=0";
sewardj7e308072011-05-04 09:50:48 +0000209 case Pcf_NONE:
210 return "no-flag";
cerion5b2325f2005-12-23 00:55:09 +0000211 default: vpanic("ppPPCCondCode");
cerion2c49e032005-02-09 17:29:49 +0000212 }
cerionbcf8c3e2005-02-04 16:17:07 +0000213}
214
cerioned623db2005-06-20 12:42:04 +0000215/* construct condition code */
cerion5b2325f2005-12-23 00:55:09 +0000216PPCCondCode mk_PPCCondCode ( PPCCondTest test, PPCCondFlag flag )
cerion7cf8e4e2005-02-16 16:08:17 +0000217{
cerion5b2325f2005-12-23 00:55:09 +0000218 PPCCondCode cc;
cerion7cf8e4e2005-02-16 16:08:17 +0000219 cc.flag = flag;
220 cc.test = test;
sewardj7e308072011-05-04 09:50:48 +0000221 if (test == Pct_ALWAYS) {
222 vassert(flag == Pcf_NONE);
223 } else {
224 vassert(flag != Pcf_NONE);
225 }
cerion7cf8e4e2005-02-16 16:08:17 +0000226 return cc;
227}
228
229/* false->true, true->false */
cerion5b2325f2005-12-23 00:55:09 +0000230PPCCondTest invertCondTest ( PPCCondTest ct )
cerion33aa6da2005-02-16 10:25:26 +0000231{
232 vassert(ct != Pct_ALWAYS);
233 return (ct == Pct_TRUE) ? Pct_FALSE : Pct_TRUE;
234}
235
236
cerioncd304492005-02-08 19:40:24 +0000237/* --------- PPCAMode: memory address expressions. --------- */
238
cerion5b2325f2005-12-23 00:55:09 +0000239PPCAMode* PPCAMode_IR ( Int idx, HReg base ) {
floriand8e3eca2015-03-13 12:46:49 +0000240 PPCAMode* am = LibVEX_Alloc_inline(sizeof(PPCAMode));
sewardja5f957d2005-07-02 01:29:32 +0000241 vassert(idx >= -0x8000 && idx < 0x8000);
cerioncd304492005-02-08 19:40:24 +0000242 am->tag = Pam_IR;
243 am->Pam.IR.base = base;
244 am->Pam.IR.index = idx;
245 return am;
246}
cerion5b2325f2005-12-23 00:55:09 +0000247PPCAMode* PPCAMode_RR ( HReg idx, HReg base ) {
floriand8e3eca2015-03-13 12:46:49 +0000248 PPCAMode* am = LibVEX_Alloc_inline(sizeof(PPCAMode));
cerioncd304492005-02-08 19:40:24 +0000249 am->tag = Pam_RR;
250 am->Pam.RR.base = base;
251 am->Pam.RR.index = idx;
252 return am;
253}
254
cerion5b2325f2005-12-23 00:55:09 +0000255PPCAMode* dopyPPCAMode ( PPCAMode* am ) {
cerioncd304492005-02-08 19:40:24 +0000256 switch (am->tag) {
cerionb85e8bb2005-02-16 08:54:33 +0000257 case Pam_IR:
cerion5b2325f2005-12-23 00:55:09 +0000258 return PPCAMode_IR( am->Pam.IR.index, am->Pam.IR.base );
cerionb85e8bb2005-02-16 08:54:33 +0000259 case Pam_RR:
cerion5b2325f2005-12-23 00:55:09 +0000260 return PPCAMode_RR( am->Pam.RR.index, am->Pam.RR.base );
cerionb85e8bb2005-02-16 08:54:33 +0000261 default:
cerion5b2325f2005-12-23 00:55:09 +0000262 vpanic("dopyPPCAMode");
cerioncd304492005-02-08 19:40:24 +0000263 }
264}
265
cerion5b2325f2005-12-23 00:55:09 +0000266void ppPPCAMode ( PPCAMode* am ) {
cerioncd304492005-02-08 19:40:24 +0000267 switch (am->tag) {
cerionb85e8bb2005-02-16 08:54:33 +0000268 case Pam_IR:
269 if (am->Pam.IR.index == 0)
cerionf9d6e222005-02-23 18:21:31 +0000270 vex_printf("0(");
cerionb85e8bb2005-02-16 08:54:33 +0000271 else
sewardja5f957d2005-07-02 01:29:32 +0000272 vex_printf("%d(", (Int)am->Pam.IR.index);
cerion5b2325f2005-12-23 00:55:09 +0000273 ppHRegPPC(am->Pam.IR.base);
cerionb85e8bb2005-02-16 08:54:33 +0000274 vex_printf(")");
275 return;
276 case Pam_RR:
cerion5b2325f2005-12-23 00:55:09 +0000277 ppHRegPPC(am->Pam.RR.base);
cerionb85e8bb2005-02-16 08:54:33 +0000278 vex_printf(",");
cerion5b2325f2005-12-23 00:55:09 +0000279 ppHRegPPC(am->Pam.RR.index);
cerionb85e8bb2005-02-16 08:54:33 +0000280 return;
281 default:
cerion5b2325f2005-12-23 00:55:09 +0000282 vpanic("ppPPCAMode");
cerioncd304492005-02-08 19:40:24 +0000283 }
284}
285
cerion5b2325f2005-12-23 00:55:09 +0000286static void addRegUsage_PPCAMode ( HRegUsage* u, PPCAMode* am ) {
cerioncd304492005-02-08 19:40:24 +0000287 switch (am->tag) {
cerionb85e8bb2005-02-16 08:54:33 +0000288 case Pam_IR:
289 addHRegUse(u, HRmRead, am->Pam.IR.base);
290 return;
291 case Pam_RR:
292 addHRegUse(u, HRmRead, am->Pam.RR.base);
293 addHRegUse(u, HRmRead, am->Pam.RR.index);
294 return;
295 default:
cerion5b2325f2005-12-23 00:55:09 +0000296 vpanic("addRegUsage_PPCAMode");
cerioncd304492005-02-08 19:40:24 +0000297 }
298}
cerioncd304492005-02-08 19:40:24 +0000299
cerion5b2325f2005-12-23 00:55:09 +0000300static void mapRegs_PPCAMode ( HRegRemap* m, PPCAMode* am ) {
cerioncd304492005-02-08 19:40:24 +0000301 switch (am->tag) {
cerionb85e8bb2005-02-16 08:54:33 +0000302 case Pam_IR:
303 am->Pam.IR.base = lookupHRegRemap(m, am->Pam.IR.base);
304 return;
305 case Pam_RR:
306 am->Pam.RR.base = lookupHRegRemap(m, am->Pam.RR.base);
307 am->Pam.RR.index = lookupHRegRemap(m, am->Pam.RR.index);
308 return;
309 default:
cerion5b2325f2005-12-23 00:55:09 +0000310 vpanic("mapRegs_PPCAMode");
cerioncd304492005-02-08 19:40:24 +0000311 }
312}
cerioncd304492005-02-08 19:40:24 +0000313
sewardjb51f0f42005-07-18 11:38:02 +0000314/* --------- Operand, which can be a reg or a u16/s16. --------- */
315
cerion5b2325f2005-12-23 00:55:09 +0000316PPCRH* PPCRH_Imm ( Bool syned, UShort imm16 ) {
floriand8e3eca2015-03-13 12:46:49 +0000317 PPCRH* op = LibVEX_Alloc_inline(sizeof(PPCRH));
sewardjb51f0f42005-07-18 11:38:02 +0000318 op->tag = Prh_Imm;
319 op->Prh.Imm.syned = syned;
320 op->Prh.Imm.imm16 = imm16;
321 /* If this is a signed value, ensure it's not -32768, so that we
322 are guaranteed always to be able to negate if needed. */
323 if (syned)
324 vassert(imm16 != 0x8000);
325 vassert(syned == True || syned == False);
326 return op;
327}
cerion5b2325f2005-12-23 00:55:09 +0000328PPCRH* PPCRH_Reg ( HReg reg ) {
floriand8e3eca2015-03-13 12:46:49 +0000329 PPCRH* op = LibVEX_Alloc_inline(sizeof(PPCRH));
sewardjb51f0f42005-07-18 11:38:02 +0000330 op->tag = Prh_Reg;
331 op->Prh.Reg.reg = reg;
332 return op;
333}
334
cerion5b2325f2005-12-23 00:55:09 +0000335void ppPPCRH ( PPCRH* op ) {
sewardjb51f0f42005-07-18 11:38:02 +0000336 switch (op->tag) {
337 case Prh_Imm:
338 if (op->Prh.Imm.syned)
339 vex_printf("%d", (Int)(Short)op->Prh.Imm.imm16);
340 else
sewardjc7cd2142005-09-09 22:31:49 +0000341 vex_printf("%u", (UInt)(UShort)op->Prh.Imm.imm16);
sewardjb51f0f42005-07-18 11:38:02 +0000342 return;
343 case Prh_Reg:
cerion5b2325f2005-12-23 00:55:09 +0000344 ppHRegPPC(op->Prh.Reg.reg);
sewardjb51f0f42005-07-18 11:38:02 +0000345 return;
346 default:
cerion5b2325f2005-12-23 00:55:09 +0000347 vpanic("ppPPCRH");
sewardjb51f0f42005-07-18 11:38:02 +0000348 }
349}
350
cerion5b2325f2005-12-23 00:55:09 +0000351/* An PPCRH can only be used in a "read" context (what would it mean
sewardjb51f0f42005-07-18 11:38:02 +0000352 to write or modify a literal?) and so we enumerate its registers
353 accordingly. */
cerion5b2325f2005-12-23 00:55:09 +0000354static void addRegUsage_PPCRH ( HRegUsage* u, PPCRH* op ) {
sewardjb51f0f42005-07-18 11:38:02 +0000355 switch (op->tag) {
356 case Prh_Imm:
357 return;
358 case Prh_Reg:
359 addHRegUse(u, HRmRead, op->Prh.Reg.reg);
360 return;
361 default:
cerion5b2325f2005-12-23 00:55:09 +0000362 vpanic("addRegUsage_PPCRH");
sewardjb51f0f42005-07-18 11:38:02 +0000363 }
364}
365
cerion5b2325f2005-12-23 00:55:09 +0000366static void mapRegs_PPCRH ( HRegRemap* m, PPCRH* op ) {
sewardjb51f0f42005-07-18 11:38:02 +0000367 switch (op->tag) {
368 case Prh_Imm:
369 return;
370 case Prh_Reg:
371 op->Prh.Reg.reg = lookupHRegRemap(m, op->Prh.Reg.reg);
372 return;
373 default:
cerion5b2325f2005-12-23 00:55:09 +0000374 vpanic("mapRegs_PPCRH");
sewardjb51f0f42005-07-18 11:38:02 +0000375 }
376}
377
378
cerionf0de28c2005-12-13 20:21:11 +0000379/* --------- Operand, which can be a reg or a u32/64. --------- */
cerioncd304492005-02-08 19:40:24 +0000380
cerion5b2325f2005-12-23 00:55:09 +0000381PPCRI* PPCRI_Imm ( ULong imm64 ) {
floriand8e3eca2015-03-13 12:46:49 +0000382 PPCRI* op = LibVEX_Alloc_inline(sizeof(PPCRI));
cerionf0de28c2005-12-13 20:21:11 +0000383 op->tag = Pri_Imm;
384 op->Pri.Imm = imm64;
cerioncd304492005-02-08 19:40:24 +0000385 return op;
386}
cerion5b2325f2005-12-23 00:55:09 +0000387PPCRI* PPCRI_Reg ( HReg reg ) {
floriand8e3eca2015-03-13 12:46:49 +0000388 PPCRI* op = LibVEX_Alloc_inline(sizeof(PPCRI));
cerionf0de28c2005-12-13 20:21:11 +0000389 op->tag = Pri_Reg;
390 op->Pri.Reg = reg;
cerioncd304492005-02-08 19:40:24 +0000391 return op;
392}
393
cerion5b2325f2005-12-23 00:55:09 +0000394void ppPPCRI ( PPCRI* dst ) {
sewardjb51f0f42005-07-18 11:38:02 +0000395 switch (dst->tag) {
396 case Pri_Imm:
cerionf0de28c2005-12-13 20:21:11 +0000397 vex_printf("0x%llx", dst->Pri.Imm);
sewardjb51f0f42005-07-18 11:38:02 +0000398 break;
399 case Pri_Reg:
cerion5b2325f2005-12-23 00:55:09 +0000400 ppHRegPPC(dst->Pri.Reg);
sewardjb51f0f42005-07-18 11:38:02 +0000401 break;
402 default:
cerion5b2325f2005-12-23 00:55:09 +0000403 vpanic("ppPPCRI");
cerioncd304492005-02-08 19:40:24 +0000404 }
405}
406
cerion5b2325f2005-12-23 00:55:09 +0000407/* An PPCRI can only be used in a "read" context (what would it
sewardjb51f0f42005-07-18 11:38:02 +0000408 mean to write or modify a literal?) and so we enumerate its
409 registers accordingly. */
cerion5b2325f2005-12-23 00:55:09 +0000410static void addRegUsage_PPCRI ( HRegUsage* u, PPCRI* dst ) {
sewardjb51f0f42005-07-18 11:38:02 +0000411 switch (dst->tag) {
412 case Pri_Imm:
413 return;
414 case Pri_Reg:
415 addHRegUse(u, HRmRead, dst->Pri.Reg);
416 return;
417 default:
cerion5b2325f2005-12-23 00:55:09 +0000418 vpanic("addRegUsage_PPCRI");
cerioncd304492005-02-08 19:40:24 +0000419 }
420}
421
cerion5b2325f2005-12-23 00:55:09 +0000422static void mapRegs_PPCRI ( HRegRemap* m, PPCRI* dst ) {
sewardjb51f0f42005-07-18 11:38:02 +0000423 switch (dst->tag) {
424 case Pri_Imm:
425 return;
426 case Pri_Reg:
427 dst->Pri.Reg = lookupHRegRemap(m, dst->Pri.Reg);
428 return;
429 default:
cerion5b2325f2005-12-23 00:55:09 +0000430 vpanic("mapRegs_PPCRI");
cerioncd304492005-02-08 19:40:24 +0000431 }
432}
433
sewardjb51f0f42005-07-18 11:38:02 +0000434
cerion27b3d7e2005-09-14 20:35:47 +0000435/* --------- Operand, which can be a vector reg or a simm5. --------- */
436
cerion5b2325f2005-12-23 00:55:09 +0000437PPCVI5s* PPCVI5s_Imm ( Char simm5 ) {
floriand8e3eca2015-03-13 12:46:49 +0000438 PPCVI5s* op = LibVEX_Alloc_inline(sizeof(PPCVI5s));
cerion27b3d7e2005-09-14 20:35:47 +0000439 op->tag = Pvi_Imm;
440 op->Pvi.Imm5s = simm5;
441 vassert(simm5 >= -16 && simm5 <= 15);
442 return op;
443}
cerion5b2325f2005-12-23 00:55:09 +0000444PPCVI5s* PPCVI5s_Reg ( HReg reg ) {
floriand8e3eca2015-03-13 12:46:49 +0000445 PPCVI5s* op = LibVEX_Alloc_inline(sizeof(PPCVI5s));
cerion5b2325f2005-12-23 00:55:09 +0000446 op->tag = Pvi_Reg;
447 op->Pvi.Reg = reg;
cerion27b3d7e2005-09-14 20:35:47 +0000448 vassert(hregClass(reg) == HRcVec128);
449 return op;
450}
451
cerion5b2325f2005-12-23 00:55:09 +0000452void ppPPCVI5s ( PPCVI5s* src ) {
cerion27b3d7e2005-09-14 20:35:47 +0000453 switch (src->tag) {
454 case Pvi_Imm:
455 vex_printf("%d", (Int)src->Pvi.Imm5s);
456 break;
457 case Pvi_Reg:
cerion5b2325f2005-12-23 00:55:09 +0000458 ppHRegPPC(src->Pvi.Reg);
cerion27b3d7e2005-09-14 20:35:47 +0000459 break;
460 default:
cerion5b2325f2005-12-23 00:55:09 +0000461 vpanic("ppPPCVI5s");
cerion27b3d7e2005-09-14 20:35:47 +0000462 }
463}
464
cerion5b2325f2005-12-23 00:55:09 +0000465/* An PPCVI5s can only be used in a "read" context (what would it
cerion27b3d7e2005-09-14 20:35:47 +0000466 mean to write or modify a literal?) and so we enumerate its
467 registers accordingly. */
cerion5b2325f2005-12-23 00:55:09 +0000468static void addRegUsage_PPCVI5s ( HRegUsage* u, PPCVI5s* dst ) {
cerion27b3d7e2005-09-14 20:35:47 +0000469 switch (dst->tag) {
470 case Pvi_Imm:
471 return;
472 case Pvi_Reg:
473 addHRegUse(u, HRmRead, dst->Pvi.Reg);
474 return;
475 default:
cerion5b2325f2005-12-23 00:55:09 +0000476 vpanic("addRegUsage_PPCVI5s");
cerion27b3d7e2005-09-14 20:35:47 +0000477 }
478}
479
cerion5b2325f2005-12-23 00:55:09 +0000480static void mapRegs_PPCVI5s ( HRegRemap* m, PPCVI5s* dst ) {
cerion27b3d7e2005-09-14 20:35:47 +0000481 switch (dst->tag) {
482 case Pvi_Imm:
483 return;
484 case Pvi_Reg:
485 dst->Pvi.Reg = lookupHRegRemap(m, dst->Pvi.Reg);
486 return;
487 default:
cerion5b2325f2005-12-23 00:55:09 +0000488 vpanic("mapRegs_PPCVI5s");
cerion27b3d7e2005-09-14 20:35:47 +0000489 }
490}
491
492
cerioncd304492005-02-08 19:40:24 +0000493/* --------- Instructions. --------- */
494
florian55085f82012-11-21 00:36:55 +0000495const HChar* showPPCUnaryOp ( PPCUnaryOp op ) {
cerion2c49e032005-02-09 17:29:49 +0000496 switch (op) {
cerion5b2325f2005-12-23 00:55:09 +0000497 case Pun_NOT: return "not";
498 case Pun_NEG: return "neg";
cerion07b07a92005-12-22 14:32:35 +0000499 case Pun_CLZ32: return "cntlzw";
500 case Pun_CLZ64: return "cntlzd";
Elliott Hughesa0664b92017-04-18 17:46:52 -0700501 case Pun_CTZ32: return "cnttzw";
502 case Pun_CTZ64: return "cnttzd";
sewardj7fd5bb02006-01-26 02:24:17 +0000503 case Pun_EXTSW: return "extsw";
cerion5b2325f2005-12-23 00:55:09 +0000504 default: vpanic("showPPCUnaryOp");
cerion2c49e032005-02-09 17:29:49 +0000505 }
506}
cerioncd304492005-02-08 19:40:24 +0000507
florian55085f82012-11-21 00:36:55 +0000508const HChar* showPPCAluOp ( PPCAluOp op, Bool immR ) {
cerioncd304492005-02-08 19:40:24 +0000509 switch (op) {
sewardjb51f0f42005-07-18 11:38:02 +0000510 case Palu_ADD: return immR ? "addi" : "add";
511 case Palu_SUB: return immR ? "subi" : "sub";
512 case Palu_AND: return immR ? "andi." : "and";
513 case Palu_OR: return immR ? "ori" : "or";
514 case Palu_XOR: return immR ? "xori" : "xor";
cerion5b2325f2005-12-23 00:55:09 +0000515 default: vpanic("showPPCAluOp");
cerionab9132d2005-02-15 15:46:59 +0000516 }
517}
518
florian55085f82012-11-21 00:36:55 +0000519const HChar* showPPCShftOp ( PPCShftOp op, Bool immR, Bool sz32 ) {
cerionbb01b7c2005-12-16 13:40:18 +0000520 switch (op) {
521 case Pshft_SHL: return sz32 ? (immR ? "slwi" : "slw") :
522 (immR ? "sldi" : "sld");
523 case Pshft_SHR: return sz32 ? (immR ? "srwi" : "srw") :
524 (immR ? "srdi" : "srd");
525 case Pshft_SAR: return sz32 ? (immR ? "srawi" : "sraw") :
526 (immR ? "sradi" : "srad");
cerion5b2325f2005-12-23 00:55:09 +0000527 default: vpanic("showPPCShftOp");
cerionbb01b7c2005-12-16 13:40:18 +0000528 }
529}
530
florian55085f82012-11-21 00:36:55 +0000531const HChar* showPPCFpOp ( PPCFpOp op ) {
cerion094d1392005-06-20 13:45:57 +0000532 switch (op) {
sewardjb183b852006-02-03 16:08:03 +0000533 case Pfp_ADDD: return "fadd";
534 case Pfp_SUBD: return "fsub";
535 case Pfp_MULD: return "fmul";
536 case Pfp_DIVD: return "fdiv";
sewardj40c80262006-02-08 19:30:46 +0000537 case Pfp_MADDD: return "fmadd";
538 case Pfp_MSUBD: return "fmsub";
539 case Pfp_MADDS: return "fmadds";
540 case Pfp_MSUBS: return "fmsubs";
sewardjb183b852006-02-03 16:08:03 +0000541 case Pfp_ADDS: return "fadds";
542 case Pfp_SUBS: return "fsubs";
543 case Pfp_MULS: return "fmuls";
544 case Pfp_DIVS: return "fdivs";
cerion094d1392005-06-20 13:45:57 +0000545 case Pfp_SQRT: return "fsqrt";
546 case Pfp_ABS: return "fabs";
547 case Pfp_NEG: return "fneg";
548 case Pfp_MOV: return "fmr";
sewardjbaf971a2006-01-27 15:09:35 +0000549 case Pfp_RES: return "fres";
550 case Pfp_RSQRTE: return "frsqrte";
sewardj0f1ef862008-08-08 08:37:06 +0000551 case Pfp_FRIM: return "frim";
552 case Pfp_FRIN: return "frin";
553 case Pfp_FRIP: return "frip";
554 case Pfp_FRIZ: return "friz";
Elliott Hughesa0664b92017-04-18 17:46:52 -0700555 case Pfp_FPADDQ: return "xsaddqp";
556 case Pfp_FPSUBQ: return "xsubqp";
557 case Pfp_FPMULQ: return "xsmulqp";
558 case Pfp_FPDIVQ: return "xsdivqp";
559 case Pfp_FPMULADDQ: return "xsmaddqp";
560 case Pfp_FPMULSUBQ: return "xsmsubqp";
561 case Pfp_FPNEGMULADDQ: return "xsnmaddqp";
562 case Pfp_FPNEGMULSUBQ: return "xsnmsubqp";
563 case Pfp_FPADDQRNDODD: return "xsaddqpo";
564 case Pfp_FPSUBQRNDODD: return "xsubqpo";
565 case Pfp_FPMULQRNDODD: return "xsmulqpo";
566 case Pfp_FPDIVQRNDODD: return "xsaddqpo";
567 case Pfp_FPMULADDQRNDODD: return "xsmaddqpo";
568 case Pfp_FPMULSUBQRNDODD: return "xsmsubqpo";
569 case Pfp_FPNEGMULADDQRNDODD: return "xsnmaddqpo";
570 case Pfp_FPNEGMULSUBQRNDODD: return "xsnmsubqpo";
571 case Pfp_FPQTOD: return "xscvqpdp";
572 case Pfp_FPQTODRNDODD: return "xscvqpdpo";
573 case Pfp_FPDTOQ: return "xscvdpqp";
574 case Pfp_IDSTOQ: return "xscvsdqp";
575 case Pfp_IDUTOQ: return "xscvudqp";
576 case Pfp_TRUNCFPQTOISD: return "xscvqpsdz";
577 case Pfp_TRUNCFPQTOISW: return "xscvqpswz";
578 case Pfp_TRUNCFPQTOIUD: return "xscvqpudz";
579 case Pfp_TRUNCFPQTOIUW: return "xscvqpuwz";
sewardjc6bbd472012-04-02 10:20:48 +0000580 case Pfp_DFPADD: return "dadd";
581 case Pfp_DFPADDQ: return "daddq";
582 case Pfp_DFPSUB: return "dsub";
583 case Pfp_DFPSUBQ: return "dsubq";
584 case Pfp_DFPMUL: return "dmul";
585 case Pfp_DFPMULQ: return "dmulq";
586 case Pfp_DFPDIV: return "ddivd";
587 case Pfp_DFPDIVQ: return "ddivq";
sewardj26217b02012-04-12 17:19:48 +0000588 case Pfp_DCTDP: return "dctdp";
589 case Pfp_DRSP: return "drsp";
590 case Pfp_DCTFIX: return "dctfix";
591 case Pfp_DCFFIX: return "dcffix";
592 case Pfp_DCTQPQ: return "dctqpq";
593 case Pfp_DCFFIXQ: return "dcffixq";
sewardjcdc376d2012-04-23 11:21:12 +0000594 case Pfp_DQUA: return "dqua";
595 case Pfp_DQUAQ: return "dquaq";
596 case Pfp_DXEX: return "dxex";
597 case Pfp_DXEXQ: return "dxexq";
598 case Pfp_DIEX: return "diex";
599 case Pfp_DIEXQ: return "diexq";
600 case Pfp_RRDTR: return "rrdtr";
cerion5b2325f2005-12-23 00:55:09 +0000601 default: vpanic("showPPCFpOp");
cerion094d1392005-06-20 13:45:57 +0000602 }
603}
cerioncd304492005-02-08 19:40:24 +0000604
florian55085f82012-11-21 00:36:55 +0000605const HChar* showPPCAvOp ( PPCAvOp op ) {
cerionc3d8bdc2005-06-28 18:06:23 +0000606 switch (op) {
cerion6b6f59e2005-06-28 20:59:18 +0000607
608 /* Unary */
609 case Pav_MOV: return "vmr"; /* Mov */
cerionc3d8bdc2005-06-28 18:06:23 +0000610
cerion6b6f59e2005-06-28 20:59:18 +0000611 case Pav_AND: return "vand"; /* Bitwise */
cerionc3d8bdc2005-06-28 18:06:23 +0000612 case Pav_OR: return "vor";
613 case Pav_XOR: return "vxor";
614 case Pav_NOT: return "vnot";
615
cerion6b6f59e2005-06-28 20:59:18 +0000616 case Pav_UNPCKH8S: return "vupkhsb"; /* Unpack */
cerionc3d8bdc2005-06-28 18:06:23 +0000617 case Pav_UNPCKH16S: return "vupkhsh";
618 case Pav_UNPCKL8S: return "vupklsb";
619 case Pav_UNPCKL16S: return "vupklsh";
620 case Pav_UNPCKHPIX: return "vupkhpx";
621 case Pav_UNPCKLPIX: return "vupklpx";
cerion6b6f59e2005-06-28 20:59:18 +0000622
623 /* Integer binary */
carll0c74bb52013-08-12 18:01:40 +0000624 case Pav_ADDU: return "vaddu_m"; // b,h,w,dw
carll48ae46b2013-10-01 15:45:54 +0000625 case Pav_QADDU: return "vaddu_s"; // b,h,w,dw
626 case Pav_QADDS: return "vadds_s"; // b,h,w,dw
cerionc3d8bdc2005-06-28 18:06:23 +0000627
carll48ae46b2013-10-01 15:45:54 +0000628 case Pav_SUBU: return "vsubu_m"; // b,h,w,dw
629 case Pav_QSUBU: return "vsubu_s"; // b,h,w,dw
630 case Pav_QSUBS: return "vsubs_s"; // b,h,w,dw
cerion6b6f59e2005-06-28 20:59:18 +0000631
carll48ae46b2013-10-01 15:45:54 +0000632 case Pav_MULU: return "vmulu"; // w
633 case Pav_OMULU: return "vmulou"; // b,h,w
634 case Pav_OMULS: return "vmulos"; // b,h,w
635 case Pav_EMULU: return "vmuleu"; // b,h,w
636 case Pav_EMULS: return "vmules"; // b,h,w
cerion6b6f59e2005-06-28 20:59:18 +0000637
638 case Pav_AVGU: return "vavgu"; // b,h,w
639 case Pav_AVGS: return "vavgs"; // b,h,w
640
641 case Pav_MAXU: return "vmaxu"; // b,h,w
642 case Pav_MAXS: return "vmaxs"; // b,h,w
643
644 case Pav_MINU: return "vminu"; // b,h,w
645 case Pav_MINS: return "vmins"; // b,h,w
646
647 /* Compare (always affects CR field 6) */
648 case Pav_CMPEQU: return "vcmpequ"; // b,h,w
649 case Pav_CMPGTU: return "vcmpgtu"; // b,h,w
650 case Pav_CMPGTS: return "vcmpgts"; // b,h,w
651
652 /* Shift */
carll48ae46b2013-10-01 15:45:54 +0000653 case Pav_SHL: return "vsl"; // ' ',b,h,w,dw
654 case Pav_SHR: return "vsr"; // ' ',b,h,w,dw
655 case Pav_SAR: return "vsra"; // b,h,w,dw
656 case Pav_ROTL: return "vrl"; // b,h,w,dw
cerion6b6f59e2005-06-28 20:59:18 +0000657
658 /* Pack */
carll0c74bb52013-08-12 18:01:40 +0000659 case Pav_PACKUU: return "vpku_um"; // h,w,dw
cerionf34ccc42005-09-16 08:55:50 +0000660 case Pav_QPACKUU: return "vpku_us"; // h,w
661 case Pav_QPACKSU: return "vpks_us"; // h,w
662 case Pav_QPACKSS: return "vpks_ss"; // h,w
cerion6b6f59e2005-06-28 20:59:18 +0000663 case Pav_PACKPXL: return "vpkpx";
664
cerionc3d8bdc2005-06-28 18:06:23 +0000665 /* Merge */
cerion6b6f59e2005-06-28 20:59:18 +0000666 case Pav_MRGHI: return "vmrgh"; // b,h,w
667 case Pav_MRGLO: return "vmrgl"; // b,h,w
668
carll48ae46b2013-10-01 15:45:54 +0000669 /* Concatenation */
670 case Pav_CATODD: return "vmrgow"; // w
671 case Pav_CATEVEN: return "vmrgew"; // w
672
carll7deaf952013-10-15 18:11:20 +0000673 /* SHA */
674 case Pav_SHA256: return "vshasigmaw"; // w
675 case Pav_SHA512: return "vshasigmaw"; // dw
676
677 /* BCD */
678 case Pav_BCDAdd: return "bcdadd."; // qw
679 case Pav_BCDSub: return "bcdsub."; // qw
Elliott Hughesa0664b92017-04-18 17:46:52 -0700680 case Pav_I128StoBCD128: return "bcdcfsq."; //qw
681 case Pav_BCD128toI128S: return "bcdctsq."; //qw
682
683 /* I128 mult by 10 */
684 case Pav_MulI128by10: return "vmul10uq"; //qw
685 case Pav_MulI128by10Carry: return "vmul10cuq"; //qw
686 case Pav_MulI128by10E: return "vmul10euq"; //qw
687 case Pav_MulI128by10ECarry: return "vmul10ecuq"; //qw
688
689 /* F128 to I128 signed */
690 case Pav_F128toI128S: return "xsrqpi|x"; //qw
691
692 /* F128 round to F128 */
693 case Pav_ROUNDFPQ: return "xsrqpxp";
carll7deaf952013-10-15 18:11:20 +0000694
695 /* Polynomial arith */
696 case Pav_POLYMULADD: return "vpmsum"; // b, h, w, d
697
698 /* Cipher */
699 case Pav_CIPHERV128: case Pav_CIPHERLV128:
700 case Pav_NCIPHERV128: case Pav_NCIPHERLV128:
701 case Pav_CIPHERSUBV128: return "v_cipher_"; // qw
702
703 /* zero count */
704 case Pav_ZEROCNTBYTE: case Pav_ZEROCNTWORD:
705 case Pav_ZEROCNTHALF: case Pav_ZEROCNTDBL:
706 return "vclz_"; // b, h, w, d
707
Elliott Hughesa0664b92017-04-18 17:46:52 -0700708 /* trailing zero count */
709 case Pav_TRAILINGZEROCNTBYTE: case Pav_TRAILINGZEROCNTWORD:
710 case Pav_TRAILINGZEROCNTHALF: case Pav_TRAILINGZEROCNTDBL:
711 return "vctz_"; // b, h, w, d
712
carll60c6bac2013-10-18 01:19:06 +0000713 /* vector gather (byte-by-byte bit matrix transpose) */
714 case Pav_BITMTXXPOSE:
715 return "vgbbd";
716
Elliott Hughesa0664b92017-04-18 17:46:52 -0700717 /* Vector Half-precision format to single precision conversion */
718 case Pav_F16toF32x4:
719 return"xvcvhpsp";
720
721 /* Vector Single-precision format to Half-precision conversion */
722 case Pav_F32toF16x4:
723 return"xvcvsphp";
724
725 /* Vector Half-precision format to Double precision conversion */
726 case Pav_F16toF64x2:
727 return"xvcvhpdp";
728
729 /* Vector Half-precision format to Double precision conversion */
730 case Pav_F64toF16x2:
731 return"xvcvdphp";
732
cerion5b2325f2005-12-23 00:55:09 +0000733 default: vpanic("showPPCAvOp");
cerion8ea0d3e2005-11-14 00:44:47 +0000734 }
735}
736
florian55085f82012-11-21 00:36:55 +0000737const HChar* showPPCAvFpOp ( PPCAvFpOp op ) {
cerion8ea0d3e2005-11-14 00:44:47 +0000738 switch (op) {
cerion6b6f59e2005-06-28 20:59:18 +0000739 /* Floating Point Binary */
cerion8ea0d3e2005-11-14 00:44:47 +0000740 case Pavfp_ADDF: return "vaddfp";
741 case Pavfp_SUBF: return "vsubfp";
742 case Pavfp_MULF: return "vmaddfp";
743 case Pavfp_MAXF: return "vmaxfp";
744 case Pavfp_MINF: return "vminfp";
745 case Pavfp_CMPEQF: return "vcmpeqfp";
746 case Pavfp_CMPGTF: return "vcmpgtfp";
747 case Pavfp_CMPGEF: return "vcmpgefp";
cerionc3d8bdc2005-06-28 18:06:23 +0000748
cerion8ea0d3e2005-11-14 00:44:47 +0000749 /* Floating Point Unary */
750 case Pavfp_RCPF: return "vrefp";
751 case Pavfp_RSQRTF: return "vrsqrtefp";
ceriond963eb42005-11-16 18:02:58 +0000752 case Pavfp_CVTU2F: return "vcfux";
753 case Pavfp_CVTS2F: return "vcfsx";
754 case Pavfp_QCVTF2U: return "vctuxs";
755 case Pavfp_QCVTF2S: return "vctsxs";
756 case Pavfp_ROUNDM: return "vrfim";
757 case Pavfp_ROUNDP: return "vrfip";
758 case Pavfp_ROUNDN: return "vrfin";
759 case Pavfp_ROUNDZ: return "vrfiz";
cerion8ea0d3e2005-11-14 00:44:47 +0000760
cerion5b2325f2005-12-23 00:55:09 +0000761 default: vpanic("showPPCAvFpOp");
cerionc3d8bdc2005-06-28 18:06:23 +0000762 }
763}
764
cerion5b2325f2005-12-23 00:55:09 +0000765PPCInstr* PPCInstr_LI ( HReg dst, ULong imm64, Bool mode64 )
sewardjb51f0f42005-07-18 11:38:02 +0000766{
floriand8e3eca2015-03-13 12:46:49 +0000767 PPCInstr* i = LibVEX_Alloc_inline(sizeof(PPCInstr));
cerionf0de28c2005-12-13 20:21:11 +0000768 i->tag = Pin_LI;
769 i->Pin.LI.dst = dst;
770 i->Pin.LI.imm64 = imm64;
771 if (!mode64)
772 vassert( (Long)imm64 == (Long)(Int)(UInt)imm64 );
sewardjb51f0f42005-07-18 11:38:02 +0000773 return i;
774}
cerion5b2325f2005-12-23 00:55:09 +0000775PPCInstr* PPCInstr_Alu ( PPCAluOp op, HReg dst,
776 HReg srcL, PPCRH* srcR ) {
floriand8e3eca2015-03-13 12:46:49 +0000777 PPCInstr* i = LibVEX_Alloc_inline(sizeof(PPCInstr));
cerionf0de28c2005-12-13 20:21:11 +0000778 i->tag = Pin_Alu;
779 i->Pin.Alu.op = op;
780 i->Pin.Alu.dst = dst;
781 i->Pin.Alu.srcL = srcL;
782 i->Pin.Alu.srcR = srcR;
cerioncd304492005-02-08 19:40:24 +0000783 return i;
784}
cerion5b2325f2005-12-23 00:55:09 +0000785PPCInstr* PPCInstr_Shft ( PPCShftOp op, Bool sz32,
786 HReg dst, HReg srcL, PPCRH* srcR ) {
floriand8e3eca2015-03-13 12:46:49 +0000787 PPCInstr* i = LibVEX_Alloc_inline(sizeof(PPCInstr));
cerionbb01b7c2005-12-16 13:40:18 +0000788 i->tag = Pin_Shft;
789 i->Pin.Shft.op = op;
790 i->Pin.Shft.sz32 = sz32;
791 i->Pin.Shft.dst = dst;
792 i->Pin.Shft.srcL = srcL;
793 i->Pin.Shft.srcR = srcR;
794 return i;
795}
cerion5b2325f2005-12-23 00:55:09 +0000796PPCInstr* PPCInstr_AddSubC ( Bool isAdd, Bool setC,
797 HReg dst, HReg srcL, HReg srcR ) {
floriand8e3eca2015-03-13 12:46:49 +0000798 PPCInstr* i = LibVEX_Alloc_inline(sizeof(PPCInstr));
cerion5b2325f2005-12-23 00:55:09 +0000799 i->tag = Pin_AddSubC;
800 i->Pin.AddSubC.isAdd = isAdd;
801 i->Pin.AddSubC.setC = setC;
802 i->Pin.AddSubC.dst = dst;
803 i->Pin.AddSubC.srcL = srcL;
804 i->Pin.AddSubC.srcR = srcR;
cerion4a49b032005-11-08 16:23:07 +0000805 return i;
806}
cerion5b2325f2005-12-23 00:55:09 +0000807PPCInstr* PPCInstr_Cmp ( Bool syned, Bool sz32,
808 UInt crfD, HReg srcL, PPCRH* srcR ) {
floriand8e3eca2015-03-13 12:46:49 +0000809 PPCInstr* i = LibVEX_Alloc_inline(sizeof(PPCInstr));
cerionf0de28c2005-12-13 20:21:11 +0000810 i->tag = Pin_Cmp;
811 i->Pin.Cmp.syned = syned;
cerionbb01b7c2005-12-16 13:40:18 +0000812 i->Pin.Cmp.sz32 = sz32;
cerionf0de28c2005-12-13 20:21:11 +0000813 i->Pin.Cmp.crfD = crfD;
814 i->Pin.Cmp.srcL = srcL;
815 i->Pin.Cmp.srcR = srcR;
cerion2c49e032005-02-09 17:29:49 +0000816 return i;
817}
cerion5b2325f2005-12-23 00:55:09 +0000818PPCInstr* PPCInstr_Unary ( PPCUnaryOp op, HReg dst, HReg src ) {
floriand8e3eca2015-03-13 12:46:49 +0000819 PPCInstr* i = LibVEX_Alloc_inline(sizeof(PPCInstr));
cerion5b2325f2005-12-23 00:55:09 +0000820 i->tag = Pin_Unary;
821 i->Pin.Unary.op = op;
822 i->Pin.Unary.dst = dst;
823 i->Pin.Unary.src = src;
cerion2c49e032005-02-09 17:29:49 +0000824 return i;
825}
cerion5b2325f2005-12-23 00:55:09 +0000826PPCInstr* PPCInstr_MulL ( Bool syned, Bool hi, Bool sz32,
827 HReg dst, HReg srcL, HReg srcR ) {
floriand8e3eca2015-03-13 12:46:49 +0000828 PPCInstr* i = LibVEX_Alloc_inline(sizeof(PPCInstr));
cerion92f5dc72005-02-10 16:11:35 +0000829 i->tag = Pin_MulL;
830 i->Pin.MulL.syned = syned;
cerionf0de28c2005-12-13 20:21:11 +0000831 i->Pin.MulL.hi = hi;
cerionbb01b7c2005-12-16 13:40:18 +0000832 i->Pin.MulL.sz32 = sz32;
cerionc0e707e2005-02-10 22:35:34 +0000833 i->Pin.MulL.dst = dst;
ceriona2f75882005-03-15 16:33:38 +0000834 i->Pin.MulL.srcL = srcL;
835 i->Pin.MulL.srcR = srcR;
cerionf0de28c2005-12-13 20:21:11 +0000836 /* if doing the low word, the signedness is irrelevant, but tie it
sewardjb51f0f42005-07-18 11:38:02 +0000837 down anyway. */
cerionf0de28c2005-12-13 20:21:11 +0000838 if (!hi) vassert(!syned);
cerion92f5dc72005-02-10 16:11:35 +0000839 return i;
840}
sewardj4aa412a2011-07-24 14:13:21 +0000841PPCInstr* PPCInstr_Div ( Bool extended, Bool syned, Bool sz32,
cerion5b2325f2005-12-23 00:55:09 +0000842 HReg dst, HReg srcL, HReg srcR ) {
floriand8e3eca2015-03-13 12:46:49 +0000843 PPCInstr* i = LibVEX_Alloc_inline(sizeof(PPCInstr));
cerion5b2325f2005-12-23 00:55:09 +0000844 i->tag = Pin_Div;
sewardj4aa412a2011-07-24 14:13:21 +0000845 i->Pin.Div.extended = extended;
cerion5b2325f2005-12-23 00:55:09 +0000846 i->Pin.Div.syned = syned;
847 i->Pin.Div.sz32 = sz32;
848 i->Pin.Div.dst = dst;
849 i->Pin.Div.srcL = srcL;
850 i->Pin.Div.srcR = srcR;
cerionc0e707e2005-02-10 22:35:34 +0000851 return i;
852}
cerion5b2325f2005-12-23 00:55:09 +0000853PPCInstr* PPCInstr_Call ( PPCCondCode cond,
sewardjcfe046e2013-01-17 14:23:53 +0000854 Addr64 target, UInt argiregs, RetLoc rloc ) {
sewardj6a64a9f2005-08-21 00:48:37 +0000855 UInt mask;
floriand8e3eca2015-03-13 12:46:49 +0000856 PPCInstr* i = LibVEX_Alloc_inline(sizeof(PPCInstr));
cerion2c49e032005-02-09 17:29:49 +0000857 i->tag = Pin_Call;
858 i->Pin.Call.cond = cond;
859 i->Pin.Call.target = target;
sewardj6a64a9f2005-08-21 00:48:37 +0000860 i->Pin.Call.argiregs = argiregs;
sewardjcfe046e2013-01-17 14:23:53 +0000861 i->Pin.Call.rloc = rloc;
sewardj6a64a9f2005-08-21 00:48:37 +0000862 /* Only r3 .. r10 inclusive may be used as arg regs. Hence: */
863 mask = (1<<3)|(1<<4)|(1<<5)|(1<<6)|(1<<7)|(1<<8)|(1<<9)|(1<<10);
864 vassert(0 == (argiregs & ~mask));
sewardj74142b82013-08-08 10:28:59 +0000865 vassert(is_sane_RetLoc(rloc));
cerion2c49e032005-02-09 17:29:49 +0000866 return i;
867}
sewardj3dee8492012-04-20 00:13:28 +0000868PPCInstr* PPCInstr_XDirect ( Addr64 dstGA, PPCAMode* amCIA,
869 PPCCondCode cond, Bool toFastEP ) {
floriand8e3eca2015-03-13 12:46:49 +0000870 PPCInstr* i = LibVEX_Alloc_inline(sizeof(PPCInstr));
sewardj3dee8492012-04-20 00:13:28 +0000871 i->tag = Pin_XDirect;
872 i->Pin.XDirect.dstGA = dstGA;
873 i->Pin.XDirect.amCIA = amCIA;
874 i->Pin.XDirect.cond = cond;
875 i->Pin.XDirect.toFastEP = toFastEP;
876 return i;
877}
878PPCInstr* PPCInstr_XIndir ( HReg dstGA, PPCAMode* amCIA,
879 PPCCondCode cond ) {
floriand8e3eca2015-03-13 12:46:49 +0000880 PPCInstr* i = LibVEX_Alloc_inline(sizeof(PPCInstr));
sewardj3dee8492012-04-20 00:13:28 +0000881 i->tag = Pin_XIndir;
882 i->Pin.XIndir.dstGA = dstGA;
883 i->Pin.XIndir.amCIA = amCIA;
884 i->Pin.XIndir.cond = cond;
885 return i;
886}
887PPCInstr* PPCInstr_XAssisted ( HReg dstGA, PPCAMode* amCIA,
888 PPCCondCode cond, IRJumpKind jk ) {
floriand8e3eca2015-03-13 12:46:49 +0000889 PPCInstr* i = LibVEX_Alloc_inline(sizeof(PPCInstr));
sewardj3dee8492012-04-20 00:13:28 +0000890 i->tag = Pin_XAssisted;
891 i->Pin.XAssisted.dstGA = dstGA;
892 i->Pin.XAssisted.amCIA = amCIA;
893 i->Pin.XAssisted.cond = cond;
894 i->Pin.XAssisted.jk = jk;
cerion2c49e032005-02-09 17:29:49 +0000895 return i;
896}
cerion5b2325f2005-12-23 00:55:09 +0000897PPCInstr* PPCInstr_CMov ( PPCCondCode cond,
898 HReg dst, PPCRI* src ) {
floriand8e3eca2015-03-13 12:46:49 +0000899 PPCInstr* i = LibVEX_Alloc_inline(sizeof(PPCInstr));
cerionf0de28c2005-12-13 20:21:11 +0000900 i->tag = Pin_CMov;
901 i->Pin.CMov.cond = cond;
902 i->Pin.CMov.src = src;
903 i->Pin.CMov.dst = dst;
cerionab9132d2005-02-15 15:46:59 +0000904 vassert(cond.test != Pct_ALWAYS);
cerionb536af92005-02-10 15:03:19 +0000905 return i;
906}
sewardj7fd5bb02006-01-26 02:24:17 +0000907PPCInstr* PPCInstr_Load ( UChar sz,
cerion5b2325f2005-12-23 00:55:09 +0000908 HReg dst, PPCAMode* src, Bool mode64 ) {
floriand8e3eca2015-03-13 12:46:49 +0000909 PPCInstr* i = LibVEX_Alloc_inline(sizeof(PPCInstr));
cerion7cf8e4e2005-02-16 16:08:17 +0000910 i->tag = Pin_Load;
911 i->Pin.Load.sz = sz;
cerion7cf8e4e2005-02-16 16:08:17 +0000912 i->Pin.Load.src = src;
913 i->Pin.Load.dst = dst;
cerionf0de28c2005-12-13 20:21:11 +0000914 vassert(sz == 1 || sz == 2 || sz == 4 || sz == 8);
915 if (sz == 8) vassert(mode64);
cerioncd304492005-02-08 19:40:24 +0000916 return i;
917}
sewardje9d8a262009-07-01 08:06:34 +0000918PPCInstr* PPCInstr_LoadL ( UChar sz,
919 HReg dst, HReg src, Bool mode64 )
920{
floriand8e3eca2015-03-13 12:46:49 +0000921 PPCInstr* i = LibVEX_Alloc_inline(sizeof(PPCInstr));
sewardje9d8a262009-07-01 08:06:34 +0000922 i->tag = Pin_LoadL;
923 i->Pin.LoadL.sz = sz;
924 i->Pin.LoadL.src = src;
925 i->Pin.LoadL.dst = dst;
carlld8268892015-04-17 23:42:40 +0000926 vassert(sz == 1 || sz == 2 || sz == 4 || sz == 8);
sewardje9d8a262009-07-01 08:06:34 +0000927 if (sz == 8) vassert(mode64);
928 return i;
929}
cerion5b2325f2005-12-23 00:55:09 +0000930PPCInstr* PPCInstr_Store ( UChar sz, PPCAMode* dst, HReg src,
931 Bool mode64 ) {
floriand8e3eca2015-03-13 12:46:49 +0000932 PPCInstr* i = LibVEX_Alloc_inline(sizeof(PPCInstr));
cerioncd304492005-02-08 19:40:24 +0000933 i->tag = Pin_Store;
934 i->Pin.Store.sz = sz;
935 i->Pin.Store.src = src;
936 i->Pin.Store.dst = dst;
cerionf0de28c2005-12-13 20:21:11 +0000937 vassert(sz == 1 || sz == 2 || sz == 4 || sz == 8);
938 if (sz == 8) vassert(mode64);
cerioncd304492005-02-08 19:40:24 +0000939 return i;
940}
sewardje9d8a262009-07-01 08:06:34 +0000941PPCInstr* PPCInstr_StoreC ( UChar sz, HReg dst, HReg src, Bool mode64 ) {
floriand8e3eca2015-03-13 12:46:49 +0000942 PPCInstr* i = LibVEX_Alloc_inline(sizeof(PPCInstr));
sewardje9d8a262009-07-01 08:06:34 +0000943 i->tag = Pin_StoreC;
944 i->Pin.StoreC.sz = sz;
945 i->Pin.StoreC.src = src;
946 i->Pin.StoreC.dst = dst;
carlld8268892015-04-17 23:42:40 +0000947 vassert(sz == 1 || sz == 2 || sz == 4 || sz == 8);
sewardje9d8a262009-07-01 08:06:34 +0000948 if (sz == 8) vassert(mode64);
949 return i;
950}
cerion5b2325f2005-12-23 00:55:09 +0000951PPCInstr* PPCInstr_Set ( PPCCondCode cond, HReg dst ) {
floriand8e3eca2015-03-13 12:46:49 +0000952 PPCInstr* i = LibVEX_Alloc_inline(sizeof(PPCInstr));
cerion5b2325f2005-12-23 00:55:09 +0000953 i->tag = Pin_Set;
954 i->Pin.Set.cond = cond;
955 i->Pin.Set.dst = dst;
cerionb536af92005-02-10 15:03:19 +0000956 return i;
957}
cerion5b2325f2005-12-23 00:55:09 +0000958PPCInstr* PPCInstr_MfCR ( HReg dst )
sewardjb51f0f42005-07-18 11:38:02 +0000959{
floriand8e3eca2015-03-13 12:46:49 +0000960 PPCInstr* i = LibVEX_Alloc_inline(sizeof(PPCInstr));
cerion5b2325f2005-12-23 00:55:09 +0000961 i->tag = Pin_MfCR;
962 i->Pin.MfCR.dst = dst;
sewardjb51f0f42005-07-18 11:38:02 +0000963 return i;
964}
cerion5b2325f2005-12-23 00:55:09 +0000965PPCInstr* PPCInstr_MFence ( void )
cerion92f5dc72005-02-10 16:11:35 +0000966{
floriand8e3eca2015-03-13 12:46:49 +0000967 PPCInstr* i = LibVEX_Alloc_inline(sizeof(PPCInstr));
cerion5b2325f2005-12-23 00:55:09 +0000968 i->tag = Pin_MFence;
cerion92f5dc72005-02-10 16:11:35 +0000969 return i;
970}
cerioncd304492005-02-08 19:40:24 +0000971
cerion5b2325f2005-12-23 00:55:09 +0000972PPCInstr* PPCInstr_FpUnary ( PPCFpOp op, HReg dst, HReg src ) {
floriand8e3eca2015-03-13 12:46:49 +0000973 PPCInstr* i = LibVEX_Alloc_inline(sizeof(PPCInstr));
cerion094d1392005-06-20 13:45:57 +0000974 i->tag = Pin_FpUnary;
975 i->Pin.FpUnary.op = op;
976 i->Pin.FpUnary.dst = dst;
977 i->Pin.FpUnary.src = src;
978 return i;
979}
cerion5b2325f2005-12-23 00:55:09 +0000980PPCInstr* PPCInstr_FpBinary ( PPCFpOp op, HReg dst,
981 HReg srcL, HReg srcR ) {
floriand8e3eca2015-03-13 12:46:49 +0000982 PPCInstr* i = LibVEX_Alloc_inline(sizeof(PPCInstr));
cerion094d1392005-06-20 13:45:57 +0000983 i->tag = Pin_FpBinary;
984 i->Pin.FpBinary.op = op;
985 i->Pin.FpBinary.dst = dst;
986 i->Pin.FpBinary.srcL = srcL;
987 i->Pin.FpBinary.srcR = srcR;
988 return i;
989}
Elliott Hughesa0664b92017-04-18 17:46:52 -0700990PPCInstr* PPCInstr_Fp128Unary(PPCFpOp op, HReg dst, HReg src) {
991 PPCInstr* i = LibVEX_Alloc_inline( sizeof(PPCInstr) );
992 i->tag = Pin_Fp128Unary;
993 i->Pin.Fp128Unary.op = op;
994 i->Pin.Fp128Unary.dst = dst;
995 i->Pin.Fp128Unary.src = src;
996 return i;
997}
998PPCInstr* PPCInstr_Fp128Binary(PPCFpOp op, HReg dst, HReg srcL, HReg srcR) {
999 PPCInstr* i = LibVEX_Alloc_inline( sizeof(PPCInstr) );
1000 i->tag = Pin_Fp128Binary;
1001 i->Pin.Fp128Binary.op = op;
1002 i->Pin.Fp128Binary.dst = dst;
1003 i->Pin.Fp128Binary.srcL = srcL;
1004 i->Pin.Fp128Binary.srcR = srcR;
1005 return i;
1006}
1007PPCInstr* PPCInstr_Fp128Trinary(PPCFpOp op, HReg dst, HReg srcL, HReg srcR) {
1008 PPCInstr* i = LibVEX_Alloc_inline( sizeof(PPCInstr) );
1009 i->tag = Pin_Fp128Trinary;
1010 i->Pin.Fp128Trinary.op = op;
1011 i->Pin.Fp128Trinary.dst = dst;
1012 i->Pin.Fp128Trinary.srcL = srcL;
1013 i->Pin.Fp128Trinary.srcR = srcR;
1014 return i;
1015}
sewardj40c80262006-02-08 19:30:46 +00001016PPCInstr* PPCInstr_FpMulAcc ( PPCFpOp op, HReg dst, HReg srcML,
1017 HReg srcMR, HReg srcAcc )
1018{
floriand8e3eca2015-03-13 12:46:49 +00001019 PPCInstr* i = LibVEX_Alloc_inline(sizeof(PPCInstr));
sewardj40c80262006-02-08 19:30:46 +00001020 i->tag = Pin_FpMulAcc;
1021 i->Pin.FpMulAcc.op = op;
1022 i->Pin.FpMulAcc.dst = dst;
1023 i->Pin.FpMulAcc.srcML = srcML;
1024 i->Pin.FpMulAcc.srcMR = srcMR;
1025 i->Pin.FpMulAcc.srcAcc = srcAcc;
1026 return i;
1027}
cerion5b2325f2005-12-23 00:55:09 +00001028PPCInstr* PPCInstr_FpLdSt ( Bool isLoad, UChar sz,
1029 HReg reg, PPCAMode* addr ) {
floriand8e3eca2015-03-13 12:46:49 +00001030 PPCInstr* i = LibVEX_Alloc_inline(sizeof(PPCInstr));
cerion094d1392005-06-20 13:45:57 +00001031 i->tag = Pin_FpLdSt;
1032 i->Pin.FpLdSt.isLoad = isLoad;
1033 i->Pin.FpLdSt.sz = sz;
1034 i->Pin.FpLdSt.reg = reg;
1035 i->Pin.FpLdSt.addr = addr;
1036 vassert(sz == 4 || sz == 8);
1037 return i;
1038}
sewardj92923de2006-01-25 21:29:48 +00001039PPCInstr* PPCInstr_FpSTFIW ( HReg addr, HReg data )
1040{
floriand8e3eca2015-03-13 12:46:49 +00001041 PPCInstr* i = LibVEX_Alloc_inline(sizeof(PPCInstr));
sewardj92923de2006-01-25 21:29:48 +00001042 i->tag = Pin_FpSTFIW;
1043 i->Pin.FpSTFIW.addr = addr;
1044 i->Pin.FpSTFIW.data = data;
cerion094d1392005-06-20 13:45:57 +00001045 return i;
1046}
sewardj92923de2006-01-25 21:29:48 +00001047PPCInstr* PPCInstr_FpRSP ( HReg dst, HReg src ) {
floriand8e3eca2015-03-13 12:46:49 +00001048 PPCInstr* i = LibVEX_Alloc_inline(sizeof(PPCInstr));
sewardj92923de2006-01-25 21:29:48 +00001049 i->tag = Pin_FpRSP;
1050 i->Pin.FpRSP.dst = dst;
1051 i->Pin.FpRSP.src = src;
cerion094d1392005-06-20 13:45:57 +00001052 return i;
1053}
sewardjc6bbd472012-04-02 10:20:48 +00001054PPCInstr* PPCInstr_Dfp64Unary(PPCFpOp op, HReg dst, HReg src) {
floriand8e3eca2015-03-13 12:46:49 +00001055 PPCInstr* i = LibVEX_Alloc_inline( sizeof(PPCInstr) );
sewardjc6bbd472012-04-02 10:20:48 +00001056 i->tag = Pin_Dfp64Unary;
1057 i->Pin.Dfp64Unary.op = op;
1058 i->Pin.Dfp64Unary.dst = dst;
1059 i->Pin.Dfp64Unary.src = src;
1060 return i;
1061}
1062PPCInstr* PPCInstr_Dfp64Binary(PPCFpOp op, HReg dst, HReg srcL, HReg srcR) {
floriand8e3eca2015-03-13 12:46:49 +00001063 PPCInstr* i = LibVEX_Alloc_inline( sizeof(PPCInstr) );
sewardjc6bbd472012-04-02 10:20:48 +00001064 i->tag = Pin_Dfp64Binary;
1065 i->Pin.Dfp64Binary.op = op;
1066 i->Pin.Dfp64Binary.dst = dst;
1067 i->Pin.Dfp64Binary.srcL = srcL;
1068 i->Pin.Dfp64Binary.srcR = srcR;
1069 return i;
1070}
sewardj26217b02012-04-12 17:19:48 +00001071PPCInstr* PPCInstr_DfpShift ( PPCFpOp op, HReg dst, HReg src, PPCRI* shift ) {
floriand8e3eca2015-03-13 12:46:49 +00001072 PPCInstr* i = LibVEX_Alloc_inline(sizeof(PPCInstr));
sewardj26217b02012-04-12 17:19:48 +00001073 i->tag = Pin_DfpShift;
1074 i->Pin.DfpShift.op = op;
1075 i->Pin.DfpShift.shift = shift;
1076 i->Pin.DfpShift.src = src;
1077 i->Pin.DfpShift.dst = dst;
1078 return i;
1079}
1080PPCInstr* PPCInstr_Dfp128Unary(PPCFpOp op, HReg dst_hi, HReg dst_lo,
1081 HReg src_hi, HReg src_lo) {
floriand8e3eca2015-03-13 12:46:49 +00001082 PPCInstr* i = LibVEX_Alloc_inline( sizeof(PPCInstr) );
sewardj26217b02012-04-12 17:19:48 +00001083 i->tag = Pin_Dfp128Unary;
1084 i->Pin.Dfp128Unary.op = op;
1085 i->Pin.Dfp128Unary.dst_hi = dst_hi;
1086 i->Pin.Dfp128Unary.dst_lo = dst_lo;
1087 i->Pin.Dfp128Unary.src_hi = src_hi;
1088 i->Pin.Dfp128Unary.src_lo = src_lo;
1089 return i;
1090}
sewardjc6bbd472012-04-02 10:20:48 +00001091PPCInstr* PPCInstr_Dfp128Binary(PPCFpOp op, HReg dst_hi, HReg dst_lo,
1092 HReg srcR_hi, HReg srcR_lo) {
1093 /* dst is used to pass the srcL argument and return the result */
floriand8e3eca2015-03-13 12:46:49 +00001094 PPCInstr* i = LibVEX_Alloc_inline( sizeof(PPCInstr) );
sewardjc6bbd472012-04-02 10:20:48 +00001095 i->tag = Pin_Dfp128Binary;
1096 i->Pin.Dfp128Binary.op = op;
1097 i->Pin.Dfp128Binary.dst_hi = dst_hi;
1098 i->Pin.Dfp128Binary.dst_lo = dst_lo;
1099 i->Pin.Dfp128Binary.srcR_hi = srcR_hi;
1100 i->Pin.Dfp128Binary.srcR_lo = srcR_lo;
1101 return i;
1102}
sewardj26217b02012-04-12 17:19:48 +00001103PPCInstr* PPCInstr_DfpShift128 ( PPCFpOp op, HReg dst_hi, HReg dst_lo,
1104 HReg src_hi, HReg src_lo,
1105 PPCRI* shift ) {
floriand8e3eca2015-03-13 12:46:49 +00001106 PPCInstr* i = LibVEX_Alloc_inline(sizeof(PPCInstr));
sewardj26217b02012-04-12 17:19:48 +00001107 i->tag = Pin_DfpShift128;
1108 i->Pin.DfpShift128.op = op;
1109 i->Pin.DfpShift128.shift = shift;
1110 i->Pin.DfpShift128.src_hi = src_hi;
1111 i->Pin.DfpShift128.src_lo = src_lo;
1112 i->Pin.DfpShift128.dst_hi = dst_hi;
1113 i->Pin.DfpShift128.dst_lo = dst_lo;
1114 return i;
1115}
sewardjcdc376d2012-04-23 11:21:12 +00001116PPCInstr* PPCInstr_DfpRound ( HReg dst, HReg src, PPCRI* r_rmc ) {
floriand8e3eca2015-03-13 12:46:49 +00001117 PPCInstr* i = LibVEX_Alloc_inline(sizeof(PPCInstr));
sewardjcdc376d2012-04-23 11:21:12 +00001118 i->tag = Pin_DfpRound;
1119 i->Pin.DfpRound.dst = dst;
1120 i->Pin.DfpRound.src = src;
1121 i->Pin.DfpRound.r_rmc = r_rmc;
1122 return i;
1123}
1124PPCInstr* PPCInstr_DfpRound128 ( HReg dst_hi, HReg dst_lo, HReg src_hi,
1125 HReg src_lo, PPCRI* r_rmc ) {
floriand8e3eca2015-03-13 12:46:49 +00001126 PPCInstr* i = LibVEX_Alloc_inline(sizeof(PPCInstr));
sewardjcdc376d2012-04-23 11:21:12 +00001127 i->tag = Pin_DfpRound128;
1128 i->Pin.DfpRound128.dst_hi = dst_hi;
1129 i->Pin.DfpRound128.dst_lo = dst_lo;
1130 i->Pin.DfpRound128.src_hi = src_hi;
1131 i->Pin.DfpRound128.src_lo = src_lo;
1132 i->Pin.DfpRound128.r_rmc = r_rmc;
1133 return i;
1134}
floriana7b0d102012-06-15 20:55:43 +00001135PPCInstr* PPCInstr_DfpQuantize ( PPCFpOp op, HReg dst, HReg srcL, HReg srcR,
sewardjcdc376d2012-04-23 11:21:12 +00001136 PPCRI* rmc ) {
floriand8e3eca2015-03-13 12:46:49 +00001137 PPCInstr* i = LibVEX_Alloc_inline(sizeof(PPCInstr));
sewardjcdc376d2012-04-23 11:21:12 +00001138 i->tag = Pin_DfpQuantize;
1139 i->Pin.DfpQuantize.op = op;
1140 i->Pin.DfpQuantize.dst = dst;
1141 i->Pin.DfpQuantize.srcL = srcL;
1142 i->Pin.DfpQuantize.srcR = srcR;
1143 i->Pin.DfpQuantize.rmc = rmc;
1144 return i;
1145}
floriana7b0d102012-06-15 20:55:43 +00001146PPCInstr* PPCInstr_DfpQuantize128 ( PPCFpOp op, HReg dst_hi, HReg dst_lo,
sewardjcdc376d2012-04-23 11:21:12 +00001147 HReg src_hi, HReg src_lo, PPCRI* rmc ) {
1148 /* dst is used to pass left operand in and return result */
floriand8e3eca2015-03-13 12:46:49 +00001149 PPCInstr* i = LibVEX_Alloc_inline(sizeof(PPCInstr));
sewardjcdc376d2012-04-23 11:21:12 +00001150 i->tag = Pin_DfpQuantize128;
1151 i->Pin.DfpQuantize128.op = op;
1152 i->Pin.DfpQuantize128.dst_hi = dst_hi;
1153 i->Pin.DfpQuantize128.dst_lo = dst_lo;
1154 i->Pin.DfpQuantize128.src_hi = src_hi;
1155 i->Pin.DfpQuantize128.src_lo = src_lo;
1156 i->Pin.DfpQuantize128.rmc = rmc;
1157 return i;
1158}
sewardj26217b02012-04-12 17:19:48 +00001159PPCInstr* PPCInstr_DfpD128toD64 ( PPCFpOp op, HReg dst,
1160 HReg src_hi, HReg src_lo ) {
floriand8e3eca2015-03-13 12:46:49 +00001161 PPCInstr* i = LibVEX_Alloc_inline(sizeof(PPCInstr));
sewardj26217b02012-04-12 17:19:48 +00001162 i->tag = Pin_DfpD128toD64;
1163 i->Pin.DfpD128toD64.op = op;
1164 i->Pin.DfpD128toD64.src_hi = src_hi;
1165 i->Pin.DfpD128toD64.src_lo = src_lo;
1166 i->Pin.DfpD128toD64.dst = dst;
1167 return i;
1168}
sewardj26217b02012-04-12 17:19:48 +00001169PPCInstr* PPCInstr_DfpI64StoD128 ( PPCFpOp op, HReg dst_hi,
1170 HReg dst_lo, HReg src ) {
floriand8e3eca2015-03-13 12:46:49 +00001171 PPCInstr* i = LibVEX_Alloc_inline(sizeof(PPCInstr));
sewardj26217b02012-04-12 17:19:48 +00001172 i->tag = Pin_DfpI64StoD128;
1173 i->Pin.DfpI64StoD128.op = op;
1174 i->Pin.DfpI64StoD128.src = src;
1175 i->Pin.DfpI64StoD128.dst_hi = dst_hi;
1176 i->Pin.DfpI64StoD128.dst_lo = dst_lo;
1177 return i;
1178}
sewardjcdc376d2012-04-23 11:21:12 +00001179PPCInstr* PPCInstr_ExtractExpD128 ( PPCFpOp op, HReg dst,
1180 HReg src_hi, HReg src_lo ) {
1181 /* dst is used to pass the srcL argument */
floriand8e3eca2015-03-13 12:46:49 +00001182 PPCInstr* i = LibVEX_Alloc_inline(sizeof(PPCInstr));
sewardjcdc376d2012-04-23 11:21:12 +00001183 i->tag = Pin_ExtractExpD128;
1184 i->Pin.ExtractExpD128.op = op;
1185 i->Pin.ExtractExpD128.dst = dst;
1186 i->Pin.ExtractExpD128.src_hi = src_hi;
1187 i->Pin.ExtractExpD128.src_lo = src_lo;
1188 return i;
1189}
1190PPCInstr* PPCInstr_InsertExpD128 ( PPCFpOp op, HReg dst_hi, HReg dst_lo,
1191 HReg srcL, HReg srcR_hi, HReg srcR_lo ) {
1192 /* dst is used to pass the srcL argument */
floriand8e3eca2015-03-13 12:46:49 +00001193 PPCInstr* i = LibVEX_Alloc_inline(sizeof(PPCInstr));
sewardjcdc376d2012-04-23 11:21:12 +00001194 i->tag = Pin_InsertExpD128;
1195 i->Pin.InsertExpD128.op = op;
1196 i->Pin.InsertExpD128.dst_hi = dst_hi;
1197 i->Pin.InsertExpD128.dst_lo = dst_lo;
1198 i->Pin.InsertExpD128.srcL = srcL;
1199 i->Pin.InsertExpD128.srcR_hi = srcR_hi;
1200 i->Pin.InsertExpD128.srcR_lo = srcR_lo;
1201 return i;
1202}
1203PPCInstr* PPCInstr_Dfp64Cmp (/* UInt crfD,*/ HReg dst, HReg srcL, HReg srcR ) {
floriand8e3eca2015-03-13 12:46:49 +00001204 PPCInstr* i = LibVEX_Alloc_inline(sizeof(PPCInstr));
sewardjcdc376d2012-04-23 11:21:12 +00001205 i->tag = Pin_Dfp64Cmp;
1206 i->Pin.Dfp64Cmp.dst = dst;
1207 i->Pin.Dfp64Cmp.srcL = srcL;
1208 i->Pin.Dfp64Cmp.srcR = srcR;
1209 return i;
1210}
1211PPCInstr* PPCInstr_Dfp128Cmp ( HReg dst, HReg srcL_hi, HReg srcL_lo,
1212 HReg srcR_hi, HReg srcR_lo ) {
floriand8e3eca2015-03-13 12:46:49 +00001213 PPCInstr* i = LibVEX_Alloc_inline(sizeof(PPCInstr));
sewardjcdc376d2012-04-23 11:21:12 +00001214 i->tag = Pin_Dfp128Cmp;
1215 i->Pin.Dfp128Cmp.dst = dst;
1216 i->Pin.Dfp128Cmp.srcL_hi = srcL_hi;
1217 i->Pin.Dfp128Cmp.srcL_lo = srcL_lo;
1218 i->Pin.Dfp128Cmp.srcR_hi = srcR_hi;
1219 i->Pin.Dfp128Cmp.srcR_lo = srcR_lo;
1220 return i;
1221}
sewardj3dee8492012-04-20 00:13:28 +00001222PPCInstr* PPCInstr_EvCheck ( PPCAMode* amCounter,
1223 PPCAMode* amFailAddr ) {
floriand8e3eca2015-03-13 12:46:49 +00001224 PPCInstr* i = LibVEX_Alloc_inline(sizeof(PPCInstr));
sewardj3dee8492012-04-20 00:13:28 +00001225 i->tag = Pin_EvCheck;
1226 i->Pin.EvCheck.amCounter = amCounter;
1227 i->Pin.EvCheck.amFailAddr = amFailAddr;
1228 return i;
1229}
1230PPCInstr* PPCInstr_ProfInc ( void ) {
floriand8e3eca2015-03-13 12:46:49 +00001231 PPCInstr* i = LibVEX_Alloc_inline(sizeof(PPCInstr));
sewardj3dee8492012-04-20 00:13:28 +00001232 i->tag = Pin_ProfInc;
1233 return i;
1234}
1235
sewardj7d810d72011-05-08 22:05:10 +00001236/*
1237Valid combo | fromI | int32 | syned | flt64 |
1238--------------------------------------------
1239 | n n n n |
1240--------------------------------------------
1241 F64->I64U | n n n y |
1242--------------------------------------------
1243 | n n y n |
1244--------------------------------------------
1245 F64->I64S | n n y y |
1246--------------------------------------------
1247 | n y n n |
1248--------------------------------------------
1249 F64->I32U | n y n y |
1250--------------------------------------------
1251 | n y y n |
1252--------------------------------------------
1253 F64->I32S | n y y y |
1254--------------------------------------------
1255 I64U->F32 | y n n n |
1256--------------------------------------------
1257 I64U->F64 | y n n y |
1258--------------------------------------------
1259 | y n y n |
1260--------------------------------------------
1261 I64S->F64 | y n y y |
1262--------------------------------------------
1263 | y y n n |
1264--------------------------------------------
1265 | y y n y |
1266--------------------------------------------
1267 | y y y n |
1268--------------------------------------------
1269 | y y y y |
1270--------------------------------------------
1271*/
sewardj66d5ef22011-04-15 11:55:00 +00001272PPCInstr* PPCInstr_FpCftI ( Bool fromI, Bool int32, Bool syned,
sewardj7d810d72011-05-08 22:05:10 +00001273 Bool flt64, HReg dst, HReg src ) {
1274 Bool tmp = fromI | int32 | syned | flt64;
1275 vassert(tmp == True || tmp == False); // iow, no high bits set
1276 UShort conversion = 0;
1277 conversion = (fromI << 3) | (int32 << 2) | (syned << 1) | flt64;
1278 switch (conversion) {
1279 // Supported conversion operations
1280 case 1: case 3: case 5: case 7:
1281 case 8: case 9: case 11:
1282 break;
1283 default:
1284 vpanic("PPCInstr_FpCftI(ppc_host)");
1285 }
floriand8e3eca2015-03-13 12:46:49 +00001286 PPCInstr* i = LibVEX_Alloc_inline(sizeof(PPCInstr));
sewardj92923de2006-01-25 21:29:48 +00001287 i->tag = Pin_FpCftI;
1288 i->Pin.FpCftI.fromI = fromI;
1289 i->Pin.FpCftI.int32 = int32;
sewardj66d5ef22011-04-15 11:55:00 +00001290 i->Pin.FpCftI.syned = syned;
sewardj7d810d72011-05-08 22:05:10 +00001291 i->Pin.FpCftI.flt64 = flt64;
sewardj92923de2006-01-25 21:29:48 +00001292 i->Pin.FpCftI.dst = dst;
1293 i->Pin.FpCftI.src = src;
cerion07b07a92005-12-22 14:32:35 +00001294 return i;
1295}
cerion5b2325f2005-12-23 00:55:09 +00001296PPCInstr* PPCInstr_FpCMov ( PPCCondCode cond, HReg dst, HReg src ) {
floriand8e3eca2015-03-13 12:46:49 +00001297 PPCInstr* i = LibVEX_Alloc_inline(sizeof(PPCInstr));
cerion094d1392005-06-20 13:45:57 +00001298 i->tag = Pin_FpCMov;
1299 i->Pin.FpCMov.cond = cond;
1300 i->Pin.FpCMov.dst = dst;
1301 i->Pin.FpCMov.src = src;
1302 vassert(cond.test != Pct_ALWAYS);
1303 return i;
1304}
sewardjc6bbd472012-04-02 10:20:48 +00001305PPCInstr* PPCInstr_FpLdFPSCR ( HReg src, Bool dfp_rm ) {
floriand8e3eca2015-03-13 12:46:49 +00001306 PPCInstr* i = LibVEX_Alloc_inline(sizeof(PPCInstr));
cerion094d1392005-06-20 13:45:57 +00001307 i->tag = Pin_FpLdFPSCR;
1308 i->Pin.FpLdFPSCR.src = src;
sewardjc6bbd472012-04-02 10:20:48 +00001309 i->Pin.FpLdFPSCR.dfp_rm = dfp_rm ? 1 : 0;
cerion094d1392005-06-20 13:45:57 +00001310 return i;
1311}
cerion5b2325f2005-12-23 00:55:09 +00001312PPCInstr* PPCInstr_FpCmp ( HReg dst, HReg srcL, HReg srcR ) {
floriand8e3eca2015-03-13 12:46:49 +00001313 PPCInstr* i = LibVEX_Alloc_inline(sizeof(PPCInstr));
cerion094d1392005-06-20 13:45:57 +00001314 i->tag = Pin_FpCmp;
1315 i->Pin.FpCmp.dst = dst;
1316 i->Pin.FpCmp.srcL = srcL;
1317 i->Pin.FpCmp.srcR = srcR;
1318 return i;
1319}
cerionbcf8c3e2005-02-04 16:17:07 +00001320
cerion7f000af2005-02-22 20:36:49 +00001321/* Read/Write Link Register */
cerion5b2325f2005-12-23 00:55:09 +00001322PPCInstr* PPCInstr_RdWrLR ( Bool wrLR, HReg gpr ) {
floriand8e3eca2015-03-13 12:46:49 +00001323 PPCInstr* i = LibVEX_Alloc_inline(sizeof(PPCInstr));
cerion7f000af2005-02-22 20:36:49 +00001324 i->tag = Pin_RdWrLR;
1325 i->Pin.RdWrLR.wrLR = wrLR;
1326 i->Pin.RdWrLR.gpr = gpr;
1327 return i;
1328}
1329
cerionc3d8bdc2005-06-28 18:06:23 +00001330/* AltiVec */
cerion5b2325f2005-12-23 00:55:09 +00001331PPCInstr* PPCInstr_AvLdSt ( Bool isLoad, UChar sz,
1332 HReg reg, PPCAMode* addr ) {
floriand8e3eca2015-03-13 12:46:49 +00001333 PPCInstr* i = LibVEX_Alloc_inline(sizeof(PPCInstr));
cerionc3d8bdc2005-06-28 18:06:23 +00001334 i->tag = Pin_AvLdSt;
1335 i->Pin.AvLdSt.isLoad = isLoad;
1336 i->Pin.AvLdSt.sz = sz;
1337 i->Pin.AvLdSt.reg = reg;
1338 i->Pin.AvLdSt.addr = addr;
1339 return i;
1340}
cerion5b2325f2005-12-23 00:55:09 +00001341PPCInstr* PPCInstr_AvUnary ( PPCAvOp op, HReg dst, HReg src ) {
floriand8e3eca2015-03-13 12:46:49 +00001342 PPCInstr* i = LibVEX_Alloc_inline(sizeof(PPCInstr));
cerion8ea0d3e2005-11-14 00:44:47 +00001343 i->tag = Pin_AvUnary;
cerionc3d8bdc2005-06-28 18:06:23 +00001344 i->Pin.AvUnary.op = op;
1345 i->Pin.AvUnary.dst = dst;
1346 i->Pin.AvUnary.src = src;
1347 return i;
1348}
cerion5b2325f2005-12-23 00:55:09 +00001349PPCInstr* PPCInstr_AvBinary ( PPCAvOp op, HReg dst,
1350 HReg srcL, HReg srcR ) {
floriand8e3eca2015-03-13 12:46:49 +00001351 PPCInstr* i = LibVEX_Alloc_inline(sizeof(PPCInstr));
cerionc3d8bdc2005-06-28 18:06:23 +00001352 i->tag = Pin_AvBinary;
1353 i->Pin.AvBinary.op = op;
1354 i->Pin.AvBinary.dst = dst;
1355 i->Pin.AvBinary.srcL = srcL;
1356 i->Pin.AvBinary.srcR = srcR;
1357 return i;
1358}
Elliott Hughesa0664b92017-04-18 17:46:52 -07001359PPCInstr* PPCInstr_AvBinaryInt ( PPCAvOp op, HReg dst,
1360 HReg src, PPCRI* val ) {
1361 PPCInstr* i = LibVEX_Alloc_inline(sizeof(PPCInstr));
1362 i->tag = Pin_AvBinaryInt;
1363 i->Pin.AvBinaryInt.op = op;
1364 i->Pin.AvBinaryInt.dst = dst;
1365 i->Pin.AvBinaryInt.src = src;
1366 i->Pin.AvBinaryInt.val = val;
1367 return i;
1368}
cerion5b2325f2005-12-23 00:55:09 +00001369PPCInstr* PPCInstr_AvBin8x16 ( PPCAvOp op, HReg dst,
1370 HReg srcL, HReg srcR ) {
floriand8e3eca2015-03-13 12:46:49 +00001371 PPCInstr* i = LibVEX_Alloc_inline(sizeof(PPCInstr));
cerion5b2325f2005-12-23 00:55:09 +00001372 i->tag = Pin_AvBin8x16;
cerion6b6f59e2005-06-28 20:59:18 +00001373 i->Pin.AvBin8x16.op = op;
1374 i->Pin.AvBin8x16.dst = dst;
1375 i->Pin.AvBin8x16.srcL = srcL;
1376 i->Pin.AvBin8x16.srcR = srcR;
1377 return i;
1378}
cerion5b2325f2005-12-23 00:55:09 +00001379PPCInstr* PPCInstr_AvBin16x8 ( PPCAvOp op, HReg dst,
1380 HReg srcL, HReg srcR ) {
floriand8e3eca2015-03-13 12:46:49 +00001381 PPCInstr* i = LibVEX_Alloc_inline(sizeof(PPCInstr));
cerion5b2325f2005-12-23 00:55:09 +00001382 i->tag = Pin_AvBin16x8;
cerion6b6f59e2005-06-28 20:59:18 +00001383 i->Pin.AvBin16x8.op = op;
1384 i->Pin.AvBin16x8.dst = dst;
1385 i->Pin.AvBin16x8.srcL = srcL;
1386 i->Pin.AvBin16x8.srcR = srcR;
1387 return i;
1388}
cerion5b2325f2005-12-23 00:55:09 +00001389PPCInstr* PPCInstr_AvBin32x4 ( PPCAvOp op, HReg dst,
1390 HReg srcL, HReg srcR ) {
floriand8e3eca2015-03-13 12:46:49 +00001391 PPCInstr* i = LibVEX_Alloc_inline(sizeof(PPCInstr));
cerion5b2325f2005-12-23 00:55:09 +00001392 i->tag = Pin_AvBin32x4;
cerion6b6f59e2005-06-28 20:59:18 +00001393 i->Pin.AvBin32x4.op = op;
1394 i->Pin.AvBin32x4.dst = dst;
1395 i->Pin.AvBin32x4.srcL = srcL;
1396 i->Pin.AvBin32x4.srcR = srcR;
1397 return i;
1398}
carll0c74bb52013-08-12 18:01:40 +00001399PPCInstr* PPCInstr_AvBin64x2 ( PPCAvOp op, HReg dst,
1400 HReg srcL, HReg srcR ) {
floriand8e3eca2015-03-13 12:46:49 +00001401 PPCInstr* i = LibVEX_Alloc_inline(sizeof(PPCInstr));
carll0c74bb52013-08-12 18:01:40 +00001402 i->tag = Pin_AvBin64x2;
1403 i->Pin.AvBin64x2.op = op;
1404 i->Pin.AvBin64x2.dst = dst;
1405 i->Pin.AvBin64x2.srcL = srcL;
1406 i->Pin.AvBin64x2.srcR = srcR;
1407 return i;
1408}
1409
sewardje522d4b2011-04-26 21:36:09 +00001410PPCInstr* PPCInstr_AvBin32Fx4 ( PPCAvFpOp op, HReg dst,
cerion5b2325f2005-12-23 00:55:09 +00001411 HReg srcL, HReg srcR ) {
floriand8e3eca2015-03-13 12:46:49 +00001412 PPCInstr* i = LibVEX_Alloc_inline(sizeof(PPCInstr));
cerion6b6f59e2005-06-28 20:59:18 +00001413 i->tag = Pin_AvBin32Fx4;
1414 i->Pin.AvBin32Fx4.op = op;
1415 i->Pin.AvBin32Fx4.dst = dst;
1416 i->Pin.AvBin32Fx4.srcL = srcL;
1417 i->Pin.AvBin32Fx4.srcR = srcR;
1418 return i;
1419}
sewardje522d4b2011-04-26 21:36:09 +00001420PPCInstr* PPCInstr_AvUn32Fx4 ( PPCAvFpOp op, HReg dst, HReg src ) {
floriand8e3eca2015-03-13 12:46:49 +00001421 PPCInstr* i = LibVEX_Alloc_inline(sizeof(PPCInstr));
cerion8ea0d3e2005-11-14 00:44:47 +00001422 i->tag = Pin_AvUn32Fx4;
1423 i->Pin.AvUn32Fx4.op = op;
1424 i->Pin.AvUn32Fx4.dst = dst;
1425 i->Pin.AvUn32Fx4.src = src;
1426 return i;
1427}
cerion5b2325f2005-12-23 00:55:09 +00001428PPCInstr* PPCInstr_AvPerm ( HReg dst, HReg srcL, HReg srcR, HReg ctl ) {
floriand8e3eca2015-03-13 12:46:49 +00001429 PPCInstr* i = LibVEX_Alloc_inline(sizeof(PPCInstr));
cerionc3d8bdc2005-06-28 18:06:23 +00001430 i->tag = Pin_AvPerm;
cerionc3d8bdc2005-06-28 18:06:23 +00001431 i->Pin.AvPerm.dst = dst;
1432 i->Pin.AvPerm.srcL = srcL;
1433 i->Pin.AvPerm.srcR = srcR;
cerion92d9d872005-09-15 21:58:50 +00001434 i->Pin.AvPerm.ctl = ctl;
cerionc3d8bdc2005-06-28 18:06:23 +00001435 return i;
1436}
carll48ae46b2013-10-01 15:45:54 +00001437
cerion5b2325f2005-12-23 00:55:09 +00001438PPCInstr* PPCInstr_AvSel ( HReg ctl, HReg dst, HReg srcL, HReg srcR ) {
floriand8e3eca2015-03-13 12:46:49 +00001439 PPCInstr* i = LibVEX_Alloc_inline(sizeof(PPCInstr));
cerionc3d8bdc2005-06-28 18:06:23 +00001440 i->tag = Pin_AvSel;
1441 i->Pin.AvSel.ctl = ctl;
1442 i->Pin.AvSel.dst = dst;
1443 i->Pin.AvSel.srcL = srcL;
1444 i->Pin.AvSel.srcR = srcR;
1445 return i;
1446}
carll9877fe52014-10-07 17:49:14 +00001447PPCInstr* PPCInstr_AvSh ( Bool shLeft, HReg dst, PPCAMode* addr ) {
floriand8e3eca2015-03-13 12:46:49 +00001448 PPCInstr* i = LibVEX_Alloc_inline(sizeof(PPCInstr));
carll9877fe52014-10-07 17:49:14 +00001449 i->tag = Pin_AvSh;
1450 i->Pin.AvSh.shLeft = shLeft;
1451 i->Pin.AvSh.dst = dst;
1452 i->Pin.AvSh.addr = addr;
1453 return i;
1454}
cerion5b2325f2005-12-23 00:55:09 +00001455PPCInstr* PPCInstr_AvShlDbl ( UChar shift, HReg dst,
1456 HReg srcL, HReg srcR ) {
floriand8e3eca2015-03-13 12:46:49 +00001457 PPCInstr* i = LibVEX_Alloc_inline(sizeof(PPCInstr));
cerionc3d8bdc2005-06-28 18:06:23 +00001458 i->tag = Pin_AvShlDbl;
1459 i->Pin.AvShlDbl.shift = shift;
1460 i->Pin.AvShlDbl.dst = dst;
1461 i->Pin.AvShlDbl.srcL = srcL;
1462 i->Pin.AvShlDbl.srcR = srcR;
1463 return i;
1464}
cerion5b2325f2005-12-23 00:55:09 +00001465PPCInstr* PPCInstr_AvSplat ( UChar sz, HReg dst, PPCVI5s* src ) {
floriand8e3eca2015-03-13 12:46:49 +00001466 PPCInstr* i = LibVEX_Alloc_inline(sizeof(PPCInstr));
cerionc3d8bdc2005-06-28 18:06:23 +00001467 i->tag = Pin_AvSplat;
1468 i->Pin.AvSplat.sz = sz;
1469 i->Pin.AvSplat.dst = dst;
1470 i->Pin.AvSplat.src = src;
1471 return i;
1472}
cerion5b2325f2005-12-23 00:55:09 +00001473PPCInstr* PPCInstr_AvCMov ( PPCCondCode cond, HReg dst, HReg src ) {
floriand8e3eca2015-03-13 12:46:49 +00001474 PPCInstr* i = LibVEX_Alloc_inline(sizeof(PPCInstr));
cerion6b6f59e2005-06-28 20:59:18 +00001475 i->tag = Pin_AvCMov;
1476 i->Pin.AvCMov.cond = cond;
1477 i->Pin.AvCMov.dst = dst;
1478 i->Pin.AvCMov.src = src;
1479 vassert(cond.test != Pct_ALWAYS);
1480 return i;
1481}
cerion5b2325f2005-12-23 00:55:09 +00001482PPCInstr* PPCInstr_AvLdVSCR ( HReg src ) {
floriand8e3eca2015-03-13 12:46:49 +00001483 PPCInstr* i = LibVEX_Alloc_inline(sizeof(PPCInstr));
cerionc3d8bdc2005-06-28 18:06:23 +00001484 i->tag = Pin_AvLdVSCR;
1485 i->Pin.AvLdVSCR.src = src;
1486 return i;
1487}
carll7deaf952013-10-15 18:11:20 +00001488PPCInstr* PPCInstr_AvCipherV128Unary ( PPCAvOp op, HReg dst, HReg src ) {
floriand8e3eca2015-03-13 12:46:49 +00001489 PPCInstr* i = LibVEX_Alloc_inline(sizeof(PPCInstr));
carll7deaf952013-10-15 18:11:20 +00001490 i->tag = Pin_AvCipherV128Unary;
1491 i->Pin.AvCipherV128Unary.op = op;
1492 i->Pin.AvCipherV128Unary.dst = dst;
1493 i->Pin.AvCipherV128Unary.src = src;
1494 return i;
1495}
1496PPCInstr* PPCInstr_AvCipherV128Binary ( PPCAvOp op, HReg dst,
1497 HReg srcL, HReg srcR ) {
floriand8e3eca2015-03-13 12:46:49 +00001498 PPCInstr* i = LibVEX_Alloc_inline(sizeof(PPCInstr));
carll7deaf952013-10-15 18:11:20 +00001499 i->tag = Pin_AvCipherV128Binary;
1500 i->Pin.AvCipherV128Binary.op = op;
1501 i->Pin.AvCipherV128Binary.dst = dst;
1502 i->Pin.AvCipherV128Binary.srcL = srcL;
1503 i->Pin.AvCipherV128Binary.srcR = srcR;
1504 return i;
1505}
1506PPCInstr* PPCInstr_AvHashV128Binary ( PPCAvOp op, HReg dst,
1507 HReg src, PPCRI* s_field ) {
floriand8e3eca2015-03-13 12:46:49 +00001508 PPCInstr* i = LibVEX_Alloc_inline(sizeof(PPCInstr));
carll7deaf952013-10-15 18:11:20 +00001509 i->tag = Pin_AvHashV128Binary;
1510 i->Pin.AvHashV128Binary.op = op;
1511 i->Pin.AvHashV128Binary.dst = dst;
1512 i->Pin.AvHashV128Binary.src = src;
1513 i->Pin.AvHashV128Binary.s_field = s_field;
1514 return i;
1515}
Elliott Hughesa0664b92017-04-18 17:46:52 -07001516PPCInstr* PPCInstr_AvBCDV128Binary ( PPCAvOp op, HReg dst,
1517 HReg src1, HReg src2 ) {
floriand8e3eca2015-03-13 12:46:49 +00001518 PPCInstr* i = LibVEX_Alloc_inline(sizeof(PPCInstr));
Elliott Hughesa0664b92017-04-18 17:46:52 -07001519 i->tag = Pin_AvBCDV128Binary;
1520 i->Pin.AvBCDV128Binary.op = op;
1521 i->Pin.AvBCDV128Binary.dst = dst;
1522 i->Pin.AvBCDV128Binary.src1 = src1;
1523 i->Pin.AvBCDV128Binary.src2 = src2;
carll7deaf952013-10-15 18:11:20 +00001524 return i;
1525}
cerionc3d8bdc2005-06-28 18:06:23 +00001526
cerion9e263e32005-03-03 17:21:51 +00001527
1528/* Pretty Print instructions */
cerionf0de28c2005-12-13 20:21:11 +00001529static void ppLoadImm ( HReg dst, ULong imm, Bool mode64 ) {
cerionf0de28c2005-12-13 20:21:11 +00001530 vex_printf("li_word ");
cerion5b2325f2005-12-23 00:55:09 +00001531 ppHRegPPC(dst);
cerionf0de28c2005-12-13 20:21:11 +00001532 if (!mode64) {
cerionf0de28c2005-12-13 20:21:11 +00001533 vex_printf(",0x%08x", (UInt)imm);
1534 } else {
1535 vex_printf(",0x%016llx", imm);
1536 }
cerion9e263e32005-03-03 17:21:51 +00001537}
1538
1539static void ppMovReg ( HReg dst, HReg src ) {
sewardja5b50222015-03-26 07:18:32 +00001540 if (!sameHReg(dst, src)) {
cerion9e263e32005-03-03 17:21:51 +00001541 vex_printf("mr ");
cerion5b2325f2005-12-23 00:55:09 +00001542 ppHRegPPC(dst);
cerion9e263e32005-03-03 17:21:51 +00001543 vex_printf(",");
cerion5b2325f2005-12-23 00:55:09 +00001544 ppHRegPPC(src);
cerion9e263e32005-03-03 17:21:51 +00001545 }
1546}
1547
floriand8c64e02014-10-08 08:54:44 +00001548void ppPPCInstr ( const PPCInstr* i, Bool mode64 )
cerionbcf8c3e2005-02-04 16:17:07 +00001549{
1550 switch (i->tag) {
cerionf0de28c2005-12-13 20:21:11 +00001551 case Pin_LI:
1552 ppLoadImm(i->Pin.LI.dst, i->Pin.LI.imm64, mode64);
sewardjb51f0f42005-07-18 11:38:02 +00001553 break;
cerionf0de28c2005-12-13 20:21:11 +00001554 case Pin_Alu: {
cerion5b2325f2005-12-23 00:55:09 +00001555 HReg r_srcL = i->Pin.Alu.srcL;
1556 PPCRH* rh_srcR = i->Pin.Alu.srcR;
sewardjb51f0f42005-07-18 11:38:02 +00001557 /* special-case "mr" */
cerionf0de28c2005-12-13 20:21:11 +00001558 if (i->Pin.Alu.op == Palu_OR && // or Rd,Rs,Rs == mr Rd,Rs
1559 rh_srcR->tag == Prh_Reg &&
florian79efdc62013-02-11 00:47:35 +00001560 sameHReg(rh_srcR->Prh.Reg.reg, r_srcL)) {
cerionb85e8bb2005-02-16 08:54:33 +00001561 vex_printf("mr ");
cerion5b2325f2005-12-23 00:55:09 +00001562 ppHRegPPC(i->Pin.Alu.dst);
cerioncd304492005-02-08 19:40:24 +00001563 vex_printf(",");
cerion5b2325f2005-12-23 00:55:09 +00001564 ppHRegPPC(r_srcL);
cerionbb01b7c2005-12-16 13:40:18 +00001565 return;
1566 }
1567 /* special-case "li" */
1568 if (i->Pin.Alu.op == Palu_ADD && // addi Rd,0,imm == li Rd,imm
1569 rh_srcR->tag == Prh_Imm &&
sewardja5b50222015-03-26 07:18:32 +00001570 hregEncoding(r_srcL) == 0) {
cerionbb01b7c2005-12-16 13:40:18 +00001571 vex_printf("li ");
cerion5b2325f2005-12-23 00:55:09 +00001572 ppHRegPPC(i->Pin.Alu.dst);
cerionb8c3b7f2005-03-01 20:27:49 +00001573 vex_printf(",");
cerion5b2325f2005-12-23 00:55:09 +00001574 ppPPCRH(rh_srcR);
cerionbb01b7c2005-12-16 13:40:18 +00001575 return;
cerionb8c3b7f2005-03-01 20:27:49 +00001576 }
cerionbb01b7c2005-12-16 13:40:18 +00001577 /* generic */
cerion5b2325f2005-12-23 00:55:09 +00001578 vex_printf("%s ", showPPCAluOp(i->Pin.Alu.op,
1579 toBool(rh_srcR->tag == Prh_Imm)));
1580 ppHRegPPC(i->Pin.Alu.dst);
cerionbb01b7c2005-12-16 13:40:18 +00001581 vex_printf(",");
cerion5b2325f2005-12-23 00:55:09 +00001582 ppHRegPPC(r_srcL);
cerionbb01b7c2005-12-16 13:40:18 +00001583 vex_printf(",");
cerion5b2325f2005-12-23 00:55:09 +00001584 ppPPCRH(rh_srcR);
cerionbb01b7c2005-12-16 13:40:18 +00001585 return;
1586 }
1587 case Pin_Shft: {
cerion5b2325f2005-12-23 00:55:09 +00001588 HReg r_srcL = i->Pin.Shft.srcL;
1589 PPCRH* rh_srcR = i->Pin.Shft.srcR;
1590 vex_printf("%s ", showPPCShftOp(i->Pin.Shft.op,
1591 toBool(rh_srcR->tag == Prh_Imm),
1592 i->Pin.Shft.sz32));
1593 ppHRegPPC(i->Pin.Shft.dst);
cerionbb01b7c2005-12-16 13:40:18 +00001594 vex_printf(",");
cerion5b2325f2005-12-23 00:55:09 +00001595 ppHRegPPC(r_srcL);
cerionbb01b7c2005-12-16 13:40:18 +00001596 vex_printf(",");
cerion5b2325f2005-12-23 00:55:09 +00001597 ppPPCRH(rh_srcR);
cerionb85e8bb2005-02-16 08:54:33 +00001598 return;
cerionf0de28c2005-12-13 20:21:11 +00001599 }
cerion5b2325f2005-12-23 00:55:09 +00001600 case Pin_AddSubC:
cerion4a49b032005-11-08 16:23:07 +00001601 vex_printf("%s%s ",
cerion5b2325f2005-12-23 00:55:09 +00001602 i->Pin.AddSubC.isAdd ? "add" : "sub",
1603 i->Pin.AddSubC.setC ? "c" : "e");
1604 ppHRegPPC(i->Pin.AddSubC.dst);
cerion4a49b032005-11-08 16:23:07 +00001605 vex_printf(",");
cerion5b2325f2005-12-23 00:55:09 +00001606 ppHRegPPC(i->Pin.AddSubC.srcL);
cerion4a49b032005-11-08 16:23:07 +00001607 vex_printf(",");
cerion5b2325f2005-12-23 00:55:09 +00001608 ppHRegPPC(i->Pin.AddSubC.srcR);
cerion4a49b032005-11-08 16:23:07 +00001609 return;
cerionf0de28c2005-12-13 20:21:11 +00001610 case Pin_Cmp:
cerionbb01b7c2005-12-16 13:40:18 +00001611 vex_printf("%s%c%s %%cr%u,",
cerionf0de28c2005-12-13 20:21:11 +00001612 i->Pin.Cmp.syned ? "cmp" : "cmpl",
cerionbb01b7c2005-12-16 13:40:18 +00001613 i->Pin.Cmp.sz32 ? 'w' : 'd',
cerionf0de28c2005-12-13 20:21:11 +00001614 i->Pin.Cmp.srcR->tag == Prh_Imm ? "i" : "",
1615 i->Pin.Cmp.crfD);
cerion5b2325f2005-12-23 00:55:09 +00001616 ppHRegPPC(i->Pin.Cmp.srcL);
cerionb85e8bb2005-02-16 08:54:33 +00001617 vex_printf(",");
cerion5b2325f2005-12-23 00:55:09 +00001618 ppPPCRH(i->Pin.Cmp.srcR);
cerionb85e8bb2005-02-16 08:54:33 +00001619 return;
cerionf0de28c2005-12-13 20:21:11 +00001620 case Pin_Unary:
cerion5b2325f2005-12-23 00:55:09 +00001621 vex_printf("%s ", showPPCUnaryOp(i->Pin.Unary.op));
1622 ppHRegPPC(i->Pin.Unary.dst);
cerionb85e8bb2005-02-16 08:54:33 +00001623 vex_printf(",");
cerion5b2325f2005-12-23 00:55:09 +00001624 ppHRegPPC(i->Pin.Unary.src);
cerionb85e8bb2005-02-16 08:54:33 +00001625 return;
1626 case Pin_MulL:
cerionbb01b7c2005-12-16 13:40:18 +00001627 vex_printf("mul%c%c%s ",
1628 i->Pin.MulL.hi ? 'h' : 'l',
1629 i->Pin.MulL.sz32 ? 'w' : 'd',
cerionf0de28c2005-12-13 20:21:11 +00001630 i->Pin.MulL.hi ? (i->Pin.MulL.syned ? "s" : "u") : "");
cerion5b2325f2005-12-23 00:55:09 +00001631 ppHRegPPC(i->Pin.MulL.dst);
cerionb85e8bb2005-02-16 08:54:33 +00001632 vex_printf(",");
cerion5b2325f2005-12-23 00:55:09 +00001633 ppHRegPPC(i->Pin.MulL.srcL);
cerionb85e8bb2005-02-16 08:54:33 +00001634 vex_printf(",");
cerion5b2325f2005-12-23 00:55:09 +00001635 ppHRegPPC(i->Pin.MulL.srcR);
cerionb85e8bb2005-02-16 08:54:33 +00001636 return;
1637 case Pin_Div:
sewardj4aa412a2011-07-24 14:13:21 +00001638 vex_printf("div%c%s%s ",
cerionbb01b7c2005-12-16 13:40:18 +00001639 i->Pin.Div.sz32 ? 'w' : 'd',
sewardj4aa412a2011-07-24 14:13:21 +00001640 i->Pin.Div.extended ? "e" : "",
cerionb85e8bb2005-02-16 08:54:33 +00001641 i->Pin.Div.syned ? "" : "u");
cerion5b2325f2005-12-23 00:55:09 +00001642 ppHRegPPC(i->Pin.Div.dst);
cerionb85e8bb2005-02-16 08:54:33 +00001643 vex_printf(",");
cerion5b2325f2005-12-23 00:55:09 +00001644 ppHRegPPC(i->Pin.Div.srcL);
cerionb85e8bb2005-02-16 08:54:33 +00001645 vex_printf(",");
cerion5b2325f2005-12-23 00:55:09 +00001646 ppHRegPPC(i->Pin.Div.srcR);
cerionb85e8bb2005-02-16 08:54:33 +00001647 return;
sewardj6a64a9f2005-08-21 00:48:37 +00001648 case Pin_Call: {
1649 Int n;
cerion8c51ed42005-02-22 11:16:54 +00001650 vex_printf("call: ");
1651 if (i->Pin.Call.cond.test != Pct_ALWAYS) {
cerion5b2325f2005-12-23 00:55:09 +00001652 vex_printf("if (%s) ", showPPCCondCode(i->Pin.Call.cond));
cerion8c51ed42005-02-22 11:16:54 +00001653 }
1654 vex_printf("{ ");
cerionf0de28c2005-12-13 20:21:11 +00001655 ppLoadImm(hregPPC_GPR10(mode64), i->Pin.Call.target, mode64);
1656 vex_printf(" ; mtctr r10 ; bctrl [");
sewardj6a64a9f2005-08-21 00:48:37 +00001657 for (n = 0; n < 32; n++) {
1658 if (i->Pin.Call.argiregs & (1<<n)) {
1659 vex_printf("r%d", n);
1660 if ((i->Pin.Call.argiregs >> n) > 1)
1661 vex_printf(",");
1662 }
1663 }
sewardjcfe046e2013-01-17 14:23:53 +00001664 vex_printf(",");
1665 ppRetLoc(i->Pin.Call.rloc);
sewardj6a64a9f2005-08-21 00:48:37 +00001666 vex_printf("] }");
cerionb85e8bb2005-02-16 08:54:33 +00001667 break;
sewardj6a64a9f2005-08-21 00:48:37 +00001668 }
sewardj3dee8492012-04-20 00:13:28 +00001669 case Pin_XDirect:
1670 vex_printf("(xDirect) ");
1671 vex_printf("if (%s) { ",
1672 showPPCCondCode(i->Pin.XDirect.cond));
1673 if (mode64) {
1674 vex_printf("imm64 r30,0x%llx; ", i->Pin.XDirect.dstGA);
1675 vex_printf("std r30,");
cerione97e1062005-02-21 15:09:19 +00001676 } else {
sewardj3dee8492012-04-20 00:13:28 +00001677 vex_printf("imm32 r30,0x%llx; ", i->Pin.XDirect.dstGA);
1678 vex_printf("stw r30,");
cerione97e1062005-02-21 15:09:19 +00001679 }
sewardj3dee8492012-04-20 00:13:28 +00001680 ppPPCAMode(i->Pin.XDirect.amCIA);
1681 vex_printf("; ");
1682 if (mode64) {
1683 vex_printf("imm64-fixed5 r30,$disp_cp_chain_me_to_%sEP; ",
1684 i->Pin.XDirect.toFastEP ? "fast" : "slow");
1685 } else {
1686 vex_printf("imm32-fixed2 r30,$disp_cp_chain_me_to_%sEP; ",
1687 i->Pin.XDirect.toFastEP ? "fast" : "slow");
1688 }
1689 vex_printf("mtctr r30; bctrl }");
1690 return;
1691 case Pin_XIndir:
1692 vex_printf("(xIndir) ");
1693 vex_printf("if (%s) { ",
1694 showPPCCondCode(i->Pin.XIndir.cond));
1695 vex_printf("%s ", mode64 ? "std" : "stw");
1696 ppHRegPPC(i->Pin.XIndir.dstGA);
1697 vex_printf(",");
1698 ppPPCAMode(i->Pin.XIndir.amCIA);
1699 vex_printf("; ");
1700 vex_printf("imm%s r30,$disp_cp_xindir; ", mode64 ? "64" : "32");
1701 vex_printf("mtctr r30; bctr }");
1702 return;
1703 case Pin_XAssisted:
1704 vex_printf("(xAssisted) ");
1705 vex_printf("if (%s) { ",
1706 showPPCCondCode(i->Pin.XAssisted.cond));
1707 vex_printf("%s ", mode64 ? "std" : "stw");
1708 ppHRegPPC(i->Pin.XAssisted.dstGA);
1709 vex_printf(",");
1710 ppPPCAMode(i->Pin.XAssisted.amCIA);
1711 vex_printf("; ");
1712 vex_printf("li r31,$IRJumpKind_to_TRCVAL(%d); ",
1713 (Int)i->Pin.XAssisted.jk);
1714 vex_printf("imm%s r30,$disp_cp_xindir; ", mode64 ? "64" : "32");
1715 vex_printf("mtctr r30; bctr }");
cerionb85e8bb2005-02-16 08:54:33 +00001716 return;
cerionf0de28c2005-12-13 20:21:11 +00001717 case Pin_CMov:
cerion5b2325f2005-12-23 00:55:09 +00001718 vex_printf("cmov (%s) ", showPPCCondCode(i->Pin.CMov.cond));
1719 ppHRegPPC(i->Pin.CMov.dst);
cerionb85e8bb2005-02-16 08:54:33 +00001720 vex_printf(",");
cerion5b2325f2005-12-23 00:55:09 +00001721 ppPPCRI(i->Pin.CMov.src);
cerion8c51ed42005-02-22 11:16:54 +00001722 vex_printf(": ");
cerionf0de28c2005-12-13 20:21:11 +00001723 if (i->Pin.CMov.cond.test != Pct_ALWAYS) {
cerion5b2325f2005-12-23 00:55:09 +00001724 vex_printf("if (%s) ", showPPCCondCode(i->Pin.CMov.cond));
cerion8c51ed42005-02-22 11:16:54 +00001725 }
1726 vex_printf("{ ");
cerionf0de28c2005-12-13 20:21:11 +00001727 if (i->Pin.CMov.src->tag == Pri_Imm) {
1728 ppLoadImm(i->Pin.CMov.dst, i->Pin.CMov.src->Pri.Imm, mode64);
cerion8c51ed42005-02-22 11:16:54 +00001729 } else {
cerionf0de28c2005-12-13 20:21:11 +00001730 ppMovReg(i->Pin.CMov.dst, i->Pin.CMov.src->Pri.Reg);
cerion8c51ed42005-02-22 11:16:54 +00001731 }
1732 vex_printf(" }");
cerionb85e8bb2005-02-16 08:54:33 +00001733 return;
cerion7cf8e4e2005-02-16 16:08:17 +00001734 case Pin_Load: {
sewardj428fabd2005-03-21 03:11:17 +00001735 Bool idxd = toBool(i->Pin.Load.src->tag == Pam_RR);
cerionf0de28c2005-12-13 20:21:11 +00001736 UChar sz = i->Pin.Load.sz;
florian5df8ab02012-10-13 19:34:19 +00001737 HChar c_sz = sz==1 ? 'b' : sz==2 ? 'h' : sz==4 ? 'w' : 'd';
sewardj34085e32007-03-09 18:07:00 +00001738 vex_printf("l%c%s%s ", c_sz, sz==8 ? "" : "z", idxd ? "x" : "" );
cerion5b2325f2005-12-23 00:55:09 +00001739 ppHRegPPC(i->Pin.Load.dst);
cerionb85e8bb2005-02-16 08:54:33 +00001740 vex_printf(",");
cerion5b2325f2005-12-23 00:55:09 +00001741 ppPPCAMode(i->Pin.Load.src);
cerionb85e8bb2005-02-16 08:54:33 +00001742 return;
1743 }
carlld8268892015-04-17 23:42:40 +00001744 case Pin_LoadL: {
1745 UChar sz = i->Pin.LoadL.sz;
1746 HChar c_sz = sz==1 ? 'b' : sz==2 ? 'h' : sz==4 ? 'w' : 'd';
1747 vex_printf("l%carx ", c_sz);
sewardje9d8a262009-07-01 08:06:34 +00001748 ppHRegPPC(i->Pin.LoadL.dst);
1749 vex_printf(",%%r0,");
1750 ppHRegPPC(i->Pin.LoadL.src);
1751 return;
carlld8268892015-04-17 23:42:40 +00001752 }
cerionb85e8bb2005-02-16 08:54:33 +00001753 case Pin_Store: {
1754 UChar sz = i->Pin.Store.sz;
sewardj428fabd2005-03-21 03:11:17 +00001755 Bool idxd = toBool(i->Pin.Store.dst->tag == Pam_RR);
florian5df8ab02012-10-13 19:34:19 +00001756 HChar c_sz = sz==1 ? 'b' : sz==2 ? 'h' : sz==4 ? 'w' : /*8*/ 'd';
cerionf0de28c2005-12-13 20:21:11 +00001757 vex_printf("st%c%s ", c_sz, idxd ? "x" : "" );
cerion5b2325f2005-12-23 00:55:09 +00001758 ppHRegPPC(i->Pin.Store.src);
cerionb85e8bb2005-02-16 08:54:33 +00001759 vex_printf(",");
cerion5b2325f2005-12-23 00:55:09 +00001760 ppPPCAMode(i->Pin.Store.dst);
cerionb85e8bb2005-02-16 08:54:33 +00001761 return;
1762 }
carlld8268892015-04-17 23:42:40 +00001763 case Pin_StoreC: {
1764 UChar sz = i->Pin.StoreC.sz;
1765 HChar c_sz = sz==1 ? 'b' : sz==2 ? 'h' : sz==4 ? 'w' : 'd';
1766 vex_printf("st%ccx. ", c_sz);
sewardje9d8a262009-07-01 08:06:34 +00001767 ppHRegPPC(i->Pin.StoreC.src);
1768 vex_printf(",%%r0,");
1769 ppHRegPPC(i->Pin.StoreC.dst);
1770 return;
carlld8268892015-04-17 23:42:40 +00001771 }
cerion5b2325f2005-12-23 00:55:09 +00001772 case Pin_Set: {
1773 PPCCondCode cc = i->Pin.Set.cond;
1774 vex_printf("set (%s),", showPPCCondCode(cc));
1775 ppHRegPPC(i->Pin.Set.dst);
cerionf9d6e222005-02-23 18:21:31 +00001776 if (cc.test == Pct_ALWAYS) {
1777 vex_printf(": { li ");
cerion5b2325f2005-12-23 00:55:09 +00001778 ppHRegPPC(i->Pin.Set.dst);
cerionf9d6e222005-02-23 18:21:31 +00001779 vex_printf(",1 }");
1780 } else {
1781 vex_printf(": { mfcr r0 ; rlwinm ");
cerion5b2325f2005-12-23 00:55:09 +00001782 ppHRegPPC(i->Pin.Set.dst);
sewardj428fabd2005-03-21 03:11:17 +00001783 vex_printf(",r0,%u,31,31", cc.flag+1);
cerionf9d6e222005-02-23 18:21:31 +00001784 if (cc.test == Pct_FALSE) {
1785 vex_printf("; xori ");
cerion5b2325f2005-12-23 00:55:09 +00001786 ppHRegPPC(i->Pin.Set.dst);
cerionf9d6e222005-02-23 18:21:31 +00001787 vex_printf(",");
cerion5b2325f2005-12-23 00:55:09 +00001788 ppHRegPPC(i->Pin.Set.dst);
sewardjf7745052005-12-16 01:06:42 +00001789 vex_printf(",1");
cerionf9d6e222005-02-23 18:21:31 +00001790 }
1791 vex_printf(" }");
1792 }
cerionb85e8bb2005-02-16 08:54:33 +00001793 return;
cerionf9d6e222005-02-23 18:21:31 +00001794 }
sewardjb51f0f42005-07-18 11:38:02 +00001795 case Pin_MfCR:
1796 vex_printf("mfcr ");
cerion5b2325f2005-12-23 00:55:09 +00001797 ppHRegPPC(i->Pin.MfCR.dst);
sewardjb51f0f42005-07-18 11:38:02 +00001798 break;
cerionb85e8bb2005-02-16 08:54:33 +00001799 case Pin_MFence:
cerion98411db2005-02-16 14:14:49 +00001800 vex_printf("mfence (=sync)");
cerionb85e8bb2005-02-16 08:54:33 +00001801 return;
cerion094d1392005-06-20 13:45:57 +00001802
1803 case Pin_FpUnary:
cerion5b2325f2005-12-23 00:55:09 +00001804 vex_printf("%s ", showPPCFpOp(i->Pin.FpUnary.op));
1805 ppHRegPPC(i->Pin.FpUnary.dst);
cerion094d1392005-06-20 13:45:57 +00001806 vex_printf(",");
cerion5b2325f2005-12-23 00:55:09 +00001807 ppHRegPPC(i->Pin.FpUnary.src);
cerion094d1392005-06-20 13:45:57 +00001808 return;
1809 case Pin_FpBinary:
cerion5b2325f2005-12-23 00:55:09 +00001810 vex_printf("%s ", showPPCFpOp(i->Pin.FpBinary.op));
1811 ppHRegPPC(i->Pin.FpBinary.dst);
cerion094d1392005-06-20 13:45:57 +00001812 vex_printf(",");
cerion5b2325f2005-12-23 00:55:09 +00001813 ppHRegPPC(i->Pin.FpBinary.srcL);
cerion094d1392005-06-20 13:45:57 +00001814 vex_printf(",");
cerion5b2325f2005-12-23 00:55:09 +00001815 ppHRegPPC(i->Pin.FpBinary.srcR);
cerion094d1392005-06-20 13:45:57 +00001816 return;
Elliott Hughesa0664b92017-04-18 17:46:52 -07001817 case Pin_Fp128Unary:
1818 vex_printf("%s ", showPPCFpOp(i->Pin.Fp128Unary.op));
1819 ppHRegPPC(i->Pin.Fp128Unary.dst);
1820 vex_printf(",");
1821 ppHRegPPC(i->Pin.Fp128Unary.src);
1822 return;
1823 case Pin_Fp128Binary:
1824 vex_printf("%s ", showPPCFpOp(i->Pin.Fp128Binary.op));
1825 ppHRegPPC(i->Pin.Fp128Binary.dst);
1826 vex_printf(",");
1827 ppHRegPPC(i->Pin.Fp128Binary.srcL);
1828 vex_printf(",");
1829 ppHRegPPC(i->Pin.Fp128Binary.srcR);
1830 return;
1831 case Pin_Fp128Trinary:
1832 vex_printf("%s ", showPPCFpOp(i->Pin.Fp128Trinary.op));
1833 ppHRegPPC(i->Pin.Fp128Trinary.dst);
1834 vex_printf(",");
1835 ppHRegPPC(i->Pin.Fp128Trinary.srcL);
1836 vex_printf(",");
1837 ppHRegPPC(i->Pin.Fp128Trinary.srcR);
1838 return;
sewardj40c80262006-02-08 19:30:46 +00001839 case Pin_FpMulAcc:
1840 vex_printf("%s ", showPPCFpOp(i->Pin.FpMulAcc.op));
1841 ppHRegPPC(i->Pin.FpMulAcc.dst);
1842 vex_printf(",");
1843 ppHRegPPC(i->Pin.FpMulAcc.srcML);
1844 vex_printf(",");
1845 ppHRegPPC(i->Pin.FpMulAcc.srcMR);
1846 vex_printf(",");
1847 ppHRegPPC(i->Pin.FpMulAcc.srcAcc);
1848 return;
cerion094d1392005-06-20 13:45:57 +00001849 case Pin_FpLdSt: {
1850 UChar sz = i->Pin.FpLdSt.sz;
1851 Bool idxd = toBool(i->Pin.FpLdSt.addr->tag == Pam_RR);
1852 if (i->Pin.FpLdSt.isLoad) {
1853 vex_printf("lf%c%s ",
1854 (sz==4 ? 's' : 'd'),
1855 idxd ? "x" : "" );
cerion5b2325f2005-12-23 00:55:09 +00001856 ppHRegPPC(i->Pin.FpLdSt.reg);
cerion094d1392005-06-20 13:45:57 +00001857 vex_printf(",");
cerion5b2325f2005-12-23 00:55:09 +00001858 ppPPCAMode(i->Pin.FpLdSt.addr);
cerion094d1392005-06-20 13:45:57 +00001859 } else {
1860 vex_printf("stf%c%s ",
1861 (sz==4 ? 's' : 'd'),
1862 idxd ? "x" : "" );
cerion5b2325f2005-12-23 00:55:09 +00001863 ppHRegPPC(i->Pin.FpLdSt.reg);
cerion094d1392005-06-20 13:45:57 +00001864 vex_printf(",");
cerion5b2325f2005-12-23 00:55:09 +00001865 ppPPCAMode(i->Pin.FpLdSt.addr);
cerion094d1392005-06-20 13:45:57 +00001866 }
1867 return;
1868 }
sewardj92923de2006-01-25 21:29:48 +00001869 case Pin_FpSTFIW:
1870 vex_printf("stfiwz ");
1871 ppHRegPPC(i->Pin.FpSTFIW.data);
1872 vex_printf(",0(");
1873 ppHRegPPC(i->Pin.FpSTFIW.addr);
1874 vex_printf(")");
1875 return;
1876 case Pin_FpRSP:
cerion094d1392005-06-20 13:45:57 +00001877 vex_printf("frsp ");
sewardj92923de2006-01-25 21:29:48 +00001878 ppHRegPPC(i->Pin.FpRSP.dst);
cerion094d1392005-06-20 13:45:57 +00001879 vex_printf(",");
sewardj92923de2006-01-25 21:29:48 +00001880 ppHRegPPC(i->Pin.FpRSP.src);
cerion094d1392005-06-20 13:45:57 +00001881 return;
sewardj92923de2006-01-25 21:29:48 +00001882 case Pin_FpCftI: {
florian55085f82012-11-21 00:36:55 +00001883 const HChar* str = "fc?????";
sewardj4aa412a2011-07-24 14:13:21 +00001884 /* Note that "fcfids" is missing from below. That instruction would
1885 * satisfy the predicate:
1886 * (i->Pin.FpCftI.fromI == True && i->Pin.FpCftI.int32 == False)
1887 * which would go into a final "else" clause to make this if-else
1888 * block balanced. But we're able to implement fcfids by leveraging
1889 * the fcfid implementation, so it wasn't necessary to include it here.
1890 */
sewardj92923de2006-01-25 21:29:48 +00001891 if (i->Pin.FpCftI.fromI == False && i->Pin.FpCftI.int32 == False)
sewardj66d5ef22011-04-15 11:55:00 +00001892 if (i->Pin.FpCftI.syned == True)
sewardj4aa412a2011-07-24 14:13:21 +00001893 str = "fctid";
sewardj66d5ef22011-04-15 11:55:00 +00001894 else
sewardj4aa412a2011-07-24 14:13:21 +00001895 str = "fctidu";
1896 else if (i->Pin.FpCftI.fromI == False && i->Pin.FpCftI.int32 == True)
1897 if (i->Pin.FpCftI.syned == True)
1898 str = "fctiw";
1899 else
1900 str = "fctiwu";
1901 else if (i->Pin.FpCftI.fromI == True && i->Pin.FpCftI.int32 == False) {
1902 if (i->Pin.FpCftI.syned == True) {
1903 str = "fcfid";
1904 } else {
1905 if (i->Pin.FpCftI.flt64 == True)
1906 str = "fcfidu";
1907 else
1908 str = "fcfidus";
1909 }
sewardj66d5ef22011-04-15 11:55:00 +00001910 }
sewardj92923de2006-01-25 21:29:48 +00001911 vex_printf("%s ", str);
1912 ppHRegPPC(i->Pin.FpCftI.dst);
1913 vex_printf(",");
1914 ppHRegPPC(i->Pin.FpCftI.src);
cerion094d1392005-06-20 13:45:57 +00001915 return;
sewardj92923de2006-01-25 21:29:48 +00001916 }
cerion094d1392005-06-20 13:45:57 +00001917 case Pin_FpCMov:
cerion5b2325f2005-12-23 00:55:09 +00001918 vex_printf("fpcmov (%s) ", showPPCCondCode(i->Pin.FpCMov.cond));
1919 ppHRegPPC(i->Pin.FpCMov.dst);
cerion094d1392005-06-20 13:45:57 +00001920 vex_printf(",");
cerion5b2325f2005-12-23 00:55:09 +00001921 ppHRegPPC(i->Pin.FpCMov.src);
cerion094d1392005-06-20 13:45:57 +00001922 vex_printf(": ");
1923 vex_printf("if (fr_dst != fr_src) { ");
1924 if (i->Pin.FpCMov.cond.test != Pct_ALWAYS) {
cerion5b2325f2005-12-23 00:55:09 +00001925 vex_printf("if (%s) { ", showPPCCondCode(i->Pin.FpCMov.cond));
cerion094d1392005-06-20 13:45:57 +00001926 }
1927 vex_printf("fmr ");
cerion5b2325f2005-12-23 00:55:09 +00001928 ppHRegPPC(i->Pin.FpCMov.dst);
cerion094d1392005-06-20 13:45:57 +00001929 vex_printf(",");
cerion5b2325f2005-12-23 00:55:09 +00001930 ppHRegPPC(i->Pin.FpCMov.src);
cerion094d1392005-06-20 13:45:57 +00001931 if (i->Pin.FpCMov.cond.test != Pct_ALWAYS)
1932 vex_printf(" }");
1933 vex_printf(" }");
1934 return;
1935 case Pin_FpLdFPSCR:
1936 vex_printf("mtfsf 0xFF,");
cerion5b2325f2005-12-23 00:55:09 +00001937 ppHRegPPC(i->Pin.FpLdFPSCR.src);
sewardjc6bbd472012-04-02 10:20:48 +00001938 vex_printf(",0, %s", i->Pin.FpLdFPSCR.dfp_rm ? "1" : "0");
cerion094d1392005-06-20 13:45:57 +00001939 return;
1940 case Pin_FpCmp:
sewardjb51f0f42005-07-18 11:38:02 +00001941 vex_printf("fcmpo %%cr1,");
cerion5b2325f2005-12-23 00:55:09 +00001942 ppHRegPPC(i->Pin.FpCmp.srcL);
cerion094d1392005-06-20 13:45:57 +00001943 vex_printf(",");
cerion5b2325f2005-12-23 00:55:09 +00001944 ppHRegPPC(i->Pin.FpCmp.srcR);
cerion094d1392005-06-20 13:45:57 +00001945 vex_printf("; mfcr ");
cerion5b2325f2005-12-23 00:55:09 +00001946 ppHRegPPC(i->Pin.FpCmp.dst);
cerion094d1392005-06-20 13:45:57 +00001947 vex_printf("; rlwinm ");
cerion5b2325f2005-12-23 00:55:09 +00001948 ppHRegPPC(i->Pin.FpCmp.dst);
cerion094d1392005-06-20 13:45:57 +00001949 vex_printf(",");
cerion5b2325f2005-12-23 00:55:09 +00001950 ppHRegPPC(i->Pin.FpCmp.dst);
cerion094d1392005-06-20 13:45:57 +00001951 vex_printf(",8,28,31");
1952 return;
cerionbcf8c3e2005-02-04 16:17:07 +00001953
cerion7f000af2005-02-22 20:36:49 +00001954 case Pin_RdWrLR:
1955 vex_printf("%s ", i->Pin.RdWrLR.wrLR ? "mtlr" : "mflr");
cerion5b2325f2005-12-23 00:55:09 +00001956 ppHRegPPC(i->Pin.RdWrLR.gpr);
cerion7f000af2005-02-22 20:36:49 +00001957 return;
1958
cerionc3d8bdc2005-06-28 18:06:23 +00001959 case Pin_AvLdSt: {
sewardj197bd172005-10-12 11:34:33 +00001960 UChar sz = i->Pin.AvLdSt.sz;
florian55085f82012-11-21 00:36:55 +00001961 const HChar* str_size;
cerionc3d8bdc2005-06-28 18:06:23 +00001962 if (i->Pin.AvLdSt.addr->tag == Pam_IR) {
cerionf0de28c2005-12-13 20:21:11 +00001963 ppLoadImm(hregPPC_GPR30(mode64),
floriane6be61f2013-02-01 16:11:51 +00001964 i->Pin.AvLdSt.addr->Pam.IR.index, mode64);
cerion01713102005-06-29 19:05:08 +00001965 vex_printf(" ; ");
cerionc3d8bdc2005-06-28 18:06:23 +00001966 }
sewardj197bd172005-10-12 11:34:33 +00001967 str_size = sz==1 ? "eb" : sz==2 ? "eh" : sz==4 ? "ew" : "";
cerion01713102005-06-29 19:05:08 +00001968 if (i->Pin.AvLdSt.isLoad)
cerion225a0342005-09-12 20:49:09 +00001969 vex_printf("lv%sx ", str_size);
cerion01713102005-06-29 19:05:08 +00001970 else
cerion225a0342005-09-12 20:49:09 +00001971 vex_printf("stv%sx ", str_size);
cerion5b2325f2005-12-23 00:55:09 +00001972 ppHRegPPC(i->Pin.AvLdSt.reg);
cerion01713102005-06-29 19:05:08 +00001973 vex_printf(",");
1974 if (i->Pin.AvLdSt.addr->tag == Pam_IR)
1975 vex_printf("%%r30");
1976 else
cerion5b2325f2005-12-23 00:55:09 +00001977 ppHRegPPC(i->Pin.AvLdSt.addr->Pam.RR.index);
cerion01713102005-06-29 19:05:08 +00001978 vex_printf(",");
cerion5b2325f2005-12-23 00:55:09 +00001979 ppHRegPPC(i->Pin.AvLdSt.addr->Pam.RR.base);
cerionc3d8bdc2005-06-28 18:06:23 +00001980 return;
1981 }
1982 case Pin_AvUnary:
cerion5b2325f2005-12-23 00:55:09 +00001983 vex_printf("%s ", showPPCAvOp(i->Pin.AvUnary.op));
1984 ppHRegPPC(i->Pin.AvUnary.dst);
cerionc3d8bdc2005-06-28 18:06:23 +00001985 vex_printf(",");
cerion5b2325f2005-12-23 00:55:09 +00001986 ppHRegPPC(i->Pin.AvUnary.src);
cerionc3d8bdc2005-06-28 18:06:23 +00001987 return;
1988 case Pin_AvBinary:
cerion5b2325f2005-12-23 00:55:09 +00001989 vex_printf("%s ", showPPCAvOp(i->Pin.AvBinary.op));
1990 ppHRegPPC(i->Pin.AvBinary.dst);
cerionc3d8bdc2005-06-28 18:06:23 +00001991 vex_printf(",");
cerion5b2325f2005-12-23 00:55:09 +00001992 ppHRegPPC(i->Pin.AvBinary.srcL);
cerionc3d8bdc2005-06-28 18:06:23 +00001993 vex_printf(",");
cerion5b2325f2005-12-23 00:55:09 +00001994 ppHRegPPC(i->Pin.AvBinary.srcR);
cerionc3d8bdc2005-06-28 18:06:23 +00001995 return;
Elliott Hughesa0664b92017-04-18 17:46:52 -07001996 case Pin_AvBinaryInt:
1997 vex_printf("%s ", showPPCAvOp(i->Pin.AvBinaryInt.op));
1998 ppHRegPPC(i->Pin.AvBinaryInt.dst);
1999 vex_printf(",");
2000 ppHRegPPC(i->Pin.AvBinaryInt.src);
2001 vex_printf(",");
2002 ppPPCRI(i->Pin.AvBinaryInt.val);
2003 return;
cerion6b6f59e2005-06-28 20:59:18 +00002004 case Pin_AvBin8x16:
cerion5b2325f2005-12-23 00:55:09 +00002005 vex_printf("%s(b) ", showPPCAvOp(i->Pin.AvBin8x16.op));
2006 ppHRegPPC(i->Pin.AvBin8x16.dst);
cerion6b6f59e2005-06-28 20:59:18 +00002007 vex_printf(",");
cerion5b2325f2005-12-23 00:55:09 +00002008 ppHRegPPC(i->Pin.AvBin8x16.srcL);
cerion6b6f59e2005-06-28 20:59:18 +00002009 vex_printf(",");
cerion5b2325f2005-12-23 00:55:09 +00002010 ppHRegPPC(i->Pin.AvBin8x16.srcR);
cerion6b6f59e2005-06-28 20:59:18 +00002011 return;
2012 case Pin_AvBin16x8:
cerion5b2325f2005-12-23 00:55:09 +00002013 vex_printf("%s(h) ", showPPCAvOp(i->Pin.AvBin16x8.op));
2014 ppHRegPPC(i->Pin.AvBin16x8.dst);
cerion6b6f59e2005-06-28 20:59:18 +00002015 vex_printf(",");
cerion5b2325f2005-12-23 00:55:09 +00002016 ppHRegPPC(i->Pin.AvBin16x8.srcL);
cerion6b6f59e2005-06-28 20:59:18 +00002017 vex_printf(",");
cerion5b2325f2005-12-23 00:55:09 +00002018 ppHRegPPC(i->Pin.AvBin16x8.srcR);
cerion6b6f59e2005-06-28 20:59:18 +00002019 return;
2020 case Pin_AvBin32x4:
cerion5b2325f2005-12-23 00:55:09 +00002021 vex_printf("%s(w) ", showPPCAvOp(i->Pin.AvBin32x4.op));
2022 ppHRegPPC(i->Pin.AvBin32x4.dst);
cerion6b6f59e2005-06-28 20:59:18 +00002023 vex_printf(",");
cerion5b2325f2005-12-23 00:55:09 +00002024 ppHRegPPC(i->Pin.AvBin32x4.srcL);
cerion6b6f59e2005-06-28 20:59:18 +00002025 vex_printf(",");
cerion5b2325f2005-12-23 00:55:09 +00002026 ppHRegPPC(i->Pin.AvBin32x4.srcR);
cerion6b6f59e2005-06-28 20:59:18 +00002027 return;
carll0c74bb52013-08-12 18:01:40 +00002028 case Pin_AvBin64x2:
2029 vex_printf("%s(w) ", showPPCAvOp(i->Pin.AvBin64x2.op));
2030 ppHRegPPC(i->Pin.AvBin64x2.dst);
2031 vex_printf(",");
2032 ppHRegPPC(i->Pin.AvBin64x2.srcL);
2033 vex_printf(",");
2034 ppHRegPPC(i->Pin.AvBin64x2.srcR);
2035 return;
cerion6b6f59e2005-06-28 20:59:18 +00002036 case Pin_AvBin32Fx4:
cerion5b2325f2005-12-23 00:55:09 +00002037 vex_printf("%s ", showPPCAvFpOp(i->Pin.AvBin32Fx4.op));
2038 ppHRegPPC(i->Pin.AvBin32Fx4.dst);
cerion6b6f59e2005-06-28 20:59:18 +00002039 vex_printf(",");
cerion5b2325f2005-12-23 00:55:09 +00002040 ppHRegPPC(i->Pin.AvBin32Fx4.srcL);
cerion6b6f59e2005-06-28 20:59:18 +00002041 vex_printf(",");
cerion5b2325f2005-12-23 00:55:09 +00002042 ppHRegPPC(i->Pin.AvBin32Fx4.srcR);
cerion6b6f59e2005-06-28 20:59:18 +00002043 return;
cerion8ea0d3e2005-11-14 00:44:47 +00002044 case Pin_AvUn32Fx4:
cerion5b2325f2005-12-23 00:55:09 +00002045 vex_printf("%s ", showPPCAvFpOp(i->Pin.AvUn32Fx4.op));
2046 ppHRegPPC(i->Pin.AvUn32Fx4.dst);
cerion8ea0d3e2005-11-14 00:44:47 +00002047 vex_printf(",");
cerion5b2325f2005-12-23 00:55:09 +00002048 ppHRegPPC(i->Pin.AvUn32Fx4.src);
cerion8ea0d3e2005-11-14 00:44:47 +00002049 return;
cerionc3d8bdc2005-06-28 18:06:23 +00002050 case Pin_AvPerm:
2051 vex_printf("vperm ");
cerion5b2325f2005-12-23 00:55:09 +00002052 ppHRegPPC(i->Pin.AvPerm.dst);
cerionc3d8bdc2005-06-28 18:06:23 +00002053 vex_printf(",");
cerion5b2325f2005-12-23 00:55:09 +00002054 ppHRegPPC(i->Pin.AvPerm.srcL);
cerionc3d8bdc2005-06-28 18:06:23 +00002055 vex_printf(",");
cerion5b2325f2005-12-23 00:55:09 +00002056 ppHRegPPC(i->Pin.AvPerm.srcR);
cerionc3d8bdc2005-06-28 18:06:23 +00002057 vex_printf(",");
cerion5b2325f2005-12-23 00:55:09 +00002058 ppHRegPPC(i->Pin.AvPerm.ctl);
cerionc3d8bdc2005-06-28 18:06:23 +00002059 return;
2060
2061 case Pin_AvSel:
2062 vex_printf("vsel ");
cerion5b2325f2005-12-23 00:55:09 +00002063 ppHRegPPC(i->Pin.AvSel.dst);
cerionc3d8bdc2005-06-28 18:06:23 +00002064 vex_printf(",");
cerion5b2325f2005-12-23 00:55:09 +00002065 ppHRegPPC(i->Pin.AvSel.srcL);
cerionc3d8bdc2005-06-28 18:06:23 +00002066 vex_printf(",");
cerion5b2325f2005-12-23 00:55:09 +00002067 ppHRegPPC(i->Pin.AvSel.srcR);
cerionc3d8bdc2005-06-28 18:06:23 +00002068 vex_printf(",");
cerion5b2325f2005-12-23 00:55:09 +00002069 ppHRegPPC(i->Pin.AvSel.ctl);
cerionc3d8bdc2005-06-28 18:06:23 +00002070 return;
2071
carll9877fe52014-10-07 17:49:14 +00002072 case Pin_AvSh:
2073 /* This only generates the following instructions with RA
2074 * register number set to 0.
2075 */
2076 if (i->Pin.AvSh.addr->tag == Pam_IR) {
2077 ppLoadImm(hregPPC_GPR30(mode64),
2078 i->Pin.AvSh.addr->Pam.IR.index, mode64);
2079 vex_printf(" ; ");
2080 }
2081
2082 if (i->Pin.AvSh.shLeft)
2083 vex_printf("lvsl ");
2084 else
2085 vex_printf("lvsr ");
2086
2087 ppHRegPPC(i->Pin.AvSh.dst);
2088 if (i->Pin.AvSh.addr->tag == Pam_IR)
2089 vex_printf("%%r30");
2090 else
2091 ppHRegPPC(i->Pin.AvSh.addr->Pam.RR.index);
2092 vex_printf(",");
2093 ppHRegPPC(i->Pin.AvSh.addr->Pam.RR.base);
2094 return;
2095
cerionc3d8bdc2005-06-28 18:06:23 +00002096 case Pin_AvShlDbl:
2097 vex_printf("vsldoi ");
cerion5b2325f2005-12-23 00:55:09 +00002098 ppHRegPPC(i->Pin.AvShlDbl.dst);
cerionc3d8bdc2005-06-28 18:06:23 +00002099 vex_printf(",");
cerion5b2325f2005-12-23 00:55:09 +00002100 ppHRegPPC(i->Pin.AvShlDbl.srcL);
cerionc3d8bdc2005-06-28 18:06:23 +00002101 vex_printf(",");
cerion5b2325f2005-12-23 00:55:09 +00002102 ppHRegPPC(i->Pin.AvShlDbl.srcR);
sewardjdb36c0f2005-07-03 00:05:31 +00002103 vex_printf(",%d", i->Pin.AvShlDbl.shift);
cerionc3d8bdc2005-06-28 18:06:23 +00002104 return;
2105
2106 case Pin_AvSplat: {
cerion27b3d7e2005-09-14 20:35:47 +00002107 UChar sz = i->Pin.AvSplat.sz;
florian5df8ab02012-10-13 19:34:19 +00002108 HChar ch_sz = toUChar( (sz == 8) ? 'b' : (sz == 16) ? 'h' : 'w' );
cerionc3d8bdc2005-06-28 18:06:23 +00002109 vex_printf("vsplt%s%c ",
cerion27b3d7e2005-09-14 20:35:47 +00002110 i->Pin.AvSplat.src->tag == Pvi_Imm ? "is" : "", ch_sz);
cerion5b2325f2005-12-23 00:55:09 +00002111 ppHRegPPC(i->Pin.AvSplat.dst);
cerionc3d8bdc2005-06-28 18:06:23 +00002112 vex_printf(",");
cerion5b2325f2005-12-23 00:55:09 +00002113 ppPPCVI5s(i->Pin.AvSplat.src);
cerion27b3d7e2005-09-14 20:35:47 +00002114 if (i->Pin.AvSplat.src->tag == Pvi_Reg)
sewardj62d05432005-10-29 22:30:47 +00002115 vex_printf(", %d", (128/sz)-1); /* louis lane */
cerionc3d8bdc2005-06-28 18:06:23 +00002116 return;
2117 }
2118
cerion6b6f59e2005-06-28 20:59:18 +00002119 case Pin_AvCMov:
cerion5b2325f2005-12-23 00:55:09 +00002120 vex_printf("avcmov (%s) ", showPPCCondCode(i->Pin.AvCMov.cond));
2121 ppHRegPPC(i->Pin.AvCMov.dst);
cerion6b6f59e2005-06-28 20:59:18 +00002122 vex_printf(",");
cerion5b2325f2005-12-23 00:55:09 +00002123 ppHRegPPC(i->Pin.AvCMov.src);
cerion6b6f59e2005-06-28 20:59:18 +00002124 vex_printf(": ");
2125 vex_printf("if (v_dst != v_src) { ");
2126 if (i->Pin.AvCMov.cond.test != Pct_ALWAYS) {
cerion5b2325f2005-12-23 00:55:09 +00002127 vex_printf("if (%s) { ", showPPCCondCode(i->Pin.AvCMov.cond));
cerion6b6f59e2005-06-28 20:59:18 +00002128 }
2129 vex_printf("vmr ");
cerion5b2325f2005-12-23 00:55:09 +00002130 ppHRegPPC(i->Pin.AvCMov.dst);
cerion6b6f59e2005-06-28 20:59:18 +00002131 vex_printf(",");
cerion5b2325f2005-12-23 00:55:09 +00002132 ppHRegPPC(i->Pin.AvCMov.src);
cerion6b6f59e2005-06-28 20:59:18 +00002133 if (i->Pin.FpCMov.cond.test != Pct_ALWAYS)
2134 vex_printf(" }");
2135 vex_printf(" }");
2136 return;
2137
cerionc3d8bdc2005-06-28 18:06:23 +00002138 case Pin_AvLdVSCR:
2139 vex_printf("mtvscr ");
cerion5b2325f2005-12-23 00:55:09 +00002140 ppHRegPPC(i->Pin.AvLdVSCR.src);
cerionc3d8bdc2005-06-28 18:06:23 +00002141 return;
2142
carll7deaf952013-10-15 18:11:20 +00002143 case Pin_AvCipherV128Unary:
2144 vex_printf("%s(w) ", showPPCAvOp(i->Pin.AvCipherV128Unary.op));
2145 ppHRegPPC(i->Pin.AvCipherV128Unary.dst);
2146 vex_printf(",");
2147 ppHRegPPC(i->Pin.AvCipherV128Unary.src);
2148 return;
2149
2150 case Pin_AvCipherV128Binary:
2151 vex_printf("%s(w) ", showPPCAvOp(i->Pin.AvCipherV128Binary.op));
2152 ppHRegPPC(i->Pin.AvCipherV128Binary.dst);
2153 vex_printf(",");
2154 ppHRegPPC(i->Pin.AvCipherV128Binary.srcL);
2155 vex_printf(",");
2156 ppHRegPPC(i->Pin.AvCipherV128Binary.srcR);
2157 return;
2158
2159 case Pin_AvHashV128Binary:
2160 vex_printf("%s(w) ", showPPCAvOp(i->Pin.AvHashV128Binary.op));
2161 ppHRegPPC(i->Pin.AvHashV128Binary.dst);
2162 vex_printf(",");
2163 ppHRegPPC(i->Pin.AvHashV128Binary.src);
2164 vex_printf(",");
2165 ppPPCRI(i->Pin.AvHashV128Binary.s_field);
2166 return;
2167
Elliott Hughesa0664b92017-04-18 17:46:52 -07002168 case Pin_AvBCDV128Binary:
2169 vex_printf("%s(w) ", showPPCAvOp(i->Pin.AvBCDV128Binary.op));
2170 ppHRegPPC(i->Pin.AvBCDV128Binary.dst);
carll7deaf952013-10-15 18:11:20 +00002171 vex_printf(",");
Elliott Hughesa0664b92017-04-18 17:46:52 -07002172 ppHRegPPC(i->Pin.AvBCDV128Binary.src1);
carll7deaf952013-10-15 18:11:20 +00002173 vex_printf(",");
Elliott Hughesa0664b92017-04-18 17:46:52 -07002174 ppHRegPPC(i->Pin.AvBCDV128Binary.src2);
carll7deaf952013-10-15 18:11:20 +00002175 return;
2176
sewardjc6bbd472012-04-02 10:20:48 +00002177 case Pin_Dfp64Unary:
2178 vex_printf("%s ", showPPCFpOp(i->Pin.Dfp64Unary.op));
2179 ppHRegPPC(i->Pin.Dfp64Unary.dst);
2180 vex_printf(",");
2181 ppHRegPPC(i->Pin.Dfp64Unary.src);
2182 return;
2183
2184 case Pin_Dfp64Binary:
2185 vex_printf("%s ", showPPCFpOp(i->Pin.Dfp64Binary.op));
2186 ppHRegPPC(i->Pin.Dfp64Binary.dst);
2187 vex_printf(",");
2188 ppHRegPPC(i->Pin.Dfp64Binary.srcL);
2189 vex_printf(",");
2190 ppHRegPPC(i->Pin.Dfp64Binary.srcR);
2191 return;
2192
sewardj26217b02012-04-12 17:19:48 +00002193 case Pin_DfpShift:
2194 vex_printf("%s ", showPPCFpOp(i->Pin.DfpShift.op));
2195 ppHRegPPC(i->Pin.DfpShift.dst);
2196 vex_printf(",");
2197 ppHRegPPC(i->Pin.DfpShift.src);
2198 vex_printf(",");
2199 ppPPCRI(i->Pin.DfpShift.shift);
2200 return;
2201
2202 case Pin_Dfp128Unary:
2203 vex_printf("%s ", showPPCFpOp(i->Pin.Dfp128Unary.op));
2204 ppHRegPPC(i->Pin.Dfp128Unary.dst_hi);
2205 vex_printf(",");
2206 ppHRegPPC(i->Pin.Dfp128Unary.src_hi);
2207 return;
2208
sewardjc6bbd472012-04-02 10:20:48 +00002209 case Pin_Dfp128Binary:
2210 vex_printf("%s ", showPPCFpOp(i->Pin.Dfp128Binary.op));
2211 ppHRegPPC(i->Pin.Dfp128Binary.dst_hi);
2212 vex_printf(",");
2213 ppHRegPPC(i->Pin.Dfp128Binary.srcR_hi);
2214 return;
2215
sewardj26217b02012-04-12 17:19:48 +00002216 case Pin_DfpShift128:
2217 vex_printf("%s ", showPPCFpOp(i->Pin.DfpShift128.op));
2218 ppHRegPPC(i->Pin.DfpShift128.dst_hi);
2219 vex_printf(",");
2220 ppHRegPPC(i->Pin.DfpShift128.src_hi);
2221 vex_printf(",");
2222 ppPPCRI(i->Pin.DfpShift128.shift);
2223 return;
2224
sewardjcdc376d2012-04-23 11:21:12 +00002225 case Pin_DfpRound:
2226 vex_printf("drintx ");
2227 ppHRegPPC(i->Pin.DfpRound.dst);
2228 vex_printf(",");
2229 ppHRegPPC(i->Pin.DfpRound.src);
2230 vex_printf(",");
2231 ppPPCRI(i->Pin.DfpRound.r_rmc); /* R in bit 3 and RMC in bits 2:0 */
2232 return;
2233
2234 case Pin_DfpRound128:
2235 vex_printf("drintxq ");
2236 ppHRegPPC(i->Pin.DfpRound128.dst_hi);
2237 vex_printf(",");
2238 ppHRegPPC(i->Pin.DfpRound128.src_hi);
2239 vex_printf(",");
2240 ppPPCRI(i->Pin.DfpRound128.r_rmc); /* R in bit 3 and RMC in bits 2:0 */
2241 return;
2242
2243 case Pin_DfpQuantize:
2244 vex_printf("%s ", showPPCFpOp(i->Pin.DfpQuantize.op));
2245 ppHRegPPC(i->Pin.DfpQuantize.dst);
2246 vex_printf(",");
2247 ppHRegPPC(i->Pin.DfpQuantize.srcL);
2248 vex_printf(",");
2249 ppHRegPPC(i->Pin.DfpQuantize.srcR);
2250 vex_printf(",");
2251 ppPPCRI(i->Pin.DfpQuantize.rmc);
2252 return;
2253
2254 case Pin_DfpQuantize128:
2255 /* Dst is used to pass in left source and return result */
2256 vex_printf("dquaq ");
2257 ppHRegPPC(i->Pin.DfpQuantize128.dst_hi);
2258 vex_printf(",");
2259 ppHRegPPC(i->Pin.DfpQuantize128.dst_hi);
2260 vex_printf(",");
2261 ppHRegPPC(i->Pin.DfpQuantize128.src_hi);
2262 vex_printf(",");
2263 ppPPCRI(i->Pin.DfpQuantize128.rmc);
2264 return;
2265
sewardj26217b02012-04-12 17:19:48 +00002266 case Pin_DfpD128toD64:
2267 vex_printf("%s ", showPPCFpOp(i->Pin.DfpD128toD64.op));
2268 ppHRegPPC(i->Pin.DfpD128toD64.dst);
2269 vex_printf(",");
2270 ppHRegPPC(i->Pin.DfpD128toD64.src_hi);
2271 vex_printf(",");
2272 return;
2273
2274 case Pin_DfpI64StoD128:
2275 vex_printf("%s ", showPPCFpOp(i->Pin.DfpI64StoD128.op));
2276 ppHRegPPC(i->Pin.DfpI64StoD128.dst_hi);
2277 vex_printf(",");
2278 ppHRegPPC(i->Pin.DfpI64StoD128.src);
2279 vex_printf(",");
2280 return;
sewardjcdc376d2012-04-23 11:21:12 +00002281 case Pin_ExtractExpD128:
2282 vex_printf("dxexq ");
2283 ppHRegPPC(i->Pin.ExtractExpD128.dst);
2284 vex_printf(",");
2285 ppHRegPPC(i->Pin.ExtractExpD128.src_hi);
2286 return;
2287 case Pin_InsertExpD128:
2288 vex_printf("diexq ");
2289 ppHRegPPC(i->Pin.InsertExpD128.dst_hi);
2290 vex_printf(",");
2291 ppHRegPPC(i->Pin.InsertExpD128.srcL);
2292 vex_printf(",");
2293 ppHRegPPC(i->Pin.InsertExpD128.srcR_hi);
2294 return;
2295 case Pin_Dfp64Cmp:
2296 vex_printf("dcmpo %%cr1,");
2297 ppHRegPPC(i->Pin.Dfp64Cmp.srcL);
2298 vex_printf(",");
2299 ppHRegPPC(i->Pin.Dfp64Cmp.srcR);
2300 vex_printf("; mfcr ");
2301 ppHRegPPC(i->Pin.Dfp64Cmp.dst);
2302 vex_printf("; rlwinm ");
2303 ppHRegPPC(i->Pin.Dfp64Cmp.dst);
2304 vex_printf(",");
2305 ppHRegPPC(i->Pin.Dfp64Cmp.dst);
2306 vex_printf(",8,28,31");
2307 return;
2308 case Pin_Dfp128Cmp:
2309 vex_printf("dcmpoq %%cr1,");
2310 ppHRegPPC(i->Pin.Dfp128Cmp.srcL_hi);
2311 vex_printf(",");
2312 ppHRegPPC(i->Pin.Dfp128Cmp.srcR_hi);
2313 vex_printf("; mfcr ");
2314 ppHRegPPC(i->Pin.Dfp128Cmp.dst);
2315 vex_printf("; rlwinm ");
2316 ppHRegPPC(i->Pin.Dfp128Cmp.dst);
2317 vex_printf(",");
2318 ppHRegPPC(i->Pin.Dfp128Cmp.dst);
2319 vex_printf(",8,28,31");
2320 return;
sewardj3dee8492012-04-20 00:13:28 +00002321 case Pin_EvCheck:
2322 /* Note that the counter dec is 32 bit even in 64-bit mode. */
2323 vex_printf("(evCheck) ");
2324 vex_printf("lwz r30,");
2325 ppPPCAMode(i->Pin.EvCheck.amCounter);
2326 vex_printf("; addic. r30,r30,-1; ");
2327 vex_printf("stw r30,");
2328 ppPPCAMode(i->Pin.EvCheck.amCounter);
2329 vex_printf("; bge nofail; lwz r30,");
2330 ppPPCAMode(i->Pin.EvCheck.amFailAddr);
2331 vex_printf("; mtctr r30; bctr; nofail:");
2332 return;
sewardj3dee8492012-04-20 00:13:28 +00002333 case Pin_ProfInc:
2334 if (mode64) {
sewardjf252de52012-04-20 10:42:24 +00002335 vex_printf("(profInc) imm64-fixed5 r30,$NotKnownYet; ");
sewardj3dee8492012-04-20 00:13:28 +00002336 vex_printf("ld r29,(r30); addi r29,r29,1; std r29,(r30)");
2337 } else {
sewardjf252de52012-04-20 10:42:24 +00002338 vex_printf("(profInc) imm32-fixed2 r30,$NotKnownYet; ");
sewardj3dee8492012-04-20 00:13:28 +00002339 vex_printf("lwz r29,4(r30); addic. r29,r29,1; stw r29,4(r30)");
2340 vex_printf("lwz r29,0(r30); addze r29,r29; stw r29,0(r30)");
2341 }
2342 break;
cerionb85e8bb2005-02-16 08:54:33 +00002343 default:
cerion5b2325f2005-12-23 00:55:09 +00002344 vex_printf("\nppPPCInstr: No such tag(%d)\n", (Int)i->tag);
2345 vpanic("ppPPCInstr");
cerionbcf8c3e2005-02-04 16:17:07 +00002346 }
2347}
2348
2349/* --------- Helpers for register allocation. --------- */
2350
floriand8c64e02014-10-08 08:54:44 +00002351void getRegUsage_PPCInstr ( HRegUsage* u, const PPCInstr* i, Bool mode64 )
cerionbcf8c3e2005-02-04 16:17:07 +00002352{
cerionbcf8c3e2005-02-04 16:17:07 +00002353 initHRegUsage(u);
2354 switch (i->tag) {
cerionf0de28c2005-12-13 20:21:11 +00002355 case Pin_LI:
2356 addHRegUse(u, HRmWrite, i->Pin.LI.dst);
sewardjb51f0f42005-07-18 11:38:02 +00002357 break;
cerionf0de28c2005-12-13 20:21:11 +00002358 case Pin_Alu:
cerion5b2325f2005-12-23 00:55:09 +00002359 addHRegUse(u, HRmRead, i->Pin.Alu.srcL);
2360 addRegUsage_PPCRH(u, i->Pin.Alu.srcR);
cerionf0de28c2005-12-13 20:21:11 +00002361 addHRegUse(u, HRmWrite, i->Pin.Alu.dst);
cerionb85e8bb2005-02-16 08:54:33 +00002362 return;
cerionbb01b7c2005-12-16 13:40:18 +00002363 case Pin_Shft:
2364 addHRegUse(u, HRmRead, i->Pin.Shft.srcL);
cerion5b2325f2005-12-23 00:55:09 +00002365 addRegUsage_PPCRH(u, i->Pin.Shft.srcR);
cerionbb01b7c2005-12-16 13:40:18 +00002366 addHRegUse(u, HRmWrite, i->Pin.Shft.dst);
2367 return;
cerion5b2325f2005-12-23 00:55:09 +00002368 case Pin_AddSubC:
2369 addHRegUse(u, HRmWrite, i->Pin.AddSubC.dst);
2370 addHRegUse(u, HRmRead, i->Pin.AddSubC.srcL);
2371 addHRegUse(u, HRmRead, i->Pin.AddSubC.srcR);
cerion4a49b032005-11-08 16:23:07 +00002372 return;
cerionf0de28c2005-12-13 20:21:11 +00002373 case Pin_Cmp:
2374 addHRegUse(u, HRmRead, i->Pin.Cmp.srcL);
cerion5b2325f2005-12-23 00:55:09 +00002375 addRegUsage_PPCRH(u, i->Pin.Cmp.srcR);
cerionb85e8bb2005-02-16 08:54:33 +00002376 return;
cerionf0de28c2005-12-13 20:21:11 +00002377 case Pin_Unary:
cerion5b2325f2005-12-23 00:55:09 +00002378 addHRegUse(u, HRmWrite, i->Pin.Unary.dst);
2379 addHRegUse(u, HRmRead, i->Pin.Unary.src);
cerionb85e8bb2005-02-16 08:54:33 +00002380 return;
2381 case Pin_MulL:
2382 addHRegUse(u, HRmWrite, i->Pin.MulL.dst);
cerion5b2325f2005-12-23 00:55:09 +00002383 addHRegUse(u, HRmRead, i->Pin.MulL.srcL);
2384 addHRegUse(u, HRmRead, i->Pin.MulL.srcR);
cerionb85e8bb2005-02-16 08:54:33 +00002385 return;
2386 case Pin_Div:
2387 addHRegUse(u, HRmWrite, i->Pin.Div.dst);
cerion5b2325f2005-12-23 00:55:09 +00002388 addHRegUse(u, HRmRead, i->Pin.Div.srcL);
2389 addHRegUse(u, HRmRead, i->Pin.Div.srcR);
cerionb85e8bb2005-02-16 08:54:33 +00002390 return;
cerionf0de28c2005-12-13 20:21:11 +00002391 case Pin_Call: {
2392 UInt argir;
cerionb85e8bb2005-02-16 08:54:33 +00002393 /* This is a bit subtle. */
2394 /* First off, claim it trashes all the caller-saved regs
2395 which fall within the register allocator's jurisdiction.
cerionf0de28c2005-12-13 20:21:11 +00002396 These I believe to be:
2397 mode32: r3 to r12
2398 mode64: r3 to r10
cerionb85e8bb2005-02-16 08:54:33 +00002399 */
sewardjcb1f68e2005-12-30 03:39:14 +00002400 /* XXXXXXXXXXXXXXXXX BUG! This doesn't say anything about the FP
2401 or Altivec registers. We get away with this ONLY because
2402 getAllocatableRegs_PPC gives the allocator callee-saved fp
2403 and Altivec regs, and no caller-save ones. */
cerionf0de28c2005-12-13 20:21:11 +00002404 addHRegUse(u, HRmWrite, hregPPC_GPR3(mode64));
2405 addHRegUse(u, HRmWrite, hregPPC_GPR4(mode64));
2406 addHRegUse(u, HRmWrite, hregPPC_GPR5(mode64));
2407 addHRegUse(u, HRmWrite, hregPPC_GPR6(mode64));
2408 addHRegUse(u, HRmWrite, hregPPC_GPR7(mode64));
2409 addHRegUse(u, HRmWrite, hregPPC_GPR8(mode64));
2410 addHRegUse(u, HRmWrite, hregPPC_GPR9(mode64));
2411 addHRegUse(u, HRmWrite, hregPPC_GPR10(mode64));
2412 if (!mode64) {
2413 addHRegUse(u, HRmWrite, hregPPC_GPR11(mode64));
2414 addHRegUse(u, HRmWrite, hregPPC_GPR12(mode64));
2415 }
2416
cerionb85e8bb2005-02-16 08:54:33 +00002417 /* Now we have to state any parameter-carrying registers
sewardj6a64a9f2005-08-21 00:48:37 +00002418 which might be read. This depends on the argiregs field. */
cerionf0de28c2005-12-13 20:21:11 +00002419 argir = i->Pin.Call.argiregs;
2420 if (argir &(1<<10)) addHRegUse(u, HRmRead, hregPPC_GPR10(mode64));
2421 if (argir & (1<<9)) addHRegUse(u, HRmRead, hregPPC_GPR9(mode64));
2422 if (argir & (1<<8)) addHRegUse(u, HRmRead, hregPPC_GPR8(mode64));
2423 if (argir & (1<<7)) addHRegUse(u, HRmRead, hregPPC_GPR7(mode64));
2424 if (argir & (1<<6)) addHRegUse(u, HRmRead, hregPPC_GPR6(mode64));
2425 if (argir & (1<<5)) addHRegUse(u, HRmRead, hregPPC_GPR5(mode64));
2426 if (argir & (1<<4)) addHRegUse(u, HRmRead, hregPPC_GPR4(mode64));
2427 if (argir & (1<<3)) addHRegUse(u, HRmRead, hregPPC_GPR3(mode64));
sewardj6a64a9f2005-08-21 00:48:37 +00002428
cerionf0de28c2005-12-13 20:21:11 +00002429 vassert(0 == (argir & ~((1<<3)|(1<<4)|(1<<5)|(1<<6)
2430 |(1<<7)|(1<<8)|(1<<9)|(1<<10))));
sewardj6a64a9f2005-08-21 00:48:37 +00002431
cerionb85e8bb2005-02-16 08:54:33 +00002432 /* Finally, there is the issue that the insn trashes a
2433 register because the literal target address has to be
cerionf0de28c2005-12-13 20:21:11 +00002434 loaded into a register. %r10 seems a suitable victim.
sewardje9d8a262009-07-01 08:06:34 +00002435 (Can't use %r0, as some insns interpret it as value zero). */
cerionf0de28c2005-12-13 20:21:11 +00002436 addHRegUse(u, HRmWrite, hregPPC_GPR10(mode64));
2437 /* Upshot of this is that the assembler really must use %r10,
ceriona56e9cc2005-02-16 18:08:25 +00002438 and no other, as a destination temporary. */
cerionb85e8bb2005-02-16 08:54:33 +00002439 return;
cerionf0de28c2005-12-13 20:21:11 +00002440 }
sewardj3dee8492012-04-20 00:13:28 +00002441 /* XDirect/XIndir/XAssisted are also a bit subtle. They
2442 conditionally exit the block. Hence we only need to list (1)
2443 the registers that they read, and (2) the registers that they
2444 write in the case where the block is not exited. (2) is empty,
2445 hence only (1) is relevant here. */
2446 case Pin_XDirect:
2447 addRegUsage_PPCAMode(u, i->Pin.XDirect.amCIA);
2448 return;
2449 case Pin_XIndir:
2450 addHRegUse(u, HRmRead, i->Pin.XIndir.dstGA);
2451 addRegUsage_PPCAMode(u, i->Pin.XIndir.amCIA);
2452 return;
2453 case Pin_XAssisted:
2454 addHRegUse(u, HRmRead, i->Pin.XAssisted.dstGA);
2455 addRegUsage_PPCAMode(u, i->Pin.XAssisted.amCIA);
cerionb85e8bb2005-02-16 08:54:33 +00002456 return;
cerionf0de28c2005-12-13 20:21:11 +00002457 case Pin_CMov:
cerion5b2325f2005-12-23 00:55:09 +00002458 addRegUsage_PPCRI(u, i->Pin.CMov.src);
cerionf0de28c2005-12-13 20:21:11 +00002459 addHRegUse(u, HRmWrite, i->Pin.CMov.dst);
cerionb85e8bb2005-02-16 08:54:33 +00002460 return;
cerion7cf8e4e2005-02-16 16:08:17 +00002461 case Pin_Load:
cerion5b2325f2005-12-23 00:55:09 +00002462 addRegUsage_PPCAMode(u, i->Pin.Load.src);
cerion7cf8e4e2005-02-16 16:08:17 +00002463 addHRegUse(u, HRmWrite, i->Pin.Load.dst);
cerionb85e8bb2005-02-16 08:54:33 +00002464 return;
sewardje9d8a262009-07-01 08:06:34 +00002465 case Pin_LoadL:
2466 addHRegUse(u, HRmRead, i->Pin.LoadL.src);
2467 addHRegUse(u, HRmWrite, i->Pin.LoadL.dst);
2468 return;
cerionb85e8bb2005-02-16 08:54:33 +00002469 case Pin_Store:
cerion5b2325f2005-12-23 00:55:09 +00002470 addHRegUse(u, HRmRead, i->Pin.Store.src);
2471 addRegUsage_PPCAMode(u, i->Pin.Store.dst);
cerionb85e8bb2005-02-16 08:54:33 +00002472 return;
sewardje9d8a262009-07-01 08:06:34 +00002473 case Pin_StoreC:
2474 addHRegUse(u, HRmRead, i->Pin.StoreC.src);
2475 addHRegUse(u, HRmRead, i->Pin.StoreC.dst);
2476 return;
cerion5b2325f2005-12-23 00:55:09 +00002477 case Pin_Set:
2478 addHRegUse(u, HRmWrite, i->Pin.Set.dst);
cerionb85e8bb2005-02-16 08:54:33 +00002479 return;
sewardjb51f0f42005-07-18 11:38:02 +00002480 case Pin_MfCR:
2481 addHRegUse(u, HRmWrite, i->Pin.MfCR.dst);
2482 return;
cerionb85e8bb2005-02-16 08:54:33 +00002483 case Pin_MFence:
2484 return;
cerion094d1392005-06-20 13:45:57 +00002485
2486 case Pin_FpUnary:
2487 addHRegUse(u, HRmWrite, i->Pin.FpUnary.dst);
2488 addHRegUse(u, HRmRead, i->Pin.FpUnary.src);
2489 return;
2490 case Pin_FpBinary:
2491 addHRegUse(u, HRmWrite, i->Pin.FpBinary.dst);
2492 addHRegUse(u, HRmRead, i->Pin.FpBinary.srcL);
2493 addHRegUse(u, HRmRead, i->Pin.FpBinary.srcR);
2494 return;
Elliott Hughesa0664b92017-04-18 17:46:52 -07002495
2496 case Pin_Fp128Unary:
2497 addHRegUse(u, HRmWrite, i->Pin.Fp128Unary.dst);
2498 addHRegUse(u, HRmRead, i->Pin.Fp128Unary.src);
2499 return;
2500 case Pin_Fp128Binary:
2501 addHRegUse(u, HRmWrite, i->Pin.Fp128Binary.dst);
2502 addHRegUse(u, HRmRead, i->Pin.Fp128Binary.srcL);
2503 addHRegUse(u, HRmRead, i->Pin.Fp128Binary.srcR);
2504 return;
2505 case Pin_Fp128Trinary:
2506 addHRegUse(u, HRmModify, i->Pin.Fp128Trinary.dst);
2507 addHRegUse(u, HRmRead, i->Pin.Fp128Trinary.srcL);
2508 addHRegUse(u, HRmRead, i->Pin.Fp128Trinary.srcR);
2509 return;
sewardj40c80262006-02-08 19:30:46 +00002510 case Pin_FpMulAcc:
2511 addHRegUse(u, HRmWrite, i->Pin.FpMulAcc.dst);
2512 addHRegUse(u, HRmRead, i->Pin.FpMulAcc.srcML);
2513 addHRegUse(u, HRmRead, i->Pin.FpMulAcc.srcMR);
2514 addHRegUse(u, HRmRead, i->Pin.FpMulAcc.srcAcc);
2515 return;
cerion094d1392005-06-20 13:45:57 +00002516 case Pin_FpLdSt:
2517 addHRegUse(u, (i->Pin.FpLdSt.isLoad ? HRmWrite : HRmRead),
2518 i->Pin.FpLdSt.reg);
cerion5b2325f2005-12-23 00:55:09 +00002519 addRegUsage_PPCAMode(u, i->Pin.FpLdSt.addr);
cerion094d1392005-06-20 13:45:57 +00002520 return;
sewardj92923de2006-01-25 21:29:48 +00002521 case Pin_FpSTFIW:
2522 addHRegUse(u, HRmRead, i->Pin.FpSTFIW.addr);
2523 addHRegUse(u, HRmRead, i->Pin.FpSTFIW.data);
cerion094d1392005-06-20 13:45:57 +00002524 return;
sewardj92923de2006-01-25 21:29:48 +00002525 case Pin_FpRSP:
2526 addHRegUse(u, HRmWrite, i->Pin.FpRSP.dst);
2527 addHRegUse(u, HRmRead, i->Pin.FpRSP.src);
cerion094d1392005-06-20 13:45:57 +00002528 return;
sewardj92923de2006-01-25 21:29:48 +00002529 case Pin_FpCftI:
2530 addHRegUse(u, HRmWrite, i->Pin.FpCftI.dst);
2531 addHRegUse(u, HRmRead, i->Pin.FpCftI.src);
cerion07b07a92005-12-22 14:32:35 +00002532 return;
cerion094d1392005-06-20 13:45:57 +00002533 case Pin_FpCMov:
2534 addHRegUse(u, HRmModify, i->Pin.FpCMov.dst);
cerion5b2325f2005-12-23 00:55:09 +00002535 addHRegUse(u, HRmRead, i->Pin.FpCMov.src);
cerion094d1392005-06-20 13:45:57 +00002536 return;
2537 case Pin_FpLdFPSCR:
2538 addHRegUse(u, HRmRead, i->Pin.FpLdFPSCR.src);
2539 return;
2540 case Pin_FpCmp:
2541 addHRegUse(u, HRmWrite, i->Pin.FpCmp.dst);
cerion5b2325f2005-12-23 00:55:09 +00002542 addHRegUse(u, HRmRead, i->Pin.FpCmp.srcL);
2543 addHRegUse(u, HRmRead, i->Pin.FpCmp.srcR);
cerion094d1392005-06-20 13:45:57 +00002544 return;
cerion7f000af2005-02-22 20:36:49 +00002545
2546 case Pin_RdWrLR:
2547 addHRegUse(u, (i->Pin.RdWrLR.wrLR ? HRmRead : HRmWrite),
2548 i->Pin.RdWrLR.gpr);
2549 return;
2550
cerionc3d8bdc2005-06-28 18:06:23 +00002551 case Pin_AvLdSt:
2552 addHRegUse(u, (i->Pin.AvLdSt.isLoad ? HRmWrite : HRmRead),
2553 i->Pin.AvLdSt.reg);
2554 if (i->Pin.AvLdSt.addr->tag == Pam_IR)
cerionf0de28c2005-12-13 20:21:11 +00002555 addHRegUse(u, HRmWrite, hregPPC_GPR30(mode64));
cerion5b2325f2005-12-23 00:55:09 +00002556 addRegUsage_PPCAMode(u, i->Pin.AvLdSt.addr);
cerionc3d8bdc2005-06-28 18:06:23 +00002557 return;
2558 case Pin_AvUnary:
2559 addHRegUse(u, HRmWrite, i->Pin.AvUnary.dst);
2560 addHRegUse(u, HRmRead, i->Pin.AvUnary.src);
2561 return;
2562 case Pin_AvBinary:
sewardjdc1f9132005-10-22 12:49:49 +00002563 if (i->Pin.AvBinary.op == Pav_XOR
florian79efdc62013-02-11 00:47:35 +00002564 && sameHReg(i->Pin.AvBinary.dst, i->Pin.AvBinary.srcL)
2565 && sameHReg(i->Pin.AvBinary.dst, i->Pin.AvBinary.srcR)) {
sewardjdc1f9132005-10-22 12:49:49 +00002566 /* reg-alloc needs to understand 'xor r,r,r' as a write of r */
2567 /* (as opposed to a rite of passage :-) */
2568 addHRegUse(u, HRmWrite, i->Pin.AvBinary.dst);
2569 } else {
2570 addHRegUse(u, HRmWrite, i->Pin.AvBinary.dst);
2571 addHRegUse(u, HRmRead, i->Pin.AvBinary.srcL);
2572 addHRegUse(u, HRmRead, i->Pin.AvBinary.srcR);
2573 }
cerionc3d8bdc2005-06-28 18:06:23 +00002574 return;
Elliott Hughesa0664b92017-04-18 17:46:52 -07002575 case Pin_AvBinaryInt:
2576 addHRegUse(u, HRmWrite, i->Pin.AvBinaryInt.dst);
2577 addHRegUse(u, HRmRead, i->Pin.AvBinaryInt.src);
2578 return;
cerion6b6f59e2005-06-28 20:59:18 +00002579 case Pin_AvBin8x16:
2580 addHRegUse(u, HRmWrite, i->Pin.AvBin8x16.dst);
2581 addHRegUse(u, HRmRead, i->Pin.AvBin8x16.srcL);
2582 addHRegUse(u, HRmRead, i->Pin.AvBin8x16.srcR);
2583 return;
2584 case Pin_AvBin16x8:
2585 addHRegUse(u, HRmWrite, i->Pin.AvBin16x8.dst);
2586 addHRegUse(u, HRmRead, i->Pin.AvBin16x8.srcL);
2587 addHRegUse(u, HRmRead, i->Pin.AvBin16x8.srcR);
2588 return;
2589 case Pin_AvBin32x4:
2590 addHRegUse(u, HRmWrite, i->Pin.AvBin32x4.dst);
2591 addHRegUse(u, HRmRead, i->Pin.AvBin32x4.srcL);
2592 addHRegUse(u, HRmRead, i->Pin.AvBin32x4.srcR);
cerion6b6f59e2005-06-28 20:59:18 +00002593 return;
carll0c74bb52013-08-12 18:01:40 +00002594 case Pin_AvBin64x2:
2595 addHRegUse(u, HRmWrite, i->Pin.AvBin64x2.dst);
2596 addHRegUse(u, HRmRead, i->Pin.AvBin64x2.srcL);
2597 addHRegUse(u, HRmRead, i->Pin.AvBin64x2.srcR);
2598 return;
cerion6b6f59e2005-06-28 20:59:18 +00002599 case Pin_AvBin32Fx4:
2600 addHRegUse(u, HRmWrite, i->Pin.AvBin32Fx4.dst);
2601 addHRegUse(u, HRmRead, i->Pin.AvBin32Fx4.srcL);
2602 addHRegUse(u, HRmRead, i->Pin.AvBin32Fx4.srcR);
cerion8ea0d3e2005-11-14 00:44:47 +00002603 if (i->Pin.AvBin32Fx4.op == Pavfp_MULF)
sewardja5b50222015-03-26 07:18:32 +00002604 addHRegUse(u, HRmWrite, hregPPC_VR29(mode64));
cerion8ea0d3e2005-11-14 00:44:47 +00002605 return;
2606 case Pin_AvUn32Fx4:
2607 addHRegUse(u, HRmWrite, i->Pin.AvUn32Fx4.dst);
2608 addHRegUse(u, HRmRead, i->Pin.AvUn32Fx4.src);
cerion6b6f59e2005-06-28 20:59:18 +00002609 return;
cerionc3d8bdc2005-06-28 18:06:23 +00002610 case Pin_AvPerm:
2611 addHRegUse(u, HRmWrite, i->Pin.AvPerm.dst);
cerionc3d8bdc2005-06-28 18:06:23 +00002612 addHRegUse(u, HRmRead, i->Pin.AvPerm.srcL);
2613 addHRegUse(u, HRmRead, i->Pin.AvPerm.srcR);
cerion92d9d872005-09-15 21:58:50 +00002614 addHRegUse(u, HRmRead, i->Pin.AvPerm.ctl);
cerionc3d8bdc2005-06-28 18:06:23 +00002615 return;
2616 case Pin_AvSel:
2617 addHRegUse(u, HRmWrite, i->Pin.AvSel.dst);
2618 addHRegUse(u, HRmRead, i->Pin.AvSel.ctl);
2619 addHRegUse(u, HRmRead, i->Pin.AvSel.srcL);
2620 addHRegUse(u, HRmRead, i->Pin.AvSel.srcR);
2621 return;
carll9877fe52014-10-07 17:49:14 +00002622 case Pin_AvSh:
2623 addHRegUse(u, HRmWrite, i->Pin.AvSh.dst);
2624 if (i->Pin.AvSh.addr->tag == Pam_IR)
2625 addHRegUse(u, HRmWrite, hregPPC_GPR30(mode64));
2626 addRegUsage_PPCAMode(u, i->Pin.AvSh.addr);
2627 return;
cerionc3d8bdc2005-06-28 18:06:23 +00002628 case Pin_AvShlDbl:
2629 addHRegUse(u, HRmWrite, i->Pin.AvShlDbl.dst);
2630 addHRegUse(u, HRmRead, i->Pin.AvShlDbl.srcL);
2631 addHRegUse(u, HRmRead, i->Pin.AvShlDbl.srcR);
2632 return;
2633 case Pin_AvSplat:
cerion5b2325f2005-12-23 00:55:09 +00002634 addHRegUse(u, HRmWrite, i->Pin.AvSplat.dst);
2635 addRegUsage_PPCVI5s(u, i->Pin.AvSplat.src);
cerionc3d8bdc2005-06-28 18:06:23 +00002636 return;
cerion6b6f59e2005-06-28 20:59:18 +00002637 case Pin_AvCMov:
2638 addHRegUse(u, HRmModify, i->Pin.AvCMov.dst);
cerion5b2325f2005-12-23 00:55:09 +00002639 addHRegUse(u, HRmRead, i->Pin.AvCMov.src);
cerion6b6f59e2005-06-28 20:59:18 +00002640 return;
cerionc3d8bdc2005-06-28 18:06:23 +00002641 case Pin_AvLdVSCR:
2642 addHRegUse(u, HRmRead, i->Pin.AvLdVSCR.src);
2643 return;
carll7deaf952013-10-15 18:11:20 +00002644 case Pin_AvCipherV128Unary:
2645 addHRegUse(u, HRmWrite, i->Pin.AvCipherV128Unary.dst);
2646 addHRegUse(u, HRmRead, i->Pin.AvCipherV128Unary.src);
2647 return;
2648 case Pin_AvCipherV128Binary:
2649 addHRegUse(u, HRmWrite, i->Pin.AvCipherV128Binary.dst);
2650 addHRegUse(u, HRmRead, i->Pin.AvCipherV128Binary.srcL);
2651 addHRegUse(u, HRmRead, i->Pin.AvCipherV128Binary.srcR);
2652 return;
2653 case Pin_AvHashV128Binary:
2654 addHRegUse(u, HRmWrite, i->Pin.AvHashV128Binary.dst);
2655 addHRegUse(u, HRmRead, i->Pin.AvHashV128Binary.src);
2656 addRegUsage_PPCRI(u, i->Pin.AvHashV128Binary.s_field);
2657 return;
Elliott Hughesa0664b92017-04-18 17:46:52 -07002658 case Pin_AvBCDV128Binary:
2659 addHRegUse(u, HRmWrite, i->Pin.AvBCDV128Binary.dst);
2660 addHRegUse(u, HRmRead, i->Pin.AvBCDV128Binary.src1);
2661 addHRegUse(u, HRmRead, i->Pin.AvBCDV128Binary.src2);
carll7deaf952013-10-15 18:11:20 +00002662 return;
sewardjc6bbd472012-04-02 10:20:48 +00002663 case Pin_Dfp64Unary:
2664 addHRegUse(u, HRmWrite, i->Pin.Dfp64Unary.dst);
2665 addHRegUse(u, HRmRead, i->Pin.Dfp64Unary.src);
2666 return;
2667 case Pin_Dfp64Binary:
2668 addHRegUse(u, HRmWrite, i->Pin.Dfp64Binary.dst);
2669 addHRegUse(u, HRmRead, i->Pin.Dfp64Binary.srcL);
2670 addHRegUse(u, HRmRead, i->Pin.Dfp64Binary.srcR);
2671 return;
sewardj26217b02012-04-12 17:19:48 +00002672 case Pin_DfpShift:
2673 addRegUsage_PPCRI(u, i->Pin.DfpShift.shift);
2674 addHRegUse(u, HRmWrite, i->Pin.DfpShift.src);
2675 addHRegUse(u, HRmWrite, i->Pin.DfpShift.dst);
2676 return;
2677 case Pin_Dfp128Unary:
2678 addHRegUse(u, HRmWrite, i->Pin.Dfp128Unary.dst_hi);
2679 addHRegUse(u, HRmWrite, i->Pin.Dfp128Unary.dst_lo);
2680 addHRegUse(u, HRmRead, i->Pin.Dfp128Unary.src_hi);
2681 addHRegUse(u, HRmRead, i->Pin.Dfp128Unary.src_lo);
2682 return;
sewardjc6bbd472012-04-02 10:20:48 +00002683 case Pin_Dfp128Binary:
2684 addHRegUse(u, HRmWrite, i->Pin.Dfp128Binary.dst_hi);
2685 addHRegUse(u, HRmWrite, i->Pin.Dfp128Binary.dst_lo);
2686 addHRegUse(u, HRmRead, i->Pin.Dfp128Binary.srcR_hi);
2687 addHRegUse(u, HRmRead, i->Pin.Dfp128Binary.srcR_lo);
2688 return;
sewardjcdc376d2012-04-23 11:21:12 +00002689 case Pin_DfpRound:
2690 addHRegUse(u, HRmWrite, i->Pin.DfpRound.dst);
2691 addHRegUse(u, HRmRead, i->Pin.DfpRound.src);
2692 return;
2693 case Pin_DfpRound128:
2694 addHRegUse(u, HRmWrite, i->Pin.DfpRound128.dst_hi);
2695 addHRegUse(u, HRmWrite, i->Pin.DfpRound128.dst_lo);
2696 addHRegUse(u, HRmRead, i->Pin.DfpRound128.src_hi);
2697 addHRegUse(u, HRmRead, i->Pin.DfpRound128.src_lo);
2698 return;
2699 case Pin_DfpQuantize:
2700 addRegUsage_PPCRI(u, i->Pin.DfpQuantize.rmc);
2701 addHRegUse(u, HRmWrite, i->Pin.DfpQuantize.dst);
2702 addHRegUse(u, HRmRead, i->Pin.DfpQuantize.srcL);
2703 addHRegUse(u, HRmRead, i->Pin.DfpQuantize.srcR);
2704 return;
2705 case Pin_DfpQuantize128:
2706 addHRegUse(u, HRmWrite, i->Pin.DfpQuantize128.dst_hi);
2707 addHRegUse(u, HRmWrite, i->Pin.DfpQuantize128.dst_lo);
2708 addHRegUse(u, HRmRead, i->Pin.DfpQuantize128.src_hi);
2709 addHRegUse(u, HRmRead, i->Pin.DfpQuantize128.src_lo);
2710 return;
sewardj26217b02012-04-12 17:19:48 +00002711 case Pin_DfpShift128:
2712 addRegUsage_PPCRI(u, i->Pin.DfpShift128.shift);
2713 addHRegUse(u, HRmWrite, i->Pin.DfpShift128.src_hi);
2714 addHRegUse(u, HRmWrite, i->Pin.DfpShift128.src_lo);
2715 addHRegUse(u, HRmWrite, i->Pin.DfpShift128.dst_hi);
2716 addHRegUse(u, HRmWrite, i->Pin.DfpShift128.dst_lo);
2717 return;
2718 case Pin_DfpD128toD64:
2719 addHRegUse(u, HRmWrite, i->Pin.DfpD128toD64.src_hi);
2720 addHRegUse(u, HRmWrite, i->Pin.DfpD128toD64.src_lo);
2721 addHRegUse(u, HRmWrite, i->Pin.DfpD128toD64.dst);
2722 return;
2723 case Pin_DfpI64StoD128:
2724 addHRegUse(u, HRmWrite, i->Pin.DfpI64StoD128.src);
2725 addHRegUse(u, HRmWrite, i->Pin.DfpI64StoD128.dst_hi);
2726 addHRegUse(u, HRmWrite, i->Pin.DfpI64StoD128.dst_lo);
2727 return;
sewardjcdc376d2012-04-23 11:21:12 +00002728 case Pin_ExtractExpD128:
2729 addHRegUse(u, HRmWrite, i->Pin.ExtractExpD128.dst);
2730 addHRegUse(u, HRmRead, i->Pin.ExtractExpD128.src_hi);
2731 addHRegUse(u, HRmRead, i->Pin.ExtractExpD128.src_lo);
2732 return;
2733 case Pin_InsertExpD128:
2734 addHRegUse(u, HRmWrite, i->Pin.InsertExpD128.dst_hi);
2735 addHRegUse(u, HRmWrite, i->Pin.InsertExpD128.dst_lo);
2736 addHRegUse(u, HRmRead, i->Pin.InsertExpD128.srcL);
2737 addHRegUse(u, HRmRead, i->Pin.InsertExpD128.srcR_hi);
2738 addHRegUse(u, HRmRead, i->Pin.InsertExpD128.srcR_lo);
2739 return;
2740 case Pin_Dfp64Cmp:
2741 addHRegUse(u, HRmWrite, i->Pin.Dfp64Cmp.dst);
2742 addHRegUse(u, HRmRead, i->Pin.Dfp64Cmp.srcL);
2743 addHRegUse(u, HRmRead, i->Pin.Dfp64Cmp.srcR);
2744 return;
2745 case Pin_Dfp128Cmp:
2746 addHRegUse(u, HRmWrite, i->Pin.Dfp128Cmp.dst);
2747 addHRegUse(u, HRmRead, i->Pin.Dfp128Cmp.srcL_hi);
2748 addHRegUse(u, HRmRead, i->Pin.Dfp128Cmp.srcL_lo);
2749 addHRegUse(u, HRmRead, i->Pin.Dfp128Cmp.srcR_hi);
2750 addHRegUse(u, HRmRead, i->Pin.Dfp128Cmp.srcR_lo);
2751 return;
sewardj3dee8492012-04-20 00:13:28 +00002752 case Pin_EvCheck:
2753 /* We expect both amodes only to mention the GSP (r31), so this
2754 is in fact pointless, since GSP isn't allocatable, but
2755 anyway.. */
2756 addRegUsage_PPCAMode(u, i->Pin.EvCheck.amCounter);
2757 addRegUsage_PPCAMode(u, i->Pin.EvCheck.amFailAddr);
2758 addHRegUse(u, HRmWrite, hregPPC_GPR30(mode64)); /* also unavail to RA */
2759 return;
2760 case Pin_ProfInc:
2761 addHRegUse(u, HRmWrite, hregPPC_GPR29(mode64));
2762 addHRegUse(u, HRmWrite, hregPPC_GPR30(mode64));
2763 return;
cerionb85e8bb2005-02-16 08:54:33 +00002764 default:
cerion5b2325f2005-12-23 00:55:09 +00002765 ppPPCInstr(i, mode64);
2766 vpanic("getRegUsage_PPCInstr");
cerionbcf8c3e2005-02-04 16:17:07 +00002767 }
2768}
2769
cerioncd304492005-02-08 19:40:24 +00002770/* local helper */
cerion92b64362005-12-13 12:02:26 +00002771static void mapReg( HRegRemap* m, HReg* r )
cerioncd304492005-02-08 19:40:24 +00002772{
2773 *r = lookupHRegRemap(m, *r);
2774}
cerionbcf8c3e2005-02-04 16:17:07 +00002775
cerion5b2325f2005-12-23 00:55:09 +00002776void mapRegs_PPCInstr ( HRegRemap* m, PPCInstr* i, Bool mode64 )
cerionbcf8c3e2005-02-04 16:17:07 +00002777{
2778 switch (i->tag) {
cerionf0de28c2005-12-13 20:21:11 +00002779 case Pin_LI:
2780 mapReg(m, &i->Pin.LI.dst);
sewardjb51f0f42005-07-18 11:38:02 +00002781 return;
cerionf0de28c2005-12-13 20:21:11 +00002782 case Pin_Alu:
2783 mapReg(m, &i->Pin.Alu.dst);
2784 mapReg(m, &i->Pin.Alu.srcL);
cerion5b2325f2005-12-23 00:55:09 +00002785 mapRegs_PPCRH(m, i->Pin.Alu.srcR);
cerionb85e8bb2005-02-16 08:54:33 +00002786 return;
cerionbb01b7c2005-12-16 13:40:18 +00002787 case Pin_Shft:
2788 mapReg(m, &i->Pin.Shft.dst);
2789 mapReg(m, &i->Pin.Shft.srcL);
cerion5b2325f2005-12-23 00:55:09 +00002790 mapRegs_PPCRH(m, i->Pin.Shft.srcR);
cerionbb01b7c2005-12-16 13:40:18 +00002791 return;
cerion5b2325f2005-12-23 00:55:09 +00002792 case Pin_AddSubC:
2793 mapReg(m, &i->Pin.AddSubC.dst);
2794 mapReg(m, &i->Pin.AddSubC.srcL);
2795 mapReg(m, &i->Pin.AddSubC.srcR);
cerion4a49b032005-11-08 16:23:07 +00002796 return;
cerionf0de28c2005-12-13 20:21:11 +00002797 case Pin_Cmp:
2798 mapReg(m, &i->Pin.Cmp.srcL);
cerion5b2325f2005-12-23 00:55:09 +00002799 mapRegs_PPCRH(m, i->Pin.Cmp.srcR);
cerionb85e8bb2005-02-16 08:54:33 +00002800 return;
cerionf0de28c2005-12-13 20:21:11 +00002801 case Pin_Unary:
cerion5b2325f2005-12-23 00:55:09 +00002802 mapReg(m, &i->Pin.Unary.dst);
2803 mapReg(m, &i->Pin.Unary.src);
cerionb85e8bb2005-02-16 08:54:33 +00002804 return;
2805 case Pin_MulL:
2806 mapReg(m, &i->Pin.MulL.dst);
ceriona2f75882005-03-15 16:33:38 +00002807 mapReg(m, &i->Pin.MulL.srcL);
sewardjb51f0f42005-07-18 11:38:02 +00002808 mapReg(m, &i->Pin.MulL.srcR);
cerionb85e8bb2005-02-16 08:54:33 +00002809 return;
2810 case Pin_Div:
2811 mapReg(m, &i->Pin.Div.dst);
ceriona2f75882005-03-15 16:33:38 +00002812 mapReg(m, &i->Pin.Div.srcL);
2813 mapReg(m, &i->Pin.Div.srcR);
cerionb85e8bb2005-02-16 08:54:33 +00002814 return;
cerionb85e8bb2005-02-16 08:54:33 +00002815 case Pin_Call:
2816 return;
sewardj3dee8492012-04-20 00:13:28 +00002817 case Pin_XDirect:
2818 mapRegs_PPCAMode(m, i->Pin.XDirect.amCIA);
2819 return;
2820 case Pin_XIndir:
2821 mapReg(m, &i->Pin.XIndir.dstGA);
2822 mapRegs_PPCAMode(m, i->Pin.XIndir.amCIA);
2823 return;
2824 case Pin_XAssisted:
2825 mapReg(m, &i->Pin.XAssisted.dstGA);
2826 mapRegs_PPCAMode(m, i->Pin.XAssisted.amCIA);
cerionb85e8bb2005-02-16 08:54:33 +00002827 return;
cerionf0de28c2005-12-13 20:21:11 +00002828 case Pin_CMov:
cerion5b2325f2005-12-23 00:55:09 +00002829 mapRegs_PPCRI(m, i->Pin.CMov.src);
cerionf0de28c2005-12-13 20:21:11 +00002830 mapReg(m, &i->Pin.CMov.dst);
cerionb85e8bb2005-02-16 08:54:33 +00002831 return;
cerion7cf8e4e2005-02-16 16:08:17 +00002832 case Pin_Load:
cerion5b2325f2005-12-23 00:55:09 +00002833 mapRegs_PPCAMode(m, i->Pin.Load.src);
cerion7cf8e4e2005-02-16 16:08:17 +00002834 mapReg(m, &i->Pin.Load.dst);
cerionb85e8bb2005-02-16 08:54:33 +00002835 return;
sewardje9d8a262009-07-01 08:06:34 +00002836 case Pin_LoadL:
2837 mapReg(m, &i->Pin.LoadL.src);
2838 mapReg(m, &i->Pin.LoadL.dst);
2839 return;
cerionb85e8bb2005-02-16 08:54:33 +00002840 case Pin_Store:
2841 mapReg(m, &i->Pin.Store.src);
cerion5b2325f2005-12-23 00:55:09 +00002842 mapRegs_PPCAMode(m, i->Pin.Store.dst);
cerionb85e8bb2005-02-16 08:54:33 +00002843 return;
sewardje9d8a262009-07-01 08:06:34 +00002844 case Pin_StoreC:
2845 mapReg(m, &i->Pin.StoreC.src);
2846 mapReg(m, &i->Pin.StoreC.dst);
2847 return;
cerion5b2325f2005-12-23 00:55:09 +00002848 case Pin_Set:
2849 mapReg(m, &i->Pin.Set.dst);
cerionb85e8bb2005-02-16 08:54:33 +00002850 return;
sewardjb51f0f42005-07-18 11:38:02 +00002851 case Pin_MfCR:
2852 mapReg(m, &i->Pin.MfCR.dst);
2853 return;
cerionb85e8bb2005-02-16 08:54:33 +00002854 case Pin_MFence:
2855 return;
cerion094d1392005-06-20 13:45:57 +00002856 case Pin_FpUnary:
sewardjb51f0f42005-07-18 11:38:02 +00002857 mapReg(m, &i->Pin.FpUnary.dst);
2858 mapReg(m, &i->Pin.FpUnary.src);
2859 return;
2860 case Pin_FpBinary:
2861 mapReg(m, &i->Pin.FpBinary.dst);
2862 mapReg(m, &i->Pin.FpBinary.srcL);
2863 mapReg(m, &i->Pin.FpBinary.srcR);
2864 return;
Elliott Hughesa0664b92017-04-18 17:46:52 -07002865 case Pin_Fp128Unary:
2866 mapReg(m, &i->Pin.Fp128Unary.dst);
2867 mapReg(m, &i->Pin.Fp128Unary.src);
2868 return;
2869 case Pin_Fp128Binary:
2870 mapReg(m, &i->Pin.Fp128Binary.dst);
2871 mapReg(m, &i->Pin.Fp128Binary.srcL);
2872 mapReg(m, &i->Pin.Fp128Binary.srcR);
2873 return;
2874 case Pin_Fp128Trinary:
2875 mapReg(m, &i->Pin.Fp128Trinary.dst);
2876 mapReg(m, &i->Pin.Fp128Trinary.srcL);
2877 mapReg(m, &i->Pin.Fp128Trinary.srcR);
2878 return;
sewardj40c80262006-02-08 19:30:46 +00002879 case Pin_FpMulAcc:
2880 mapReg(m, &i->Pin.FpMulAcc.dst);
2881 mapReg(m, &i->Pin.FpMulAcc.srcML);
2882 mapReg(m, &i->Pin.FpMulAcc.srcMR);
2883 mapReg(m, &i->Pin.FpMulAcc.srcAcc);
2884 return;
sewardjb51f0f42005-07-18 11:38:02 +00002885 case Pin_FpLdSt:
2886 mapReg(m, &i->Pin.FpLdSt.reg);
cerion5b2325f2005-12-23 00:55:09 +00002887 mapRegs_PPCAMode(m, i->Pin.FpLdSt.addr);
sewardjb51f0f42005-07-18 11:38:02 +00002888 return;
sewardj92923de2006-01-25 21:29:48 +00002889 case Pin_FpSTFIW:
2890 mapReg(m, &i->Pin.FpSTFIW.addr);
2891 mapReg(m, &i->Pin.FpSTFIW.data);
sewardjb51f0f42005-07-18 11:38:02 +00002892 return;
sewardj92923de2006-01-25 21:29:48 +00002893 case Pin_FpRSP:
2894 mapReg(m, &i->Pin.FpRSP.dst);
2895 mapReg(m, &i->Pin.FpRSP.src);
sewardjb51f0f42005-07-18 11:38:02 +00002896 return;
sewardj92923de2006-01-25 21:29:48 +00002897 case Pin_FpCftI:
2898 mapReg(m, &i->Pin.FpCftI.dst);
2899 mapReg(m, &i->Pin.FpCftI.src);
cerion07b07a92005-12-22 14:32:35 +00002900 return;
sewardjb51f0f42005-07-18 11:38:02 +00002901 case Pin_FpCMov:
2902 mapReg(m, &i->Pin.FpCMov.dst);
2903 mapReg(m, &i->Pin.FpCMov.src);
2904 return;
2905 case Pin_FpLdFPSCR:
2906 mapReg(m, &i->Pin.FpLdFPSCR.src);
2907 return;
2908 case Pin_FpCmp:
2909 mapReg(m, &i->Pin.FpCmp.dst);
2910 mapReg(m, &i->Pin.FpCmp.srcL);
2911 mapReg(m, &i->Pin.FpCmp.srcR);
2912 return;
cerion7f000af2005-02-22 20:36:49 +00002913 case Pin_RdWrLR:
2914 mapReg(m, &i->Pin.RdWrLR.gpr);
2915 return;
cerionc3d8bdc2005-06-28 18:06:23 +00002916 case Pin_AvLdSt:
2917 mapReg(m, &i->Pin.AvLdSt.reg);
cerion5b2325f2005-12-23 00:55:09 +00002918 mapRegs_PPCAMode(m, i->Pin.AvLdSt.addr);
cerionc3d8bdc2005-06-28 18:06:23 +00002919 return;
2920 case Pin_AvUnary:
2921 mapReg(m, &i->Pin.AvUnary.dst);
2922 mapReg(m, &i->Pin.AvUnary.src);
2923 return;
2924 case Pin_AvBinary:
2925 mapReg(m, &i->Pin.AvBinary.dst);
2926 mapReg(m, &i->Pin.AvBinary.srcL);
2927 mapReg(m, &i->Pin.AvBinary.srcR);
2928 return;
Elliott Hughesa0664b92017-04-18 17:46:52 -07002929 case Pin_AvBinaryInt:
2930 mapReg(m, &i->Pin.AvBinaryInt.dst);
2931 mapReg(m, &i->Pin.AvBinaryInt.src);
2932 return;
cerion6b6f59e2005-06-28 20:59:18 +00002933 case Pin_AvBin8x16:
2934 mapReg(m, &i->Pin.AvBin8x16.dst);
2935 mapReg(m, &i->Pin.AvBin8x16.srcL);
2936 mapReg(m, &i->Pin.AvBin8x16.srcR);
2937 return;
2938 case Pin_AvBin16x8:
2939 mapReg(m, &i->Pin.AvBin16x8.dst);
2940 mapReg(m, &i->Pin.AvBin16x8.srcL);
2941 mapReg(m, &i->Pin.AvBin16x8.srcR);
2942 return;
2943 case Pin_AvBin32x4:
2944 mapReg(m, &i->Pin.AvBin32x4.dst);
2945 mapReg(m, &i->Pin.AvBin32x4.srcL);
2946 mapReg(m, &i->Pin.AvBin32x4.srcR);
2947 return;
carll0c74bb52013-08-12 18:01:40 +00002948 case Pin_AvBin64x2:
2949 mapReg(m, &i->Pin.AvBin64x2.dst);
2950 mapReg(m, &i->Pin.AvBin64x2.srcL);
2951 mapReg(m, &i->Pin.AvBin64x2.srcR);
2952 return;
cerion6b6f59e2005-06-28 20:59:18 +00002953 case Pin_AvBin32Fx4:
2954 mapReg(m, &i->Pin.AvBin32Fx4.dst);
2955 mapReg(m, &i->Pin.AvBin32Fx4.srcL);
2956 mapReg(m, &i->Pin.AvBin32Fx4.srcR);
2957 return;
cerion8ea0d3e2005-11-14 00:44:47 +00002958 case Pin_AvUn32Fx4:
2959 mapReg(m, &i->Pin.AvUn32Fx4.dst);
2960 mapReg(m, &i->Pin.AvUn32Fx4.src);
2961 return;
cerionc3d8bdc2005-06-28 18:06:23 +00002962 case Pin_AvPerm:
2963 mapReg(m, &i->Pin.AvPerm.dst);
2964 mapReg(m, &i->Pin.AvPerm.srcL);
2965 mapReg(m, &i->Pin.AvPerm.srcR);
2966 mapReg(m, &i->Pin.AvPerm.ctl);
2967 return;
2968 case Pin_AvSel:
2969 mapReg(m, &i->Pin.AvSel.dst);
2970 mapReg(m, &i->Pin.AvSel.srcL);
2971 mapReg(m, &i->Pin.AvSel.srcR);
2972 mapReg(m, &i->Pin.AvSel.ctl);
2973 return;
carll9877fe52014-10-07 17:49:14 +00002974 case Pin_AvSh:
2975 mapReg(m, &i->Pin.AvSh.dst);
2976 mapRegs_PPCAMode(m, i->Pin.AvSh.addr);
2977 return;
cerionc3d8bdc2005-06-28 18:06:23 +00002978 case Pin_AvShlDbl:
2979 mapReg(m, &i->Pin.AvShlDbl.dst);
2980 mapReg(m, &i->Pin.AvShlDbl.srcL);
2981 mapReg(m, &i->Pin.AvShlDbl.srcR);
2982 return;
2983 case Pin_AvSplat:
2984 mapReg(m, &i->Pin.AvSplat.dst);
cerion5b2325f2005-12-23 00:55:09 +00002985 mapRegs_PPCVI5s(m, i->Pin.AvSplat.src);
cerionc3d8bdc2005-06-28 18:06:23 +00002986 return;
cerion6b6f59e2005-06-28 20:59:18 +00002987 case Pin_AvCMov:
2988 mapReg(m, &i->Pin.AvCMov.dst);
2989 mapReg(m, &i->Pin.AvCMov.src);
2990 return;
cerionc3d8bdc2005-06-28 18:06:23 +00002991 case Pin_AvLdVSCR:
2992 mapReg(m, &i->Pin.AvLdVSCR.src);
2993 return;
carll7deaf952013-10-15 18:11:20 +00002994 case Pin_AvCipherV128Unary:
2995 mapReg(m, &i->Pin.AvCipherV128Unary.dst);
2996 mapReg(m, &i->Pin.AvCipherV128Unary.src);
2997 return;
2998 case Pin_AvCipherV128Binary:
2999 mapReg(m, &i->Pin.AvCipherV128Binary.dst);
3000 mapReg(m, &i->Pin.AvCipherV128Binary.srcL);
3001 mapReg(m, &i->Pin.AvCipherV128Binary.srcR);
3002 return;
3003 case Pin_AvHashV128Binary:
3004 mapRegs_PPCRI(m, i->Pin.AvHashV128Binary.s_field);
3005 mapReg(m, &i->Pin.AvHashV128Binary.dst);
3006 mapReg(m, &i->Pin.AvHashV128Binary.src);
3007 return;
Elliott Hughesa0664b92017-04-18 17:46:52 -07003008 case Pin_AvBCDV128Binary:
3009 mapReg(m, &i->Pin.AvBCDV128Binary.dst);
3010 mapReg(m, &i->Pin.AvBCDV128Binary.src1);
3011 mapReg(m, &i->Pin.AvBCDV128Binary.src2);
carll7deaf952013-10-15 18:11:20 +00003012 return;
sewardjc6bbd472012-04-02 10:20:48 +00003013 case Pin_Dfp64Unary:
3014 mapReg(m, &i->Pin.Dfp64Unary.dst);
3015 mapReg(m, &i->Pin.Dfp64Unary.src);
3016 return;
3017 case Pin_Dfp64Binary:
3018 mapReg(m, &i->Pin.Dfp64Binary.dst);
3019 mapReg(m, &i->Pin.Dfp64Binary.srcL);
3020 mapReg(m, &i->Pin.Dfp64Binary.srcR);
3021 return;
sewardj26217b02012-04-12 17:19:48 +00003022 case Pin_DfpShift:
3023 mapRegs_PPCRI(m, i->Pin.DfpShift.shift);
3024 mapReg(m, &i->Pin.DfpShift.src);
3025 mapReg(m, &i->Pin.DfpShift.dst);
3026 return;
3027 case Pin_Dfp128Unary:
3028 mapReg(m, &i->Pin.Dfp128Unary.dst_hi);
3029 mapReg(m, &i->Pin.Dfp128Unary.dst_lo);
3030 mapReg(m, &i->Pin.Dfp128Unary.src_hi);
3031 mapReg(m, &i->Pin.Dfp128Unary.src_lo);
3032 return;
sewardjc6bbd472012-04-02 10:20:48 +00003033 case Pin_Dfp128Binary:
3034 mapReg(m, &i->Pin.Dfp128Binary.dst_hi);
3035 mapReg(m, &i->Pin.Dfp128Binary.dst_lo);
3036 mapReg(m, &i->Pin.Dfp128Binary.srcR_hi);
3037 mapReg(m, &i->Pin.Dfp128Binary.srcR_lo);
3038 return;
sewardj26217b02012-04-12 17:19:48 +00003039 case Pin_DfpShift128:
3040 mapRegs_PPCRI(m, i->Pin.DfpShift128.shift);
3041 mapReg(m, &i->Pin.DfpShift128.src_hi);
3042 mapReg(m, &i->Pin.DfpShift128.src_lo);
3043 mapReg(m, &i->Pin.DfpShift128.dst_hi);
3044 mapReg(m, &i->Pin.DfpShift128.dst_lo);
3045 return;
sewardjcdc376d2012-04-23 11:21:12 +00003046 case Pin_DfpRound:
3047 mapReg(m, &i->Pin.DfpRound.dst);
3048 mapReg(m, &i->Pin.DfpRound.src);
3049 return;
3050 case Pin_DfpRound128:
3051 mapReg(m, &i->Pin.DfpRound128.dst_hi);
3052 mapReg(m, &i->Pin.DfpRound128.dst_lo);
3053 mapReg(m, &i->Pin.DfpRound128.src_hi);
3054 mapReg(m, &i->Pin.DfpRound128.src_lo);
3055 return;
3056 case Pin_DfpQuantize:
3057 mapRegs_PPCRI(m, i->Pin.DfpQuantize.rmc);
3058 mapReg(m, &i->Pin.DfpQuantize.dst);
3059 mapReg(m, &i->Pin.DfpQuantize.srcL);
3060 mapReg(m, &i->Pin.DfpQuantize.srcR);
3061 return;
3062 case Pin_DfpQuantize128:
3063 mapRegs_PPCRI(m, i->Pin.DfpQuantize128.rmc);
3064 mapReg(m, &i->Pin.DfpQuantize128.dst_hi);
3065 mapReg(m, &i->Pin.DfpQuantize128.dst_lo);
3066 mapReg(m, &i->Pin.DfpQuantize128.src_hi);
3067 mapReg(m, &i->Pin.DfpQuantize128.src_lo);
floriana7b0d102012-06-15 20:55:43 +00003068 return;
sewardj26217b02012-04-12 17:19:48 +00003069 case Pin_DfpD128toD64:
3070 mapReg(m, &i->Pin.DfpD128toD64.src_hi);
3071 mapReg(m, &i->Pin.DfpD128toD64.src_lo);
3072 mapReg(m, &i->Pin.DfpD128toD64.dst);
3073 return;
3074 case Pin_DfpI64StoD128:
3075 mapReg(m, &i->Pin.DfpI64StoD128.src);
3076 mapReg(m, &i->Pin.DfpI64StoD128.dst_hi);
3077 mapReg(m, &i->Pin.DfpI64StoD128.dst_lo);
3078 return;
sewardjcdc376d2012-04-23 11:21:12 +00003079 case Pin_ExtractExpD128:
3080 mapReg(m, &i->Pin.ExtractExpD128.dst);
3081 mapReg(m, &i->Pin.ExtractExpD128.src_hi);
3082 mapReg(m, &i->Pin.ExtractExpD128.src_lo);
3083 return;
3084 case Pin_InsertExpD128:
3085 mapReg(m, &i->Pin.InsertExpD128.dst_hi);
3086 mapReg(m, &i->Pin.InsertExpD128.dst_lo);
3087 mapReg(m, &i->Pin.InsertExpD128.srcL);
3088 mapReg(m, &i->Pin.InsertExpD128.srcR_hi);
3089 mapReg(m, &i->Pin.InsertExpD128.srcR_lo);
3090 return;
3091 case Pin_Dfp64Cmp:
3092 mapReg(m, &i->Pin.Dfp64Cmp.dst);
3093 mapReg(m, &i->Pin.Dfp64Cmp.srcL);
3094 mapReg(m, &i->Pin.Dfp64Cmp.srcR);
3095 return;
3096 case Pin_Dfp128Cmp:
3097 mapReg(m, &i->Pin.Dfp128Cmp.dst);
3098 mapReg(m, &i->Pin.Dfp128Cmp.srcL_hi);
3099 mapReg(m, &i->Pin.Dfp128Cmp.srcL_lo);
3100 mapReg(m, &i->Pin.Dfp128Cmp.srcR_hi);
3101 mapReg(m, &i->Pin.Dfp128Cmp.srcR_lo);
3102 return;
sewardj3dee8492012-04-20 00:13:28 +00003103 case Pin_EvCheck:
3104 /* We expect both amodes only to mention the GSP (r31), so this
3105 is in fact pointless, since GSP isn't allocatable, but
3106 anyway.. */
3107 mapRegs_PPCAMode(m, i->Pin.EvCheck.amCounter);
3108 mapRegs_PPCAMode(m, i->Pin.EvCheck.amFailAddr);
3109 return;
3110 case Pin_ProfInc:
3111 /* hardwires r29 and r30 -- nothing to modify. */
3112 return;
cerionb85e8bb2005-02-16 08:54:33 +00003113 default:
cerion5b2325f2005-12-23 00:55:09 +00003114 ppPPCInstr(i, mode64);
3115 vpanic("mapRegs_PPCInstr");
cerionbcf8c3e2005-02-04 16:17:07 +00003116 }
3117}
3118
3119/* Figure out if i represents a reg-reg move, and if so assign the
3120 source and destination to *src and *dst. If in doubt say No. Used
3121 by the register allocator to do move coalescing.
3122*/
floriand8c64e02014-10-08 08:54:44 +00003123Bool isMove_PPCInstr ( const PPCInstr* i, HReg* src, HReg* dst )
cerionbcf8c3e2005-02-04 16:17:07 +00003124{
cerionab9132d2005-02-15 15:46:59 +00003125 /* Moves between integer regs */
cerionf0de28c2005-12-13 20:21:11 +00003126 if (i->tag == Pin_Alu) {
cerionab9132d2005-02-15 15:46:59 +00003127 // or Rd,Rs,Rs == mr Rd,Rs
cerionf0de28c2005-12-13 20:21:11 +00003128 if (i->Pin.Alu.op != Palu_OR)
cerionab9132d2005-02-15 15:46:59 +00003129 return False;
cerionf0de28c2005-12-13 20:21:11 +00003130 if (i->Pin.Alu.srcR->tag != Prh_Reg)
cerionab9132d2005-02-15 15:46:59 +00003131 return False;
florian79efdc62013-02-11 00:47:35 +00003132 if (! sameHReg(i->Pin.Alu.srcR->Prh.Reg.reg, i->Pin.Alu.srcL))
cerionb85e8bb2005-02-16 08:54:33 +00003133 return False;
cerionf0de28c2005-12-13 20:21:11 +00003134 *src = i->Pin.Alu.srcL;
3135 *dst = i->Pin.Alu.dst;
cerionab9132d2005-02-15 15:46:59 +00003136 return True;
3137 }
cerion094d1392005-06-20 13:45:57 +00003138 /* Moves between FP regs */
3139 if (i->tag == Pin_FpUnary) {
3140 if (i->Pin.FpUnary.op != Pfp_MOV)
3141 return False;
3142 *src = i->Pin.FpUnary.src;
3143 *dst = i->Pin.FpUnary.dst;
3144 return True;
3145 }
cerionbcf8c3e2005-02-04 16:17:07 +00003146 return False;
3147}
3148
3149
cerion75949202005-12-24 13:14:11 +00003150/* Generate ppc spill/reload instructions under the direction of the
cerionbcf8c3e2005-02-04 16:17:07 +00003151 register allocator. Note it's critical these don't write the
3152 condition codes. */
sewardj2a0cc852010-01-02 13:23:54 +00003153
3154void genSpill_PPC ( /*OUT*/HInstr** i1, /*OUT*/HInstr** i2,
3155 HReg rreg, Int offsetB, Bool mode64 )
cerione13bb312005-02-10 19:51:03 +00003156{
cerion5b2325f2005-12-23 00:55:09 +00003157 PPCAMode* am;
cerione13bb312005-02-10 19:51:03 +00003158 vassert(!hregIsVirtual(rreg));
sewardj2a0cc852010-01-02 13:23:54 +00003159 *i1 = *i2 = NULL;
cerion5b2325f2005-12-23 00:55:09 +00003160 am = PPCAMode_IR( offsetB, GuestStatePtr(mode64) );
cerione13bb312005-02-10 19:51:03 +00003161 switch (hregClass(rreg)) {
sewardj2a0cc852010-01-02 13:23:54 +00003162 case HRcInt64:
3163 vassert(mode64);
3164 *i1 = PPCInstr_Store( 8, am, rreg, mode64 );
3165 return;
3166 case HRcInt32:
3167 vassert(!mode64);
3168 *i1 = PPCInstr_Store( 4, am, rreg, mode64 );
3169 return;
3170 case HRcFlt64:
3171 *i1 = PPCInstr_FpLdSt ( False/*store*/, 8, rreg, am );
3172 return;
3173 case HRcVec128:
3174 // XXX: GPR30 used as spill register to kludge AltiVec
3175 // AMode_IR
3176 *i1 = PPCInstr_AvLdSt ( False/*store*/, 16, rreg, am );
3177 return;
3178 default:
3179 ppHRegClass(hregClass(rreg));
3180 vpanic("genSpill_PPC: unimplemented regclass");
cerione13bb312005-02-10 19:51:03 +00003181 }
cerionbcf8c3e2005-02-04 16:17:07 +00003182}
3183
sewardj2a0cc852010-01-02 13:23:54 +00003184void genReload_PPC ( /*OUT*/HInstr** i1, /*OUT*/HInstr** i2,
3185 HReg rreg, Int offsetB, Bool mode64 )
cerione13bb312005-02-10 19:51:03 +00003186{
cerion5b2325f2005-12-23 00:55:09 +00003187 PPCAMode* am;
cerione13bb312005-02-10 19:51:03 +00003188 vassert(!hregIsVirtual(rreg));
sewardj2a0cc852010-01-02 13:23:54 +00003189 *i1 = *i2 = NULL;
cerion5b2325f2005-12-23 00:55:09 +00003190 am = PPCAMode_IR( offsetB, GuestStatePtr(mode64) );
cerione13bb312005-02-10 19:51:03 +00003191 switch (hregClass(rreg)) {
sewardj2a0cc852010-01-02 13:23:54 +00003192 case HRcInt64:
3193 vassert(mode64);
3194 *i1 = PPCInstr_Load( 8, rreg, am, mode64 );
3195 return;
3196 case HRcInt32:
3197 vassert(!mode64);
3198 *i1 = PPCInstr_Load( 4, rreg, am, mode64 );
3199 return;
3200 case HRcFlt64:
3201 *i1 = PPCInstr_FpLdSt ( True/*load*/, 8, rreg, am );
3202 return;
3203 case HRcVec128:
3204 // XXX: GPR30 used as spill register to kludge AltiVec AMode_IR
3205 *i1 = PPCInstr_AvLdSt ( True/*load*/, 16, rreg, am );
3206 return;
3207 default:
3208 ppHRegClass(hregClass(rreg));
3209 vpanic("genReload_PPC: unimplemented regclass");
cerione13bb312005-02-10 19:51:03 +00003210 }
cerionbcf8c3e2005-02-04 16:17:07 +00003211}
3212
3213
cerion75949202005-12-24 13:14:11 +00003214/* --------- The ppc assembler (bleh.) --------- */
cerioncd304492005-02-08 19:40:24 +00003215
sewardja5b50222015-03-26 07:18:32 +00003216inline static UInt iregEnc ( HReg r, Bool mode64 )
cerioncd304492005-02-08 19:40:24 +00003217{
3218 UInt n;
sewardja5b50222015-03-26 07:18:32 +00003219 vassert(hregClass(r) == (mode64 ? HRcInt64 : HRcInt32));
cerioncd304492005-02-08 19:40:24 +00003220 vassert(!hregIsVirtual(r));
sewardja5b50222015-03-26 07:18:32 +00003221 n = hregEncoding(r);
cerioncd304492005-02-08 19:40:24 +00003222 vassert(n <= 32);
3223 return n;
3224}
cerioncd304492005-02-08 19:40:24 +00003225
sewardja5b50222015-03-26 07:18:32 +00003226inline static UInt fregEnc ( HReg fr )
cerion094d1392005-06-20 13:45:57 +00003227{
3228 UInt n;
3229 vassert(hregClass(fr) == HRcFlt64);
3230 vassert(!hregIsVirtual(fr));
sewardja5b50222015-03-26 07:18:32 +00003231 n = hregEncoding(fr);
cerion094d1392005-06-20 13:45:57 +00003232 vassert(n <= 32);
3233 return n;
3234}
cerioncd304492005-02-08 19:40:24 +00003235
sewardja5b50222015-03-26 07:18:32 +00003236inline static UInt vregEnc ( HReg v )
cerionc3d8bdc2005-06-28 18:06:23 +00003237{
3238 UInt n;
3239 vassert(hregClass(v) == HRcVec128);
3240 vassert(!hregIsVirtual(v));
sewardja5b50222015-03-26 07:18:32 +00003241 n = hregEncoding(v);
cerionc3d8bdc2005-06-28 18:06:23 +00003242 vassert(n <= 32);
3243 return n;
3244}
3245
carll1f5fe1f2014-08-07 23:25:23 +00003246/* Emit an instruction ppc-endianly */
3247static UChar* emit32 ( UChar* p, UInt w32, VexEndness endness_host )
ceriond5e38382005-02-11 13:38:15 +00003248{
carll1f5fe1f2014-08-07 23:25:23 +00003249 if (endness_host == VexEndnessBE) {
3250 *p++ = toUChar((w32 >> 24) & 0x000000FF);
3251 *p++ = toUChar((w32 >> 16) & 0x000000FF);
3252 *p++ = toUChar((w32 >> 8) & 0x000000FF);
3253 *p++ = toUChar((w32) & 0x000000FF);
3254 } else {
3255 *p++ = toUChar((w32) & 0x000000FF);
3256 *p++ = toUChar((w32 >> 8) & 0x000000FF);
3257 *p++ = toUChar((w32 >> 16) & 0x000000FF);
3258 *p++ = toUChar((w32 >> 24) & 0x000000FF);
3259 }
ceriond5e38382005-02-11 13:38:15 +00003260 return p;
3261}
cerioncd304492005-02-08 19:40:24 +00003262
carll1f5fe1f2014-08-07 23:25:23 +00003263/* Fetch an instruction ppc-endianly */
3264static UInt fetch32 ( UChar* p, VexEndness endness_host )
sewardj3dee8492012-04-20 00:13:28 +00003265{
3266 UInt w32 = 0;
carll1f5fe1f2014-08-07 23:25:23 +00003267 if (endness_host == VexEndnessBE) {
3268 w32 |= ((0xFF & (UInt)p[0]) << 24);
3269 w32 |= ((0xFF & (UInt)p[1]) << 16);
3270 w32 |= ((0xFF & (UInt)p[2]) << 8);
3271 w32 |= ((0xFF & (UInt)p[3]) << 0);
3272 } else {
3273 w32 |= ((0xFF & (UInt)p[3]) << 24);
3274 w32 |= ((0xFF & (UInt)p[2]) << 16);
3275 w32 |= ((0xFF & (UInt)p[1]) << 8);
3276 w32 |= ((0xFF & (UInt)p[0]) << 0);
3277 }
sewardj3dee8492012-04-20 00:13:28 +00003278 return w32;
3279}
3280
cerion75949202005-12-24 13:14:11 +00003281/* The following mkForm[...] functions refer to ppc instruction forms
cerion094d1392005-06-20 13:45:57 +00003282 as per PPC32 p576
3283 */
cerioned623db2005-06-20 12:42:04 +00003284
cerion5b2325f2005-12-23 00:55:09 +00003285static UChar* mkFormD ( UChar* p, UInt opc1,
carll1f5fe1f2014-08-07 23:25:23 +00003286 UInt r1, UInt r2, UInt imm, VexEndness endness_host )
ceriond5e38382005-02-11 13:38:15 +00003287{
sewardj9a036bf2005-03-14 18:19:08 +00003288 UInt theInstr;
ceriona2f75882005-03-15 16:33:38 +00003289 vassert(opc1 < 0x40);
cerionf0de28c2005-12-13 20:21:11 +00003290 vassert(r1 < 0x20);
3291 vassert(r2 < 0x20);
cerion35663a72005-03-01 09:11:49 +00003292 imm = imm & 0xFFFF;
ceriona2f75882005-03-15 16:33:38 +00003293 theInstr = ((opc1<<26) | (r1<<21) | (r2<<16) | (imm));
carll1f5fe1f2014-08-07 23:25:23 +00003294 return emit32(p, theInstr, endness_host);
ceriond5e38382005-02-11 13:38:15 +00003295}
3296
cerionf0de28c2005-12-13 20:21:11 +00003297static UChar* mkFormMD ( UChar* p, UInt opc1, UInt r1, UInt r2,
carll1f5fe1f2014-08-07 23:25:23 +00003298 UInt imm1, UInt imm2, UInt opc2,
3299 VexEndness endness_host )
cerionf0de28c2005-12-13 20:21:11 +00003300{
3301 UInt theInstr;
3302 vassert(opc1 < 0x40);
3303 vassert(r1 < 0x20);
3304 vassert(r2 < 0x20);
3305 vassert(imm1 < 0x40);
3306 vassert(imm2 < 0x40);
3307 vassert(opc2 < 0x08);
3308 imm2 = ((imm2 & 0x1F) << 1) | (imm2 >> 5);
3309 theInstr = ((opc1<<26) | (r1<<21) | (r2<<16) |
cerion5b2325f2005-12-23 00:55:09 +00003310 ((imm1 & 0x1F)<<11) | (imm2<<5) |
3311 (opc2<<2) | ((imm1 >> 5)<<1));
carll1f5fe1f2014-08-07 23:25:23 +00003312 return emit32(p, theInstr, endness_host);
cerionf0de28c2005-12-13 20:21:11 +00003313}
3314
ceriona2f75882005-03-15 16:33:38 +00003315static UChar* mkFormX ( UChar* p, UInt opc1, UInt r1, UInt r2,
carll1f5fe1f2014-08-07 23:25:23 +00003316 UInt r3, UInt opc2, UInt b0, VexEndness endness_host )
ceriond5e38382005-02-11 13:38:15 +00003317{
sewardj9a036bf2005-03-14 18:19:08 +00003318 UInt theInstr;
ceriona2f75882005-03-15 16:33:38 +00003319 vassert(opc1 < 0x40);
cerionf0de28c2005-12-13 20:21:11 +00003320 vassert(r1 < 0x20);
3321 vassert(r2 < 0x20);
3322 vassert(r3 < 0x20);
ceriona2f75882005-03-15 16:33:38 +00003323 vassert(opc2 < 0x400);
cerionf0de28c2005-12-13 20:21:11 +00003324 vassert(b0 < 0x2);
cerion5b2325f2005-12-23 00:55:09 +00003325 theInstr = ((opc1<<26) | (r1<<21) | (r2<<16) |
3326 (r3<<11) | (opc2<<1) | (b0));
carll1f5fe1f2014-08-07 23:25:23 +00003327 return emit32(p, theInstr, endness_host);
ceriond5e38382005-02-11 13:38:15 +00003328}
3329
ceriona2f75882005-03-15 16:33:38 +00003330static UChar* mkFormXO ( UChar* p, UInt opc1, UInt r1, UInt r2,
carll1f5fe1f2014-08-07 23:25:23 +00003331 UInt r3, UInt b10, UInt opc2, UInt b0,
3332 VexEndness endness_host )
cerionab9132d2005-02-15 15:46:59 +00003333{
sewardj9a036bf2005-03-14 18:19:08 +00003334 UInt theInstr;
ceriona2f75882005-03-15 16:33:38 +00003335 vassert(opc1 < 0x40);
cerionf0de28c2005-12-13 20:21:11 +00003336 vassert(r1 < 0x20);
3337 vassert(r2 < 0x20);
3338 vassert(r3 < 0x20);
3339 vassert(b10 < 0x2);
ceriona2f75882005-03-15 16:33:38 +00003340 vassert(opc2 < 0x200);
cerionf0de28c2005-12-13 20:21:11 +00003341 vassert(b0 < 0x2);
ceriona2f75882005-03-15 16:33:38 +00003342 theInstr = ((opc1<<26) | (r1<<21) | (r2<<16) |
3343 (r3<<11) | (b10 << 10) | (opc2<<1) | (b0));
carll1f5fe1f2014-08-07 23:25:23 +00003344 return emit32(p, theInstr, endness_host);
cerionab9132d2005-02-15 15:46:59 +00003345}
ceriond5e38382005-02-11 13:38:15 +00003346
ceriona2f75882005-03-15 16:33:38 +00003347static UChar* mkFormXL ( UChar* p, UInt opc1, UInt f1, UInt f2,
carll1f5fe1f2014-08-07 23:25:23 +00003348 UInt f3, UInt opc2, UInt b0, VexEndness endness_host )
cerion33aa6da2005-02-16 10:25:26 +00003349{
sewardj9a036bf2005-03-14 18:19:08 +00003350 UInt theInstr;
ceriona2f75882005-03-15 16:33:38 +00003351 vassert(opc1 < 0x40);
cerionf0de28c2005-12-13 20:21:11 +00003352 vassert(f1 < 0x20);
3353 vassert(f2 < 0x20);
3354 vassert(f3 < 0x20);
ceriona2f75882005-03-15 16:33:38 +00003355 vassert(opc2 < 0x400);
cerionf0de28c2005-12-13 20:21:11 +00003356 vassert(b0 < 0x2);
cerion5b2325f2005-12-23 00:55:09 +00003357 theInstr = ((opc1<<26) | (f1<<21) | (f2<<16) |
3358 (f3<<11) | (opc2<<1) | (b0));
carll1f5fe1f2014-08-07 23:25:23 +00003359 return emit32(p, theInstr, endness_host);
cerion33aa6da2005-02-16 10:25:26 +00003360}
3361
3362// Note: for split field ops, give mnemonic arg
carll1f5fe1f2014-08-07 23:25:23 +00003363static UChar* mkFormXFX ( UChar* p, UInt r1, UInt f2, UInt opc2,
3364 VexEndness endness_host )
cerion33aa6da2005-02-16 10:25:26 +00003365{
sewardj9a036bf2005-03-14 18:19:08 +00003366 UInt theInstr;
cerionf0de28c2005-12-13 20:21:11 +00003367 vassert(r1 < 0x20);
3368 vassert(f2 < 0x20);
ceriona2f75882005-03-15 16:33:38 +00003369 vassert(opc2 < 0x400);
3370 switch (opc2) {
cerion33aa6da2005-02-16 10:25:26 +00003371 case 144: // mtcrf
3372 vassert(f2 < 0x100);
3373 f2 = f2 << 1;
3374 break;
3375 case 339: // mfspr
3376 case 371: // mftb
3377 case 467: // mtspr
3378 vassert(f2 < 0x400);
cerion5b2325f2005-12-23 00:55:09 +00003379 // re-arrange split field
3380 f2 = ((f2>>5) & 0x1F) | ((f2 & 0x1F)<<5);
cerion33aa6da2005-02-16 10:25:26 +00003381 break;
cerion5b2325f2005-12-23 00:55:09 +00003382 default: vpanic("mkFormXFX(ppch)");
cerion33aa6da2005-02-16 10:25:26 +00003383 }
ceriona2f75882005-03-15 16:33:38 +00003384 theInstr = ((31<<26) | (r1<<21) | (f2<<11) | (opc2<<1));
carll1f5fe1f2014-08-07 23:25:23 +00003385 return emit32(p, theInstr, endness_host);
cerion33aa6da2005-02-16 10:25:26 +00003386}
3387
cerion094d1392005-06-20 13:45:57 +00003388// Only used by mtfsf
carll1f5fe1f2014-08-07 23:25:23 +00003389static UChar* mkFormXFL ( UChar* p, UInt FM, UInt freg, UInt dfp_rm,
3390 VexEndness endness_host )
cerion094d1392005-06-20 13:45:57 +00003391{
3392 UInt theInstr;
3393 vassert(FM < 0x100);
3394 vassert(freg < 0x20);
sewardjc6bbd472012-04-02 10:20:48 +00003395 theInstr = ((63<<26) | (FM<<17) | (dfp_rm<<16) | (freg<<11) | (711<<1));
carll1f5fe1f2014-08-07 23:25:23 +00003396 return emit32(p, theInstr, endness_host);
cerion094d1392005-06-20 13:45:57 +00003397}
3398
cerionf0de28c2005-12-13 20:21:11 +00003399static UChar* mkFormXS ( UChar* p, UInt opc1, UInt r1, UInt r2,
carll1f5fe1f2014-08-07 23:25:23 +00003400 UInt imm, UInt opc2, UInt b0,
3401 VexEndness endness_host )
cerionf0de28c2005-12-13 20:21:11 +00003402{
3403 UInt theInstr;
3404 vassert(opc1 < 0x40);
3405 vassert(r1 < 0x20);
3406 vassert(r2 < 0x20);
3407 vassert(imm < 0x40);
3408 vassert(opc2 < 0x400);
3409 vassert(b0 < 0x2);
3410 theInstr = ((opc1<<26) | (r1<<21) | (r2<<16) |
3411 ((imm & 0x1F)<<11) | (opc2<<2) | ((imm>>5)<<1) | (b0));
carll1f5fe1f2014-08-07 23:25:23 +00003412 return emit32(p, theInstr, endness_host);
cerionf0de28c2005-12-13 20:21:11 +00003413}
3414
3415
cerion33aa6da2005-02-16 10:25:26 +00003416#if 0
3417// 'b'
carll1f5fe1f2014-08-07 23:25:23 +00003418static UChar* mkFormI ( UChar* p, UInt LI, UInt AA, UInt LK,
3419 VexEndness endness_host )
cerion33aa6da2005-02-16 10:25:26 +00003420{
sewardj9a036bf2005-03-14 18:19:08 +00003421 UInt theInstr;
cerion33aa6da2005-02-16 10:25:26 +00003422 vassert(LI < 0x1000000);
3423 vassert(AA < 0x2);
3424 vassert(LK < 0x2);
sewardj9a036bf2005-03-14 18:19:08 +00003425 theInstr = ((18<<26) | (LI<<2) | (AA<<1) | (LK));
carll1f5fe1f2014-08-07 23:25:23 +00003426 return emit32(p, theInstr, endness_host);
cerion33aa6da2005-02-16 10:25:26 +00003427}
3428#endif
3429
3430// 'bc'
3431static UChar* mkFormB ( UChar* p, UInt BO, UInt BI,
carll1f5fe1f2014-08-07 23:25:23 +00003432 UInt BD, UInt AA, UInt LK, VexEndness endness_host )
cerion33aa6da2005-02-16 10:25:26 +00003433{
sewardj9a036bf2005-03-14 18:19:08 +00003434 UInt theInstr;
cerion33aa6da2005-02-16 10:25:26 +00003435 vassert(BO < 0x20);
3436 vassert(BI < 0x20);
3437 vassert(BD < 0x4000);
3438 vassert(AA < 0x2);
3439 vassert(LK < 0x2);
cerion5b2325f2005-12-23 00:55:09 +00003440 theInstr = ((16<<26) | (BO<<21) | (BI<<16) |
3441 (BD<<2) | (AA<<1) | (LK));
carll1f5fe1f2014-08-07 23:25:23 +00003442 return emit32(p, theInstr, endness_host);
cerion33aa6da2005-02-16 10:25:26 +00003443}
3444
cerion33aa6da2005-02-16 10:25:26 +00003445// rotates
ceriona2f75882005-03-15 16:33:38 +00003446static UChar* mkFormM ( UChar* p, UInt opc1, UInt r1, UInt r2,
carll1f5fe1f2014-08-07 23:25:23 +00003447 UInt f3, UInt MB, UInt ME, UInt Rc,
3448 VexEndness endness_host )
cerion33aa6da2005-02-16 10:25:26 +00003449{
sewardj9a036bf2005-03-14 18:19:08 +00003450 UInt theInstr;
ceriona2f75882005-03-15 16:33:38 +00003451 vassert(opc1 < 0x40);
cerionf0de28c2005-12-13 20:21:11 +00003452 vassert(r1 < 0x20);
3453 vassert(r2 < 0x20);
3454 vassert(f3 < 0x20);
3455 vassert(MB < 0x20);
3456 vassert(ME < 0x20);
3457 vassert(Rc < 0x2);
ceriona2f75882005-03-15 16:33:38 +00003458 theInstr = ((opc1<<26) | (r1<<21) | (r2<<16) |
sewardj9a036bf2005-03-14 18:19:08 +00003459 (f3<<11) | (MB<<6) | (ME<<1) | (Rc));
carll1f5fe1f2014-08-07 23:25:23 +00003460 return emit32(p, theInstr, endness_host);
cerion33aa6da2005-02-16 10:25:26 +00003461}
cerion33aa6da2005-02-16 10:25:26 +00003462
cerion094d1392005-06-20 13:45:57 +00003463static UChar* mkFormA ( UChar* p, UInt opc1, UInt r1, UInt r2,
carll1f5fe1f2014-08-07 23:25:23 +00003464 UInt r3, UInt r4, UInt opc2, UInt b0,
3465 VexEndness endness_host )
cerion094d1392005-06-20 13:45:57 +00003466{
3467 UInt theInstr;
3468 vassert(opc1 < 0x40);
3469 vassert(r1 < 0x20);
3470 vassert(r2 < 0x20);
3471 vassert(r3 < 0x20);
3472 vassert(r4 < 0x20);
3473 vassert(opc2 < 0x20);
3474 vassert(b0 < 0x2 );
3475 theInstr = ((opc1<<26) | (r1<<21) | (r2<<16) | (r3<<11) |
3476 (r4<<6) | (opc2<<1) | (b0));
carll1f5fe1f2014-08-07 23:25:23 +00003477 return emit32(p, theInstr, endness_host);
cerion094d1392005-06-20 13:45:57 +00003478}
3479
sewardj26217b02012-04-12 17:19:48 +00003480static UChar* mkFormZ22 ( UChar* p, UInt opc1, UInt r1, UInt r2,
carll1f5fe1f2014-08-07 23:25:23 +00003481 UInt constant, UInt opc2, UInt b0,
3482 VexEndness endness_host)
sewardj26217b02012-04-12 17:19:48 +00003483{
3484 UInt theInstr;
3485 vassert(opc1 < 0x40);
3486 vassert(r1 < 0x20);
3487 vassert(r2 < 0x20);
3488 vassert(constant < 0x40); /* 6 bit constant */
3489 vassert(opc2 < 0x200); /* 9 bit field */
3490 vassert(b0 < 0x2);
3491 theInstr = ((opc1<<26) | (r1<<21) | (r2<<16) |
3492 (constant<<10) | (opc2<<1) | (b0));
carll1f5fe1f2014-08-07 23:25:23 +00003493 return emit32(p, theInstr, endness_host);
sewardj26217b02012-04-12 17:19:48 +00003494}
3495
sewardjcdc376d2012-04-23 11:21:12 +00003496static UChar* mkFormZ23 ( UChar* p, UInt opc1, UInt r1, UInt r2,
carll1f5fe1f2014-08-07 23:25:23 +00003497 UInt r3, UInt rmc, UInt opc2, UInt b0,
3498 VexEndness endness_host)
sewardjcdc376d2012-04-23 11:21:12 +00003499{
3500 UInt theInstr;
3501 vassert(opc1 < 0x40);
3502 vassert(r1 < 0x20);
3503 vassert(r2 < 0x20);
3504 vassert(r3 < 0x20);
3505 vassert(rmc < 0x4);
3506 vassert(opc2 < 0x100);
3507 vassert(b0 < 0x2);
3508 theInstr = ((opc1<<26) | (r1<<21) | (r2<<16) |
3509 (r3<<11) | (rmc<<9) | (opc2<<1) | (b0));
carll1f5fe1f2014-08-07 23:25:23 +00003510 return emit32(p, theInstr, endness_host);
sewardjcdc376d2012-04-23 11:21:12 +00003511}
3512
cerionf0de28c2005-12-13 20:21:11 +00003513static UChar* doAMode_IR ( UChar* p, UInt opc1, UInt rSD,
carll1f5fe1f2014-08-07 23:25:23 +00003514 PPCAMode* am, Bool mode64, VexEndness endness_host )
ceriond5e38382005-02-11 13:38:15 +00003515{
cerioned623db2005-06-20 12:42:04 +00003516 UInt rA, idx;
ceriond5e38382005-02-11 13:38:15 +00003517 vassert(am->tag == Pam_IR);
ceriona2f75882005-03-15 16:33:38 +00003518 vassert(am->Pam.IR.index < 0x10000);
3519
sewardja5b50222015-03-26 07:18:32 +00003520 rA = iregEnc(am->Pam.IR.base, mode64);
sewardj9a036bf2005-03-14 18:19:08 +00003521 idx = am->Pam.IR.index;
ceriona2f75882005-03-15 16:33:38 +00003522
cerionf0de28c2005-12-13 20:21:11 +00003523 if (opc1 == 58 || opc1 == 62) { // ld/std: mode64 only
3524 vassert(mode64);
sewardj34085e32007-03-09 18:07:00 +00003525 /* stay sane with DS form: lowest 2 bits must be 00. This
3526 should be guaranteed to us by iselWordExpr_AMode. */
3527 vassert(0 == (idx & 3));
cerionf0de28c2005-12-13 20:21:11 +00003528 }
carll1f5fe1f2014-08-07 23:25:23 +00003529 p = mkFormD(p, opc1, rSD, rA, idx, endness_host);
ceriond5e38382005-02-11 13:38:15 +00003530 return p;
3531}
3532
ceriona2f75882005-03-15 16:33:38 +00003533static UChar* doAMode_RR ( UChar* p, UInt opc1, UInt opc2,
carll1f5fe1f2014-08-07 23:25:23 +00003534 UInt rSD, PPCAMode* am, Bool mode64,
3535 VexEndness endness_host )
ceriond5e38382005-02-11 13:38:15 +00003536{
cerioned623db2005-06-20 12:42:04 +00003537 UInt rA, rB;
ceriond5e38382005-02-11 13:38:15 +00003538 vassert(am->tag == Pam_RR);
ceriona2f75882005-03-15 16:33:38 +00003539
sewardja5b50222015-03-26 07:18:32 +00003540 rA = iregEnc(am->Pam.RR.base, mode64);
3541 rB = iregEnc(am->Pam.RR.index, mode64);
ceriona2f75882005-03-15 16:33:38 +00003542
carll1f5fe1f2014-08-07 23:25:23 +00003543 p = mkFormX(p, opc1, rSD, rA, rB, opc2, 0, endness_host);
ceriond5e38382005-02-11 13:38:15 +00003544 return p;
3545}
3546
cerionf0de28c2005-12-13 20:21:11 +00003547
cerione97e1062005-02-21 15:09:19 +00003548/* Load imm to r_dst */
carll1f5fe1f2014-08-07 23:25:23 +00003549static UChar* mkLoadImm ( UChar* p, UInt r_dst, ULong imm, Bool mode64,
3550 VexEndness endness_host )
cerione97e1062005-02-21 15:09:19 +00003551{
3552 vassert(r_dst < 0x20);
3553
sewardjafd16392006-05-06 14:40:40 +00003554 if (!mode64) {
3555 /* In 32-bit mode, make sure the top 32 bits of imm are a sign
3556 extension of the bottom 32 bits, so that the range tests
3557 below work correctly. */
3558 UInt u32 = (UInt)imm;
3559 Int s32 = (Int)u32;
3560 Long s64 = (Long)s32;
3561 imm = (ULong)s64;
3562 }
3563
cerion5b2325f2005-12-23 00:55:09 +00003564 if (imm >= 0xFFFFFFFFFFFF8000ULL || imm < 0x8000) {
cerionf0de28c2005-12-13 20:21:11 +00003565 // sign-extendable from 16 bits
3566
cerione97e1062005-02-21 15:09:19 +00003567 // addi r_dst,0,imm => li r_dst,imm
carll1f5fe1f2014-08-07 23:25:23 +00003568 p = mkFormD(p, 14, r_dst, 0, imm & 0xFFFF, endness_host);
cerione97e1062005-02-21 15:09:19 +00003569 } else {
cerion5b2325f2005-12-23 00:55:09 +00003570 if (imm >= 0xFFFFFFFF80000000ULL || imm < 0x80000000ULL) {
cerionf0de28c2005-12-13 20:21:11 +00003571 // sign-extendable from 32 bits
3572
3573 // addis r_dst,r0,(imm>>16) => lis r_dst, (imm>>16)
carll1f5fe1f2014-08-07 23:25:23 +00003574 p = mkFormD(p, 15, r_dst, 0, (imm>>16) & 0xFFFF, endness_host);
cerionf0de28c2005-12-13 20:21:11 +00003575 // ori r_dst, r_dst, (imm & 0xFFFF)
carll1f5fe1f2014-08-07 23:25:23 +00003576 p = mkFormD(p, 24, r_dst, r_dst, imm & 0xFFFF, endness_host);
cerionf0de28c2005-12-13 20:21:11 +00003577 } else {
3578 // full 64bit immediate load: 5 (five!) insns.
3579 vassert(mode64);
3580
3581 // load high word
sewardjaca070a2006-10-17 00:28:22 +00003582
cerionf0de28c2005-12-13 20:21:11 +00003583 // lis r_dst, (imm>>48) & 0xFFFF
carll1f5fe1f2014-08-07 23:25:23 +00003584 p = mkFormD(p, 15, r_dst, 0, (imm>>48) & 0xFFFF, endness_host);
sewardjaca070a2006-10-17 00:28:22 +00003585
cerionf0de28c2005-12-13 20:21:11 +00003586 // ori r_dst, r_dst, (imm>>32) & 0xFFFF
sewardjaca070a2006-10-17 00:28:22 +00003587 if ((imm>>32) & 0xFFFF)
carll1f5fe1f2014-08-07 23:25:23 +00003588 p = mkFormD(p, 24, r_dst, r_dst, (imm>>32) & 0xFFFF, endness_host);
cerionf0de28c2005-12-13 20:21:11 +00003589
3590 // shift r_dst low word to high word => rldicr
carll1f5fe1f2014-08-07 23:25:23 +00003591 p = mkFormMD(p, 30, r_dst, r_dst, 32, 31, 1, endness_host);
cerionf0de28c2005-12-13 20:21:11 +00003592
3593 // load low word
sewardjaca070a2006-10-17 00:28:22 +00003594
cerionf0de28c2005-12-13 20:21:11 +00003595 // oris r_dst, r_dst, (imm>>16) & 0xFFFF
sewardjaca070a2006-10-17 00:28:22 +00003596 if ((imm>>16) & 0xFFFF)
carll1f5fe1f2014-08-07 23:25:23 +00003597 p = mkFormD(p, 25, r_dst, r_dst, (imm>>16) & 0xFFFF, endness_host);
sewardjaca070a2006-10-17 00:28:22 +00003598
cerionf0de28c2005-12-13 20:21:11 +00003599 // ori r_dst, r_dst, (imm) & 0xFFFF
sewardjaca070a2006-10-17 00:28:22 +00003600 if (imm & 0xFFFF)
carll1f5fe1f2014-08-07 23:25:23 +00003601 p = mkFormD(p, 24, r_dst, r_dst, imm & 0xFFFF, endness_host);
cerionf0de28c2005-12-13 20:21:11 +00003602 }
cerione97e1062005-02-21 15:09:19 +00003603 }
3604 return p;
3605}
3606
sewardj3dee8492012-04-20 00:13:28 +00003607/* A simplified version of mkLoadImm that always generates 2 or 5
3608 instructions (32 or 64 bits respectively) even if it could generate
3609 fewer. This is needed for generating fixed sized patchable
3610 sequences. */
3611static UChar* mkLoadImm_EXACTLY2or5 ( UChar* p,
carll1f5fe1f2014-08-07 23:25:23 +00003612 UInt r_dst, ULong imm, Bool mode64,
3613 VexEndness endness_host )
sewardj3dee8492012-04-20 00:13:28 +00003614{
3615 vassert(r_dst < 0x20);
3616
3617 if (!mode64) {
3618 /* In 32-bit mode, make sure the top 32 bits of imm are a sign
3619 extension of the bottom 32 bits. (Probably unnecessary.) */
3620 UInt u32 = (UInt)imm;
3621 Int s32 = (Int)u32;
3622 Long s64 = (Long)s32;
3623 imm = (ULong)s64;
3624 }
3625
3626 if (!mode64) {
3627 // addis r_dst,r0,(imm>>16) => lis r_dst, (imm>>16)
carll1f5fe1f2014-08-07 23:25:23 +00003628 p = mkFormD(p, 15, r_dst, 0, (imm>>16) & 0xFFFF, endness_host);
sewardj3dee8492012-04-20 00:13:28 +00003629 // ori r_dst, r_dst, (imm & 0xFFFF)
carll1f5fe1f2014-08-07 23:25:23 +00003630 p = mkFormD(p, 24, r_dst, r_dst, imm & 0xFFFF, endness_host);
sewardj3dee8492012-04-20 00:13:28 +00003631
3632 } else {
3633 // full 64bit immediate load: 5 (five!) insns.
3634
3635 // load high word
3636 // lis r_dst, (imm>>48) & 0xFFFF
carll1f5fe1f2014-08-07 23:25:23 +00003637 p = mkFormD(p, 15, r_dst, 0, (imm>>48) & 0xFFFF, endness_host);
sewardj3dee8492012-04-20 00:13:28 +00003638
3639 // ori r_dst, r_dst, (imm>>32) & 0xFFFF
carll1f5fe1f2014-08-07 23:25:23 +00003640 p = mkFormD(p, 24, r_dst, r_dst, (imm>>32) & 0xFFFF, endness_host);
sewardj3dee8492012-04-20 00:13:28 +00003641
3642 // shift r_dst low word to high word => rldicr
carll1f5fe1f2014-08-07 23:25:23 +00003643 p = mkFormMD(p, 30, r_dst, r_dst, 32, 31, 1, endness_host);
sewardj3dee8492012-04-20 00:13:28 +00003644
3645 // load low word
3646 // oris r_dst, r_dst, (imm>>16) & 0xFFFF
carll1f5fe1f2014-08-07 23:25:23 +00003647 p = mkFormD(p, 25, r_dst, r_dst, (imm>>16) & 0xFFFF, endness_host);
sewardj3dee8492012-04-20 00:13:28 +00003648
3649 // ori r_dst, r_dst, (imm) & 0xFFFF
carll1f5fe1f2014-08-07 23:25:23 +00003650 p = mkFormD(p, 24, r_dst, r_dst, imm & 0xFFFF, endness_host);
sewardj3dee8492012-04-20 00:13:28 +00003651 }
3652 return p;
3653}
3654
3655/* Checks whether the sequence of bytes at p was indeed created
3656 by mkLoadImm_EXACTLY2or5 with the given parameters. */
3657static Bool isLoadImm_EXACTLY2or5 ( UChar* p_to_check,
carll1f5fe1f2014-08-07 23:25:23 +00003658 UInt r_dst, ULong imm, Bool mode64,
3659 VexEndness endness_host )
sewardj3dee8492012-04-20 00:13:28 +00003660{
3661 vassert(r_dst < 0x20);
3662
3663 if (!mode64) {
3664 /* In 32-bit mode, make sure the top 32 bits of imm are a sign
3665 extension of the bottom 32 bits. (Probably unnecessary.) */
3666 UInt u32 = (UInt)imm;
3667 Int s32 = (Int)u32;
3668 Long s64 = (Long)s32;
3669 imm = (ULong)s64;
3670 }
3671
3672 if (!mode64) {
3673 UInt expect[2] = { 0, 0 };
3674 UChar* p = (UChar*)&expect[0];
3675 // addis r_dst,r0,(imm>>16) => lis r_dst, (imm>>16)
carll1f5fe1f2014-08-07 23:25:23 +00003676 p = mkFormD(p, 15, r_dst, 0, (imm>>16) & 0xFFFF, endness_host);
sewardj3dee8492012-04-20 00:13:28 +00003677 // ori r_dst, r_dst, (imm & 0xFFFF)
carll1f5fe1f2014-08-07 23:25:23 +00003678 p = mkFormD(p, 24, r_dst, r_dst, imm & 0xFFFF, endness_host);
sewardj3dee8492012-04-20 00:13:28 +00003679 vassert(p == (UChar*)&expect[2]);
3680
carll1f5fe1f2014-08-07 23:25:23 +00003681 return fetch32(p_to_check + 0, endness_host) == expect[0]
3682 && fetch32(p_to_check + 4, endness_host) == expect[1];
sewardj3dee8492012-04-20 00:13:28 +00003683
3684 } else {
3685 UInt expect[5] = { 0, 0, 0, 0, 0 };
3686 UChar* p = (UChar*)&expect[0];
3687 // full 64bit immediate load: 5 (five!) insns.
3688
3689 // load high word
3690 // lis r_dst, (imm>>48) & 0xFFFF
carll1f5fe1f2014-08-07 23:25:23 +00003691 p = mkFormD(p, 15, r_dst, 0, (imm>>48) & 0xFFFF, endness_host);
sewardj3dee8492012-04-20 00:13:28 +00003692
3693 // ori r_dst, r_dst, (imm>>32) & 0xFFFF
carll1f5fe1f2014-08-07 23:25:23 +00003694 p = mkFormD(p, 24, r_dst, r_dst, (imm>>32) & 0xFFFF, endness_host);
sewardj3dee8492012-04-20 00:13:28 +00003695
3696 // shift r_dst low word to high word => rldicr
carll1f5fe1f2014-08-07 23:25:23 +00003697 p = mkFormMD(p, 30, r_dst, r_dst, 32, 31, 1, endness_host);
sewardj3dee8492012-04-20 00:13:28 +00003698
3699 // load low word
3700 // oris r_dst, r_dst, (imm>>16) & 0xFFFF
carll1f5fe1f2014-08-07 23:25:23 +00003701 p = mkFormD(p, 25, r_dst, r_dst, (imm>>16) & 0xFFFF, endness_host);
sewardj3dee8492012-04-20 00:13:28 +00003702
3703 // ori r_dst, r_dst, (imm) & 0xFFFF
carll1f5fe1f2014-08-07 23:25:23 +00003704 p = mkFormD(p, 24, r_dst, r_dst, imm & 0xFFFF, endness_host);
sewardj3dee8492012-04-20 00:13:28 +00003705
3706 vassert(p == (UChar*)&expect[5]);
3707
carll1f5fe1f2014-08-07 23:25:23 +00003708 return fetch32(p_to_check + 0, endness_host) == expect[0]
3709 && fetch32(p_to_check + 4, endness_host) == expect[1]
3710 && fetch32(p_to_check + 8, endness_host) == expect[2]
3711 && fetch32(p_to_check + 12, endness_host) == expect[3]
3712 && fetch32(p_to_check + 16, endness_host) == expect[4];
sewardj3dee8492012-04-20 00:13:28 +00003713 }
3714}
3715
3716
3717/* Generate a machine-word sized load or store. Simplified version of
3718 the Pin_Load and Pin_Store cases below. */
3719static UChar* do_load_or_store_machine_word (
3720 UChar* p, Bool isLoad,
carll1f5fe1f2014-08-07 23:25:23 +00003721 UInt reg, PPCAMode* am, Bool mode64, VexEndness endness_host )
sewardj3dee8492012-04-20 00:13:28 +00003722{
3723 if (isLoad) {
3724 UInt opc1, sz = mode64 ? 8 : 4;
3725 switch (am->tag) {
3726 case Pam_IR:
3727 if (mode64) {
3728 vassert(0 == (am->Pam.IR.index & 3));
3729 }
3730 switch (sz) {
3731 case 4: opc1 = 32; vassert(!mode64); break;
3732 case 8: opc1 = 58; vassert(mode64); break;
3733 default: vassert(0);
3734 }
carll1f5fe1f2014-08-07 23:25:23 +00003735 p = doAMode_IR(p, opc1, reg, am, mode64, endness_host);
sewardj3dee8492012-04-20 00:13:28 +00003736 break;
3737 case Pam_RR:
3738 /* we could handle this case, but we don't expect to ever
3739 need to. */
3740 vassert(0);
3741 default:
3742 vassert(0);
3743 }
3744 } else /*store*/ {
3745 UInt opc1, sz = mode64 ? 8 : 4;
3746 switch (am->tag) {
3747 case Pam_IR:
3748 if (mode64) {
3749 vassert(0 == (am->Pam.IR.index & 3));
3750 }
3751 switch (sz) {
3752 case 4: opc1 = 36; vassert(!mode64); break;
3753 case 8: opc1 = 62; vassert(mode64); break;
3754 default: vassert(0);
3755 }
carll1f5fe1f2014-08-07 23:25:23 +00003756 p = doAMode_IR(p, opc1, reg, am, mode64, endness_host);
sewardj3dee8492012-04-20 00:13:28 +00003757 break;
3758 case Pam_RR:
3759 /* we could handle this case, but we don't expect to ever
3760 need to. */
3761 vassert(0);
3762 default:
3763 vassert(0);
3764 }
3765 }
3766 return p;
3767}
3768
3769/* Generate a 32-bit sized load or store. Simplified version of
3770 do_load_or_store_machine_word above. */
3771static UChar* do_load_or_store_word32 (
3772 UChar* p, Bool isLoad,
carll1f5fe1f2014-08-07 23:25:23 +00003773 UInt reg, PPCAMode* am, Bool mode64, VexEndness endness_host )
sewardj3dee8492012-04-20 00:13:28 +00003774{
3775 if (isLoad) {
3776 UInt opc1;
3777 switch (am->tag) {
3778 case Pam_IR:
3779 if (mode64) {
3780 vassert(0 == (am->Pam.IR.index & 3));
3781 }
3782 opc1 = 32;
carll1f5fe1f2014-08-07 23:25:23 +00003783 p = doAMode_IR(p, opc1, reg, am, mode64, endness_host);
sewardj3dee8492012-04-20 00:13:28 +00003784 break;
3785 case Pam_RR:
3786 /* we could handle this case, but we don't expect to ever
3787 need to. */
3788 vassert(0);
3789 default:
3790 vassert(0);
3791 }
3792 } else /*store*/ {
3793 UInt opc1;
3794 switch (am->tag) {
3795 case Pam_IR:
3796 if (mode64) {
3797 vassert(0 == (am->Pam.IR.index & 3));
3798 }
3799 opc1 = 36;
carll1f5fe1f2014-08-07 23:25:23 +00003800 p = doAMode_IR(p, opc1, reg, am, mode64, endness_host);
sewardj3dee8492012-04-20 00:13:28 +00003801 break;
3802 case Pam_RR:
3803 /* we could handle this case, but we don't expect to ever
3804 need to. */
3805 vassert(0);
3806 default:
3807 vassert(0);
3808 }
3809 }
3810 return p;
3811}
3812
cerione97e1062005-02-21 15:09:19 +00003813/* Move r_dst to r_src */
carll1f5fe1f2014-08-07 23:25:23 +00003814static UChar* mkMoveReg ( UChar* p, UInt r_dst, UInt r_src,
3815 VexEndness endness_host )
cerione97e1062005-02-21 15:09:19 +00003816{
3817 vassert(r_dst < 0x20);
3818 vassert(r_src < 0x20);
3819
3820 if (r_dst != r_src) {
3821 /* or r_dst, r_src, r_src */
carll1f5fe1f2014-08-07 23:25:23 +00003822 p = mkFormX(p, 31, r_src, r_dst, r_src, 444, 0, endness_host );
cerione97e1062005-02-21 15:09:19 +00003823 }
3824 return p;
3825}
3826
cerionc3d8bdc2005-06-28 18:06:23 +00003827static UChar* mkFormVX ( UChar* p, UInt opc1, UInt r1, UInt r2,
carll1f5fe1f2014-08-07 23:25:23 +00003828 UInt r3, UInt opc2, VexEndness endness_host )
cerionc3d8bdc2005-06-28 18:06:23 +00003829{
3830 UInt theInstr;
3831 vassert(opc1 < 0x40);
3832 vassert(r1 < 0x20);
3833 vassert(r2 < 0x20);
3834 vassert(r3 < 0x20);
3835 vassert(opc2 < 0x800);
cerion6b6f59e2005-06-28 20:59:18 +00003836 theInstr = ((opc1<<26) | (r1<<21) | (r2<<16) | (r3<<11) | opc2);
carll1f5fe1f2014-08-07 23:25:23 +00003837 return emit32(p, theInstr, endness_host);
cerion6b6f59e2005-06-28 20:59:18 +00003838}
3839
Elliott Hughesa0664b92017-04-18 17:46:52 -07003840static UChar* mkFormVSXRND ( UChar* p, UInt opc1, UInt R, UInt r1,
3841 UInt r2, UInt RMC, UInt opc2, UChar EX,
3842 VexEndness endness_host )
3843{
3844 /* The register mapping is all done using VR register numbers for the
3845 * V128 support. This means that the operands for this instruction have
3846 * been loaded into a VR register. The 32 VR registers map to VSR registers
3847 * 32 to 63. For these instructions, the hardware adds 32 to the source
3848 * and destination register numbers. Do not need to adjust the register
3849 * numbers for these instructions.
3850 */
3851
3852 UInt theInstr;
3853
3854 vassert(opc1 < 0x40);
3855 vassert(r1 < 0x20);
3856 vassert(r2 < 0x20);
3857 vassert(opc2 < 0x100);
3858 vassert(EX < 0x2);
3859 vassert(R < 0x2);
3860 vassert(RMC < 0x4);
3861
3862 theInstr = ((opc1<<26) | (r1<<21) | (R<<16) | (r2<<11) | (RMC<<9) |
3863 (opc2 << 1) | EX);
3864 return emit32(p, theInstr, endness_host);
3865}
3866
3867static UChar* mkFormVX_BX_TX ( UChar* p, UInt opc1, UInt r1, UInt r2,
3868 UInt r3, UInt opc2, VexEndness endness_host )
3869{
3870 /* The register mapping is all done using VR register numbers for the
3871 * V128 support. This means that the operands for this instruction have
3872 * been loaded into a VR register. The 32 VR registers map to VSR registers
3873 * 32 to 63. So to make the issued instruction reference the
3874 * corresponding VR register we have to add 32 to the source and
3875 * destination operand numbers, then load the new operand number into the
3876 * correct bit fields.
3877 *
3878 * r1 = 32xTX + T; r3 = 32xBX + B;
3879 * TX is bit 0, BX is bit 1, T is in bits [25:21], B is in bit [14:11]
3880 * opc2 is in bits [10:2]
3881 */
3882 UInt T, TX, B, BX;
3883
3884 UInt theInstr;
3885
3886 r1 += 32; // adjust the VSR register number to map to the VR number
3887 r3 += 32;
3888
3889 vassert(opc1 < 0x40);
3890 vassert(r1 < 0x40);
3891 vassert(r2 < 0x20);
3892 vassert(r3 < 0x40);
3893 vassert(opc2 < 0x800);
3894
3895 T = r1 & 0x1F;
3896 TX = r1 >> 5;
3897 B = r3 & 0x1F;
3898 BX = r3 >> 5;
3899 theInstr = ((opc1<<26) | (T<<21) | (r2<<16) | (B<<11) | (opc2<<2)
3900 | (BX<<1) | TX);
3901 return emit32(p, theInstr, endness_host);
3902}
3903
3904static UChar* mkFormVXR0 ( UChar* p, UInt opc1, UInt r1, UInt r2,
3905 UInt r3, UInt opc2, UChar R0,
3906 VexEndness endness_host )
3907{
3908 /* The register mapping is all done using VR register numbers for the
3909 * V128 support. This means that the operands for this instruction have
3910 * been loaded into a VR register. The 32 VR registers map to VSR registers
3911 * 32 to 63. For these instructions, the hardware adds 32 to the source
3912 * and destination register numbers. Do not need to adjust the register
3913 * numbers for these instructions.
3914 */
3915
3916 UInt theInstr;
3917
3918 vassert(opc1 < 0x40);
3919 vassert(r1 < 0x20); // register numbers are between 0 and 31 (5-bits)
3920 vassert(r2 < 0x20);
3921 vassert(r3 < 0x20);
3922 vassert(opc2 < 0x800);
3923 vassert(R0 < 0x2);
3924
3925 theInstr = ((opc1<<26) | (r1<<21) | (r2<<16) | (r3<<11) | (opc2<<1) | R0);
3926 return emit32(p, theInstr, endness_host);
3927}
3928
carll9877fe52014-10-07 17:49:14 +00003929static UChar* mkFormVXI ( UChar* p, UInt opc1, UInt r1, UInt r2,
3930 UInt r3, UInt opc2, VexEndness endness_host )
3931{
3932 UInt theInstr;
3933 vassert(opc1 < 0x40);
3934 vassert(r1 < 0x20);
3935 vassert(r2 < 0x20);
3936 vassert(r3 < 0x20);
3937 vassert(opc2 < 0x27);
3938 theInstr = ((opc1<<26) | (r1<<21) | (r2<<16) | (r3<<11) | opc2<<1);
3939 return emit32(p, theInstr, endness_host);
3940}
3941
cerion8ea0d3e2005-11-14 00:44:47 +00003942static UChar* mkFormVXR ( UChar* p, UInt opc1, UInt r1, UInt r2,
carll1f5fe1f2014-08-07 23:25:23 +00003943 UInt r3, UInt Rc, UInt opc2,
3944 VexEndness endness_host )
cerion6b6f59e2005-06-28 20:59:18 +00003945{
3946 UInt theInstr;
3947 vassert(opc1 < 0x40);
3948 vassert(r1 < 0x20);
3949 vassert(r2 < 0x20);
3950 vassert(r3 < 0x20);
3951 vassert(Rc < 0x2);
3952 vassert(opc2 < 0x400);
cerion5b2325f2005-12-23 00:55:09 +00003953 theInstr = ((opc1<<26) | (r1<<21) | (r2<<16) |
3954 (r3<<11) | (Rc<<10) | opc2);
carll1f5fe1f2014-08-07 23:25:23 +00003955 return emit32(p, theInstr, endness_host);
cerionc3d8bdc2005-06-28 18:06:23 +00003956}
3957
3958static UChar* mkFormVA ( UChar* p, UInt opc1, UInt r1, UInt r2,
carll1f5fe1f2014-08-07 23:25:23 +00003959 UInt r3, UInt r4, UInt opc2, VexEndness endness_host )
cerionc3d8bdc2005-06-28 18:06:23 +00003960{
3961 UInt theInstr;
3962 vassert(opc1 < 0x40);
3963 vassert(r1 < 0x20);
3964 vassert(r2 < 0x20);
3965 vassert(r3 < 0x20);
3966 vassert(r4 < 0x20);
3967 vassert(opc2 < 0x40);
cerion5b2325f2005-12-23 00:55:09 +00003968 theInstr = ((opc1<<26) | (r1<<21) | (r2<<16) |
3969 (r3<<11) | (r4<<6) | opc2);
carll1f5fe1f2014-08-07 23:25:23 +00003970 return emit32(p, theInstr, endness_host);
cerionc3d8bdc2005-06-28 18:06:23 +00003971}
3972
3973
ceriond5e38382005-02-11 13:38:15 +00003974
cerionbcf8c3e2005-02-04 16:17:07 +00003975/* Emit an instruction into buf and return the number of bytes used.
3976 Note that buf is not the insn's final place, and therefore it is
sewardj3dee8492012-04-20 00:13:28 +00003977 imperative to emit position-independent code. If the emitted
3978 instruction was a profiler inc, set *is_profInc to True, else leave
3979 it unchanged.
sewardjb8a8dba2005-12-15 21:33:50 +00003980*/
sewardj3dee8492012-04-20 00:13:28 +00003981Int emit_PPCInstr ( /*MB_MOD*/Bool* is_profInc,
floriand8c64e02014-10-08 08:54:44 +00003982 UChar* buf, Int nbuf, const PPCInstr* i,
sewardj9b769162014-07-24 12:42:03 +00003983 Bool mode64, VexEndness endness_host,
florian8462d112014-09-24 15:18:09 +00003984 const void* disp_cp_chain_me_to_slowEP,
3985 const void* disp_cp_chain_me_to_fastEP,
3986 const void* disp_cp_xindir,
3987 const void* disp_cp_xassisted)
cerionbcf8c3e2005-02-04 16:17:07 +00003988{
cerionbcf8c3e2005-02-04 16:17:07 +00003989 UChar* p = &buf[0];
cerion7cf8e4e2005-02-16 16:08:17 +00003990 vassert(nbuf >= 32);
cerion2c49e032005-02-09 17:29:49 +00003991
sewardj7fd5bb02006-01-26 02:24:17 +00003992 if (0) {
3993 vex_printf("asm ");ppPPCInstr(i, mode64); vex_printf("\n");
3994 }
cerionbcf8c3e2005-02-04 16:17:07 +00003995
3996 switch (i->tag) {
3997
cerionf0de28c2005-12-13 20:21:11 +00003998 case Pin_LI:
sewardja5b50222015-03-26 07:18:32 +00003999 p = mkLoadImm(p, iregEnc(i->Pin.LI.dst, mode64),
carll1f5fe1f2014-08-07 23:25:23 +00004000 i->Pin.LI.imm64, mode64, endness_host);
sewardjb51f0f42005-07-18 11:38:02 +00004001 goto done;
4002
cerionf0de28c2005-12-13 20:21:11 +00004003 case Pin_Alu: {
cerion5b2325f2005-12-23 00:55:09 +00004004 PPCRH* srcR = i->Pin.Alu.srcR;
4005 Bool immR = toBool(srcR->tag == Prh_Imm);
sewardja5b50222015-03-26 07:18:32 +00004006 UInt r_dst = iregEnc(i->Pin.Alu.dst, mode64);
4007 UInt r_srcL = iregEnc(i->Pin.Alu.srcL, mode64);
cerion5b2325f2005-12-23 00:55:09 +00004008 UInt r_srcR = immR ? (-1)/*bogus*/ :
sewardja5b50222015-03-26 07:18:32 +00004009 iregEnc(srcR->Prh.Reg.reg, mode64);
cerion2c49e032005-02-09 17:29:49 +00004010
cerionf0de28c2005-12-13 20:21:11 +00004011 switch (i->Pin.Alu.op) {
sewardjb51f0f42005-07-18 11:38:02 +00004012 case Palu_ADD:
4013 if (immR) {
4014 /* addi (PPC32 p350) */
4015 vassert(srcR->Prh.Imm.syned);
4016 vassert(srcR->Prh.Imm.imm16 != 0x8000);
carll1f5fe1f2014-08-07 23:25:23 +00004017 p = mkFormD(p, 14, r_dst, r_srcL, srcR->Prh.Imm.imm16, endness_host);
cerion9e263e32005-03-03 17:21:51 +00004018 } else {
sewardjb51f0f42005-07-18 11:38:02 +00004019 /* add (PPC32 p347) */
carll1f5fe1f2014-08-07 23:25:23 +00004020 p = mkFormXO(p, 31, r_dst, r_srcL, r_srcR, 0, 266, 0, endness_host);
cerionab9132d2005-02-15 15:46:59 +00004021 }
sewardjb51f0f42005-07-18 11:38:02 +00004022 break;
cerionab9132d2005-02-15 15:46:59 +00004023
sewardjb51f0f42005-07-18 11:38:02 +00004024 case Palu_SUB:
4025 if (immR) {
4026 /* addi (PPC32 p350), but with negated imm */
4027 vassert(srcR->Prh.Imm.syned);
4028 vassert(srcR->Prh.Imm.imm16 != 0x8000);
carll1f5fe1f2014-08-07 23:25:23 +00004029 p = mkFormD(p, 14, r_dst, r_srcL, (- srcR->Prh.Imm.imm16),
4030 endness_host);
cerion9e263e32005-03-03 17:21:51 +00004031 } else {
sewardjb51f0f42005-07-18 11:38:02 +00004032 /* subf (PPC32 p537), with args the "wrong" way round */
carll1f5fe1f2014-08-07 23:25:23 +00004033 p = mkFormXO(p, 31, r_dst, r_srcR, r_srcL, 0, 40, 0, endness_host);
cerionab9132d2005-02-15 15:46:59 +00004034 }
cerion5e2527e2005-02-25 16:39:58 +00004035 break;
cerion5e2527e2005-02-25 16:39:58 +00004036
sewardjb51f0f42005-07-18 11:38:02 +00004037 case Palu_AND:
4038 if (immR) {
4039 /* andi. (PPC32 p358) */
4040 vassert(!srcR->Prh.Imm.syned);
carll1f5fe1f2014-08-07 23:25:23 +00004041 p = mkFormD(p, 28, r_srcL, r_dst, srcR->Prh.Imm.imm16, endness_host);
sewardjb51f0f42005-07-18 11:38:02 +00004042 } else {
4043 /* and (PPC32 p356) */
carll1f5fe1f2014-08-07 23:25:23 +00004044 p = mkFormX(p, 31, r_srcL, r_dst, r_srcR, 28, 0, endness_host);
cerion9e263e32005-03-03 17:21:51 +00004045 }
cerionb85e8bb2005-02-16 08:54:33 +00004046 break;
cerion9e263e32005-03-03 17:21:51 +00004047
sewardjb51f0f42005-07-18 11:38:02 +00004048 case Palu_OR:
4049 if (immR) {
4050 /* ori (PPC32 p497) */
4051 vassert(!srcR->Prh.Imm.syned);
carll1f5fe1f2014-08-07 23:25:23 +00004052 p = mkFormD(p, 24, r_srcL, r_dst, srcR->Prh.Imm.imm16, endness_host);
sewardjb51f0f42005-07-18 11:38:02 +00004053 } else {
4054 /* or (PPC32 p495) */
carll1f5fe1f2014-08-07 23:25:23 +00004055 p = mkFormX(p, 31, r_srcL, r_dst, r_srcR, 444, 0, endness_host);
sewardjb51f0f42005-07-18 11:38:02 +00004056 }
4057 break;
4058
4059 case Palu_XOR:
4060 if (immR) {
4061 /* xori (PPC32 p550) */
4062 vassert(!srcR->Prh.Imm.syned);
carll1f5fe1f2014-08-07 23:25:23 +00004063 p = mkFormD(p, 26, r_srcL, r_dst, srcR->Prh.Imm.imm16, endness_host);
sewardjb51f0f42005-07-18 11:38:02 +00004064 } else {
4065 /* xor (PPC32 p549) */
carll1f5fe1f2014-08-07 23:25:23 +00004066 p = mkFormX(p, 31, r_srcL, r_dst, r_srcR, 316, 0, endness_host);
sewardjb51f0f42005-07-18 11:38:02 +00004067 }
4068 break;
4069
cerionbb01b7c2005-12-16 13:40:18 +00004070 default:
4071 goto bad;
4072 }
4073 goto done;
4074 }
4075
4076 case Pin_Shft: {
cerion5b2325f2005-12-23 00:55:09 +00004077 PPCRH* srcR = i->Pin.Shft.srcR;
4078 Bool sz32 = i->Pin.Shft.sz32;
4079 Bool immR = toBool(srcR->tag == Prh_Imm);
sewardja5b50222015-03-26 07:18:32 +00004080 UInt r_dst = iregEnc(i->Pin.Shft.dst, mode64);
4081 UInt r_srcL = iregEnc(i->Pin.Shft.srcL, mode64);
cerion5b2325f2005-12-23 00:55:09 +00004082 UInt r_srcR = immR ? (-1)/*bogus*/ :
sewardja5b50222015-03-26 07:18:32 +00004083 iregEnc(srcR->Prh.Reg.reg, mode64);
cerionbb01b7c2005-12-16 13:40:18 +00004084 if (!mode64)
4085 vassert(sz32);
4086
4087 switch (i->Pin.Shft.op) {
4088 case Pshft_SHL:
4089 if (sz32) {
cerionf0de28c2005-12-13 20:21:11 +00004090 if (immR) {
4091 /* rd = rs << n, 1 <= n <= 31
4092 is
4093 rlwinm rd,rs,n,0,31-n (PPC32 p501)
4094 */
4095 UInt n = srcR->Prh.Imm.imm16;
4096 vassert(!srcR->Prh.Imm.syned);
4097 vassert(n > 0 && n < 32);
carll1f5fe1f2014-08-07 23:25:23 +00004098 p = mkFormM(p, 21, r_srcL, r_dst, n, 0, 31-n, 0, endness_host);
cerionf0de28c2005-12-13 20:21:11 +00004099 } else {
4100 /* slw (PPC32 p505) */
carll1f5fe1f2014-08-07 23:25:23 +00004101 p = mkFormX(p, 31, r_srcL, r_dst, r_srcR, 24, 0, endness_host);
cerionf0de28c2005-12-13 20:21:11 +00004102 }
sewardjb51f0f42005-07-18 11:38:02 +00004103 } else {
cerionf0de28c2005-12-13 20:21:11 +00004104 if (immR) {
4105 /* rd = rs << n, 1 <= n <= 63
4106 is
4107 rldicr rd,rs,n,63-n (PPC64 p559)
4108 */
4109 UInt n = srcR->Prh.Imm.imm16;
4110 vassert(!srcR->Prh.Imm.syned);
4111 vassert(n > 0 && n < 64);
carll1f5fe1f2014-08-07 23:25:23 +00004112 p = mkFormMD(p, 30, r_srcL, r_dst, n, 63-n, 1, endness_host);
cerionf0de28c2005-12-13 20:21:11 +00004113 } else {
4114 /* sld (PPC64 p568) */
carll1f5fe1f2014-08-07 23:25:23 +00004115 p = mkFormX(p, 31, r_srcL, r_dst, r_srcR, 27, 0, endness_host);
cerionf0de28c2005-12-13 20:21:11 +00004116 }
sewardjb51f0f42005-07-18 11:38:02 +00004117 }
4118 break;
4119
cerionbb01b7c2005-12-16 13:40:18 +00004120 case Pshft_SHR:
4121 if (sz32) {
4122 if (immR) {
cerionf0de28c2005-12-13 20:21:11 +00004123 /* rd = rs >>u n, 1 <= n <= 31
4124 is
4125 rlwinm rd,rs,32-n,n,31 (PPC32 p501)
4126 */
4127 UInt n = srcR->Prh.Imm.imm16;
4128 vassert(!srcR->Prh.Imm.syned);
4129 vassert(n > 0 && n < 32);
carll1f5fe1f2014-08-07 23:25:23 +00004130 p = mkFormM(p, 21, r_srcL, r_dst, 32-n, n, 31, 0, endness_host);
cerionf0de28c2005-12-13 20:21:11 +00004131 } else {
4132 /* srw (PPC32 p508) */
carll1f5fe1f2014-08-07 23:25:23 +00004133 p = mkFormX(p, 31, r_srcL, r_dst, r_srcR, 536, 0, endness_host);
cerionf0de28c2005-12-13 20:21:11 +00004134 }
sewardjb51f0f42005-07-18 11:38:02 +00004135 } else {
cerionf0de28c2005-12-13 20:21:11 +00004136 if (immR) {
4137 /* rd = rs >>u n, 1 <= n <= 63
4138 is
4139 rldicl rd,rs,64-n,n (PPC64 p558)
4140 */
4141 UInt n = srcR->Prh.Imm.imm16;
4142 vassert(!srcR->Prh.Imm.syned);
4143 vassert(n > 0 && n < 64);
carll1f5fe1f2014-08-07 23:25:23 +00004144 p = mkFormMD(p, 30, r_srcL, r_dst, 64-n, n, 0, endness_host);
cerionf0de28c2005-12-13 20:21:11 +00004145 } else {
4146 /* srd (PPC64 p574) */
carll1f5fe1f2014-08-07 23:25:23 +00004147 p = mkFormX(p, 31, r_srcL, r_dst, r_srcR, 539, 0, endness_host);
cerionf0de28c2005-12-13 20:21:11 +00004148 }
sewardjb51f0f42005-07-18 11:38:02 +00004149 }
4150 break;
4151
cerionbb01b7c2005-12-16 13:40:18 +00004152 case Pshft_SAR:
4153 if (sz32) {
cerionf0de28c2005-12-13 20:21:11 +00004154 if (immR) {
4155 /* srawi (PPC32 p507) */
4156 UInt n = srcR->Prh.Imm.imm16;
4157 vassert(!srcR->Prh.Imm.syned);
sewardjeb17e492007-08-25 23:07:44 +00004158 /* In 64-bit mode, we allow right shifts by zero bits
4159 as that is a handy way to sign extend the lower 32
4160 bits into the upper 32 bits. */
4161 if (mode64)
4162 vassert(n >= 0 && n < 32);
4163 else
4164 vassert(n > 0 && n < 32);
carll1f5fe1f2014-08-07 23:25:23 +00004165 p = mkFormX(p, 31, r_srcL, r_dst, n, 824, 0, endness_host);
cerionf0de28c2005-12-13 20:21:11 +00004166 } else {
4167 /* sraw (PPC32 p506) */
carll1f5fe1f2014-08-07 23:25:23 +00004168 p = mkFormX(p, 31, r_srcL, r_dst, r_srcR, 792, 0, endness_host);
cerionf0de28c2005-12-13 20:21:11 +00004169 }
sewardjb51f0f42005-07-18 11:38:02 +00004170 } else {
cerionf0de28c2005-12-13 20:21:11 +00004171 if (immR) {
4172 /* sradi (PPC64 p571) */
4173 UInt n = srcR->Prh.Imm.imm16;
4174 vassert(!srcR->Prh.Imm.syned);
4175 vassert(n > 0 && n < 64);
carll1f5fe1f2014-08-07 23:25:23 +00004176 p = mkFormXS(p, 31, r_srcL, r_dst, n, 413, 0, endness_host);
cerionf0de28c2005-12-13 20:21:11 +00004177 } else {
4178 /* srad (PPC32 p570) */
carll1f5fe1f2014-08-07 23:25:23 +00004179 p = mkFormX(p, 31, r_srcL, r_dst, r_srcR, 794, 0, endness_host);
cerionf0de28c2005-12-13 20:21:11 +00004180 }
sewardjb51f0f42005-07-18 11:38:02 +00004181 }
cerionb85e8bb2005-02-16 08:54:33 +00004182 break;
cerion9e263e32005-03-03 17:21:51 +00004183
cerionab9132d2005-02-15 15:46:59 +00004184 default:
4185 goto bad;
4186 }
cerionb85e8bb2005-02-16 08:54:33 +00004187 goto done;
cerionab9132d2005-02-15 15:46:59 +00004188 }
cerion2c49e032005-02-09 17:29:49 +00004189
cerion5b2325f2005-12-23 00:55:09 +00004190 case Pin_AddSubC: {
4191 Bool isAdd = i->Pin.AddSubC.isAdd;
4192 Bool setC = i->Pin.AddSubC.setC;
sewardja5b50222015-03-26 07:18:32 +00004193 UInt r_srcL = iregEnc(i->Pin.AddSubC.srcL, mode64);
4194 UInt r_srcR = iregEnc(i->Pin.AddSubC.srcR, mode64);
4195 UInt r_dst = iregEnc(i->Pin.AddSubC.dst, mode64);
cerion4a49b032005-11-08 16:23:07 +00004196
4197 if (isAdd) {
4198 if (setC) /* addc (PPC32 p348) */
carll1f5fe1f2014-08-07 23:25:23 +00004199 p = mkFormXO(p, 31, r_dst, r_srcL, r_srcR, 0, 10, 0, endness_host);
cerion4a49b032005-11-08 16:23:07 +00004200 else /* adde (PPC32 p349) */
carll1f5fe1f2014-08-07 23:25:23 +00004201 p = mkFormXO(p, 31, r_dst, r_srcL, r_srcR, 0, 138, 0, endness_host);
cerion4a49b032005-11-08 16:23:07 +00004202 } else {
4203 /* subfX, with args the "wrong" way round */
4204 if (setC) /* subfc (PPC32 p538) */
carll1f5fe1f2014-08-07 23:25:23 +00004205 p = mkFormXO(p, 31, r_dst, r_srcR, r_srcL, 0, 8, 0, endness_host);
cerion4a49b032005-11-08 16:23:07 +00004206 else /* subfe (PPC32 p539) */
carll1f5fe1f2014-08-07 23:25:23 +00004207 p = mkFormXO(p, 31, r_dst, r_srcR, r_srcL, 0, 136, 0, endness_host);
cerion4a49b032005-11-08 16:23:07 +00004208 }
4209 goto done;
4210 }
4211
cerionf0de28c2005-12-13 20:21:11 +00004212 case Pin_Cmp: {
4213 Bool syned = i->Pin.Cmp.syned;
cerionbb01b7c2005-12-16 13:40:18 +00004214 Bool sz32 = i->Pin.Cmp.sz32;
cerionf0de28c2005-12-13 20:21:11 +00004215 UInt fld1 = i->Pin.Cmp.crfD << 2;
sewardja5b50222015-03-26 07:18:32 +00004216 UInt r_srcL = iregEnc(i->Pin.Cmp.srcL, mode64);
ceriona2f75882005-03-15 16:33:38 +00004217 UInt r_srcR, imm_srcR;
cerion5b2325f2005-12-23 00:55:09 +00004218 PPCRH* srcR = i->Pin.Cmp.srcR;
cerionab9132d2005-02-15 15:46:59 +00004219
cerionbb01b7c2005-12-16 13:40:18 +00004220 if (!mode64) // cmp double word invalid for mode32
4221 vassert(sz32);
4222 else if (!sz32) // mode64 && cmp64: set L=1
4223 fld1 |= 1;
4224
sewardjb51f0f42005-07-18 11:38:02 +00004225 switch (srcR->tag) {
4226 case Prh_Imm:
cerionbb01b7c2005-12-16 13:40:18 +00004227 vassert(syned == srcR->Prh.Imm.syned);
sewardjb51f0f42005-07-18 11:38:02 +00004228 imm_srcR = srcR->Prh.Imm.imm16;
cerionbb01b7c2005-12-16 13:40:18 +00004229 if (syned) { // cmpw/di (signed) (PPC32 p368)
sewardjb51f0f42005-07-18 11:38:02 +00004230 vassert(imm_srcR != 0x8000);
carll1f5fe1f2014-08-07 23:25:23 +00004231 p = mkFormD(p, 11, fld1, r_srcL, imm_srcR, endness_host);
cerionbb01b7c2005-12-16 13:40:18 +00004232 } else { // cmplw/di (unsigned) (PPC32 p370)
carll1f5fe1f2014-08-07 23:25:23 +00004233 p = mkFormD(p, 10, fld1, r_srcL, imm_srcR, endness_host);
sewardjb51f0f42005-07-18 11:38:02 +00004234 }
cerion98411db2005-02-16 14:14:49 +00004235 break;
sewardjb51f0f42005-07-18 11:38:02 +00004236 case Prh_Reg:
sewardja5b50222015-03-26 07:18:32 +00004237 r_srcR = iregEnc(srcR->Prh.Reg.reg, mode64);
cerionbb01b7c2005-12-16 13:40:18 +00004238 if (syned) // cmpwi (signed) (PPC32 p367)
carll1f5fe1f2014-08-07 23:25:23 +00004239 p = mkFormX(p, 31, fld1, r_srcL, r_srcR, 0, 0, endness_host);
cerionbb01b7c2005-12-16 13:40:18 +00004240 else // cmplwi (unsigned) (PPC32 p379)
carll1f5fe1f2014-08-07 23:25:23 +00004241 p = mkFormX(p, 31, fld1, r_srcL, r_srcR, 32, 0, endness_host);
cerion98411db2005-02-16 14:14:49 +00004242 break;
sewardjb51f0f42005-07-18 11:38:02 +00004243 default:
4244 goto bad;
cerion98411db2005-02-16 14:14:49 +00004245 }
4246 goto done;
4247 }
cerionb536af92005-02-10 15:03:19 +00004248
cerionf0de28c2005-12-13 20:21:11 +00004249 case Pin_Unary: {
sewardja5b50222015-03-26 07:18:32 +00004250 UInt r_dst = iregEnc(i->Pin.Unary.dst, mode64);
4251 UInt r_src = iregEnc(i->Pin.Unary.src, mode64);
cerion98411db2005-02-16 14:14:49 +00004252
cerion5b2325f2005-12-23 00:55:09 +00004253 switch (i->Pin.Unary.op) {
cerion98411db2005-02-16 14:14:49 +00004254 case Pun_NOT: // nor r_dst,r_src,r_src
carll1f5fe1f2014-08-07 23:25:23 +00004255 p = mkFormX(p, 31, r_src, r_dst, r_src, 124, 0, endness_host);
cerion98411db2005-02-16 14:14:49 +00004256 break;
4257 case Pun_NEG: // neg r_dst,r_src
carll1f5fe1f2014-08-07 23:25:23 +00004258 p = mkFormXO(p, 31, r_dst, r_src, 0, 0, 104, 0, endness_host);
cerion98411db2005-02-16 14:14:49 +00004259 break;
cerion07b07a92005-12-22 14:32:35 +00004260 case Pun_CLZ32: // cntlzw r_dst, r_src
carll1f5fe1f2014-08-07 23:25:23 +00004261 p = mkFormX(p, 31, r_src, r_dst, 0, 26, 0, endness_host);
cerion98411db2005-02-16 14:14:49 +00004262 break;
cerion07b07a92005-12-22 14:32:35 +00004263 case Pun_CLZ64: // cntlzd r_dst, r_src
sewardj7fd5bb02006-01-26 02:24:17 +00004264 vassert(mode64);
carll1f5fe1f2014-08-07 23:25:23 +00004265 p = mkFormX(p, 31, r_src, r_dst, 0, 58, 0, endness_host);
cerion07b07a92005-12-22 14:32:35 +00004266 break;
Elliott Hughesa0664b92017-04-18 17:46:52 -07004267 case Pun_CTZ32: // cnttzw r_dst, r_src
4268 /* Note oder of src and dst is backwards from normal */
4269 p = mkFormX(p, 31, r_src, r_dst, 0, 538, 0, endness_host);
4270 break;
4271 case Pun_CTZ64: // cnttzd r_dst, r_src
4272 /* Note oder of src and dst is backwards from normal */
4273 vassert(mode64);
4274 p = mkFormX(p, 31, r_src, r_dst, 0, 570, 0, endness_host);
4275 break;
sewardj7fd5bb02006-01-26 02:24:17 +00004276 case Pun_EXTSW: // extsw r_dst, r_src
4277 vassert(mode64);
carll1f5fe1f2014-08-07 23:25:23 +00004278 p = mkFormX(p, 31, r_src, r_dst, 0, 986, 0, endness_host);
sewardj7fd5bb02006-01-26 02:24:17 +00004279 break;
cerion98411db2005-02-16 14:14:49 +00004280 default: goto bad;
4281 }
4282 goto done;
4283 }
4284
4285 case Pin_MulL: {
4286 Bool syned = i->Pin.MulL.syned;
cerionbb01b7c2005-12-16 13:40:18 +00004287 Bool sz32 = i->Pin.MulL.sz32;
sewardja5b50222015-03-26 07:18:32 +00004288 UInt r_dst = iregEnc(i->Pin.MulL.dst, mode64);
4289 UInt r_srcL = iregEnc(i->Pin.MulL.srcL, mode64);
4290 UInt r_srcR = iregEnc(i->Pin.MulL.srcR, mode64);
cerionbb01b7c2005-12-16 13:40:18 +00004291
4292 if (!mode64)
4293 vassert(sz32);
cerion98411db2005-02-16 14:14:49 +00004294
cerionf0de28c2005-12-13 20:21:11 +00004295 if (i->Pin.MulL.hi) {
sewardjb51f0f42005-07-18 11:38:02 +00004296 // mul hi words, must consider sign
cerionbb01b7c2005-12-16 13:40:18 +00004297 if (sz32) {
4298 if (syned) // mulhw r_dst,r_srcL,r_srcR
carll1f5fe1f2014-08-07 23:25:23 +00004299 p = mkFormXO(p, 31, r_dst, r_srcL, r_srcR, 0, 75, 0,
4300 endness_host);
cerionbb01b7c2005-12-16 13:40:18 +00004301 else // mulhwu r_dst,r_srcL,r_srcR
carll1f5fe1f2014-08-07 23:25:23 +00004302 p = mkFormXO(p, 31, r_dst, r_srcL, r_srcR, 0, 11, 0,
4303 endness_host);
cerionbb01b7c2005-12-16 13:40:18 +00004304 } else {
4305 if (syned) // mulhd r_dst,r_srcL,r_srcR
carll1f5fe1f2014-08-07 23:25:23 +00004306 p = mkFormXO(p, 31, r_dst, r_srcL, r_srcR, 0, 73, 0,
4307 endness_host);
cerionbb01b7c2005-12-16 13:40:18 +00004308 else // mulhdu r_dst,r_srcL,r_srcR
carll1f5fe1f2014-08-07 23:25:23 +00004309 p = mkFormXO(p, 31, r_dst, r_srcL, r_srcR, 0, 9, 0, endness_host);
cerion98411db2005-02-16 14:14:49 +00004310 }
sewardjb51f0f42005-07-18 11:38:02 +00004311 } else {
4312 // mul low word, sign is irrelevant
4313 vassert(!i->Pin.MulL.syned);
cerionbb01b7c2005-12-16 13:40:18 +00004314 if (sz32) // mullw r_dst,r_srcL,r_srcR
carll1f5fe1f2014-08-07 23:25:23 +00004315 p = mkFormXO(p, 31, r_dst, r_srcL, r_srcR, 0, 235, 0, endness_host);
cerionbb01b7c2005-12-16 13:40:18 +00004316 else // mulld r_dst,r_srcL,r_srcR
carll1f5fe1f2014-08-07 23:25:23 +00004317 p = mkFormXO(p, 31, r_dst, r_srcL, r_srcR, 0, 233, 0, endness_host);
cerion98411db2005-02-16 14:14:49 +00004318 }
4319 goto done;
4320 }
cerion2c49e032005-02-09 17:29:49 +00004321
cerionfd0b87f2005-02-16 14:43:14 +00004322 case Pin_Div: {
cerionf0de28c2005-12-13 20:21:11 +00004323 Bool syned = i->Pin.Div.syned;
cerionbb01b7c2005-12-16 13:40:18 +00004324 Bool sz32 = i->Pin.Div.sz32;
sewardja5b50222015-03-26 07:18:32 +00004325 UInt r_dst = iregEnc(i->Pin.Div.dst, mode64);
4326 UInt r_srcL = iregEnc(i->Pin.Div.srcL, mode64);
4327 UInt r_srcR = iregEnc(i->Pin.Div.srcR, mode64);
cerionfd0b87f2005-02-16 14:43:14 +00004328
cerionbb01b7c2005-12-16 13:40:18 +00004329 if (!mode64)
4330 vassert(sz32);
4331
sewardj4aa412a2011-07-24 14:13:21 +00004332 if (i->Pin.Div.extended) {
4333 if (sz32) {
4334 if (syned)
4335 // divwe r_dst,r_srcL,r_srcR
carll1f5fe1f2014-08-07 23:25:23 +00004336 p = mkFormXO(p, 31, r_dst, r_srcL, r_srcR, 0, 427, 0,
4337 endness_host);
sewardj4aa412a2011-07-24 14:13:21 +00004338 else
4339 // divweu r_dst,r_srcL,r_srcR
carll1f5fe1f2014-08-07 23:25:23 +00004340 p = mkFormXO(p, 31, r_dst, r_srcL, r_srcR, 0, 395, 0,
4341 endness_host);
sewardj4aa412a2011-07-24 14:13:21 +00004342 } else {
sewardje71e56a2011-09-05 12:11:06 +00004343 if (syned)
4344 // divde r_dst,r_srcL,r_srcR
carll1f5fe1f2014-08-07 23:25:23 +00004345 p = mkFormXO(p, 31, r_dst, r_srcL, r_srcR, 0, 425, 0,
4346 endness_host);
sewardje71e56a2011-09-05 12:11:06 +00004347 else
4348 // divdeu r_dst,r_srcL,r_srcR
carll1f5fe1f2014-08-07 23:25:23 +00004349 p = mkFormXO(p, 31, r_dst, r_srcL, r_srcR, 0, 393, 0,
4350 endness_host);
sewardj4aa412a2011-07-24 14:13:21 +00004351 }
4352 } else if (sz32) {
cerionbb01b7c2005-12-16 13:40:18 +00004353 if (syned) // divw r_dst,r_srcL,r_srcR
carll1f5fe1f2014-08-07 23:25:23 +00004354 p = mkFormXO(p, 31, r_dst, r_srcL, r_srcR, 0, 491, 0, endness_host);
cerionbb01b7c2005-12-16 13:40:18 +00004355 else // divwu r_dst,r_srcL,r_srcR
carll1f5fe1f2014-08-07 23:25:23 +00004356 p = mkFormXO(p, 31, r_dst, r_srcL, r_srcR, 0, 459, 0, endness_host);
cerionbb01b7c2005-12-16 13:40:18 +00004357 } else {
4358 if (syned) // divd r_dst,r_srcL,r_srcR
carll1f5fe1f2014-08-07 23:25:23 +00004359 p = mkFormXO(p, 31, r_dst, r_srcL, r_srcR, 0, 489, 0, endness_host);
cerionbb01b7c2005-12-16 13:40:18 +00004360 else // divdu r_dst,r_srcL,r_srcR
carll1f5fe1f2014-08-07 23:25:23 +00004361 p = mkFormXO(p, 31, r_dst, r_srcL, r_srcR, 0, 457, 0, endness_host);
cerionfd0b87f2005-02-16 14:43:14 +00004362 }
4363 goto done;
4364 }
cerion2c49e032005-02-09 17:29:49 +00004365
cerion33aa6da2005-02-16 10:25:26 +00004366 case Pin_Call: {
sewardjcfe046e2013-01-17 14:23:53 +00004367 if (i->Pin.Call.cond.test != Pct_ALWAYS
sewardj74142b82013-08-08 10:28:59 +00004368 && i->Pin.Call.rloc.pri != RLPri_None) {
sewardjcfe046e2013-01-17 14:23:53 +00004369 /* The call might not happen (it isn't unconditional) and it
4370 returns a result. In this case we will need to generate a
4371 control flow diamond to put 0x555..555 in the return
4372 register(s) in the case where the call doesn't happen. If
4373 this ever becomes necessary, maybe copy code from the ARM
4374 equivalent. Until that day, just give up. */
4375 goto bad;
4376 }
cerion5b2325f2005-12-23 00:55:09 +00004377 PPCCondCode cond = i->Pin.Call.cond;
4378 UInt r_dst = 10;
ceriona56e9cc2005-02-16 18:08:25 +00004379 /* As per detailed comment for Pin_Call in
cerion5b2325f2005-12-23 00:55:09 +00004380 getRegUsage_PPCInstr above, %r10 is used as an address temp */
ceriona56e9cc2005-02-16 18:08:25 +00004381
cerioned623db2005-06-20 12:42:04 +00004382 /* jump over the following insns if condition does not hold */
sewardj3dee8492012-04-20 00:13:28 +00004383 UChar* ptmp = NULL;
cerione97e1062005-02-21 15:09:19 +00004384 if (cond.test != Pct_ALWAYS) {
cerion9762bbf2005-06-23 08:44:52 +00004385 /* jmp fwds if !condition */
4386 /* don't know how many bytes to jump over yet...
4387 make space for a jump instruction and fill in later. */
4388 ptmp = p; /* fill in this bit later */
cerion5b2325f2005-12-23 00:55:09 +00004389 p += 4; // p += 4
cerionab9132d2005-02-15 15:46:59 +00004390 }
4391
cerion5b2325f2005-12-23 00:55:09 +00004392 /* load target to r_dst */ // p += 4|8|20
carll1f5fe1f2014-08-07 23:25:23 +00004393 p = mkLoadImm(p, r_dst, i->Pin.Call.target, mode64, endness_host);
cerionab9132d2005-02-15 15:46:59 +00004394
ceriona56e9cc2005-02-16 18:08:25 +00004395 /* mtspr 9,r_dst => move r_dst to count register */
carll1f5fe1f2014-08-07 23:25:23 +00004396 p = mkFormXFX(p, r_dst, 9, 467, endness_host); // p += 4
cerion33aa6da2005-02-16 10:25:26 +00004397
cerion8c51ed42005-02-22 11:16:54 +00004398 /* bctrl => branch to count register (and save to lr) */
carll1f5fe1f2014-08-07 23:25:23 +00004399 p = mkFormXL(p, 19, Pct_ALWAYS, 0, 0, 528, 1, endness_host); // p += 4
cerion9762bbf2005-06-23 08:44:52 +00004400
4401 /* Fix up the conditional jump, if there was one. */
4402 if (cond.test != Pct_ALWAYS) {
4403 Int delta = p - ptmp;
cerionf0de28c2005-12-13 20:21:11 +00004404 vassert(delta >= 16 && delta <= 32);
cerion9762bbf2005-06-23 08:44:52 +00004405 /* bc !ct,cf,delta */
cerion5b2325f2005-12-23 00:55:09 +00004406 mkFormB(ptmp, invertCondTest(cond.test),
carll1f5fe1f2014-08-07 23:25:23 +00004407 cond.flag, (delta>>2), 0, 0, endness_host);
cerion9762bbf2005-06-23 08:44:52 +00004408 }
cerion33aa6da2005-02-16 10:25:26 +00004409 goto done;
4410 }
4411
sewardj3dee8492012-04-20 00:13:28 +00004412 case Pin_XDirect: {
4413 /* NB: what goes on here has to be very closely coordinated
4414 with the chainXDirect_PPC and unchainXDirect_PPC below. */
4415 /* We're generating chain-me requests here, so we need to be
4416 sure this is actually allowed -- no-redir translations
4417 can't use chain-me's. Hence: */
4418 vassert(disp_cp_chain_me_to_slowEP != NULL);
4419 vassert(disp_cp_chain_me_to_fastEP != NULL);
sewardjb8a8dba2005-12-15 21:33:50 +00004420
sewardj3dee8492012-04-20 00:13:28 +00004421 /* First off, if this is conditional, create a conditional jump
4422 over the rest of it. Or at least, leave a space for it that
4423 we will shortly fill in. */
4424 UChar* ptmp = NULL;
4425 if (i->Pin.XDirect.cond.test != Pct_ALWAYS) {
4426 vassert(i->Pin.XDirect.cond.flag != Pcf_NONE);
4427 ptmp = p;
cerione97e1062005-02-21 15:09:19 +00004428 p += 4;
cerion33aa6da2005-02-16 10:25:26 +00004429 } else {
sewardj3dee8492012-04-20 00:13:28 +00004430 vassert(i->Pin.XDirect.cond.flag == Pcf_NONE);
cerion33aa6da2005-02-16 10:25:26 +00004431 }
sewardj3dee8492012-04-20 00:13:28 +00004432
4433 /* Update the guest CIA. */
4434 /* imm32/64 r30, dstGA */
4435 if (!mode64) vassert(0 == (((ULong)i->Pin.XDirect.dstGA) >> 32));
carll1f5fe1f2014-08-07 23:25:23 +00004436 p = mkLoadImm(p, /*r*/30, (ULong)i->Pin.XDirect.dstGA, mode64,
4437 endness_host);
sewardj3dee8492012-04-20 00:13:28 +00004438 /* stw/std r30, amCIA */
4439 p = do_load_or_store_machine_word(
4440 p, False/*!isLoad*/,
carll1f5fe1f2014-08-07 23:25:23 +00004441 /*r*/30, i->Pin.XDirect.amCIA, mode64, endness_host
sewardj3dee8492012-04-20 00:13:28 +00004442 );
4443
4444 /* --- FIRST PATCHABLE BYTE follows --- */
4445 /* VG_(disp_cp_chain_me_to_{slowEP,fastEP}) (where we're calling
4446 to) backs up the return address, so as to find the address of
4447 the first patchable byte. So: don't change the number of
4448 instructions (32-bit: 4, 64-bit: 7) below. */
4449 /* imm32/64-fixed r30, VG_(disp_cp_chain_me_to_{slowEP,fastEP} */
florian8462d112014-09-24 15:18:09 +00004450 const void* disp_cp_chain_me
sewardj3dee8492012-04-20 00:13:28 +00004451 = i->Pin.XDirect.toFastEP ? disp_cp_chain_me_to_fastEP
4452 : disp_cp_chain_me_to_slowEP;
4453 p = mkLoadImm_EXACTLY2or5(
florian93a09742015-01-07 20:14:48 +00004454 p, /*r*/30, (Addr)disp_cp_chain_me, mode64, endness_host);
sewardj3dee8492012-04-20 00:13:28 +00004455 /* mtctr r30 */
carll1f5fe1f2014-08-07 23:25:23 +00004456 p = mkFormXFX(p, /*r*/30, 9, 467, endness_host);
sewardj3dee8492012-04-20 00:13:28 +00004457 /* bctrl */
carll1f5fe1f2014-08-07 23:25:23 +00004458 p = mkFormXL(p, 19, Pct_ALWAYS, 0, 0, 528, 1, endness_host);
sewardj3dee8492012-04-20 00:13:28 +00004459 /* --- END of PATCHABLE BYTES --- */
cerion7cf8e4e2005-02-16 16:08:17 +00004460
4461 /* Fix up the conditional jump, if there was one. */
sewardj3dee8492012-04-20 00:13:28 +00004462 if (i->Pin.XDirect.cond.test != Pct_ALWAYS) {
cerion7cf8e4e2005-02-16 16:08:17 +00004463 Int delta = p - ptmp;
sewardj9e1cf152012-04-20 02:18:31 +00004464 vassert(delta >= 16 && delta <= 64 && 0 == (delta & 3));
cerione97e1062005-02-21 15:09:19 +00004465 /* bc !ct,cf,delta */
sewardj3dee8492012-04-20 00:13:28 +00004466 mkFormB(ptmp, invertCondTest(i->Pin.XDirect.cond.test),
carll1f5fe1f2014-08-07 23:25:23 +00004467 i->Pin.XDirect.cond.flag, (delta>>2), 0, 0, endness_host);
sewardj3dee8492012-04-20 00:13:28 +00004468 }
4469 goto done;
4470 }
4471
4472 case Pin_XIndir: {
4473 /* We're generating transfers that could lead indirectly to a
4474 chain-me, so we need to be sure this is actually allowed --
4475 no-redir translations are not allowed to reach normal
4476 translations without going through the scheduler. That means
4477 no XDirects or XIndirs out from no-redir translations.
4478 Hence: */
4479 vassert(disp_cp_xindir != NULL);
4480
4481 /* First off, if this is conditional, create a conditional jump
4482 over the rest of it. Or at least, leave a space for it that
4483 we will shortly fill in. */
4484 UChar* ptmp = NULL;
4485 if (i->Pin.XIndir.cond.test != Pct_ALWAYS) {
4486 vassert(i->Pin.XIndir.cond.flag != Pcf_NONE);
4487 ptmp = p;
4488 p += 4;
4489 } else {
4490 vassert(i->Pin.XIndir.cond.flag == Pcf_NONE);
4491 }
4492
4493 /* Update the guest CIA. */
4494 /* stw/std r-dstGA, amCIA */
4495 p = do_load_or_store_machine_word(
4496 p, False/*!isLoad*/,
sewardja5b50222015-03-26 07:18:32 +00004497 iregEnc(i->Pin.XIndir.dstGA, mode64),
carll1f5fe1f2014-08-07 23:25:23 +00004498 i->Pin.XIndir.amCIA, mode64, endness_host
sewardj3dee8492012-04-20 00:13:28 +00004499 );
4500
4501 /* imm32/64 r30, VG_(disp_cp_xindir) */
florian93a09742015-01-07 20:14:48 +00004502 p = mkLoadImm(p, /*r*/30, (ULong)(Addr)disp_cp_xindir, mode64,
carll1f5fe1f2014-08-07 23:25:23 +00004503 endness_host);
sewardj3dee8492012-04-20 00:13:28 +00004504 /* mtctr r30 */
carll1f5fe1f2014-08-07 23:25:23 +00004505 p = mkFormXFX(p, /*r*/30, 9, 467, endness_host);
sewardj3dee8492012-04-20 00:13:28 +00004506 /* bctr */
carll1f5fe1f2014-08-07 23:25:23 +00004507 p = mkFormXL(p, 19, Pct_ALWAYS, 0, 0, 528, 0, endness_host);
sewardj3dee8492012-04-20 00:13:28 +00004508
4509 /* Fix up the conditional jump, if there was one. */
4510 if (i->Pin.XIndir.cond.test != Pct_ALWAYS) {
4511 Int delta = p - ptmp;
4512 vassert(delta >= 16 && delta <= 32 && 0 == (delta & 3));
4513 /* bc !ct,cf,delta */
4514 mkFormB(ptmp, invertCondTest(i->Pin.XIndir.cond.test),
carll1f5fe1f2014-08-07 23:25:23 +00004515 i->Pin.XIndir.cond.flag, (delta>>2), 0, 0, endness_host);
sewardj3dee8492012-04-20 00:13:28 +00004516 }
4517 goto done;
4518 }
4519
4520 case Pin_XAssisted: {
4521 /* First off, if this is conditional, create a conditional jump
4522 over the rest of it. Or at least, leave a space for it that
4523 we will shortly fill in. */
4524 UChar* ptmp = NULL;
4525 if (i->Pin.XAssisted.cond.test != Pct_ALWAYS) {
4526 vassert(i->Pin.XAssisted.cond.flag != Pcf_NONE);
4527 ptmp = p;
4528 p += 4;
4529 } else {
4530 vassert(i->Pin.XAssisted.cond.flag == Pcf_NONE);
4531 }
4532
4533 /* Update the guest CIA. */
4534 /* stw/std r-dstGA, amCIA */
4535 p = do_load_or_store_machine_word(
4536 p, False/*!isLoad*/,
sewardja5b50222015-03-26 07:18:32 +00004537 iregEnc(i->Pin.XIndir.dstGA, mode64),
carll1f5fe1f2014-08-07 23:25:23 +00004538 i->Pin.XIndir.amCIA, mode64, endness_host
sewardj3dee8492012-04-20 00:13:28 +00004539 );
4540
4541 /* imm32/64 r31, $magic_number */
4542 UInt trcval = 0;
4543 switch (i->Pin.XAssisted.jk) {
4544 case Ijk_ClientReq: trcval = VEX_TRC_JMP_CLIENTREQ; break;
4545 case Ijk_Sys_syscall: trcval = VEX_TRC_JMP_SYS_SYSCALL; break;
4546 //case Ijk_Sys_int128: trcval = VEX_TRC_JMP_SYS_INT128; break;
4547 //case Ijk_Yield: trcval = VEX_TRC_JMP_YIELD; break;
4548 case Ijk_EmWarn: trcval = VEX_TRC_JMP_EMWARN; break;
sewardjf252de52012-04-20 10:42:24 +00004549 case Ijk_EmFail: trcval = VEX_TRC_JMP_EMFAIL; break;
sewardj3dee8492012-04-20 00:13:28 +00004550 //case Ijk_MapFail: trcval = VEX_TRC_JMP_MAPFAIL; break;
4551 case Ijk_NoDecode: trcval = VEX_TRC_JMP_NODECODE; break;
sewardj05f5e012014-05-04 10:52:11 +00004552 case Ijk_InvalICache: trcval = VEX_TRC_JMP_INVALICACHE; break;
sewardj3dee8492012-04-20 00:13:28 +00004553 case Ijk_NoRedir: trcval = VEX_TRC_JMP_NOREDIR; break;
4554 case Ijk_SigTRAP: trcval = VEX_TRC_JMP_SIGTRAP; break;
4555 //case Ijk_SigSEGV: trcval = VEX_TRC_JMP_SIGSEGV; break;
4556 case Ijk_SigBUS: trcval = VEX_TRC_JMP_SIGBUS; break;
4557 case Ijk_Boring: trcval = VEX_TRC_JMP_BORING; break;
4558 /* We don't expect to see the following being assisted. */
4559 //case Ijk_Ret:
4560 //case Ijk_Call:
4561 /* fallthrough */
4562 default:
4563 ppIRJumpKind(i->Pin.XAssisted.jk);
4564 vpanic("emit_ARMInstr.Pin_XAssisted: unexpected jump kind");
4565 }
4566 vassert(trcval != 0);
carll1f5fe1f2014-08-07 23:25:23 +00004567 p = mkLoadImm(p, /*r*/31, trcval, mode64, endness_host);
sewardj3dee8492012-04-20 00:13:28 +00004568
4569 /* imm32/64 r30, VG_(disp_cp_xassisted) */
4570 p = mkLoadImm(p, /*r*/30,
florian93a09742015-01-07 20:14:48 +00004571 (ULong)(Addr)disp_cp_xassisted, mode64,
carll1f5fe1f2014-08-07 23:25:23 +00004572 endness_host);
sewardj3dee8492012-04-20 00:13:28 +00004573 /* mtctr r30 */
carll1f5fe1f2014-08-07 23:25:23 +00004574 p = mkFormXFX(p, /*r*/30, 9, 467, endness_host);
sewardj3dee8492012-04-20 00:13:28 +00004575 /* bctr */
carll1f5fe1f2014-08-07 23:25:23 +00004576 p = mkFormXL(p, 19, Pct_ALWAYS, 0, 0, 528, 0, endness_host);
sewardj3dee8492012-04-20 00:13:28 +00004577
4578 /* Fix up the conditional jump, if there was one. */
4579 if (i->Pin.XAssisted.cond.test != Pct_ALWAYS) {
4580 Int delta = p - ptmp;
4581 vassert(delta >= 16 && delta <= 32 && 0 == (delta & 3));
4582 /* bc !ct,cf,delta */
4583 mkFormB(ptmp, invertCondTest(i->Pin.XAssisted.cond.test),
carll1f5fe1f2014-08-07 23:25:23 +00004584 i->Pin.XAssisted.cond.flag, (delta>>2), 0, 0, endness_host);
cerion7cf8e4e2005-02-16 16:08:17 +00004585 }
cerion33aa6da2005-02-16 10:25:26 +00004586 goto done;
4587 }
cerionb536af92005-02-10 15:03:19 +00004588
cerionf0de28c2005-12-13 20:21:11 +00004589 case Pin_CMov: {
cerion5b2325f2005-12-23 00:55:09 +00004590 UInt r_dst, r_src;
cerionf0de28c2005-12-13 20:21:11 +00004591 ULong imm_src;
cerion5b2325f2005-12-23 00:55:09 +00004592 PPCCondCode cond;
cerionf0de28c2005-12-13 20:21:11 +00004593 vassert(i->Pin.CMov.cond.test != Pct_ALWAYS);
ceriona2f75882005-03-15 16:33:38 +00004594
sewardja5b50222015-03-26 07:18:32 +00004595 r_dst = iregEnc(i->Pin.CMov.dst, mode64);
cerionf0de28c2005-12-13 20:21:11 +00004596 cond = i->Pin.CMov.cond;
cerion98411db2005-02-16 14:14:49 +00004597
cerione97e1062005-02-21 15:09:19 +00004598 /* branch (if cond fails) over move instrs */
sewardj3dee8492012-04-20 00:13:28 +00004599 UChar* ptmp = NULL;
cerione97e1062005-02-21 15:09:19 +00004600 if (cond.test != Pct_ALWAYS) {
4601 /* don't know how many bytes to jump over yet...
4602 make space for a jump instruction and fill in later. */
4603 ptmp = p; /* fill in this bit later */
4604 p += 4;
4605 }
cerion98411db2005-02-16 14:14:49 +00004606
4607 // cond true: move src => dst
cerionf0de28c2005-12-13 20:21:11 +00004608 switch (i->Pin.CMov.src->tag) {
cerion98411db2005-02-16 14:14:49 +00004609 case Pri_Imm:
cerionf0de28c2005-12-13 20:21:11 +00004610 imm_src = i->Pin.CMov.src->Pri.Imm;
carll1f5fe1f2014-08-07 23:25:23 +00004611 p = mkLoadImm(p, r_dst, imm_src, mode64, endness_host); // p += 4|8|20
cerion98411db2005-02-16 14:14:49 +00004612 break;
4613 case Pri_Reg:
sewardja5b50222015-03-26 07:18:32 +00004614 r_src = iregEnc(i->Pin.CMov.src->Pri.Reg, mode64);
carll1f5fe1f2014-08-07 23:25:23 +00004615 p = mkMoveReg(p, r_dst, r_src, endness_host); // p += 4
cerion98411db2005-02-16 14:14:49 +00004616 break;
4617 default: goto bad;
4618 }
cerione97e1062005-02-21 15:09:19 +00004619
4620 /* Fix up the conditional jump, if there was one. */
4621 if (cond.test != Pct_ALWAYS) {
4622 Int delta = p - ptmp;
cerionf0de28c2005-12-13 20:21:11 +00004623 vassert(delta >= 8 && delta <= 24);
cerione97e1062005-02-21 15:09:19 +00004624 /* bc !ct,cf,delta */
cerion5b2325f2005-12-23 00:55:09 +00004625 mkFormB(ptmp, invertCondTest(cond.test),
carll1f5fe1f2014-08-07 23:25:23 +00004626 cond.flag, (delta>>2), 0, 0, endness_host);
cerione97e1062005-02-21 15:09:19 +00004627 }
cerion98411db2005-02-16 14:14:49 +00004628 goto done;
4629 }
cerionb536af92005-02-10 15:03:19 +00004630
cerion7cf8e4e2005-02-16 16:08:17 +00004631 case Pin_Load: {
cerion5b2325f2005-12-23 00:55:09 +00004632 PPCAMode* am_addr = i->Pin.Load.src;
sewardja5b50222015-03-26 07:18:32 +00004633 UInt r_dst = iregEnc(i->Pin.Load.dst, mode64);
ceriona2f75882005-03-15 16:33:38 +00004634 UInt opc1, opc2, sz = i->Pin.Load.sz;
cerionf0de28c2005-12-13 20:21:11 +00004635 switch (am_addr->tag) {
ceriond5e38382005-02-11 13:38:15 +00004636 case Pam_IR:
sewardj34085e32007-03-09 18:07:00 +00004637 if (mode64 && (sz == 4 || sz == 8)) {
4638 /* should be guaranteed to us by iselWordExpr_AMode */
4639 vassert(0 == (am_addr->Pam.IR.index & 3));
4640 }
cerionf0de28c2005-12-13 20:21:11 +00004641 switch(sz) {
sewardj7fd5bb02006-01-26 02:24:17 +00004642 case 1: opc1 = 34; break;
4643 case 2: opc1 = 40; break;
4644 case 4: opc1 = 32; break;
4645 case 8: opc1 = 58; vassert(mode64); break;
4646 default: goto bad;
cerionab9132d2005-02-15 15:46:59 +00004647 }
carll1f5fe1f2014-08-07 23:25:23 +00004648 p = doAMode_IR(p, opc1, r_dst, am_addr, mode64, endness_host);
cerionab9132d2005-02-15 15:46:59 +00004649 goto done;
ceriond5e38382005-02-11 13:38:15 +00004650 case Pam_RR:
cerionf0de28c2005-12-13 20:21:11 +00004651 switch(sz) {
sewardj7fd5bb02006-01-26 02:24:17 +00004652 case 1: opc2 = 87; break;
4653 case 2: opc2 = 279; break;
4654 case 4: opc2 = 23; break;
4655 case 8: opc2 = 21; vassert(mode64); break;
4656 default: goto bad;
cerionab9132d2005-02-15 15:46:59 +00004657 }
carll1f5fe1f2014-08-07 23:25:23 +00004658 p = doAMode_RR(p, 31, opc2, r_dst, am_addr, mode64, endness_host);
cerionab9132d2005-02-15 15:46:59 +00004659 goto done;
ceriond5e38382005-02-11 13:38:15 +00004660 default:
cerionab9132d2005-02-15 15:46:59 +00004661 goto bad;
ceriond5e38382005-02-11 13:38:15 +00004662 }
4663 }
cerionb536af92005-02-10 15:03:19 +00004664
sewardje9d8a262009-07-01 08:06:34 +00004665 case Pin_LoadL: {
carlld8268892015-04-17 23:42:40 +00004666 if (i->Pin.LoadL.sz == 1) {
4667 p = mkFormX(p, 31, iregEnc(i->Pin.LoadL.dst, mode64),
4668 0, iregEnc(i->Pin.LoadL.src, mode64), 52, 0, endness_host);
4669 goto done;
4670 }
4671 if (i->Pin.LoadL.sz == 2) {
4672 p = mkFormX(p, 31, iregEnc(i->Pin.LoadL.dst, mode64),
4673 0, iregEnc(i->Pin.LoadL.src, mode64), 116, 0, endness_host);
4674 goto done;
4675 }
sewardje9d8a262009-07-01 08:06:34 +00004676 if (i->Pin.LoadL.sz == 4) {
sewardja5b50222015-03-26 07:18:32 +00004677 p = mkFormX(p, 31, iregEnc(i->Pin.LoadL.dst, mode64),
4678 0, iregEnc(i->Pin.LoadL.src, mode64), 20, 0, endness_host);
sewardje9d8a262009-07-01 08:06:34 +00004679 goto done;
4680 }
4681 if (i->Pin.LoadL.sz == 8 && mode64) {
sewardja5b50222015-03-26 07:18:32 +00004682 p = mkFormX(p, 31, iregEnc(i->Pin.LoadL.dst, mode64),
4683 0, iregEnc(i->Pin.LoadL.src, mode64), 84, 0, endness_host);
sewardje9d8a262009-07-01 08:06:34 +00004684 goto done;
4685 }
4686 goto bad;
4687 }
4688
cerion5b2325f2005-12-23 00:55:09 +00004689 case Pin_Set: {
cerionab9132d2005-02-15 15:46:59 +00004690 /* Make the destination register be 1 or 0, depending on whether
cerion9e263e32005-03-03 17:21:51 +00004691 the relevant condition holds. */
sewardja5b50222015-03-26 07:18:32 +00004692 UInt r_dst = iregEnc(i->Pin.Set.dst, mode64);
cerion5b2325f2005-12-23 00:55:09 +00004693 PPCCondCode cond = i->Pin.Set.cond;
4694 UInt rot_imm, r_tmp;
cerion98411db2005-02-16 14:14:49 +00004695
4696 if (cond.test == Pct_ALWAYS) {
cerion9e263e32005-03-03 17:21:51 +00004697 // Just load 1 to dst => li dst,1
carll1f5fe1f2014-08-07 23:25:23 +00004698 p = mkFormD(p, 14, r_dst, 0, 1, endness_host);
cerionab9132d2005-02-15 15:46:59 +00004699 } else {
sewardj7e308072011-05-04 09:50:48 +00004700 vassert(cond.flag != Pcf_NONE);
cerion7cf8e4e2005-02-16 16:08:17 +00004701 rot_imm = 1 + cond.flag;
cerion5b2325f2005-12-23 00:55:09 +00004702 r_tmp = 0; // Not set in getAllocable, so no need to declare.
cerion98411db2005-02-16 14:14:49 +00004703
4704 // r_tmp = CR => mfcr r_tmp
carll1f5fe1f2014-08-07 23:25:23 +00004705 p = mkFormX(p, 31, r_tmp, 0, 0, 19, 0, endness_host);
cerion98411db2005-02-16 14:14:49 +00004706
4707 // r_dst = flag (rotate left and mask)
cerion7cf8e4e2005-02-16 16:08:17 +00004708 // => rlwinm r_dst,r_tmp,rot_imm,31,31
carll1f5fe1f2014-08-07 23:25:23 +00004709 p = mkFormM(p, 21, r_tmp, r_dst, rot_imm, 31, 31, 0, endness_host);
cerion98411db2005-02-16 14:14:49 +00004710
4711 if (cond.test == Pct_FALSE) {
ceriona2f75882005-03-15 16:33:38 +00004712 // flip bit => xori r_dst,r_dst,1
carll1f5fe1f2014-08-07 23:25:23 +00004713 p = mkFormD(p, 26, r_dst, r_dst, 1, endness_host);
cerionab9132d2005-02-15 15:46:59 +00004714 }
4715 }
4716 goto done;
cerionab9132d2005-02-15 15:46:59 +00004717 }
cerionb536af92005-02-10 15:03:19 +00004718
sewardjb51f0f42005-07-18 11:38:02 +00004719 case Pin_MfCR:
4720 // mfcr dst
sewardja5b50222015-03-26 07:18:32 +00004721 p = mkFormX(p, 31, iregEnc(i->Pin.MfCR.dst, mode64), 0, 0, 19, 0,
carll1f5fe1f2014-08-07 23:25:23 +00004722 endness_host);
sewardjb51f0f42005-07-18 11:38:02 +00004723 goto done;
4724
cerion98411db2005-02-16 14:14:49 +00004725 case Pin_MFence: {
carll1f5fe1f2014-08-07 23:25:23 +00004726 p = mkFormX(p, 31, 0, 0, 0, 598, 0, endness_host); // sync, PPC32 p616
sewardje9d8a262009-07-01 08:06:34 +00004727 // CAB: Should this be isync?
4728 // p = mkFormXL(p, 19, 0, 0, 0, 150, 0); // isync, PPC32 p467
cerion98411db2005-02-16 14:14:49 +00004729 goto done;
4730 }
cerionb536af92005-02-10 15:03:19 +00004731
ceriond5e38382005-02-11 13:38:15 +00004732 case Pin_Store: {
cerion5b2325f2005-12-23 00:55:09 +00004733 PPCAMode* am_addr = i->Pin.Store.dst;
sewardja5b50222015-03-26 07:18:32 +00004734 UInt r_src = iregEnc(i->Pin.Store.src, mode64);
ceriona2f75882005-03-15 16:33:38 +00004735 UInt opc1, opc2, sz = i->Pin.Store.sz;
ceriond5e38382005-02-11 13:38:15 +00004736 switch (i->Pin.Store.dst->tag) {
4737 case Pam_IR:
sewardj34085e32007-03-09 18:07:00 +00004738 if (mode64 && (sz == 4 || sz == 8)) {
4739 /* should be guaranteed to us by iselWordExpr_AMode */
4740 vassert(0 == (am_addr->Pam.IR.index & 3));
4741 }
cerionf0de28c2005-12-13 20:21:11 +00004742 switch(sz) {
4743 case 1: opc1 = 38; break;
4744 case 2: opc1 = 44; break;
4745 case 4: opc1 = 36; break;
4746 case 8: vassert(mode64);
4747 opc1 = 62; break;
4748 default:
4749 goto bad;
4750 }
carll1f5fe1f2014-08-07 23:25:23 +00004751 p = doAMode_IR(p, opc1, r_src, am_addr, mode64, endness_host);
cerionab9132d2005-02-15 15:46:59 +00004752 goto done;
ceriond5e38382005-02-11 13:38:15 +00004753 case Pam_RR:
cerionf0de28c2005-12-13 20:21:11 +00004754 switch(sz) {
4755 case 1: opc2 = 215; break;
4756 case 2: opc2 = 407; break;
4757 case 4: opc2 = 151; break;
4758 case 8: vassert(mode64);
4759 opc2 = 149; break;
4760 default:
4761 goto bad;
4762 }
carll1f5fe1f2014-08-07 23:25:23 +00004763 p = doAMode_RR(p, 31, opc2, r_src, am_addr, mode64, endness_host);
cerionab9132d2005-02-15 15:46:59 +00004764 goto done;
ceriond5e38382005-02-11 13:38:15 +00004765 default:
cerionab9132d2005-02-15 15:46:59 +00004766 goto bad;
ceriond5e38382005-02-11 13:38:15 +00004767 }
4768 goto done;
4769 }
cerionb536af92005-02-10 15:03:19 +00004770
sewardje9d8a262009-07-01 08:06:34 +00004771 case Pin_StoreC: {
carlld8268892015-04-17 23:42:40 +00004772 if (i->Pin.StoreC.sz == 1) {
4773 p = mkFormX(p, 31, iregEnc(i->Pin.StoreC.src, mode64),
4774 0, iregEnc(i->Pin.StoreC.dst, mode64), 694, 1, endness_host);
4775 goto done;
4776 }
4777 if (i->Pin.StoreC.sz == 2) {
4778 p = mkFormX(p, 31, iregEnc(i->Pin.StoreC.src, mode64),
4779 0, iregEnc(i->Pin.StoreC.dst, mode64), 726, 1, endness_host);
4780 goto done;
4781 }
4782
sewardje9d8a262009-07-01 08:06:34 +00004783 if (i->Pin.StoreC.sz == 4) {
sewardja5b50222015-03-26 07:18:32 +00004784 p = mkFormX(p, 31, iregEnc(i->Pin.StoreC.src, mode64),
4785 0, iregEnc(i->Pin.StoreC.dst, mode64), 150, 1, endness_host);
sewardje9d8a262009-07-01 08:06:34 +00004786 goto done;
4787 }
4788 if (i->Pin.StoreC.sz == 8 && mode64) {
sewardja5b50222015-03-26 07:18:32 +00004789 p = mkFormX(p, 31, iregEnc(i->Pin.StoreC.src, mode64),
4790 0, iregEnc(i->Pin.StoreC.dst, mode64), 214, 1, endness_host);
sewardje9d8a262009-07-01 08:06:34 +00004791 goto done;
4792 }
4793 goto bad;
4794 }
4795
cerion094d1392005-06-20 13:45:57 +00004796 case Pin_FpUnary: {
sewardja5b50222015-03-26 07:18:32 +00004797 UInt fr_dst = fregEnc(i->Pin.FpUnary.dst);
4798 UInt fr_src = fregEnc(i->Pin.FpUnary.src);
cerion094d1392005-06-20 13:45:57 +00004799 switch (i->Pin.FpUnary.op) {
sewardjbaf971a2006-01-27 15:09:35 +00004800 case Pfp_RSQRTE: // frsqrtre, PPC32 p424
carll1f5fe1f2014-08-07 23:25:23 +00004801 p = mkFormA( p, 63, fr_dst, 0, fr_src, 0, 26, 0, endness_host );
sewardjbaf971a2006-01-27 15:09:35 +00004802 break;
4803 case Pfp_RES: // fres, PPC32 p421
carll1f5fe1f2014-08-07 23:25:23 +00004804 p = mkFormA( p, 59, fr_dst, 0, fr_src, 0, 24, 0, endness_host );
sewardjbaf971a2006-01-27 15:09:35 +00004805 break;
cerion094d1392005-06-20 13:45:57 +00004806 case Pfp_SQRT: // fsqrt, PPC32 p427
carll1f5fe1f2014-08-07 23:25:23 +00004807 p = mkFormA( p, 63, fr_dst, 0, fr_src, 0, 22, 0, endness_host );
cerion094d1392005-06-20 13:45:57 +00004808 break;
4809 case Pfp_ABS: // fabs, PPC32 p399
carll1f5fe1f2014-08-07 23:25:23 +00004810 p = mkFormX(p, 63, fr_dst, 0, fr_src, 264, 0, endness_host);
cerion094d1392005-06-20 13:45:57 +00004811 break;
4812 case Pfp_NEG: // fneg, PPC32 p416
carll1f5fe1f2014-08-07 23:25:23 +00004813 p = mkFormX(p, 63, fr_dst, 0, fr_src, 40, 0, endness_host);
cerion094d1392005-06-20 13:45:57 +00004814 break;
4815 case Pfp_MOV: // fmr, PPC32 p410
carll1f5fe1f2014-08-07 23:25:23 +00004816 p = mkFormX(p, 63, fr_dst, 0, fr_src, 72, 0, endness_host);
cerion094d1392005-06-20 13:45:57 +00004817 break;
sewardj0f1ef862008-08-08 08:37:06 +00004818 case Pfp_FRIM: // frim, PPC ISA 2.05 p137
carll1f5fe1f2014-08-07 23:25:23 +00004819 p = mkFormX(p, 63, fr_dst, 0, fr_src, 488, 0, endness_host);
sewardj0f1ef862008-08-08 08:37:06 +00004820 break;
4821 case Pfp_FRIP: // frip, PPC ISA 2.05 p137
carll1f5fe1f2014-08-07 23:25:23 +00004822 p = mkFormX(p, 63, fr_dst, 0, fr_src, 456, 0, endness_host);
sewardj0f1ef862008-08-08 08:37:06 +00004823 break;
4824 case Pfp_FRIN: // frin, PPC ISA 2.05 p137
carll1f5fe1f2014-08-07 23:25:23 +00004825 p = mkFormX(p, 63, fr_dst, 0, fr_src, 392, 0, endness_host);
sewardj0f1ef862008-08-08 08:37:06 +00004826 break;
4827 case Pfp_FRIZ: // friz, PPC ISA 2.05 p137
carll1f5fe1f2014-08-07 23:25:23 +00004828 p = mkFormX(p, 63, fr_dst, 0, fr_src, 424, 0, endness_host);
sewardj0f1ef862008-08-08 08:37:06 +00004829 break;
cerion094d1392005-06-20 13:45:57 +00004830 default:
4831 goto bad;
4832 }
4833 goto done;
4834 }
4835
4836 case Pin_FpBinary: {
sewardja5b50222015-03-26 07:18:32 +00004837 UInt fr_dst = fregEnc(i->Pin.FpBinary.dst);
4838 UInt fr_srcL = fregEnc(i->Pin.FpBinary.srcL);
4839 UInt fr_srcR = fregEnc(i->Pin.FpBinary.srcR);
cerion094d1392005-06-20 13:45:57 +00004840 switch (i->Pin.FpBinary.op) {
sewardjb183b852006-02-03 16:08:03 +00004841 case Pfp_ADDD: // fadd, PPC32 p400
carll1f5fe1f2014-08-07 23:25:23 +00004842 p = mkFormA( p, 63, fr_dst, fr_srcL, fr_srcR, 0, 21, 0, endness_host );
cerion094d1392005-06-20 13:45:57 +00004843 break;
sewardjb183b852006-02-03 16:08:03 +00004844 case Pfp_ADDS: // fadds, PPC32 p401
carll1f5fe1f2014-08-07 23:25:23 +00004845 p = mkFormA( p, 59, fr_dst, fr_srcL, fr_srcR, 0, 21, 0, endness_host );
sewardjb183b852006-02-03 16:08:03 +00004846 break;
4847 case Pfp_SUBD: // fsub, PPC32 p429
carll1f5fe1f2014-08-07 23:25:23 +00004848 p = mkFormA( p, 63, fr_dst, fr_srcL, fr_srcR, 0, 20, 0, endness_host );
cerion094d1392005-06-20 13:45:57 +00004849 break;
sewardjb183b852006-02-03 16:08:03 +00004850 case Pfp_SUBS: // fsubs, PPC32 p430
carll1f5fe1f2014-08-07 23:25:23 +00004851 p = mkFormA( p, 59, fr_dst, fr_srcL, fr_srcR, 0, 20, 0, endness_host );
sewardjb183b852006-02-03 16:08:03 +00004852 break;
4853 case Pfp_MULD: // fmul, PPC32 p413
carll1f5fe1f2014-08-07 23:25:23 +00004854 p = mkFormA( p, 63, fr_dst, fr_srcL, 0, fr_srcR, 25, 0, endness_host );
cerion094d1392005-06-20 13:45:57 +00004855 break;
sewardjb183b852006-02-03 16:08:03 +00004856 case Pfp_MULS: // fmuls, PPC32 p414
carll1f5fe1f2014-08-07 23:25:23 +00004857 p = mkFormA( p, 59, fr_dst, fr_srcL, 0, fr_srcR, 25, 0, endness_host );
sewardjb183b852006-02-03 16:08:03 +00004858 break;
4859 case Pfp_DIVD: // fdiv, PPC32 p406
carll1f5fe1f2014-08-07 23:25:23 +00004860 p = mkFormA( p, 63, fr_dst, fr_srcL, fr_srcR, 0, 18, 0, endness_host );
cerion094d1392005-06-20 13:45:57 +00004861 break;
sewardjb183b852006-02-03 16:08:03 +00004862 case Pfp_DIVS: // fdivs, PPC32 p407
carll1f5fe1f2014-08-07 23:25:23 +00004863 p = mkFormA( p, 59, fr_dst, fr_srcL, fr_srcR, 0, 18, 0, endness_host );
sewardjb183b852006-02-03 16:08:03 +00004864 break;
cerion094d1392005-06-20 13:45:57 +00004865 default:
4866 goto bad;
4867 }
4868 goto done;
4869 }
4870
Elliott Hughesa0664b92017-04-18 17:46:52 -07004871 case Pin_Fp128Unary: {
4872 /* Note Fp128 instructions use the vector scalar registers. The register
4873 * mapping for the V128 type assumes the a vector instruction. The
4874 * PPC hardware has a single register file that the vector scalar
4875 * registers and the vector registers map to. The 32 vector
4876 * registers instructions map to the same registers as the vector
4877 * scalar registers 32 to 63. mkFormVXR0 does the needed
4878 * adjustment.
4879 */
4880 UInt fr_dst = vregEnc(i->Pin.Fp128Unary.dst);
4881 UInt fr_src = vregEnc(i->Pin.Fp128Unary.src);
4882
4883 switch (i->Pin.Fp128Unary.op) {
4884 case Pfp_FPSQRTQ: // xssqrtqp, use rounding specified by RN
4885 p = mkFormVXR0( p, 63, fr_dst, 27, fr_src, 804, 0, endness_host );
4886 break;
4887 case Pfp_FPSQRTQRNDODD: // xssqrtqpo, use rounding specified by RN
4888 p = mkFormVXR0( p, 63, fr_dst, 27, fr_src, 804, 1, endness_host );
4889 break;
4890 case Pfp_FPQTOD: // xscvqpdp, use rounding specified by RN
4891 p = mkFormVXR0( p, 63, fr_dst, 20, fr_src, 836, 0, endness_host );
4892 break;
4893 case Pfp_FPQTODRNDODD: // xscvqpdpo, use rounding specified by RN
4894 p = mkFormVXR0( p, 63, fr_dst, 20, fr_src, 836, 1, endness_host );
4895 break;
4896 case Pfp_FPDTOQ: // xscvdpqp
4897 p = mkFormVXR0( p, 63, fr_dst, 22, fr_src, 836, 0, endness_host );
4898 break;
4899 case Pfp_IDSTOQ: // xscvsdqp
4900 p = mkFormVXR0( p, 63, fr_dst, 10, fr_src, 836, 0, endness_host );
4901 break;
4902 case Pfp_IDUTOQ: // xscvudqp
4903 p = mkFormVXR0( p, 63, fr_dst, 2, fr_src, 836, 0, endness_host );
4904 break;
4905 case Pfp_TRUNCFPQTOISD: // xscvqpsdz
4906 p = mkFormVXR0( p, 63, fr_dst, 25, fr_src, 836, 0, endness_host );
4907 break;
4908 case Pfp_TRUNCFPQTOISW: // xscvqpswz
4909 p = mkFormVXR0( p, 63, fr_dst, 9, fr_src, 836, 0, endness_host );
4910 break;
4911 case Pfp_TRUNCFPQTOIUD: // xscvqpudz
4912 p = mkFormVXR0( p, 63, fr_dst, 17, fr_src, 836, 0, endness_host );
4913 break;
4914 case Pfp_TRUNCFPQTOIUW: // xscvqpuwz
4915 p = mkFormVXR0( p, 63, fr_dst, 1, fr_src, 836, 0, endness_host );
4916 break;
4917 default:
4918 goto bad;
4919 }
4920 goto done;
4921 }
4922
4923 case Pin_Fp128Binary: {
4924 /* Note Fp128 instructions use the vector registers */
4925 UInt fr_dst = vregEnc(i->Pin.Fp128Binary.dst);
4926 UInt fr_srcL = vregEnc(i->Pin.Fp128Binary.srcL);
4927 UInt fr_srcR = vregEnc(i->Pin.Fp128Binary.srcR);
4928
4929 /* Note this issues a Vector scalar instruction. The register
4930 * mapping for the V128 type assumes the a vector instruction. The
4931 * PPC hardware has a single register file that the vector scalar
4932 * registers and the vector registers map to. The 32 vector
4933 * registers instructions map to the same registers as the vector
4934 * scalar registers 32 to 63. For these instructions the HW adds
4935 * 32 to the register numbers to access the VSRR register. No need
4936 * to adjust the numbers to map to the VR register that contians the
4937 * operands.
4938 */
4939
4940 switch (i->Pin.Fp128Binary.op) {
4941 case Pfp_FPADDQ: // xsaddqp, use rounding specified by RN
4942 p = mkFormVXR0( p, 63, fr_dst, fr_srcL, fr_srcR, 4, 0, endness_host );
4943 break;
4944 case Pfp_FPADDQRNDODD: // xsaddqpo, round to odd
4945 p = mkFormVXR0( p, 63, fr_dst, fr_srcL, fr_srcR, 4, 1, endness_host );
4946 break;
4947 case Pfp_FPSUBQ: // xssubqp, use rounding specified by RN
4948 p = mkFormVXR0( p, 63, fr_dst, fr_srcL, fr_srcR, 516, 0, endness_host );
4949 break;
4950 case Pfp_FPSUBQRNDODD: // xssubqpo, round to odd
4951 p = mkFormVXR0( p, 63, fr_dst, fr_srcL, fr_srcR, 516, 1, endness_host );
4952 break;
4953 case Pfp_FPMULQ: // xsmulqp, use rounding specified by RN
4954 p = mkFormVXR0( p, 63, fr_dst, fr_srcL, fr_srcR, 36, 0, endness_host );
4955 break;
4956 case Pfp_FPMULQRNDODD: // xsmulqpo, round to odd
4957 p = mkFormVXR0( p, 63, fr_dst, fr_srcL, fr_srcR, 36, 1, endness_host );
4958 break;
4959 case Pfp_FPDIVQ: // xsdivqp, use rounding specified by RN
4960 p = mkFormVXR0( p, 63, fr_dst, fr_srcL, fr_srcR, 548, 0, endness_host );
4961 break;
4962 case Pfp_FPDIVQRNDODD: // xsdivqpo, round to odd
4963 p = mkFormVXR0( p, 63, fr_dst, fr_srcL, fr_srcR, 548, 1, endness_host );
4964 break;
4965 case Pfp_FPMULADDQ: // xsmaddqp, use rounding specified by RN
4966 p = mkFormVXR0( p, 63, fr_dst, fr_srcL, fr_srcR, 388, 0, endness_host );
4967 break;
4968 case Pfp_FPMULADDQRNDODD: // xsmaddqpo, round to odd
4969 p = mkFormVXR0( p, 63, fr_dst, fr_srcL, fr_srcR, 388, 1, endness_host );
4970 break;
4971 case Pfp_FPMULSUBQ: // xsmsubqp, use rounding specified by RN
4972 p = mkFormVXR0( p, 63, fr_dst, fr_srcL, fr_srcR, 420, 0, endness_host );
4973 break;
4974 case Pfp_FPMULSUBQRNDODD: // xsmsubsqpo, round to odd
4975 p = mkFormVXR0( p, 63, fr_dst, fr_srcL, fr_srcR, 420, 1, endness_host );
4976 break;
4977 case Pfp_FPNEGMULADDQ: // xsnmaddqp, use rounding specified by RN
4978 p = mkFormVXR0( p, 63, fr_dst, fr_srcL, fr_srcR, 452, 0, endness_host );
4979 break;
4980 case Pfp_FPNEGMULADDQRNDODD: // xsnmaddqpo, round to odd
4981 p = mkFormVXR0( p, 63, fr_dst, fr_srcL, fr_srcR, 452, 1, endness_host );
4982 break;
4983 case Pfp_FPNEGMULSUBQ: // xsnmsubqp, use rounding specified by RN
4984 p = mkFormVXR0( p, 63, fr_dst, fr_srcL, fr_srcR, 484, 0, endness_host );
4985 break;
4986 case Pfp_FPNEGMULSUBQRNDODD: // xsnmsubsqpo, round to odd
4987 p = mkFormVXR0( p, 63, fr_dst, fr_srcL, fr_srcR, 484, 1, endness_host );
4988 break;
4989 default:
4990 goto bad;
4991 }
4992 goto done;
4993 }
4994
4995 case Pin_Fp128Trinary: {
4996 /* Note Fp128 instructions use the vector registers */
4997 UInt fr_dst = vregEnc(i->Pin.Fp128Binary.dst);
4998 UInt fr_srcL = vregEnc(i->Pin.Fp128Binary.srcL);
4999 UInt fr_srcR = vregEnc(i->Pin.Fp128Binary.srcR);
5000
5001 /* Note this issues a Vector scalar instruction. The register
5002 * mapping for the V128 type assumes the a vector instruction. The
5003 * PPC hardware has a single register file that the vector scalar
5004 * registers and the vector registers map to. The 32 vector
5005 * registers instructions map to the same registers as the vector
5006 * scalar registers 32 to 63. For these instructions the HW adds
5007 * 32 to the register numbers to access the VSRR register. No need
5008 * to adjust the numbers to map to the VR register that contians the
5009 * operands.
5010 */
5011
5012 switch (i->Pin.Fp128Binary.op) {
5013 case Pfp_FPMULADDQ: // xsmaddqp, use rounding specified by RN
5014 p = mkFormVXR0( p, 63, fr_dst, fr_srcL, fr_srcR, 388, 0, endness_host );
5015 break;
5016 case Pfp_FPMULADDQRNDODD: // xsmaddqpo, round to odd
5017 p = mkFormVXR0( p, 63, fr_dst, fr_srcL, fr_srcR, 388, 1, endness_host );
5018 break;
5019 case Pfp_FPMULSUBQ: // xsmsubqp, use rounding specified by RN
5020 p = mkFormVXR0( p, 63, fr_dst, fr_srcL, fr_srcR, 420, 0, endness_host );
5021 break;
5022 case Pfp_FPMULSUBQRNDODD: // xsmsubsqpo, round to odd
5023 p = mkFormVXR0( p, 63, fr_dst, fr_srcL, fr_srcR, 420, 1, endness_host );
5024 break;
5025 case Pfp_FPNEGMULADDQ: // xsnmaddqp, use rounding specified by RN
5026 p = mkFormVXR0( p, 63, fr_dst, fr_srcL, fr_srcR, 452, 0, endness_host );
5027 break;
5028 case Pfp_FPNEGMULADDQRNDODD: // xsnmaddqpo, round to odd
5029 p = mkFormVXR0( p, 63, fr_dst, fr_srcL, fr_srcR, 452, 1, endness_host );
5030 break;
5031 case Pfp_FPNEGMULSUBQ: // xsnmsubqp, use rounding specified by RN
5032 p = mkFormVXR0( p, 63, fr_dst, fr_srcL, fr_srcR, 484, 0, endness_host );
5033 break;
5034 case Pfp_FPNEGMULSUBQRNDODD: // xsnmsubsqpo, round to odd
5035 p = mkFormVXR0( p, 63, fr_dst, fr_srcL, fr_srcR, 484, 1, endness_host );
5036 break;
5037 default:
5038 goto bad;
5039 }
5040 goto done;
5041 }
5042
sewardj40c80262006-02-08 19:30:46 +00005043 case Pin_FpMulAcc: {
sewardja5b50222015-03-26 07:18:32 +00005044 UInt fr_dst = fregEnc(i->Pin.FpMulAcc.dst);
5045 UInt fr_srcML = fregEnc(i->Pin.FpMulAcc.srcML);
5046 UInt fr_srcMR = fregEnc(i->Pin.FpMulAcc.srcMR);
5047 UInt fr_srcAcc = fregEnc(i->Pin.FpMulAcc.srcAcc);
sewardj40c80262006-02-08 19:30:46 +00005048 switch (i->Pin.FpMulAcc.op) {
5049 case Pfp_MADDD: // fmadd, PPC32 p408
carll1f5fe1f2014-08-07 23:25:23 +00005050 p = mkFormA( p, 63, fr_dst, fr_srcML, fr_srcAcc, fr_srcMR, 29, 0,
5051 endness_host );
sewardj40c80262006-02-08 19:30:46 +00005052 break;
5053 case Pfp_MADDS: // fmadds, PPC32 p409
carll1f5fe1f2014-08-07 23:25:23 +00005054 p = mkFormA( p, 59, fr_dst, fr_srcML, fr_srcAcc, fr_srcMR, 29, 0,
5055 endness_host );
sewardj40c80262006-02-08 19:30:46 +00005056 break;
5057 case Pfp_MSUBD: // fmsub, PPC32 p411
carll1f5fe1f2014-08-07 23:25:23 +00005058 p = mkFormA( p, 63, fr_dst, fr_srcML, fr_srcAcc, fr_srcMR, 28, 0,
5059 endness_host );
sewardj40c80262006-02-08 19:30:46 +00005060 break;
5061 case Pfp_MSUBS: // fmsubs, PPC32 p412
carll1f5fe1f2014-08-07 23:25:23 +00005062 p = mkFormA( p, 59, fr_dst, fr_srcML, fr_srcAcc, fr_srcMR, 28, 0,
5063 endness_host );
sewardj40c80262006-02-08 19:30:46 +00005064 break;
5065 default:
5066 goto bad;
5067 }
5068 goto done;
5069 }
5070
cerion094d1392005-06-20 13:45:57 +00005071 case Pin_FpLdSt: {
cerion5b2325f2005-12-23 00:55:09 +00005072 PPCAMode* am_addr = i->Pin.FpLdSt.addr;
sewardja5b50222015-03-26 07:18:32 +00005073 UInt f_reg = fregEnc(i->Pin.FpLdSt.reg);
cerion094d1392005-06-20 13:45:57 +00005074 Bool idxd = toBool(i->Pin.FpLdSt.addr->tag == Pam_RR);
5075 UChar sz = i->Pin.FpLdSt.sz;
cerionf0de28c2005-12-13 20:21:11 +00005076 UInt opc;
cerion094d1392005-06-20 13:45:57 +00005077 vassert(sz == 4 || sz == 8);
5078
5079 if (i->Pin.FpLdSt.isLoad) { // Load from memory
5080 if (idxd) { // lf[s|d]x, PPC32 p444|440
cerionf0de28c2005-12-13 20:21:11 +00005081 opc = (sz == 4) ? 535 : 599;
carll1f5fe1f2014-08-07 23:25:23 +00005082 p = doAMode_RR(p, 31, opc, f_reg, am_addr, mode64, endness_host);
cerion094d1392005-06-20 13:45:57 +00005083 } else { // lf[s|d], PPC32 p441|437
cerionf0de28c2005-12-13 20:21:11 +00005084 opc = (sz == 4) ? 48 : 50;
carll1f5fe1f2014-08-07 23:25:23 +00005085 p = doAMode_IR(p, opc, f_reg, am_addr, mode64, endness_host);
cerion094d1392005-06-20 13:45:57 +00005086 }
5087 } else { // Store to memory
5088 if (idxd) { // stf[s|d]x, PPC32 p521|516
cerionf0de28c2005-12-13 20:21:11 +00005089 opc = (sz == 4) ? 663 : 727;
carll1f5fe1f2014-08-07 23:25:23 +00005090 p = doAMode_RR(p, 31, opc, f_reg, am_addr, mode64, endness_host);
cerion094d1392005-06-20 13:45:57 +00005091 } else { // stf[s|d], PPC32 p518|513
cerionf0de28c2005-12-13 20:21:11 +00005092 opc = (sz == 4) ? 52 : 54;
carll1f5fe1f2014-08-07 23:25:23 +00005093 p = doAMode_IR(p, opc, f_reg, am_addr, mode64, endness_host);
cerion094d1392005-06-20 13:45:57 +00005094 }
5095 }
5096 goto done;
5097 }
5098
sewardj92923de2006-01-25 21:29:48 +00005099 case Pin_FpSTFIW: {
sewardja5b50222015-03-26 07:18:32 +00005100 UInt ir_addr = iregEnc(i->Pin.FpSTFIW.addr, mode64);
5101 UInt fr_data = fregEnc(i->Pin.FpSTFIW.data);
sewardj92923de2006-01-25 21:29:48 +00005102 // stfiwx (store fp64[lo32] as int32), PPC32 p517
5103 // Use rA==0, so that EA == rB == ir_addr
carll1f5fe1f2014-08-07 23:25:23 +00005104 p = mkFormX(p, 31, fr_data, 0/*rA=0*/, ir_addr, 983, 0, endness_host);
sewardj92923de2006-01-25 21:29:48 +00005105 goto done;
5106 }
5107
5108 case Pin_FpRSP: {
sewardja5b50222015-03-26 07:18:32 +00005109 UInt fr_dst = fregEnc(i->Pin.FpRSP.dst);
5110 UInt fr_src = fregEnc(i->Pin.FpRSP.src);
cerion094d1392005-06-20 13:45:57 +00005111 // frsp, PPC32 p423
carll1f5fe1f2014-08-07 23:25:23 +00005112 p = mkFormX(p, 63, fr_dst, 0, fr_src, 12, 0, endness_host);
cerion094d1392005-06-20 13:45:57 +00005113 goto done;
5114 }
5115
sewardj92923de2006-01-25 21:29:48 +00005116 case Pin_FpCftI: {
sewardja5b50222015-03-26 07:18:32 +00005117 UInt fr_dst = fregEnc(i->Pin.FpCftI.dst);
5118 UInt fr_src = fregEnc(i->Pin.FpCftI.src);
sewardj92923de2006-01-25 21:29:48 +00005119 if (i->Pin.FpCftI.fromI == False && i->Pin.FpCftI.int32 == True) {
sewardj4aa412a2011-07-24 14:13:21 +00005120 if (i->Pin.FpCftI.syned == True) {
5121 // fctiw (conv f64 to i32), PPC32 p404
carll1f5fe1f2014-08-07 23:25:23 +00005122 p = mkFormX(p, 63, fr_dst, 0, fr_src, 14, 0, endness_host);
sewardj4aa412a2011-07-24 14:13:21 +00005123 goto done;
5124 } else {
5125 // fctiwu (conv f64 to u32)
carll1f5fe1f2014-08-07 23:25:23 +00005126 p = mkFormX(p, 63, fr_dst, 0, fr_src, 142, 0, endness_host);
sewardj4aa412a2011-07-24 14:13:21 +00005127 goto done;
5128 }
sewardj92923de2006-01-25 21:29:48 +00005129 }
sewardj7fd5bb02006-01-26 02:24:17 +00005130 if (i->Pin.FpCftI.fromI == False && i->Pin.FpCftI.int32 == False) {
sewardj4aa412a2011-07-24 14:13:21 +00005131 if (i->Pin.FpCftI.syned == True) {
5132 // fctid (conv f64 to i64), PPC64 p437
carll1f5fe1f2014-08-07 23:25:23 +00005133 p = mkFormX(p, 63, fr_dst, 0, fr_src, 814, 0, endness_host);
sewardj4aa412a2011-07-24 14:13:21 +00005134 goto done;
5135 } else {
5136 // fctidu (conv f64 to u64)
carll1f5fe1f2014-08-07 23:25:23 +00005137 p = mkFormX(p, 63, fr_dst, 0, fr_src, 942, 0, endness_host);
sewardj4aa412a2011-07-24 14:13:21 +00005138 goto done;
5139 }
sewardj7fd5bb02006-01-26 02:24:17 +00005140 }
5141 if (i->Pin.FpCftI.fromI == True && i->Pin.FpCftI.int32 == False) {
sewardj66d5ef22011-04-15 11:55:00 +00005142 if (i->Pin.FpCftI.syned == True) {
5143 // fcfid (conv i64 to f64), PPC64 p434
carll1f5fe1f2014-08-07 23:25:23 +00005144 p = mkFormX(p, 63, fr_dst, 0, fr_src, 846, 0, endness_host);
sewardj66d5ef22011-04-15 11:55:00 +00005145 goto done;
sewardj7d810d72011-05-08 22:05:10 +00005146 } else if (i->Pin.FpCftI.flt64 == True) {
sewardj66d5ef22011-04-15 11:55:00 +00005147 // fcfidu (conv u64 to f64)
carll1f5fe1f2014-08-07 23:25:23 +00005148 p = mkFormX(p, 63, fr_dst, 0, fr_src, 974, 0, endness_host);
sewardj66d5ef22011-04-15 11:55:00 +00005149 goto done;
5150 } else {
5151 // fcfidus (conv u64 to f32)
carll1f5fe1f2014-08-07 23:25:23 +00005152 p = mkFormX(p, 59, fr_dst, 0, fr_src, 974, 0, endness_host);
sewardj66d5ef22011-04-15 11:55:00 +00005153 goto done;
5154 }
sewardj7fd5bb02006-01-26 02:24:17 +00005155 }
sewardj92923de2006-01-25 21:29:48 +00005156 goto bad;
cerion094d1392005-06-20 13:45:57 +00005157 }
5158
5159 case Pin_FpCMov: {
sewardja5b50222015-03-26 07:18:32 +00005160 UInt fr_dst = fregEnc(i->Pin.FpCMov.dst);
5161 UInt fr_src = fregEnc(i->Pin.FpCMov.src);
cerion5b2325f2005-12-23 00:55:09 +00005162 PPCCondCode cc = i->Pin.FpCMov.cond;
cerion094d1392005-06-20 13:45:57 +00005163
5164 if (fr_dst == fr_src) goto done;
5165
5166 vassert(cc.test != Pct_ALWAYS);
5167
5168 /* jmp fwds if !condition */
5169 if (cc.test != Pct_ALWAYS) {
5170 /* bc !ct,cf,n_bytes>>2 */
carll1f5fe1f2014-08-07 23:25:23 +00005171 p = mkFormB(p, invertCondTest(cc.test), cc.flag, 8>>2, 0, 0,
5172 endness_host);
cerion094d1392005-06-20 13:45:57 +00005173 }
5174
5175 // fmr, PPC32 p410
carll1f5fe1f2014-08-07 23:25:23 +00005176 p = mkFormX(p, 63, fr_dst, 0, fr_src, 72, 0, endness_host);
cerion094d1392005-06-20 13:45:57 +00005177 goto done;
5178 }
5179
5180 case Pin_FpLdFPSCR: {
sewardja5b50222015-03-26 07:18:32 +00005181 UInt fr_src = fregEnc(i->Pin.FpLdFPSCR.src);
carll1f5fe1f2014-08-07 23:25:23 +00005182 p = mkFormXFL(p, 0xFF, fr_src, i->Pin.FpLdFPSCR.dfp_rm, endness_host); // mtfsf, PPC32 p480
cerion094d1392005-06-20 13:45:57 +00005183 goto done;
5184 }
5185
5186 case Pin_FpCmp: {
sewardjb51f0f42005-07-18 11:38:02 +00005187 UChar crfD = 1;
sewardja5b50222015-03-26 07:18:32 +00005188 UInt r_dst = iregEnc(i->Pin.FpCmp.dst, mode64);
5189 UInt fr_srcL = fregEnc(i->Pin.FpCmp.srcL);
5190 UInt fr_srcR = fregEnc(i->Pin.FpCmp.srcR);
cerion094d1392005-06-20 13:45:57 +00005191 vassert(crfD < 8);
5192 // fcmpo, PPC32 p402
carll1f5fe1f2014-08-07 23:25:23 +00005193 p = mkFormX(p, 63, crfD<<2, fr_srcL, fr_srcR, 32, 0, endness_host);
cerion094d1392005-06-20 13:45:57 +00005194
5195 // mfcr (mv CR to r_dst), PPC32 p467
carll1f5fe1f2014-08-07 23:25:23 +00005196 p = mkFormX(p, 31, r_dst, 0, 0, 19, 0, endness_host);
cerion094d1392005-06-20 13:45:57 +00005197
5198 // rlwinm r_dst,r_dst,8,28,31, PPC32 p501
sewardjb51f0f42005-07-18 11:38:02 +00005199 // => rotate field 1 to bottomw of word, masking out upper 28
carll1f5fe1f2014-08-07 23:25:23 +00005200 p = mkFormM(p, 21, r_dst, r_dst, 8, 28, 31, 0, endness_host);
cerion094d1392005-06-20 13:45:57 +00005201 goto done;
5202 }
cerionbcf8c3e2005-02-04 16:17:07 +00005203
cerion7f000af2005-02-22 20:36:49 +00005204 case Pin_RdWrLR: {
sewardja5b50222015-03-26 07:18:32 +00005205 UInt reg = iregEnc(i->Pin.RdWrLR.gpr, mode64);
cerion7f000af2005-02-22 20:36:49 +00005206 /* wrLR==True ? mtlr r4 : mflr r4 */
carll1f5fe1f2014-08-07 23:25:23 +00005207 p = mkFormXFX(p, reg, 8, (i->Pin.RdWrLR.wrLR==True) ? 467 : 339,
5208 endness_host);
cerion7f000af2005-02-22 20:36:49 +00005209 goto done;
5210 }
5211
cerionc3d8bdc2005-06-28 18:06:23 +00005212
5213 /* AltiVec */
5214 case Pin_AvLdSt: {
5215 UInt opc2, v_reg, r_idx, r_base;
5216 UChar sz = i->Pin.AvLdSt.sz;
5217 Bool idxd = toBool(i->Pin.AvLdSt.addr->tag == Pam_RR);
cerion225a0342005-09-12 20:49:09 +00005218 vassert(sz == 1 || sz == 2 || sz == 4 || sz == 16);
cerionc3d8bdc2005-06-28 18:06:23 +00005219
sewardja5b50222015-03-26 07:18:32 +00005220 v_reg = vregEnc(i->Pin.AvLdSt.reg);
5221 r_base = iregEnc(i->Pin.AvLdSt.addr->Pam.RR.base, mode64);
cerionc3d8bdc2005-06-28 18:06:23 +00005222
5223 // Only have AltiVec AMode_RR: kludge AMode_IR
5224 if (!idxd) {
5225 r_idx = 30; // XXX: Using r30 as temp
cerion5b2325f2005-12-23 00:55:09 +00005226 p = mkLoadImm(p, r_idx,
carll1f5fe1f2014-08-07 23:25:23 +00005227 i->Pin.AvLdSt.addr->Pam.IR.index, mode64, endness_host);
cerionc3d8bdc2005-06-28 18:06:23 +00005228 } else {
sewardja5b50222015-03-26 07:18:32 +00005229 r_idx = iregEnc(i->Pin.AvLdSt.addr->Pam.RR.index, mode64);
cerionc3d8bdc2005-06-28 18:06:23 +00005230 }
5231
cerion225a0342005-09-12 20:49:09 +00005232 if (i->Pin.FpLdSt.isLoad) { // Load from memory (1,2,4,16)
cerion5b2325f2005-12-23 00:55:09 +00005233 opc2 = (sz==1) ? 7 : (sz==2) ? 39 : (sz==4) ? 71 : 103;
carll1f5fe1f2014-08-07 23:25:23 +00005234 p = mkFormX(p, 31, v_reg, r_idx, r_base, opc2, 0, endness_host);
cerion225a0342005-09-12 20:49:09 +00005235 } else { // Store to memory (1,2,4,16)
cerion5b2325f2005-12-23 00:55:09 +00005236 opc2 = (sz==1) ? 135 : (sz==2) ? 167 : (sz==4) ? 199 : 231;
carll1f5fe1f2014-08-07 23:25:23 +00005237 p = mkFormX(p, 31, v_reg, r_idx, r_base, opc2, 0, endness_host);
cerionc3d8bdc2005-06-28 18:06:23 +00005238 }
5239 goto done;
5240 }
5241
5242 case Pin_AvUnary: {
sewardja5b50222015-03-26 07:18:32 +00005243 UInt v_dst = vregEnc(i->Pin.AvUnary.dst);
5244 UInt v_src = vregEnc(i->Pin.AvUnary.src);
Elliott Hughesa0664b92017-04-18 17:46:52 -07005245 UInt opc2 = 0xFFFFFFFF, opc3 = 0xFFFFFFFF; /* invalid */
5246
cerionc3d8bdc2005-06-28 18:06:23 +00005247 switch (i->Pin.AvUnary.op) {
5248 case Pav_MOV: opc2 = 1156; break; // vor vD,vS,vS
5249 case Pav_NOT: opc2 = 1284; break; // vnor vD,vS,vS
5250 case Pav_UNPCKH8S: opc2 = 526; break; // vupkhsb
5251 case Pav_UNPCKH16S: opc2 = 590; break; // vupkhsh
5252 case Pav_UNPCKL8S: opc2 = 654; break; // vupklsb
5253 case Pav_UNPCKL16S: opc2 = 718; break; // vupklsh
5254 case Pav_UNPCKHPIX: opc2 = 846; break; // vupkhpx
5255 case Pav_UNPCKLPIX: opc2 = 974; break; // vupklpx
carll7deaf952013-10-15 18:11:20 +00005256
5257 case Pav_ZEROCNTBYTE: opc2 = 1794; break; // vclzb
5258 case Pav_ZEROCNTHALF: opc2 = 1858; break; // vclzh
5259 case Pav_ZEROCNTWORD: opc2 = 1922; break; // vclzw
5260 case Pav_ZEROCNTDBL: opc2 = 1986; break; // vclzd
Elliott Hughesa0664b92017-04-18 17:46:52 -07005261 case Pav_TRAILINGZEROCNTBYTE: opc2 = 1538; break; // vctzb
5262 case Pav_TRAILINGZEROCNTHALF: opc2 = 1538; break; // vctzh
5263 case Pav_TRAILINGZEROCNTWORD: opc2 = 1538; break; // vctzw
5264 case Pav_TRAILINGZEROCNTDBL: opc2 = 1538; break; // vctzd
carll60c6bac2013-10-18 01:19:06 +00005265 case Pav_BITMTXXPOSE: opc2 = 1292; break; // vgbbd
Elliott Hughesa0664b92017-04-18 17:46:52 -07005266 case Pav_BCD128toI128S: opc2 = 385; break; //bcdctsq.
5267 case Pav_MulI128by10: opc2 = 513; break; // vmul10uq
5268 case Pav_MulI128by10Carry: opc2 = 1; break; // vmul10cuq
5269 case Pav_F16toF64x2: opc2 = 347; opc3 = 16; break; // xvcvhpdp
5270 case Pav_F64toF16x2: opc2 = 347; opc3 = 17; break; // xvcvdphp
5271 case Pav_F16toF32x4: opc2 = 475; opc3 = 24; break; // xvcvhpsp
5272 case Pav_F32toF16x4: opc2 = 475; opc3 = 25; break; // xvcvsphp
5273
cerionc3d8bdc2005-06-28 18:06:23 +00005274 default:
5275 goto bad;
5276 }
5277 switch (i->Pin.AvUnary.op) {
5278 case Pav_MOV:
5279 case Pav_NOT:
carll1f5fe1f2014-08-07 23:25:23 +00005280 p = mkFormVX( p, 4, v_dst, v_src, v_src, opc2, endness_host );
cerionc3d8bdc2005-06-28 18:06:23 +00005281 break;
Elliott Hughesa0664b92017-04-18 17:46:52 -07005282 case Pav_F16toF32x4:
5283 {
5284 /* I64 source has four 16-bit float values in the upper 64-bit
5285 * of the source vector register, lower 64-bits are undefined.
5286 */
5287 /* Scatter the four F16 values in the Vector register */
5288 p = mkFormVX( p, 4, v_dst, 0, v_src, 590, endness_host );// vupkhsh
5289
5290 /* The layout of the vector register is now: S0F0 S1F1 S2F2 S3F3
5291 * where S is the sign extension of the 16-bit F value. We don't
5292 * care about the extended signs.
5293 */
5294
5295 /* Input, in v_dst, is now correct for the xvcvhpsp instruction */
5296 p = mkFormVX_BX_TX( p, 60, v_dst, opc3, v_dst, opc2,
5297 endness_host );
5298 }
5299 break;
5300 case Pav_F64toF16x2:
5301 case Pav_F16toF64x2:
5302 case Pav_F32toF16x4:
5303 /* Note this issues a Vector scalar instruction. The register
5304 * mapping for the V128 type assumes the a vector instruction. The
5305 * PPC hardware has a single register file that the vector scalar
5306 * registers and the vector registers map to. The 32 vector registers
5307 * instructions map to the same registers as the vector scalar
5308 * registers 32 to 63. mkFormVX_BX_TX does the needed adjustment.
5309 */
5310 p = mkFormVX_BX_TX( p, 60, v_dst, opc3, v_src, opc2, endness_host );
5311 break;
5312 case Pav_BCD128toI128S: // bcdctsq
5313 p = mkFormVX( p, 4, v_dst, 0, v_src, (1<<10 | 385), endness_host );
5314 break;
5315 case Pav_MulI128by10:
5316 case Pav_MulI128by10Carry:
5317 p = mkFormVX( p, 4, v_dst, v_src, 0, opc2, endness_host );
5318 break;
5319 case Pav_TRAILINGZEROCNTBYTE:
5320 p = mkFormVX( p, 4, v_dst, 28, v_src, opc2, endness_host );
5321 break;
5322 case Pav_TRAILINGZEROCNTHALF:
5323 p = mkFormVX( p, 4, v_dst, 29, v_src, opc2, endness_host );
5324 break;
5325 case Pav_TRAILINGZEROCNTWORD:
5326 p = mkFormVX( p, 4, v_dst, 30, v_src, opc2, endness_host );
5327 break;
5328 case Pav_TRAILINGZEROCNTDBL:
5329 p = mkFormVX( p, 4, v_dst, 31, v_src, opc2, endness_host );
5330 break;
cerionc3d8bdc2005-06-28 18:06:23 +00005331 default:
carll1f5fe1f2014-08-07 23:25:23 +00005332 p = mkFormVX( p, 4, v_dst, 0, v_src, opc2, endness_host );
cerion8ea0d3e2005-11-14 00:44:47 +00005333 break;
cerionc3d8bdc2005-06-28 18:06:23 +00005334 }
5335 goto done;
5336 }
5337
5338 case Pin_AvBinary: {
sewardja5b50222015-03-26 07:18:32 +00005339 UInt v_dst = vregEnc(i->Pin.AvBinary.dst);
5340 UInt v_srcL = vregEnc(i->Pin.AvBinary.srcL);
5341 UInt v_srcR = vregEnc(i->Pin.AvBinary.srcR);
cerionc3d8bdc2005-06-28 18:06:23 +00005342 UInt opc2;
cerion27b3d7e2005-09-14 20:35:47 +00005343 if (i->Pin.AvBinary.op == Pav_SHL) {
carll1f5fe1f2014-08-07 23:25:23 +00005344 p = mkFormVX( p, 4, v_dst, v_srcL, v_srcR, 1036, endness_host ); // vslo
5345 p = mkFormVX( p, 4, v_dst, v_dst, v_srcR, 452, endness_host ); // vsl
cerion27b3d7e2005-09-14 20:35:47 +00005346 goto done;
5347 }
5348 if (i->Pin.AvBinary.op == Pav_SHR) {
carll1f5fe1f2014-08-07 23:25:23 +00005349 p = mkFormVX( p, 4, v_dst, v_srcL, v_srcR, 1100, endness_host ); // vsro
5350 p = mkFormVX( p, 4, v_dst, v_dst, v_srcR, 708, endness_host ); // vsr
cerion27b3d7e2005-09-14 20:35:47 +00005351 goto done;
5352 }
cerionc3d8bdc2005-06-28 18:06:23 +00005353 switch (i->Pin.AvBinary.op) {
5354 /* Bitwise */
cerion225a0342005-09-12 20:49:09 +00005355 case Pav_AND: opc2 = 1028; break; // vand
cerionc3d8bdc2005-06-28 18:06:23 +00005356 case Pav_OR: opc2 = 1156; break; // vor
cerion225a0342005-09-12 20:49:09 +00005357 case Pav_XOR: opc2 = 1220; break; // vxor
Elliott Hughesa0664b92017-04-18 17:46:52 -07005358 /* Mult by 10 */
5359 case Pav_MulI128by10E: opc2 = 577; break; // vmul10euq
5360 case Pav_MulI128by10ECarry: opc2 = 65; break; // vmul10ecuq
cerionc3d8bdc2005-06-28 18:06:23 +00005361 default:
5362 goto bad;
5363 }
carll1f5fe1f2014-08-07 23:25:23 +00005364 p = mkFormVX( p, 4, v_dst, v_srcL, v_srcR, opc2, endness_host );
cerionc3d8bdc2005-06-28 18:06:23 +00005365 goto done;
5366 }
5367
Elliott Hughesa0664b92017-04-18 17:46:52 -07005368 case Pin_AvBinaryInt: {
5369 UInt ps = i->Pin.AvBinaryInt.val->Pri.Imm;
5370 UInt dst = vregEnc(i->Pin.AvBinaryInt.dst);
5371 UInt src = vregEnc(i->Pin.AvBinaryInt.src);
5372
5373 switch (i->Pin.AvBinaryInt.op) {
5374 /* BCD */
5375 case Pav_I128StoBCD128: // bcdcfsq
5376 {
5377 /* v_srcR actually contains the value of the one-bit ps field */
5378 int opc2 = 385;
5379 p = mkFormVX( p, 4, dst, 2, src,
5380 (1 << 10 | (ps << 9) | opc2), endness_host );
5381 }
5382 break;
5383
5384 case Pav_F128toI128S: // xsrqpi, xsrqpix
5385 {
5386 int opc2 = 5;
5387 UInt EX = ps & 0x1;
5388 UInt R = (ps >> 3) & 0x1;
5389 UInt RMC = (ps >> 1) & 0x3;
5390 /* Note this issues a Vector scalar instruction. The register
5391 * mapping for the V128 type assumes the a vector instruction. The
5392 * PPC hardware has a single register file that the vector scalar
5393 * registers and the vector registers map to. The 32 vector
5394 * registers instructions map to the same registers as the vector
5395 * scalar registers 32 to 63. For these instructions the HW adds
5396 * 32 to the register numbers to access the VSRR register. No need
5397 * to adjust the numbers to map to the VR register that contians
5398 * the operands.
5399 */
5400 p = mkFormVSXRND( p, 63, R, dst, src, RMC, opc2, EX,
5401 endness_host );
5402 }
5403 break;
5404
5405 case Pav_ROUNDFPQ: // xsrqpxp
5406 {
5407 int opc2 = 37;
5408 UInt EX = ps & 0x1;
5409 UInt RMC = (ps >> 1) & 0x3;
5410 UInt R = (ps >> 3) & 0x1;
5411 p = mkFormVSXRND( p, 63, R, dst, src, RMC, opc2, EX,
5412 endness_host );
5413 }
5414 break;
5415
5416 default:
5417 goto bad;
5418
5419 }
5420 goto done;
5421 }
5422
cerion6b6f59e2005-06-28 20:59:18 +00005423 case Pin_AvBin8x16: {
sewardja5b50222015-03-26 07:18:32 +00005424 UInt v_dst = vregEnc(i->Pin.AvBin8x16.dst);
5425 UInt v_srcL = vregEnc(i->Pin.AvBin8x16.srcL);
5426 UInt v_srcR = vregEnc(i->Pin.AvBin8x16.srcR);
cerion6b6f59e2005-06-28 20:59:18 +00005427 UInt opc2;
5428 switch (i->Pin.AvBin8x16.op) {
5429
cerionf34ccc42005-09-16 08:55:50 +00005430 case Pav_ADDU: opc2 = 0; break; // vaddubm
5431 case Pav_QADDU: opc2 = 512; break; // vaddubs
5432 case Pav_QADDS: opc2 = 768; break; // vaddsbs
cerion6b6f59e2005-06-28 20:59:18 +00005433
cerionf34ccc42005-09-16 08:55:50 +00005434 case Pav_SUBU: opc2 = 1024; break; // vsububm
5435 case Pav_QSUBU: opc2 = 1536; break; // vsububs
5436 case Pav_QSUBS: opc2 = 1792; break; // vsubsbs
cerion6b6f59e2005-06-28 20:59:18 +00005437
cerion1ac656a2005-11-04 19:44:48 +00005438 case Pav_OMULU: opc2 = 8; break; // vmuloub
5439 case Pav_OMULS: opc2 = 264; break; // vmulosb
5440 case Pav_EMULU: opc2 = 520; break; // vmuleub
5441 case Pav_EMULS: opc2 = 776; break; // vmulesb
5442
cerion6b6f59e2005-06-28 20:59:18 +00005443 case Pav_AVGU: opc2 = 1026; break; // vavgub
5444 case Pav_AVGS: opc2 = 1282; break; // vavgsb
5445 case Pav_MAXU: opc2 = 2; break; // vmaxub
5446 case Pav_MAXS: opc2 = 258; break; // vmaxsb
5447 case Pav_MINU: opc2 = 514; break; // vminub
5448 case Pav_MINS: opc2 = 770; break; // vminsb
5449
5450 case Pav_CMPEQU: opc2 = 6; break; // vcmpequb
5451 case Pav_CMPGTU: opc2 = 518; break; // vcmpgtub
5452 case Pav_CMPGTS: opc2 = 774; break; // vcmpgtsb
5453
5454 case Pav_SHL: opc2 = 260; break; // vslb
5455 case Pav_SHR: opc2 = 516; break; // vsrb
5456 case Pav_SAR: opc2 = 772; break; // vsrab
5457 case Pav_ROTL: opc2 = 4; break; // vrlb
5458
5459 case Pav_MRGHI: opc2 = 12; break; // vmrghb
5460 case Pav_MRGLO: opc2 = 268; break; // vmrglb
5461
carll7deaf952013-10-15 18:11:20 +00005462 case Pav_POLYMULADD: opc2 = 1032; break; // vpmsumb
5463
cerion6b6f59e2005-06-28 20:59:18 +00005464 default:
5465 goto bad;
5466 }
carll1f5fe1f2014-08-07 23:25:23 +00005467 p = mkFormVX( p, 4, v_dst, v_srcL, v_srcR, opc2, endness_host );
cerion6b6f59e2005-06-28 20:59:18 +00005468 goto done;
5469 }
5470
5471 case Pin_AvBin16x8: {
sewardja5b50222015-03-26 07:18:32 +00005472 UInt v_dst = vregEnc(i->Pin.AvBin16x8.dst);
5473 UInt v_srcL = vregEnc(i->Pin.AvBin16x8.srcL);
5474 UInt v_srcR = vregEnc(i->Pin.AvBin16x8.srcR);
cerion6b6f59e2005-06-28 20:59:18 +00005475 UInt opc2;
5476 switch (i->Pin.AvBin16x8.op) {
5477
cerionf34ccc42005-09-16 08:55:50 +00005478 case Pav_ADDU: opc2 = 64; break; // vadduhm
5479 case Pav_QADDU: opc2 = 576; break; // vadduhs
5480 case Pav_QADDS: opc2 = 832; break; // vaddshs
cerion6b6f59e2005-06-28 20:59:18 +00005481
cerionf34ccc42005-09-16 08:55:50 +00005482 case Pav_SUBU: opc2 = 1088; break; // vsubuhm
5483 case Pav_QSUBU: opc2 = 1600; break; // vsubuhs
5484 case Pav_QSUBS: opc2 = 1856; break; // vsubshs
cerion6b6f59e2005-06-28 20:59:18 +00005485
cerion1ac656a2005-11-04 19:44:48 +00005486 case Pav_OMULU: opc2 = 72; break; // vmulouh
5487 case Pav_OMULS: opc2 = 328; break; // vmulosh
5488 case Pav_EMULU: opc2 = 584; break; // vmuleuh
5489 case Pav_EMULS: opc2 = 840; break; // vmulesh
cerion6b6f59e2005-06-28 20:59:18 +00005490
5491 case Pav_AVGU: opc2 = 1090; break; // vavguh
5492 case Pav_AVGS: opc2 = 1346; break; // vavgsh
5493 case Pav_MAXU: opc2 = 66; break; // vmaxuh
5494 case Pav_MAXS: opc2 = 322; break; // vmaxsh
5495 case Pav_MINS: opc2 = 834; break; // vminsh
5496 case Pav_MINU: opc2 = 578; break; // vminuh
5497
5498 case Pav_CMPEQU: opc2 = 70; break; // vcmpequh
5499 case Pav_CMPGTU: opc2 = 582; break; // vcmpgtuh
5500 case Pav_CMPGTS: opc2 = 838; break; // vcmpgtsh
5501
5502 case Pav_SHL: opc2 = 324; break; // vslh
5503 case Pav_SHR: opc2 = 580; break; // vsrh
5504 case Pav_SAR: opc2 = 836; break; // vsrah
5505 case Pav_ROTL: opc2 = 68; break; // vrlh
5506
cerionf34ccc42005-09-16 08:55:50 +00005507 case Pav_PACKUU: opc2 = 14; break; // vpkuhum
5508 case Pav_QPACKUU: opc2 = 142; break; // vpkuhus
5509 case Pav_QPACKSU: opc2 = 270; break; // vpkshus
5510 case Pav_QPACKSS: opc2 = 398; break; // vpkshss
5511 case Pav_PACKPXL: opc2 = 782; break; // vpkpx
cerion6b6f59e2005-06-28 20:59:18 +00005512
5513 case Pav_MRGHI: opc2 = 76; break; // vmrghh
5514 case Pav_MRGLO: opc2 = 332; break; // vmrglh
5515
carll7deaf952013-10-15 18:11:20 +00005516 case Pav_POLYMULADD: opc2 = 1224; break; // vpmsumh
5517
cerion6b6f59e2005-06-28 20:59:18 +00005518 default:
5519 goto bad;
5520 }
carll1f5fe1f2014-08-07 23:25:23 +00005521 p = mkFormVX( p, 4, v_dst, v_srcL, v_srcR, opc2, endness_host );
cerion6b6f59e2005-06-28 20:59:18 +00005522 goto done;
5523 }
5524
5525 case Pin_AvBin32x4: {
sewardja5b50222015-03-26 07:18:32 +00005526 UInt v_dst = vregEnc(i->Pin.AvBin32x4.dst);
5527 UInt v_srcL = vregEnc(i->Pin.AvBin32x4.srcL);
5528 UInt v_srcR = vregEnc(i->Pin.AvBin32x4.srcR);
cerion6b6f59e2005-06-28 20:59:18 +00005529 UInt opc2;
5530 switch (i->Pin.AvBin32x4.op) {
5531
cerionf34ccc42005-09-16 08:55:50 +00005532 case Pav_ADDU: opc2 = 128; break; // vadduwm
5533 case Pav_QADDU: opc2 = 640; break; // vadduws
5534 case Pav_QADDS: opc2 = 896; break; // vaddsws
cerion6b6f59e2005-06-28 20:59:18 +00005535
cerionf34ccc42005-09-16 08:55:50 +00005536 case Pav_SUBU: opc2 = 1152; break; // vsubuwm
5537 case Pav_QSUBU: opc2 = 1664; break; // vsubuws
5538 case Pav_QSUBS: opc2 = 1920; break; // vsubsws
cerion6b6f59e2005-06-28 20:59:18 +00005539
carll48ae46b2013-10-01 15:45:54 +00005540 case Pav_MULU: opc2 = 137; break; // vmuluwm
5541 case Pav_OMULU: opc2 = 136; break; // vmulouw
5542 case Pav_OMULS: opc2 = 392; break; // vmulosw
5543 case Pav_EMULU: opc2 = 648; break; // vmuleuw
5544 case Pav_EMULS: opc2 = 904; break; // vmulesw
5545
cerion6b6f59e2005-06-28 20:59:18 +00005546 case Pav_AVGU: opc2 = 1154; break; // vavguw
5547 case Pav_AVGS: opc2 = 1410; break; // vavgsw
5548
5549 case Pav_MAXU: opc2 = 130; break; // vmaxuw
5550 case Pav_MAXS: opc2 = 386; break; // vmaxsw
5551
5552 case Pav_MINS: opc2 = 898; break; // vminsw
5553 case Pav_MINU: opc2 = 642; break; // vminuw
5554
5555 case Pav_CMPEQU: opc2 = 134; break; // vcmpequw
5556 case Pav_CMPGTS: opc2 = 902; break; // vcmpgtsw
5557 case Pav_CMPGTU: opc2 = 646; break; // vcmpgtuw
5558
5559 case Pav_SHL: opc2 = 388; break; // vslw
5560 case Pav_SHR: opc2 = 644; break; // vsrw
5561 case Pav_SAR: opc2 = 900; break; // vsraw
5562 case Pav_ROTL: opc2 = 132; break; // vrlw
5563
cerionf34ccc42005-09-16 08:55:50 +00005564 case Pav_PACKUU: opc2 = 78; break; // vpkuwum
5565 case Pav_QPACKUU: opc2 = 206; break; // vpkuwus
5566 case Pav_QPACKSU: opc2 = 334; break; // vpkswus
5567 case Pav_QPACKSS: opc2 = 462; break; // vpkswss
cerion6b6f59e2005-06-28 20:59:18 +00005568
5569 case Pav_MRGHI: opc2 = 140; break; // vmrghw
5570 case Pav_MRGLO: opc2 = 396; break; // vmrglw
5571
carll48ae46b2013-10-01 15:45:54 +00005572 case Pav_CATODD: opc2 = 1676; break; // vmrgow
5573 case Pav_CATEVEN: opc2 = 1932; break; // vmrgew
5574
carll7deaf952013-10-15 18:11:20 +00005575 case Pav_POLYMULADD: opc2 = 1160; break; // vpmsumw
5576
cerion6b6f59e2005-06-28 20:59:18 +00005577 default:
5578 goto bad;
5579 }
carll1f5fe1f2014-08-07 23:25:23 +00005580 p = mkFormVX( p, 4, v_dst, v_srcL, v_srcR, opc2, endness_host );
cerion6b6f59e2005-06-28 20:59:18 +00005581 goto done;
5582 }
5583
carll0c74bb52013-08-12 18:01:40 +00005584 case Pin_AvBin64x2: {
sewardja5b50222015-03-26 07:18:32 +00005585 UInt v_dst = vregEnc(i->Pin.AvBin64x2.dst);
5586 UInt v_srcL = vregEnc(i->Pin.AvBin64x2.srcL);
5587 UInt v_srcR = vregEnc(i->Pin.AvBin64x2.srcR);
carll0c74bb52013-08-12 18:01:40 +00005588 UInt opc2;
5589 switch (i->Pin.AvBin64x2.op) {
carll48ae46b2013-10-01 15:45:54 +00005590 case Pav_ADDU: opc2 = 192; break; // vaddudm vector double add
5591 case Pav_SUBU: opc2 = 1216; break; // vsubudm vector double add
5592 case Pav_MAXU: opc2 = 194; break; // vmaxud vector double max
5593 case Pav_MAXS: opc2 = 450; break; // vmaxsd vector double max
5594 case Pav_MINU: opc2 = 706; break; // vminud vector double min
5595 case Pav_MINS: opc2 = 962; break; // vminsd vector double min
5596 case Pav_CMPEQU: opc2 = 199; break; // vcmpequd vector double compare
5597 case Pav_CMPGTU: opc2 = 711; break; // vcmpgtud vector double compare
5598 case Pav_CMPGTS: opc2 = 967; break; // vcmpgtsd vector double compare
5599 case Pav_SHL: opc2 = 1476; break; // vsld
5600 case Pav_SHR: opc2 = 1732; break; // vsrd
5601 case Pav_SAR: opc2 = 964; break; // vsrad
5602 case Pav_ROTL: opc2 = 196; break; // vrld
5603 case Pav_PACKUU: opc2 = 1102; break; // vpkudum
5604 case Pav_QPACKUU: opc2 = 1230; break; // vpkudus, vpksdus (emulated)
5605 case Pav_QPACKSS: opc2 = 1486; break; // vpksdsm
5606 case Pav_MRGHI: opc2 = 1614; break; // vmrghw
5607 case Pav_MRGLO: opc2 = 1742; break; // vmrglw
carll7deaf952013-10-15 18:11:20 +00005608 case Pav_POLYMULADD: opc2 = 1096; break; // vpmsumd
carll48ae46b2013-10-01 15:45:54 +00005609 default:
5610 goto bad;
carll0c74bb52013-08-12 18:01:40 +00005611 }
carll1f5fe1f2014-08-07 23:25:23 +00005612 p = mkFormVX( p, 4, v_dst, v_srcL, v_srcR, opc2, endness_host );
carll0c74bb52013-08-12 18:01:40 +00005613 goto done;
5614 }
carll7deaf952013-10-15 18:11:20 +00005615 case Pin_AvCipherV128Unary: {
sewardja5b50222015-03-26 07:18:32 +00005616 UInt v_dst = vregEnc(i->Pin.AvCipherV128Unary.dst);
5617 UInt v_src = vregEnc(i->Pin.AvCipherV128Unary.src);
carll7deaf952013-10-15 18:11:20 +00005618 UInt opc2;
5619 switch (i->Pin.AvCipherV128Unary.op) {
5620 case Pav_CIPHERSUBV128: opc2 = 1480; break; // vsbox
5621 default:
5622 goto bad;
5623 }
carll1f5fe1f2014-08-07 23:25:23 +00005624 p = mkFormVX( p, 4, v_dst, v_src, 0, opc2, endness_host );
carll7deaf952013-10-15 18:11:20 +00005625 goto done;
5626 }
5627 case Pin_AvCipherV128Binary: {
sewardja5b50222015-03-26 07:18:32 +00005628 UInt v_dst = vregEnc(i->Pin.AvCipherV128Binary.dst);
5629 UInt v_srcL = vregEnc(i->Pin.AvCipherV128Binary.srcL);
5630 UInt v_srcR = vregEnc(i->Pin.AvCipherV128Binary.srcR);
carll7deaf952013-10-15 18:11:20 +00005631 UInt opc2;
5632 switch (i->Pin.AvCipherV128Binary.op) {
5633 case Pav_CIPHERV128: opc2 = 1288; break; // vcipher
5634 case Pav_CIPHERLV128: opc2 = 1289; break; // vcipherlast
5635 case Pav_NCIPHERV128: opc2 = 1352; break; // vncipher
5636 case Pav_NCIPHERLV128: opc2 = 1353; break; // vncipherlast
5637 default:
5638 goto bad;
5639 }
carll1f5fe1f2014-08-07 23:25:23 +00005640 p = mkFormVX( p, 4, v_dst, v_srcL, v_srcR, opc2, endness_host );
carll7deaf952013-10-15 18:11:20 +00005641 goto done;
5642 }
5643 case Pin_AvHashV128Binary: {
sewardja5b50222015-03-26 07:18:32 +00005644 UInt v_dst = vregEnc(i->Pin.AvHashV128Binary.dst);
5645 UInt v_src = vregEnc(i->Pin.AvHashV128Binary.src);
carll7deaf952013-10-15 18:11:20 +00005646 PPCRI* s_field = i->Pin.AvHashV128Binary.s_field;
5647 UInt opc2;
5648 switch (i->Pin.AvHashV128Binary.op) {
5649 case Pav_SHA256: opc2 = 1666; break; // vshasigmaw
5650 case Pav_SHA512: opc2 = 1730; break; // vshasigmad
5651 default:
5652 goto bad;
5653 }
carll1f5fe1f2014-08-07 23:25:23 +00005654 p = mkFormVX( p, 4, v_dst, v_src, s_field->Pri.Imm, opc2, endness_host );
carll7deaf952013-10-15 18:11:20 +00005655 goto done;
5656 }
Elliott Hughesa0664b92017-04-18 17:46:52 -07005657 case Pin_AvBCDV128Binary: {
5658 UInt v_dst = vregEnc(i->Pin.AvBCDV128Binary.dst);
5659 UInt v_src1 = vregEnc(i->Pin.AvBCDV128Binary.src1);
5660 UInt v_src2 = vregEnc(i->Pin.AvBCDV128Binary.src2);
5661 UInt ps = 0; /* Issue the instruction with ps=0. The IR code will
5662 * fix up the result if ps=1.
5663 */
carll7deaf952013-10-15 18:11:20 +00005664 UInt opc2;
Elliott Hughesa0664b92017-04-18 17:46:52 -07005665 switch (i->Pin.AvBCDV128Binary.op) {
carll7deaf952013-10-15 18:11:20 +00005666 case Pav_BCDAdd: opc2 = 1; break; // bcdadd
5667 case Pav_BCDSub: opc2 = 65; break; // bcdsub
5668 default:
5669 goto bad;
5670 }
5671 p = mkFormVXR( p, 4, v_dst, v_src1, v_src2,
Elliott Hughesa0664b92017-04-18 17:46:52 -07005672 0x1, ps | opc2, endness_host );
carll7deaf952013-10-15 18:11:20 +00005673 goto done;
5674 }
cerion6b6f59e2005-06-28 20:59:18 +00005675 case Pin_AvBin32Fx4: {
sewardja5b50222015-03-26 07:18:32 +00005676 UInt v_dst = vregEnc(i->Pin.AvBin32Fx4.dst);
5677 UInt v_srcL = vregEnc(i->Pin.AvBin32Fx4.srcL);
5678 UInt v_srcR = vregEnc(i->Pin.AvBin32Fx4.srcR);
cerion6b6f59e2005-06-28 20:59:18 +00005679 switch (i->Pin.AvBin32Fx4.op) {
5680
cerion8ea0d3e2005-11-14 00:44:47 +00005681 case Pavfp_ADDF:
carll1f5fe1f2014-08-07 23:25:23 +00005682 p = mkFormVX( p, 4, v_dst, v_srcL, v_srcR, 10, endness_host ); // vaddfp
cerion6b6f59e2005-06-28 20:59:18 +00005683 break;
cerion8ea0d3e2005-11-14 00:44:47 +00005684 case Pavfp_SUBF:
carll1f5fe1f2014-08-07 23:25:23 +00005685 p = mkFormVX( p, 4, v_dst, v_srcL, v_srcR, 74, endness_host ); // vsubfp
cerion6b6f59e2005-06-28 20:59:18 +00005686 break;
cerion8ea0d3e2005-11-14 00:44:47 +00005687 case Pavfp_MAXF:
carll1f5fe1f2014-08-07 23:25:23 +00005688 p = mkFormVX( p, 4, v_dst, v_srcL, v_srcR, 1034, endness_host ); // vmaxfp
cerion6b6f59e2005-06-28 20:59:18 +00005689 break;
cerion8ea0d3e2005-11-14 00:44:47 +00005690 case Pavfp_MINF:
carll1f5fe1f2014-08-07 23:25:23 +00005691 p = mkFormVX( p, 4, v_dst, v_srcL, v_srcR, 1098, endness_host ); // vminfp
cerion6b6f59e2005-06-28 20:59:18 +00005692 break;
5693
cerion8ea0d3e2005-11-14 00:44:47 +00005694 case Pavfp_MULF: {
cerion6b6f59e2005-06-28 20:59:18 +00005695 /* Make a vmulfp from a vmaddfp:
5696 load -0.0 (0x8000_0000) to each 32-bit word of vB
5697 this makes the add a noop.
5698 */
sewardjf7745052005-12-16 01:06:42 +00005699 UInt vB = 29; // XXX: Using v29 for temp do not change
5700 // without also changing
cerion5b2325f2005-12-23 00:55:09 +00005701 // getRegUsage_PPCInstr
cerion8ea0d3e2005-11-14 00:44:47 +00005702 UInt konst = 0x1F;
cerion6b6f59e2005-06-28 20:59:18 +00005703
ceriond963eb42005-11-16 18:02:58 +00005704 // Better way to load -0.0 (0x80000000) ?
cerion6b6f59e2005-06-28 20:59:18 +00005705 // vspltisw vB,0x1F (0x1F => each word of vB)
carll1f5fe1f2014-08-07 23:25:23 +00005706 p = mkFormVX( p, 4, vB, konst, 0, 908, endness_host );
cerion6b6f59e2005-06-28 20:59:18 +00005707
cerion5b2325f2005-12-23 00:55:09 +00005708 // vslw vB,vB,vB (each word of vB = (0x1F << 0x1F) = 0x80000000
carll1f5fe1f2014-08-07 23:25:23 +00005709 p = mkFormVX( p, 4, vB, vB, vB, 388, endness_host );
cerion6b6f59e2005-06-28 20:59:18 +00005710
5711 // Finally, do the multiply:
carll1f5fe1f2014-08-07 23:25:23 +00005712 p = mkFormVA( p, 4, v_dst, v_srcL, vB, v_srcR, 46, endness_host );
cerion36991ef2005-09-15 12:42:16 +00005713 break;
cerion6b6f59e2005-06-28 20:59:18 +00005714 }
cerion5b2325f2005-12-23 00:55:09 +00005715 case Pavfp_CMPEQF: // vcmpeqfp
carll1f5fe1f2014-08-07 23:25:23 +00005716 p = mkFormVXR( p, 4, v_dst, v_srcL, v_srcR, 0, 198, endness_host);
cerion36991ef2005-09-15 12:42:16 +00005717 break;
cerion5b2325f2005-12-23 00:55:09 +00005718 case Pavfp_CMPGTF: // vcmpgtfp
carll1f5fe1f2014-08-07 23:25:23 +00005719 p = mkFormVXR( p, 4, v_dst, v_srcL, v_srcR, 0, 710, endness_host );
cerion36991ef2005-09-15 12:42:16 +00005720 break;
cerion5b2325f2005-12-23 00:55:09 +00005721 case Pavfp_CMPGEF: // vcmpgefp
carll1f5fe1f2014-08-07 23:25:23 +00005722 p = mkFormVXR( p, 4, v_dst, v_srcL, v_srcR, 0, 454, endness_host );
cerion36991ef2005-09-15 12:42:16 +00005723 break;
cerion6b6f59e2005-06-28 20:59:18 +00005724
5725 default:
5726 goto bad;
5727 }
5728 goto done;
5729 }
5730
cerion8ea0d3e2005-11-14 00:44:47 +00005731 case Pin_AvUn32Fx4: {
sewardja5b50222015-03-26 07:18:32 +00005732 UInt v_dst = vregEnc(i->Pin.AvUn32Fx4.dst);
5733 UInt v_src = vregEnc(i->Pin.AvUn32Fx4.src);
cerion8ea0d3e2005-11-14 00:44:47 +00005734 UInt opc2;
5735 switch (i->Pin.AvUn32Fx4.op) {
ceriond963eb42005-11-16 18:02:58 +00005736 case Pavfp_RCPF: opc2 = 266; break; // vrefp
5737 case Pavfp_RSQRTF: opc2 = 330; break; // vrsqrtefp
5738 case Pavfp_CVTU2F: opc2 = 778; break; // vcfux
5739 case Pavfp_CVTS2F: opc2 = 842; break; // vcfsx
5740 case Pavfp_QCVTF2U: opc2 = 906; break; // vctuxs
5741 case Pavfp_QCVTF2S: opc2 = 970; break; // vctsxs
5742 case Pavfp_ROUNDM: opc2 = 714; break; // vrfim
5743 case Pavfp_ROUNDP: opc2 = 650; break; // vrfip
5744 case Pavfp_ROUNDN: opc2 = 522; break; // vrfin
5745 case Pavfp_ROUNDZ: opc2 = 586; break; // vrfiz
cerion8ea0d3e2005-11-14 00:44:47 +00005746 default:
5747 goto bad;
5748 }
carll1f5fe1f2014-08-07 23:25:23 +00005749 p = mkFormVX( p, 4, v_dst, 0, v_src, opc2, endness_host );
cerion8ea0d3e2005-11-14 00:44:47 +00005750 goto done;
5751 }
5752
cerionc3d8bdc2005-06-28 18:06:23 +00005753 case Pin_AvPerm: { // vperm
sewardja5b50222015-03-26 07:18:32 +00005754 UInt v_dst = vregEnc(i->Pin.AvPerm.dst);
5755 UInt v_srcL = vregEnc(i->Pin.AvPerm.srcL);
5756 UInt v_srcR = vregEnc(i->Pin.AvPerm.srcR);
5757 UInt v_ctl = vregEnc(i->Pin.AvPerm.ctl);
carll1f5fe1f2014-08-07 23:25:23 +00005758 p = mkFormVA( p, 4, v_dst, v_srcL, v_srcR, v_ctl, 43, endness_host );
cerionc3d8bdc2005-06-28 18:06:23 +00005759 goto done;
5760 }
5761
5762 case Pin_AvSel: { // vsel
sewardja5b50222015-03-26 07:18:32 +00005763 UInt v_ctl = vregEnc(i->Pin.AvSel.ctl);
5764 UInt v_dst = vregEnc(i->Pin.AvSel.dst);
5765 UInt v_srcL = vregEnc(i->Pin.AvSel.srcL);
5766 UInt v_srcR = vregEnc(i->Pin.AvSel.srcR);
carll1f5fe1f2014-08-07 23:25:23 +00005767 p = mkFormVA( p, 4, v_dst, v_srcL, v_srcR, v_ctl, 42, endness_host );
cerionc3d8bdc2005-06-28 18:06:23 +00005768 goto done;
5769 }
5770
carll9877fe52014-10-07 17:49:14 +00005771 case Pin_AvSh: { // vsl or vsr
sewardja5b50222015-03-26 07:18:32 +00005772 UInt v_dst = vregEnc(i->Pin.AvSh.dst);
carll9877fe52014-10-07 17:49:14 +00005773 Bool idxd = toBool(i->Pin.AvSh.addr->tag == Pam_RR);
5774 UInt r_idx, r_base;
5775
sewardja5b50222015-03-26 07:18:32 +00005776 r_base = iregEnc(i->Pin.AvSh.addr->Pam.RR.base, mode64);
carll9877fe52014-10-07 17:49:14 +00005777
5778 if (!idxd) {
carll99de41e2014-10-07 18:20:39 +00005779 r_idx = 30; // XXX: Using r30 as temp
carll9877fe52014-10-07 17:49:14 +00005780 p = mkLoadImm(p, r_idx,
5781 i->Pin.AvSh.addr->Pam.IR.index, mode64, endness_host);
5782 } else {
sewardja5b50222015-03-26 07:18:32 +00005783 r_idx = iregEnc(i->Pin.AvSh.addr->Pam.RR.index, mode64);
carll9877fe52014-10-07 17:49:14 +00005784 }
5785
5786 if (i->Pin.AvSh.shLeft)
5787 //vsl VRT,RA,RB
5788 p = mkFormVXI( p, 31, v_dst, r_idx, r_base, 6, endness_host );
5789 else
5790 //vsr VRT,RA,RB
5791 p = mkFormVXI( p, 31, v_dst, r_idx, r_base, 38, endness_host );
5792 goto done;
5793 }
5794
cerionc3d8bdc2005-06-28 18:06:23 +00005795 case Pin_AvShlDbl: { // vsldoi
5796 UInt shift = i->Pin.AvShlDbl.shift;
sewardja5b50222015-03-26 07:18:32 +00005797 UInt v_dst = vregEnc(i->Pin.AvShlDbl.dst);
5798 UInt v_srcL = vregEnc(i->Pin.AvShlDbl.srcL);
5799 UInt v_srcR = vregEnc(i->Pin.AvShlDbl.srcR);
cerionc3d8bdc2005-06-28 18:06:23 +00005800 vassert(shift <= 0xF);
carll1f5fe1f2014-08-07 23:25:23 +00005801 p = mkFormVA( p, 4, v_dst, v_srcL, v_srcR, shift, 44, endness_host );
cerionc3d8bdc2005-06-28 18:06:23 +00005802 goto done;
5803 }
5804
5805 case Pin_AvSplat: { // vsplt(is)(b,h,w)
sewardja5b50222015-03-26 07:18:32 +00005806 UInt v_dst = vregEnc(i->Pin.AvShlDbl.dst);
cerionc3d8bdc2005-06-28 18:06:23 +00005807 UChar sz = i->Pin.AvSplat.sz;
cerion27b3d7e2005-09-14 20:35:47 +00005808 UInt v_src, opc2;
cerionc3d8bdc2005-06-28 18:06:23 +00005809 vassert(sz == 8 || sz == 16 || sz == 32);
5810
cerion27b3d7e2005-09-14 20:35:47 +00005811 if (i->Pin.AvSplat.src->tag == Pvi_Imm) {
sewardj197bd172005-10-12 11:34:33 +00005812 Char simm5;
cerion6b6f59e2005-06-28 20:59:18 +00005813 opc2 = (sz == 8) ? 780 : (sz == 16) ? 844 : 908; // 8,16,32
cerion27b3d7e2005-09-14 20:35:47 +00005814 /* expects 5-bit-signed-imm */
sewardj197bd172005-10-12 11:34:33 +00005815 simm5 = i->Pin.AvSplat.src->Pvi.Imm5s;
cerion27b3d7e2005-09-14 20:35:47 +00005816 vassert(simm5 >= -16 && simm5 <= 15);
ceriond3e52412005-09-14 21:15:40 +00005817 simm5 = simm5 & 0x1F;
carll1f5fe1f2014-08-07 23:25:23 +00005818 p = mkFormVX( p, 4, v_dst, (UInt)simm5, 0, opc2, endness_host );
cerion27b3d7e2005-09-14 20:35:47 +00005819 }
5820 else { // Pri_Reg
sewardj197bd172005-10-12 11:34:33 +00005821 UInt lowest_lane;
cerionc3d8bdc2005-06-28 18:06:23 +00005822 opc2 = (sz == 8) ? 524 : (sz == 16) ? 588 : 652; // 8,16,32
cerion27b3d7e2005-09-14 20:35:47 +00005823 vassert(hregClass(i->Pin.AvSplat.src->Pvi.Reg) == HRcVec128);
sewardja5b50222015-03-26 07:18:32 +00005824 v_src = vregEnc(i->Pin.AvSplat.src->Pvi.Reg);
sewardj197bd172005-10-12 11:34:33 +00005825 lowest_lane = (128/sz)-1;
carll1f5fe1f2014-08-07 23:25:23 +00005826 p = mkFormVX( p, 4, v_dst, lowest_lane, v_src, opc2, endness_host );
cerionc3d8bdc2005-06-28 18:06:23 +00005827 }
5828 goto done;
5829 }
5830
cerion6b6f59e2005-06-28 20:59:18 +00005831 case Pin_AvCMov: {
sewardja5b50222015-03-26 07:18:32 +00005832 UInt v_dst = vregEnc(i->Pin.AvCMov.dst);
5833 UInt v_src = vregEnc(i->Pin.AvCMov.src);
cerion5b2325f2005-12-23 00:55:09 +00005834 PPCCondCode cc = i->Pin.AvCMov.cond;
cerion6b6f59e2005-06-28 20:59:18 +00005835
5836 if (v_dst == v_src) goto done;
5837
5838 vassert(cc.test != Pct_ALWAYS);
5839
5840 /* jmp fwds 2 insns if !condition */
5841 if (cc.test != Pct_ALWAYS) {
5842 /* bc !ct,cf,n_bytes>>2 */
carll1f5fe1f2014-08-07 23:25:23 +00005843 p = mkFormB(p, invertCondTest(cc.test), cc.flag, 8>>2, 0, 0,
5844 endness_host);
cerion6b6f59e2005-06-28 20:59:18 +00005845 }
5846 /* vmr */
carll1f5fe1f2014-08-07 23:25:23 +00005847 p = mkFormVX( p, 4, v_dst, v_src, v_src, 1156, endness_host );
cerion6b6f59e2005-06-28 20:59:18 +00005848 goto done;
5849 }
5850
cerionc3d8bdc2005-06-28 18:06:23 +00005851 case Pin_AvLdVSCR: { // mtvscr
sewardja5b50222015-03-26 07:18:32 +00005852 UInt v_src = vregEnc(i->Pin.AvLdVSCR.src);
carll1f5fe1f2014-08-07 23:25:23 +00005853 p = mkFormVX( p, 4, 0, 0, v_src, 1604, endness_host );
cerionc3d8bdc2005-06-28 18:06:23 +00005854 goto done;
5855 }
5856
sewardjc6bbd472012-04-02 10:20:48 +00005857 case Pin_Dfp64Unary: {
sewardja5b50222015-03-26 07:18:32 +00005858 UInt fr_dst = fregEnc( i->Pin.FpUnary.dst );
5859 UInt fr_src = fregEnc( i->Pin.FpUnary.src );
sewardjc6bbd472012-04-02 10:20:48 +00005860
5861 switch (i->Pin.Dfp64Unary.op) {
5862 case Pfp_MOV: // fmr, PPC32 p410
carll1f5fe1f2014-08-07 23:25:23 +00005863 p = mkFormX( p, 63, fr_dst, 0, fr_src, 72, 0, endness_host );
sewardjc6bbd472012-04-02 10:20:48 +00005864 break;
sewardj26217b02012-04-12 17:19:48 +00005865 case Pfp_DCTDP: // D32 to D64
carll1f5fe1f2014-08-07 23:25:23 +00005866 p = mkFormX( p, 59, fr_dst, 0, fr_src, 258, 0, endness_host );
sewardj26217b02012-04-12 17:19:48 +00005867 break;
5868 case Pfp_DRSP: // D64 to D32
carll1f5fe1f2014-08-07 23:25:23 +00005869 p = mkFormX( p, 59, fr_dst, 0, fr_src, 770, 0, endness_host );
sewardj26217b02012-04-12 17:19:48 +00005870 break;
5871 case Pfp_DCFFIX: // I64 to D64 conversion
5872 /* ONLY WORKS ON POWER7 */
carll1f5fe1f2014-08-07 23:25:23 +00005873 p = mkFormX( p, 59, fr_dst, 0, fr_src, 802, 0, endness_host );
sewardj26217b02012-04-12 17:19:48 +00005874 break;
5875 case Pfp_DCTFIX: // D64 to I64 conversion
carll1f5fe1f2014-08-07 23:25:23 +00005876 p = mkFormX( p, 59, fr_dst, 0, fr_src, 290, 0, endness_host );
sewardj26217b02012-04-12 17:19:48 +00005877 break;
sewardjcdc376d2012-04-23 11:21:12 +00005878 case Pfp_DXEX: // Extract exponent
carll1f5fe1f2014-08-07 23:25:23 +00005879 p = mkFormX( p, 59, fr_dst, 0, fr_src, 354, 0, endness_host );
sewardjcdc376d2012-04-23 11:21:12 +00005880 break;
sewardjc6bbd472012-04-02 10:20:48 +00005881 default:
5882 goto bad;
5883 }
5884 goto done;
5885 }
5886
5887 case Pin_Dfp64Binary: {
sewardja5b50222015-03-26 07:18:32 +00005888 UInt fr_dst = fregEnc( i->Pin.Dfp64Binary.dst );
5889 UInt fr_srcL = fregEnc( i->Pin.Dfp64Binary.srcL );
5890 UInt fr_srcR = fregEnc( i->Pin.Dfp64Binary.srcR );
sewardjc6bbd472012-04-02 10:20:48 +00005891 switch (i->Pin.Dfp64Binary.op) {
5892 case Pfp_DFPADD: /* dadd, dfp add, use default RM from reg ignore mode
5893 * from the Iop instruction. */
carll1f5fe1f2014-08-07 23:25:23 +00005894 p = mkFormX( p, 59, fr_dst, fr_srcL, fr_srcR, 2, 0, endness_host );
sewardjc6bbd472012-04-02 10:20:48 +00005895 break;
5896 case Pfp_DFPSUB: /* dsub, dfp subtract, use default RM from reg ignore
5897 * mode from the Iop instruction. */
carll1f5fe1f2014-08-07 23:25:23 +00005898 p = mkFormX( p, 59, fr_dst, fr_srcL, fr_srcR, 514, 0, endness_host );
sewardjc6bbd472012-04-02 10:20:48 +00005899 break;
5900 case Pfp_DFPMUL: /* dmul, dfp multipy, use default RM from reg ignore
5901 * mode from the Iop instruction. */
carll1f5fe1f2014-08-07 23:25:23 +00005902 p = mkFormX( p, 59, fr_dst, fr_srcL, fr_srcR, 34, 0, endness_host );
sewardjc6bbd472012-04-02 10:20:48 +00005903 break;
5904 case Pfp_DFPDIV: /* ddiv, dfp divide, use default RM from reg ignore
5905 * mode from the Iop instruction. */
carll1f5fe1f2014-08-07 23:25:23 +00005906 p = mkFormX( p, 59, fr_dst, fr_srcL, fr_srcR, 546, 0, endness_host );
sewardjc6bbd472012-04-02 10:20:48 +00005907 break;
sewardjcdc376d2012-04-23 11:21:12 +00005908 case Pfp_DIEX: /* diex, insert exponent */
carll1f5fe1f2014-08-07 23:25:23 +00005909 p = mkFormX( p, 59, fr_dst, fr_srcL, fr_srcR, 866, 0, endness_host );
sewardjcdc376d2012-04-23 11:21:12 +00005910 break;
sewardjc6bbd472012-04-02 10:20:48 +00005911 default:
5912 goto bad;
5913 }
5914 goto done;
5915 }
5916
sewardj26217b02012-04-12 17:19:48 +00005917 case Pin_DfpShift: {
sewardja5b50222015-03-26 07:18:32 +00005918 UInt fr_src = fregEnc(i->Pin.DfpShift.src);
5919 UInt fr_dst = fregEnc(i->Pin.DfpShift.dst);
sewardj26217b02012-04-12 17:19:48 +00005920 UInt shift;
5921
5922 shift = i->Pin.DfpShift.shift->Pri.Imm;
5923
5924 switch (i->Pin.DfpShift.op) {
5925 case Pfp_DSCLI: /* dscli, DFP shift left by fr_srcR */
carll1f5fe1f2014-08-07 23:25:23 +00005926 p = mkFormZ22( p, 59, fr_dst, fr_src, shift, 66, 0, endness_host );
sewardj26217b02012-04-12 17:19:48 +00005927 break;
5928 case Pfp_DSCRI: /* dscri, DFP shift right by fr_srcR */
carll1f5fe1f2014-08-07 23:25:23 +00005929 p = mkFormZ22( p, 59, fr_dst, fr_src, shift, 98, 0, endness_host );
sewardj26217b02012-04-12 17:19:48 +00005930 break;
5931 default:
5932 vex_printf("ERROR: emit_PPCInstr default case\n");
5933 goto bad;
5934 }
5935 goto done;
5936 }
5937
sewardjcdc376d2012-04-23 11:21:12 +00005938 case Pin_ExtractExpD128: {
sewardja5b50222015-03-26 07:18:32 +00005939 UInt fr_dst = fregEnc(i->Pin.ExtractExpD128.dst);
5940 UInt fr_srcHi = fregEnc(i->Pin.ExtractExpD128.src_hi);
5941 UInt fr_srcLo = fregEnc(i->Pin.ExtractExpD128.src_lo);
sewardjcdc376d2012-04-23 11:21:12 +00005942
5943 switch (i->Pin.ExtractExpD128.op) {
5944 case Pfp_DXEXQ:
5945 /* Setup the upper and lower registers of the source operand
5946 * register pair.
5947 */
carll1f5fe1f2014-08-07 23:25:23 +00005948 p = mkFormX( p, 63, 12, 0, fr_srcHi, 72, 0, endness_host );
5949 p = mkFormX( p, 63, 13, 0, fr_srcLo, 72, 0, endness_host );
5950 p = mkFormX( p, 63, 10, 0, 12, 354, 0, endness_host );
sewardjcdc376d2012-04-23 11:21:12 +00005951
5952 /* The instruction will put the 64-bit result in
5953 * register 10.
5954 */
carll1f5fe1f2014-08-07 23:25:23 +00005955 p = mkFormX(p, 63, fr_dst, 0, 10, 72, 0, endness_host);
sewardjcdc376d2012-04-23 11:21:12 +00005956 break;
5957 default:
5958 vex_printf("Error: emit_PPCInstr case Pin_DfpExtractExp, case inst Default\n");
5959 goto bad;
5960 }
5961 goto done;
5962 }
sewardj26217b02012-04-12 17:19:48 +00005963 case Pin_Dfp128Unary: {
sewardja5b50222015-03-26 07:18:32 +00005964 UInt fr_dstHi = fregEnc(i->Pin.Dfp128Unary.dst_hi);
5965 UInt fr_dstLo = fregEnc(i->Pin.Dfp128Unary.dst_lo);
5966 UInt fr_srcLo = fregEnc(i->Pin.Dfp128Unary.src_lo);
sewardj26217b02012-04-12 17:19:48 +00005967
5968 /* Do instruction with 128-bit source operands in registers (10,11)
5969 * and (12,13).
5970 */
5971 switch (i->Pin.Dfp128Unary.op) {
5972 case Pfp_DCTQPQ: // D64 to D128, srcLo holds 64 bit operand
carll1f5fe1f2014-08-07 23:25:23 +00005973 p = mkFormX( p, 63, 12, 0, fr_srcLo, 72, 0, endness_host );
sewardj26217b02012-04-12 17:19:48 +00005974
carll1f5fe1f2014-08-07 23:25:23 +00005975 p = mkFormX( p, 63, 10, 0, 12, 258, 0, endness_host );
sewardj26217b02012-04-12 17:19:48 +00005976
5977 /* The instruction will put the 128-bit result in
5978 * registers (10,11). Note, the operand in the instruction only
5979 * reference the first of the two registers in the pair.
5980 */
carll1f5fe1f2014-08-07 23:25:23 +00005981 p = mkFormX(p, 63, fr_dstHi, 0, 10, 72, 0, endness_host);
5982 p = mkFormX(p, 63, fr_dstLo, 0, 11, 72, 0, endness_host);
sewardj26217b02012-04-12 17:19:48 +00005983 break;
5984 default:
5985 vex_printf("Error: emit_PPCInstr case Pin_Dfp128Unary, case inst Default\
5986\n");
5987 goto bad;
5988 }
5989 goto done;
5990 }
5991
sewardjc6bbd472012-04-02 10:20:48 +00005992 case Pin_Dfp128Binary: {
5993 /* dst is used to supply the left source operand and return
5994 * the result.
5995 */
sewardja5b50222015-03-26 07:18:32 +00005996 UInt fr_dstHi = fregEnc( i->Pin.Dfp128Binary.dst_hi );
5997 UInt fr_dstLo = fregEnc( i->Pin.Dfp128Binary.dst_lo );
5998 UInt fr_srcRHi = fregEnc( i->Pin.Dfp128Binary.srcR_hi );
5999 UInt fr_srcRLo = fregEnc( i->Pin.Dfp128Binary.srcR_lo );
sewardjc6bbd472012-04-02 10:20:48 +00006000
6001 /* Setup the upper and lower registers of the source operand
6002 * register pair.
6003 */
carll1f5fe1f2014-08-07 23:25:23 +00006004 p = mkFormX( p, 63, 10, 0, fr_dstHi, 72, 0, endness_host );
6005 p = mkFormX( p, 63, 11, 0, fr_dstLo, 72, 0, endness_host );
6006 p = mkFormX( p, 63, 12, 0, fr_srcRHi, 72, 0, endness_host );
6007 p = mkFormX( p, 63, 13, 0, fr_srcRLo, 72, 0, endness_host );
sewardjc6bbd472012-04-02 10:20:48 +00006008
6009 /* Do instruction with 128-bit source operands in registers (10,11)
6010 * and (12,13).
6011 */
6012 switch (i->Pin.Dfp128Binary.op) {
6013 case Pfp_DFPADDQ:
carll1f5fe1f2014-08-07 23:25:23 +00006014 p = mkFormX( p, 63, 10, 10, 12, 2, 0, endness_host );
sewardjc6bbd472012-04-02 10:20:48 +00006015 break;
6016 case Pfp_DFPSUBQ:
carll1f5fe1f2014-08-07 23:25:23 +00006017 p = mkFormX( p, 63, 10, 10, 12, 514, 0, endness_host );
sewardjc6bbd472012-04-02 10:20:48 +00006018 break;
6019 case Pfp_DFPMULQ:
carll1f5fe1f2014-08-07 23:25:23 +00006020 p = mkFormX( p, 63, 10, 10, 12, 34, 0, endness_host );
sewardjc6bbd472012-04-02 10:20:48 +00006021 break;
6022 case Pfp_DFPDIVQ:
carll1f5fe1f2014-08-07 23:25:23 +00006023 p = mkFormX( p, 63, 10, 10, 12, 546, 0, endness_host );
sewardjc6bbd472012-04-02 10:20:48 +00006024 break;
6025 default:
6026 goto bad;
6027 }
6028
6029 /* The instruction will put the 128-bit result in
6030 * registers (10,11). Note, the operand in the instruction only
6031 * reference the first of the two registers in the pair.
6032 */
carll1f5fe1f2014-08-07 23:25:23 +00006033 p = mkFormX(p, 63, fr_dstHi, 0, 10, 72, 0, endness_host);
6034 p = mkFormX(p, 63, fr_dstLo, 0, 11, 72, 0, endness_host);
sewardjc6bbd472012-04-02 10:20:48 +00006035 goto done;
6036 }
6037
sewardj26217b02012-04-12 17:19:48 +00006038 case Pin_DfpShift128: {
sewardja5b50222015-03-26 07:18:32 +00006039 UInt fr_src_hi = fregEnc(i->Pin.DfpShift128.src_hi);
6040 UInt fr_src_lo = fregEnc(i->Pin.DfpShift128.src_lo);
6041 UInt fr_dst_hi = fregEnc(i->Pin.DfpShift128.dst_hi);
6042 UInt fr_dst_lo = fregEnc(i->Pin.DfpShift128.dst_lo);
sewardj26217b02012-04-12 17:19:48 +00006043 UInt shift;
6044
6045 shift = i->Pin.DfpShift128.shift->Pri.Imm;
6046
6047 /* setup source operand in register 12, 13 pair */
carll1f5fe1f2014-08-07 23:25:23 +00006048 p = mkFormX(p, 63, 12, 0, fr_src_hi, 72, 0, endness_host);
6049 p = mkFormX(p, 63, 13, 0, fr_src_lo, 72, 0, endness_host);
sewardj26217b02012-04-12 17:19:48 +00006050
6051 /* execute instruction putting result in register 10, 11 pair */
6052 switch (i->Pin.DfpShift128.op) {
6053 case Pfp_DSCLIQ: /* dscliq, DFP shift left, fr_srcR is the integer
6054 * shift amount.
6055 */
carll1f5fe1f2014-08-07 23:25:23 +00006056 p = mkFormZ22( p, 63, 10, 12, shift, 66, 0, endness_host );
sewardj26217b02012-04-12 17:19:48 +00006057 break;
6058 case Pfp_DSCRIQ: /* dscriq, DFP shift right, fr_srcR is the integer
6059 * shift amount.
6060 */
carll1f5fe1f2014-08-07 23:25:23 +00006061 p = mkFormZ22( p, 63, 10, 12, shift, 98, 0, endness_host );
sewardj26217b02012-04-12 17:19:48 +00006062 break;
6063 default:
6064 vex_printf("ERROR: emit_PPCInstr quad default case %d \n",
florianb1737742015-08-03 16:03:13 +00006065 (Int)i->Pin.DfpShift128.op);
sewardj26217b02012-04-12 17:19:48 +00006066 goto bad;
6067 }
6068
6069 /* The instruction put the 128-bit result in registers (10,11).
6070 * Note, the operand in the instruction only reference the first of
6071 * the two registers in the pair.
6072 */
carll1f5fe1f2014-08-07 23:25:23 +00006073 p = mkFormX(p, 63, fr_dst_hi, 0, 10, 72, 0, endness_host);
6074 p = mkFormX(p, 63, fr_dst_lo, 0, 11, 72, 0, endness_host);
sewardj26217b02012-04-12 17:19:48 +00006075 goto done;
6076 }
6077
sewardjcdc376d2012-04-23 11:21:12 +00006078 case Pin_DfpRound: {
sewardja5b50222015-03-26 07:18:32 +00006079 UInt fr_dst = fregEnc(i->Pin.DfpRound.dst);
6080 UInt fr_src = fregEnc(i->Pin.DfpRound.src);
sewardjcdc376d2012-04-23 11:21:12 +00006081 UInt r_rmc, r, rmc;
6082
6083 r_rmc = i->Pin.DfpRound.r_rmc->Pri.Imm;
6084 r = (r_rmc & 0x8) >> 3;
6085 rmc = r_rmc & 0x3;
6086
6087 // drintx
carll1f5fe1f2014-08-07 23:25:23 +00006088 p = mkFormZ23(p, 59, fr_dst, r, fr_src, rmc, 99, 0, endness_host);
sewardjcdc376d2012-04-23 11:21:12 +00006089 goto done;
6090 }
6091
6092 case Pin_DfpRound128: {
sewardja5b50222015-03-26 07:18:32 +00006093 UInt fr_dstHi = fregEnc(i->Pin.DfpRound128.dst_hi);
6094 UInt fr_dstLo = fregEnc(i->Pin.DfpRound128.dst_lo);
6095 UInt fr_srcHi = fregEnc(i->Pin.DfpRound128.src_hi);
6096 UInt fr_srcLo = fregEnc(i->Pin.DfpRound128.src_lo);
sewardjcdc376d2012-04-23 11:21:12 +00006097 UInt r_rmc, r, rmc;
6098
6099 r_rmc = i->Pin.DfpRound128.r_rmc->Pri.Imm;
6100 r = (r_rmc & 0x8) >> 3;
6101 rmc = r_rmc & 0x3;
6102
6103 /* Setup the upper and lower registers of the source operand
6104 * register pair.
6105 */
carll1f5fe1f2014-08-07 23:25:23 +00006106 p = mkFormX(p, 63, 12, 0, fr_srcHi, 72, 0, endness_host);
6107 p = mkFormX(p, 63, 13, 0, fr_srcLo, 72, 0, endness_host);
sewardjcdc376d2012-04-23 11:21:12 +00006108
6109 /* Do drintx instruction with 128-bit source operands in
6110 * registers (12,13).
6111 */
carll1f5fe1f2014-08-07 23:25:23 +00006112 p = mkFormZ23(p, 63, 10, r, 12, rmc, 99, 0, endness_host);
sewardjcdc376d2012-04-23 11:21:12 +00006113
6114 /* The instruction will put the 128-bit result in
6115 * registers (10,11). Note, the operand in the instruction only
6116 * reference the first of the two registers in the pair.
6117 */
carll1f5fe1f2014-08-07 23:25:23 +00006118 p = mkFormX(p, 63, fr_dstHi, 0, 10, 72, 0, endness_host);
6119 p = mkFormX(p, 63, fr_dstLo, 0, 11, 72, 0, endness_host);
sewardjcdc376d2012-04-23 11:21:12 +00006120 goto done;
6121 }
6122
6123 case Pin_DfpQuantize: {
sewardja5b50222015-03-26 07:18:32 +00006124 UInt fr_dst = fregEnc(i->Pin.DfpQuantize.dst);
6125 UInt fr_srcL = fregEnc(i->Pin.DfpQuantize.srcL);
6126 UInt fr_srcR = fregEnc(i->Pin.DfpQuantize.srcR);
sewardjcdc376d2012-04-23 11:21:12 +00006127 UInt rmc;
6128
6129 rmc = i->Pin.DfpQuantize.rmc->Pri.Imm;
6130
6131 switch (i->Pin.DfpQuantize.op) {
6132 case Pfp_DQUA:
carll1f5fe1f2014-08-07 23:25:23 +00006133 p = mkFormZ23(p, 59, fr_dst, fr_srcL, fr_srcR, rmc, 3, 0, endness_host);
sewardjcdc376d2012-04-23 11:21:12 +00006134 break;
6135 case Pfp_RRDTR:
carll1f5fe1f2014-08-07 23:25:23 +00006136 p = mkFormZ23(p, 59, fr_dst, fr_srcL, fr_srcR, rmc, 35, 0, endness_host);
sewardjcdc376d2012-04-23 11:21:12 +00006137 break;
6138 default:
6139 break;
6140 }
6141 goto done;
6142 }
6143
6144 case Pin_DfpQuantize128: {
sewardja5b50222015-03-26 07:18:32 +00006145 UInt fr_dst_hi = fregEnc(i->Pin.DfpQuantize128.dst_hi);
6146 UInt fr_dst_lo = fregEnc(i->Pin.DfpQuantize128.dst_lo);
6147 UInt fr_src_hi = fregEnc(i->Pin.DfpQuantize128.src_hi);
6148 UInt fr_src_lo = fregEnc(i->Pin.DfpQuantize128.src_lo);
sewardjcdc376d2012-04-23 11:21:12 +00006149 UInt rmc;
6150
6151 rmc = i->Pin.DfpQuantize128.rmc->Pri.Imm;
6152 /* Setup the upper and lower registers of the source operand
6153 * register pairs. Note, left source operand passed in via the
6154 * dst register pair.
6155 */
carll1f5fe1f2014-08-07 23:25:23 +00006156 p = mkFormX(p, 63, 10, 0, fr_dst_hi, 72, 0, endness_host);
6157 p = mkFormX(p, 63, 11, 0, fr_dst_lo, 72, 0, endness_host);
6158 p = mkFormX(p, 63, 12, 0, fr_src_hi, 72, 0, endness_host);
6159 p = mkFormX(p, 63, 13, 0, fr_src_lo, 72, 0, endness_host);
sewardjcdc376d2012-04-23 11:21:12 +00006160
6161 /* Do dquaq instruction with 128-bit source operands in
6162 * registers (12,13).
6163 */
6164 switch (i->Pin.DfpQuantize128.op) {
6165 case Pfp_DQUAQ:
carll1f5fe1f2014-08-07 23:25:23 +00006166 p = mkFormZ23(p, 63, 10, 10, 12, rmc, 3, 0, endness_host);
sewardjcdc376d2012-04-23 11:21:12 +00006167 break;
6168 case Pfp_DRRNDQ:
carll1f5fe1f2014-08-07 23:25:23 +00006169 p = mkFormZ23(p, 63, 10, 10, 12, rmc, 35, 0, endness_host);
sewardjcdc376d2012-04-23 11:21:12 +00006170 break;
6171 default:
6172 vpanic("Pin_DfpQuantize128: default case, couldn't find inst to issue \n");
6173 break;
6174 }
6175
6176 /* The instruction will put the 128-bit result in
6177 * registers (10,11). Note, the operand in the instruction only
6178 * reference the first of the two registers in the pair.
6179 */
carll1f5fe1f2014-08-07 23:25:23 +00006180 p = mkFormX(p, 63, fr_dst_hi, 0, 10, 72, 0, endness_host);
6181 p = mkFormX(p, 63, fr_dst_lo, 0, 11, 72, 0, endness_host);
sewardjcdc376d2012-04-23 11:21:12 +00006182 goto done;
6183 }
6184
sewardj26217b02012-04-12 17:19:48 +00006185 case Pin_DfpD128toD64: {
sewardja5b50222015-03-26 07:18:32 +00006186 UInt fr_dst = fregEnc( i->Pin.DfpD128toD64.dst );
6187 UInt fr_srcHi = fregEnc( i->Pin.DfpD128toD64.src_hi );
6188 UInt fr_srcLo = fregEnc( i->Pin.DfpD128toD64.src_lo );
sewardj26217b02012-04-12 17:19:48 +00006189
6190 /* Setup the upper and lower registers of the source operand
6191 * register pair.
6192 */
carll1f5fe1f2014-08-07 23:25:23 +00006193 p = mkFormX( p, 63, 10, 0, fr_dst, 72, 0, endness_host );
6194 p = mkFormX( p, 63, 12, 0, fr_srcHi, 72, 0, endness_host );
6195 p = mkFormX( p, 63, 13, 0, fr_srcLo, 72, 0, endness_host );
sewardj26217b02012-04-12 17:19:48 +00006196
6197 /* Do instruction with 128-bit source operands in registers (10,11) */
6198 switch (i->Pin.Dfp128Binary.op) {
6199 case Pfp_DRDPQ:
carll1f5fe1f2014-08-07 23:25:23 +00006200 p = mkFormX( p, 63, 10, 0, 12, 770, 0, endness_host );
sewardj26217b02012-04-12 17:19:48 +00006201 break;
6202 case Pfp_DCTFIXQ:
carll1f5fe1f2014-08-07 23:25:23 +00006203 p = mkFormX( p, 63, 10, 0, 12, 290, 0, endness_host );
sewardj26217b02012-04-12 17:19:48 +00006204 break;
6205 default:
6206 goto bad;
6207 }
6208
6209 /* The instruction will put the 64-bit result in registers 10. */
carll1f5fe1f2014-08-07 23:25:23 +00006210 p = mkFormX(p, 63, fr_dst, 0, 10, 72, 0, endness_host);
sewardj26217b02012-04-12 17:19:48 +00006211 goto done;
6212 }
sewardjdb014092012-04-20 23:58:17 +00006213
sewardj26217b02012-04-12 17:19:48 +00006214 case Pin_DfpI64StoD128: {
sewardja5b50222015-03-26 07:18:32 +00006215 UInt fr_dstHi = fregEnc( i->Pin.DfpI64StoD128.dst_hi );
6216 UInt fr_dstLo = fregEnc( i->Pin.DfpI64StoD128.dst_lo );
6217 UInt fr_src = fregEnc( i->Pin.DfpI64StoD128.src );
sewardj26217b02012-04-12 17:19:48 +00006218
6219 switch (i->Pin.Dfp128Binary.op) {
6220 case Pfp_DCFFIXQ:
carll1f5fe1f2014-08-07 23:25:23 +00006221 p = mkFormX( p, 63, 10, 11, fr_src, 802, 0, endness_host );
sewardj26217b02012-04-12 17:19:48 +00006222 break;
6223 default:
6224 goto bad;
6225 }
6226
6227 /* The instruction will put the 64-bit result in registers 10, 11. */
carll1f5fe1f2014-08-07 23:25:23 +00006228 p = mkFormX(p, 63, fr_dstHi, 0, 10, 72, 0, endness_host);
6229 p = mkFormX(p, 63, fr_dstLo, 0, 11, 72, 0, endness_host);
sewardj26217b02012-04-12 17:19:48 +00006230 goto done;
6231 }
sewardjdb014092012-04-20 23:58:17 +00006232
sewardjcdc376d2012-04-23 11:21:12 +00006233 case Pin_InsertExpD128: {
sewardja5b50222015-03-26 07:18:32 +00006234 UInt fr_dstHi = fregEnc(i->Pin.InsertExpD128.dst_hi);
6235 UInt fr_dstLo = fregEnc(i->Pin.InsertExpD128.dst_lo);
6236 UInt fr_srcL = fregEnc(i->Pin.InsertExpD128.srcL);
6237 UInt fr_srcRHi = fregEnc(i->Pin.InsertExpD128.srcR_hi);
6238 UInt fr_srcRLo = fregEnc(i->Pin.InsertExpD128.srcR_lo);
sewardjcdc376d2012-04-23 11:21:12 +00006239
6240 /* The left operand is a single F64 value, the right is an F128
6241 * register pair.
6242 */
carll1f5fe1f2014-08-07 23:25:23 +00006243 p = mkFormX(p, 63, 10, 0, fr_srcL, 72, 0, endness_host);
6244 p = mkFormX(p, 63, 12, 0, fr_srcRHi, 72, 0, endness_host);
6245 p = mkFormX(p, 63, 13, 0, fr_srcRLo, 72, 0, endness_host);
6246 p = mkFormX(p, 63, 10, 10, 12, 866, 0, endness_host );
sewardjcdc376d2012-04-23 11:21:12 +00006247
6248 /* The instruction will put the 128-bit result into
6249 * registers (10,11). Note, the operand in the instruction only
6250 * reference the first of the two registers in the pair.
6251 */
carll1f5fe1f2014-08-07 23:25:23 +00006252 p = mkFormX(p, 63, fr_dstHi, 0, 10, 72, 0, endness_host);
6253 p = mkFormX(p, 63, fr_dstLo, 0, 11, 72, 0, endness_host);
sewardjcdc376d2012-04-23 11:21:12 +00006254 goto done;
6255 }
6256
6257 case Pin_Dfp64Cmp:{
6258 UChar crfD = 1;
sewardja5b50222015-03-26 07:18:32 +00006259 UInt r_dst = iregEnc(i->Pin.Dfp64Cmp.dst, mode64);
6260 UInt fr_srcL = fregEnc(i->Pin.Dfp64Cmp.srcL);
6261 UInt fr_srcR = fregEnc(i->Pin.Dfp64Cmp.srcR);
sewardjcdc376d2012-04-23 11:21:12 +00006262 vassert(crfD < 8);
6263 // dcmpo, dcmpu
carll1f5fe1f2014-08-07 23:25:23 +00006264 p = mkFormX(p, 59, crfD<<2, fr_srcL, fr_srcR, 130, 0, endness_host);
sewardjcdc376d2012-04-23 11:21:12 +00006265
6266 // mfcr (mv CR to r_dst)
carll1f5fe1f2014-08-07 23:25:23 +00006267 p = mkFormX(p, 31, r_dst, 0, 0, 19, 0, endness_host);
sewardjcdc376d2012-04-23 11:21:12 +00006268
6269 // rlwinm r_dst,r_dst,8,28,31
6270 // => rotate field 1 to bottomw of word, masking out upper 28
carll1f5fe1f2014-08-07 23:25:23 +00006271 p = mkFormM(p, 21, r_dst, r_dst, 8, 28, 31, 0, endness_host);
sewardjcdc376d2012-04-23 11:21:12 +00006272 goto done;
6273 }
6274
6275 case Pin_Dfp128Cmp: {
6276 UChar crfD = 1;
sewardja5b50222015-03-26 07:18:32 +00006277 UInt r_dst = iregEnc(i->Pin.Dfp128Cmp.dst, mode64);
6278 UInt fr_srcL_hi = fregEnc(i->Pin.Dfp128Cmp.srcL_hi);
6279 UInt fr_srcL_lo = fregEnc(i->Pin.Dfp128Cmp.srcL_lo);
6280 UInt fr_srcR_hi = fregEnc(i->Pin.Dfp128Cmp.srcR_hi);
6281 UInt fr_srcR_lo = fregEnc(i->Pin.Dfp128Cmp.srcR_lo);
sewardjcdc376d2012-04-23 11:21:12 +00006282 vassert(crfD < 8);
6283 // dcmpoq, dcmpuq
6284 /* Setup the upper and lower registers of the source operand
6285 * register pair.
6286 */
carll1f5fe1f2014-08-07 23:25:23 +00006287 p = mkFormX(p, 63, 10, 0, fr_srcL_hi, 72, 0, endness_host);
6288 p = mkFormX(p, 63, 11, 0, fr_srcL_lo, 72, 0, endness_host);
6289 p = mkFormX(p, 63, 12, 0, fr_srcR_hi, 72, 0, endness_host);
6290 p = mkFormX(p, 63, 13, 0, fr_srcR_lo, 72, 0, endness_host);
sewardjcdc376d2012-04-23 11:21:12 +00006291
carll1f5fe1f2014-08-07 23:25:23 +00006292 p = mkFormX(p, 63, crfD<<2, 10, 12, 130, 0, endness_host);
sewardjcdc376d2012-04-23 11:21:12 +00006293
6294 // mfcr (mv CR to r_dst)
carll1f5fe1f2014-08-07 23:25:23 +00006295 p = mkFormX(p, 31, r_dst, 0, 0, 19, 0, endness_host);
sewardjcdc376d2012-04-23 11:21:12 +00006296
6297 // rlwinm r_dst,r_dst,8,28,31
6298 // => rotate field 1 to bottomw of word, masking out upper 28
carll1f5fe1f2014-08-07 23:25:23 +00006299 p = mkFormM(p, 21, r_dst, r_dst, 8, 28, 31, 0, endness_host);
sewardjcdc376d2012-04-23 11:21:12 +00006300 goto done;
6301 }
6302
sewardj3dee8492012-04-20 00:13:28 +00006303 case Pin_EvCheck: {
6304 /* This requires a 32-bit dec/test in both 32- and 64-bit
6305 modes. */
6306 /* We generate:
6307 lwz r30, amCounter
6308 addic. r30, r30, -1
6309 stw r30, amCounter
6310 bge nofail
6311 lwz/ld r30, amFailAddr
6312 mtctr r30
6313 bctr
6314 nofail:
6315 */
6316 UChar* p0 = p;
6317 /* lwz r30, amCounter */
6318 p = do_load_or_store_word32(p, True/*isLoad*/, /*r*/30,
carll1f5fe1f2014-08-07 23:25:23 +00006319 i->Pin.EvCheck.amCounter, mode64,
6320 endness_host);
sewardj3dee8492012-04-20 00:13:28 +00006321 /* addic. r30,r30,-1 */
carll1f5fe1f2014-08-07 23:25:23 +00006322 p = emit32(p, 0x37DEFFFF, endness_host);
sewardj3dee8492012-04-20 00:13:28 +00006323 /* stw r30, amCounter */
6324 p = do_load_or_store_word32(p, False/*!isLoad*/, /*r*/30,
carll1f5fe1f2014-08-07 23:25:23 +00006325 i->Pin.EvCheck.amCounter, mode64,
6326 endness_host);
sewardj3dee8492012-04-20 00:13:28 +00006327 /* bge nofail */
carll1f5fe1f2014-08-07 23:25:23 +00006328 p = emit32(p, 0x40800010, endness_host);
sewardj3dee8492012-04-20 00:13:28 +00006329 /* lwz/ld r30, amFailAddr */
6330 p = do_load_or_store_machine_word(p, True/*isLoad*/, /*r*/30,
carll1f5fe1f2014-08-07 23:25:23 +00006331 i->Pin.EvCheck.amFailAddr, mode64,
6332 endness_host);
sewardj3dee8492012-04-20 00:13:28 +00006333 /* mtctr r30 */
carll1f5fe1f2014-08-07 23:25:23 +00006334 p = mkFormXFX(p, /*r*/30, 9, 467, endness_host);
sewardj3dee8492012-04-20 00:13:28 +00006335 /* bctr */
carll1f5fe1f2014-08-07 23:25:23 +00006336 p = mkFormXL(p, 19, Pct_ALWAYS, 0, 0, 528, 0, endness_host);
sewardj3dee8492012-04-20 00:13:28 +00006337 /* nofail: */
6338
6339 /* Crosscheck */
florian7ce2cc82015-01-10 16:10:58 +00006340 vassert(evCheckSzB_PPC() == (UChar*)p - (UChar*)p0);
sewardj3dee8492012-04-20 00:13:28 +00006341 goto done;
6342 }
6343
6344 case Pin_ProfInc: {
6345 /* We generate:
6346 (ctrP is unknown now, so use 0x65556555(65556555) in the
6347 expectation that a later call to LibVEX_patchProfCtr
6348 will be used to fill in the immediate fields once the
6349 right value is known.)
6350 32-bit:
6351 imm32-exactly r30, 0x65556555
6352 lwz r29, 4(r30)
6353 addic. r29, r29, 1
6354 stw r29, 4(r30)
6355 lwz r29, 0(r30)
6356 addze r29, r29
6357 stw r29, 0(r30)
6358 64-bit:
6359 imm64-exactly r30, 0x6555655565556555
6360 ld r29, 0(r30)
sewardjf252de52012-04-20 10:42:24 +00006361 addi r29, r29, 1
sewardj3dee8492012-04-20 00:13:28 +00006362 std r29, 0(r30)
6363 */
6364 if (mode64) {
6365 p = mkLoadImm_EXACTLY2or5(
carll1f5fe1f2014-08-07 23:25:23 +00006366 p, /*r*/30, 0x6555655565556555ULL, True/*mode64*/, endness_host);
6367 p = emit32(p, 0xEBBE0000, endness_host);
6368 p = emit32(p, 0x3BBD0001, endness_host);
6369 p = emit32(p, 0xFBBE0000, endness_host);
sewardj3dee8492012-04-20 00:13:28 +00006370 } else {
6371 p = mkLoadImm_EXACTLY2or5(
carll1f5fe1f2014-08-07 23:25:23 +00006372 p, /*r*/30, 0x65556555ULL, False/*!mode64*/, endness_host);
6373 p = emit32(p, 0x83BE0004, endness_host);
6374 p = emit32(p, 0x37BD0001, endness_host);
6375 p = emit32(p, 0x93BE0004, endness_host);
6376 p = emit32(p, 0x83BE0000, endness_host);
6377 p = emit32(p, 0x7FBD0194, endness_host);
6378 p = emit32(p, 0x93BE0000, endness_host);
sewardj3dee8492012-04-20 00:13:28 +00006379 }
6380 /* Tell the caller .. */
6381 vassert(!(*is_profInc));
6382 *is_profInc = True;
6383 goto done;
6384 }
6385
cerionbcf8c3e2005-02-04 16:17:07 +00006386 default:
6387 goto bad;
6388 }
6389
6390 bad:
cerionab9132d2005-02-15 15:46:59 +00006391 vex_printf("\n=> ");
cerion5b2325f2005-12-23 00:55:09 +00006392 ppPPCInstr(i, mode64);
6393 vpanic("emit_PPCInstr");
cerionbcf8c3e2005-02-04 16:17:07 +00006394 /*NOTREACHED*/
6395
cerionbcf8c3e2005-02-04 16:17:07 +00006396 done:
sewardj9e1cf152012-04-20 02:18:31 +00006397 vassert(p - &buf[0] <= 64);
cerionbcf8c3e2005-02-04 16:17:07 +00006398 return p - &buf[0];
cerionbcf8c3e2005-02-04 16:17:07 +00006399}
6400
sewardj3dee8492012-04-20 00:13:28 +00006401
6402/* How big is an event check? See case for Pin_EvCheck in
6403 emit_PPCInstr just above. That crosschecks what this returns, so
6404 we can tell if we're inconsistent. */
florian7ce2cc82015-01-10 16:10:58 +00006405Int evCheckSzB_PPC (void)
sewardj3dee8492012-04-20 00:13:28 +00006406{
6407 return 28;
6408}
6409
6410
6411/* NB: what goes on here has to be very closely coordinated with the
6412 emitInstr case for XDirect, above. */
sewardj9b769162014-07-24 12:42:03 +00006413VexInvalRange chainXDirect_PPC ( VexEndness endness_host,
6414 void* place_to_chain,
florian7d6f81d2014-09-22 21:43:37 +00006415 const void* disp_cp_chain_me_EXPECTED,
6416 const void* place_to_jump_to,
sewardj3dee8492012-04-20 00:13:28 +00006417 Bool mode64 )
6418{
sewardj9b769162014-07-24 12:42:03 +00006419 if (mode64) {
carll1f5fe1f2014-08-07 23:25:23 +00006420 vassert((endness_host == VexEndnessBE) ||
6421 (endness_host == VexEndnessLE));
sewardj9b769162014-07-24 12:42:03 +00006422 } else {
6423 vassert(endness_host == VexEndnessBE);
6424 }
6425
sewardj3dee8492012-04-20 00:13:28 +00006426 /* What we're expecting to see is:
6427 imm32/64-fixed r30, disp_cp_chain_me_to_EXPECTED
6428 mtctr r30
6429 bctrl
6430 viz
6431 <8 or 20 bytes generated by mkLoadImm_EXACTLY2or5>
6432 7F C9 03 A6
6433 4E 80 04 21
6434 */
6435 UChar* p = (UChar*)place_to_chain;
6436 vassert(0 == (3 & (HWord)p));
6437 vassert(isLoadImm_EXACTLY2or5(p, /*r*/30,
florian93a09742015-01-07 20:14:48 +00006438 (Addr)disp_cp_chain_me_EXPECTED,
carll1f5fe1f2014-08-07 23:25:23 +00006439 mode64, endness_host));
6440 vassert(fetch32(p + (mode64 ? 20 : 8) + 0, endness_host) == 0x7FC903A6);
6441 vassert(fetch32(p + (mode64 ? 20 : 8) + 4, endness_host) == 0x4E800421);
sewardj3dee8492012-04-20 00:13:28 +00006442 /* And what we want to change it to is:
6443 imm32/64-fixed r30, place_to_jump_to
6444 mtctr r30
6445 bctr
6446 viz
6447 <8 or 20 bytes generated by mkLoadImm_EXACTLY2or5>
6448 7F C9 03 A6
6449 4E 80 04 20
6450 The replacement has the same length as the original.
6451 */
6452 p = mkLoadImm_EXACTLY2or5(p, /*r*/30,
florian93a09742015-01-07 20:14:48 +00006453 (Addr)place_to_jump_to, mode64,
carll1f5fe1f2014-08-07 23:25:23 +00006454 endness_host);
6455 p = emit32(p, 0x7FC903A6, endness_host);
6456 p = emit32(p, 0x4E800420, endness_host);
sewardj3dee8492012-04-20 00:13:28 +00006457
6458 Int len = p - (UChar*)place_to_chain;
6459 vassert(len == (mode64 ? 28 : 16)); /* stay sane */
6460 VexInvalRange vir = {(HWord)place_to_chain, len};
6461 return vir;
6462}
6463
6464
6465/* NB: what goes on here has to be very closely coordinated with the
6466 emitInstr case for XDirect, above. */
sewardj9b769162014-07-24 12:42:03 +00006467VexInvalRange unchainXDirect_PPC ( VexEndness endness_host,
6468 void* place_to_unchain,
florian7d6f81d2014-09-22 21:43:37 +00006469 const void* place_to_jump_to_EXPECTED,
6470 const void* disp_cp_chain_me,
sewardj3dee8492012-04-20 00:13:28 +00006471 Bool mode64 )
6472{
sewardj9b769162014-07-24 12:42:03 +00006473 if (mode64) {
carll1f5fe1f2014-08-07 23:25:23 +00006474 vassert((endness_host == VexEndnessBE) ||
6475 (endness_host == VexEndnessLE));
sewardj9b769162014-07-24 12:42:03 +00006476 } else {
6477 vassert(endness_host == VexEndnessBE);
6478 }
6479
sewardj3dee8492012-04-20 00:13:28 +00006480 /* What we're expecting to see is:
6481 imm32/64-fixed r30, place_to_jump_to_EXPECTED
6482 mtctr r30
6483 bctr
6484 viz
6485 <8 or 20 bytes generated by mkLoadImm_EXACTLY2or5>
6486 7F C9 03 A6
6487 4E 80 04 20
6488 */
6489 UChar* p = (UChar*)place_to_unchain;
6490 vassert(0 == (3 & (HWord)p));
6491 vassert(isLoadImm_EXACTLY2or5(p, /*r*/30,
florian93a09742015-01-07 20:14:48 +00006492 (Addr)place_to_jump_to_EXPECTED,
carll1f5fe1f2014-08-07 23:25:23 +00006493 mode64, endness_host));
6494 vassert(fetch32(p + (mode64 ? 20 : 8) + 0, endness_host) == 0x7FC903A6);
6495 vassert(fetch32(p + (mode64 ? 20 : 8) + 4, endness_host) == 0x4E800420);
sewardj3dee8492012-04-20 00:13:28 +00006496 /* And what we want to change it to is:
6497 imm32/64-fixed r30, disp_cp_chain_me
6498 mtctr r30
6499 bctrl
6500 viz
6501 <8 or 20 bytes generated by mkLoadImm_EXACTLY2or5>
6502 7F C9 03 A6
6503 4E 80 04 21
6504 The replacement has the same length as the original.
6505 */
6506 p = mkLoadImm_EXACTLY2or5(p, /*r*/30,
florian93a09742015-01-07 20:14:48 +00006507 (Addr)disp_cp_chain_me, mode64,
carll1f5fe1f2014-08-07 23:25:23 +00006508 endness_host);
6509 p = emit32(p, 0x7FC903A6, endness_host);
6510 p = emit32(p, 0x4E800421, endness_host);
sewardj3dee8492012-04-20 00:13:28 +00006511
6512 Int len = p - (UChar*)place_to_unchain;
6513 vassert(len == (mode64 ? 28 : 16)); /* stay sane */
6514 VexInvalRange vir = {(HWord)place_to_unchain, len};
6515 return vir;
6516}
6517
6518
6519/* Patch the counter address into a profile inc point, as previously
6520 created by the Pin_ProfInc case for emit_PPCInstr. */
sewardj9b769162014-07-24 12:42:03 +00006521VexInvalRange patchProfInc_PPC ( VexEndness endness_host,
6522 void* place_to_patch,
florian7d6f81d2014-09-22 21:43:37 +00006523 const ULong* location_of_counter,
sewardj3dee8492012-04-20 00:13:28 +00006524 Bool mode64 )
6525{
sewardj9b769162014-07-24 12:42:03 +00006526 if (mode64) {
carll1f5fe1f2014-08-07 23:25:23 +00006527 vassert((endness_host == VexEndnessBE) ||
6528 (endness_host == VexEndnessLE));
sewardj9b769162014-07-24 12:42:03 +00006529 } else {
6530 vassert(endness_host == VexEndnessBE);
6531 }
6532
sewardj3dee8492012-04-20 00:13:28 +00006533 UChar* p = (UChar*)place_to_patch;
6534 vassert(0 == (3 & (HWord)p));
6535
6536 Int len = 0;
6537 if (mode64) {
6538 vassert(isLoadImm_EXACTLY2or5(p, /*r*/30,
carll1f5fe1f2014-08-07 23:25:23 +00006539 0x6555655565556555ULL, True/*mode64*/,
6540 endness_host));
6541 vassert(fetch32(p + 20, endness_host) == 0xEBBE0000);
6542 vassert(fetch32(p + 24, endness_host) == 0x3BBD0001);
6543 vassert(fetch32(p + 28, endness_host) == 0xFBBE0000);
sewardj3dee8492012-04-20 00:13:28 +00006544 p = mkLoadImm_EXACTLY2or5(p, /*r*/30,
florian93a09742015-01-07 20:14:48 +00006545 (Addr)location_of_counter,
carll1f5fe1f2014-08-07 23:25:23 +00006546 True/*mode64*/, endness_host);
sewardj3dee8492012-04-20 00:13:28 +00006547 len = p - (UChar*)place_to_patch;
6548 vassert(len == 20);
6549 } else {
6550 vassert(isLoadImm_EXACTLY2or5(p, /*r*/30,
carll1f5fe1f2014-08-07 23:25:23 +00006551 0x65556555ULL, False/*!mode64*/,
6552 endness_host));
6553 vassert(fetch32(p + 8, endness_host) == 0x83BE0004);
6554 vassert(fetch32(p + 12, endness_host) == 0x37BD0001);
6555 vassert(fetch32(p + 16, endness_host) == 0x93BE0004);
6556 vassert(fetch32(p + 20, endness_host) == 0x83BE0000);
6557 vassert(fetch32(p + 24, endness_host) == 0x7FBD0194);
6558 vassert(fetch32(p + 28, endness_host) == 0x93BE0000);
sewardj3dee8492012-04-20 00:13:28 +00006559 p = mkLoadImm_EXACTLY2or5(p, /*r*/30,
florian93a09742015-01-07 20:14:48 +00006560 (Addr)location_of_counter,
carll1f5fe1f2014-08-07 23:25:23 +00006561 False/*!mode64*/, endness_host);
sewardj3dee8492012-04-20 00:13:28 +00006562 len = p - (UChar*)place_to_patch;
6563 vassert(len == 8);
6564 }
6565 VexInvalRange vir = {(HWord)place_to_patch, len};
6566 return vir;
6567}
6568
6569
cerionbcf8c3e2005-02-04 16:17:07 +00006570/*---------------------------------------------------------------*/
sewardjcef7d3e2009-07-02 12:21:59 +00006571/*--- end host_ppc_defs.c ---*/
cerionbcf8c3e2005-02-04 16:17:07 +00006572/*---------------------------------------------------------------*/