blob: 2f82eec5281986210da4e01b102e5e5cb0eb1fea [file] [log] [blame]
cerionbcf8c3e2005-02-04 16:17:07 +00001
2/*---------------------------------------------------------------*/
3/*--- ---*/
4/*--- This file (host-ppc32/hdefs.c) is ---*/
sewardj428fabd2005-03-21 03:11:17 +00005/*--- Copyright (c) OpenWorks LLP. All rights reserved. ---*/
cerionbcf8c3e2005-02-04 16:17:07 +00006/*--- ---*/
7/*---------------------------------------------------------------*/
8
9/*
10 This file is part of LibVEX, a library for dynamic binary
11 instrumentation and translation.
12
sewardj428fabd2005-03-21 03:11:17 +000013 Copyright (C) 2004-2005 OpenWorks LLP.
cerionbcf8c3e2005-02-04 16:17:07 +000014
15 This program is free software; you can redistribute it and/or modify
16 it under the terms of the GNU General Public License as published by
17 the Free Software Foundation; Version 2 dated June 1991 of the
18 license.
19
20 This program is distributed in the hope that it will be useful,
21 but WITHOUT ANY WARRANTY; without even the implied warranty of
22 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE, or liability
23 for damages. See the GNU General Public License for more details.
24
25 Neither the names of the U.S. Department of Energy nor the
26 University of California nor the names of its contributors may be
27 used to endorse or promote products derived from this software
28 without prior written permission.
29
30 You should have received a copy of the GNU General Public License
31 along with this program; if not, write to the Free Software
32 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
33 USA.
34*/
35
36#include "libvex_basictypes.h"
37#include "libvex.h"
38#include "libvex_trc_values.h"
39
40#include "main/vex_util.h"
41#include "host-generic/h_generic_regs.h"
42#include "host-ppc32/hdefs.h"
43
44
45/* --------- Registers. --------- */
46
47void ppHRegPPC32 ( HReg reg )
cerioncd304492005-02-08 19:40:24 +000048{
49 Int r;
50 static HChar* ireg32_names[32]
cerionb85e8bb2005-02-16 08:54:33 +000051 = { "%r0", "%r1", "%r2", "%r3", "%r4", "%r5", "%r6", "%r7",
52 "%r8", "%r9", "%r10", "%r11", "%r12", "%r13", "%r14", "%r15",
53 "%r16", "%r17", "%r18", "%r19", "%r20", "%r21", "%r22", "%r23",
54 "%r24", "%r25", "%r26", "%r27", "%r28", "%r29", "%r30", "%r31" };
cerioncd304492005-02-08 19:40:24 +000055 /* Be generic for all virtual regs. */
56 if (hregIsVirtual(reg)) {
57 ppHReg(reg);
58 return;
59 }
60 /* But specific for real regs. */
61 switch (hregClass(reg)) {
cerionb85e8bb2005-02-16 08:54:33 +000062 case HRcInt32:
63 r = hregNumber(reg);
64 vassert(r >= 0 && r < 32);
65 vex_printf("%s", ireg32_names[r]);
66 return;
67 case HRcFlt64:
68 r = hregNumber(reg);
cerion094d1392005-06-20 13:45:57 +000069 vassert(r >= 0 && r < 32);
70 vex_printf("%%fr%d", r);
cerionb85e8bb2005-02-16 08:54:33 +000071 return;
cerionc3d8bdc2005-06-28 18:06:23 +000072 case HRcVec128:
73 r = hregNumber(reg);
74 vassert(r >= 0 && r < 32);
75 vex_printf("%%v%d", r);
76 return;
cerionb85e8bb2005-02-16 08:54:33 +000077 default:
78 vpanic("ppHRegPPC32");
cerioncd304492005-02-08 19:40:24 +000079 }
cerionbcf8c3e2005-02-04 16:17:07 +000080}
81
cerioncd304492005-02-08 19:40:24 +000082HReg hregPPC32_GPR0 ( void ) { return mkHReg( 0, HRcInt32, False); }
83HReg hregPPC32_GPR1 ( void ) { return mkHReg( 1, HRcInt32, False); }
84HReg hregPPC32_GPR2 ( void ) { return mkHReg( 2, HRcInt32, False); }
85HReg hregPPC32_GPR3 ( void ) { return mkHReg( 3, HRcInt32, False); }
86HReg hregPPC32_GPR4 ( void ) { return mkHReg( 4, HRcInt32, False); }
87HReg hregPPC32_GPR5 ( void ) { return mkHReg( 5, HRcInt32, False); }
88HReg hregPPC32_GPR6 ( void ) { return mkHReg( 6, HRcInt32, False); }
89HReg hregPPC32_GPR7 ( void ) { return mkHReg( 7, HRcInt32, False); }
90HReg hregPPC32_GPR8 ( void ) { return mkHReg( 8, HRcInt32, False); }
91HReg hregPPC32_GPR9 ( void ) { return mkHReg( 9, HRcInt32, False); }
92HReg hregPPC32_GPR10 ( void ) { return mkHReg(10, HRcInt32, False); }
93HReg hregPPC32_GPR11 ( void ) { return mkHReg(11, HRcInt32, False); }
94HReg hregPPC32_GPR12 ( void ) { return mkHReg(12, HRcInt32, False); }
95HReg hregPPC32_GPR13 ( void ) { return mkHReg(13, HRcInt32, False); }
96HReg hregPPC32_GPR14 ( void ) { return mkHReg(14, HRcInt32, False); }
97HReg hregPPC32_GPR15 ( void ) { return mkHReg(15, HRcInt32, False); }
98HReg hregPPC32_GPR16 ( void ) { return mkHReg(16, HRcInt32, False); }
99HReg hregPPC32_GPR17 ( void ) { return mkHReg(17, HRcInt32, False); }
100HReg hregPPC32_GPR18 ( void ) { return mkHReg(18, HRcInt32, False); }
101HReg hregPPC32_GPR19 ( void ) { return mkHReg(19, HRcInt32, False); }
102HReg hregPPC32_GPR20 ( void ) { return mkHReg(20, HRcInt32, False); }
103HReg hregPPC32_GPR21 ( void ) { return mkHReg(21, HRcInt32, False); }
104HReg hregPPC32_GPR22 ( void ) { return mkHReg(22, HRcInt32, False); }
105HReg hregPPC32_GPR23 ( void ) { return mkHReg(23, HRcInt32, False); }
106HReg hregPPC32_GPR24 ( void ) { return mkHReg(24, HRcInt32, False); }
107HReg hregPPC32_GPR25 ( void ) { return mkHReg(25, HRcInt32, False); }
108HReg hregPPC32_GPR26 ( void ) { return mkHReg(26, HRcInt32, False); }
109HReg hregPPC32_GPR27 ( void ) { return mkHReg(27, HRcInt32, False); }
110HReg hregPPC32_GPR28 ( void ) { return mkHReg(28, HRcInt32, False); }
111HReg hregPPC32_GPR29 ( void ) { return mkHReg(29, HRcInt32, False); }
112HReg hregPPC32_GPR30 ( void ) { return mkHReg(30, HRcInt32, False); }
113HReg hregPPC32_GPR31 ( void ) { return mkHReg(31, HRcInt32, False); }
114
115HReg hregPPC32_FPR0 ( void ) { return mkHReg( 0, HRcFlt64, False); }
116HReg hregPPC32_FPR1 ( void ) { return mkHReg( 1, HRcFlt64, False); }
117HReg hregPPC32_FPR2 ( void ) { return mkHReg( 2, HRcFlt64, False); }
118HReg hregPPC32_FPR3 ( void ) { return mkHReg( 3, HRcFlt64, False); }
119HReg hregPPC32_FPR4 ( void ) { return mkHReg( 4, HRcFlt64, False); }
120HReg hregPPC32_FPR5 ( void ) { return mkHReg( 5, HRcFlt64, False); }
121HReg hregPPC32_FPR6 ( void ) { return mkHReg( 6, HRcFlt64, False); }
122HReg hregPPC32_FPR7 ( void ) { return mkHReg( 7, HRcFlt64, False); }
123HReg hregPPC32_FPR8 ( void ) { return mkHReg( 8, HRcFlt64, False); }
124HReg hregPPC32_FPR9 ( void ) { return mkHReg( 9, HRcFlt64, False); }
125HReg hregPPC32_FPR10 ( void ) { return mkHReg(10, HRcFlt64, False); }
126HReg hregPPC32_FPR11 ( void ) { return mkHReg(11, HRcFlt64, False); }
127HReg hregPPC32_FPR12 ( void ) { return mkHReg(12, HRcFlt64, False); }
128HReg hregPPC32_FPR13 ( void ) { return mkHReg(13, HRcFlt64, False); }
129HReg hregPPC32_FPR14 ( void ) { return mkHReg(14, HRcFlt64, False); }
130HReg hregPPC32_FPR15 ( void ) { return mkHReg(15, HRcFlt64, False); }
131HReg hregPPC32_FPR16 ( void ) { return mkHReg(16, HRcFlt64, False); }
132HReg hregPPC32_FPR17 ( void ) { return mkHReg(17, HRcFlt64, False); }
133HReg hregPPC32_FPR18 ( void ) { return mkHReg(18, HRcFlt64, False); }
134HReg hregPPC32_FPR19 ( void ) { return mkHReg(19, HRcFlt64, False); }
135HReg hregPPC32_FPR20 ( void ) { return mkHReg(20, HRcFlt64, False); }
136HReg hregPPC32_FPR21 ( void ) { return mkHReg(21, HRcFlt64, False); }
137HReg hregPPC32_FPR22 ( void ) { return mkHReg(22, HRcFlt64, False); }
138HReg hregPPC32_FPR23 ( void ) { return mkHReg(23, HRcFlt64, False); }
139HReg hregPPC32_FPR24 ( void ) { return mkHReg(24, HRcFlt64, False); }
140HReg hregPPC32_FPR25 ( void ) { return mkHReg(25, HRcFlt64, False); }
141HReg hregPPC32_FPR26 ( void ) { return mkHReg(26, HRcFlt64, False); }
142HReg hregPPC32_FPR27 ( void ) { return mkHReg(27, HRcFlt64, False); }
143HReg hregPPC32_FPR28 ( void ) { return mkHReg(28, HRcFlt64, False); }
144HReg hregPPC32_FPR29 ( void ) { return mkHReg(29, HRcFlt64, False); }
145HReg hregPPC32_FPR30 ( void ) { return mkHReg(30, HRcFlt64, False); }
146HReg hregPPC32_FPR31 ( void ) { return mkHReg(31, HRcFlt64, False); }
cerionbcf8c3e2005-02-04 16:17:07 +0000147
cerionc3d8bdc2005-06-28 18:06:23 +0000148HReg hregPPC32_VR0 ( void ) { return mkHReg( 0, HRcVec128, False); }
149HReg hregPPC32_VR1 ( void ) { return mkHReg( 1, HRcVec128, False); }
150HReg hregPPC32_VR2 ( void ) { return mkHReg( 2, HRcVec128, False); }
151HReg hregPPC32_VR3 ( void ) { return mkHReg( 3, HRcVec128, False); }
152HReg hregPPC32_VR4 ( void ) { return mkHReg( 4, HRcVec128, False); }
153HReg hregPPC32_VR5 ( void ) { return mkHReg( 5, HRcVec128, False); }
154HReg hregPPC32_VR6 ( void ) { return mkHReg( 6, HRcVec128, False); }
155HReg hregPPC32_VR7 ( void ) { return mkHReg( 7, HRcVec128, False); }
156HReg hregPPC32_VR8 ( void ) { return mkHReg( 8, HRcVec128, False); }
157HReg hregPPC32_VR9 ( void ) { return mkHReg( 9, HRcVec128, False); }
158HReg hregPPC32_VR10 ( void ) { return mkHReg(10, HRcVec128, False); }
159HReg hregPPC32_VR11 ( void ) { return mkHReg(11, HRcVec128, False); }
160HReg hregPPC32_VR12 ( void ) { return mkHReg(12, HRcVec128, False); }
161HReg hregPPC32_VR13 ( void ) { return mkHReg(13, HRcVec128, False); }
162HReg hregPPC32_VR14 ( void ) { return mkHReg(14, HRcVec128, False); }
163HReg hregPPC32_VR15 ( void ) { return mkHReg(15, HRcVec128, False); }
164HReg hregPPC32_VR16 ( void ) { return mkHReg(16, HRcVec128, False); }
165HReg hregPPC32_VR17 ( void ) { return mkHReg(17, HRcVec128, False); }
166HReg hregPPC32_VR18 ( void ) { return mkHReg(18, HRcVec128, False); }
167HReg hregPPC32_VR19 ( void ) { return mkHReg(19, HRcVec128, False); }
168HReg hregPPC32_VR20 ( void ) { return mkHReg(20, HRcVec128, False); }
169HReg hregPPC32_VR21 ( void ) { return mkHReg(21, HRcVec128, False); }
170HReg hregPPC32_VR22 ( void ) { return mkHReg(22, HRcVec128, False); }
171HReg hregPPC32_VR23 ( void ) { return mkHReg(23, HRcVec128, False); }
172HReg hregPPC32_VR24 ( void ) { return mkHReg(24, HRcVec128, False); }
173HReg hregPPC32_VR25 ( void ) { return mkHReg(25, HRcVec128, False); }
174HReg hregPPC32_VR26 ( void ) { return mkHReg(26, HRcVec128, False); }
175HReg hregPPC32_VR27 ( void ) { return mkHReg(27, HRcVec128, False); }
176HReg hregPPC32_VR28 ( void ) { return mkHReg(28, HRcVec128, False); }
177HReg hregPPC32_VR29 ( void ) { return mkHReg(29, HRcVec128, False); }
178HReg hregPPC32_VR30 ( void ) { return mkHReg(30, HRcVec128, False); }
179HReg hregPPC32_VR31 ( void ) { return mkHReg(31, HRcVec128, False); }
180
cerionbcf8c3e2005-02-04 16:17:07 +0000181void getAllocableRegs_PPC32 ( Int* nregs, HReg** arr )
cerioncd304492005-02-08 19:40:24 +0000182{
cerionc3d8bdc2005-06-28 18:06:23 +0000183 UInt i=0;
cerionb4a632a2005-02-09 21:01:22 +0000184 *nregs = 59;
cerioncd304492005-02-08 19:40:24 +0000185 *arr = LibVEX_Alloc(*nregs * sizeof(HReg));
ceriona56e9cc2005-02-16 18:08:25 +0000186 // GPR0 = scratch reg where possible - some ops interpret as value zero
cerion2c49e032005-02-09 17:29:49 +0000187 // GPR1 = stack pointer
188 // GPR2 = TOC pointer
cerionc3d8bdc2005-06-28 18:06:23 +0000189 (*arr)[i++] = hregPPC32_GPR3();
190 (*arr)[i++] = hregPPC32_GPR4();
191 (*arr)[i++] = hregPPC32_GPR5();
192 (*arr)[i++] = hregPPC32_GPR6();
193 (*arr)[i++] = hregPPC32_GPR7();
194 (*arr)[i++] = hregPPC32_GPR8();
195 (*arr)[i++] = hregPPC32_GPR9();
196 (*arr)[i++] = hregPPC32_GPR10();
197 (*arr)[i++] = hregPPC32_GPR11();
198 (*arr)[i++] = hregPPC32_GPR12();
cerion2c49e032005-02-09 17:29:49 +0000199 // GPR13 = thread specific pointer
cerionc3d8bdc2005-06-28 18:06:23 +0000200 (*arr)[i++] = hregPPC32_GPR14();
201 (*arr)[i++] = hregPPC32_GPR15();
202 (*arr)[i++] = hregPPC32_GPR16();
203 (*arr)[i++] = hregPPC32_GPR17();
204 (*arr)[i++] = hregPPC32_GPR18();
205 (*arr)[i++] = hregPPC32_GPR19();
206 (*arr)[i++] = hregPPC32_GPR20();
207 (*arr)[i++] = hregPPC32_GPR21();
208 (*arr)[i++] = hregPPC32_GPR22();
209 (*arr)[i++] = hregPPC32_GPR23();
210 (*arr)[i++] = hregPPC32_GPR24();
211 (*arr)[i++] = hregPPC32_GPR25();
212 (*arr)[i++] = hregPPC32_GPR26();
213 (*arr)[i++] = hregPPC32_GPR27();
214 (*arr)[i++] = hregPPC32_GPR28();
215 (*arr)[i++] = hregPPC32_GPR29();
216 // GPR30 AltiVec spill reg temporary
cerion2c49e032005-02-09 17:29:49 +0000217 // GPR31 = GuestStatePtr
cerioncd304492005-02-08 19:40:24 +0000218
cerionc3d8bdc2005-06-28 18:06:23 +0000219 (*arr)[i++] = hregPPC32_FPR0();
220 (*arr)[i++] = hregPPC32_FPR1();
221 (*arr)[i++] = hregPPC32_FPR2();
222 (*arr)[i++] = hregPPC32_FPR3();
223 (*arr)[i++] = hregPPC32_FPR4();
224 (*arr)[i++] = hregPPC32_FPR5();
225 (*arr)[i++] = hregPPC32_FPR6();
226 (*arr)[i++] = hregPPC32_FPR7();
227 (*arr)[i++] = hregPPC32_FPR8();
228 (*arr)[i++] = hregPPC32_FPR9();
229 (*arr)[i++] = hregPPC32_FPR10();
230 (*arr)[i++] = hregPPC32_FPR11();
231 (*arr)[i++] = hregPPC32_FPR12();
232 (*arr)[i++] = hregPPC32_FPR13();
233 (*arr)[i++] = hregPPC32_FPR14();
234 (*arr)[i++] = hregPPC32_FPR15();
235 (*arr)[i++] = hregPPC32_FPR16();
236 (*arr)[i++] = hregPPC32_FPR17();
237 (*arr)[i++] = hregPPC32_FPR18();
238 (*arr)[i++] = hregPPC32_FPR19();
239 (*arr)[i++] = hregPPC32_FPR20();
240 (*arr)[i++] = hregPPC32_FPR21();
241 (*arr)[i++] = hregPPC32_FPR22();
242 (*arr)[i++] = hregPPC32_FPR23();
243 (*arr)[i++] = hregPPC32_FPR24();
244 (*arr)[i++] = hregPPC32_FPR25();
245 (*arr)[i++] = hregPPC32_FPR26();
246 (*arr)[i++] = hregPPC32_FPR27();
247 (*arr)[i++] = hregPPC32_FPR28();
248 (*arr)[i++] = hregPPC32_FPR29();
249 (*arr)[i++] = hregPPC32_FPR30();
250 (*arr)[i++] = hregPPC32_FPR31();
251
252 (*arr)[i++] = hregPPC32_VR0();
253 (*arr)[i++] = hregPPC32_VR1();
254 (*arr)[i++] = hregPPC32_VR2();
255 (*arr)[i++] = hregPPC32_VR3();
256 (*arr)[i++] = hregPPC32_VR4();
257 (*arr)[i++] = hregPPC32_VR5();
258 (*arr)[i++] = hregPPC32_VR6();
259 (*arr)[i++] = hregPPC32_VR7();
260 (*arr)[i++] = hregPPC32_VR8();
261 (*arr)[i++] = hregPPC32_VR9();
262 (*arr)[i++] = hregPPC32_VR10();
263 (*arr)[i++] = hregPPC32_VR11();
264 (*arr)[i++] = hregPPC32_VR12();
265 (*arr)[i++] = hregPPC32_VR13();
266 (*arr)[i++] = hregPPC32_VR14();
267 (*arr)[i++] = hregPPC32_VR15();
268 (*arr)[i++] = hregPPC32_VR16();
269 (*arr)[i++] = hregPPC32_VR17();
270 (*arr)[i++] = hregPPC32_VR18();
271 (*arr)[i++] = hregPPC32_VR19();
272 (*arr)[i++] = hregPPC32_VR20();
273 (*arr)[i++] = hregPPC32_VR21();
274 (*arr)[i++] = hregPPC32_VR22();
275 (*arr)[i++] = hregPPC32_VR23();
276 (*arr)[i++] = hregPPC32_VR24();
277 (*arr)[i++] = hregPPC32_VR25();
278 (*arr)[i++] = hregPPC32_VR26();
279 (*arr)[i++] = hregPPC32_VR27();
280 (*arr)[i++] = hregPPC32_VR28();
281 (*arr)[i++] = hregPPC32_VR29();
282 (*arr)[i++] = hregPPC32_VR30();
283 (*arr)[i++] = hregPPC32_VR31();
cerion2c49e032005-02-09 17:29:49 +0000284}
285
286
287/* --------- Condition codes, Intel encoding. --------- */
288
289HChar* showPPC32CondCode ( PPC32CondCode cond )
290{
cerionab9132d2005-02-15 15:46:59 +0000291 if (cond.test == Pct_ALWAYS) return "always";
292
293 switch (cond.flag) {
294 case Pcf_SO: return (cond.test == Pct_TRUE) ? "so=1" : "so=0";
295 case Pcf_EQ: return (cond.test == Pct_TRUE) ? "eq=1" : "eq=0";
296 case Pcf_GT: return (cond.test == Pct_TRUE) ? "gt=1" : "gt=0";
297 case Pcf_LT: return (cond.test == Pct_TRUE) ? "lt=1" : "lt=0";
298 default: vpanic("ppPPC32CondCode");
cerion2c49e032005-02-09 17:29:49 +0000299 }
cerionbcf8c3e2005-02-04 16:17:07 +0000300}
301
cerioned623db2005-06-20 12:42:04 +0000302/* construct condition code */
cerion7cf8e4e2005-02-16 16:08:17 +0000303PPC32CondCode mk_PPCCondCode ( PPC32CondTest test, PPC32CondFlag flag )
304{
305 PPC32CondCode cc;
306 cc.flag = flag;
307 cc.test = test;
308 return cc;
309}
310
311/* false->true, true->false */
cerion33aa6da2005-02-16 10:25:26 +0000312PPC32CondTest invertCondTest ( PPC32CondTest ct )
313{
314 vassert(ct != Pct_ALWAYS);
315 return (ct == Pct_TRUE) ? Pct_FALSE : Pct_TRUE;
316}
317
318
cerioncd304492005-02-08 19:40:24 +0000319/* --------- PPCAMode: memory address expressions. --------- */
320
321PPC32AMode* PPC32AMode_IR ( UInt idx, HReg base ) {
322 PPC32AMode* am = LibVEX_Alloc(sizeof(PPC32AMode));
sewardj9a036bf2005-03-14 18:19:08 +0000323 vassert(idx < 0x10000);
cerioncd304492005-02-08 19:40:24 +0000324 am->tag = Pam_IR;
325 am->Pam.IR.base = base;
326 am->Pam.IR.index = idx;
327 return am;
328}
329PPC32AMode* PPC32AMode_RR ( HReg idx, HReg base ) {
330 PPC32AMode* am = LibVEX_Alloc(sizeof(PPC32AMode));
331 am->tag = Pam_RR;
332 am->Pam.RR.base = base;
333 am->Pam.RR.index = idx;
334 return am;
335}
336
337PPC32AMode* dopyPPC32AMode ( PPC32AMode* am ) {
338 switch (am->tag) {
cerionb85e8bb2005-02-16 08:54:33 +0000339 case Pam_IR:
340 return PPC32AMode_IR( am->Pam.IR.index, am->Pam.IR.base );
341 case Pam_RR:
342 return PPC32AMode_RR( am->Pam.RR.index, am->Pam.RR.base );
343 default:
344 vpanic("dopyPPC32AMode");
cerioncd304492005-02-08 19:40:24 +0000345 }
346}
347
348void ppPPC32AMode ( PPC32AMode* am ) {
349 switch (am->tag) {
cerionb85e8bb2005-02-16 08:54:33 +0000350 case Pam_IR:
351 if (am->Pam.IR.index == 0)
cerionf9d6e222005-02-23 18:21:31 +0000352 vex_printf("0(");
cerionb85e8bb2005-02-16 08:54:33 +0000353 else
354 vex_printf("0x%x(", am->Pam.IR.index);
355 ppHRegPPC32(am->Pam.IR.base);
356 vex_printf(")");
357 return;
358 case Pam_RR:
359 ppHRegPPC32(am->Pam.RR.base);
360 vex_printf(",");
361 ppHRegPPC32(am->Pam.RR.index);
362 return;
363 default:
364 vpanic("ppPPC32AMode");
cerioncd304492005-02-08 19:40:24 +0000365 }
366}
367
cerioncd304492005-02-08 19:40:24 +0000368static void addRegUsage_PPC32AMode ( HRegUsage* u, PPC32AMode* am ) {
369 switch (am->tag) {
cerionb85e8bb2005-02-16 08:54:33 +0000370 case Pam_IR:
371 addHRegUse(u, HRmRead, am->Pam.IR.base);
372 return;
373 case Pam_RR:
374 addHRegUse(u, HRmRead, am->Pam.RR.base);
375 addHRegUse(u, HRmRead, am->Pam.RR.index);
376 return;
377 default:
378 vpanic("addRegUsage_PPC32AMode");
cerioncd304492005-02-08 19:40:24 +0000379 }
380}
cerioncd304492005-02-08 19:40:24 +0000381
cerioncd304492005-02-08 19:40:24 +0000382static void mapRegs_PPC32AMode ( HRegRemap* m, PPC32AMode* am ) {
383 switch (am->tag) {
cerionb85e8bb2005-02-16 08:54:33 +0000384 case Pam_IR:
385 am->Pam.IR.base = lookupHRegRemap(m, am->Pam.IR.base);
386 return;
387 case Pam_RR:
388 am->Pam.RR.base = lookupHRegRemap(m, am->Pam.RR.base);
389 am->Pam.RR.index = lookupHRegRemap(m, am->Pam.RR.index);
390 return;
391 default:
392 vpanic("mapRegs_PPC32AMode");
cerioncd304492005-02-08 19:40:24 +0000393 }
394}
cerioncd304492005-02-08 19:40:24 +0000395
396/* --------- Operand, which can be reg or immediate only. --------- */
397
398PPC32RI* PPC32RI_Imm ( UInt imm32 ) {
399 PPC32RI* op = LibVEX_Alloc(sizeof(PPC32RI));
400 op->tag = Pri_Imm;
401 op->Pri.Imm.imm32 = imm32;
402 return op;
403}
404PPC32RI* PPC32RI_Reg ( HReg reg ) {
405 PPC32RI* op = LibVEX_Alloc(sizeof(PPC32RI));
406 op->tag = Pri_Reg;
407 op->Pri.Reg.reg = reg;
408 return op;
409}
410
411void ppPPC32RI ( PPC32RI* op ) {
412 switch (op->tag) {
cerionb85e8bb2005-02-16 08:54:33 +0000413 case Pri_Imm:
414 vex_printf("$0x%x", op->Pri.Imm.imm32);
415 return;
416 case Pri_Reg:
417 ppHRegPPC32(op->Pri.Reg.reg);
418 return;
419 default:
420 vpanic("ppPPC32RI");
cerioncd304492005-02-08 19:40:24 +0000421 }
422}
423
424/* An PPC32RI can only be used in a "read" context (what would it mean
425 to write or modify a literal?) and so we enumerate its registers
426 accordingly. */
427static void addRegUsage_PPC32RI ( HRegUsage* u, PPC32RI* op ) {
428 switch (op->tag) {
cerionb85e8bb2005-02-16 08:54:33 +0000429 case Pri_Imm:
430 return;
431 case Pri_Reg:
432 addHRegUse(u, HRmRead, op->Pri.Reg.reg);
433 return;
434 default:
435 vpanic("addRegUsage_PPC32RI");
cerioncd304492005-02-08 19:40:24 +0000436 }
437}
438
439static void mapRegs_PPC32RI ( HRegRemap* m, PPC32RI* op ) {
440 switch (op->tag) {
cerionb85e8bb2005-02-16 08:54:33 +0000441 case Pri_Imm:
442 return;
443 case Pri_Reg:
444 op->Pri.Reg.reg = lookupHRegRemap(m, op->Pri.Reg.reg);
445 return;
446 default:
447 vpanic("mapRegs_PPC32RI");
cerioncd304492005-02-08 19:40:24 +0000448 }
449}
450
451/* --------- Instructions. --------- */
452
cerionbcf8c3e2005-02-04 16:17:07 +0000453//.. HChar* showX86ScalarSz ( X86ScalarSz sz ) {
454//.. switch (sz) {
455//.. case Xss_16: return "w";
456//.. case Xss_32: return "l";
457//.. default: vpanic("showX86ScalarSz");
458//.. }
459//.. }
cerioncd304492005-02-08 19:40:24 +0000460
cerion2c49e032005-02-09 17:29:49 +0000461HChar* showPPC32UnaryOp ( PPC32UnaryOp op ) {
462 switch (op) {
cerionb85e8bb2005-02-16 08:54:33 +0000463 case Pun_NOT: return "not";
464 case Pun_NEG: return "neg";
465 case Pun_CLZ: return "cntlzw";
466 default: vpanic("showPPC32UnaryOp");
cerion2c49e032005-02-09 17:29:49 +0000467 }
468}
cerioncd304492005-02-08 19:40:24 +0000469
470HChar* showPPC32AluOp ( PPC32AluOp op ) {
471 switch (op) {
cerionb85e8bb2005-02-16 08:54:33 +0000472 case Palu_ADD: return "add";
cerionb85e8bb2005-02-16 08:54:33 +0000473// case Palu_ADC: return "adc";
474// case Palu_SBB: return "sbb";
475 case Palu_AND: return "and";
476 case Palu_OR: return "or";
477 case Palu_XOR: return "xor";
cerionb85e8bb2005-02-16 08:54:33 +0000478 default: vpanic("showPPC32AluOp");
cerioncd304492005-02-08 19:40:24 +0000479 }
480}
481
482HChar* showPPC32ShiftOp ( PPC32ShiftOp op ) {
483 switch (op) {
cerionb85e8bb2005-02-16 08:54:33 +0000484 case Psh_SHL: return "slw";
485 case Psh_SHR: return "srw";
486 case Psh_SAR: return "sraw";
487 case Psh_ROL: return "rlw";
488 default: vpanic("showPPC32ShiftOp");
cerioncd304492005-02-08 19:40:24 +0000489 }
490}
491
cerionab9132d2005-02-15 15:46:59 +0000492HChar* showPPC32CmpOp ( PPC32CmpOp op ) {
493 switch (op) {
cerionb85e8bb2005-02-16 08:54:33 +0000494 case Pcmp_U: return "cmpl";
495 case Pcmp_S: return "cmp";
496 default: vpanic("showPPC32CmpOp");
cerionab9132d2005-02-15 15:46:59 +0000497 }
498}
499
cerion094d1392005-06-20 13:45:57 +0000500HChar* showPPC32FpOp ( PPC32FpOp op ) {
501 switch (op) {
502 case Pfp_ADD: return "fadd";
503 case Pfp_SUB: return "fsub";
504 case Pfp_MUL: return "fmul";
505 case Pfp_DIV: return "fdiv";
506 case Pfp_SQRT: return "fsqrt";
507 case Pfp_ABS: return "fabs";
508 case Pfp_NEG: return "fneg";
509 case Pfp_MOV: return "fmr";
510 default: vpanic("showPPC32FpOp");
511 }
512}
cerioncd304492005-02-08 19:40:24 +0000513
cerionc3d8bdc2005-06-28 18:06:23 +0000514HChar* showPPC32AvOp ( PPC32AvOp op ) {
515 switch (op) {
cerion6b6f59e2005-06-28 20:59:18 +0000516
517 /* Unary */
518 case Pav_MOV: return "vmr"; /* Mov */
cerionc3d8bdc2005-06-28 18:06:23 +0000519
cerion6b6f59e2005-06-28 20:59:18 +0000520 case Pav_AND: return "vand"; /* Bitwise */
cerionc3d8bdc2005-06-28 18:06:23 +0000521 case Pav_OR: return "vor";
522 case Pav_XOR: return "vxor";
523 case Pav_NOT: return "vnot";
524
cerion6b6f59e2005-06-28 20:59:18 +0000525 case Pav_UNPCKH8S: return "vupkhsb"; /* Unpack */
cerionc3d8bdc2005-06-28 18:06:23 +0000526 case Pav_UNPCKH16S: return "vupkhsh";
527 case Pav_UNPCKL8S: return "vupklsb";
528 case Pav_UNPCKL16S: return "vupklsh";
529 case Pav_UNPCKHPIX: return "vupkhpx";
530 case Pav_UNPCKLPIX: return "vupklpx";
cerion6b6f59e2005-06-28 20:59:18 +0000531
532 /* Integer binary */
533 case Pav_ADDUM: return "vaddu_m"; // b,h,w
534 case Pav_ADDUS: return "vaddu_s"; // b,h,w
535 case Pav_ADDSS: return "vadds_s"; // b,h,w
cerionc3d8bdc2005-06-28 18:06:23 +0000536
cerion6b6f59e2005-06-28 20:59:18 +0000537 case Pav_SUBUM: return "vsubu_m"; // b,h,w
538 case Pav_SUBUS: return "vsubu_s"; // b,h,w
539 case Pav_SUBSS: return "vsubs_s"; // b,h,w
540
541 case Pav_OMULU: return "vmulou"; // b,h
542 case Pav_OMULS: return "vmulos"; // b,h
543 case Pav_EMULU: return "vmuleu"; // b,h
544 case Pav_EMULS: return "vmules"; // b,h
545
546 case Pav_AVGU: return "vavgu"; // b,h,w
547 case Pav_AVGS: return "vavgs"; // b,h,w
548
549 case Pav_MAXU: return "vmaxu"; // b,h,w
550 case Pav_MAXS: return "vmaxs"; // b,h,w
551
552 case Pav_MINU: return "vminu"; // b,h,w
553 case Pav_MINS: return "vmins"; // b,h,w
554
555 /* Compare (always affects CR field 6) */
556 case Pav_CMPEQU: return "vcmpequ"; // b,h,w
557 case Pav_CMPGTU: return "vcmpgtu"; // b,h,w
558 case Pav_CMPGTS: return "vcmpgts"; // b,h,w
559
560 /* Shift */
561 case Pav_SHL: return "vsl"; // ' ',b,h,w
562 case Pav_SHR: return "vsr"; // ' ',b,h,w
563 case Pav_SAR: return "vsra"; // b,h,w
564 case Pav_ROTL: return "vrl"; // b,h,w
565
566 /* Pack */
567 case Pav_PACKUUM: return "vpku_um"; // h,w
568 case Pav_PACKUUS: return "vpku_us"; // h,w
569 case Pav_PACKSUS: return "vpks_us"; // h,w
570 case Pav_PACKSSS: return "vpks_ss"; // h,w
571 case Pav_PACKPXL: return "vpkpx";
572
cerionc3d8bdc2005-06-28 18:06:23 +0000573 /* Merge */
cerion6b6f59e2005-06-28 20:59:18 +0000574 case Pav_MRGHI: return "vmrgh"; // b,h,w
575 case Pav_MRGLO: return "vmrgl"; // b,h,w
576
577
578 /* Floating Point Binary */
579 case Pav_ADDF: return "vaddfp";
580 case Pav_SUBF: return "vsubfp";
581 case Pav_MULF: return "vmaddfp";
582 case Pav_MAXF: return "vmaxfp";
583 case Pav_MINF: return "vminfp";
584 case Pav_CMPEQF: return "vcmpeqfp";
585 case Pav_CMPGTF: return "vcmpgtfp";
586 case Pav_CMPGEF: return "vcmpgefp";
cerionc3d8bdc2005-06-28 18:06:23 +0000587
588 default: vpanic("showPPC32AvOp");
589 }
590}
591
ceriona2f75882005-03-15 16:33:38 +0000592PPC32Instr* PPC32Instr_Alu32 ( PPC32AluOp op, HReg dst, HReg srcL, PPC32RI* srcR ) {
sewardj9a036bf2005-03-14 18:19:08 +0000593 PPC32Instr* i = LibVEX_Alloc(sizeof(PPC32Instr));
ceriona2f75882005-03-15 16:33:38 +0000594 if (srcR->tag == Pri_Imm)
595 vassert(srcR->Pri.Imm.imm32 < 0x10000);
cerioncd304492005-02-08 19:40:24 +0000596 i->tag = Pin_Alu32;
597 i->Pin.Alu32.op = op;
598 i->Pin.Alu32.dst = dst;
ceriona2f75882005-03-15 16:33:38 +0000599 i->Pin.Alu32.srcL = srcL;
600 i->Pin.Alu32.srcR = srcR;
cerioncd304492005-02-08 19:40:24 +0000601 return i;
602}
ceriona2f75882005-03-15 16:33:38 +0000603PPC32Instr* PPC32Instr_Sub32 ( HReg dst, PPC32RI* srcL, HReg srcR ) {
sewardj9a036bf2005-03-14 18:19:08 +0000604 PPC32Instr* i = LibVEX_Alloc(sizeof(PPC32Instr));
ceriona2f75882005-03-15 16:33:38 +0000605 if (srcL->tag == Pri_Imm)
606 vassert(srcL->Pri.Imm.imm32 < 0x10000);
cerion5e2527e2005-02-25 16:39:58 +0000607 i->tag = Pin_Sub32;
608 i->Pin.Sub32.dst = dst;
ceriona2f75882005-03-15 16:33:38 +0000609 i->Pin.Sub32.srcL = srcL;
610 i->Pin.Sub32.srcR = srcR;
cerion5e2527e2005-02-25 16:39:58 +0000611 return i;
612}
cerioncd304492005-02-08 19:40:24 +0000613PPC32Instr* PPC32Instr_Sh32 ( PPC32ShiftOp op, HReg dst, HReg src, PPC32RI* shft ) {
sewardj9a036bf2005-03-14 18:19:08 +0000614 PPC32Instr* i = LibVEX_Alloc(sizeof(PPC32Instr));
cerionab9132d2005-02-15 15:46:59 +0000615 if (op == Psh_SHL || op == Psh_SHR) // No imm versions for these.
616 vassert(shft->tag == Pri_Reg);
617 if (shft->tag == Pri_Imm)
618 vassert(shft->Pri.Imm.imm32 < 32);
cerioncd304492005-02-08 19:40:24 +0000619 i->tag = Pin_Sh32;
620 i->Pin.Sh32.op = op;
621 i->Pin.Sh32.dst = dst;
622 i->Pin.Sh32.src = src;
623 i->Pin.Sh32.shft = shft;
624 return i;
625}
ceriona2f75882005-03-15 16:33:38 +0000626PPC32Instr* PPC32Instr_Cmp32 ( PPC32CmpOp op, UInt crfD, HReg srcL, PPC32RI* srcR ) {
sewardj9a036bf2005-03-14 18:19:08 +0000627 PPC32Instr* i = LibVEX_Alloc(sizeof(PPC32Instr));
ceriona2f75882005-03-15 16:33:38 +0000628 if (srcR->tag == Pri_Imm)
629 vassert(srcR->Pri.Imm.imm32 < 0x10000);
cerionab9132d2005-02-15 15:46:59 +0000630 i->tag = Pin_Cmp32;
631 i->Pin.Cmp32.op = op;
632 i->Pin.Cmp32.crfD = crfD;
ceriona2f75882005-03-15 16:33:38 +0000633 i->Pin.Cmp32.srcL = srcL;
634 i->Pin.Cmp32.srcR = srcR;
cerion2c49e032005-02-09 17:29:49 +0000635 return i;
636}
cerione13bb312005-02-10 19:51:03 +0000637PPC32Instr* PPC32Instr_Unary32 ( PPC32UnaryOp op, HReg dst, HReg src ) {
cerion2c49e032005-02-09 17:29:49 +0000638 PPC32Instr* i = LibVEX_Alloc(sizeof(PPC32Instr));
639 i->tag = Pin_Unary32;
640 i->Pin.Unary32.op = op;
641 i->Pin.Unary32.dst = dst;
cerione13bb312005-02-10 19:51:03 +0000642 i->Pin.Unary32.src = src;
cerion2c49e032005-02-09 17:29:49 +0000643 return i;
644}
cerion92f5dc72005-02-10 16:11:35 +0000645PPC32Instr* PPC32Instr_MulL ( Bool syned, Bool word, HReg dst,
ceriona2f75882005-03-15 16:33:38 +0000646 HReg srcL, PPC32RI* srcR ) {
sewardj9a036bf2005-03-14 18:19:08 +0000647 PPC32Instr* i = LibVEX_Alloc(sizeof(PPC32Instr));
cerion98411db2005-02-16 14:14:49 +0000648 if (word == 1) { // high
ceriona2f75882005-03-15 16:33:38 +0000649 vassert(srcR->tag == Pri_Reg);
cerion98411db2005-02-16 14:14:49 +0000650 } else { // low
ceriona2f75882005-03-15 16:33:38 +0000651 if (srcR->tag == Pri_Imm) {
cerion98411db2005-02-16 14:14:49 +0000652 vassert(syned == True);
ceriona2f75882005-03-15 16:33:38 +0000653 vassert(srcR->Pri.Imm.imm32 < 0x10000);
cerion98411db2005-02-16 14:14:49 +0000654 }
655 }
cerion92f5dc72005-02-10 16:11:35 +0000656 i->tag = Pin_MulL;
657 i->Pin.MulL.syned = syned;
658 i->Pin.MulL.word = word;
cerionc0e707e2005-02-10 22:35:34 +0000659 i->Pin.MulL.dst = dst;
ceriona2f75882005-03-15 16:33:38 +0000660 i->Pin.MulL.srcL = srcL;
661 i->Pin.MulL.srcR = srcR;
cerion92f5dc72005-02-10 16:11:35 +0000662 return i;
663}
ceriona2f75882005-03-15 16:33:38 +0000664PPC32Instr* PPC32Instr_Div ( Bool syned, HReg dst, HReg srcL, HReg srcR ) {
sewardj9a036bf2005-03-14 18:19:08 +0000665 PPC32Instr* i = LibVEX_Alloc(sizeof(PPC32Instr));
cerionc0e707e2005-02-10 22:35:34 +0000666 i->tag = Pin_Div;
667 i->Pin.Div.syned = syned;
668 i->Pin.Div.dst = dst;
ceriona2f75882005-03-15 16:33:38 +0000669 i->Pin.Div.srcL = srcL;
670 i->Pin.Div.srcR = srcR;
cerionc0e707e2005-02-10 22:35:34 +0000671 return i;
672}
cerion2c49e032005-02-09 17:29:49 +0000673PPC32Instr* PPC32Instr_Call ( PPC32CondCode cond, Addr32 target, Int regparms ) {
674 PPC32Instr* i = LibVEX_Alloc(sizeof(PPC32Instr));
675 i->tag = Pin_Call;
676 i->Pin.Call.cond = cond;
677 i->Pin.Call.target = target;
678 i->Pin.Call.regparms = regparms;
679 vassert(regparms >= 0 && regparms < PPC32_N_REGPARMS);
680 return i;
681}
682PPC32Instr* PPC32Instr_Goto ( IRJumpKind jk, PPC32CondCode cond, PPC32RI* dst ) {
683 PPC32Instr* i = LibVEX_Alloc(sizeof(PPC32Instr));
684 i->tag = Pin_Goto;
685 i->Pin.Goto.cond = cond;
686 i->Pin.Goto.dst = dst;
687 i->Pin.Goto.jk = jk;
688 return i;
689}
cerionb536af92005-02-10 15:03:19 +0000690PPC32Instr* PPC32Instr_CMov32 ( PPC32CondCode cond, HReg dst, PPC32RI* src ) {
691 PPC32Instr* i = LibVEX_Alloc(sizeof(PPC32Instr));
692 i->tag = Pin_CMov32;
693 i->Pin.CMov32.cond = cond;
694 i->Pin.CMov32.src = src;
695 i->Pin.CMov32.dst = dst;
cerionab9132d2005-02-15 15:46:59 +0000696 vassert(cond.test != Pct_ALWAYS);
cerionb536af92005-02-10 15:03:19 +0000697 return i;
698}
cerion7cf8e4e2005-02-16 16:08:17 +0000699PPC32Instr* PPC32Instr_Load ( UChar sz, Bool syned,
700 HReg dst, PPC32AMode* src ) {
701 PPC32Instr* i = LibVEX_Alloc(sizeof(PPC32Instr));
702 i->tag = Pin_Load;
703 i->Pin.Load.sz = sz;
704 i->Pin.Load.syned = syned;
705 i->Pin.Load.src = src;
706 i->Pin.Load.dst = dst;
cerion2c49e032005-02-09 17:29:49 +0000707 vassert(sz == 1 || sz == 2 || sz == 4);
cerioncd304492005-02-08 19:40:24 +0000708 return i;
709}
710PPC32Instr* PPC32Instr_Store ( UChar sz, PPC32AMode* dst, HReg src ) {
711 PPC32Instr* i = LibVEX_Alloc(sizeof(PPC32Instr));
712 i->tag = Pin_Store;
713 i->Pin.Store.sz = sz;
714 i->Pin.Store.src = src;
715 i->Pin.Store.dst = dst;
716 vassert(sz == 1 || sz == 2 || sz == 4);
717 return i;
718}
cerionb536af92005-02-10 15:03:19 +0000719PPC32Instr* PPC32Instr_Set32 ( PPC32CondCode cond, HReg dst ) {
720 PPC32Instr* i = LibVEX_Alloc(sizeof(PPC32Instr));
721 i->tag = Pin_Set32;
722 i->Pin.Set32.cond = cond;
723 i->Pin.Set32.dst = dst;
724 return i;
725}
cerion98411db2005-02-16 14:14:49 +0000726PPC32Instr* PPC32Instr_MFence ( void )
cerion92f5dc72005-02-10 16:11:35 +0000727{
728 PPC32Instr* i = LibVEX_Alloc(sizeof(PPC32Instr));
729 i->tag = Pin_MFence;
cerion92f5dc72005-02-10 16:11:35 +0000730 return i;
731}
cerioncd304492005-02-08 19:40:24 +0000732
cerion094d1392005-06-20 13:45:57 +0000733PPC32Instr* PPC32Instr_FpUnary ( PPC32FpOp op, HReg dst, HReg src ) {
734 PPC32Instr* i = LibVEX_Alloc(sizeof(PPC32Instr));
735 i->tag = Pin_FpUnary;
736 i->Pin.FpUnary.op = op;
737 i->Pin.FpUnary.dst = dst;
738 i->Pin.FpUnary.src = src;
739 return i;
740}
741PPC32Instr* PPC32Instr_FpBinary ( PPC32FpOp op, HReg dst, HReg srcL, HReg srcR ) {
742 PPC32Instr* i = LibVEX_Alloc(sizeof(PPC32Instr));
743 i->tag = Pin_FpBinary;
744 i->Pin.FpBinary.op = op;
745 i->Pin.FpBinary.dst = dst;
746 i->Pin.FpBinary.srcL = srcL;
747 i->Pin.FpBinary.srcR = srcR;
748 return i;
749}
750PPC32Instr* PPC32Instr_FpLdSt ( Bool isLoad, UChar sz, HReg reg, PPC32AMode* addr ) {
751 PPC32Instr* i = LibVEX_Alloc(sizeof(PPC32Instr));
752 i->tag = Pin_FpLdSt;
753 i->Pin.FpLdSt.isLoad = isLoad;
754 i->Pin.FpLdSt.sz = sz;
755 i->Pin.FpLdSt.reg = reg;
756 i->Pin.FpLdSt.addr = addr;
757 vassert(sz == 4 || sz == 8);
758 return i;
759}
760PPC32Instr* PPC32Instr_FpF64toF32 ( HReg dst, HReg src ) {
761 PPC32Instr* i = LibVEX_Alloc(sizeof(PPC32Instr));
762 i->tag = Pin_FpF64toF32;
763 i->Pin.FpF64toF32.dst = dst;
764 i->Pin.FpF64toF32.src = src;
765 return i;
766}
767PPC32Instr* PPC32Instr_FpF64toI32 ( HReg dst, HReg src ) {
768 PPC32Instr* i = LibVEX_Alloc(sizeof(PPC32Instr));
769 i->tag = Pin_FpF64toI32;
770 i->Pin.FpF64toI32.dst = dst;
771 i->Pin.FpF64toI32.src = src;
772 return i;
773}
774PPC32Instr* PPC32Instr_FpCMov ( PPC32CondCode cond, HReg dst, HReg src ) {
775 PPC32Instr* i = LibVEX_Alloc(sizeof(PPC32Instr));
776 i->tag = Pin_FpCMov;
777 i->Pin.FpCMov.cond = cond;
778 i->Pin.FpCMov.dst = dst;
779 i->Pin.FpCMov.src = src;
780 vassert(cond.test != Pct_ALWAYS);
781 return i;
782}
783PPC32Instr* PPC32Instr_FpLdFPSCR ( HReg src ) {
784 PPC32Instr* i = LibVEX_Alloc(sizeof(PPC32Instr));
785 i->tag = Pin_FpLdFPSCR;
786 i->Pin.FpLdFPSCR.src = src;
787 return i;
788}
789PPC32Instr* PPC32Instr_FpCmp ( HReg dst, HReg srcL, HReg srcR ) {
790 PPC32Instr* i = LibVEX_Alloc(sizeof(PPC32Instr));
791 i->tag = Pin_FpCmp;
792 i->Pin.FpCmp.dst = dst;
793 i->Pin.FpCmp.srcL = srcL;
794 i->Pin.FpCmp.srcR = srcR;
795 return i;
796}
cerionbcf8c3e2005-02-04 16:17:07 +0000797
cerion7f000af2005-02-22 20:36:49 +0000798/* Read/Write Link Register */
cerionc3d8bdc2005-06-28 18:06:23 +0000799PPC32Instr* PPC32Instr_RdWrLR ( Bool wrLR, HReg gpr ) {
cerion7f000af2005-02-22 20:36:49 +0000800 PPC32Instr* i = LibVEX_Alloc(sizeof(PPC32Instr));
801 i->tag = Pin_RdWrLR;
802 i->Pin.RdWrLR.wrLR = wrLR;
803 i->Pin.RdWrLR.gpr = gpr;
804 return i;
805}
806
cerionc3d8bdc2005-06-28 18:06:23 +0000807/* AltiVec */
808PPC32Instr* PPC32Instr_AvLdSt ( Bool isLoad, UChar sz, HReg reg, PPC32AMode* addr ) {
809 PPC32Instr* i = LibVEX_Alloc(sizeof(PPC32Instr));
810 i->tag = Pin_AvLdSt;
811 i->Pin.AvLdSt.isLoad = isLoad;
812 i->Pin.AvLdSt.sz = sz;
813 i->Pin.AvLdSt.reg = reg;
814 i->Pin.AvLdSt.addr = addr;
815 return i;
816}
817PPC32Instr* PPC32Instr_AvUnary ( PPC32AvOp op, HReg dst, HReg src ) {
818 PPC32Instr* i = LibVEX_Alloc(sizeof(PPC32Instr));
819 i->tag = Pin_AvUnary;
820 i->Pin.AvUnary.op = op;
821 i->Pin.AvUnary.dst = dst;
822 i->Pin.AvUnary.src = src;
823 return i;
824}
825PPC32Instr* PPC32Instr_AvBinary ( PPC32AvOp op, HReg dst, HReg srcL, HReg srcR ) {
826 PPC32Instr* i = LibVEX_Alloc(sizeof(PPC32Instr));
827 i->tag = Pin_AvBinary;
828 i->Pin.AvBinary.op = op;
829 i->Pin.AvBinary.dst = dst;
830 i->Pin.AvBinary.srcL = srcL;
831 i->Pin.AvBinary.srcR = srcR;
832 return i;
833}
cerion6b6f59e2005-06-28 20:59:18 +0000834PPC32Instr* PPC32Instr_AvBin8x16 ( PPC32AvOp op, HReg dst, HReg srcL, HReg srcR ) {
835 PPC32Instr* i = LibVEX_Alloc(sizeof(PPC32Instr));
836 i->tag = Pin_AvBin8x16;
837 i->Pin.AvBin8x16.op = op;
838 i->Pin.AvBin8x16.dst = dst;
839 i->Pin.AvBin8x16.srcL = srcL;
840 i->Pin.AvBin8x16.srcR = srcR;
841 return i;
842}
843PPC32Instr* PPC32Instr_AvBin16x8 ( PPC32AvOp op, HReg dst, HReg srcL, HReg srcR ) {
844 PPC32Instr* i = LibVEX_Alloc(sizeof(PPC32Instr));
845 i->tag = Pin_AvBin16x8;
846 i->Pin.AvBin16x8.op = op;
847 i->Pin.AvBin16x8.dst = dst;
848 i->Pin.AvBin16x8.srcL = srcL;
849 i->Pin.AvBin16x8.srcR = srcR;
850 return i;
851}
852PPC32Instr* PPC32Instr_AvBin32x4 ( PPC32AvOp op, HReg dst, HReg srcL, HReg srcR ) {
853 PPC32Instr* i = LibVEX_Alloc(sizeof(PPC32Instr));
854 i->tag = Pin_AvBin32x4;
855 i->Pin.AvBin32x4.op = op;
856 i->Pin.AvBin32x4.dst = dst;
857 i->Pin.AvBin32x4.srcL = srcL;
858 i->Pin.AvBin32x4.srcR = srcR;
859 return i;
860}
861PPC32Instr* PPC32Instr_AvBin32Fx4 ( PPC32AvOp op, HReg dst, HReg srcL, HReg srcR ) {
862 PPC32Instr* i = LibVEX_Alloc(sizeof(PPC32Instr));
863 i->tag = Pin_AvBin32Fx4;
864 i->Pin.AvBin32Fx4.op = op;
865 i->Pin.AvBin32Fx4.dst = dst;
866 i->Pin.AvBin32Fx4.srcL = srcL;
867 i->Pin.AvBin32Fx4.srcR = srcR;
868 return i;
869}
cerionc3d8bdc2005-06-28 18:06:23 +0000870PPC32Instr* PPC32Instr_AvPerm ( HReg ctl, HReg dst, HReg srcL, HReg srcR ) {
871 PPC32Instr* i = LibVEX_Alloc(sizeof(PPC32Instr));
872 i->tag = Pin_AvPerm;
873 i->Pin.AvPerm.ctl = ctl;
874 i->Pin.AvPerm.dst = dst;
875 i->Pin.AvPerm.srcL = srcL;
876 i->Pin.AvPerm.srcR = srcR;
877 return i;
878}
879PPC32Instr* PPC32Instr_AvSel ( HReg ctl, HReg dst, HReg srcL, HReg srcR ) {
880 PPC32Instr* i = LibVEX_Alloc(sizeof(PPC32Instr));
881 i->tag = Pin_AvSel;
882 i->Pin.AvSel.ctl = ctl;
883 i->Pin.AvSel.dst = dst;
884 i->Pin.AvSel.srcL = srcL;
885 i->Pin.AvSel.srcR = srcR;
886 return i;
887}
888PPC32Instr* PPC32Instr_AvShlDbl ( UChar shift, HReg dst, HReg srcL, HReg srcR ) {
889 PPC32Instr* i = LibVEX_Alloc(sizeof(PPC32Instr));
890 i->tag = Pin_AvShlDbl;
891 i->Pin.AvShlDbl.shift = shift;
892 i->Pin.AvShlDbl.dst = dst;
893 i->Pin.AvShlDbl.srcL = srcL;
894 i->Pin.AvShlDbl.srcR = srcR;
895 return i;
896}
897PPC32Instr* PPC32Instr_AvSplat ( UChar sz, HReg dst, PPC32RI* src ) {
898 PPC32Instr* i = LibVEX_Alloc(sizeof(PPC32Instr));
899 i->tag = Pin_AvSplat;
900 i->Pin.AvSplat.sz = sz;
901 i->Pin.AvSplat.dst = dst;
902 i->Pin.AvSplat.src = src;
903 return i;
904}
cerion6b6f59e2005-06-28 20:59:18 +0000905PPC32Instr* PPC32Instr_AvCMov ( PPC32CondCode cond, HReg dst, HReg src ) {
906 PPC32Instr* i = LibVEX_Alloc(sizeof(PPC32Instr));
907 i->tag = Pin_AvCMov;
908 i->Pin.AvCMov.cond = cond;
909 i->Pin.AvCMov.dst = dst;
910 i->Pin.AvCMov.src = src;
911 vassert(cond.test != Pct_ALWAYS);
912 return i;
913}
cerionc3d8bdc2005-06-28 18:06:23 +0000914PPC32Instr* PPC32Instr_AvLdVSCR ( HReg src ) {
915 PPC32Instr* i = LibVEX_Alloc(sizeof(PPC32Instr));
916 i->tag = Pin_AvLdVSCR;
917 i->Pin.AvLdVSCR.src = src;
918 return i;
919}
920
cerion9e263e32005-03-03 17:21:51 +0000921
922/* Pretty Print instructions */
923static void ppLoadImm ( HReg dst, UInt imm ) {
924 if (imm < 0x10000) {
925 vex_printf("li ");
926 ppHRegPPC32(dst);
927 vex_printf(",0x%x", imm);
928 } else {
929 vex_printf("lis ");
930 ppHRegPPC32(dst);
931 vex_printf(",0x%x ; ", imm >> 16);
932 vex_printf("ori ");
933 ppHRegPPC32(dst);
934 vex_printf(",");
935 ppHRegPPC32(dst);
936 vex_printf(",0x%x", imm & 0xFFFF);
937 }
938}
939
940static void ppMovReg ( HReg dst, HReg src ) {
941 if (hregNumber(dst) != hregNumber(src)) {
942 vex_printf("mr ");
943 ppHRegPPC32(dst);
944 vex_printf(",");
945 ppHRegPPC32(src);
946 }
947}
948
cerionbcf8c3e2005-02-04 16:17:07 +0000949void ppPPC32Instr ( PPC32Instr* i )
950{
951 switch (i->tag) {
cerionb85e8bb2005-02-16 08:54:33 +0000952 case Pin_Alu32:
953 if (i->Pin.Alu32.op == Palu_OR && // or Rd,Rs,Rs == mr Rd,Rs
ceriona2f75882005-03-15 16:33:38 +0000954 i->Pin.Alu32.srcR->tag == Pri_Reg &&
955 i->Pin.Alu32.srcR->Pri.Reg.reg == i->Pin.Alu32.srcL) {
cerionb85e8bb2005-02-16 08:54:33 +0000956 vex_printf("mr ");
957 ppHRegPPC32(i->Pin.Alu32.dst);
cerioncd304492005-02-08 19:40:24 +0000958 vex_printf(",");
ceriona2f75882005-03-15 16:33:38 +0000959 ppHRegPPC32(i->Pin.Alu32.srcL);
cerioncd304492005-02-08 19:40:24 +0000960 return;
cerionb85e8bb2005-02-16 08:54:33 +0000961 }
cerion9e263e32005-03-03 17:21:51 +0000962 if (i->Pin.Alu32.op == Palu_ADD && // add rD,r0,val == li rD,val
ceriona2f75882005-03-15 16:33:38 +0000963 i->Pin.Alu32.srcL == hregPPC32_GPR0() &&
964 i->Pin.Alu32.srcR->tag == Pri_Imm) {
cerionb85e8bb2005-02-16 08:54:33 +0000965 vex_printf("li ");
966 ppHRegPPC32(i->Pin.Alu32.dst);
967 vex_printf(",");
ceriona2f75882005-03-15 16:33:38 +0000968 ppPPC32RI(i->Pin.Alu32.srcR);
cerionb85e8bb2005-02-16 08:54:33 +0000969 return;
970 }
cerionb8c3b7f2005-03-01 20:27:49 +0000971 if (i->Pin.Alu32.op == Palu_AND && // 'andi.' - always has the '.'
ceriona2f75882005-03-15 16:33:38 +0000972 i->Pin.Alu32.srcR->tag == Pri_Imm) {
cerionb8c3b7f2005-03-01 20:27:49 +0000973 vex_printf("andi. ");
974 ppHRegPPC32(i->Pin.Alu32.dst);
975 vex_printf(",");
ceriona2f75882005-03-15 16:33:38 +0000976 ppHRegPPC32(i->Pin.Alu32.srcL);
cerionb8c3b7f2005-03-01 20:27:49 +0000977 vex_printf(",");
ceriona2f75882005-03-15 16:33:38 +0000978 ppPPC32RI(i->Pin.Alu32.srcR);
cerionb8c3b7f2005-03-01 20:27:49 +0000979 return;
980 }
cerionb85e8bb2005-02-16 08:54:33 +0000981 vex_printf("%s%s ", showPPC32AluOp(i->Pin.Alu32.op),
ceriona2f75882005-03-15 16:33:38 +0000982 i->Pin.Alu32.srcR->tag == Pri_Imm ? "i" : "" );
cerionb85e8bb2005-02-16 08:54:33 +0000983 ppHRegPPC32(i->Pin.Alu32.dst);
984 vex_printf(",");
ceriona2f75882005-03-15 16:33:38 +0000985 ppHRegPPC32(i->Pin.Alu32.srcL);
cerionb85e8bb2005-02-16 08:54:33 +0000986 vex_printf(",");
ceriona2f75882005-03-15 16:33:38 +0000987 ppPPC32RI(i->Pin.Alu32.srcR);
cerionb85e8bb2005-02-16 08:54:33 +0000988 return;
cerion5e2527e2005-02-25 16:39:58 +0000989 case Pin_Sub32:
ceriona2f75882005-03-15 16:33:38 +0000990 vex_printf("subf%s ", i->Pin.Sub32.srcL->tag == Pri_Imm ? "ic" : "" );
cerion5e2527e2005-02-25 16:39:58 +0000991 ppHRegPPC32(i->Pin.Sub32.dst);
992 vex_printf(",");
ceriona2f75882005-03-15 16:33:38 +0000993 ppHRegPPC32(i->Pin.Sub32.srcR); // yes, order is right :-)
cerion5e2527e2005-02-25 16:39:58 +0000994 vex_printf(",");
ceriona2f75882005-03-15 16:33:38 +0000995 ppPPC32RI(i->Pin.Sub32.srcL);
cerion5e2527e2005-02-25 16:39:58 +0000996 return;
cerionb85e8bb2005-02-16 08:54:33 +0000997 case Pin_Sh32:
998 vex_printf("%s%s ", showPPC32ShiftOp(i->Pin.Sh32.op),
999 i->Pin.Sh32.shft->tag == Pri_Imm ? "i" : "" );
1000 ppHRegPPC32(i->Pin.Sh32.dst);
1001 vex_printf(",");
1002 ppHRegPPC32(i->Pin.Sh32.src);
1003 vex_printf(",");
1004 ppPPC32RI(i->Pin.Sh32.shft);
1005 return;
cerionb85e8bb2005-02-16 08:54:33 +00001006 case Pin_Cmp32:
sewardj428fabd2005-03-21 03:11:17 +00001007 vex_printf("%s%s %%crf%u,", showPPC32CmpOp(i->Pin.Cmp32.op),
ceriona2f75882005-03-15 16:33:38 +00001008 i->Pin.Cmp32.srcR->tag == Pri_Imm ? "i" : "",
cerion8c51ed42005-02-22 11:16:54 +00001009 (7 - i->Pin.Cmp32.crfD));
ceriona2f75882005-03-15 16:33:38 +00001010 ppHRegPPC32(i->Pin.Cmp32.srcL);
cerionb85e8bb2005-02-16 08:54:33 +00001011 vex_printf(",");
ceriona2f75882005-03-15 16:33:38 +00001012 ppPPC32RI(i->Pin.Cmp32.srcR);
cerionb85e8bb2005-02-16 08:54:33 +00001013 return;
1014 case Pin_Unary32:
1015 vex_printf("%s ", showPPC32UnaryOp(i->Pin.Unary32.op));
1016 ppHRegPPC32(i->Pin.Unary32.dst);
1017 vex_printf(",");
1018 ppHRegPPC32(i->Pin.Unary32.src);
1019 return;
1020 case Pin_MulL:
ceriona2f75882005-03-15 16:33:38 +00001021 if (i->Pin.MulL.srcR->tag == Pri_Imm) {
cerionb85e8bb2005-02-16 08:54:33 +00001022 vex_printf("mulli ");
1023 } else {
1024 vex_printf("mul%s%c ",
1025 i->Pin.MulL.word ? "hw" : "lw",
1026 i->Pin.MulL.syned ? 's' : 'u');
1027 }
1028 ppHRegPPC32(i->Pin.MulL.dst);
1029 vex_printf(",");
ceriona2f75882005-03-15 16:33:38 +00001030 ppHRegPPC32(i->Pin.MulL.srcL);
cerionb85e8bb2005-02-16 08:54:33 +00001031 vex_printf(",");
ceriona2f75882005-03-15 16:33:38 +00001032 ppPPC32RI(i->Pin.MulL.srcR);
cerionb85e8bb2005-02-16 08:54:33 +00001033 return;
1034 case Pin_Div:
1035 vex_printf("divw%s ",
1036 i->Pin.Div.syned ? "" : "u");
cerion33aa6da2005-02-16 10:25:26 +00001037 ppHRegPPC32(i->Pin.Div.dst);
cerionb85e8bb2005-02-16 08:54:33 +00001038 vex_printf(",");
ceriona2f75882005-03-15 16:33:38 +00001039 ppHRegPPC32(i->Pin.Div.srcL);
cerionb85e8bb2005-02-16 08:54:33 +00001040 vex_printf(",");
ceriona2f75882005-03-15 16:33:38 +00001041 ppHRegPPC32(i->Pin.Div.srcR);
cerionb85e8bb2005-02-16 08:54:33 +00001042 return;
cerionb85e8bb2005-02-16 08:54:33 +00001043 case Pin_Call:
cerion8c51ed42005-02-22 11:16:54 +00001044 vex_printf("call: ");
1045 if (i->Pin.Call.cond.test != Pct_ALWAYS) {
1046 vex_printf("if (%%crf0.%s) ", showPPC32CondCode(i->Pin.Call.cond));
1047 }
1048 vex_printf("{ ");
cerion9e263e32005-03-03 17:21:51 +00001049 ppLoadImm(hregPPC32_GPR12(), i->Pin.Call.target);
cerion9762bbf2005-06-23 08:44:52 +00001050 vex_printf(" ; mtctr r12 ; bctrl [regparms=%d] }",i->Pin.Call.regparms);
cerionb85e8bb2005-02-16 08:54:33 +00001051 break;
1052 case Pin_Goto:
cerion33aa6da2005-02-16 10:25:26 +00001053 vex_printf("goto: ");
cerionb85e8bb2005-02-16 08:54:33 +00001054 if (i->Pin.Goto.cond.test != Pct_ALWAYS) {
cerion8c51ed42005-02-22 11:16:54 +00001055 vex_printf("if (%%crf0.%s) ", showPPC32CondCode(i->Pin.Goto.cond));
cerionb85e8bb2005-02-16 08:54:33 +00001056 }
cerion8c51ed42005-02-22 11:16:54 +00001057 vex_printf("{ ");
cerionb85e8bb2005-02-16 08:54:33 +00001058 if (i->Pin.Goto.jk != Ijk_Boring) {
cerion9e263e32005-03-03 17:21:51 +00001059 vex_printf("li %%r31,$");
cerionb85e8bb2005-02-16 08:54:33 +00001060 ppIRJumpKind(i->Pin.Goto.jk);
1061 vex_printf(" ; ");
1062 }
cerione97e1062005-02-21 15:09:19 +00001063 if (i->Pin.Goto.dst->tag == Pri_Imm) {
cerion9e263e32005-03-03 17:21:51 +00001064 ppLoadImm(hregPPC32_GPR3(), i->Pin.Goto.dst->Pri.Imm.imm32);
cerione97e1062005-02-21 15:09:19 +00001065 } else {
cerion9e263e32005-03-03 17:21:51 +00001066 ppMovReg(hregPPC32_GPR3(), i->Pin.Goto.dst->Pri.Reg.reg);
cerione97e1062005-02-21 15:09:19 +00001067 }
cerion9e263e32005-03-03 17:21:51 +00001068 vex_printf(" ; blr }");
cerionb85e8bb2005-02-16 08:54:33 +00001069 return;
1070 case Pin_CMov32:
cerionb85e8bb2005-02-16 08:54:33 +00001071 vex_printf("cmov32 (%s) ", showPPC32CondCode(i->Pin.CMov32.cond));
1072 ppHRegPPC32(i->Pin.CMov32.dst);
1073 vex_printf(",");
1074 ppPPC32RI(i->Pin.CMov32.src);
cerion8c51ed42005-02-22 11:16:54 +00001075 vex_printf(": ");
1076 if (i->Pin.CMov32.cond.test != Pct_ALWAYS) {
1077 vex_printf("if (%%crf0.%s) ", showPPC32CondCode(i->Pin.CMov32.cond));
1078 }
1079 vex_printf("{ ");
1080 if (i->Pin.CMov32.src->tag == Pri_Imm) {
cerion9e263e32005-03-03 17:21:51 +00001081 ppLoadImm(i->Pin.CMov32.dst, i->Pin.CMov32.src->Pri.Imm.imm32);
cerion8c51ed42005-02-22 11:16:54 +00001082 } else {
cerion9e263e32005-03-03 17:21:51 +00001083 ppMovReg(i->Pin.CMov32.dst, i->Pin.CMov32.src->Pri.Reg.reg);
cerion8c51ed42005-02-22 11:16:54 +00001084 }
1085 vex_printf(" }");
cerionb85e8bb2005-02-16 08:54:33 +00001086 return;
cerion7cf8e4e2005-02-16 16:08:17 +00001087 case Pin_Load: {
1088 UChar sz = i->Pin.Load.sz;
1089 Bool syned = i->Pin.Load.syned;
sewardj428fabd2005-03-21 03:11:17 +00001090 Bool idxd = toBool(i->Pin.Load.src->tag == Pam_RR);
cerion7cf8e4e2005-02-16 16:08:17 +00001091 vex_printf("l%c%c%s ",
cerionb85e8bb2005-02-16 08:54:33 +00001092 (sz==1) ? 'b' : (sz==2 ? 'h' : 'w'),
1093 syned ? 'a' : 'z',
cerionb85e8bb2005-02-16 08:54:33 +00001094 idxd ? "x" : "" );
cerion7cf8e4e2005-02-16 16:08:17 +00001095 ppHRegPPC32(i->Pin.Load.dst);
cerionb85e8bb2005-02-16 08:54:33 +00001096 vex_printf(",");
cerion7cf8e4e2005-02-16 16:08:17 +00001097 ppPPC32AMode(i->Pin.Load.src);
cerionb85e8bb2005-02-16 08:54:33 +00001098 return;
1099 }
1100 case Pin_Store: {
1101 UChar sz = i->Pin.Store.sz;
sewardj428fabd2005-03-21 03:11:17 +00001102 Bool idxd = toBool(i->Pin.Store.dst->tag == Pam_RR);
cerion7cf8e4e2005-02-16 16:08:17 +00001103 vex_printf("st%c%s ",
cerionb85e8bb2005-02-16 08:54:33 +00001104 (sz==1) ? 'b' : (sz==2 ? 'h' : 'w'),
cerionb85e8bb2005-02-16 08:54:33 +00001105 idxd ? "x" : "" );
1106 ppHRegPPC32(i->Pin.Store.src);
1107 vex_printf(",");
1108 ppPPC32AMode(i->Pin.Store.dst);
1109 return;
1110 }
cerionf9d6e222005-02-23 18:21:31 +00001111 case Pin_Set32: {
1112 PPC32CondCode cc = i->Pin.Set32.cond;
1113 vex_printf("set32 (%s),", showPPC32CondCode(cc));
cerionb85e8bb2005-02-16 08:54:33 +00001114 ppHRegPPC32(i->Pin.Set32.dst);
cerionf9d6e222005-02-23 18:21:31 +00001115 if (cc.test == Pct_ALWAYS) {
1116 vex_printf(": { li ");
1117 ppHRegPPC32(i->Pin.Set32.dst);
1118 vex_printf(",1 }");
1119 } else {
1120 vex_printf(": { mfcr r0 ; rlwinm ");
1121 ppHRegPPC32(i->Pin.Set32.dst);
sewardj428fabd2005-03-21 03:11:17 +00001122 vex_printf(",r0,%u,31,31", cc.flag+1);
cerionf9d6e222005-02-23 18:21:31 +00001123 if (cc.test == Pct_FALSE) {
1124 vex_printf("; xori ");
1125 ppHRegPPC32(i->Pin.Set32.dst);
1126 vex_printf(",");
1127 ppHRegPPC32(i->Pin.Set32.dst);
1128 vex_printf("1");
1129 }
1130 vex_printf(" }");
1131 }
cerionb85e8bb2005-02-16 08:54:33 +00001132 return;
cerionf9d6e222005-02-23 18:21:31 +00001133 }
cerionb85e8bb2005-02-16 08:54:33 +00001134 case Pin_MFence:
cerion98411db2005-02-16 14:14:49 +00001135 vex_printf("mfence (=sync)");
cerionb85e8bb2005-02-16 08:54:33 +00001136 return;
cerion094d1392005-06-20 13:45:57 +00001137
1138 case Pin_FpUnary:
1139 vex_printf("%s ", showPPC32FpOp(i->Pin.FpUnary.op));
1140 ppHRegPPC32(i->Pin.FpUnary.dst);
1141 vex_printf(",");
1142 ppHRegPPC32(i->Pin.FpUnary.src);
1143 return;
1144 case Pin_FpBinary:
1145 vex_printf("%s ", showPPC32FpOp(i->Pin.FpBinary.op));
1146 ppHRegPPC32(i->Pin.FpBinary.dst);
1147 vex_printf(",");
1148 ppHRegPPC32(i->Pin.FpBinary.srcL);
1149 vex_printf(",");
1150 ppHRegPPC32(i->Pin.FpBinary.srcR);
1151 return;
1152 case Pin_FpLdSt: {
1153 UChar sz = i->Pin.FpLdSt.sz;
1154 Bool idxd = toBool(i->Pin.FpLdSt.addr->tag == Pam_RR);
1155 if (i->Pin.FpLdSt.isLoad) {
1156 vex_printf("lf%c%s ",
1157 (sz==4 ? 's' : 'd'),
1158 idxd ? "x" : "" );
1159 ppHRegPPC32(i->Pin.FpLdSt.reg);
1160 vex_printf(",");
1161 ppPPC32AMode(i->Pin.FpLdSt.addr);
1162 } else {
1163 vex_printf("stf%c%s ",
1164 (sz==4 ? 's' : 'd'),
1165 idxd ? "x" : "" );
1166 ppHRegPPC32(i->Pin.FpLdSt.reg);
1167 vex_printf(",");
1168 ppPPC32AMode(i->Pin.FpLdSt.addr);
1169 }
1170 return;
1171 }
1172 case Pin_FpF64toF32:
1173 vex_printf("frsp ");
1174 ppHRegPPC32(i->Pin.FpF64toF32.dst);
1175 vex_printf(",");
1176 ppHRegPPC32(i->Pin.FpF64toF32.src);
1177 return;
1178 case Pin_FpF64toI32:
1179 vex_printf("fctiw %%fr7,");
1180 ppHRegPPC32(i->Pin.FpF64toI32.src);
1181 vex_printf("; stfiwx %%fr7,%%r0,%%r1");
1182 vex_printf("; lwzx ");
1183 ppHRegPPC32(i->Pin.FpF64toI32.dst);
1184 vex_printf(",%%r0,%%r1");
1185 return;
1186 case Pin_FpCMov:
1187 vex_printf("fpcmov (%s) ", showPPC32CondCode(i->Pin.FpCMov.cond));
1188 ppHRegPPC32(i->Pin.FpCMov.dst);
1189 vex_printf(",");
1190 ppHRegPPC32(i->Pin.FpCMov.src);
1191 vex_printf(": ");
1192 vex_printf("if (fr_dst != fr_src) { ");
1193 if (i->Pin.FpCMov.cond.test != Pct_ALWAYS) {
1194 vex_printf("if (%%crf0.%s) { ", showPPC32CondCode(i->Pin.FpCMov.cond));
1195 }
1196 vex_printf("fmr ");
1197 ppHRegPPC32(i->Pin.FpCMov.dst);
1198 vex_printf(",");
1199 ppHRegPPC32(i->Pin.FpCMov.src);
1200 if (i->Pin.FpCMov.cond.test != Pct_ALWAYS)
1201 vex_printf(" }");
1202 vex_printf(" }");
1203 return;
1204 case Pin_FpLdFPSCR:
1205 vex_printf("mtfsf 0xFF,");
1206 ppHRegPPC32(i->Pin.FpLdFPSCR.src);
1207 return;
1208 case Pin_FpCmp:
1209 vex_printf("fcmpo %%crf1,");
1210 ppHRegPPC32(i->Pin.FpCmp.srcL);
1211 vex_printf(",");
1212 ppHRegPPC32(i->Pin.FpCmp.srcR);
1213 vex_printf("; mfcr ");
1214 ppHRegPPC32(i->Pin.FpCmp.dst);
1215 vex_printf("; rlwinm ");
1216 ppHRegPPC32(i->Pin.FpCmp.dst);
1217 vex_printf(",");
1218 ppHRegPPC32(i->Pin.FpCmp.dst);
1219 vex_printf(",8,28,31");
1220 return;
cerionbcf8c3e2005-02-04 16:17:07 +00001221
cerion7f000af2005-02-22 20:36:49 +00001222 case Pin_RdWrLR:
1223 vex_printf("%s ", i->Pin.RdWrLR.wrLR ? "mtlr" : "mflr");
1224 ppHRegPPC32(i->Pin.RdWrLR.gpr);
1225 return;
1226
cerionc3d8bdc2005-06-28 18:06:23 +00001227 case Pin_AvLdSt: {
1228 UChar sz = i->Pin.AvLdSt.sz;
cerionc3d8bdc2005-06-28 18:06:23 +00001229 if (i->Pin.AvLdSt.addr->tag == Pam_IR) {
1230 vex_printf("{ ");
1231 ppLoadImm(hregPPC32_GPR30(), i->Pin.AvLdSt.addr->Pam.RR.index);
1232 vex_printf(" }");
1233 }
1234 if (i->Pin.AvLdSt.isLoad) {
cerion91c62fd2005-06-29 07:59:18 +00001235 vex_printf("lv%sx ", sz==8 ? "eb" : sz==16 ? "eh" : sz==32 ? "ew" : "");
cerionc3d8bdc2005-06-28 18:06:23 +00001236 ppHRegPPC32(i->Pin.AvLdSt.reg);
1237 vex_printf(",");
1238 ppPPC32AMode(i->Pin.AvLdSt.addr);
1239 } else {
cerion91c62fd2005-06-29 07:59:18 +00001240 vex_printf("stv%sx ", sz==8 ? "eb" : sz==16 ? "eh" : sz==32 ? "ew" : "");
cerionc3d8bdc2005-06-28 18:06:23 +00001241 ppHRegPPC32(i->Pin.AvLdSt.reg);
1242 vex_printf(",");
1243 ppPPC32AMode(i->Pin.AvLdSt.addr);
1244 }
1245 return;
1246 }
1247 case Pin_AvUnary:
1248 vex_printf("%s ", showPPC32AvOp(i->Pin.AvUnary.op));
1249 ppHRegPPC32(i->Pin.AvUnary.dst);
1250 vex_printf(",");
1251 ppHRegPPC32(i->Pin.AvUnary.src);
1252 return;
1253 case Pin_AvBinary:
1254 vex_printf("%s ", showPPC32AvOp(i->Pin.AvBinary.op));
1255 ppHRegPPC32(i->Pin.AvBinary.dst);
1256 vex_printf(",");
1257 ppHRegPPC32(i->Pin.AvBinary.srcL);
1258 vex_printf(",");
1259 ppHRegPPC32(i->Pin.AvBinary.srcR);
1260 return;
cerion6b6f59e2005-06-28 20:59:18 +00001261 case Pin_AvBin8x16:
1262 vex_printf("%s(b) ", showPPC32AvOp(i->Pin.AvBin8x16.op));
1263 ppHRegPPC32(i->Pin.AvBin8x16.dst);
1264 vex_printf(",");
1265 ppHRegPPC32(i->Pin.AvBin8x16.srcL);
1266 vex_printf(",");
1267 ppHRegPPC32(i->Pin.AvBin8x16.srcR);
1268 return;
1269 case Pin_AvBin16x8:
1270 vex_printf("%s(h) ", showPPC32AvOp(i->Pin.AvBin16x8.op));
1271 ppHRegPPC32(i->Pin.AvBin16x8.dst);
1272 vex_printf(",");
1273 ppHRegPPC32(i->Pin.AvBin16x8.srcL);
1274 vex_printf(",");
1275 ppHRegPPC32(i->Pin.AvBin16x8.srcR);
1276 return;
1277 case Pin_AvBin32x4:
1278 vex_printf("%s(w) ", showPPC32AvOp(i->Pin.AvBin32x4.op));
1279 ppHRegPPC32(i->Pin.AvBin32x4.dst);
1280 vex_printf(",");
1281 ppHRegPPC32(i->Pin.AvBin32x4.srcL);
1282 vex_printf(",");
1283 ppHRegPPC32(i->Pin.AvBin32x4.srcR);
1284 return;
1285 case Pin_AvBin32Fx4:
1286 vex_printf("%s ", showPPC32AvOp(i->Pin.AvBin32Fx4.op));
1287 ppHRegPPC32(i->Pin.AvBin32Fx4.dst);
1288 vex_printf(",");
1289 ppHRegPPC32(i->Pin.AvBin32Fx4.srcL);
1290 vex_printf(",");
1291 ppHRegPPC32(i->Pin.AvBin32Fx4.srcR);
1292 return;
cerionc3d8bdc2005-06-28 18:06:23 +00001293 case Pin_AvPerm:
1294 vex_printf("vperm ");
1295 ppHRegPPC32(i->Pin.AvPerm.dst);
1296 vex_printf(",");
1297 ppHRegPPC32(i->Pin.AvPerm.srcL);
1298 vex_printf(",");
1299 ppHRegPPC32(i->Pin.AvPerm.srcR);
1300 vex_printf(",");
1301 ppHRegPPC32(i->Pin.AvPerm.ctl);
1302 return;
1303
1304 case Pin_AvSel:
1305 vex_printf("vsel ");
1306 ppHRegPPC32(i->Pin.AvSel.dst);
1307 vex_printf(",");
1308 ppHRegPPC32(i->Pin.AvSel.srcL);
1309 vex_printf(",");
1310 ppHRegPPC32(i->Pin.AvSel.srcR);
1311 vex_printf(",");
1312 ppHRegPPC32(i->Pin.AvSel.ctl);
1313 return;
1314
1315 case Pin_AvShlDbl:
1316 vex_printf("vsldoi ");
1317 ppHRegPPC32(i->Pin.AvShlDbl.dst);
1318 vex_printf(",");
1319 ppHRegPPC32(i->Pin.AvShlDbl.srcL);
1320 vex_printf(",");
1321 ppHRegPPC32(i->Pin.AvShlDbl.srcR);
1322 vex_printf(",%u", i->Pin.AvShlDbl.shift);
1323 return;
1324
1325 case Pin_AvSplat: {
1326 UChar ch_sz = (i->Pin.AvSplat.sz == 8) ? 'b' :
1327 (i->Pin.AvSplat.sz == 16) ? 'h' : 'w';
1328 vex_printf("vsplt%s%c ",
1329 i->Pin.AvSplat.src->tag == Pri_Imm ? "is" : "", ch_sz);
1330 ppHRegPPC32(i->Pin.AvSplat.dst);
1331 vex_printf(",");
1332 if (i->Pin.AvSplat.src->tag == Pri_Imm) {
1333 vex_printf("%d", (Char)(i->Pin.AvSplat.src->Pri.Imm.imm32));
1334 } else {
1335 ppHRegPPC32(i->Pin.AvSplat.src->Pri.Reg.reg);
1336 vex_printf(", 0");
1337 }
1338 return;
1339 }
1340
cerion6b6f59e2005-06-28 20:59:18 +00001341 case Pin_AvCMov:
1342 vex_printf("avcmov (%s) ", showPPC32CondCode(i->Pin.AvCMov.cond));
1343 ppHRegPPC32(i->Pin.AvCMov.dst);
1344 vex_printf(",");
1345 ppHRegPPC32(i->Pin.AvCMov.src);
1346 vex_printf(": ");
1347 vex_printf("if (v_dst != v_src) { ");
1348 if (i->Pin.AvCMov.cond.test != Pct_ALWAYS) {
1349 vex_printf("if (%%crf0.%s) { ", showPPC32CondCode(i->Pin.AvCMov.cond));
1350 }
1351 vex_printf("vmr ");
1352 ppHRegPPC32(i->Pin.AvCMov.dst);
1353 vex_printf(",");
1354 ppHRegPPC32(i->Pin.AvCMov.src);
1355 if (i->Pin.FpCMov.cond.test != Pct_ALWAYS)
1356 vex_printf(" }");
1357 vex_printf(" }");
1358 return;
1359
cerionc3d8bdc2005-06-28 18:06:23 +00001360 case Pin_AvLdVSCR:
1361 vex_printf("mtvscr ");
1362 ppHRegPPC32(i->Pin.AvLdVSCR.src);
1363 return;
1364
cerionb85e8bb2005-02-16 08:54:33 +00001365 default:
sewardj428fabd2005-03-21 03:11:17 +00001366 vex_printf("\nppPPC32Instr(ppc32): No such tag(%d)\n", (Int)i->tag);
cerionb85e8bb2005-02-16 08:54:33 +00001367 vpanic("ppPPC32Instr(ppc32)");
cerionbcf8c3e2005-02-04 16:17:07 +00001368 }
1369}
1370
1371/* --------- Helpers for register allocation. --------- */
1372
1373void getRegUsage_PPC32Instr ( HRegUsage* u, PPC32Instr* i )
1374{
1375// Bool unary;
1376 initHRegUsage(u);
1377 switch (i->tag) {
cerionb85e8bb2005-02-16 08:54:33 +00001378 case Pin_Alu32:
ceriona2f75882005-03-15 16:33:38 +00001379 addHRegUse(u, HRmRead, i->Pin.Alu32.srcL);
1380 addRegUsage_PPC32RI(u, i->Pin.Alu32.srcR);
cerionb85e8bb2005-02-16 08:54:33 +00001381 addHRegUse(u, HRmWrite, i->Pin.Alu32.dst);
cerionb85e8bb2005-02-16 08:54:33 +00001382 return;
cerioncd304492005-02-08 19:40:24 +00001383
cerion5e2527e2005-02-25 16:39:58 +00001384 case Pin_Sub32:
ceriona2f75882005-03-15 16:33:38 +00001385 addRegUsage_PPC32RI(u, i->Pin.Sub32.srcL);
1386 addHRegUse(u, HRmRead, i->Pin.Sub32.srcR);
cerion5e2527e2005-02-25 16:39:58 +00001387 addHRegUse(u, HRmWrite, i->Pin.Sub32.dst);
1388 return;
1389
cerionb85e8bb2005-02-16 08:54:33 +00001390 case Pin_Sh32:
1391 addHRegUse(u, HRmWrite, i->Pin.Sh32.dst);
1392 addHRegUse(u, HRmRead, i->Pin.Sh32.src);
1393 addRegUsage_PPC32RI(u, i->Pin.Sh32.shft);
cerionb85e8bb2005-02-16 08:54:33 +00001394 return;
1395
cerionb85e8bb2005-02-16 08:54:33 +00001396 case Pin_Cmp32:
ceriona2f75882005-03-15 16:33:38 +00001397 addHRegUse(u, HRmRead, i->Pin.Cmp32.srcL);
1398 addRegUsage_PPC32RI(u, i->Pin.Cmp32.srcR);
cerionb85e8bb2005-02-16 08:54:33 +00001399 return;
cerionab9132d2005-02-15 15:46:59 +00001400
cerionb85e8bb2005-02-16 08:54:33 +00001401 case Pin_Unary32:
1402 addHRegUse(u, HRmWrite, i->Pin.Unary32.dst);
1403 addHRegUse(u, HRmRead, i->Pin.Unary32.src);
1404 return;
1405 case Pin_MulL:
1406 addHRegUse(u, HRmWrite, i->Pin.MulL.dst);
ceriona2f75882005-03-15 16:33:38 +00001407 addHRegUse(u, HRmRead, i->Pin.MulL.srcL);
1408 addRegUsage_PPC32RI(u, i->Pin.MulL.srcR);
cerionb85e8bb2005-02-16 08:54:33 +00001409 return;
1410 case Pin_Div:
1411 addHRegUse(u, HRmWrite, i->Pin.Div.dst);
ceriona2f75882005-03-15 16:33:38 +00001412 addHRegUse(u, HRmRead, i->Pin.Div.srcL);
1413 addHRegUse(u, HRmRead, i->Pin.Div.srcR);
cerionb85e8bb2005-02-16 08:54:33 +00001414 return;
cerionb85e8bb2005-02-16 08:54:33 +00001415 case Pin_Call:
1416 /* This is a bit subtle. */
1417 /* First off, claim it trashes all the caller-saved regs
1418 which fall within the register allocator's jurisdiction.
ceriona56e9cc2005-02-16 18:08:25 +00001419 These I believe to be: r3:12
cerionb85e8bb2005-02-16 08:54:33 +00001420 */
cerionb85e8bb2005-02-16 08:54:33 +00001421 addHRegUse(u, HRmWrite, hregPPC32_GPR3());
1422 addHRegUse(u, HRmWrite, hregPPC32_GPR4());
1423 addHRegUse(u, HRmWrite, hregPPC32_GPR5());
1424 addHRegUse(u, HRmWrite, hregPPC32_GPR6());
1425 addHRegUse(u, HRmWrite, hregPPC32_GPR7());
1426 addHRegUse(u, HRmWrite, hregPPC32_GPR8());
1427 addHRegUse(u, HRmWrite, hregPPC32_GPR9());
1428 addHRegUse(u, HRmWrite, hregPPC32_GPR10());
1429 addHRegUse(u, HRmWrite, hregPPC32_GPR11());
1430 addHRegUse(u, HRmWrite, hregPPC32_GPR12());
1431
1432 /* Now we have to state any parameter-carrying registers
1433 which might be read. This depends on the regparmness. */
1434 switch (i->Pin.Call.regparms) {
1435 case 8: addHRegUse(u, HRmRead, hregPPC32_GPR10()); /*fallthru*/
1436 case 7: addHRegUse(u, HRmRead, hregPPC32_GPR9() ); /*fallthru*/
1437 case 6: addHRegUse(u, HRmRead, hregPPC32_GPR8() ); /*fallthru*/
1438 case 5: addHRegUse(u, HRmRead, hregPPC32_GPR7() ); /*fallthru*/
1439 case 4: addHRegUse(u, HRmRead, hregPPC32_GPR6() ); /*fallthru*/
1440 case 3: addHRegUse(u, HRmRead, hregPPC32_GPR5() ); /*fallthru*/
1441 case 2: addHRegUse(u, HRmRead, hregPPC32_GPR4() ); /*fallthru*/
1442 case 1: addHRegUse(u, HRmRead, hregPPC32_GPR3() ); /*fallthru*/
1443 case 0: break;
1444 default: vpanic("getRegUsage_PPC32Instr:Call:regparms");
1445 }
1446 /* Finally, there is the issue that the insn trashes a
1447 register because the literal target address has to be
ceriona56e9cc2005-02-16 18:08:25 +00001448 loaded into a register. %r12 seems a suitable victim.
1449 (Can't use %r0, as use ops that interpret it as value zero). */
cerionb85e8bb2005-02-16 08:54:33 +00001450 addHRegUse(u, HRmWrite, hregPPC32_GPR12());
1451 /* Upshot of this is that the assembler really must use %r12,
ceriona56e9cc2005-02-16 18:08:25 +00001452 and no other, as a destination temporary. */
cerionb85e8bb2005-02-16 08:54:33 +00001453 return;
1454 case Pin_Goto:
1455 addRegUsage_PPC32RI(u, i->Pin.Goto.dst);
ceriona56e9cc2005-02-16 18:08:25 +00001456 /* GPR3 holds destination address from Pin_Goto */
1457 addHRegUse(u, HRmWrite, hregPPC32_GPR3());
cerionb85e8bb2005-02-16 08:54:33 +00001458 if (i->Pin.Goto.jk != Ijk_Boring)
1459 addHRegUse(u, HRmWrite, GuestStatePtr);
1460 return;
1461 case Pin_CMov32:
1462 addRegUsage_PPC32RI(u, i->Pin.CMov32.src);
cerioned623db2005-06-20 12:42:04 +00001463 addHRegUse(u, HRmWrite, i->Pin.CMov32.dst);
cerionb85e8bb2005-02-16 08:54:33 +00001464 return;
cerion7cf8e4e2005-02-16 16:08:17 +00001465 case Pin_Load:
1466 addRegUsage_PPC32AMode(u, i->Pin.Load.src);
1467 addHRegUse(u, HRmWrite, i->Pin.Load.dst);
cerionb85e8bb2005-02-16 08:54:33 +00001468 return;
1469 case Pin_Store:
1470 addHRegUse(u, HRmRead, i->Pin.Store.src);
1471 addRegUsage_PPC32AMode(u, i->Pin.Store.dst);
1472 return;
1473 case Pin_Set32:
1474 addHRegUse(u, HRmWrite, i->Pin.Set32.dst);
1475 return;
cerionb85e8bb2005-02-16 08:54:33 +00001476 case Pin_MFence:
1477 return;
cerion094d1392005-06-20 13:45:57 +00001478
1479 case Pin_FpUnary:
1480 addHRegUse(u, HRmWrite, i->Pin.FpUnary.dst);
1481 addHRegUse(u, HRmRead, i->Pin.FpUnary.src);
1482 return;
1483 case Pin_FpBinary:
1484 addHRegUse(u, HRmWrite, i->Pin.FpBinary.dst);
1485 addHRegUse(u, HRmRead, i->Pin.FpBinary.srcL);
1486 addHRegUse(u, HRmRead, i->Pin.FpBinary.srcR);
1487 return;
1488 case Pin_FpLdSt:
1489 addHRegUse(u, (i->Pin.FpLdSt.isLoad ? HRmWrite : HRmRead),
1490 i->Pin.FpLdSt.reg);
1491 addRegUsage_PPC32AMode(u, i->Pin.FpLdSt.addr);
1492 return;
1493 case Pin_FpF64toF32:
1494 addHRegUse(u, HRmWrite, i->Pin.FpF64toF32.dst);
1495 addHRegUse(u, HRmRead, i->Pin.FpF64toF32.src);
1496 return;
1497 case Pin_FpF64toI32:
1498 addHRegUse(u, HRmWrite, i->Pin.FpF64toI32.dst);
1499 addHRegUse(u, HRmWrite, hregPPC32_FPR7());
1500 addHRegUse(u, HRmRead, i->Pin.FpF64toI32.src);
1501 return;
1502 case Pin_FpCMov:
1503 addHRegUse(u, HRmModify, i->Pin.FpCMov.dst);
1504 addHRegUse(u, HRmRead, i->Pin.FpCMov.src);
1505 return;
1506 case Pin_FpLdFPSCR:
1507 addHRegUse(u, HRmRead, i->Pin.FpLdFPSCR.src);
1508 return;
1509 case Pin_FpCmp:
1510 addHRegUse(u, HRmWrite, i->Pin.FpCmp.dst);
1511 addHRegUse(u, HRmRead, i->Pin.FpCmp.srcL);
1512 addHRegUse(u, HRmRead, i->Pin.FpCmp.srcR);
1513 return;
cerion7f000af2005-02-22 20:36:49 +00001514
1515 case Pin_RdWrLR:
1516 addHRegUse(u, (i->Pin.RdWrLR.wrLR ? HRmRead : HRmWrite),
1517 i->Pin.RdWrLR.gpr);
1518 return;
1519
cerionc3d8bdc2005-06-28 18:06:23 +00001520 case Pin_AvLdSt:
1521 addHRegUse(u, (i->Pin.AvLdSt.isLoad ? HRmWrite : HRmRead),
1522 i->Pin.AvLdSt.reg);
1523 if (i->Pin.AvLdSt.addr->tag == Pam_IR)
1524 addHRegUse(u, HRmWrite, hregPPC32_GPR30());
1525 addRegUsage_PPC32AMode(u, i->Pin.AvLdSt.addr);
1526 return;
1527 case Pin_AvUnary:
1528 addHRegUse(u, HRmWrite, i->Pin.AvUnary.dst);
1529 addHRegUse(u, HRmRead, i->Pin.AvUnary.src);
1530 return;
1531 case Pin_AvBinary:
1532 addHRegUse(u, HRmWrite, i->Pin.AvBinary.dst);
1533 addHRegUse(u, HRmRead, i->Pin.AvBinary.srcL);
1534 addHRegUse(u, HRmRead, i->Pin.AvBinary.srcR);
1535 return;
cerion6b6f59e2005-06-28 20:59:18 +00001536 case Pin_AvBin8x16:
1537 addHRegUse(u, HRmWrite, i->Pin.AvBin8x16.dst);
1538 addHRegUse(u, HRmRead, i->Pin.AvBin8x16.srcL);
1539 addHRegUse(u, HRmRead, i->Pin.AvBin8x16.srcR);
1540 return;
1541 case Pin_AvBin16x8:
1542 addHRegUse(u, HRmWrite, i->Pin.AvBin16x8.dst);
1543 addHRegUse(u, HRmRead, i->Pin.AvBin16x8.srcL);
1544 addHRegUse(u, HRmRead, i->Pin.AvBin16x8.srcR);
1545 return;
1546 case Pin_AvBin32x4:
1547 addHRegUse(u, HRmWrite, i->Pin.AvBin32x4.dst);
1548 addHRegUse(u, HRmRead, i->Pin.AvBin32x4.srcL);
1549 addHRegUse(u, HRmRead, i->Pin.AvBin32x4.srcR);
1550 if (i->Pin.AvBin32x4.op == Pav_MULF)
1551 addHRegUse(u, HRmWrite, hregPPC32_GPR29());
1552 return;
1553 case Pin_AvBin32Fx4:
1554 addHRegUse(u, HRmWrite, i->Pin.AvBin32Fx4.dst);
1555 addHRegUse(u, HRmRead, i->Pin.AvBin32Fx4.srcL);
1556 addHRegUse(u, HRmRead, i->Pin.AvBin32Fx4.srcR);
1557 return;
cerionc3d8bdc2005-06-28 18:06:23 +00001558 case Pin_AvPerm:
1559 addHRegUse(u, HRmWrite, i->Pin.AvPerm.dst);
1560 addHRegUse(u, HRmRead, i->Pin.AvPerm.ctl);
1561 addHRegUse(u, HRmRead, i->Pin.AvPerm.srcL);
1562 addHRegUse(u, HRmRead, i->Pin.AvPerm.srcR);
1563 return;
1564 case Pin_AvSel:
1565 addHRegUse(u, HRmWrite, i->Pin.AvSel.dst);
1566 addHRegUse(u, HRmRead, i->Pin.AvSel.ctl);
1567 addHRegUse(u, HRmRead, i->Pin.AvSel.srcL);
1568 addHRegUse(u, HRmRead, i->Pin.AvSel.srcR);
1569 return;
1570 case Pin_AvShlDbl:
1571 addHRegUse(u, HRmWrite, i->Pin.AvShlDbl.dst);
1572 addHRegUse(u, HRmRead, i->Pin.AvShlDbl.srcL);
1573 addHRegUse(u, HRmRead, i->Pin.AvShlDbl.srcR);
1574 return;
1575 case Pin_AvSplat:
1576 addHRegUse(u, HRmWrite, i->Pin.AvSplat.dst);
1577 addRegUsage_PPC32RI(u, i->Pin.AvSplat.src);
1578 return;
cerion6b6f59e2005-06-28 20:59:18 +00001579 case Pin_AvCMov:
1580 addHRegUse(u, HRmModify, i->Pin.AvCMov.dst);
1581 addHRegUse(u, HRmRead, i->Pin.AvCMov.src);
1582 return;
cerionc3d8bdc2005-06-28 18:06:23 +00001583 case Pin_AvLdVSCR:
1584 addHRegUse(u, HRmRead, i->Pin.AvLdVSCR.src);
1585 return;
1586
cerionb85e8bb2005-02-16 08:54:33 +00001587 default:
1588 ppPPC32Instr(i);
1589 vpanic("getRegUsage_PPC32Instr");
cerionbcf8c3e2005-02-04 16:17:07 +00001590 }
1591}
1592
cerioncd304492005-02-08 19:40:24 +00001593/* local helper */
1594static void mapReg(HRegRemap* m, HReg* r)
1595{
1596 *r = lookupHRegRemap(m, *r);
1597}
cerionbcf8c3e2005-02-04 16:17:07 +00001598
1599void mapRegs_PPC32Instr (HRegRemap* m, PPC32Instr* i)
1600{
1601 switch (i->tag) {
cerionb85e8bb2005-02-16 08:54:33 +00001602 case Pin_Alu32:
1603 mapReg(m, &i->Pin.Alu32.dst);
ceriona2f75882005-03-15 16:33:38 +00001604 mapReg(m, &i->Pin.Alu32.srcL);
1605 mapRegs_PPC32RI(m, i->Pin.Alu32.srcR);
cerionb85e8bb2005-02-16 08:54:33 +00001606 return;
cerion5e2527e2005-02-25 16:39:58 +00001607 case Pin_Sub32:
1608 mapReg(m, &i->Pin.Sub32.dst);
ceriona2f75882005-03-15 16:33:38 +00001609 mapRegs_PPC32RI(m, i->Pin.Sub32.srcL);
1610 mapReg(m, &i->Pin.Sub32.srcR);
cerion5e2527e2005-02-25 16:39:58 +00001611 return;
cerionb85e8bb2005-02-16 08:54:33 +00001612 case Pin_Sh32:
1613 mapReg(m, &i->Pin.Sh32.dst);
1614 mapReg(m, &i->Pin.Sh32.src);
1615 mapRegs_PPC32RI(m, i->Pin.Sh32.shft);
1616 return;
cerionb85e8bb2005-02-16 08:54:33 +00001617 case Pin_Cmp32:
ceriona2f75882005-03-15 16:33:38 +00001618 mapReg(m, &i->Pin.Cmp32.srcL);
1619 mapRegs_PPC32RI(m, i->Pin.Cmp32.srcR);
cerionb85e8bb2005-02-16 08:54:33 +00001620 return;
1621 case Pin_Unary32:
1622 mapReg(m, &i->Pin.Unary32.dst);
1623 mapReg(m, &i->Pin.Unary32.src);
1624 return;
1625 case Pin_MulL:
1626 mapReg(m, &i->Pin.MulL.dst);
ceriona2f75882005-03-15 16:33:38 +00001627 mapReg(m, &i->Pin.MulL.srcL);
1628 mapRegs_PPC32RI(m, i->Pin.MulL.srcR);
cerionb85e8bb2005-02-16 08:54:33 +00001629 return;
1630 case Pin_Div:
1631 mapReg(m, &i->Pin.Div.dst);
ceriona2f75882005-03-15 16:33:38 +00001632 mapReg(m, &i->Pin.Div.srcL);
1633 mapReg(m, &i->Pin.Div.srcR);
cerionb85e8bb2005-02-16 08:54:33 +00001634 return;
cerionb85e8bb2005-02-16 08:54:33 +00001635 case Pin_Call:
1636 return;
1637 case Pin_Goto:
1638 mapRegs_PPC32RI(m, i->Pin.Goto.dst);
1639 return;
1640 case Pin_CMov32:
1641 mapRegs_PPC32RI(m, i->Pin.CMov32.src);
1642 mapReg(m, &i->Pin.CMov32.dst);
1643 return;
cerion7cf8e4e2005-02-16 16:08:17 +00001644 case Pin_Load:
1645 mapRegs_PPC32AMode(m, i->Pin.Load.src);
1646 mapReg(m, &i->Pin.Load.dst);
cerionb85e8bb2005-02-16 08:54:33 +00001647 return;
1648 case Pin_Store:
1649 mapReg(m, &i->Pin.Store.src);
1650 mapRegs_PPC32AMode(m, i->Pin.Store.dst);
1651 return;
1652 case Pin_Set32:
1653 mapReg(m, &i->Pin.Set32.dst);
1654 return;
cerionb85e8bb2005-02-16 08:54:33 +00001655 case Pin_MFence:
1656 return;
cerion094d1392005-06-20 13:45:57 +00001657
1658 case Pin_FpUnary:
1659 mapReg(m, &i->Pin.FpUnary.dst);
1660 mapReg(m, &i->Pin.FpUnary.src);
1661 return;
1662 case Pin_FpBinary:
1663 mapReg(m, &i->Pin.FpBinary.dst);
1664 mapReg(m, &i->Pin.FpBinary.srcL);
1665 mapReg(m, &i->Pin.FpBinary.srcR);
1666 return;
1667 case Pin_FpLdSt:
1668 mapReg(m, &i->Pin.FpLdSt.reg);
1669 mapRegs_PPC32AMode(m, i->Pin.FpLdSt.addr);
1670 return;
1671 case Pin_FpF64toF32:
1672 mapReg(m, &i->Pin.FpF64toF32.dst);
1673 mapReg(m, &i->Pin.FpF64toF32.src);
1674 return;
1675 case Pin_FpF64toI32:
1676 mapReg(m, &i->Pin.FpF64toI32.dst);
1677 mapReg(m, &i->Pin.FpF64toI32.src);
1678 return;
1679 case Pin_FpCMov:
1680 mapReg(m, &i->Pin.FpCMov.dst);
1681 mapReg(m, &i->Pin.FpCMov.src);
1682 return;
1683 case Pin_FpLdFPSCR:
1684 mapReg(m, &i->Pin.FpLdFPSCR.src);
1685 return;
1686 case Pin_FpCmp:
1687 mapReg(m, &i->Pin.FpCmp.dst);
1688 mapReg(m, &i->Pin.FpCmp.srcL);
1689 mapReg(m, &i->Pin.FpCmp.srcR);
1690 return;
cerion7f000af2005-02-22 20:36:49 +00001691
1692 case Pin_RdWrLR:
1693 mapReg(m, &i->Pin.RdWrLR.gpr);
1694 return;
1695
cerionc3d8bdc2005-06-28 18:06:23 +00001696 case Pin_AvLdSt:
1697 mapReg(m, &i->Pin.AvLdSt.reg);
1698 mapRegs_PPC32AMode(m, i->Pin.AvLdSt.addr);
1699 return;
1700 case Pin_AvUnary:
1701 mapReg(m, &i->Pin.AvUnary.dst);
1702 mapReg(m, &i->Pin.AvUnary.src);
1703 return;
1704 case Pin_AvBinary:
1705 mapReg(m, &i->Pin.AvBinary.dst);
1706 mapReg(m, &i->Pin.AvBinary.srcL);
1707 mapReg(m, &i->Pin.AvBinary.srcR);
1708 return;
cerion6b6f59e2005-06-28 20:59:18 +00001709 case Pin_AvBin8x16:
1710 mapReg(m, &i->Pin.AvBin8x16.dst);
1711 mapReg(m, &i->Pin.AvBin8x16.srcL);
1712 mapReg(m, &i->Pin.AvBin8x16.srcR);
1713 return;
1714 case Pin_AvBin16x8:
1715 mapReg(m, &i->Pin.AvBin16x8.dst);
1716 mapReg(m, &i->Pin.AvBin16x8.srcL);
1717 mapReg(m, &i->Pin.AvBin16x8.srcR);
1718 return;
1719 case Pin_AvBin32x4:
1720 mapReg(m, &i->Pin.AvBin32x4.dst);
1721 mapReg(m, &i->Pin.AvBin32x4.srcL);
1722 mapReg(m, &i->Pin.AvBin32x4.srcR);
1723 return;
1724 case Pin_AvBin32Fx4:
1725 mapReg(m, &i->Pin.AvBin32Fx4.dst);
1726 mapReg(m, &i->Pin.AvBin32Fx4.srcL);
1727 mapReg(m, &i->Pin.AvBin32Fx4.srcR);
1728 return;
cerionc3d8bdc2005-06-28 18:06:23 +00001729 case Pin_AvPerm:
1730 mapReg(m, &i->Pin.AvPerm.dst);
1731 mapReg(m, &i->Pin.AvPerm.srcL);
1732 mapReg(m, &i->Pin.AvPerm.srcR);
1733 mapReg(m, &i->Pin.AvPerm.ctl);
1734 return;
1735 case Pin_AvSel:
1736 mapReg(m, &i->Pin.AvSel.dst);
1737 mapReg(m, &i->Pin.AvSel.srcL);
1738 mapReg(m, &i->Pin.AvSel.srcR);
1739 mapReg(m, &i->Pin.AvSel.ctl);
1740 return;
1741 case Pin_AvShlDbl:
1742 mapReg(m, &i->Pin.AvShlDbl.dst);
1743 mapReg(m, &i->Pin.AvShlDbl.srcL);
1744 mapReg(m, &i->Pin.AvShlDbl.srcR);
1745 return;
1746 case Pin_AvSplat:
1747 mapReg(m, &i->Pin.AvSplat.dst);
1748 mapRegs_PPC32RI(m, i->Pin.AvSplat.src);
1749 return;
cerion6b6f59e2005-06-28 20:59:18 +00001750 case Pin_AvCMov:
1751 mapReg(m, &i->Pin.AvCMov.dst);
1752 mapReg(m, &i->Pin.AvCMov.src);
1753 return;
cerionc3d8bdc2005-06-28 18:06:23 +00001754 case Pin_AvLdVSCR:
1755 mapReg(m, &i->Pin.AvLdVSCR.src);
1756 return;
1757
cerionb85e8bb2005-02-16 08:54:33 +00001758 default:
1759 ppPPC32Instr(i);
1760 vpanic("mapRegs_PPC32Instr");
cerionbcf8c3e2005-02-04 16:17:07 +00001761 }
1762}
1763
1764/* Figure out if i represents a reg-reg move, and if so assign the
1765 source and destination to *src and *dst. If in doubt say No. Used
1766 by the register allocator to do move coalescing.
1767*/
1768Bool isMove_PPC32Instr ( PPC32Instr* i, HReg* src, HReg* dst )
1769{
cerionab9132d2005-02-15 15:46:59 +00001770 /* Moves between integer regs */
1771 if (i->tag == Pin_Alu32) {
1772 // or Rd,Rs,Rs == mr Rd,Rs
1773 if (i->Pin.Alu32.op != Palu_OR)
1774 return False;
ceriona2f75882005-03-15 16:33:38 +00001775 if (i->Pin.Alu32.srcR->tag != Pri_Reg)
cerionab9132d2005-02-15 15:46:59 +00001776 return False;
ceriona2f75882005-03-15 16:33:38 +00001777 if (i->Pin.Alu32.srcR->Pri.Reg.reg != i->Pin.Alu32.srcL)
cerionb85e8bb2005-02-16 08:54:33 +00001778 return False;
ceriona2f75882005-03-15 16:33:38 +00001779 *src = i->Pin.Alu32.srcL;
cerionab9132d2005-02-15 15:46:59 +00001780 *dst = i->Pin.Alu32.dst;
1781 return True;
1782 }
cerion094d1392005-06-20 13:45:57 +00001783 /* Moves between FP regs */
1784 if (i->tag == Pin_FpUnary) {
1785 if (i->Pin.FpUnary.op != Pfp_MOV)
1786 return False;
1787 *src = i->Pin.FpUnary.src;
1788 *dst = i->Pin.FpUnary.dst;
1789 return True;
1790 }
cerionbcf8c3e2005-02-04 16:17:07 +00001791 return False;
1792}
1793
1794
cerione13bb312005-02-10 19:51:03 +00001795/* Generate ppc32 spill/reload instructions under the direction of the
cerionbcf8c3e2005-02-04 16:17:07 +00001796 register allocator. Note it's critical these don't write the
1797 condition codes. */
cerionc3d8bdc2005-06-28 18:06:23 +00001798PPC32Instr* genSpill_PPC32 ( HReg rreg, UShort offsetB )
cerione13bb312005-02-10 19:51:03 +00001799{
1800 PPC32AMode* am;
cerione13bb312005-02-10 19:51:03 +00001801 vassert(!hregIsVirtual(rreg));
1802 am = PPC32AMode_IR(offsetB, GuestStatePtr);
cerionb85e8bb2005-02-16 08:54:33 +00001803
cerione13bb312005-02-10 19:51:03 +00001804 switch (hregClass(rreg)) {
cerionb85e8bb2005-02-16 08:54:33 +00001805 case HRcInt32:
1806 return PPC32Instr_Store( 4, am, rreg);
cerion094d1392005-06-20 13:45:57 +00001807 case HRcFlt64:
1808 return PPC32Instr_FpLdSt ( False/*store*/, 8, rreg, am );
cerionc3d8bdc2005-06-28 18:06:23 +00001809 case HRcVec128:
1810 // XXX: GPR30 used as spill register to kludge AltiVec AMode_IR
1811 return PPC32Instr_AvLdSt ( False/*store*/, 16, rreg, am );
cerionb85e8bb2005-02-16 08:54:33 +00001812 default:
1813 ppHRegClass(hregClass(rreg));
1814 vpanic("genSpill_PPC32: unimplemented regclass");
cerione13bb312005-02-10 19:51:03 +00001815 }
cerionbcf8c3e2005-02-04 16:17:07 +00001816}
1817
cerionc3d8bdc2005-06-28 18:06:23 +00001818PPC32Instr* genReload_PPC32 ( HReg rreg, UShort offsetB )
cerione13bb312005-02-10 19:51:03 +00001819{
1820 PPC32AMode* am;
cerione13bb312005-02-10 19:51:03 +00001821 vassert(!hregIsVirtual(rreg));
1822 am = PPC32AMode_IR(offsetB, GuestStatePtr);
1823
1824 switch (hregClass(rreg)) {
cerionb85e8bb2005-02-16 08:54:33 +00001825 case HRcInt32:
cerion7cf8e4e2005-02-16 16:08:17 +00001826 return PPC32Instr_Load( 4, False, rreg, am );
cerion094d1392005-06-20 13:45:57 +00001827 case HRcFlt64:
1828 return PPC32Instr_FpLdSt ( True/*load*/, 8, rreg, am );
cerionc3d8bdc2005-06-28 18:06:23 +00001829 case HRcVec128:
1830 // XXX: GPR30 used as spill register to kludge AltiVec AMode_IR
1831 return PPC32Instr_AvLdSt ( True/*load*/, 16, rreg, am );
cerionb85e8bb2005-02-16 08:54:33 +00001832 default:
1833 ppHRegClass(hregClass(rreg));
1834 vpanic("genReload_PPC32: unimplemented regclass");
cerione13bb312005-02-10 19:51:03 +00001835 }
cerionbcf8c3e2005-02-04 16:17:07 +00001836}
1837
1838
ceriond5e38382005-02-11 13:38:15 +00001839/* --------- The ppc32 assembler (bleh.) --------- */
cerioncd304492005-02-08 19:40:24 +00001840
cerioncd304492005-02-08 19:40:24 +00001841static UInt iregNo ( HReg r )
1842{
1843 UInt n;
1844 vassert(hregClass(r) == HRcInt32);
1845 vassert(!hregIsVirtual(r));
1846 n = hregNumber(r);
1847 vassert(n <= 32);
1848 return n;
1849}
cerioncd304492005-02-08 19:40:24 +00001850
cerion094d1392005-06-20 13:45:57 +00001851static UInt fregNo ( HReg fr )
1852{
1853 UInt n;
1854 vassert(hregClass(fr) == HRcFlt64);
1855 vassert(!hregIsVirtual(fr));
1856 n = hregNumber(fr);
1857 vassert(n <= 32);
1858 return n;
1859}
cerioncd304492005-02-08 19:40:24 +00001860
cerionc3d8bdc2005-06-28 18:06:23 +00001861static UInt vregNo ( HReg v )
1862{
1863 UInt n;
1864 vassert(hregClass(v) == HRcVec128);
1865 vassert(!hregIsVirtual(v));
1866 n = hregNumber(v);
1867 vassert(n <= 32);
1868 return n;
1869}
1870
cerionab9132d2005-02-15 15:46:59 +00001871/* Emit 32bit instruction big-endianly */
ceriond5e38382005-02-11 13:38:15 +00001872static UChar* emit32 ( UChar* p, UInt w32 )
1873{
sewardj428fabd2005-03-21 03:11:17 +00001874 *p++ = toUChar((w32 >> 24) & 0x000000FF);
1875 *p++ = toUChar((w32 >> 16) & 0x000000FF);
1876 *p++ = toUChar((w32 >> 8) & 0x000000FF);
1877 *p++ = toUChar((w32) & 0x000000FF);
ceriond5e38382005-02-11 13:38:15 +00001878 return p;
1879}
cerioncd304492005-02-08 19:40:24 +00001880
cerion094d1392005-06-20 13:45:57 +00001881/* The following mkForm[...] functions refer to PPC32 instruction forms
1882 as per PPC32 p576
1883 */
cerioned623db2005-06-20 12:42:04 +00001884
ceriona2f75882005-03-15 16:33:38 +00001885static UChar* mkFormD ( UChar* p, UInt opc1, UInt r1, UInt r2, UInt imm )
ceriond5e38382005-02-11 13:38:15 +00001886{
sewardj9a036bf2005-03-14 18:19:08 +00001887 UInt theInstr;
ceriona2f75882005-03-15 16:33:38 +00001888 vassert(opc1 < 0x40);
ceriond5e38382005-02-11 13:38:15 +00001889 vassert(r1 < 0x20);
1890 vassert(r2 < 0x20);
cerion35663a72005-03-01 09:11:49 +00001891 vassert(imm < 0x10000 || imm >= 0xFFFF8000); // Pos|Neg
1892 imm = imm & 0xFFFF;
ceriona2f75882005-03-15 16:33:38 +00001893 theInstr = ((opc1<<26) | (r1<<21) | (r2<<16) | (imm));
ceriond5e38382005-02-11 13:38:15 +00001894 return emit32(p, theInstr);
1895}
1896
ceriona2f75882005-03-15 16:33:38 +00001897static UChar* mkFormX ( UChar* p, UInt opc1, UInt r1, UInt r2,
1898 UInt r3, UInt opc2, UInt b0 )
ceriond5e38382005-02-11 13:38:15 +00001899{
sewardj9a036bf2005-03-14 18:19:08 +00001900 UInt theInstr;
ceriona2f75882005-03-15 16:33:38 +00001901 vassert(opc1 < 0x40);
ceriond5e38382005-02-11 13:38:15 +00001902 vassert(r1 < 0x20);
1903 vassert(r2 < 0x20);
1904 vassert(r3 < 0x20);
ceriona2f75882005-03-15 16:33:38 +00001905 vassert(opc2 < 0x400);
ceriond5e38382005-02-11 13:38:15 +00001906 vassert(b0 < 0x2);
ceriona2f75882005-03-15 16:33:38 +00001907 theInstr = ((opc1<<26) | (r1<<21) | (r2<<16) | (r3<<11) | (opc2<<1) | (b0));
ceriond5e38382005-02-11 13:38:15 +00001908 return emit32(p, theInstr);
1909}
1910
ceriona2f75882005-03-15 16:33:38 +00001911static UChar* mkFormXO ( UChar* p, UInt opc1, UInt r1, UInt r2,
1912 UInt r3, UInt b10, UInt opc2, UInt b0 )
cerionab9132d2005-02-15 15:46:59 +00001913{
sewardj9a036bf2005-03-14 18:19:08 +00001914 UInt theInstr;
ceriona2f75882005-03-15 16:33:38 +00001915 vassert(opc1 < 0x40);
cerionab9132d2005-02-15 15:46:59 +00001916 vassert(r1 < 0x20);
1917 vassert(r2 < 0x20);
1918 vassert(r3 < 0x20);
1919 vassert(b10 < 0x2);
ceriona2f75882005-03-15 16:33:38 +00001920 vassert(opc2 < 0x200);
cerionab9132d2005-02-15 15:46:59 +00001921 vassert(b0 < 0x2);
ceriona2f75882005-03-15 16:33:38 +00001922 theInstr = ((opc1<<26) | (r1<<21) | (r2<<16) |
1923 (r3<<11) | (b10 << 10) | (opc2<<1) | (b0));
cerionab9132d2005-02-15 15:46:59 +00001924 return emit32(p, theInstr);
1925}
ceriond5e38382005-02-11 13:38:15 +00001926
ceriona2f75882005-03-15 16:33:38 +00001927static UChar* mkFormXL ( UChar* p, UInt opc1, UInt f1, UInt f2,
1928 UInt f3, UInt opc2, UInt b0 )
cerion33aa6da2005-02-16 10:25:26 +00001929{
sewardj9a036bf2005-03-14 18:19:08 +00001930 UInt theInstr;
ceriona2f75882005-03-15 16:33:38 +00001931 vassert(opc1 < 0x40);
cerion33aa6da2005-02-16 10:25:26 +00001932 vassert(f1 < 0x20);
1933 vassert(f2 < 0x20);
1934 vassert(f3 < 0x20);
ceriona2f75882005-03-15 16:33:38 +00001935 vassert(opc2 < 0x400);
cerion33aa6da2005-02-16 10:25:26 +00001936 vassert(b0 < 0x2);
ceriona2f75882005-03-15 16:33:38 +00001937 theInstr = ((opc1<<26) | (f1<<21) | (f2<<16) | (f3<<11) | (opc2<<1) | (b0));
cerion33aa6da2005-02-16 10:25:26 +00001938 return emit32(p, theInstr);
1939}
1940
1941// Note: for split field ops, give mnemonic arg
ceriona2f75882005-03-15 16:33:38 +00001942static UChar* mkFormXFX ( UChar* p, UInt r1, UInt f2, UInt opc2 )
cerion33aa6da2005-02-16 10:25:26 +00001943{
sewardj9a036bf2005-03-14 18:19:08 +00001944 UInt theInstr;
cerion33aa6da2005-02-16 10:25:26 +00001945 vassert(r1 < 0x20);
1946 vassert(f2 < 0x20);
ceriona2f75882005-03-15 16:33:38 +00001947 vassert(opc2 < 0x400);
1948 switch (opc2) {
cerion33aa6da2005-02-16 10:25:26 +00001949 case 144: // mtcrf
1950 vassert(f2 < 0x100);
1951 f2 = f2 << 1;
1952 break;
1953 case 339: // mfspr
1954 case 371: // mftb
1955 case 467: // mtspr
1956 vassert(f2 < 0x400);
1957 f2 = ((f2>>5) & 0x1F) | ((f2 & 0x1F)<<5); // re-arrange split field
1958 break;
1959 default: vpanic("mkFormXFX(PPC32)");
1960 }
ceriona2f75882005-03-15 16:33:38 +00001961 theInstr = ((31<<26) | (r1<<21) | (f2<<11) | (opc2<<1));
cerion33aa6da2005-02-16 10:25:26 +00001962 return emit32(p, theInstr);
1963}
1964
cerion094d1392005-06-20 13:45:57 +00001965// Only used by mtfsf
1966static UChar* mkFormXFL ( UChar* p, UInt FM, UInt freg )
1967{
1968 UInt theInstr;
1969 vassert(FM < 0x100);
1970 vassert(freg < 0x20);
1971 theInstr = ((63<<26) | (FM<<17) | (freg<<11) | (711<<1));
1972 return emit32(p, theInstr);
1973}
1974
cerion33aa6da2005-02-16 10:25:26 +00001975#if 0
1976// 'b'
1977static UChar* mkFormI ( UChar* p, UInt LI, UInt AA, UInt LK )
1978{
sewardj9a036bf2005-03-14 18:19:08 +00001979 UInt theInstr;
cerion33aa6da2005-02-16 10:25:26 +00001980 vassert(LI < 0x1000000);
1981 vassert(AA < 0x2);
1982 vassert(LK < 0x2);
sewardj9a036bf2005-03-14 18:19:08 +00001983 theInstr = ((18<<26) | (LI<<2) | (AA<<1) | (LK));
cerion33aa6da2005-02-16 10:25:26 +00001984 return emit32(p, theInstr);
1985}
1986#endif
1987
1988// 'bc'
1989static UChar* mkFormB ( UChar* p, UInt BO, UInt BI,
1990 UInt BD, UInt AA, UInt LK )
1991{
sewardj9a036bf2005-03-14 18:19:08 +00001992 UInt theInstr;
cerion33aa6da2005-02-16 10:25:26 +00001993 vassert(BO < 0x20);
1994 vassert(BI < 0x20);
1995 vassert(BD < 0x4000);
1996 vassert(AA < 0x2);
1997 vassert(LK < 0x2);
ceriona2f75882005-03-15 16:33:38 +00001998 theInstr = ((16<<26) | (BO<<21) | (BI<<16) | (BD<<2) | (AA<<1) | (LK));
cerion33aa6da2005-02-16 10:25:26 +00001999 return emit32(p, theInstr);
2000}
2001
cerion33aa6da2005-02-16 10:25:26 +00002002// rotates
ceriona2f75882005-03-15 16:33:38 +00002003static UChar* mkFormM ( UChar* p, UInt opc1, UInt r1, UInt r2,
cerion33aa6da2005-02-16 10:25:26 +00002004 UInt f3, UInt MB, UInt ME, UInt Rc )
2005{
sewardj9a036bf2005-03-14 18:19:08 +00002006 UInt theInstr;
ceriona2f75882005-03-15 16:33:38 +00002007 vassert(opc1 < 0x40);
cerion33aa6da2005-02-16 10:25:26 +00002008 vassert(r1 < 0x20);
2009 vassert(r2 < 0x20);
2010 vassert(f3 < 0x20);
2011 vassert(MB < 0x20);
2012 vassert(ME < 0x20);
2013 vassert(Rc < 0x2);
ceriona2f75882005-03-15 16:33:38 +00002014 theInstr = ((opc1<<26) | (r1<<21) | (r2<<16) |
sewardj9a036bf2005-03-14 18:19:08 +00002015 (f3<<11) | (MB<<6) | (ME<<1) | (Rc));
cerion33aa6da2005-02-16 10:25:26 +00002016 return emit32(p, theInstr);
2017}
cerion33aa6da2005-02-16 10:25:26 +00002018
cerion094d1392005-06-20 13:45:57 +00002019static UChar* mkFormA ( UChar* p, UInt opc1, UInt r1, UInt r2,
2020 UInt r3, UInt r4, UInt opc2, UInt b0 )
2021{
2022 UInt theInstr;
2023 vassert(opc1 < 0x40);
2024 vassert(r1 < 0x20);
2025 vassert(r2 < 0x20);
2026 vassert(r3 < 0x20);
2027 vassert(r4 < 0x20);
2028 vassert(opc2 < 0x20);
2029 vassert(b0 < 0x2 );
2030 theInstr = ((opc1<<26) | (r1<<21) | (r2<<16) | (r3<<11) |
2031 (r4<<6) | (opc2<<1) | (b0));
2032 return emit32(p, theInstr);
2033}
2034
cerioned623db2005-06-20 12:42:04 +00002035static UChar* doAMode_IR ( UChar* p, UInt opc1, UInt rSD, PPC32AMode* am )
ceriond5e38382005-02-11 13:38:15 +00002036{
cerioned623db2005-06-20 12:42:04 +00002037 UInt rA, idx;
ceriond5e38382005-02-11 13:38:15 +00002038 vassert(am->tag == Pam_IR);
ceriona2f75882005-03-15 16:33:38 +00002039 vassert(am->Pam.IR.index < 0x10000);
2040
sewardj9a036bf2005-03-14 18:19:08 +00002041 rA = iregNo(am->Pam.IR.base);
2042 idx = am->Pam.IR.index;
ceriona2f75882005-03-15 16:33:38 +00002043
2044 p = mkFormD(p, opc1, rSD, rA, idx);
ceriond5e38382005-02-11 13:38:15 +00002045 return p;
2046}
2047
2048
ceriona2f75882005-03-15 16:33:38 +00002049static UChar* doAMode_RR ( UChar* p, UInt opc1, UInt opc2,
cerioned623db2005-06-20 12:42:04 +00002050 UInt rSD, PPC32AMode* am )
ceriond5e38382005-02-11 13:38:15 +00002051{
cerioned623db2005-06-20 12:42:04 +00002052 UInt rA, rB;
ceriond5e38382005-02-11 13:38:15 +00002053 vassert(am->tag == Pam_RR);
ceriona2f75882005-03-15 16:33:38 +00002054
sewardj9a036bf2005-03-14 18:19:08 +00002055 rA = iregNo(am->Pam.RR.base);
2056 rB = iregNo(am->Pam.RR.index);
ceriona2f75882005-03-15 16:33:38 +00002057
2058 p = mkFormX(p, opc1, rSD, rA, rB, opc2, 0);
ceriond5e38382005-02-11 13:38:15 +00002059 return p;
2060}
2061
cerione97e1062005-02-21 15:09:19 +00002062/* Load imm to r_dst */
2063static UChar* mkLoadImm ( UChar* p, UInt r_dst, UInt imm )
2064{
2065 vassert(r_dst < 0x20);
2066
cerion47c526b2005-03-03 05:17:08 +00002067 if (imm >= 0xFFFF8000 || imm <= 0x7FFF) { // sign-extendable from 16 bits?
cerione97e1062005-02-21 15:09:19 +00002068 // addi r_dst,0,imm => li r_dst,imm
2069 p = mkFormD(p, 14, r_dst, 0, imm);
2070 } else {
2071 // addis r_dst,r0,(imm>>16) => lis r_dst, (imm>>16)
2072 p = mkFormD(p, 15, r_dst, 0, (imm>>16));
2073 // ori r_dst, r_dst, (imm & 0xFFFF)
2074 p = mkFormD(p, 24, r_dst, r_dst, (imm & 0xFFFF));
2075 }
2076 return p;
2077}
2078
cerione97e1062005-02-21 15:09:19 +00002079/* Move r_dst to r_src */
2080static UChar* mkMoveReg ( UChar* p, UInt r_dst, UInt r_src )
2081{
2082 vassert(r_dst < 0x20);
2083 vassert(r_src < 0x20);
2084
2085 if (r_dst != r_src) {
2086 /* or r_dst, r_src, r_src */
2087 p = mkFormX(p, 31, r_src, r_dst, r_src, 444, 0 );
2088 }
2089 return p;
2090}
2091
cerionc3d8bdc2005-06-28 18:06:23 +00002092static UChar* mkFormVX ( UChar* p, UInt opc1, UInt r1, UInt r2,
2093 UInt r3, UInt opc2 )
2094{
2095 UInt theInstr;
2096 vassert(opc1 < 0x40);
2097 vassert(r1 < 0x20);
2098 vassert(r2 < 0x20);
2099 vassert(r3 < 0x20);
2100 vassert(opc2 < 0x800);
cerion6b6f59e2005-06-28 20:59:18 +00002101 theInstr = ((opc1<<26) | (r1<<21) | (r2<<16) | (r3<<11) | opc2);
2102 return emit32(p, theInstr);
2103}
2104
2105static UChar* mkFormVXR ( UChar* p, UInt opc1, UInt r1, UInt r2, UInt Rc,
2106 UInt r3, UInt opc2 )
2107{
2108 UInt theInstr;
2109 vassert(opc1 < 0x40);
2110 vassert(r1 < 0x20);
2111 vassert(r2 < 0x20);
2112 vassert(r3 < 0x20);
2113 vassert(Rc < 0x2);
2114 vassert(opc2 < 0x400);
2115 theInstr = ((opc1<<26) | (r1<<21) | (r2<<16) | (r3<<11) | (Rc<<10) | opc2);
cerionc3d8bdc2005-06-28 18:06:23 +00002116 return emit32(p, theInstr);
2117}
2118
2119static UChar* mkFormVA ( UChar* p, UInt opc1, UInt r1, UInt r2,
2120 UInt r3, UInt r4, UInt opc2 )
2121{
2122 UInt theInstr;
2123 vassert(opc1 < 0x40);
2124 vassert(r1 < 0x20);
2125 vassert(r2 < 0x20);
2126 vassert(r3 < 0x20);
2127 vassert(r4 < 0x20);
2128 vassert(opc2 < 0x40);
2129 theInstr = ((opc1<<26) | (r1<<21) | (r2<<16) | (r3<<11) | (r4<<6) | opc2);
2130 return emit32(p, theInstr);
2131}
2132
2133
ceriond5e38382005-02-11 13:38:15 +00002134
cerionbcf8c3e2005-02-04 16:17:07 +00002135/* Emit an instruction into buf and return the number of bytes used.
2136 Note that buf is not the insn's final place, and therefore it is
2137 imperative to emit position-independent code. */
2138
2139Int emit_PPC32Instr ( UChar* buf, Int nbuf, PPC32Instr* i )
2140{
2141//.. UInt irno, opc, opc_rr, subopc_imm, opc_imma, opc_cl, opc_imm, subopc;
cerioned623db2005-06-20 12:42:04 +00002142
cerionbcf8c3e2005-02-04 16:17:07 +00002143 UChar* p = &buf[0];
cerion7cf8e4e2005-02-16 16:08:17 +00002144 UChar* ptmp = p;
2145 vassert(nbuf >= 32);
cerion2c49e032005-02-09 17:29:49 +00002146
cerion9a934a92005-02-21 16:44:03 +00002147// vex_printf("asm ");ppPPC32Instr(i); vex_printf("\n");
cerionbcf8c3e2005-02-04 16:17:07 +00002148
2149 switch (i->tag) {
2150
cerionab9132d2005-02-15 15:46:59 +00002151 case Pin_Alu32: {
ceriona2f75882005-03-15 16:33:38 +00002152 UInt opc1, opc2, r_srcR, imm_srcR;
2153 UInt r_dst = iregNo(i->Pin.Alu32.dst);
2154 UInt r_srcL = iregNo(i->Pin.Alu32.srcL);
cerion2c49e032005-02-09 17:29:49 +00002155
cerion9e263e32005-03-03 17:21:51 +00002156 /* ADD/AND/OR/XOR */
ceriona2f75882005-03-15 16:33:38 +00002157 if (i->Pin.Alu32.srcR->tag == Pri_Reg) {
2158 opc1 = 31;
2159 r_srcR = iregNo(i->Pin.Alu32.srcR->Pri.Reg.reg);
cerionab9132d2005-02-15 15:46:59 +00002160 switch (i->Pin.Alu32.op) {
ceriona2f75882005-03-15 16:33:38 +00002161 case Palu_ADD: opc2 = 266; break;
2162 case Palu_AND: opc2 = 28; break;
2163 case Palu_XOR: opc2 = 316; break;
2164 case Palu_OR: opc2 = 444; break;
cerionab9132d2005-02-15 15:46:59 +00002165 default:
2166 goto bad;
2167 }
2168
cerion9e263e32005-03-03 17:21:51 +00002169 if (i->Pin.Alu32.op == Palu_ADD) {
ceriona2f75882005-03-15 16:33:38 +00002170 p = mkFormXO(p, opc1, r_dst, r_srcL, r_srcR, 0, opc2, 0);
cerion9e263e32005-03-03 17:21:51 +00002171 } else {
ceriona2f75882005-03-15 16:33:38 +00002172 p = mkFormX(p, opc1, r_srcL, r_dst, r_srcR, opc2, 0);
cerionab9132d2005-02-15 15:46:59 +00002173 }
cerioned623db2005-06-20 12:42:04 +00002174 } else { // tag == Pri_Imm:
ceriona2f75882005-03-15 16:33:38 +00002175 imm_srcR = i->Pin.Alu32.srcR->Pri.Imm.imm32;
cerionab9132d2005-02-15 15:46:59 +00002176 switch (i->Pin.Alu32.op) {
ceriona2f75882005-03-15 16:33:38 +00002177 case Palu_ADD: opc1 = 14; break;
2178 case Palu_AND: opc1 = 28; break;
2179 case Palu_XOR: opc1 = 26; break;
2180 case Palu_OR: opc1 = 24; break;
cerionab9132d2005-02-15 15:46:59 +00002181 default:
2182 goto bad;
2183 }
2184
cerion9e263e32005-03-03 17:21:51 +00002185 if (i->Pin.Alu32.op == Palu_ADD) {
ceriona2f75882005-03-15 16:33:38 +00002186 p = mkFormD(p, opc1, r_dst, r_srcL, imm_srcR);
cerion9e263e32005-03-03 17:21:51 +00002187 } else {
ceriona2f75882005-03-15 16:33:38 +00002188 p = mkFormD(p, opc1, r_srcL, r_dst, imm_srcR);
cerionab9132d2005-02-15 15:46:59 +00002189 }
cerionab9132d2005-02-15 15:46:59 +00002190 }
cerionb85e8bb2005-02-16 08:54:33 +00002191 goto done;
cerionab9132d2005-02-15 15:46:59 +00002192 }
2193
cerion5e2527e2005-02-25 16:39:58 +00002194 case Pin_Sub32: {
ceriona2f75882005-03-15 16:33:38 +00002195 UInt r_dst = iregNo(i->Pin.Sub32.dst);
2196 UInt r_srcR = iregNo(i->Pin.Sub32.srcR);
2197 UInt r_srcL, imm_srcL;
cerion5e2527e2005-02-25 16:39:58 +00002198
2199 // Note argument swap: PPC32 only has sub-from instrs
ceriona2f75882005-03-15 16:33:38 +00002200 switch (i->Pin.Sub32.srcL->tag) {
cerion5e2527e2005-02-25 16:39:58 +00002201 case Pri_Reg:
ceriona2f75882005-03-15 16:33:38 +00002202 r_srcL = iregNo(i->Pin.Sub32.srcL->Pri.Reg.reg);
2203 // subf r_dst, r_srcR, r_srcL
2204 p = mkFormXO(p, 31, r_dst, r_srcR, r_srcL, 0, 40, 0);
cerion5e2527e2005-02-25 16:39:58 +00002205 break;
2206 case Pri_Imm:
ceriona2f75882005-03-15 16:33:38 +00002207 imm_srcL = i->Pin.Sub32.srcL->Pri.Imm.imm32;
2208 // subf r_dst, r_srcR, imm_srcL
2209 p = mkFormD(p, 8, r_dst, r_srcR, imm_srcL);
cerion5e2527e2005-02-25 16:39:58 +00002210 break;
2211 default:
2212 goto bad;
2213 }
2214 goto done;
2215 }
2216
cerionab9132d2005-02-15 15:46:59 +00002217 case Pin_Sh32: {
ceriona2f75882005-03-15 16:33:38 +00002218 UInt opc1 = 31, opc2, r_shft, imm_shft;
cerionb85e8bb2005-02-16 08:54:33 +00002219 UInt op = i->Pin.Sh32.op;
ceriona2f75882005-03-15 16:33:38 +00002220 UInt r_src = iregNo(i->Pin.Sh32.src);
2221 UInt r_dst = iregNo(i->Pin.Sh32.dst);
cerionab9132d2005-02-15 15:46:59 +00002222
cerionab9132d2005-02-15 15:46:59 +00002223 switch (i->Pin.Sh32.shft->tag) {
2224 case Pri_Reg:
cerion9e263e32005-03-03 17:21:51 +00002225 switch (op) {
2226 case Psh_SHL: opc2 = 24; break;
2227 case Psh_SHR: opc2 = 536; break;
2228 case Psh_SAR: opc2 = 792; break;
2229 default: goto bad;
2230 }
ceriona2f75882005-03-15 16:33:38 +00002231 r_shft = iregNo(i->Pin.Sh32.shft->Pri.Reg.reg);
2232 p = mkFormX(p, opc1, r_src, r_dst, r_shft, opc2, 0);
cerionb85e8bb2005-02-16 08:54:33 +00002233 break;
cerion9e263e32005-03-03 17:21:51 +00002234
2235 case Pri_Imm: // SAR only
2236 if (op != Psh_SAR) goto bad;
2237 opc2 = 824;
ceriona2f75882005-03-15 16:33:38 +00002238 imm_shft = i->Pin.Sh32.shft->Pri.Imm.imm32;
2239 p = mkFormX(p, opc1, r_src, r_dst, imm_shft, opc2, 0);
cerionb85e8bb2005-02-16 08:54:33 +00002240 break;
cerion9e263e32005-03-03 17:21:51 +00002241
cerionab9132d2005-02-15 15:46:59 +00002242 default:
2243 goto bad;
2244 }
cerionb85e8bb2005-02-16 08:54:33 +00002245 goto done;
cerionab9132d2005-02-15 15:46:59 +00002246 }
cerion2c49e032005-02-09 17:29:49 +00002247
cerion98411db2005-02-16 14:14:49 +00002248 case Pin_Cmp32: {
2249 UInt opc1, opc2=0;
2250 UInt op = i->Pin.Cmp32.op;
cerione97e1062005-02-21 15:09:19 +00002251 UInt fld1 = (7 - i->Pin.Cmp32.crfD) << 2;
ceriona2f75882005-03-15 16:33:38 +00002252 UInt r_srcL = iregNo(i->Pin.Cmp32.srcL);
2253 UInt r_srcR, imm_srcR;
cerionab9132d2005-02-15 15:46:59 +00002254
ceriona2f75882005-03-15 16:33:38 +00002255 switch (i->Pin.Cmp32.srcR->tag) {
cerion98411db2005-02-16 14:14:49 +00002256 case Pri_Imm:
2257 opc1 = (op == Pcmp_U) ? 10 : 11;
ceriona2f75882005-03-15 16:33:38 +00002258 imm_srcR = i->Pin.Cmp32.srcR->Pri.Imm.imm32;
2259 p = mkFormD(p, opc1, fld1, r_srcL, imm_srcR);
cerion98411db2005-02-16 14:14:49 +00002260 break;
2261 case Pri_Reg:
2262 opc1 = 31;
2263 opc2 = (op == Pcmp_U) ? 32 : 0;
ceriona2f75882005-03-15 16:33:38 +00002264 r_srcR = iregNo(i->Pin.Cmp32.srcR->Pri.Reg.reg);
2265 p = mkFormX(p, opc1, fld1, r_srcL, r_srcR, opc2, 0);
cerion98411db2005-02-16 14:14:49 +00002266 break;
2267 default: goto bad;
2268 }
2269 goto done;
2270 }
cerionb536af92005-02-10 15:03:19 +00002271
cerion98411db2005-02-16 14:14:49 +00002272 case Pin_Unary32: {
2273 UInt r_dst = iregNo(i->Pin.Unary32.dst);
2274 UInt r_src = iregNo(i->Pin.Unary32.src);
2275
2276 switch (i->Pin.Unary32.op) {
2277 case Pun_NOT: // nor r_dst,r_src,r_src
2278 p = mkFormX(p, 31, r_src, r_dst, r_src, 124, 0);
2279 break;
2280 case Pun_NEG: // neg r_dst,r_src
2281 p = mkFormXO(p, 31, r_dst, r_src, 0, 0, 104, 0);
2282 break;
2283 case Pun_CLZ: // cntlzw r_dst, r_src
cerion99f35772005-03-15 16:36:02 +00002284 p = mkFormX(p, 31, r_src, r_dst, 0, 26, 0);
cerion98411db2005-02-16 14:14:49 +00002285 break;
2286 default: goto bad;
2287 }
2288 goto done;
2289 }
2290
2291 case Pin_MulL: {
2292 Bool syned = i->Pin.MulL.syned;
2293 UInt r_dst = iregNo(i->Pin.MulL.dst);
ceriona2f75882005-03-15 16:33:38 +00002294 UInt r_srcL = iregNo(i->Pin.MulL.srcL);
2295 UInt r_srcR, imm;
cerion98411db2005-02-16 14:14:49 +00002296
2297 switch (i->Pin.MulL.word) {
cerion9e263e32005-03-03 17:21:51 +00002298 case 0: // Mult LOW word
ceriona2f75882005-03-15 16:33:38 +00002299 switch (i->Pin.MulL.srcR->tag) {
cerion98411db2005-02-16 14:14:49 +00002300 case Pri_Reg:
ceriona2f75882005-03-15 16:33:38 +00002301 // mullw r_dst,r_srcL,r_srcR
cerion98411db2005-02-16 14:14:49 +00002302 // sign makes no difference.
ceriona2f75882005-03-15 16:33:38 +00002303 r_srcR = iregNo(i->Pin.MulL.srcR->Pri.Reg.reg);
2304 p = mkFormXO(p, 31, r_dst, r_srcL, r_srcR, 0, 235, 0);
cerion98411db2005-02-16 14:14:49 +00002305 break;
2306 case Pri_Imm:
2307 // mulli r_dst,r_src,imm
2308 vassert(syned == True); // always signed
ceriona2f75882005-03-15 16:33:38 +00002309 imm = i->Pin.MulL.srcR->Pri.Imm.imm32;
2310 p = mkFormD(p, 07, r_dst, r_srcL, imm);
cerion98411db2005-02-16 14:14:49 +00002311 break;
2312 default:
2313 goto bad;
2314 }
2315 break;
cerion9e263e32005-03-03 17:21:51 +00002316
2317 case 1: // Mult HIGH word
ceriona2f75882005-03-15 16:33:38 +00002318 vassert(i->Pin.MulL.srcR->tag == Pri_Reg);
2319 r_srcR = iregNo(i->Pin.MulL.srcR->Pri.Reg.reg);
cerion98411db2005-02-16 14:14:49 +00002320 if (syned == True) {
ceriona2f75882005-03-15 16:33:38 +00002321 // mulhw r_dst,r_srcL,r_srcR
2322 p = mkFormXO(p, 31, r_dst, r_srcL, r_srcR, 0, 75, 0);
cerion98411db2005-02-16 14:14:49 +00002323 } else {
ceriona2f75882005-03-15 16:33:38 +00002324 // mulhwu r_dst,r_srcL,r_srcR
2325 p = mkFormXO(p, 31, r_dst, r_srcL, r_srcR, 0, 11, 0);
cerion98411db2005-02-16 14:14:49 +00002326 }
2327 break;
cerion9e263e32005-03-03 17:21:51 +00002328
2329 default: goto bad;
cerion98411db2005-02-16 14:14:49 +00002330 }
2331 goto done;
2332 }
cerion2c49e032005-02-09 17:29:49 +00002333
cerionfd0b87f2005-02-16 14:43:14 +00002334 case Pin_Div: {
2335 Bool syned = i->Pin.MulL.syned;
2336 UInt r_dst = iregNo(i->Pin.Div.dst);
ceriona2f75882005-03-15 16:33:38 +00002337 UInt r_srcL = iregNo(i->Pin.Div.srcL);
2338 UInt r_srcR = iregNo(i->Pin.Div.srcR);
cerionfd0b87f2005-02-16 14:43:14 +00002339
2340 if (syned == True) {
ceriona2f75882005-03-15 16:33:38 +00002341 // divw r_dst,r_srcL,r_srcR
2342 p = mkFormXO(p, 31, r_dst, r_srcL, r_srcR, 0, 491, 0);
cerionfd0b87f2005-02-16 14:43:14 +00002343 } else {
ceriona2f75882005-03-15 16:33:38 +00002344 // divwu r_dst,r_srcL,r_srcR
2345 p = mkFormXO(p, 31, r_dst, r_srcL, r_srcR, 0, 459, 0);
cerionfd0b87f2005-02-16 14:43:14 +00002346 }
2347 goto done;
2348 }
cerion2c49e032005-02-09 17:29:49 +00002349
cerion33aa6da2005-02-16 10:25:26 +00002350 case Pin_Call: {
cerion7cf8e4e2005-02-16 16:08:17 +00002351 PPC32CondCode cond = i->Pin.Call.cond;
ceriona56e9cc2005-02-16 18:08:25 +00002352 UInt r_dst = 12;
2353 /* As per detailed comment for Pin_Call in
cerion9e263e32005-03-03 17:21:51 +00002354 getRegUsage_PPC32Instr above, %r12 is used as an address temp */
ceriona56e9cc2005-02-16 18:08:25 +00002355
cerioned623db2005-06-20 12:42:04 +00002356 /* jump over the following insns if condition does not hold */
cerione97e1062005-02-21 15:09:19 +00002357 if (cond.test != Pct_ALWAYS) {
cerion9762bbf2005-06-23 08:44:52 +00002358 /* jmp fwds if !condition */
2359 /* don't know how many bytes to jump over yet...
2360 make space for a jump instruction and fill in later. */
2361 ptmp = p; /* fill in this bit later */
2362 p += 4; // p += 4
cerionab9132d2005-02-15 15:46:59 +00002363 }
2364
cerione97e1062005-02-21 15:09:19 +00002365 /* load target to r_dst */
cerion9762bbf2005-06-23 08:44:52 +00002366 p = mkLoadImm(p, r_dst, i->Pin.Call.target); // p += 4|8
cerionab9132d2005-02-15 15:46:59 +00002367
ceriona56e9cc2005-02-16 18:08:25 +00002368 /* mtspr 9,r_dst => move r_dst to count register */
cerion9762bbf2005-06-23 08:44:52 +00002369 p = mkFormXFX(p, r_dst, 9, 467); // p += 4
cerion33aa6da2005-02-16 10:25:26 +00002370
cerion8c51ed42005-02-22 11:16:54 +00002371 /* bctrl => branch to count register (and save to lr) */
cerion9762bbf2005-06-23 08:44:52 +00002372 p = mkFormXL(p, 19, Pct_ALWAYS, 0, 0, 528, 1); // p += 4
2373
2374 /* Fix up the conditional jump, if there was one. */
2375 if (cond.test != Pct_ALWAYS) {
2376 Int delta = p - ptmp;
2377 vassert(delta >= 16 && delta <= 20);
2378 /* bc !ct,cf,delta */
2379 mkFormB(ptmp, invertCondTest(cond.test), cond.flag, (delta>>2), 0, 0);
2380 }
cerion33aa6da2005-02-16 10:25:26 +00002381 goto done;
2382 }
2383
2384 case Pin_Goto: {
2385 UInt magic_num = 0;
cerione97e1062005-02-21 15:09:19 +00002386 UChar r_return = 3; /* Put target addr into %r3 */
cerion33aa6da2005-02-16 10:25:26 +00002387 PPC32CondCode cond = i->Pin.Goto.cond;
ceriona2f75882005-03-15 16:33:38 +00002388 UInt r_dst, imm_dst;
cerion33aa6da2005-02-16 10:25:26 +00002389
2390 /* First off, if this is conditional, create a conditional
2391 jump over the rest of it. */
2392 if (cond.test != Pct_ALWAYS) {
2393 /* jmp fwds if !condition */
cerione97e1062005-02-21 15:09:19 +00002394 /* don't know how many bytes to jump over yet...
2395 make space for a jump instruction and fill in later. */
cerion7cf8e4e2005-02-16 16:08:17 +00002396 ptmp = p; /* fill in this bit later */
cerione97e1062005-02-21 15:09:19 +00002397 p += 4;
cerion33aa6da2005-02-16 10:25:26 +00002398 }
2399
cerione97e1062005-02-21 15:09:19 +00002400 // cond succeeds...
2401
cerion33aa6da2005-02-16 10:25:26 +00002402 /* If a non-boring, set GuestStatePtr appropriately. */
cerion33aa6da2005-02-16 10:25:26 +00002403 switch (i->Pin.Goto.jk) {
2404 case Ijk_ClientReq: magic_num = VEX_TRC_JMP_CLIENTREQ; break;
2405 case Ijk_Syscall: magic_num = VEX_TRC_JMP_SYSCALL; break;
2406 case Ijk_Yield: magic_num = VEX_TRC_JMP_YIELD; break;
2407 case Ijk_EmWarn: magic_num = VEX_TRC_JMP_EMWARN; break;
2408 case Ijk_MapFail: magic_num = VEX_TRC_JMP_MAPFAIL; break;
2409 case Ijk_NoDecode: magic_num = VEX_TRC_JMP_NODECODE; break;
sewardj7ce9d152005-03-15 16:54:13 +00002410 case Ijk_TInval: magic_num = VEX_TRC_JMP_TINVAL; break;
cerion33aa6da2005-02-16 10:25:26 +00002411 case Ijk_Ret:
2412 case Ijk_Call:
2413 case Ijk_Boring:
2414 break;
2415 default:
2416 ppIRJumpKind(i->Pin.Goto.jk);
2417 vpanic("emit_PPC32Instr.Pin_Goto: unknown jump kind");
2418 }
2419 if (magic_num !=0) {
2420 vassert(magic_num < 0x10000);
cerione97e1062005-02-21 15:09:19 +00002421 /* addi r31,0,magic_num */
cerioned623db2005-06-20 12:42:04 +00002422 p = mkFormD(p, 14, 31, 0, magic_num); // p += 4
cerion33aa6da2005-02-16 10:25:26 +00002423 }
2424
cerione97e1062005-02-21 15:09:19 +00002425 /* Get the destination address into %r_return */
cerion33aa6da2005-02-16 10:25:26 +00002426 if (i->Pin.Goto.dst->tag == Pri_Imm) {
ceriona2f75882005-03-15 16:33:38 +00002427 imm_dst = i->Pin.Goto.dst->Pri.Imm.imm32;
cerioned623db2005-06-20 12:42:04 +00002428 p = mkLoadImm(p, r_return, imm_dst); // p += 4|8
cerion33aa6da2005-02-16 10:25:26 +00002429 } else {
2430 vassert(i->Pin.Goto.dst->tag == Pri_Reg);
sewardj9a036bf2005-03-14 18:19:08 +00002431 r_dst = iregNo(i->Pin.Goto.dst->Pri.Reg.reg);
cerioned623db2005-06-20 12:42:04 +00002432 p = mkMoveReg(p, r_return, r_dst); // p += 4
cerion33aa6da2005-02-16 10:25:26 +00002433 }
cerione97e1062005-02-21 15:09:19 +00002434
2435 /* blr */
cerioned623db2005-06-20 12:42:04 +00002436 p = mkFormXL(p, 19, Pct_ALWAYS, 0, 0, 16, 0); // p += 4
cerion7cf8e4e2005-02-16 16:08:17 +00002437
2438 /* Fix up the conditional jump, if there was one. */
2439 if (cond.test != Pct_ALWAYS) {
2440 Int delta = p - ptmp;
cerioned623db2005-06-20 12:42:04 +00002441 vassert(delta >= 12 && delta <= 20);
cerione97e1062005-02-21 15:09:19 +00002442 /* bc !ct,cf,delta */
2443 mkFormB(ptmp, invertCondTest(cond.test), cond.flag, (delta>>2), 0, 0);
cerion7cf8e4e2005-02-16 16:08:17 +00002444 }
cerion33aa6da2005-02-16 10:25:26 +00002445 goto done;
2446 }
cerionb536af92005-02-10 15:03:19 +00002447
cerion98411db2005-02-16 14:14:49 +00002448 case Pin_CMov32: {
ceriona2f75882005-03-15 16:33:38 +00002449 UInt r_dst, imm_src, r_src;
sewardj9a036bf2005-03-14 18:19:08 +00002450 PPC32CondCode cond;
cerion98411db2005-02-16 14:14:49 +00002451 vassert(i->Pin.CMov32.cond.test != Pct_ALWAYS);
ceriona2f75882005-03-15 16:33:38 +00002452
sewardj9a036bf2005-03-14 18:19:08 +00002453 r_dst = iregNo(i->Pin.CMov32.dst);
2454 cond = i->Pin.CMov32.cond;
cerion98411db2005-02-16 14:14:49 +00002455
cerione97e1062005-02-21 15:09:19 +00002456 /* branch (if cond fails) over move instrs */
2457 if (cond.test != Pct_ALWAYS) {
2458 /* don't know how many bytes to jump over yet...
2459 make space for a jump instruction and fill in later. */
2460 ptmp = p; /* fill in this bit later */
2461 p += 4;
2462 }
cerion98411db2005-02-16 14:14:49 +00002463
2464 // cond true: move src => dst
2465 switch (i->Pin.CMov32.src->tag) {
2466 case Pri_Imm:
ceriona2f75882005-03-15 16:33:38 +00002467 imm_src = i->Pin.CMov32.src->Pri.Imm.imm32;
2468 p = mkLoadImm(p, r_dst, imm_src);
cerion98411db2005-02-16 14:14:49 +00002469 break;
2470 case Pri_Reg:
2471 r_src = iregNo(i->Pin.CMov32.src->Pri.Reg.reg);
cerione97e1062005-02-21 15:09:19 +00002472 p = mkMoveReg(p, r_dst, r_src);
cerion98411db2005-02-16 14:14:49 +00002473 break;
2474 default: goto bad;
2475 }
cerione97e1062005-02-21 15:09:19 +00002476
2477 /* Fix up the conditional jump, if there was one. */
2478 if (cond.test != Pct_ALWAYS) {
2479 Int delta = p - ptmp;
2480 vassert(delta >= 4 && delta <= 12);
2481 /* bc !ct,cf,delta */
2482 mkFormB(ptmp, invertCondTest(cond.test), cond.flag, (delta>>2), 0, 0);
2483 }
cerion98411db2005-02-16 14:14:49 +00002484 goto done;
2485 }
cerionb536af92005-02-10 15:03:19 +00002486
cerion7cf8e4e2005-02-16 16:08:17 +00002487 case Pin_Load: {
cerioned623db2005-06-20 12:42:04 +00002488 PPC32AMode* am_addr = i->Pin.Load.src;
2489 UInt r_dst = iregNo(i->Pin.Load.dst);
cerion7cf8e4e2005-02-16 16:08:17 +00002490 Bool syned = i->Pin.Load.syned;
ceriona2f75882005-03-15 16:33:38 +00002491 UInt opc1, opc2, sz = i->Pin.Load.sz;
cerion7cf8e4e2005-02-16 16:08:17 +00002492 switch (i->Pin.Load.src->tag) {
ceriond5e38382005-02-11 13:38:15 +00002493 case Pam_IR:
cerionab9132d2005-02-15 15:46:59 +00002494 if (sz == 2) { // the only signed load
ceriona2f75882005-03-15 16:33:38 +00002495 opc1 = (syned) ? 42: 40;
cerionab9132d2005-02-15 15:46:59 +00002496 } else {
cerion7cf8e4e2005-02-16 16:08:17 +00002497 vassert(syned == False);
ceriona2f75882005-03-15 16:33:38 +00002498 opc1 = (sz == 1) ? 34 : 32; // 1:4
cerionab9132d2005-02-15 15:46:59 +00002499 }
cerioned623db2005-06-20 12:42:04 +00002500 p = doAMode_IR(p, opc1, r_dst, am_addr);
cerionab9132d2005-02-15 15:46:59 +00002501 goto done;
ceriond5e38382005-02-11 13:38:15 +00002502 case Pam_RR:
cerionab9132d2005-02-15 15:46:59 +00002503 if (sz == 2) { // the only signed load
ceriona2f75882005-03-15 16:33:38 +00002504 opc2 = (syned) ? 343: 279;
cerionab9132d2005-02-15 15:46:59 +00002505 } else {
cerion7cf8e4e2005-02-16 16:08:17 +00002506 vassert(syned == False);
ceriona2f75882005-03-15 16:33:38 +00002507 opc2 = (sz == 1) ? 87 : 23; // 1:4
cerionab9132d2005-02-15 15:46:59 +00002508 }
cerioned623db2005-06-20 12:42:04 +00002509 p = doAMode_RR(p, 31, opc2, r_dst, am_addr);
cerionab9132d2005-02-15 15:46:59 +00002510 goto done;
ceriond5e38382005-02-11 13:38:15 +00002511 default:
cerionab9132d2005-02-15 15:46:59 +00002512 goto bad;
ceriond5e38382005-02-11 13:38:15 +00002513 }
2514 }
cerionb536af92005-02-10 15:03:19 +00002515
cerionab9132d2005-02-15 15:46:59 +00002516 case Pin_Set32: {
2517 /* Make the destination register be 1 or 0, depending on whether
cerion9e263e32005-03-03 17:21:51 +00002518 the relevant condition holds. */
cerion98411db2005-02-16 14:14:49 +00002519 UInt r_dst = iregNo(i->Pin.Set32.dst);
2520 PPC32CondCode cond = i->Pin.Set32.cond;
cerion7cf8e4e2005-02-16 16:08:17 +00002521 UInt rot_imm;
cerion98411db2005-02-16 14:14:49 +00002522 UInt r_tmp;
2523
2524 if (cond.test == Pct_ALWAYS) {
cerion9e263e32005-03-03 17:21:51 +00002525 // Just load 1 to dst => li dst,1
cerion98411db2005-02-16 14:14:49 +00002526 p = mkFormD(p, 14, r_dst, 0, 1);
cerionab9132d2005-02-15 15:46:59 +00002527 } else {
cerion7cf8e4e2005-02-16 16:08:17 +00002528 rot_imm = 1 + cond.flag;
ceriona56e9cc2005-02-16 18:08:25 +00002529 r_tmp = 0; // Not within scope of regalloc, so no need to declare.
cerion98411db2005-02-16 14:14:49 +00002530
2531 // r_tmp = CR => mfcr r_tmp
2532 p = mkFormX(p, 31, r_tmp, 0, 0, 19, 0);
2533
2534 // r_dst = flag (rotate left and mask)
cerion7cf8e4e2005-02-16 16:08:17 +00002535 // => rlwinm r_dst,r_tmp,rot_imm,31,31
cerione97e1062005-02-21 15:09:19 +00002536 p = mkFormM(p, 21, r_tmp, r_dst, rot_imm, 31, 31, 0);
cerion98411db2005-02-16 14:14:49 +00002537
2538 if (cond.test == Pct_FALSE) {
ceriona2f75882005-03-15 16:33:38 +00002539 // flip bit => xori r_dst,r_dst,1
cerion98411db2005-02-16 14:14:49 +00002540 p = mkFormD(p, 26, r_dst, r_dst, 1);
cerionab9132d2005-02-15 15:46:59 +00002541 }
2542 }
2543 goto done;
cerionab9132d2005-02-15 15:46:59 +00002544 }
cerionb536af92005-02-10 15:03:19 +00002545
cerion98411db2005-02-16 14:14:49 +00002546 case Pin_MFence: {
cerioned623db2005-06-20 12:42:04 +00002547 p = mkFormX(p, 31, 0, 0, 0, 598, 0); // sync, PPC32 p616
2548// CAB: Should this be isync?
2549// p = mkFormXL(p, 19, 0, 0, 0, 150, 0); // isync, PPC32 p467
cerion98411db2005-02-16 14:14:49 +00002550 goto done;
2551 }
cerionb536af92005-02-10 15:03:19 +00002552
ceriond5e38382005-02-11 13:38:15 +00002553 case Pin_Store: {
cerioned623db2005-06-20 12:42:04 +00002554 PPC32AMode* am_addr = i->Pin.Store.dst;
2555 UInt r_src = iregNo(i->Pin.Store.src);
ceriona2f75882005-03-15 16:33:38 +00002556 UInt opc1, opc2, sz = i->Pin.Store.sz;
ceriond5e38382005-02-11 13:38:15 +00002557 switch (i->Pin.Store.dst->tag) {
2558 case Pam_IR:
ceriona2f75882005-03-15 16:33:38 +00002559 opc1 = (sz == 1) ? 38 : ((sz == 2) ? 44 : 36); // 1:2:4
cerioned623db2005-06-20 12:42:04 +00002560 p = doAMode_IR(p, opc1, r_src, am_addr);
cerionab9132d2005-02-15 15:46:59 +00002561 goto done;
ceriond5e38382005-02-11 13:38:15 +00002562 case Pam_RR:
ceriona2f75882005-03-15 16:33:38 +00002563 opc2 = (sz == 1) ? 215 : ((sz == 2) ? 407 : 151); // 1:2:4
cerioned623db2005-06-20 12:42:04 +00002564 p = doAMode_RR(p, 31, opc2, r_src, am_addr);
cerionab9132d2005-02-15 15:46:59 +00002565 goto done;
ceriond5e38382005-02-11 13:38:15 +00002566 default:
cerionab9132d2005-02-15 15:46:59 +00002567 goto bad;
ceriond5e38382005-02-11 13:38:15 +00002568 }
2569 goto done;
2570 }
cerionb536af92005-02-10 15:03:19 +00002571
cerion094d1392005-06-20 13:45:57 +00002572 case Pin_FpUnary: {
2573 UInt fr_dst = fregNo(i->Pin.FpUnary.dst);
2574 UInt fr_src = fregNo(i->Pin.FpUnary.src);
2575 switch (i->Pin.FpUnary.op) {
2576 case Pfp_SQRT: // fsqrt, PPC32 p427
2577 p = mkFormA( p, 63, fr_dst, 0, fr_src, 0, 22, 0 );
2578 break;
2579 case Pfp_ABS: // fabs, PPC32 p399
2580 p = mkFormX(p, 63, fr_dst, 0, fr_src, 264, 0);
2581 break;
2582 case Pfp_NEG: // fneg, PPC32 p416
2583 p = mkFormX(p, 63, fr_dst, 0, fr_src, 40, 0);
2584 break;
2585 case Pfp_MOV: // fmr, PPC32 p410
2586 p = mkFormX(p, 63, fr_dst, 0, fr_src, 72, 0);
2587 break;
2588 default:
2589 goto bad;
2590 }
2591 goto done;
2592 }
2593
2594 case Pin_FpBinary: {
2595 UInt fr_dst = fregNo(i->Pin.FpBinary.dst);
2596 UInt fr_srcL = fregNo(i->Pin.FpBinary.srcL);
2597 UInt fr_srcR = fregNo(i->Pin.FpBinary.srcR);
2598 switch (i->Pin.FpBinary.op) {
2599 case Pfp_ADD: // fadd, PPC32 p400
2600 p = mkFormA( p, 63, fr_dst, fr_srcL, fr_srcR, 0, 21, 0 );
2601 break;
2602 case Pfp_SUB: // fsub, PPC32 p429
2603 p = mkFormA( p, 63, fr_dst, fr_srcL, fr_srcR, 0, 20, 0 );
2604 break;
2605 case Pfp_MUL: // fmul, PPC32 p413
2606 p = mkFormA( p, 63, fr_dst, fr_srcL, 0, fr_srcR, 25, 0 );
2607 break;
2608 case Pfp_DIV: // fdiv, PPC32 p406
2609 p = mkFormA( p, 63, fr_dst, fr_srcL, fr_srcR, 0, 18, 0 );
2610 break;
2611 default:
2612 goto bad;
2613 }
2614 goto done;
2615 }
2616
2617 case Pin_FpLdSt: {
2618 PPC32AMode* am_addr = i->Pin.FpLdSt.addr;
2619 UInt f_reg = fregNo(i->Pin.FpLdSt.reg);
2620 Bool idxd = toBool(i->Pin.FpLdSt.addr->tag == Pam_RR);
2621 UChar sz = i->Pin.FpLdSt.sz;
2622 vassert(sz == 4 || sz == 8);
2623
2624 if (i->Pin.FpLdSt.isLoad) { // Load from memory
2625 if (idxd) { // lf[s|d]x, PPC32 p444|440
2626 p = doAMode_RR(p, 31, ((sz == 4) ? 535 : 599), f_reg, am_addr);
2627 } else { // lf[s|d], PPC32 p441|437
2628 p = doAMode_IR(p, ((sz == 4) ? 48 : 50), f_reg, am_addr);
2629 }
2630 } else { // Store to memory
2631 if (idxd) { // stf[s|d]x, PPC32 p521|516
2632 p = doAMode_RR(p, 31, ((sz == 4) ? 663 : 727), f_reg, am_addr);
2633 } else { // stf[s|d], PPC32 p518|513
2634 p = doAMode_IR(p, ((sz == 4) ? 52 : 54), f_reg, am_addr);
2635 }
2636 }
2637 goto done;
2638 }
2639
2640 case Pin_FpF64toF32: {
2641 UInt fr_dst = fregNo(i->Pin.FpF64toF32.dst);
2642 UInt fr_src = fregNo(i->Pin.FpF64toF32.src);
2643 // frsp, PPC32 p423
2644 p = mkFormX(p, 63, fr_dst, 0, fr_src, 12, 0);
2645 goto done;
2646 }
2647
2648 case Pin_FpF64toI32: {
2649 UInt r_dst = iregNo(i->Pin.FpF64toI32.dst);
2650 UInt fr_src = fregNo(i->Pin.FpF64toI32.src);
2651 UChar fr_tmp = 7; // Temp freg
2652 PPC32AMode* am_addr;
2653
2654 // fctiw (conv f64 to i32), PPC32 p404
2655 p = mkFormX(p, 63, fr_tmp, 0, fr_src, 14, 0);
2656
2657 // No RI form of stfiwx, so need PPC32AMode_RR:
2658 am_addr = PPC32AMode_RR( StackFramePtr, hregPPC32_GPR0() );
2659
2660 // stfiwx (store fp64[lo32] as int32), PPC32 p517
2661 p = doAMode_RR(p, 31, 983, fr_tmp, am_addr);
2662
2663 // lwzx (load int32), PPC32 p463
2664 p = doAMode_RR(p, 31, 23, r_dst, am_addr);
2665 goto done;
2666 }
2667
2668 case Pin_FpCMov: {
2669 UInt fr_dst = fregNo(i->Pin.FpCMov.dst);
2670 UInt fr_src = fregNo(i->Pin.FpCMov.src);
2671 PPC32CondCode cc = i->Pin.FpCMov.cond;
2672
2673 if (fr_dst == fr_src) goto done;
2674
2675 vassert(cc.test != Pct_ALWAYS);
2676
2677 /* jmp fwds if !condition */
2678 if (cc.test != Pct_ALWAYS) {
2679 /* bc !ct,cf,n_bytes>>2 */
2680 p = mkFormB(p, invertCondTest(cc.test), cc.flag, 8>>2, 0, 0);
2681 }
2682
2683 // fmr, PPC32 p410
2684 p = mkFormX(p, 63, fr_dst, 0, fr_src, 72, 0);
2685 goto done;
2686 }
2687
2688 case Pin_FpLdFPSCR: {
2689 UInt fr_src = fregNo(i->Pin.FpLdFPSCR.src);
2690 p = mkFormXFL(p, 0xFF, fr_src); // mtfsf, PPC32 p480
2691 goto done;
2692 }
2693
2694 case Pin_FpCmp: {
2695 UChar crfD = 1;
2696 UInt r_dst = iregNo(i->Pin.FpCmp.dst);
2697 UInt fr_srcL = fregNo(i->Pin.FpCmp.srcL);
2698 UInt fr_srcR = fregNo(i->Pin.FpCmp.srcR);
2699 vassert(crfD < 8);
2700 // fcmpo, PPC32 p402
2701 p = mkFormX(p, 63, (crfD<<2), fr_srcL, fr_srcR, 32, 0);
2702
2703 // mfcr (mv CR to r_dst), PPC32 p467
2704 p = mkFormX(p, 31, r_dst, 0, 0, 19, 0);
2705
2706 // rlwinm r_dst,r_dst,8,28,31, PPC32 p501
2707 // => rotate field 6 to field 0, masking to field 0
2708 p = mkFormM(p, 21, r_dst, r_dst, 8, 28, 31, 0);
2709 goto done;
2710 }
cerionbcf8c3e2005-02-04 16:17:07 +00002711
cerion7f000af2005-02-22 20:36:49 +00002712 case Pin_RdWrLR: {
2713 UInt reg = iregNo(i->Pin.RdWrLR.gpr);
2714 /* wrLR==True ? mtlr r4 : mflr r4 */
2715 p = mkFormXFX(p, reg, 8, (i->Pin.RdWrLR.wrLR==True) ? 467 : 339);
2716 goto done;
2717 }
2718
cerionc3d8bdc2005-06-28 18:06:23 +00002719
2720 /* AltiVec */
2721 case Pin_AvLdSt: {
2722 UInt opc2, v_reg, r_idx, r_base;
2723 UChar sz = i->Pin.AvLdSt.sz;
2724 Bool idxd = toBool(i->Pin.AvLdSt.addr->tag == Pam_RR);
2725 vassert(sz == 8 || sz == 16 || sz == 32 || sz == 128);
2726
2727 v_reg = vregNo(i->Pin.AvLdSt.reg);
2728 r_base = iregNo(i->Pin.AvLdSt.addr->Pam.RR.base);
2729
2730 // Only have AltiVec AMode_RR: kludge AMode_IR
2731 if (!idxd) {
2732 r_idx = 30; // XXX: Using r30 as temp
2733 p = mkLoadImm(p, r_idx, i->Pin.AvLdSt.addr->Pam.IR.index);
2734 } else {
2735 r_idx = iregNo(i->Pin.AvLdSt.addr->Pam.RR.index);
2736 }
2737
2738 if (i->Pin.FpLdSt.isLoad) { // Load from memory (8,16,32,128)
2739 opc2 = (sz == 8) ? 7 : (sz == 16) ? 39 : (sz == 32) ? 71 : 103;
2740 p = mkFormX(p, 31, v_reg, r_idx, r_base, opc2, 0);
2741 } else { // Store to memory (8,16,32,128)
2742 opc2 = (sz == 8) ? 135 : (sz == 16) ? 167 : (sz == 32) ? 199 : 231;
2743 p = mkFormX(p, 31, v_reg, r_idx, r_base, opc2, 0);
2744 }
2745 goto done;
2746 }
2747
2748 case Pin_AvUnary: {
2749 UInt v_dst = vregNo(i->Pin.AvUnary.dst);
2750 UInt v_src = vregNo(i->Pin.AvUnary.src);
2751 UInt opc2;
2752 switch (i->Pin.AvUnary.op) {
2753 case Pav_MOV: opc2 = 1156; break; // vor vD,vS,vS
2754 case Pav_NOT: opc2 = 1284; break; // vnor vD,vS,vS
2755 case Pav_UNPCKH8S: opc2 = 526; break; // vupkhsb
2756 case Pav_UNPCKH16S: opc2 = 590; break; // vupkhsh
2757 case Pav_UNPCKL8S: opc2 = 654; break; // vupklsb
2758 case Pav_UNPCKL16S: opc2 = 718; break; // vupklsh
2759 case Pav_UNPCKHPIX: opc2 = 846; break; // vupkhpx
2760 case Pav_UNPCKLPIX: opc2 = 974; break; // vupklpx
2761 default:
2762 goto bad;
2763 }
2764 switch (i->Pin.AvUnary.op) {
2765 case Pav_MOV:
2766 case Pav_NOT:
2767 p = mkFormVX( p, 4, v_dst, v_src, v_src, opc2 );
2768 break;
2769 default:
2770 p = mkFormVX( p, 4, v_dst, 0, v_src, opc2 );
2771 break;
2772 }
2773 goto done;
2774 }
2775
2776 case Pin_AvBinary: {
2777 UInt v_dst = vregNo(i->Pin.AvBinary.dst);
2778 UInt v_srcL = vregNo(i->Pin.AvBinary.srcL);
2779 UInt v_srcR = vregNo(i->Pin.AvBinary.srcR);
2780 UInt opc2;
2781 switch (i->Pin.AvBinary.op) {
2782 /* Bitwise */
2783 case Pav_AND: opc2 = 1026; break; // vand
2784 case Pav_OR: opc2 = 1156; break; // vor
2785 case Pav_XOR: opc2 = 1120; break; // vxor
2786
cerionc3d8bdc2005-06-28 18:06:23 +00002787 /* Shift */
cerion6b6f59e2005-06-28 20:59:18 +00002788 case Pav_SHL: opc2 = 452; break; // vsl
2789 case Pav_SHR: opc2 = 708; break; // vsr
cerionc3d8bdc2005-06-28 18:06:23 +00002790
2791 default:
2792 goto bad;
2793 }
2794 p = mkFormVX( p, 4, v_dst, v_srcL, v_srcR, opc2 );
2795 goto done;
2796 }
2797
cerion6b6f59e2005-06-28 20:59:18 +00002798 case Pin_AvBin8x16: {
2799 UInt v_dst = vregNo(i->Pin.AvBin8x16.dst);
2800 UInt v_srcL = vregNo(i->Pin.AvBin8x16.srcL);
2801 UInt v_srcR = vregNo(i->Pin.AvBin8x16.srcR);
2802 UInt opc2;
2803 switch (i->Pin.AvBin8x16.op) {
2804
2805 case Pav_ADDUM: opc2 = 0; break; // vaddubm
2806 case Pav_ADDUS: opc2 = 512; break; // vaddubs
2807 case Pav_ADDSS: opc2 = 768; break; // vaddsbs
2808
2809 case Pav_SUBUM: opc2 = 1024; break; // vsububm
2810 case Pav_SUBUS: opc2 = 1536; break; // vsububs
2811 case Pav_SUBSS: opc2 = 1792; break; // vsubsbs
2812
2813 case Pav_OMULU: opc2 = 8; break; // vmuloub
2814 case Pav_OMULS: opc2 = 264; break; // vmulosb
2815 case Pav_EMULU: opc2 = 520; break; // vmuleub
2816 case Pav_EMULS: opc2 = 776; break; // vmulesb
2817
2818 case Pav_AVGU: opc2 = 1026; break; // vavgub
2819 case Pav_AVGS: opc2 = 1282; break; // vavgsb
2820 case Pav_MAXU: opc2 = 2; break; // vmaxub
2821 case Pav_MAXS: opc2 = 258; break; // vmaxsb
2822 case Pav_MINU: opc2 = 514; break; // vminub
2823 case Pav_MINS: opc2 = 770; break; // vminsb
2824
2825 case Pav_CMPEQU: opc2 = 6; break; // vcmpequb
2826 case Pav_CMPGTU: opc2 = 518; break; // vcmpgtub
2827 case Pav_CMPGTS: opc2 = 774; break; // vcmpgtsb
2828
2829 case Pav_SHL: opc2 = 260; break; // vslb
2830 case Pav_SHR: opc2 = 516; break; // vsrb
2831 case Pav_SAR: opc2 = 772; break; // vsrab
2832 case Pav_ROTL: opc2 = 4; break; // vrlb
2833
2834 case Pav_MRGHI: opc2 = 12; break; // vmrghb
2835 case Pav_MRGLO: opc2 = 268; break; // vmrglb
2836
2837 default:
2838 goto bad;
2839 }
2840 p = mkFormVX( p, 4, v_dst, v_srcL, v_srcR, opc2 );
2841 goto done;
2842 }
2843
2844 case Pin_AvBin16x8: {
2845 UInt v_dst = vregNo(i->Pin.AvBin16x8.dst);
2846 UInt v_srcL = vregNo(i->Pin.AvBin16x8.srcL);
2847 UInt v_srcR = vregNo(i->Pin.AvBin16x8.srcR);
2848 UInt opc2;
2849 switch (i->Pin.AvBin16x8.op) {
2850
2851 case Pav_ADDUM: opc2 = 64; break; // vadduhm
2852 case Pav_ADDUS: opc2 = 576; break; // vadduhs
2853 case Pav_ADDSS: opc2 = 832; break; // vaddshs
2854
2855 case Pav_SUBUM: opc2 = 1088; break; // vsubuhm
2856 case Pav_SUBUS: opc2 = 1600; break; // vsubuhs
2857 case Pav_SUBSS: opc2 = 1856; break; // vsubshs
2858
2859 case Pav_OMULU: opc2 = 72; break; // vmulouh
2860 case Pav_OMULS: opc2 = 328; break; // vmulosh
2861 case Pav_EMULU: opc2 = 584; break; // vmuleuh
2862 case Pav_EMULS: opc2 = 840; break; // vmulesh
2863
2864 case Pav_AVGU: opc2 = 1090; break; // vavguh
2865 case Pav_AVGS: opc2 = 1346; break; // vavgsh
2866 case Pav_MAXU: opc2 = 66; break; // vmaxuh
2867 case Pav_MAXS: opc2 = 322; break; // vmaxsh
2868 case Pav_MINS: opc2 = 834; break; // vminsh
2869 case Pav_MINU: opc2 = 578; break; // vminuh
2870
2871 case Pav_CMPEQU: opc2 = 70; break; // vcmpequh
2872 case Pav_CMPGTU: opc2 = 582; break; // vcmpgtuh
2873 case Pav_CMPGTS: opc2 = 838; break; // vcmpgtsh
2874
2875 case Pav_SHL: opc2 = 324; break; // vslh
2876 case Pav_SHR: opc2 = 580; break; // vsrh
2877 case Pav_SAR: opc2 = 836; break; // vsrah
2878 case Pav_ROTL: opc2 = 68; break; // vrlh
2879
2880 case Pav_PACKUUM: opc2 = 14; break; // vpkuhum
2881 case Pav_PACKUUS: opc2 = 142; break; // vpkuhus
2882 case Pav_PACKSUS: opc2 = 270; break; // vpkshus
2883 case Pav_PACKSSS: opc2 = 398; break; // vpkshss
2884 case Pav_PACKPXL: opc2 = 782; break; // vpkpx
2885
2886 case Pav_MRGHI: opc2 = 76; break; // vmrghh
2887 case Pav_MRGLO: opc2 = 332; break; // vmrglh
2888
2889 default:
2890 goto bad;
2891 }
2892 p = mkFormVX( p, 4, v_dst, v_srcL, v_srcR, opc2 );
2893 goto done;
2894 }
2895
2896 case Pin_AvBin32x4: {
2897 UInt v_dst = vregNo(i->Pin.AvBin32x4.dst);
2898 UInt v_srcL = vregNo(i->Pin.AvBin32x4.srcL);
2899 UInt v_srcR = vregNo(i->Pin.AvBin32x4.srcR);
2900 UInt opc2;
2901 switch (i->Pin.AvBin32x4.op) {
2902
2903 case Pav_ADDUM: opc2 = 128; break; // vadduwm
2904 case Pav_ADDUS: opc2 = 640; break; // vadduws
2905 case Pav_ADDSS: opc2 = 896; break; // vaddsws
2906
2907 case Pav_SUBUM: opc2 = 1152; break; // vsubuwm
2908 case Pav_SUBUS: opc2 = 1664; break; // vsubuws
2909 case Pav_SUBSS: opc2 = 1920; break; // vsubsws
2910
2911 case Pav_AVGU: opc2 = 1154; break; // vavguw
2912 case Pav_AVGS: opc2 = 1410; break; // vavgsw
2913
2914 case Pav_MAXU: opc2 = 130; break; // vmaxuw
2915 case Pav_MAXS: opc2 = 386; break; // vmaxsw
2916
2917 case Pav_MINS: opc2 = 898; break; // vminsw
2918 case Pav_MINU: opc2 = 642; break; // vminuw
2919
2920 case Pav_CMPEQU: opc2 = 134; break; // vcmpequw
2921 case Pav_CMPGTS: opc2 = 902; break; // vcmpgtsw
2922 case Pav_CMPGTU: opc2 = 646; break; // vcmpgtuw
2923
2924 case Pav_SHL: opc2 = 388; break; // vslw
2925 case Pav_SHR: opc2 = 644; break; // vsrw
2926 case Pav_SAR: opc2 = 900; break; // vsraw
2927 case Pav_ROTL: opc2 = 132; break; // vrlw
2928
2929 case Pav_PACKUUM: opc2 = 78; break; // vpkuwum
2930 case Pav_PACKUUS: opc2 = 206; break; // vpkuwus
2931 case Pav_PACKSUS: opc2 = 334; break; // vpkswus
2932 case Pav_PACKSSS: opc2 = 462; break; // vpkswss
2933
2934 case Pav_MRGHI: opc2 = 140; break; // vmrghw
2935 case Pav_MRGLO: opc2 = 396; break; // vmrglw
2936
2937 default:
2938 goto bad;
2939 }
2940 p = mkFormVX( p, 4, v_dst, v_srcL, v_srcR, opc2 );
2941 goto done;
2942 }
2943
2944 case Pin_AvBin32Fx4: {
2945 UInt v_dst = vregNo(i->Pin.AvBin32Fx4.dst);
2946 UInt v_srcL = vregNo(i->Pin.AvBin32Fx4.srcL);
2947 UInt v_srcR = vregNo(i->Pin.AvBin32Fx4.srcR);
2948 switch (i->Pin.AvBin32Fx4.op) {
2949
2950 case Pav_ADDF:
2951 p = mkFormVX( p, 4, v_dst, v_srcL, v_srcR, 10 ); // vaddfp
2952 break;
2953 case Pav_SUBF:
2954 p = mkFormVX( p, 4, v_dst, v_srcL, v_srcR, 74 ); // vsubfp
2955 break;
2956 case Pav_MAXF:
2957 p = mkFormVX( p, 4, v_dst, v_srcL, v_srcR, 1034 ); // vmaxfp
2958 break;
2959 case Pav_MINF:
2960 p = mkFormVX( p, 4, v_dst, v_srcL, v_srcR, 1098 ); // vminfp
2961 break;
2962
2963 case Pav_MULF: {
2964 /* Make a vmulfp from a vmaddfp:
2965 load -0.0 (0x8000_0000) to each 32-bit word of vB
2966 this makes the add a noop.
2967 */
2968 UInt vB = 29; // XXX: Using r29 for temp
2969 UInt zero_simm = 0x80000000;
2970
2971 // Better way to load zero_imm?
2972 // vspltisw vB,0x1F (0x1F => each word of vB)
2973 p = mkFormVX( p, 4, vB, zero_simm, 0, 908 );
2974
2975 // vslw vB,vB,vB (each word of vB = (0x1F << 0x1F) = 0x80000000
2976 p = mkFormVX( p, 4, vB, vB, vB, 388 );
2977
2978 // Finally, do the multiply:
2979 p = mkFormVA( p, 4, v_dst, v_srcL, vB, v_srcR, 46 );
2980 break;
2981 }
2982 case Pav_CMPEQF:
2983 p = mkFormVXR( p, 4, v_dst, v_srcL, v_srcR, 0, 198 ); // vcmpeqfp
2984 break;
2985 case Pav_CMPGTF:
2986 p = mkFormVXR( p, 4, v_dst, v_srcL, v_srcR, 1, 710 ); // vcmpgtfp
2987 break;
2988 case Pav_CMPGEF:
2989 p = mkFormVXR( p, 4, v_dst, v_srcL, v_srcR, 1, 454 ); // vcmpgefp
2990 break;
2991
2992 default:
2993 goto bad;
2994 }
2995 goto done;
2996 }
2997
cerionc3d8bdc2005-06-28 18:06:23 +00002998 case Pin_AvPerm: { // vperm
2999 UInt v_ctl = vregNo(i->Pin.AvPerm.ctl);
3000 UInt v_dst = vregNo(i->Pin.AvPerm.dst);
3001 UInt v_srcL = vregNo(i->Pin.AvPerm.srcL);
3002 UInt v_srcR = vregNo(i->Pin.AvPerm.srcR);
3003 p = mkFormVA( p, 4, v_dst, v_srcL, v_srcR, v_ctl, 43 );
3004 goto done;
3005 }
3006
3007 case Pin_AvSel: { // vsel
3008 UInt v_ctl = vregNo(i->Pin.AvSel.ctl);
3009 UInt v_dst = vregNo(i->Pin.AvSel.dst);
3010 UInt v_srcL = vregNo(i->Pin.AvSel.srcL);
3011 UInt v_srcR = vregNo(i->Pin.AvSel.srcR);
3012 p = mkFormVA( p, 4, v_dst, v_srcL, v_srcR, v_ctl, 42 );
3013 goto done;
3014 }
3015
3016 case Pin_AvShlDbl: { // vsldoi
3017 UInt shift = i->Pin.AvShlDbl.shift;
3018 UInt v_dst = vregNo(i->Pin.AvShlDbl.dst);
3019 UInt v_srcL = vregNo(i->Pin.AvShlDbl.srcL);
3020 UInt v_srcR = vregNo(i->Pin.AvShlDbl.srcR);
3021 vassert(shift <= 0xF);
3022 p = mkFormVA( p, 4, v_dst, v_srcL, v_srcR, shift, 44 );
3023 goto done;
3024 }
3025
3026 case Pin_AvSplat: { // vsplt(is)(b,h,w)
3027 UInt v_dst = vregNo(i->Pin.AvShlDbl.dst);
3028 UChar sz = i->Pin.AvSplat.sz;
3029 UInt v_src, simm_src, opc2;
3030 vassert(sz == 8 || sz == 16 || sz == 32);
3031
3032 if (i->Pin.AvSplat.src->tag == Pri_Imm) {
cerion6b6f59e2005-06-28 20:59:18 +00003033 opc2 = (sz == 8) ? 780 : (sz == 16) ? 844 : 908; // 8,16,32
cerionc3d8bdc2005-06-28 18:06:23 +00003034 simm_src = i->Pin.AvSplat.src->Pri.Imm.imm32;
3035 p = mkFormVX( p, 4, v_dst, simm_src, 0, opc2 );
3036 } else { // Pri_Reg
3037 opc2 = (sz == 8) ? 524 : (sz == 16) ? 588 : 652; // 8,16,32
3038 v_src = iregNo(i->Pin.AvSplat.src->Pri.Reg.reg);
3039 p = mkFormVX( p, 4, v_dst, 0, v_src, opc2 );
3040 }
3041 goto done;
3042 }
3043
cerion6b6f59e2005-06-28 20:59:18 +00003044 case Pin_AvCMov: {
3045 UInt v_dst = vregNo(i->Pin.AvCMov.dst);
3046 UInt v_src = vregNo(i->Pin.AvCMov.src);
3047 PPC32CondCode cc = i->Pin.AvCMov.cond;
3048
3049 if (v_dst == v_src) goto done;
3050
3051 vassert(cc.test != Pct_ALWAYS);
3052
3053 /* jmp fwds 2 insns if !condition */
3054 if (cc.test != Pct_ALWAYS) {
3055 /* bc !ct,cf,n_bytes>>2 */
3056 p = mkFormB(p, invertCondTest(cc.test), cc.flag, 8>>2, 0, 0);
3057 }
3058 /* vmr */
3059 p = mkFormVX( p, 4, v_dst, v_src, v_src, 1156 );
3060 goto done;
3061 }
3062
cerionc3d8bdc2005-06-28 18:06:23 +00003063 case Pin_AvLdVSCR: { // mtvscr
3064 UInt v_src = vregNo(i->Pin.AvLdVSCR.src);
3065 p = mkFormVX( p, 4, 0, 0, v_src, 1604 );
3066 goto done;
3067 }
3068
cerionbcf8c3e2005-02-04 16:17:07 +00003069 default:
3070 goto bad;
3071 }
3072
3073 bad:
cerionab9132d2005-02-15 15:46:59 +00003074 vex_printf("\n=> ");
cerionbcf8c3e2005-02-04 16:17:07 +00003075 ppPPC32Instr(i);
3076 vpanic("emit_PPC32Instr");
3077 /*NOTREACHED*/
3078
cerionbcf8c3e2005-02-04 16:17:07 +00003079 done:
3080 vassert(p - &buf[0] <= 32);
3081 return p - &buf[0];
cerionbcf8c3e2005-02-04 16:17:07 +00003082}
3083
3084/*---------------------------------------------------------------*/
3085/*--- end host-ppc32/hdefs.c ---*/
3086/*---------------------------------------------------------------*/