blob: a06c09a71214f6447f0df2a465dcd862cbbb3754 [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;
cerion01713102005-06-29 19:05:08 +0000184 *nregs = 90;
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();
cerion01713102005-06-29 19:05:08 +0000284
285 vassert(i == *nregs);
cerion2c49e032005-02-09 17:29:49 +0000286}
287
288
289/* --------- Condition codes, Intel encoding. --------- */
290
291HChar* showPPC32CondCode ( PPC32CondCode cond )
292{
cerionab9132d2005-02-15 15:46:59 +0000293 if (cond.test == Pct_ALWAYS) return "always";
294
295 switch (cond.flag) {
296 case Pcf_SO: return (cond.test == Pct_TRUE) ? "so=1" : "so=0";
297 case Pcf_EQ: return (cond.test == Pct_TRUE) ? "eq=1" : "eq=0";
298 case Pcf_GT: return (cond.test == Pct_TRUE) ? "gt=1" : "gt=0";
299 case Pcf_LT: return (cond.test == Pct_TRUE) ? "lt=1" : "lt=0";
300 default: vpanic("ppPPC32CondCode");
cerion2c49e032005-02-09 17:29:49 +0000301 }
cerionbcf8c3e2005-02-04 16:17:07 +0000302}
303
cerioned623db2005-06-20 12:42:04 +0000304/* construct condition code */
cerion7cf8e4e2005-02-16 16:08:17 +0000305PPC32CondCode mk_PPCCondCode ( PPC32CondTest test, PPC32CondFlag flag )
306{
307 PPC32CondCode cc;
308 cc.flag = flag;
309 cc.test = test;
310 return cc;
311}
312
313/* false->true, true->false */
cerion33aa6da2005-02-16 10:25:26 +0000314PPC32CondTest invertCondTest ( PPC32CondTest ct )
315{
316 vassert(ct != Pct_ALWAYS);
317 return (ct == Pct_TRUE) ? Pct_FALSE : Pct_TRUE;
318}
319
320
cerioncd304492005-02-08 19:40:24 +0000321/* --------- PPCAMode: memory address expressions. --------- */
322
323PPC32AMode* PPC32AMode_IR ( UInt idx, HReg base ) {
324 PPC32AMode* am = LibVEX_Alloc(sizeof(PPC32AMode));
sewardj9a036bf2005-03-14 18:19:08 +0000325 vassert(idx < 0x10000);
cerioncd304492005-02-08 19:40:24 +0000326 am->tag = Pam_IR;
327 am->Pam.IR.base = base;
328 am->Pam.IR.index = idx;
329 return am;
330}
331PPC32AMode* PPC32AMode_RR ( HReg idx, HReg base ) {
332 PPC32AMode* am = LibVEX_Alloc(sizeof(PPC32AMode));
333 am->tag = Pam_RR;
334 am->Pam.RR.base = base;
335 am->Pam.RR.index = idx;
336 return am;
337}
338
339PPC32AMode* dopyPPC32AMode ( PPC32AMode* am ) {
340 switch (am->tag) {
cerionb85e8bb2005-02-16 08:54:33 +0000341 case Pam_IR:
342 return PPC32AMode_IR( am->Pam.IR.index, am->Pam.IR.base );
343 case Pam_RR:
344 return PPC32AMode_RR( am->Pam.RR.index, am->Pam.RR.base );
345 default:
346 vpanic("dopyPPC32AMode");
cerioncd304492005-02-08 19:40:24 +0000347 }
348}
349
350void ppPPC32AMode ( PPC32AMode* am ) {
351 switch (am->tag) {
cerionb85e8bb2005-02-16 08:54:33 +0000352 case Pam_IR:
353 if (am->Pam.IR.index == 0)
cerionf9d6e222005-02-23 18:21:31 +0000354 vex_printf("0(");
cerionb85e8bb2005-02-16 08:54:33 +0000355 else
356 vex_printf("0x%x(", am->Pam.IR.index);
357 ppHRegPPC32(am->Pam.IR.base);
358 vex_printf(")");
359 return;
360 case Pam_RR:
361 ppHRegPPC32(am->Pam.RR.base);
362 vex_printf(",");
363 ppHRegPPC32(am->Pam.RR.index);
364 return;
365 default:
366 vpanic("ppPPC32AMode");
cerioncd304492005-02-08 19:40:24 +0000367 }
368}
369
cerioncd304492005-02-08 19:40:24 +0000370static void addRegUsage_PPC32AMode ( HRegUsage* u, PPC32AMode* am ) {
371 switch (am->tag) {
cerionb85e8bb2005-02-16 08:54:33 +0000372 case Pam_IR:
373 addHRegUse(u, HRmRead, am->Pam.IR.base);
374 return;
375 case Pam_RR:
376 addHRegUse(u, HRmRead, am->Pam.RR.base);
377 addHRegUse(u, HRmRead, am->Pam.RR.index);
378 return;
379 default:
380 vpanic("addRegUsage_PPC32AMode");
cerioncd304492005-02-08 19:40:24 +0000381 }
382}
cerioncd304492005-02-08 19:40:24 +0000383
cerioncd304492005-02-08 19:40:24 +0000384static void mapRegs_PPC32AMode ( HRegRemap* m, PPC32AMode* am ) {
385 switch (am->tag) {
cerionb85e8bb2005-02-16 08:54:33 +0000386 case Pam_IR:
387 am->Pam.IR.base = lookupHRegRemap(m, am->Pam.IR.base);
388 return;
389 case Pam_RR:
390 am->Pam.RR.base = lookupHRegRemap(m, am->Pam.RR.base);
391 am->Pam.RR.index = lookupHRegRemap(m, am->Pam.RR.index);
392 return;
393 default:
394 vpanic("mapRegs_PPC32AMode");
cerioncd304492005-02-08 19:40:24 +0000395 }
396}
cerioncd304492005-02-08 19:40:24 +0000397
398/* --------- Operand, which can be reg or immediate only. --------- */
399
400PPC32RI* PPC32RI_Imm ( UInt imm32 ) {
401 PPC32RI* op = LibVEX_Alloc(sizeof(PPC32RI));
402 op->tag = Pri_Imm;
403 op->Pri.Imm.imm32 = imm32;
404 return op;
405}
406PPC32RI* PPC32RI_Reg ( HReg reg ) {
407 PPC32RI* op = LibVEX_Alloc(sizeof(PPC32RI));
408 op->tag = Pri_Reg;
409 op->Pri.Reg.reg = reg;
410 return op;
411}
412
413void ppPPC32RI ( PPC32RI* op ) {
414 switch (op->tag) {
cerionb85e8bb2005-02-16 08:54:33 +0000415 case Pri_Imm:
416 vex_printf("$0x%x", op->Pri.Imm.imm32);
417 return;
418 case Pri_Reg:
419 ppHRegPPC32(op->Pri.Reg.reg);
420 return;
421 default:
422 vpanic("ppPPC32RI");
cerioncd304492005-02-08 19:40:24 +0000423 }
424}
425
426/* An PPC32RI can only be used in a "read" context (what would it mean
427 to write or modify a literal?) and so we enumerate its registers
428 accordingly. */
429static void addRegUsage_PPC32RI ( HRegUsage* u, PPC32RI* op ) {
430 switch (op->tag) {
cerionb85e8bb2005-02-16 08:54:33 +0000431 case Pri_Imm:
432 return;
433 case Pri_Reg:
434 addHRegUse(u, HRmRead, op->Pri.Reg.reg);
435 return;
436 default:
437 vpanic("addRegUsage_PPC32RI");
cerioncd304492005-02-08 19:40:24 +0000438 }
439}
440
441static void mapRegs_PPC32RI ( HRegRemap* m, PPC32RI* op ) {
442 switch (op->tag) {
cerionb85e8bb2005-02-16 08:54:33 +0000443 case Pri_Imm:
444 return;
445 case Pri_Reg:
446 op->Pri.Reg.reg = lookupHRegRemap(m, op->Pri.Reg.reg);
447 return;
448 default:
449 vpanic("mapRegs_PPC32RI");
cerioncd304492005-02-08 19:40:24 +0000450 }
451}
452
453/* --------- Instructions. --------- */
454
cerionbcf8c3e2005-02-04 16:17:07 +0000455//.. HChar* showX86ScalarSz ( X86ScalarSz sz ) {
456//.. switch (sz) {
457//.. case Xss_16: return "w";
458//.. case Xss_32: return "l";
459//.. default: vpanic("showX86ScalarSz");
460//.. }
461//.. }
cerioncd304492005-02-08 19:40:24 +0000462
cerion2c49e032005-02-09 17:29:49 +0000463HChar* showPPC32UnaryOp ( PPC32UnaryOp op ) {
464 switch (op) {
cerionb85e8bb2005-02-16 08:54:33 +0000465 case Pun_NOT: return "not";
466 case Pun_NEG: return "neg";
467 case Pun_CLZ: return "cntlzw";
468 default: vpanic("showPPC32UnaryOp");
cerion2c49e032005-02-09 17:29:49 +0000469 }
470}
cerioncd304492005-02-08 19:40:24 +0000471
472HChar* showPPC32AluOp ( PPC32AluOp op ) {
473 switch (op) {
cerionb85e8bb2005-02-16 08:54:33 +0000474 case Palu_ADD: return "add";
cerionb85e8bb2005-02-16 08:54:33 +0000475// case Palu_ADC: return "adc";
476// case Palu_SBB: return "sbb";
477 case Palu_AND: return "and";
478 case Palu_OR: return "or";
479 case Palu_XOR: return "xor";
cerionb85e8bb2005-02-16 08:54:33 +0000480 default: vpanic("showPPC32AluOp");
cerioncd304492005-02-08 19:40:24 +0000481 }
482}
483
484HChar* showPPC32ShiftOp ( PPC32ShiftOp op ) {
485 switch (op) {
cerionb85e8bb2005-02-16 08:54:33 +0000486 case Psh_SHL: return "slw";
487 case Psh_SHR: return "srw";
488 case Psh_SAR: return "sraw";
489 case Psh_ROL: return "rlw";
490 default: vpanic("showPPC32ShiftOp");
cerioncd304492005-02-08 19:40:24 +0000491 }
492}
493
cerionab9132d2005-02-15 15:46:59 +0000494HChar* showPPC32CmpOp ( PPC32CmpOp op ) {
495 switch (op) {
cerionb85e8bb2005-02-16 08:54:33 +0000496 case Pcmp_U: return "cmpl";
497 case Pcmp_S: return "cmp";
498 default: vpanic("showPPC32CmpOp");
cerionab9132d2005-02-15 15:46:59 +0000499 }
500}
501
cerion094d1392005-06-20 13:45:57 +0000502HChar* showPPC32FpOp ( PPC32FpOp op ) {
503 switch (op) {
504 case Pfp_ADD: return "fadd";
505 case Pfp_SUB: return "fsub";
506 case Pfp_MUL: return "fmul";
507 case Pfp_DIV: return "fdiv";
508 case Pfp_SQRT: return "fsqrt";
509 case Pfp_ABS: return "fabs";
510 case Pfp_NEG: return "fneg";
511 case Pfp_MOV: return "fmr";
512 default: vpanic("showPPC32FpOp");
513 }
514}
cerioncd304492005-02-08 19:40:24 +0000515
cerionc3d8bdc2005-06-28 18:06:23 +0000516HChar* showPPC32AvOp ( PPC32AvOp op ) {
517 switch (op) {
cerion6b6f59e2005-06-28 20:59:18 +0000518
519 /* Unary */
520 case Pav_MOV: return "vmr"; /* Mov */
cerionc3d8bdc2005-06-28 18:06:23 +0000521
cerion6b6f59e2005-06-28 20:59:18 +0000522 case Pav_AND: return "vand"; /* Bitwise */
cerionc3d8bdc2005-06-28 18:06:23 +0000523 case Pav_OR: return "vor";
524 case Pav_XOR: return "vxor";
525 case Pav_NOT: return "vnot";
526
cerion6b6f59e2005-06-28 20:59:18 +0000527 case Pav_UNPCKH8S: return "vupkhsb"; /* Unpack */
cerionc3d8bdc2005-06-28 18:06:23 +0000528 case Pav_UNPCKH16S: return "vupkhsh";
529 case Pav_UNPCKL8S: return "vupklsb";
530 case Pav_UNPCKL16S: return "vupklsh";
531 case Pav_UNPCKHPIX: return "vupkhpx";
532 case Pav_UNPCKLPIX: return "vupklpx";
cerion6b6f59e2005-06-28 20:59:18 +0000533
534 /* Integer binary */
535 case Pav_ADDUM: return "vaddu_m"; // b,h,w
536 case Pav_ADDUS: return "vaddu_s"; // b,h,w
537 case Pav_ADDSS: return "vadds_s"; // b,h,w
cerionc3d8bdc2005-06-28 18:06:23 +0000538
cerion6b6f59e2005-06-28 20:59:18 +0000539 case Pav_SUBUM: return "vsubu_m"; // b,h,w
540 case Pav_SUBUS: return "vsubu_s"; // b,h,w
541 case Pav_SUBSS: return "vsubs_s"; // b,h,w
542
543 case Pav_OMULU: return "vmulou"; // b,h
544 case Pav_OMULS: return "vmulos"; // b,h
545 case Pav_EMULU: return "vmuleu"; // b,h
546 case Pav_EMULS: return "vmules"; // b,h
547
548 case Pav_AVGU: return "vavgu"; // b,h,w
549 case Pav_AVGS: return "vavgs"; // b,h,w
550
551 case Pav_MAXU: return "vmaxu"; // b,h,w
552 case Pav_MAXS: return "vmaxs"; // b,h,w
553
554 case Pav_MINU: return "vminu"; // b,h,w
555 case Pav_MINS: return "vmins"; // b,h,w
556
557 /* Compare (always affects CR field 6) */
558 case Pav_CMPEQU: return "vcmpequ"; // b,h,w
559 case Pav_CMPGTU: return "vcmpgtu"; // b,h,w
560 case Pav_CMPGTS: return "vcmpgts"; // b,h,w
561
562 /* Shift */
563 case Pav_SHL: return "vsl"; // ' ',b,h,w
564 case Pav_SHR: return "vsr"; // ' ',b,h,w
565 case Pav_SAR: return "vsra"; // b,h,w
566 case Pav_ROTL: return "vrl"; // b,h,w
567
568 /* Pack */
569 case Pav_PACKUUM: return "vpku_um"; // h,w
570 case Pav_PACKUUS: return "vpku_us"; // h,w
571 case Pav_PACKSUS: return "vpks_us"; // h,w
572 case Pav_PACKSSS: return "vpks_ss"; // h,w
573 case Pav_PACKPXL: return "vpkpx";
574
cerionc3d8bdc2005-06-28 18:06:23 +0000575 /* Merge */
cerion6b6f59e2005-06-28 20:59:18 +0000576 case Pav_MRGHI: return "vmrgh"; // b,h,w
577 case Pav_MRGLO: return "vmrgl"; // b,h,w
578
579
580 /* Floating Point Binary */
581 case Pav_ADDF: return "vaddfp";
582 case Pav_SUBF: return "vsubfp";
583 case Pav_MULF: return "vmaddfp";
584 case Pav_MAXF: return "vmaxfp";
585 case Pav_MINF: return "vminfp";
586 case Pav_CMPEQF: return "vcmpeqfp";
587 case Pav_CMPGTF: return "vcmpgtfp";
588 case Pav_CMPGEF: return "vcmpgefp";
cerionc3d8bdc2005-06-28 18:06:23 +0000589
590 default: vpanic("showPPC32AvOp");
591 }
592}
593
ceriona2f75882005-03-15 16:33:38 +0000594PPC32Instr* PPC32Instr_Alu32 ( PPC32AluOp op, HReg dst, HReg srcL, PPC32RI* srcR ) {
sewardj9a036bf2005-03-14 18:19:08 +0000595 PPC32Instr* i = LibVEX_Alloc(sizeof(PPC32Instr));
ceriona2f75882005-03-15 16:33:38 +0000596 if (srcR->tag == Pri_Imm)
597 vassert(srcR->Pri.Imm.imm32 < 0x10000);
cerioncd304492005-02-08 19:40:24 +0000598 i->tag = Pin_Alu32;
599 i->Pin.Alu32.op = op;
600 i->Pin.Alu32.dst = dst;
ceriona2f75882005-03-15 16:33:38 +0000601 i->Pin.Alu32.srcL = srcL;
602 i->Pin.Alu32.srcR = srcR;
cerioncd304492005-02-08 19:40:24 +0000603 return i;
604}
ceriona2f75882005-03-15 16:33:38 +0000605PPC32Instr* PPC32Instr_Sub32 ( HReg dst, PPC32RI* srcL, HReg srcR ) {
sewardj9a036bf2005-03-14 18:19:08 +0000606 PPC32Instr* i = LibVEX_Alloc(sizeof(PPC32Instr));
ceriona2f75882005-03-15 16:33:38 +0000607 if (srcL->tag == Pri_Imm)
608 vassert(srcL->Pri.Imm.imm32 < 0x10000);
cerion5e2527e2005-02-25 16:39:58 +0000609 i->tag = Pin_Sub32;
610 i->Pin.Sub32.dst = dst;
ceriona2f75882005-03-15 16:33:38 +0000611 i->Pin.Sub32.srcL = srcL;
612 i->Pin.Sub32.srcR = srcR;
cerion5e2527e2005-02-25 16:39:58 +0000613 return i;
614}
cerioncd304492005-02-08 19:40:24 +0000615PPC32Instr* PPC32Instr_Sh32 ( PPC32ShiftOp op, HReg dst, HReg src, PPC32RI* shft ) {
sewardj9a036bf2005-03-14 18:19:08 +0000616 PPC32Instr* i = LibVEX_Alloc(sizeof(PPC32Instr));
cerionab9132d2005-02-15 15:46:59 +0000617 if (op == Psh_SHL || op == Psh_SHR) // No imm versions for these.
618 vassert(shft->tag == Pri_Reg);
619 if (shft->tag == Pri_Imm)
620 vassert(shft->Pri.Imm.imm32 < 32);
cerioncd304492005-02-08 19:40:24 +0000621 i->tag = Pin_Sh32;
622 i->Pin.Sh32.op = op;
623 i->Pin.Sh32.dst = dst;
624 i->Pin.Sh32.src = src;
625 i->Pin.Sh32.shft = shft;
626 return i;
627}
ceriona2f75882005-03-15 16:33:38 +0000628PPC32Instr* PPC32Instr_Cmp32 ( PPC32CmpOp op, UInt crfD, HReg srcL, PPC32RI* srcR ) {
sewardj9a036bf2005-03-14 18:19:08 +0000629 PPC32Instr* i = LibVEX_Alloc(sizeof(PPC32Instr));
ceriona2f75882005-03-15 16:33:38 +0000630 if (srcR->tag == Pri_Imm)
631 vassert(srcR->Pri.Imm.imm32 < 0x10000);
cerionab9132d2005-02-15 15:46:59 +0000632 i->tag = Pin_Cmp32;
633 i->Pin.Cmp32.op = op;
634 i->Pin.Cmp32.crfD = crfD;
ceriona2f75882005-03-15 16:33:38 +0000635 i->Pin.Cmp32.srcL = srcL;
636 i->Pin.Cmp32.srcR = srcR;
cerion2c49e032005-02-09 17:29:49 +0000637 return i;
638}
cerione13bb312005-02-10 19:51:03 +0000639PPC32Instr* PPC32Instr_Unary32 ( PPC32UnaryOp op, HReg dst, HReg src ) {
cerion2c49e032005-02-09 17:29:49 +0000640 PPC32Instr* i = LibVEX_Alloc(sizeof(PPC32Instr));
641 i->tag = Pin_Unary32;
642 i->Pin.Unary32.op = op;
643 i->Pin.Unary32.dst = dst;
cerione13bb312005-02-10 19:51:03 +0000644 i->Pin.Unary32.src = src;
cerion2c49e032005-02-09 17:29:49 +0000645 return i;
646}
cerion92f5dc72005-02-10 16:11:35 +0000647PPC32Instr* PPC32Instr_MulL ( Bool syned, Bool word, HReg dst,
ceriona2f75882005-03-15 16:33:38 +0000648 HReg srcL, PPC32RI* srcR ) {
sewardj9a036bf2005-03-14 18:19:08 +0000649 PPC32Instr* i = LibVEX_Alloc(sizeof(PPC32Instr));
cerion98411db2005-02-16 14:14:49 +0000650 if (word == 1) { // high
ceriona2f75882005-03-15 16:33:38 +0000651 vassert(srcR->tag == Pri_Reg);
cerion98411db2005-02-16 14:14:49 +0000652 } else { // low
ceriona2f75882005-03-15 16:33:38 +0000653 if (srcR->tag == Pri_Imm) {
cerion98411db2005-02-16 14:14:49 +0000654 vassert(syned == True);
ceriona2f75882005-03-15 16:33:38 +0000655 vassert(srcR->Pri.Imm.imm32 < 0x10000);
cerion98411db2005-02-16 14:14:49 +0000656 }
657 }
cerion92f5dc72005-02-10 16:11:35 +0000658 i->tag = Pin_MulL;
659 i->Pin.MulL.syned = syned;
660 i->Pin.MulL.word = word;
cerionc0e707e2005-02-10 22:35:34 +0000661 i->Pin.MulL.dst = dst;
ceriona2f75882005-03-15 16:33:38 +0000662 i->Pin.MulL.srcL = srcL;
663 i->Pin.MulL.srcR = srcR;
cerion92f5dc72005-02-10 16:11:35 +0000664 return i;
665}
ceriona2f75882005-03-15 16:33:38 +0000666PPC32Instr* PPC32Instr_Div ( Bool syned, HReg dst, HReg srcL, HReg srcR ) {
sewardj9a036bf2005-03-14 18:19:08 +0000667 PPC32Instr* i = LibVEX_Alloc(sizeof(PPC32Instr));
cerionc0e707e2005-02-10 22:35:34 +0000668 i->tag = Pin_Div;
669 i->Pin.Div.syned = syned;
670 i->Pin.Div.dst = dst;
ceriona2f75882005-03-15 16:33:38 +0000671 i->Pin.Div.srcL = srcL;
672 i->Pin.Div.srcR = srcR;
cerionc0e707e2005-02-10 22:35:34 +0000673 return i;
674}
cerion2c49e032005-02-09 17:29:49 +0000675PPC32Instr* PPC32Instr_Call ( PPC32CondCode cond, Addr32 target, Int regparms ) {
676 PPC32Instr* i = LibVEX_Alloc(sizeof(PPC32Instr));
677 i->tag = Pin_Call;
678 i->Pin.Call.cond = cond;
679 i->Pin.Call.target = target;
680 i->Pin.Call.regparms = regparms;
681 vassert(regparms >= 0 && regparms < PPC32_N_REGPARMS);
682 return i;
683}
684PPC32Instr* PPC32Instr_Goto ( IRJumpKind jk, PPC32CondCode cond, PPC32RI* dst ) {
685 PPC32Instr* i = LibVEX_Alloc(sizeof(PPC32Instr));
686 i->tag = Pin_Goto;
687 i->Pin.Goto.cond = cond;
688 i->Pin.Goto.dst = dst;
689 i->Pin.Goto.jk = jk;
690 return i;
691}
cerionb536af92005-02-10 15:03:19 +0000692PPC32Instr* PPC32Instr_CMov32 ( PPC32CondCode cond, HReg dst, PPC32RI* src ) {
693 PPC32Instr* i = LibVEX_Alloc(sizeof(PPC32Instr));
694 i->tag = Pin_CMov32;
695 i->Pin.CMov32.cond = cond;
696 i->Pin.CMov32.src = src;
697 i->Pin.CMov32.dst = dst;
cerionab9132d2005-02-15 15:46:59 +0000698 vassert(cond.test != Pct_ALWAYS);
cerionb536af92005-02-10 15:03:19 +0000699 return i;
700}
cerion7cf8e4e2005-02-16 16:08:17 +0000701PPC32Instr* PPC32Instr_Load ( UChar sz, Bool syned,
702 HReg dst, PPC32AMode* src ) {
703 PPC32Instr* i = LibVEX_Alloc(sizeof(PPC32Instr));
704 i->tag = Pin_Load;
705 i->Pin.Load.sz = sz;
706 i->Pin.Load.syned = syned;
707 i->Pin.Load.src = src;
708 i->Pin.Load.dst = dst;
cerion2c49e032005-02-09 17:29:49 +0000709 vassert(sz == 1 || sz == 2 || sz == 4);
cerioncd304492005-02-08 19:40:24 +0000710 return i;
711}
712PPC32Instr* PPC32Instr_Store ( UChar sz, PPC32AMode* dst, HReg src ) {
713 PPC32Instr* i = LibVEX_Alloc(sizeof(PPC32Instr));
714 i->tag = Pin_Store;
715 i->Pin.Store.sz = sz;
716 i->Pin.Store.src = src;
717 i->Pin.Store.dst = dst;
718 vassert(sz == 1 || sz == 2 || sz == 4);
719 return i;
720}
cerionb536af92005-02-10 15:03:19 +0000721PPC32Instr* PPC32Instr_Set32 ( PPC32CondCode cond, HReg dst ) {
722 PPC32Instr* i = LibVEX_Alloc(sizeof(PPC32Instr));
723 i->tag = Pin_Set32;
724 i->Pin.Set32.cond = cond;
725 i->Pin.Set32.dst = dst;
726 return i;
727}
cerion98411db2005-02-16 14:14:49 +0000728PPC32Instr* PPC32Instr_MFence ( void )
cerion92f5dc72005-02-10 16:11:35 +0000729{
730 PPC32Instr* i = LibVEX_Alloc(sizeof(PPC32Instr));
731 i->tag = Pin_MFence;
cerion92f5dc72005-02-10 16:11:35 +0000732 return i;
733}
cerioncd304492005-02-08 19:40:24 +0000734
cerion094d1392005-06-20 13:45:57 +0000735PPC32Instr* PPC32Instr_FpUnary ( PPC32FpOp op, HReg dst, HReg src ) {
736 PPC32Instr* i = LibVEX_Alloc(sizeof(PPC32Instr));
737 i->tag = Pin_FpUnary;
738 i->Pin.FpUnary.op = op;
739 i->Pin.FpUnary.dst = dst;
740 i->Pin.FpUnary.src = src;
741 return i;
742}
743PPC32Instr* PPC32Instr_FpBinary ( PPC32FpOp op, HReg dst, HReg srcL, HReg srcR ) {
744 PPC32Instr* i = LibVEX_Alloc(sizeof(PPC32Instr));
745 i->tag = Pin_FpBinary;
746 i->Pin.FpBinary.op = op;
747 i->Pin.FpBinary.dst = dst;
748 i->Pin.FpBinary.srcL = srcL;
749 i->Pin.FpBinary.srcR = srcR;
750 return i;
751}
752PPC32Instr* PPC32Instr_FpLdSt ( Bool isLoad, UChar sz, HReg reg, PPC32AMode* addr ) {
753 PPC32Instr* i = LibVEX_Alloc(sizeof(PPC32Instr));
754 i->tag = Pin_FpLdSt;
755 i->Pin.FpLdSt.isLoad = isLoad;
756 i->Pin.FpLdSt.sz = sz;
757 i->Pin.FpLdSt.reg = reg;
758 i->Pin.FpLdSt.addr = addr;
759 vassert(sz == 4 || sz == 8);
760 return i;
761}
762PPC32Instr* PPC32Instr_FpF64toF32 ( HReg dst, HReg src ) {
763 PPC32Instr* i = LibVEX_Alloc(sizeof(PPC32Instr));
764 i->tag = Pin_FpF64toF32;
765 i->Pin.FpF64toF32.dst = dst;
766 i->Pin.FpF64toF32.src = src;
767 return i;
768}
769PPC32Instr* PPC32Instr_FpF64toI32 ( HReg dst, HReg src ) {
770 PPC32Instr* i = LibVEX_Alloc(sizeof(PPC32Instr));
771 i->tag = Pin_FpF64toI32;
772 i->Pin.FpF64toI32.dst = dst;
773 i->Pin.FpF64toI32.src = src;
774 return i;
775}
776PPC32Instr* PPC32Instr_FpCMov ( PPC32CondCode cond, HReg dst, HReg src ) {
777 PPC32Instr* i = LibVEX_Alloc(sizeof(PPC32Instr));
778 i->tag = Pin_FpCMov;
779 i->Pin.FpCMov.cond = cond;
780 i->Pin.FpCMov.dst = dst;
781 i->Pin.FpCMov.src = src;
782 vassert(cond.test != Pct_ALWAYS);
783 return i;
784}
785PPC32Instr* PPC32Instr_FpLdFPSCR ( HReg src ) {
786 PPC32Instr* i = LibVEX_Alloc(sizeof(PPC32Instr));
787 i->tag = Pin_FpLdFPSCR;
788 i->Pin.FpLdFPSCR.src = src;
789 return i;
790}
791PPC32Instr* PPC32Instr_FpCmp ( HReg dst, HReg srcL, HReg srcR ) {
792 PPC32Instr* i = LibVEX_Alloc(sizeof(PPC32Instr));
793 i->tag = Pin_FpCmp;
794 i->Pin.FpCmp.dst = dst;
795 i->Pin.FpCmp.srcL = srcL;
796 i->Pin.FpCmp.srcR = srcR;
797 return i;
798}
cerionbcf8c3e2005-02-04 16:17:07 +0000799
cerion7f000af2005-02-22 20:36:49 +0000800/* Read/Write Link Register */
cerionc3d8bdc2005-06-28 18:06:23 +0000801PPC32Instr* PPC32Instr_RdWrLR ( Bool wrLR, HReg gpr ) {
cerion7f000af2005-02-22 20:36:49 +0000802 PPC32Instr* i = LibVEX_Alloc(sizeof(PPC32Instr));
803 i->tag = Pin_RdWrLR;
804 i->Pin.RdWrLR.wrLR = wrLR;
805 i->Pin.RdWrLR.gpr = gpr;
806 return i;
807}
808
cerionc3d8bdc2005-06-28 18:06:23 +0000809/* AltiVec */
810PPC32Instr* PPC32Instr_AvLdSt ( Bool isLoad, UChar sz, HReg reg, PPC32AMode* addr ) {
811 PPC32Instr* i = LibVEX_Alloc(sizeof(PPC32Instr));
812 i->tag = Pin_AvLdSt;
813 i->Pin.AvLdSt.isLoad = isLoad;
814 i->Pin.AvLdSt.sz = sz;
815 i->Pin.AvLdSt.reg = reg;
816 i->Pin.AvLdSt.addr = addr;
817 return i;
818}
819PPC32Instr* PPC32Instr_AvUnary ( PPC32AvOp op, HReg dst, HReg src ) {
820 PPC32Instr* i = LibVEX_Alloc(sizeof(PPC32Instr));
821 i->tag = Pin_AvUnary;
822 i->Pin.AvUnary.op = op;
823 i->Pin.AvUnary.dst = dst;
824 i->Pin.AvUnary.src = src;
825 return i;
826}
827PPC32Instr* PPC32Instr_AvBinary ( PPC32AvOp op, HReg dst, HReg srcL, HReg srcR ) {
828 PPC32Instr* i = LibVEX_Alloc(sizeof(PPC32Instr));
829 i->tag = Pin_AvBinary;
830 i->Pin.AvBinary.op = op;
831 i->Pin.AvBinary.dst = dst;
832 i->Pin.AvBinary.srcL = srcL;
833 i->Pin.AvBinary.srcR = srcR;
834 return i;
835}
cerion6b6f59e2005-06-28 20:59:18 +0000836PPC32Instr* PPC32Instr_AvBin8x16 ( PPC32AvOp op, HReg dst, HReg srcL, HReg srcR ) {
837 PPC32Instr* i = LibVEX_Alloc(sizeof(PPC32Instr));
838 i->tag = Pin_AvBin8x16;
839 i->Pin.AvBin8x16.op = op;
840 i->Pin.AvBin8x16.dst = dst;
841 i->Pin.AvBin8x16.srcL = srcL;
842 i->Pin.AvBin8x16.srcR = srcR;
843 return i;
844}
845PPC32Instr* PPC32Instr_AvBin16x8 ( PPC32AvOp op, HReg dst, HReg srcL, HReg srcR ) {
846 PPC32Instr* i = LibVEX_Alloc(sizeof(PPC32Instr));
847 i->tag = Pin_AvBin16x8;
848 i->Pin.AvBin16x8.op = op;
849 i->Pin.AvBin16x8.dst = dst;
850 i->Pin.AvBin16x8.srcL = srcL;
851 i->Pin.AvBin16x8.srcR = srcR;
852 return i;
853}
854PPC32Instr* PPC32Instr_AvBin32x4 ( PPC32AvOp op, HReg dst, HReg srcL, HReg srcR ) {
855 PPC32Instr* i = LibVEX_Alloc(sizeof(PPC32Instr));
856 i->tag = Pin_AvBin32x4;
857 i->Pin.AvBin32x4.op = op;
858 i->Pin.AvBin32x4.dst = dst;
859 i->Pin.AvBin32x4.srcL = srcL;
860 i->Pin.AvBin32x4.srcR = srcR;
861 return i;
862}
863PPC32Instr* PPC32Instr_AvBin32Fx4 ( PPC32AvOp op, HReg dst, HReg srcL, HReg srcR ) {
864 PPC32Instr* i = LibVEX_Alloc(sizeof(PPC32Instr));
865 i->tag = Pin_AvBin32Fx4;
866 i->Pin.AvBin32Fx4.op = op;
867 i->Pin.AvBin32Fx4.dst = dst;
868 i->Pin.AvBin32Fx4.srcL = srcL;
869 i->Pin.AvBin32Fx4.srcR = srcR;
870 return i;
871}
cerionc3d8bdc2005-06-28 18:06:23 +0000872PPC32Instr* PPC32Instr_AvPerm ( HReg ctl, HReg dst, HReg srcL, HReg srcR ) {
873 PPC32Instr* i = LibVEX_Alloc(sizeof(PPC32Instr));
874 i->tag = Pin_AvPerm;
875 i->Pin.AvPerm.ctl = ctl;
876 i->Pin.AvPerm.dst = dst;
877 i->Pin.AvPerm.srcL = srcL;
878 i->Pin.AvPerm.srcR = srcR;
879 return i;
880}
881PPC32Instr* PPC32Instr_AvSel ( HReg ctl, HReg dst, HReg srcL, HReg srcR ) {
882 PPC32Instr* i = LibVEX_Alloc(sizeof(PPC32Instr));
883 i->tag = Pin_AvSel;
884 i->Pin.AvSel.ctl = ctl;
885 i->Pin.AvSel.dst = dst;
886 i->Pin.AvSel.srcL = srcL;
887 i->Pin.AvSel.srcR = srcR;
888 return i;
889}
890PPC32Instr* PPC32Instr_AvShlDbl ( UChar shift, HReg dst, HReg srcL, HReg srcR ) {
891 PPC32Instr* i = LibVEX_Alloc(sizeof(PPC32Instr));
892 i->tag = Pin_AvShlDbl;
893 i->Pin.AvShlDbl.shift = shift;
894 i->Pin.AvShlDbl.dst = dst;
895 i->Pin.AvShlDbl.srcL = srcL;
896 i->Pin.AvShlDbl.srcR = srcR;
897 return i;
898}
899PPC32Instr* PPC32Instr_AvSplat ( UChar sz, HReg dst, PPC32RI* src ) {
900 PPC32Instr* i = LibVEX_Alloc(sizeof(PPC32Instr));
901 i->tag = Pin_AvSplat;
902 i->Pin.AvSplat.sz = sz;
903 i->Pin.AvSplat.dst = dst;
904 i->Pin.AvSplat.src = src;
905 return i;
906}
cerion6b6f59e2005-06-28 20:59:18 +0000907PPC32Instr* PPC32Instr_AvCMov ( PPC32CondCode cond, HReg dst, HReg src ) {
908 PPC32Instr* i = LibVEX_Alloc(sizeof(PPC32Instr));
909 i->tag = Pin_AvCMov;
910 i->Pin.AvCMov.cond = cond;
911 i->Pin.AvCMov.dst = dst;
912 i->Pin.AvCMov.src = src;
913 vassert(cond.test != Pct_ALWAYS);
914 return i;
915}
cerionc3d8bdc2005-06-28 18:06:23 +0000916PPC32Instr* PPC32Instr_AvLdVSCR ( HReg src ) {
917 PPC32Instr* i = LibVEX_Alloc(sizeof(PPC32Instr));
918 i->tag = Pin_AvLdVSCR;
919 i->Pin.AvLdVSCR.src = src;
920 return i;
921}
922
cerion9e263e32005-03-03 17:21:51 +0000923
924/* Pretty Print instructions */
925static void ppLoadImm ( HReg dst, UInt imm ) {
926 if (imm < 0x10000) {
927 vex_printf("li ");
928 ppHRegPPC32(dst);
929 vex_printf(",0x%x", imm);
930 } else {
931 vex_printf("lis ");
932 ppHRegPPC32(dst);
933 vex_printf(",0x%x ; ", imm >> 16);
934 vex_printf("ori ");
935 ppHRegPPC32(dst);
936 vex_printf(",");
937 ppHRegPPC32(dst);
938 vex_printf(",0x%x", imm & 0xFFFF);
939 }
940}
941
942static void ppMovReg ( HReg dst, HReg src ) {
943 if (hregNumber(dst) != hregNumber(src)) {
944 vex_printf("mr ");
945 ppHRegPPC32(dst);
946 vex_printf(",");
947 ppHRegPPC32(src);
948 }
949}
950
cerionbcf8c3e2005-02-04 16:17:07 +0000951void ppPPC32Instr ( PPC32Instr* i )
952{
953 switch (i->tag) {
cerionb85e8bb2005-02-16 08:54:33 +0000954 case Pin_Alu32:
955 if (i->Pin.Alu32.op == Palu_OR && // or Rd,Rs,Rs == mr Rd,Rs
ceriona2f75882005-03-15 16:33:38 +0000956 i->Pin.Alu32.srcR->tag == Pri_Reg &&
957 i->Pin.Alu32.srcR->Pri.Reg.reg == i->Pin.Alu32.srcL) {
cerionb85e8bb2005-02-16 08:54:33 +0000958 vex_printf("mr ");
959 ppHRegPPC32(i->Pin.Alu32.dst);
cerioncd304492005-02-08 19:40:24 +0000960 vex_printf(",");
ceriona2f75882005-03-15 16:33:38 +0000961 ppHRegPPC32(i->Pin.Alu32.srcL);
cerioncd304492005-02-08 19:40:24 +0000962 return;
cerionb85e8bb2005-02-16 08:54:33 +0000963 }
cerion9e263e32005-03-03 17:21:51 +0000964 if (i->Pin.Alu32.op == Palu_ADD && // add rD,r0,val == li rD,val
ceriona2f75882005-03-15 16:33:38 +0000965 i->Pin.Alu32.srcL == hregPPC32_GPR0() &&
966 i->Pin.Alu32.srcR->tag == Pri_Imm) {
cerionb85e8bb2005-02-16 08:54:33 +0000967 vex_printf("li ");
968 ppHRegPPC32(i->Pin.Alu32.dst);
969 vex_printf(",");
ceriona2f75882005-03-15 16:33:38 +0000970 ppPPC32RI(i->Pin.Alu32.srcR);
cerionb85e8bb2005-02-16 08:54:33 +0000971 return;
972 }
cerionb8c3b7f2005-03-01 20:27:49 +0000973 if (i->Pin.Alu32.op == Palu_AND && // 'andi.' - always has the '.'
ceriona2f75882005-03-15 16:33:38 +0000974 i->Pin.Alu32.srcR->tag == Pri_Imm) {
cerionb8c3b7f2005-03-01 20:27:49 +0000975 vex_printf("andi. ");
976 ppHRegPPC32(i->Pin.Alu32.dst);
977 vex_printf(",");
ceriona2f75882005-03-15 16:33:38 +0000978 ppHRegPPC32(i->Pin.Alu32.srcL);
cerionb8c3b7f2005-03-01 20:27:49 +0000979 vex_printf(",");
ceriona2f75882005-03-15 16:33:38 +0000980 ppPPC32RI(i->Pin.Alu32.srcR);
cerionb8c3b7f2005-03-01 20:27:49 +0000981 return;
982 }
cerionb85e8bb2005-02-16 08:54:33 +0000983 vex_printf("%s%s ", showPPC32AluOp(i->Pin.Alu32.op),
ceriona2f75882005-03-15 16:33:38 +0000984 i->Pin.Alu32.srcR->tag == Pri_Imm ? "i" : "" );
cerionb85e8bb2005-02-16 08:54:33 +0000985 ppHRegPPC32(i->Pin.Alu32.dst);
986 vex_printf(",");
ceriona2f75882005-03-15 16:33:38 +0000987 ppHRegPPC32(i->Pin.Alu32.srcL);
cerionb85e8bb2005-02-16 08:54:33 +0000988 vex_printf(",");
ceriona2f75882005-03-15 16:33:38 +0000989 ppPPC32RI(i->Pin.Alu32.srcR);
cerionb85e8bb2005-02-16 08:54:33 +0000990 return;
cerion5e2527e2005-02-25 16:39:58 +0000991 case Pin_Sub32:
ceriona2f75882005-03-15 16:33:38 +0000992 vex_printf("subf%s ", i->Pin.Sub32.srcL->tag == Pri_Imm ? "ic" : "" );
cerion5e2527e2005-02-25 16:39:58 +0000993 ppHRegPPC32(i->Pin.Sub32.dst);
994 vex_printf(",");
ceriona2f75882005-03-15 16:33:38 +0000995 ppHRegPPC32(i->Pin.Sub32.srcR); // yes, order is right :-)
cerion5e2527e2005-02-25 16:39:58 +0000996 vex_printf(",");
ceriona2f75882005-03-15 16:33:38 +0000997 ppPPC32RI(i->Pin.Sub32.srcL);
cerion5e2527e2005-02-25 16:39:58 +0000998 return;
cerionb85e8bb2005-02-16 08:54:33 +0000999 case Pin_Sh32:
1000 vex_printf("%s%s ", showPPC32ShiftOp(i->Pin.Sh32.op),
1001 i->Pin.Sh32.shft->tag == Pri_Imm ? "i" : "" );
1002 ppHRegPPC32(i->Pin.Sh32.dst);
1003 vex_printf(",");
1004 ppHRegPPC32(i->Pin.Sh32.src);
1005 vex_printf(",");
1006 ppPPC32RI(i->Pin.Sh32.shft);
1007 return;
cerionb85e8bb2005-02-16 08:54:33 +00001008 case Pin_Cmp32:
sewardj428fabd2005-03-21 03:11:17 +00001009 vex_printf("%s%s %%crf%u,", showPPC32CmpOp(i->Pin.Cmp32.op),
ceriona2f75882005-03-15 16:33:38 +00001010 i->Pin.Cmp32.srcR->tag == Pri_Imm ? "i" : "",
cerion8c51ed42005-02-22 11:16:54 +00001011 (7 - i->Pin.Cmp32.crfD));
ceriona2f75882005-03-15 16:33:38 +00001012 ppHRegPPC32(i->Pin.Cmp32.srcL);
cerionb85e8bb2005-02-16 08:54:33 +00001013 vex_printf(",");
ceriona2f75882005-03-15 16:33:38 +00001014 ppPPC32RI(i->Pin.Cmp32.srcR);
cerionb85e8bb2005-02-16 08:54:33 +00001015 return;
1016 case Pin_Unary32:
1017 vex_printf("%s ", showPPC32UnaryOp(i->Pin.Unary32.op));
1018 ppHRegPPC32(i->Pin.Unary32.dst);
1019 vex_printf(",");
1020 ppHRegPPC32(i->Pin.Unary32.src);
1021 return;
1022 case Pin_MulL:
ceriona2f75882005-03-15 16:33:38 +00001023 if (i->Pin.MulL.srcR->tag == Pri_Imm) {
cerionb85e8bb2005-02-16 08:54:33 +00001024 vex_printf("mulli ");
1025 } else {
1026 vex_printf("mul%s%c ",
1027 i->Pin.MulL.word ? "hw" : "lw",
1028 i->Pin.MulL.syned ? 's' : 'u');
1029 }
1030 ppHRegPPC32(i->Pin.MulL.dst);
1031 vex_printf(",");
ceriona2f75882005-03-15 16:33:38 +00001032 ppHRegPPC32(i->Pin.MulL.srcL);
cerionb85e8bb2005-02-16 08:54:33 +00001033 vex_printf(",");
ceriona2f75882005-03-15 16:33:38 +00001034 ppPPC32RI(i->Pin.MulL.srcR);
cerionb85e8bb2005-02-16 08:54:33 +00001035 return;
1036 case Pin_Div:
1037 vex_printf("divw%s ",
1038 i->Pin.Div.syned ? "" : "u");
cerion33aa6da2005-02-16 10:25:26 +00001039 ppHRegPPC32(i->Pin.Div.dst);
cerionb85e8bb2005-02-16 08:54:33 +00001040 vex_printf(",");
ceriona2f75882005-03-15 16:33:38 +00001041 ppHRegPPC32(i->Pin.Div.srcL);
cerionb85e8bb2005-02-16 08:54:33 +00001042 vex_printf(",");
ceriona2f75882005-03-15 16:33:38 +00001043 ppHRegPPC32(i->Pin.Div.srcR);
cerionb85e8bb2005-02-16 08:54:33 +00001044 return;
cerionb85e8bb2005-02-16 08:54:33 +00001045 case Pin_Call:
cerion8c51ed42005-02-22 11:16:54 +00001046 vex_printf("call: ");
1047 if (i->Pin.Call.cond.test != Pct_ALWAYS) {
1048 vex_printf("if (%%crf0.%s) ", showPPC32CondCode(i->Pin.Call.cond));
1049 }
1050 vex_printf("{ ");
cerion9e263e32005-03-03 17:21:51 +00001051 ppLoadImm(hregPPC32_GPR12(), i->Pin.Call.target);
cerion9762bbf2005-06-23 08:44:52 +00001052 vex_printf(" ; mtctr r12 ; bctrl [regparms=%d] }",i->Pin.Call.regparms);
cerionb85e8bb2005-02-16 08:54:33 +00001053 break;
1054 case Pin_Goto:
cerion33aa6da2005-02-16 10:25:26 +00001055 vex_printf("goto: ");
cerionb85e8bb2005-02-16 08:54:33 +00001056 if (i->Pin.Goto.cond.test != Pct_ALWAYS) {
cerion8c51ed42005-02-22 11:16:54 +00001057 vex_printf("if (%%crf0.%s) ", showPPC32CondCode(i->Pin.Goto.cond));
cerionb85e8bb2005-02-16 08:54:33 +00001058 }
cerion8c51ed42005-02-22 11:16:54 +00001059 vex_printf("{ ");
cerionb85e8bb2005-02-16 08:54:33 +00001060 if (i->Pin.Goto.jk != Ijk_Boring) {
cerion9e263e32005-03-03 17:21:51 +00001061 vex_printf("li %%r31,$");
cerionb85e8bb2005-02-16 08:54:33 +00001062 ppIRJumpKind(i->Pin.Goto.jk);
1063 vex_printf(" ; ");
1064 }
cerione97e1062005-02-21 15:09:19 +00001065 if (i->Pin.Goto.dst->tag == Pri_Imm) {
cerion9e263e32005-03-03 17:21:51 +00001066 ppLoadImm(hregPPC32_GPR3(), i->Pin.Goto.dst->Pri.Imm.imm32);
cerione97e1062005-02-21 15:09:19 +00001067 } else {
cerion9e263e32005-03-03 17:21:51 +00001068 ppMovReg(hregPPC32_GPR3(), i->Pin.Goto.dst->Pri.Reg.reg);
cerione97e1062005-02-21 15:09:19 +00001069 }
cerion9e263e32005-03-03 17:21:51 +00001070 vex_printf(" ; blr }");
cerionb85e8bb2005-02-16 08:54:33 +00001071 return;
1072 case Pin_CMov32:
cerionb85e8bb2005-02-16 08:54:33 +00001073 vex_printf("cmov32 (%s) ", showPPC32CondCode(i->Pin.CMov32.cond));
1074 ppHRegPPC32(i->Pin.CMov32.dst);
1075 vex_printf(",");
1076 ppPPC32RI(i->Pin.CMov32.src);
cerion8c51ed42005-02-22 11:16:54 +00001077 vex_printf(": ");
1078 if (i->Pin.CMov32.cond.test != Pct_ALWAYS) {
1079 vex_printf("if (%%crf0.%s) ", showPPC32CondCode(i->Pin.CMov32.cond));
1080 }
1081 vex_printf("{ ");
1082 if (i->Pin.CMov32.src->tag == Pri_Imm) {
cerion9e263e32005-03-03 17:21:51 +00001083 ppLoadImm(i->Pin.CMov32.dst, i->Pin.CMov32.src->Pri.Imm.imm32);
cerion8c51ed42005-02-22 11:16:54 +00001084 } else {
cerion9e263e32005-03-03 17:21:51 +00001085 ppMovReg(i->Pin.CMov32.dst, i->Pin.CMov32.src->Pri.Reg.reg);
cerion8c51ed42005-02-22 11:16:54 +00001086 }
1087 vex_printf(" }");
cerionb85e8bb2005-02-16 08:54:33 +00001088 return;
cerion7cf8e4e2005-02-16 16:08:17 +00001089 case Pin_Load: {
1090 UChar sz = i->Pin.Load.sz;
1091 Bool syned = i->Pin.Load.syned;
sewardj428fabd2005-03-21 03:11:17 +00001092 Bool idxd = toBool(i->Pin.Load.src->tag == Pam_RR);
cerion7cf8e4e2005-02-16 16:08:17 +00001093 vex_printf("l%c%c%s ",
cerionb85e8bb2005-02-16 08:54:33 +00001094 (sz==1) ? 'b' : (sz==2 ? 'h' : 'w'),
1095 syned ? 'a' : 'z',
cerionb85e8bb2005-02-16 08:54:33 +00001096 idxd ? "x" : "" );
cerion7cf8e4e2005-02-16 16:08:17 +00001097 ppHRegPPC32(i->Pin.Load.dst);
cerionb85e8bb2005-02-16 08:54:33 +00001098 vex_printf(",");
cerion7cf8e4e2005-02-16 16:08:17 +00001099 ppPPC32AMode(i->Pin.Load.src);
cerionb85e8bb2005-02-16 08:54:33 +00001100 return;
1101 }
1102 case Pin_Store: {
1103 UChar sz = i->Pin.Store.sz;
sewardj428fabd2005-03-21 03:11:17 +00001104 Bool idxd = toBool(i->Pin.Store.dst->tag == Pam_RR);
cerion7cf8e4e2005-02-16 16:08:17 +00001105 vex_printf("st%c%s ",
cerionb85e8bb2005-02-16 08:54:33 +00001106 (sz==1) ? 'b' : (sz==2 ? 'h' : 'w'),
cerionb85e8bb2005-02-16 08:54:33 +00001107 idxd ? "x" : "" );
1108 ppHRegPPC32(i->Pin.Store.src);
1109 vex_printf(",");
1110 ppPPC32AMode(i->Pin.Store.dst);
1111 return;
1112 }
cerionf9d6e222005-02-23 18:21:31 +00001113 case Pin_Set32: {
1114 PPC32CondCode cc = i->Pin.Set32.cond;
1115 vex_printf("set32 (%s),", showPPC32CondCode(cc));
cerionb85e8bb2005-02-16 08:54:33 +00001116 ppHRegPPC32(i->Pin.Set32.dst);
cerionf9d6e222005-02-23 18:21:31 +00001117 if (cc.test == Pct_ALWAYS) {
1118 vex_printf(": { li ");
1119 ppHRegPPC32(i->Pin.Set32.dst);
1120 vex_printf(",1 }");
1121 } else {
1122 vex_printf(": { mfcr r0 ; rlwinm ");
1123 ppHRegPPC32(i->Pin.Set32.dst);
sewardj428fabd2005-03-21 03:11:17 +00001124 vex_printf(",r0,%u,31,31", cc.flag+1);
cerionf9d6e222005-02-23 18:21:31 +00001125 if (cc.test == Pct_FALSE) {
1126 vex_printf("; xori ");
1127 ppHRegPPC32(i->Pin.Set32.dst);
1128 vex_printf(",");
1129 ppHRegPPC32(i->Pin.Set32.dst);
1130 vex_printf("1");
1131 }
1132 vex_printf(" }");
1133 }
cerionb85e8bb2005-02-16 08:54:33 +00001134 return;
cerionf9d6e222005-02-23 18:21:31 +00001135 }
cerionb85e8bb2005-02-16 08:54:33 +00001136 case Pin_MFence:
cerion98411db2005-02-16 14:14:49 +00001137 vex_printf("mfence (=sync)");
cerionb85e8bb2005-02-16 08:54:33 +00001138 return;
cerion094d1392005-06-20 13:45:57 +00001139
1140 case Pin_FpUnary:
1141 vex_printf("%s ", showPPC32FpOp(i->Pin.FpUnary.op));
1142 ppHRegPPC32(i->Pin.FpUnary.dst);
1143 vex_printf(",");
1144 ppHRegPPC32(i->Pin.FpUnary.src);
1145 return;
1146 case Pin_FpBinary:
1147 vex_printf("%s ", showPPC32FpOp(i->Pin.FpBinary.op));
1148 ppHRegPPC32(i->Pin.FpBinary.dst);
1149 vex_printf(",");
1150 ppHRegPPC32(i->Pin.FpBinary.srcL);
1151 vex_printf(",");
1152 ppHRegPPC32(i->Pin.FpBinary.srcR);
1153 return;
1154 case Pin_FpLdSt: {
1155 UChar sz = i->Pin.FpLdSt.sz;
1156 Bool idxd = toBool(i->Pin.FpLdSt.addr->tag == Pam_RR);
1157 if (i->Pin.FpLdSt.isLoad) {
1158 vex_printf("lf%c%s ",
1159 (sz==4 ? 's' : 'd'),
1160 idxd ? "x" : "" );
1161 ppHRegPPC32(i->Pin.FpLdSt.reg);
1162 vex_printf(",");
1163 ppPPC32AMode(i->Pin.FpLdSt.addr);
1164 } else {
1165 vex_printf("stf%c%s ",
1166 (sz==4 ? 's' : 'd'),
1167 idxd ? "x" : "" );
1168 ppHRegPPC32(i->Pin.FpLdSt.reg);
1169 vex_printf(",");
1170 ppPPC32AMode(i->Pin.FpLdSt.addr);
1171 }
1172 return;
1173 }
1174 case Pin_FpF64toF32:
1175 vex_printf("frsp ");
1176 ppHRegPPC32(i->Pin.FpF64toF32.dst);
1177 vex_printf(",");
1178 ppHRegPPC32(i->Pin.FpF64toF32.src);
1179 return;
1180 case Pin_FpF64toI32:
1181 vex_printf("fctiw %%fr7,");
1182 ppHRegPPC32(i->Pin.FpF64toI32.src);
1183 vex_printf("; stfiwx %%fr7,%%r0,%%r1");
1184 vex_printf("; lwzx ");
1185 ppHRegPPC32(i->Pin.FpF64toI32.dst);
1186 vex_printf(",%%r0,%%r1");
1187 return;
1188 case Pin_FpCMov:
1189 vex_printf("fpcmov (%s) ", showPPC32CondCode(i->Pin.FpCMov.cond));
1190 ppHRegPPC32(i->Pin.FpCMov.dst);
1191 vex_printf(",");
1192 ppHRegPPC32(i->Pin.FpCMov.src);
1193 vex_printf(": ");
1194 vex_printf("if (fr_dst != fr_src) { ");
1195 if (i->Pin.FpCMov.cond.test != Pct_ALWAYS) {
1196 vex_printf("if (%%crf0.%s) { ", showPPC32CondCode(i->Pin.FpCMov.cond));
1197 }
1198 vex_printf("fmr ");
1199 ppHRegPPC32(i->Pin.FpCMov.dst);
1200 vex_printf(",");
1201 ppHRegPPC32(i->Pin.FpCMov.src);
1202 if (i->Pin.FpCMov.cond.test != Pct_ALWAYS)
1203 vex_printf(" }");
1204 vex_printf(" }");
1205 return;
1206 case Pin_FpLdFPSCR:
1207 vex_printf("mtfsf 0xFF,");
1208 ppHRegPPC32(i->Pin.FpLdFPSCR.src);
1209 return;
1210 case Pin_FpCmp:
1211 vex_printf("fcmpo %%crf1,");
1212 ppHRegPPC32(i->Pin.FpCmp.srcL);
1213 vex_printf(",");
1214 ppHRegPPC32(i->Pin.FpCmp.srcR);
1215 vex_printf("; mfcr ");
1216 ppHRegPPC32(i->Pin.FpCmp.dst);
1217 vex_printf("; rlwinm ");
1218 ppHRegPPC32(i->Pin.FpCmp.dst);
1219 vex_printf(",");
1220 ppHRegPPC32(i->Pin.FpCmp.dst);
1221 vex_printf(",8,28,31");
1222 return;
cerionbcf8c3e2005-02-04 16:17:07 +00001223
cerion7f000af2005-02-22 20:36:49 +00001224 case Pin_RdWrLR:
1225 vex_printf("%s ", i->Pin.RdWrLR.wrLR ? "mtlr" : "mflr");
1226 ppHRegPPC32(i->Pin.RdWrLR.gpr);
1227 return;
1228
cerionc3d8bdc2005-06-28 18:06:23 +00001229 case Pin_AvLdSt: {
1230 UChar sz = i->Pin.AvLdSt.sz;
cerionc3d8bdc2005-06-28 18:06:23 +00001231 if (i->Pin.AvLdSt.addr->tag == Pam_IR) {
cerionc3d8bdc2005-06-28 18:06:23 +00001232 ppLoadImm(hregPPC32_GPR30(), i->Pin.AvLdSt.addr->Pam.RR.index);
cerion01713102005-06-29 19:05:08 +00001233 vex_printf(" ; ");
cerionc3d8bdc2005-06-28 18:06:23 +00001234 }
cerion01713102005-06-29 19:05:08 +00001235 if (i->Pin.AvLdSt.isLoad)
cerion91c62fd2005-06-29 07:59:18 +00001236 vex_printf("lv%sx ", sz==8 ? "eb" : sz==16 ? "eh" : sz==32 ? "ew" : "");
cerion01713102005-06-29 19:05:08 +00001237 else
cerion91c62fd2005-06-29 07:59:18 +00001238 vex_printf("stv%sx ", sz==8 ? "eb" : sz==16 ? "eh" : sz==32 ? "ew" : "");
cerion01713102005-06-29 19:05:08 +00001239 ppHRegPPC32(i->Pin.AvLdSt.reg);
1240 vex_printf(",");
1241 if (i->Pin.AvLdSt.addr->tag == Pam_IR)
1242 vex_printf("%%r30");
1243 else
1244 ppHRegPPC32(i->Pin.AvLdSt.addr->Pam.RR.index);
1245 vex_printf(",");
1246 ppHRegPPC32(i->Pin.AvLdSt.addr->Pam.RR.base);
cerionc3d8bdc2005-06-28 18:06:23 +00001247 return;
1248 }
1249 case Pin_AvUnary:
1250 vex_printf("%s ", showPPC32AvOp(i->Pin.AvUnary.op));
1251 ppHRegPPC32(i->Pin.AvUnary.dst);
1252 vex_printf(",");
1253 ppHRegPPC32(i->Pin.AvUnary.src);
1254 return;
1255 case Pin_AvBinary:
1256 vex_printf("%s ", showPPC32AvOp(i->Pin.AvBinary.op));
1257 ppHRegPPC32(i->Pin.AvBinary.dst);
1258 vex_printf(",");
1259 ppHRegPPC32(i->Pin.AvBinary.srcL);
1260 vex_printf(",");
1261 ppHRegPPC32(i->Pin.AvBinary.srcR);
1262 return;
cerion6b6f59e2005-06-28 20:59:18 +00001263 case Pin_AvBin8x16:
1264 vex_printf("%s(b) ", showPPC32AvOp(i->Pin.AvBin8x16.op));
1265 ppHRegPPC32(i->Pin.AvBin8x16.dst);
1266 vex_printf(",");
1267 ppHRegPPC32(i->Pin.AvBin8x16.srcL);
1268 vex_printf(",");
1269 ppHRegPPC32(i->Pin.AvBin8x16.srcR);
1270 return;
1271 case Pin_AvBin16x8:
1272 vex_printf("%s(h) ", showPPC32AvOp(i->Pin.AvBin16x8.op));
1273 ppHRegPPC32(i->Pin.AvBin16x8.dst);
1274 vex_printf(",");
1275 ppHRegPPC32(i->Pin.AvBin16x8.srcL);
1276 vex_printf(",");
1277 ppHRegPPC32(i->Pin.AvBin16x8.srcR);
1278 return;
1279 case Pin_AvBin32x4:
1280 vex_printf("%s(w) ", showPPC32AvOp(i->Pin.AvBin32x4.op));
1281 ppHRegPPC32(i->Pin.AvBin32x4.dst);
1282 vex_printf(",");
1283 ppHRegPPC32(i->Pin.AvBin32x4.srcL);
1284 vex_printf(",");
1285 ppHRegPPC32(i->Pin.AvBin32x4.srcR);
1286 return;
1287 case Pin_AvBin32Fx4:
1288 vex_printf("%s ", showPPC32AvOp(i->Pin.AvBin32Fx4.op));
1289 ppHRegPPC32(i->Pin.AvBin32Fx4.dst);
1290 vex_printf(",");
1291 ppHRegPPC32(i->Pin.AvBin32Fx4.srcL);
1292 vex_printf(",");
1293 ppHRegPPC32(i->Pin.AvBin32Fx4.srcR);
1294 return;
cerionc3d8bdc2005-06-28 18:06:23 +00001295 case Pin_AvPerm:
1296 vex_printf("vperm ");
1297 ppHRegPPC32(i->Pin.AvPerm.dst);
1298 vex_printf(",");
1299 ppHRegPPC32(i->Pin.AvPerm.srcL);
1300 vex_printf(",");
1301 ppHRegPPC32(i->Pin.AvPerm.srcR);
1302 vex_printf(",");
1303 ppHRegPPC32(i->Pin.AvPerm.ctl);
1304 return;
1305
1306 case Pin_AvSel:
1307 vex_printf("vsel ");
1308 ppHRegPPC32(i->Pin.AvSel.dst);
1309 vex_printf(",");
1310 ppHRegPPC32(i->Pin.AvSel.srcL);
1311 vex_printf(",");
1312 ppHRegPPC32(i->Pin.AvSel.srcR);
1313 vex_printf(",");
1314 ppHRegPPC32(i->Pin.AvSel.ctl);
1315 return;
1316
1317 case Pin_AvShlDbl:
1318 vex_printf("vsldoi ");
1319 ppHRegPPC32(i->Pin.AvShlDbl.dst);
1320 vex_printf(",");
1321 ppHRegPPC32(i->Pin.AvShlDbl.srcL);
1322 vex_printf(",");
1323 ppHRegPPC32(i->Pin.AvShlDbl.srcR);
1324 vex_printf(",%u", i->Pin.AvShlDbl.shift);
1325 return;
1326
1327 case Pin_AvSplat: {
1328 UChar ch_sz = (i->Pin.AvSplat.sz == 8) ? 'b' :
1329 (i->Pin.AvSplat.sz == 16) ? 'h' : 'w';
1330 vex_printf("vsplt%s%c ",
1331 i->Pin.AvSplat.src->tag == Pri_Imm ? "is" : "", ch_sz);
1332 ppHRegPPC32(i->Pin.AvSplat.dst);
1333 vex_printf(",");
1334 if (i->Pin.AvSplat.src->tag == Pri_Imm) {
1335 vex_printf("%d", (Char)(i->Pin.AvSplat.src->Pri.Imm.imm32));
1336 } else {
1337 ppHRegPPC32(i->Pin.AvSplat.src->Pri.Reg.reg);
1338 vex_printf(", 0");
1339 }
1340 return;
1341 }
1342
cerion6b6f59e2005-06-28 20:59:18 +00001343 case Pin_AvCMov:
1344 vex_printf("avcmov (%s) ", showPPC32CondCode(i->Pin.AvCMov.cond));
1345 ppHRegPPC32(i->Pin.AvCMov.dst);
1346 vex_printf(",");
1347 ppHRegPPC32(i->Pin.AvCMov.src);
1348 vex_printf(": ");
1349 vex_printf("if (v_dst != v_src) { ");
1350 if (i->Pin.AvCMov.cond.test != Pct_ALWAYS) {
1351 vex_printf("if (%%crf0.%s) { ", showPPC32CondCode(i->Pin.AvCMov.cond));
1352 }
1353 vex_printf("vmr ");
1354 ppHRegPPC32(i->Pin.AvCMov.dst);
1355 vex_printf(",");
1356 ppHRegPPC32(i->Pin.AvCMov.src);
1357 if (i->Pin.FpCMov.cond.test != Pct_ALWAYS)
1358 vex_printf(" }");
1359 vex_printf(" }");
1360 return;
1361
cerionc3d8bdc2005-06-28 18:06:23 +00001362 case Pin_AvLdVSCR:
1363 vex_printf("mtvscr ");
1364 ppHRegPPC32(i->Pin.AvLdVSCR.src);
1365 return;
1366
cerionb85e8bb2005-02-16 08:54:33 +00001367 default:
sewardj428fabd2005-03-21 03:11:17 +00001368 vex_printf("\nppPPC32Instr(ppc32): No such tag(%d)\n", (Int)i->tag);
cerionb85e8bb2005-02-16 08:54:33 +00001369 vpanic("ppPPC32Instr(ppc32)");
cerionbcf8c3e2005-02-04 16:17:07 +00001370 }
1371}
1372
1373/* --------- Helpers for register allocation. --------- */
1374
1375void getRegUsage_PPC32Instr ( HRegUsage* u, PPC32Instr* i )
1376{
1377// Bool unary;
1378 initHRegUsage(u);
1379 switch (i->tag) {
cerionb85e8bb2005-02-16 08:54:33 +00001380 case Pin_Alu32:
ceriona2f75882005-03-15 16:33:38 +00001381 addHRegUse(u, HRmRead, i->Pin.Alu32.srcL);
1382 addRegUsage_PPC32RI(u, i->Pin.Alu32.srcR);
cerionb85e8bb2005-02-16 08:54:33 +00001383 addHRegUse(u, HRmWrite, i->Pin.Alu32.dst);
cerionb85e8bb2005-02-16 08:54:33 +00001384 return;
cerioncd304492005-02-08 19:40:24 +00001385
cerion5e2527e2005-02-25 16:39:58 +00001386 case Pin_Sub32:
ceriona2f75882005-03-15 16:33:38 +00001387 addRegUsage_PPC32RI(u, i->Pin.Sub32.srcL);
1388 addHRegUse(u, HRmRead, i->Pin.Sub32.srcR);
cerion5e2527e2005-02-25 16:39:58 +00001389 addHRegUse(u, HRmWrite, i->Pin.Sub32.dst);
1390 return;
1391
cerionb85e8bb2005-02-16 08:54:33 +00001392 case Pin_Sh32:
1393 addHRegUse(u, HRmWrite, i->Pin.Sh32.dst);
1394 addHRegUse(u, HRmRead, i->Pin.Sh32.src);
1395 addRegUsage_PPC32RI(u, i->Pin.Sh32.shft);
cerionb85e8bb2005-02-16 08:54:33 +00001396 return;
1397
cerionb85e8bb2005-02-16 08:54:33 +00001398 case Pin_Cmp32:
ceriona2f75882005-03-15 16:33:38 +00001399 addHRegUse(u, HRmRead, i->Pin.Cmp32.srcL);
1400 addRegUsage_PPC32RI(u, i->Pin.Cmp32.srcR);
cerionb85e8bb2005-02-16 08:54:33 +00001401 return;
cerionab9132d2005-02-15 15:46:59 +00001402
cerionb85e8bb2005-02-16 08:54:33 +00001403 case Pin_Unary32:
1404 addHRegUse(u, HRmWrite, i->Pin.Unary32.dst);
1405 addHRegUse(u, HRmRead, i->Pin.Unary32.src);
1406 return;
1407 case Pin_MulL:
1408 addHRegUse(u, HRmWrite, i->Pin.MulL.dst);
ceriona2f75882005-03-15 16:33:38 +00001409 addHRegUse(u, HRmRead, i->Pin.MulL.srcL);
1410 addRegUsage_PPC32RI(u, i->Pin.MulL.srcR);
cerionb85e8bb2005-02-16 08:54:33 +00001411 return;
1412 case Pin_Div:
1413 addHRegUse(u, HRmWrite, i->Pin.Div.dst);
ceriona2f75882005-03-15 16:33:38 +00001414 addHRegUse(u, HRmRead, i->Pin.Div.srcL);
1415 addHRegUse(u, HRmRead, i->Pin.Div.srcR);
cerionb85e8bb2005-02-16 08:54:33 +00001416 return;
cerionb85e8bb2005-02-16 08:54:33 +00001417 case Pin_Call:
1418 /* This is a bit subtle. */
1419 /* First off, claim it trashes all the caller-saved regs
1420 which fall within the register allocator's jurisdiction.
ceriona56e9cc2005-02-16 18:08:25 +00001421 These I believe to be: r3:12
cerionb85e8bb2005-02-16 08:54:33 +00001422 */
cerionb85e8bb2005-02-16 08:54:33 +00001423 addHRegUse(u, HRmWrite, hregPPC32_GPR3());
1424 addHRegUse(u, HRmWrite, hregPPC32_GPR4());
1425 addHRegUse(u, HRmWrite, hregPPC32_GPR5());
1426 addHRegUse(u, HRmWrite, hregPPC32_GPR6());
1427 addHRegUse(u, HRmWrite, hregPPC32_GPR7());
1428 addHRegUse(u, HRmWrite, hregPPC32_GPR8());
1429 addHRegUse(u, HRmWrite, hregPPC32_GPR9());
1430 addHRegUse(u, HRmWrite, hregPPC32_GPR10());
1431 addHRegUse(u, HRmWrite, hregPPC32_GPR11());
1432 addHRegUse(u, HRmWrite, hregPPC32_GPR12());
1433
1434 /* Now we have to state any parameter-carrying registers
1435 which might be read. This depends on the regparmness. */
1436 switch (i->Pin.Call.regparms) {
1437 case 8: addHRegUse(u, HRmRead, hregPPC32_GPR10()); /*fallthru*/
1438 case 7: addHRegUse(u, HRmRead, hregPPC32_GPR9() ); /*fallthru*/
1439 case 6: addHRegUse(u, HRmRead, hregPPC32_GPR8() ); /*fallthru*/
1440 case 5: addHRegUse(u, HRmRead, hregPPC32_GPR7() ); /*fallthru*/
1441 case 4: addHRegUse(u, HRmRead, hregPPC32_GPR6() ); /*fallthru*/
1442 case 3: addHRegUse(u, HRmRead, hregPPC32_GPR5() ); /*fallthru*/
1443 case 2: addHRegUse(u, HRmRead, hregPPC32_GPR4() ); /*fallthru*/
1444 case 1: addHRegUse(u, HRmRead, hregPPC32_GPR3() ); /*fallthru*/
1445 case 0: break;
1446 default: vpanic("getRegUsage_PPC32Instr:Call:regparms");
1447 }
1448 /* Finally, there is the issue that the insn trashes a
1449 register because the literal target address has to be
ceriona56e9cc2005-02-16 18:08:25 +00001450 loaded into a register. %r12 seems a suitable victim.
1451 (Can't use %r0, as use ops that interpret it as value zero). */
cerionb85e8bb2005-02-16 08:54:33 +00001452 addHRegUse(u, HRmWrite, hregPPC32_GPR12());
1453 /* Upshot of this is that the assembler really must use %r12,
ceriona56e9cc2005-02-16 18:08:25 +00001454 and no other, as a destination temporary. */
cerionb85e8bb2005-02-16 08:54:33 +00001455 return;
1456 case Pin_Goto:
1457 addRegUsage_PPC32RI(u, i->Pin.Goto.dst);
ceriona56e9cc2005-02-16 18:08:25 +00001458 /* GPR3 holds destination address from Pin_Goto */
1459 addHRegUse(u, HRmWrite, hregPPC32_GPR3());
cerionb85e8bb2005-02-16 08:54:33 +00001460 if (i->Pin.Goto.jk != Ijk_Boring)
1461 addHRegUse(u, HRmWrite, GuestStatePtr);
1462 return;
1463 case Pin_CMov32:
1464 addRegUsage_PPC32RI(u, i->Pin.CMov32.src);
cerioned623db2005-06-20 12:42:04 +00001465 addHRegUse(u, HRmWrite, i->Pin.CMov32.dst);
cerionb85e8bb2005-02-16 08:54:33 +00001466 return;
cerion7cf8e4e2005-02-16 16:08:17 +00001467 case Pin_Load:
1468 addRegUsage_PPC32AMode(u, i->Pin.Load.src);
1469 addHRegUse(u, HRmWrite, i->Pin.Load.dst);
cerionb85e8bb2005-02-16 08:54:33 +00001470 return;
1471 case Pin_Store:
1472 addHRegUse(u, HRmRead, i->Pin.Store.src);
1473 addRegUsage_PPC32AMode(u, i->Pin.Store.dst);
1474 return;
1475 case Pin_Set32:
1476 addHRegUse(u, HRmWrite, i->Pin.Set32.dst);
1477 return;
cerionb85e8bb2005-02-16 08:54:33 +00001478 case Pin_MFence:
1479 return;
cerion094d1392005-06-20 13:45:57 +00001480
1481 case Pin_FpUnary:
1482 addHRegUse(u, HRmWrite, i->Pin.FpUnary.dst);
1483 addHRegUse(u, HRmRead, i->Pin.FpUnary.src);
1484 return;
1485 case Pin_FpBinary:
1486 addHRegUse(u, HRmWrite, i->Pin.FpBinary.dst);
1487 addHRegUse(u, HRmRead, i->Pin.FpBinary.srcL);
1488 addHRegUse(u, HRmRead, i->Pin.FpBinary.srcR);
1489 return;
1490 case Pin_FpLdSt:
1491 addHRegUse(u, (i->Pin.FpLdSt.isLoad ? HRmWrite : HRmRead),
1492 i->Pin.FpLdSt.reg);
1493 addRegUsage_PPC32AMode(u, i->Pin.FpLdSt.addr);
1494 return;
1495 case Pin_FpF64toF32:
1496 addHRegUse(u, HRmWrite, i->Pin.FpF64toF32.dst);
1497 addHRegUse(u, HRmRead, i->Pin.FpF64toF32.src);
1498 return;
1499 case Pin_FpF64toI32:
1500 addHRegUse(u, HRmWrite, i->Pin.FpF64toI32.dst);
1501 addHRegUse(u, HRmWrite, hregPPC32_FPR7());
1502 addHRegUse(u, HRmRead, i->Pin.FpF64toI32.src);
1503 return;
1504 case Pin_FpCMov:
1505 addHRegUse(u, HRmModify, i->Pin.FpCMov.dst);
1506 addHRegUse(u, HRmRead, i->Pin.FpCMov.src);
1507 return;
1508 case Pin_FpLdFPSCR:
1509 addHRegUse(u, HRmRead, i->Pin.FpLdFPSCR.src);
1510 return;
1511 case Pin_FpCmp:
1512 addHRegUse(u, HRmWrite, i->Pin.FpCmp.dst);
1513 addHRegUse(u, HRmRead, i->Pin.FpCmp.srcL);
1514 addHRegUse(u, HRmRead, i->Pin.FpCmp.srcR);
1515 return;
cerion7f000af2005-02-22 20:36:49 +00001516
1517 case Pin_RdWrLR:
1518 addHRegUse(u, (i->Pin.RdWrLR.wrLR ? HRmRead : HRmWrite),
1519 i->Pin.RdWrLR.gpr);
1520 return;
1521
cerionc3d8bdc2005-06-28 18:06:23 +00001522 case Pin_AvLdSt:
1523 addHRegUse(u, (i->Pin.AvLdSt.isLoad ? HRmWrite : HRmRead),
1524 i->Pin.AvLdSt.reg);
1525 if (i->Pin.AvLdSt.addr->tag == Pam_IR)
1526 addHRegUse(u, HRmWrite, hregPPC32_GPR30());
1527 addRegUsage_PPC32AMode(u, i->Pin.AvLdSt.addr);
1528 return;
1529 case Pin_AvUnary:
1530 addHRegUse(u, HRmWrite, i->Pin.AvUnary.dst);
1531 addHRegUse(u, HRmRead, i->Pin.AvUnary.src);
1532 return;
1533 case Pin_AvBinary:
1534 addHRegUse(u, HRmWrite, i->Pin.AvBinary.dst);
1535 addHRegUse(u, HRmRead, i->Pin.AvBinary.srcL);
1536 addHRegUse(u, HRmRead, i->Pin.AvBinary.srcR);
1537 return;
cerion6b6f59e2005-06-28 20:59:18 +00001538 case Pin_AvBin8x16:
1539 addHRegUse(u, HRmWrite, i->Pin.AvBin8x16.dst);
1540 addHRegUse(u, HRmRead, i->Pin.AvBin8x16.srcL);
1541 addHRegUse(u, HRmRead, i->Pin.AvBin8x16.srcR);
1542 return;
1543 case Pin_AvBin16x8:
1544 addHRegUse(u, HRmWrite, i->Pin.AvBin16x8.dst);
1545 addHRegUse(u, HRmRead, i->Pin.AvBin16x8.srcL);
1546 addHRegUse(u, HRmRead, i->Pin.AvBin16x8.srcR);
1547 return;
1548 case Pin_AvBin32x4:
1549 addHRegUse(u, HRmWrite, i->Pin.AvBin32x4.dst);
1550 addHRegUse(u, HRmRead, i->Pin.AvBin32x4.srcL);
1551 addHRegUse(u, HRmRead, i->Pin.AvBin32x4.srcR);
1552 if (i->Pin.AvBin32x4.op == Pav_MULF)
1553 addHRegUse(u, HRmWrite, hregPPC32_GPR29());
1554 return;
1555 case Pin_AvBin32Fx4:
1556 addHRegUse(u, HRmWrite, i->Pin.AvBin32Fx4.dst);
1557 addHRegUse(u, HRmRead, i->Pin.AvBin32Fx4.srcL);
1558 addHRegUse(u, HRmRead, i->Pin.AvBin32Fx4.srcR);
1559 return;
cerionc3d8bdc2005-06-28 18:06:23 +00001560 case Pin_AvPerm:
1561 addHRegUse(u, HRmWrite, i->Pin.AvPerm.dst);
1562 addHRegUse(u, HRmRead, i->Pin.AvPerm.ctl);
1563 addHRegUse(u, HRmRead, i->Pin.AvPerm.srcL);
1564 addHRegUse(u, HRmRead, i->Pin.AvPerm.srcR);
1565 return;
1566 case Pin_AvSel:
1567 addHRegUse(u, HRmWrite, i->Pin.AvSel.dst);
1568 addHRegUse(u, HRmRead, i->Pin.AvSel.ctl);
1569 addHRegUse(u, HRmRead, i->Pin.AvSel.srcL);
1570 addHRegUse(u, HRmRead, i->Pin.AvSel.srcR);
1571 return;
1572 case Pin_AvShlDbl:
1573 addHRegUse(u, HRmWrite, i->Pin.AvShlDbl.dst);
1574 addHRegUse(u, HRmRead, i->Pin.AvShlDbl.srcL);
1575 addHRegUse(u, HRmRead, i->Pin.AvShlDbl.srcR);
1576 return;
1577 case Pin_AvSplat:
1578 addHRegUse(u, HRmWrite, i->Pin.AvSplat.dst);
1579 addRegUsage_PPC32RI(u, i->Pin.AvSplat.src);
1580 return;
cerion6b6f59e2005-06-28 20:59:18 +00001581 case Pin_AvCMov:
1582 addHRegUse(u, HRmModify, i->Pin.AvCMov.dst);
1583 addHRegUse(u, HRmRead, i->Pin.AvCMov.src);
1584 return;
cerionc3d8bdc2005-06-28 18:06:23 +00001585 case Pin_AvLdVSCR:
1586 addHRegUse(u, HRmRead, i->Pin.AvLdVSCR.src);
1587 return;
1588
cerionb85e8bb2005-02-16 08:54:33 +00001589 default:
1590 ppPPC32Instr(i);
1591 vpanic("getRegUsage_PPC32Instr");
cerionbcf8c3e2005-02-04 16:17:07 +00001592 }
1593}
1594
cerioncd304492005-02-08 19:40:24 +00001595/* local helper */
1596static void mapReg(HRegRemap* m, HReg* r)
1597{
1598 *r = lookupHRegRemap(m, *r);
1599}
cerionbcf8c3e2005-02-04 16:17:07 +00001600
1601void mapRegs_PPC32Instr (HRegRemap* m, PPC32Instr* i)
1602{
1603 switch (i->tag) {
cerionb85e8bb2005-02-16 08:54:33 +00001604 case Pin_Alu32:
1605 mapReg(m, &i->Pin.Alu32.dst);
ceriona2f75882005-03-15 16:33:38 +00001606 mapReg(m, &i->Pin.Alu32.srcL);
1607 mapRegs_PPC32RI(m, i->Pin.Alu32.srcR);
cerionb85e8bb2005-02-16 08:54:33 +00001608 return;
cerion5e2527e2005-02-25 16:39:58 +00001609 case Pin_Sub32:
1610 mapReg(m, &i->Pin.Sub32.dst);
ceriona2f75882005-03-15 16:33:38 +00001611 mapRegs_PPC32RI(m, i->Pin.Sub32.srcL);
1612 mapReg(m, &i->Pin.Sub32.srcR);
cerion5e2527e2005-02-25 16:39:58 +00001613 return;
cerionb85e8bb2005-02-16 08:54:33 +00001614 case Pin_Sh32:
1615 mapReg(m, &i->Pin.Sh32.dst);
1616 mapReg(m, &i->Pin.Sh32.src);
1617 mapRegs_PPC32RI(m, i->Pin.Sh32.shft);
1618 return;
cerionb85e8bb2005-02-16 08:54:33 +00001619 case Pin_Cmp32:
ceriona2f75882005-03-15 16:33:38 +00001620 mapReg(m, &i->Pin.Cmp32.srcL);
1621 mapRegs_PPC32RI(m, i->Pin.Cmp32.srcR);
cerionb85e8bb2005-02-16 08:54:33 +00001622 return;
1623 case Pin_Unary32:
1624 mapReg(m, &i->Pin.Unary32.dst);
1625 mapReg(m, &i->Pin.Unary32.src);
1626 return;
1627 case Pin_MulL:
1628 mapReg(m, &i->Pin.MulL.dst);
ceriona2f75882005-03-15 16:33:38 +00001629 mapReg(m, &i->Pin.MulL.srcL);
1630 mapRegs_PPC32RI(m, i->Pin.MulL.srcR);
cerionb85e8bb2005-02-16 08:54:33 +00001631 return;
1632 case Pin_Div:
1633 mapReg(m, &i->Pin.Div.dst);
ceriona2f75882005-03-15 16:33:38 +00001634 mapReg(m, &i->Pin.Div.srcL);
1635 mapReg(m, &i->Pin.Div.srcR);
cerionb85e8bb2005-02-16 08:54:33 +00001636 return;
cerionb85e8bb2005-02-16 08:54:33 +00001637 case Pin_Call:
1638 return;
1639 case Pin_Goto:
1640 mapRegs_PPC32RI(m, i->Pin.Goto.dst);
1641 return;
1642 case Pin_CMov32:
1643 mapRegs_PPC32RI(m, i->Pin.CMov32.src);
1644 mapReg(m, &i->Pin.CMov32.dst);
1645 return;
cerion7cf8e4e2005-02-16 16:08:17 +00001646 case Pin_Load:
1647 mapRegs_PPC32AMode(m, i->Pin.Load.src);
1648 mapReg(m, &i->Pin.Load.dst);
cerionb85e8bb2005-02-16 08:54:33 +00001649 return;
1650 case Pin_Store:
1651 mapReg(m, &i->Pin.Store.src);
1652 mapRegs_PPC32AMode(m, i->Pin.Store.dst);
1653 return;
1654 case Pin_Set32:
1655 mapReg(m, &i->Pin.Set32.dst);
1656 return;
cerionb85e8bb2005-02-16 08:54:33 +00001657 case Pin_MFence:
1658 return;
cerion094d1392005-06-20 13:45:57 +00001659
1660 case Pin_FpUnary:
1661 mapReg(m, &i->Pin.FpUnary.dst);
1662 mapReg(m, &i->Pin.FpUnary.src);
1663 return;
1664 case Pin_FpBinary:
1665 mapReg(m, &i->Pin.FpBinary.dst);
1666 mapReg(m, &i->Pin.FpBinary.srcL);
1667 mapReg(m, &i->Pin.FpBinary.srcR);
1668 return;
1669 case Pin_FpLdSt:
1670 mapReg(m, &i->Pin.FpLdSt.reg);
1671 mapRegs_PPC32AMode(m, i->Pin.FpLdSt.addr);
1672 return;
1673 case Pin_FpF64toF32:
1674 mapReg(m, &i->Pin.FpF64toF32.dst);
1675 mapReg(m, &i->Pin.FpF64toF32.src);
1676 return;
1677 case Pin_FpF64toI32:
1678 mapReg(m, &i->Pin.FpF64toI32.dst);
1679 mapReg(m, &i->Pin.FpF64toI32.src);
1680 return;
1681 case Pin_FpCMov:
1682 mapReg(m, &i->Pin.FpCMov.dst);
1683 mapReg(m, &i->Pin.FpCMov.src);
1684 return;
1685 case Pin_FpLdFPSCR:
1686 mapReg(m, &i->Pin.FpLdFPSCR.src);
1687 return;
1688 case Pin_FpCmp:
1689 mapReg(m, &i->Pin.FpCmp.dst);
1690 mapReg(m, &i->Pin.FpCmp.srcL);
1691 mapReg(m, &i->Pin.FpCmp.srcR);
1692 return;
cerion7f000af2005-02-22 20:36:49 +00001693
1694 case Pin_RdWrLR:
1695 mapReg(m, &i->Pin.RdWrLR.gpr);
1696 return;
1697
cerionc3d8bdc2005-06-28 18:06:23 +00001698 case Pin_AvLdSt:
1699 mapReg(m, &i->Pin.AvLdSt.reg);
1700 mapRegs_PPC32AMode(m, i->Pin.AvLdSt.addr);
1701 return;
1702 case Pin_AvUnary:
1703 mapReg(m, &i->Pin.AvUnary.dst);
1704 mapReg(m, &i->Pin.AvUnary.src);
1705 return;
1706 case Pin_AvBinary:
1707 mapReg(m, &i->Pin.AvBinary.dst);
1708 mapReg(m, &i->Pin.AvBinary.srcL);
1709 mapReg(m, &i->Pin.AvBinary.srcR);
1710 return;
cerion6b6f59e2005-06-28 20:59:18 +00001711 case Pin_AvBin8x16:
1712 mapReg(m, &i->Pin.AvBin8x16.dst);
1713 mapReg(m, &i->Pin.AvBin8x16.srcL);
1714 mapReg(m, &i->Pin.AvBin8x16.srcR);
1715 return;
1716 case Pin_AvBin16x8:
1717 mapReg(m, &i->Pin.AvBin16x8.dst);
1718 mapReg(m, &i->Pin.AvBin16x8.srcL);
1719 mapReg(m, &i->Pin.AvBin16x8.srcR);
1720 return;
1721 case Pin_AvBin32x4:
1722 mapReg(m, &i->Pin.AvBin32x4.dst);
1723 mapReg(m, &i->Pin.AvBin32x4.srcL);
1724 mapReg(m, &i->Pin.AvBin32x4.srcR);
1725 return;
1726 case Pin_AvBin32Fx4:
1727 mapReg(m, &i->Pin.AvBin32Fx4.dst);
1728 mapReg(m, &i->Pin.AvBin32Fx4.srcL);
1729 mapReg(m, &i->Pin.AvBin32Fx4.srcR);
1730 return;
cerionc3d8bdc2005-06-28 18:06:23 +00001731 case Pin_AvPerm:
1732 mapReg(m, &i->Pin.AvPerm.dst);
1733 mapReg(m, &i->Pin.AvPerm.srcL);
1734 mapReg(m, &i->Pin.AvPerm.srcR);
1735 mapReg(m, &i->Pin.AvPerm.ctl);
1736 return;
1737 case Pin_AvSel:
1738 mapReg(m, &i->Pin.AvSel.dst);
1739 mapReg(m, &i->Pin.AvSel.srcL);
1740 mapReg(m, &i->Pin.AvSel.srcR);
1741 mapReg(m, &i->Pin.AvSel.ctl);
1742 return;
1743 case Pin_AvShlDbl:
1744 mapReg(m, &i->Pin.AvShlDbl.dst);
1745 mapReg(m, &i->Pin.AvShlDbl.srcL);
1746 mapReg(m, &i->Pin.AvShlDbl.srcR);
1747 return;
1748 case Pin_AvSplat:
1749 mapReg(m, &i->Pin.AvSplat.dst);
1750 mapRegs_PPC32RI(m, i->Pin.AvSplat.src);
1751 return;
cerion6b6f59e2005-06-28 20:59:18 +00001752 case Pin_AvCMov:
1753 mapReg(m, &i->Pin.AvCMov.dst);
1754 mapReg(m, &i->Pin.AvCMov.src);
1755 return;
cerionc3d8bdc2005-06-28 18:06:23 +00001756 case Pin_AvLdVSCR:
1757 mapReg(m, &i->Pin.AvLdVSCR.src);
1758 return;
1759
cerionb85e8bb2005-02-16 08:54:33 +00001760 default:
1761 ppPPC32Instr(i);
1762 vpanic("mapRegs_PPC32Instr");
cerionbcf8c3e2005-02-04 16:17:07 +00001763 }
1764}
1765
1766/* Figure out if i represents a reg-reg move, and if so assign the
1767 source and destination to *src and *dst. If in doubt say No. Used
1768 by the register allocator to do move coalescing.
1769*/
1770Bool isMove_PPC32Instr ( PPC32Instr* i, HReg* src, HReg* dst )
1771{
cerionab9132d2005-02-15 15:46:59 +00001772 /* Moves between integer regs */
1773 if (i->tag == Pin_Alu32) {
1774 // or Rd,Rs,Rs == mr Rd,Rs
1775 if (i->Pin.Alu32.op != Palu_OR)
1776 return False;
ceriona2f75882005-03-15 16:33:38 +00001777 if (i->Pin.Alu32.srcR->tag != Pri_Reg)
cerionab9132d2005-02-15 15:46:59 +00001778 return False;
ceriona2f75882005-03-15 16:33:38 +00001779 if (i->Pin.Alu32.srcR->Pri.Reg.reg != i->Pin.Alu32.srcL)
cerionb85e8bb2005-02-16 08:54:33 +00001780 return False;
ceriona2f75882005-03-15 16:33:38 +00001781 *src = i->Pin.Alu32.srcL;
cerionab9132d2005-02-15 15:46:59 +00001782 *dst = i->Pin.Alu32.dst;
1783 return True;
1784 }
cerion094d1392005-06-20 13:45:57 +00001785 /* Moves between FP regs */
1786 if (i->tag == Pin_FpUnary) {
1787 if (i->Pin.FpUnary.op != Pfp_MOV)
1788 return False;
1789 *src = i->Pin.FpUnary.src;
1790 *dst = i->Pin.FpUnary.dst;
1791 return True;
1792 }
cerionbcf8c3e2005-02-04 16:17:07 +00001793 return False;
1794}
1795
1796
cerione13bb312005-02-10 19:51:03 +00001797/* Generate ppc32 spill/reload instructions under the direction of the
cerionbcf8c3e2005-02-04 16:17:07 +00001798 register allocator. Note it's critical these don't write the
1799 condition codes. */
cerionc3d8bdc2005-06-28 18:06:23 +00001800PPC32Instr* genSpill_PPC32 ( HReg rreg, UShort offsetB )
cerione13bb312005-02-10 19:51:03 +00001801{
1802 PPC32AMode* am;
cerione13bb312005-02-10 19:51:03 +00001803 vassert(!hregIsVirtual(rreg));
1804 am = PPC32AMode_IR(offsetB, GuestStatePtr);
cerionb85e8bb2005-02-16 08:54:33 +00001805
cerione13bb312005-02-10 19:51:03 +00001806 switch (hregClass(rreg)) {
cerionb85e8bb2005-02-16 08:54:33 +00001807 case HRcInt32:
1808 return PPC32Instr_Store( 4, am, rreg);
cerion094d1392005-06-20 13:45:57 +00001809 case HRcFlt64:
1810 return PPC32Instr_FpLdSt ( False/*store*/, 8, rreg, am );
cerionc3d8bdc2005-06-28 18:06:23 +00001811 case HRcVec128:
1812 // XXX: GPR30 used as spill register to kludge AltiVec AMode_IR
1813 return PPC32Instr_AvLdSt ( False/*store*/, 16, rreg, am );
cerionb85e8bb2005-02-16 08:54:33 +00001814 default:
1815 ppHRegClass(hregClass(rreg));
1816 vpanic("genSpill_PPC32: unimplemented regclass");
cerione13bb312005-02-10 19:51:03 +00001817 }
cerionbcf8c3e2005-02-04 16:17:07 +00001818}
1819
cerionc3d8bdc2005-06-28 18:06:23 +00001820PPC32Instr* genReload_PPC32 ( HReg rreg, UShort offsetB )
cerione13bb312005-02-10 19:51:03 +00001821{
1822 PPC32AMode* am;
cerione13bb312005-02-10 19:51:03 +00001823 vassert(!hregIsVirtual(rreg));
1824 am = PPC32AMode_IR(offsetB, GuestStatePtr);
1825
1826 switch (hregClass(rreg)) {
cerionb85e8bb2005-02-16 08:54:33 +00001827 case HRcInt32:
cerion7cf8e4e2005-02-16 16:08:17 +00001828 return PPC32Instr_Load( 4, False, rreg, am );
cerion094d1392005-06-20 13:45:57 +00001829 case HRcFlt64:
1830 return PPC32Instr_FpLdSt ( True/*load*/, 8, rreg, am );
cerionc3d8bdc2005-06-28 18:06:23 +00001831 case HRcVec128:
1832 // XXX: GPR30 used as spill register to kludge AltiVec AMode_IR
1833 return PPC32Instr_AvLdSt ( True/*load*/, 16, rreg, am );
cerionb85e8bb2005-02-16 08:54:33 +00001834 default:
1835 ppHRegClass(hregClass(rreg));
1836 vpanic("genReload_PPC32: unimplemented regclass");
cerione13bb312005-02-10 19:51:03 +00001837 }
cerionbcf8c3e2005-02-04 16:17:07 +00001838}
1839
1840
ceriond5e38382005-02-11 13:38:15 +00001841/* --------- The ppc32 assembler (bleh.) --------- */
cerioncd304492005-02-08 19:40:24 +00001842
cerioncd304492005-02-08 19:40:24 +00001843static UInt iregNo ( HReg r )
1844{
1845 UInt n;
1846 vassert(hregClass(r) == HRcInt32);
1847 vassert(!hregIsVirtual(r));
1848 n = hregNumber(r);
1849 vassert(n <= 32);
1850 return n;
1851}
cerioncd304492005-02-08 19:40:24 +00001852
cerion094d1392005-06-20 13:45:57 +00001853static UInt fregNo ( HReg fr )
1854{
1855 UInt n;
1856 vassert(hregClass(fr) == HRcFlt64);
1857 vassert(!hregIsVirtual(fr));
1858 n = hregNumber(fr);
1859 vassert(n <= 32);
1860 return n;
1861}
cerioncd304492005-02-08 19:40:24 +00001862
cerionc3d8bdc2005-06-28 18:06:23 +00001863static UInt vregNo ( HReg v )
1864{
1865 UInt n;
1866 vassert(hregClass(v) == HRcVec128);
1867 vassert(!hregIsVirtual(v));
1868 n = hregNumber(v);
1869 vassert(n <= 32);
1870 return n;
1871}
1872
cerionab9132d2005-02-15 15:46:59 +00001873/* Emit 32bit instruction big-endianly */
ceriond5e38382005-02-11 13:38:15 +00001874static UChar* emit32 ( UChar* p, UInt w32 )
1875{
sewardj428fabd2005-03-21 03:11:17 +00001876 *p++ = toUChar((w32 >> 24) & 0x000000FF);
1877 *p++ = toUChar((w32 >> 16) & 0x000000FF);
1878 *p++ = toUChar((w32 >> 8) & 0x000000FF);
1879 *p++ = toUChar((w32) & 0x000000FF);
ceriond5e38382005-02-11 13:38:15 +00001880 return p;
1881}
cerioncd304492005-02-08 19:40:24 +00001882
cerion094d1392005-06-20 13:45:57 +00001883/* The following mkForm[...] functions refer to PPC32 instruction forms
1884 as per PPC32 p576
1885 */
cerioned623db2005-06-20 12:42:04 +00001886
ceriona2f75882005-03-15 16:33:38 +00001887static UChar* mkFormD ( UChar* p, UInt opc1, UInt r1, UInt r2, UInt imm )
ceriond5e38382005-02-11 13:38:15 +00001888{
sewardj9a036bf2005-03-14 18:19:08 +00001889 UInt theInstr;
ceriona2f75882005-03-15 16:33:38 +00001890 vassert(opc1 < 0x40);
ceriond5e38382005-02-11 13:38:15 +00001891 vassert(r1 < 0x20);
1892 vassert(r2 < 0x20);
cerion35663a72005-03-01 09:11:49 +00001893 vassert(imm < 0x10000 || imm >= 0xFFFF8000); // Pos|Neg
1894 imm = imm & 0xFFFF;
ceriona2f75882005-03-15 16:33:38 +00001895 theInstr = ((opc1<<26) | (r1<<21) | (r2<<16) | (imm));
ceriond5e38382005-02-11 13:38:15 +00001896 return emit32(p, theInstr);
1897}
1898
ceriona2f75882005-03-15 16:33:38 +00001899static UChar* mkFormX ( UChar* p, UInt opc1, UInt r1, UInt r2,
1900 UInt r3, UInt opc2, UInt b0 )
ceriond5e38382005-02-11 13:38:15 +00001901{
sewardj9a036bf2005-03-14 18:19:08 +00001902 UInt theInstr;
ceriona2f75882005-03-15 16:33:38 +00001903 vassert(opc1 < 0x40);
ceriond5e38382005-02-11 13:38:15 +00001904 vassert(r1 < 0x20);
1905 vassert(r2 < 0x20);
1906 vassert(r3 < 0x20);
ceriona2f75882005-03-15 16:33:38 +00001907 vassert(opc2 < 0x400);
ceriond5e38382005-02-11 13:38:15 +00001908 vassert(b0 < 0x2);
ceriona2f75882005-03-15 16:33:38 +00001909 theInstr = ((opc1<<26) | (r1<<21) | (r2<<16) | (r3<<11) | (opc2<<1) | (b0));
ceriond5e38382005-02-11 13:38:15 +00001910 return emit32(p, theInstr);
1911}
1912
ceriona2f75882005-03-15 16:33:38 +00001913static UChar* mkFormXO ( UChar* p, UInt opc1, UInt r1, UInt r2,
1914 UInt r3, UInt b10, UInt opc2, UInt b0 )
cerionab9132d2005-02-15 15:46:59 +00001915{
sewardj9a036bf2005-03-14 18:19:08 +00001916 UInt theInstr;
ceriona2f75882005-03-15 16:33:38 +00001917 vassert(opc1 < 0x40);
cerionab9132d2005-02-15 15:46:59 +00001918 vassert(r1 < 0x20);
1919 vassert(r2 < 0x20);
1920 vassert(r3 < 0x20);
1921 vassert(b10 < 0x2);
ceriona2f75882005-03-15 16:33:38 +00001922 vassert(opc2 < 0x200);
cerionab9132d2005-02-15 15:46:59 +00001923 vassert(b0 < 0x2);
ceriona2f75882005-03-15 16:33:38 +00001924 theInstr = ((opc1<<26) | (r1<<21) | (r2<<16) |
1925 (r3<<11) | (b10 << 10) | (opc2<<1) | (b0));
cerionab9132d2005-02-15 15:46:59 +00001926 return emit32(p, theInstr);
1927}
ceriond5e38382005-02-11 13:38:15 +00001928
ceriona2f75882005-03-15 16:33:38 +00001929static UChar* mkFormXL ( UChar* p, UInt opc1, UInt f1, UInt f2,
1930 UInt f3, UInt opc2, UInt b0 )
cerion33aa6da2005-02-16 10:25:26 +00001931{
sewardj9a036bf2005-03-14 18:19:08 +00001932 UInt theInstr;
ceriona2f75882005-03-15 16:33:38 +00001933 vassert(opc1 < 0x40);
cerion33aa6da2005-02-16 10:25:26 +00001934 vassert(f1 < 0x20);
1935 vassert(f2 < 0x20);
1936 vassert(f3 < 0x20);
ceriona2f75882005-03-15 16:33:38 +00001937 vassert(opc2 < 0x400);
cerion33aa6da2005-02-16 10:25:26 +00001938 vassert(b0 < 0x2);
ceriona2f75882005-03-15 16:33:38 +00001939 theInstr = ((opc1<<26) | (f1<<21) | (f2<<16) | (f3<<11) | (opc2<<1) | (b0));
cerion33aa6da2005-02-16 10:25:26 +00001940 return emit32(p, theInstr);
1941}
1942
1943// Note: for split field ops, give mnemonic arg
ceriona2f75882005-03-15 16:33:38 +00001944static UChar* mkFormXFX ( UChar* p, UInt r1, UInt f2, UInt opc2 )
cerion33aa6da2005-02-16 10:25:26 +00001945{
sewardj9a036bf2005-03-14 18:19:08 +00001946 UInt theInstr;
cerion33aa6da2005-02-16 10:25:26 +00001947 vassert(r1 < 0x20);
1948 vassert(f2 < 0x20);
ceriona2f75882005-03-15 16:33:38 +00001949 vassert(opc2 < 0x400);
1950 switch (opc2) {
cerion33aa6da2005-02-16 10:25:26 +00001951 case 144: // mtcrf
1952 vassert(f2 < 0x100);
1953 f2 = f2 << 1;
1954 break;
1955 case 339: // mfspr
1956 case 371: // mftb
1957 case 467: // mtspr
1958 vassert(f2 < 0x400);
1959 f2 = ((f2>>5) & 0x1F) | ((f2 & 0x1F)<<5); // re-arrange split field
1960 break;
1961 default: vpanic("mkFormXFX(PPC32)");
1962 }
ceriona2f75882005-03-15 16:33:38 +00001963 theInstr = ((31<<26) | (r1<<21) | (f2<<11) | (opc2<<1));
cerion33aa6da2005-02-16 10:25:26 +00001964 return emit32(p, theInstr);
1965}
1966
cerion094d1392005-06-20 13:45:57 +00001967// Only used by mtfsf
1968static UChar* mkFormXFL ( UChar* p, UInt FM, UInt freg )
1969{
1970 UInt theInstr;
1971 vassert(FM < 0x100);
1972 vassert(freg < 0x20);
1973 theInstr = ((63<<26) | (FM<<17) | (freg<<11) | (711<<1));
1974 return emit32(p, theInstr);
1975}
1976
cerion33aa6da2005-02-16 10:25:26 +00001977#if 0
1978// 'b'
1979static UChar* mkFormI ( UChar* p, UInt LI, UInt AA, UInt LK )
1980{
sewardj9a036bf2005-03-14 18:19:08 +00001981 UInt theInstr;
cerion33aa6da2005-02-16 10:25:26 +00001982 vassert(LI < 0x1000000);
1983 vassert(AA < 0x2);
1984 vassert(LK < 0x2);
sewardj9a036bf2005-03-14 18:19:08 +00001985 theInstr = ((18<<26) | (LI<<2) | (AA<<1) | (LK));
cerion33aa6da2005-02-16 10:25:26 +00001986 return emit32(p, theInstr);
1987}
1988#endif
1989
1990// 'bc'
1991static UChar* mkFormB ( UChar* p, UInt BO, UInt BI,
1992 UInt BD, UInt AA, UInt LK )
1993{
sewardj9a036bf2005-03-14 18:19:08 +00001994 UInt theInstr;
cerion33aa6da2005-02-16 10:25:26 +00001995 vassert(BO < 0x20);
1996 vassert(BI < 0x20);
1997 vassert(BD < 0x4000);
1998 vassert(AA < 0x2);
1999 vassert(LK < 0x2);
ceriona2f75882005-03-15 16:33:38 +00002000 theInstr = ((16<<26) | (BO<<21) | (BI<<16) | (BD<<2) | (AA<<1) | (LK));
cerion33aa6da2005-02-16 10:25:26 +00002001 return emit32(p, theInstr);
2002}
2003
cerion33aa6da2005-02-16 10:25:26 +00002004// rotates
ceriona2f75882005-03-15 16:33:38 +00002005static UChar* mkFormM ( UChar* p, UInt opc1, UInt r1, UInt r2,
cerion33aa6da2005-02-16 10:25:26 +00002006 UInt f3, UInt MB, UInt ME, UInt Rc )
2007{
sewardj9a036bf2005-03-14 18:19:08 +00002008 UInt theInstr;
ceriona2f75882005-03-15 16:33:38 +00002009 vassert(opc1 < 0x40);
cerion33aa6da2005-02-16 10:25:26 +00002010 vassert(r1 < 0x20);
2011 vassert(r2 < 0x20);
2012 vassert(f3 < 0x20);
2013 vassert(MB < 0x20);
2014 vassert(ME < 0x20);
2015 vassert(Rc < 0x2);
ceriona2f75882005-03-15 16:33:38 +00002016 theInstr = ((opc1<<26) | (r1<<21) | (r2<<16) |
sewardj9a036bf2005-03-14 18:19:08 +00002017 (f3<<11) | (MB<<6) | (ME<<1) | (Rc));
cerion33aa6da2005-02-16 10:25:26 +00002018 return emit32(p, theInstr);
2019}
cerion33aa6da2005-02-16 10:25:26 +00002020
cerion094d1392005-06-20 13:45:57 +00002021static UChar* mkFormA ( UChar* p, UInt opc1, UInt r1, UInt r2,
2022 UInt r3, UInt r4, UInt opc2, UInt b0 )
2023{
2024 UInt theInstr;
2025 vassert(opc1 < 0x40);
2026 vassert(r1 < 0x20);
2027 vassert(r2 < 0x20);
2028 vassert(r3 < 0x20);
2029 vassert(r4 < 0x20);
2030 vassert(opc2 < 0x20);
2031 vassert(b0 < 0x2 );
2032 theInstr = ((opc1<<26) | (r1<<21) | (r2<<16) | (r3<<11) |
2033 (r4<<6) | (opc2<<1) | (b0));
2034 return emit32(p, theInstr);
2035}
2036
cerioned623db2005-06-20 12:42:04 +00002037static UChar* doAMode_IR ( UChar* p, UInt opc1, UInt rSD, PPC32AMode* am )
ceriond5e38382005-02-11 13:38:15 +00002038{
cerioned623db2005-06-20 12:42:04 +00002039 UInt rA, idx;
ceriond5e38382005-02-11 13:38:15 +00002040 vassert(am->tag == Pam_IR);
ceriona2f75882005-03-15 16:33:38 +00002041 vassert(am->Pam.IR.index < 0x10000);
2042
sewardj9a036bf2005-03-14 18:19:08 +00002043 rA = iregNo(am->Pam.IR.base);
2044 idx = am->Pam.IR.index;
ceriona2f75882005-03-15 16:33:38 +00002045
2046 p = mkFormD(p, opc1, rSD, rA, idx);
ceriond5e38382005-02-11 13:38:15 +00002047 return p;
2048}
2049
2050
ceriona2f75882005-03-15 16:33:38 +00002051static UChar* doAMode_RR ( UChar* p, UInt opc1, UInt opc2,
cerioned623db2005-06-20 12:42:04 +00002052 UInt rSD, PPC32AMode* am )
ceriond5e38382005-02-11 13:38:15 +00002053{
cerioned623db2005-06-20 12:42:04 +00002054 UInt rA, rB;
ceriond5e38382005-02-11 13:38:15 +00002055 vassert(am->tag == Pam_RR);
ceriona2f75882005-03-15 16:33:38 +00002056
sewardj9a036bf2005-03-14 18:19:08 +00002057 rA = iregNo(am->Pam.RR.base);
2058 rB = iregNo(am->Pam.RR.index);
ceriona2f75882005-03-15 16:33:38 +00002059
2060 p = mkFormX(p, opc1, rSD, rA, rB, opc2, 0);
ceriond5e38382005-02-11 13:38:15 +00002061 return p;
2062}
2063
cerione97e1062005-02-21 15:09:19 +00002064/* Load imm to r_dst */
2065static UChar* mkLoadImm ( UChar* p, UInt r_dst, UInt imm )
2066{
2067 vassert(r_dst < 0x20);
2068
cerion47c526b2005-03-03 05:17:08 +00002069 if (imm >= 0xFFFF8000 || imm <= 0x7FFF) { // sign-extendable from 16 bits?
cerione97e1062005-02-21 15:09:19 +00002070 // addi r_dst,0,imm => li r_dst,imm
2071 p = mkFormD(p, 14, r_dst, 0, imm);
2072 } else {
2073 // addis r_dst,r0,(imm>>16) => lis r_dst, (imm>>16)
2074 p = mkFormD(p, 15, r_dst, 0, (imm>>16));
2075 // ori r_dst, r_dst, (imm & 0xFFFF)
2076 p = mkFormD(p, 24, r_dst, r_dst, (imm & 0xFFFF));
2077 }
2078 return p;
2079}
2080
cerione97e1062005-02-21 15:09:19 +00002081/* Move r_dst to r_src */
2082static UChar* mkMoveReg ( UChar* p, UInt r_dst, UInt r_src )
2083{
2084 vassert(r_dst < 0x20);
2085 vassert(r_src < 0x20);
2086
2087 if (r_dst != r_src) {
2088 /* or r_dst, r_src, r_src */
2089 p = mkFormX(p, 31, r_src, r_dst, r_src, 444, 0 );
2090 }
2091 return p;
2092}
2093
cerionc3d8bdc2005-06-28 18:06:23 +00002094static UChar* mkFormVX ( UChar* p, UInt opc1, UInt r1, UInt r2,
2095 UInt r3, UInt opc2 )
2096{
2097 UInt theInstr;
2098 vassert(opc1 < 0x40);
2099 vassert(r1 < 0x20);
2100 vassert(r2 < 0x20);
2101 vassert(r3 < 0x20);
2102 vassert(opc2 < 0x800);
cerion6b6f59e2005-06-28 20:59:18 +00002103 theInstr = ((opc1<<26) | (r1<<21) | (r2<<16) | (r3<<11) | opc2);
2104 return emit32(p, theInstr);
2105}
2106
2107static UChar* mkFormVXR ( UChar* p, UInt opc1, UInt r1, UInt r2, UInt Rc,
2108 UInt r3, UInt opc2 )
2109{
2110 UInt theInstr;
2111 vassert(opc1 < 0x40);
2112 vassert(r1 < 0x20);
2113 vassert(r2 < 0x20);
2114 vassert(r3 < 0x20);
2115 vassert(Rc < 0x2);
2116 vassert(opc2 < 0x400);
2117 theInstr = ((opc1<<26) | (r1<<21) | (r2<<16) | (r3<<11) | (Rc<<10) | opc2);
cerionc3d8bdc2005-06-28 18:06:23 +00002118 return emit32(p, theInstr);
2119}
2120
2121static UChar* mkFormVA ( UChar* p, UInt opc1, UInt r1, UInt r2,
2122 UInt r3, UInt r4, UInt opc2 )
2123{
2124 UInt theInstr;
2125 vassert(opc1 < 0x40);
2126 vassert(r1 < 0x20);
2127 vassert(r2 < 0x20);
2128 vassert(r3 < 0x20);
2129 vassert(r4 < 0x20);
2130 vassert(opc2 < 0x40);
2131 theInstr = ((opc1<<26) | (r1<<21) | (r2<<16) | (r3<<11) | (r4<<6) | opc2);
2132 return emit32(p, theInstr);
2133}
2134
2135
ceriond5e38382005-02-11 13:38:15 +00002136
cerionbcf8c3e2005-02-04 16:17:07 +00002137/* Emit an instruction into buf and return the number of bytes used.
2138 Note that buf is not the insn's final place, and therefore it is
2139 imperative to emit position-independent code. */
2140
2141Int emit_PPC32Instr ( UChar* buf, Int nbuf, PPC32Instr* i )
2142{
2143//.. UInt irno, opc, opc_rr, subopc_imm, opc_imma, opc_cl, opc_imm, subopc;
cerioned623db2005-06-20 12:42:04 +00002144
cerionbcf8c3e2005-02-04 16:17:07 +00002145 UChar* p = &buf[0];
cerion7cf8e4e2005-02-16 16:08:17 +00002146 UChar* ptmp = p;
2147 vassert(nbuf >= 32);
cerion2c49e032005-02-09 17:29:49 +00002148
cerion9a934a92005-02-21 16:44:03 +00002149// vex_printf("asm ");ppPPC32Instr(i); vex_printf("\n");
cerionbcf8c3e2005-02-04 16:17:07 +00002150
2151 switch (i->tag) {
2152
cerionab9132d2005-02-15 15:46:59 +00002153 case Pin_Alu32: {
ceriona2f75882005-03-15 16:33:38 +00002154 UInt opc1, opc2, r_srcR, imm_srcR;
2155 UInt r_dst = iregNo(i->Pin.Alu32.dst);
2156 UInt r_srcL = iregNo(i->Pin.Alu32.srcL);
cerion2c49e032005-02-09 17:29:49 +00002157
cerion9e263e32005-03-03 17:21:51 +00002158 /* ADD/AND/OR/XOR */
ceriona2f75882005-03-15 16:33:38 +00002159 if (i->Pin.Alu32.srcR->tag == Pri_Reg) {
2160 opc1 = 31;
2161 r_srcR = iregNo(i->Pin.Alu32.srcR->Pri.Reg.reg);
cerionab9132d2005-02-15 15:46:59 +00002162 switch (i->Pin.Alu32.op) {
ceriona2f75882005-03-15 16:33:38 +00002163 case Palu_ADD: opc2 = 266; break;
2164 case Palu_AND: opc2 = 28; break;
2165 case Palu_XOR: opc2 = 316; break;
2166 case Palu_OR: opc2 = 444; break;
cerionab9132d2005-02-15 15:46:59 +00002167 default:
2168 goto bad;
2169 }
2170
cerion9e263e32005-03-03 17:21:51 +00002171 if (i->Pin.Alu32.op == Palu_ADD) {
ceriona2f75882005-03-15 16:33:38 +00002172 p = mkFormXO(p, opc1, r_dst, r_srcL, r_srcR, 0, opc2, 0);
cerion9e263e32005-03-03 17:21:51 +00002173 } else {
ceriona2f75882005-03-15 16:33:38 +00002174 p = mkFormX(p, opc1, r_srcL, r_dst, r_srcR, opc2, 0);
cerionab9132d2005-02-15 15:46:59 +00002175 }
cerioned623db2005-06-20 12:42:04 +00002176 } else { // tag == Pri_Imm:
ceriona2f75882005-03-15 16:33:38 +00002177 imm_srcR = i->Pin.Alu32.srcR->Pri.Imm.imm32;
cerionab9132d2005-02-15 15:46:59 +00002178 switch (i->Pin.Alu32.op) {
ceriona2f75882005-03-15 16:33:38 +00002179 case Palu_ADD: opc1 = 14; break;
2180 case Palu_AND: opc1 = 28; break;
2181 case Palu_XOR: opc1 = 26; break;
2182 case Palu_OR: opc1 = 24; break;
cerionab9132d2005-02-15 15:46:59 +00002183 default:
2184 goto bad;
2185 }
2186
cerion9e263e32005-03-03 17:21:51 +00002187 if (i->Pin.Alu32.op == Palu_ADD) {
ceriona2f75882005-03-15 16:33:38 +00002188 p = mkFormD(p, opc1, r_dst, r_srcL, imm_srcR);
cerion9e263e32005-03-03 17:21:51 +00002189 } else {
ceriona2f75882005-03-15 16:33:38 +00002190 p = mkFormD(p, opc1, r_srcL, r_dst, imm_srcR);
cerionab9132d2005-02-15 15:46:59 +00002191 }
cerionab9132d2005-02-15 15:46:59 +00002192 }
cerionb85e8bb2005-02-16 08:54:33 +00002193 goto done;
cerionab9132d2005-02-15 15:46:59 +00002194 }
2195
cerion5e2527e2005-02-25 16:39:58 +00002196 case Pin_Sub32: {
ceriona2f75882005-03-15 16:33:38 +00002197 UInt r_dst = iregNo(i->Pin.Sub32.dst);
2198 UInt r_srcR = iregNo(i->Pin.Sub32.srcR);
2199 UInt r_srcL, imm_srcL;
cerion5e2527e2005-02-25 16:39:58 +00002200
2201 // Note argument swap: PPC32 only has sub-from instrs
ceriona2f75882005-03-15 16:33:38 +00002202 switch (i->Pin.Sub32.srcL->tag) {
cerion5e2527e2005-02-25 16:39:58 +00002203 case Pri_Reg:
ceriona2f75882005-03-15 16:33:38 +00002204 r_srcL = iregNo(i->Pin.Sub32.srcL->Pri.Reg.reg);
2205 // subf r_dst, r_srcR, r_srcL
2206 p = mkFormXO(p, 31, r_dst, r_srcR, r_srcL, 0, 40, 0);
cerion5e2527e2005-02-25 16:39:58 +00002207 break;
2208 case Pri_Imm:
ceriona2f75882005-03-15 16:33:38 +00002209 imm_srcL = i->Pin.Sub32.srcL->Pri.Imm.imm32;
2210 // subf r_dst, r_srcR, imm_srcL
2211 p = mkFormD(p, 8, r_dst, r_srcR, imm_srcL);
cerion5e2527e2005-02-25 16:39:58 +00002212 break;
2213 default:
2214 goto bad;
2215 }
2216 goto done;
2217 }
2218
cerionab9132d2005-02-15 15:46:59 +00002219 case Pin_Sh32: {
ceriona2f75882005-03-15 16:33:38 +00002220 UInt opc1 = 31, opc2, r_shft, imm_shft;
cerionb85e8bb2005-02-16 08:54:33 +00002221 UInt op = i->Pin.Sh32.op;
ceriona2f75882005-03-15 16:33:38 +00002222 UInt r_src = iregNo(i->Pin.Sh32.src);
2223 UInt r_dst = iregNo(i->Pin.Sh32.dst);
cerionab9132d2005-02-15 15:46:59 +00002224
cerionab9132d2005-02-15 15:46:59 +00002225 switch (i->Pin.Sh32.shft->tag) {
2226 case Pri_Reg:
cerion9e263e32005-03-03 17:21:51 +00002227 switch (op) {
2228 case Psh_SHL: opc2 = 24; break;
2229 case Psh_SHR: opc2 = 536; break;
2230 case Psh_SAR: opc2 = 792; break;
2231 default: goto bad;
2232 }
ceriona2f75882005-03-15 16:33:38 +00002233 r_shft = iregNo(i->Pin.Sh32.shft->Pri.Reg.reg);
2234 p = mkFormX(p, opc1, r_src, r_dst, r_shft, opc2, 0);
cerionb85e8bb2005-02-16 08:54:33 +00002235 break;
cerion9e263e32005-03-03 17:21:51 +00002236
2237 case Pri_Imm: // SAR only
2238 if (op != Psh_SAR) goto bad;
2239 opc2 = 824;
ceriona2f75882005-03-15 16:33:38 +00002240 imm_shft = i->Pin.Sh32.shft->Pri.Imm.imm32;
2241 p = mkFormX(p, opc1, r_src, r_dst, imm_shft, opc2, 0);
cerionb85e8bb2005-02-16 08:54:33 +00002242 break;
cerion9e263e32005-03-03 17:21:51 +00002243
cerionab9132d2005-02-15 15:46:59 +00002244 default:
2245 goto bad;
2246 }
cerionb85e8bb2005-02-16 08:54:33 +00002247 goto done;
cerionab9132d2005-02-15 15:46:59 +00002248 }
cerion2c49e032005-02-09 17:29:49 +00002249
cerion98411db2005-02-16 14:14:49 +00002250 case Pin_Cmp32: {
2251 UInt opc1, opc2=0;
2252 UInt op = i->Pin.Cmp32.op;
cerione97e1062005-02-21 15:09:19 +00002253 UInt fld1 = (7 - i->Pin.Cmp32.crfD) << 2;
ceriona2f75882005-03-15 16:33:38 +00002254 UInt r_srcL = iregNo(i->Pin.Cmp32.srcL);
2255 UInt r_srcR, imm_srcR;
cerionab9132d2005-02-15 15:46:59 +00002256
ceriona2f75882005-03-15 16:33:38 +00002257 switch (i->Pin.Cmp32.srcR->tag) {
cerion98411db2005-02-16 14:14:49 +00002258 case Pri_Imm:
2259 opc1 = (op == Pcmp_U) ? 10 : 11;
ceriona2f75882005-03-15 16:33:38 +00002260 imm_srcR = i->Pin.Cmp32.srcR->Pri.Imm.imm32;
2261 p = mkFormD(p, opc1, fld1, r_srcL, imm_srcR);
cerion98411db2005-02-16 14:14:49 +00002262 break;
2263 case Pri_Reg:
2264 opc1 = 31;
2265 opc2 = (op == Pcmp_U) ? 32 : 0;
ceriona2f75882005-03-15 16:33:38 +00002266 r_srcR = iregNo(i->Pin.Cmp32.srcR->Pri.Reg.reg);
2267 p = mkFormX(p, opc1, fld1, r_srcL, r_srcR, opc2, 0);
cerion98411db2005-02-16 14:14:49 +00002268 break;
2269 default: goto bad;
2270 }
2271 goto done;
2272 }
cerionb536af92005-02-10 15:03:19 +00002273
cerion98411db2005-02-16 14:14:49 +00002274 case Pin_Unary32: {
2275 UInt r_dst = iregNo(i->Pin.Unary32.dst);
2276 UInt r_src = iregNo(i->Pin.Unary32.src);
2277
2278 switch (i->Pin.Unary32.op) {
2279 case Pun_NOT: // nor r_dst,r_src,r_src
2280 p = mkFormX(p, 31, r_src, r_dst, r_src, 124, 0);
2281 break;
2282 case Pun_NEG: // neg r_dst,r_src
2283 p = mkFormXO(p, 31, r_dst, r_src, 0, 0, 104, 0);
2284 break;
2285 case Pun_CLZ: // cntlzw r_dst, r_src
cerion99f35772005-03-15 16:36:02 +00002286 p = mkFormX(p, 31, r_src, r_dst, 0, 26, 0);
cerion98411db2005-02-16 14:14:49 +00002287 break;
2288 default: goto bad;
2289 }
2290 goto done;
2291 }
2292
2293 case Pin_MulL: {
2294 Bool syned = i->Pin.MulL.syned;
2295 UInt r_dst = iregNo(i->Pin.MulL.dst);
ceriona2f75882005-03-15 16:33:38 +00002296 UInt r_srcL = iregNo(i->Pin.MulL.srcL);
2297 UInt r_srcR, imm;
cerion98411db2005-02-16 14:14:49 +00002298
2299 switch (i->Pin.MulL.word) {
cerion9e263e32005-03-03 17:21:51 +00002300 case 0: // Mult LOW word
ceriona2f75882005-03-15 16:33:38 +00002301 switch (i->Pin.MulL.srcR->tag) {
cerion98411db2005-02-16 14:14:49 +00002302 case Pri_Reg:
ceriona2f75882005-03-15 16:33:38 +00002303 // mullw r_dst,r_srcL,r_srcR
cerion98411db2005-02-16 14:14:49 +00002304 // sign makes no difference.
ceriona2f75882005-03-15 16:33:38 +00002305 r_srcR = iregNo(i->Pin.MulL.srcR->Pri.Reg.reg);
2306 p = mkFormXO(p, 31, r_dst, r_srcL, r_srcR, 0, 235, 0);
cerion98411db2005-02-16 14:14:49 +00002307 break;
2308 case Pri_Imm:
2309 // mulli r_dst,r_src,imm
2310 vassert(syned == True); // always signed
ceriona2f75882005-03-15 16:33:38 +00002311 imm = i->Pin.MulL.srcR->Pri.Imm.imm32;
2312 p = mkFormD(p, 07, r_dst, r_srcL, imm);
cerion98411db2005-02-16 14:14:49 +00002313 break;
2314 default:
2315 goto bad;
2316 }
2317 break;
cerion9e263e32005-03-03 17:21:51 +00002318
2319 case 1: // Mult HIGH word
ceriona2f75882005-03-15 16:33:38 +00002320 vassert(i->Pin.MulL.srcR->tag == Pri_Reg);
2321 r_srcR = iregNo(i->Pin.MulL.srcR->Pri.Reg.reg);
cerion98411db2005-02-16 14:14:49 +00002322 if (syned == True) {
ceriona2f75882005-03-15 16:33:38 +00002323 // mulhw r_dst,r_srcL,r_srcR
2324 p = mkFormXO(p, 31, r_dst, r_srcL, r_srcR, 0, 75, 0);
cerion98411db2005-02-16 14:14:49 +00002325 } else {
ceriona2f75882005-03-15 16:33:38 +00002326 // mulhwu r_dst,r_srcL,r_srcR
2327 p = mkFormXO(p, 31, r_dst, r_srcL, r_srcR, 0, 11, 0);
cerion98411db2005-02-16 14:14:49 +00002328 }
2329 break;
cerion9e263e32005-03-03 17:21:51 +00002330
2331 default: goto bad;
cerion98411db2005-02-16 14:14:49 +00002332 }
2333 goto done;
2334 }
cerion2c49e032005-02-09 17:29:49 +00002335
cerionfd0b87f2005-02-16 14:43:14 +00002336 case Pin_Div: {
2337 Bool syned = i->Pin.MulL.syned;
2338 UInt r_dst = iregNo(i->Pin.Div.dst);
ceriona2f75882005-03-15 16:33:38 +00002339 UInt r_srcL = iregNo(i->Pin.Div.srcL);
2340 UInt r_srcR = iregNo(i->Pin.Div.srcR);
cerionfd0b87f2005-02-16 14:43:14 +00002341
2342 if (syned == True) {
ceriona2f75882005-03-15 16:33:38 +00002343 // divw r_dst,r_srcL,r_srcR
2344 p = mkFormXO(p, 31, r_dst, r_srcL, r_srcR, 0, 491, 0);
cerionfd0b87f2005-02-16 14:43:14 +00002345 } else {
ceriona2f75882005-03-15 16:33:38 +00002346 // divwu r_dst,r_srcL,r_srcR
2347 p = mkFormXO(p, 31, r_dst, r_srcL, r_srcR, 0, 459, 0);
cerionfd0b87f2005-02-16 14:43:14 +00002348 }
2349 goto done;
2350 }
cerion2c49e032005-02-09 17:29:49 +00002351
cerion33aa6da2005-02-16 10:25:26 +00002352 case Pin_Call: {
cerion7cf8e4e2005-02-16 16:08:17 +00002353 PPC32CondCode cond = i->Pin.Call.cond;
ceriona56e9cc2005-02-16 18:08:25 +00002354 UInt r_dst = 12;
2355 /* As per detailed comment for Pin_Call in
cerion9e263e32005-03-03 17:21:51 +00002356 getRegUsage_PPC32Instr above, %r12 is used as an address temp */
ceriona56e9cc2005-02-16 18:08:25 +00002357
cerioned623db2005-06-20 12:42:04 +00002358 /* jump over the following insns if condition does not hold */
cerione97e1062005-02-21 15:09:19 +00002359 if (cond.test != Pct_ALWAYS) {
cerion9762bbf2005-06-23 08:44:52 +00002360 /* jmp fwds if !condition */
2361 /* don't know how many bytes to jump over yet...
2362 make space for a jump instruction and fill in later. */
2363 ptmp = p; /* fill in this bit later */
2364 p += 4; // p += 4
cerionab9132d2005-02-15 15:46:59 +00002365 }
2366
cerione97e1062005-02-21 15:09:19 +00002367 /* load target to r_dst */
cerion9762bbf2005-06-23 08:44:52 +00002368 p = mkLoadImm(p, r_dst, i->Pin.Call.target); // p += 4|8
cerionab9132d2005-02-15 15:46:59 +00002369
ceriona56e9cc2005-02-16 18:08:25 +00002370 /* mtspr 9,r_dst => move r_dst to count register */
cerion9762bbf2005-06-23 08:44:52 +00002371 p = mkFormXFX(p, r_dst, 9, 467); // p += 4
cerion33aa6da2005-02-16 10:25:26 +00002372
cerion8c51ed42005-02-22 11:16:54 +00002373 /* bctrl => branch to count register (and save to lr) */
cerion9762bbf2005-06-23 08:44:52 +00002374 p = mkFormXL(p, 19, Pct_ALWAYS, 0, 0, 528, 1); // p += 4
2375
2376 /* Fix up the conditional jump, if there was one. */
2377 if (cond.test != Pct_ALWAYS) {
2378 Int delta = p - ptmp;
2379 vassert(delta >= 16 && delta <= 20);
2380 /* bc !ct,cf,delta */
2381 mkFormB(ptmp, invertCondTest(cond.test), cond.flag, (delta>>2), 0, 0);
2382 }
cerion33aa6da2005-02-16 10:25:26 +00002383 goto done;
2384 }
2385
2386 case Pin_Goto: {
2387 UInt magic_num = 0;
cerione97e1062005-02-21 15:09:19 +00002388 UChar r_return = 3; /* Put target addr into %r3 */
cerion33aa6da2005-02-16 10:25:26 +00002389 PPC32CondCode cond = i->Pin.Goto.cond;
ceriona2f75882005-03-15 16:33:38 +00002390 UInt r_dst, imm_dst;
cerion33aa6da2005-02-16 10:25:26 +00002391
2392 /* First off, if this is conditional, create a conditional
2393 jump over the rest of it. */
2394 if (cond.test != Pct_ALWAYS) {
2395 /* jmp fwds if !condition */
cerione97e1062005-02-21 15:09:19 +00002396 /* don't know how many bytes to jump over yet...
2397 make space for a jump instruction and fill in later. */
cerion7cf8e4e2005-02-16 16:08:17 +00002398 ptmp = p; /* fill in this bit later */
cerione97e1062005-02-21 15:09:19 +00002399 p += 4;
cerion33aa6da2005-02-16 10:25:26 +00002400 }
2401
cerione97e1062005-02-21 15:09:19 +00002402 // cond succeeds...
2403
cerion33aa6da2005-02-16 10:25:26 +00002404 /* If a non-boring, set GuestStatePtr appropriately. */
cerion33aa6da2005-02-16 10:25:26 +00002405 switch (i->Pin.Goto.jk) {
2406 case Ijk_ClientReq: magic_num = VEX_TRC_JMP_CLIENTREQ; break;
2407 case Ijk_Syscall: magic_num = VEX_TRC_JMP_SYSCALL; break;
2408 case Ijk_Yield: magic_num = VEX_TRC_JMP_YIELD; break;
2409 case Ijk_EmWarn: magic_num = VEX_TRC_JMP_EMWARN; break;
2410 case Ijk_MapFail: magic_num = VEX_TRC_JMP_MAPFAIL; break;
2411 case Ijk_NoDecode: magic_num = VEX_TRC_JMP_NODECODE; break;
sewardj7ce9d152005-03-15 16:54:13 +00002412 case Ijk_TInval: magic_num = VEX_TRC_JMP_TINVAL; break;
cerion33aa6da2005-02-16 10:25:26 +00002413 case Ijk_Ret:
2414 case Ijk_Call:
2415 case Ijk_Boring:
2416 break;
2417 default:
2418 ppIRJumpKind(i->Pin.Goto.jk);
2419 vpanic("emit_PPC32Instr.Pin_Goto: unknown jump kind");
2420 }
2421 if (magic_num !=0) {
2422 vassert(magic_num < 0x10000);
cerione97e1062005-02-21 15:09:19 +00002423 /* addi r31,0,magic_num */
cerioned623db2005-06-20 12:42:04 +00002424 p = mkFormD(p, 14, 31, 0, magic_num); // p += 4
cerion33aa6da2005-02-16 10:25:26 +00002425 }
2426
cerione97e1062005-02-21 15:09:19 +00002427 /* Get the destination address into %r_return */
cerion33aa6da2005-02-16 10:25:26 +00002428 if (i->Pin.Goto.dst->tag == Pri_Imm) {
ceriona2f75882005-03-15 16:33:38 +00002429 imm_dst = i->Pin.Goto.dst->Pri.Imm.imm32;
cerioned623db2005-06-20 12:42:04 +00002430 p = mkLoadImm(p, r_return, imm_dst); // p += 4|8
cerion33aa6da2005-02-16 10:25:26 +00002431 } else {
2432 vassert(i->Pin.Goto.dst->tag == Pri_Reg);
sewardj9a036bf2005-03-14 18:19:08 +00002433 r_dst = iregNo(i->Pin.Goto.dst->Pri.Reg.reg);
cerioned623db2005-06-20 12:42:04 +00002434 p = mkMoveReg(p, r_return, r_dst); // p += 4
cerion33aa6da2005-02-16 10:25:26 +00002435 }
cerione97e1062005-02-21 15:09:19 +00002436
2437 /* blr */
cerioned623db2005-06-20 12:42:04 +00002438 p = mkFormXL(p, 19, Pct_ALWAYS, 0, 0, 16, 0); // p += 4
cerion7cf8e4e2005-02-16 16:08:17 +00002439
2440 /* Fix up the conditional jump, if there was one. */
2441 if (cond.test != Pct_ALWAYS) {
2442 Int delta = p - ptmp;
cerioned623db2005-06-20 12:42:04 +00002443 vassert(delta >= 12 && delta <= 20);
cerione97e1062005-02-21 15:09:19 +00002444 /* bc !ct,cf,delta */
2445 mkFormB(ptmp, invertCondTest(cond.test), cond.flag, (delta>>2), 0, 0);
cerion7cf8e4e2005-02-16 16:08:17 +00002446 }
cerion33aa6da2005-02-16 10:25:26 +00002447 goto done;
2448 }
cerionb536af92005-02-10 15:03:19 +00002449
cerion98411db2005-02-16 14:14:49 +00002450 case Pin_CMov32: {
ceriona2f75882005-03-15 16:33:38 +00002451 UInt r_dst, imm_src, r_src;
sewardj9a036bf2005-03-14 18:19:08 +00002452 PPC32CondCode cond;
cerion98411db2005-02-16 14:14:49 +00002453 vassert(i->Pin.CMov32.cond.test != Pct_ALWAYS);
ceriona2f75882005-03-15 16:33:38 +00002454
sewardj9a036bf2005-03-14 18:19:08 +00002455 r_dst = iregNo(i->Pin.CMov32.dst);
2456 cond = i->Pin.CMov32.cond;
cerion98411db2005-02-16 14:14:49 +00002457
cerione97e1062005-02-21 15:09:19 +00002458 /* branch (if cond fails) over move instrs */
2459 if (cond.test != Pct_ALWAYS) {
2460 /* don't know how many bytes to jump over yet...
2461 make space for a jump instruction and fill in later. */
2462 ptmp = p; /* fill in this bit later */
2463 p += 4;
2464 }
cerion98411db2005-02-16 14:14:49 +00002465
2466 // cond true: move src => dst
2467 switch (i->Pin.CMov32.src->tag) {
2468 case Pri_Imm:
ceriona2f75882005-03-15 16:33:38 +00002469 imm_src = i->Pin.CMov32.src->Pri.Imm.imm32;
2470 p = mkLoadImm(p, r_dst, imm_src);
cerion98411db2005-02-16 14:14:49 +00002471 break;
2472 case Pri_Reg:
2473 r_src = iregNo(i->Pin.CMov32.src->Pri.Reg.reg);
cerione97e1062005-02-21 15:09:19 +00002474 p = mkMoveReg(p, r_dst, r_src);
cerion98411db2005-02-16 14:14:49 +00002475 break;
2476 default: goto bad;
2477 }
cerione97e1062005-02-21 15:09:19 +00002478
2479 /* Fix up the conditional jump, if there was one. */
2480 if (cond.test != Pct_ALWAYS) {
2481 Int delta = p - ptmp;
2482 vassert(delta >= 4 && delta <= 12);
2483 /* bc !ct,cf,delta */
2484 mkFormB(ptmp, invertCondTest(cond.test), cond.flag, (delta>>2), 0, 0);
2485 }
cerion98411db2005-02-16 14:14:49 +00002486 goto done;
2487 }
cerionb536af92005-02-10 15:03:19 +00002488
cerion7cf8e4e2005-02-16 16:08:17 +00002489 case Pin_Load: {
cerioned623db2005-06-20 12:42:04 +00002490 PPC32AMode* am_addr = i->Pin.Load.src;
2491 UInt r_dst = iregNo(i->Pin.Load.dst);
cerion7cf8e4e2005-02-16 16:08:17 +00002492 Bool syned = i->Pin.Load.syned;
ceriona2f75882005-03-15 16:33:38 +00002493 UInt opc1, opc2, sz = i->Pin.Load.sz;
cerion7cf8e4e2005-02-16 16:08:17 +00002494 switch (i->Pin.Load.src->tag) {
ceriond5e38382005-02-11 13:38:15 +00002495 case Pam_IR:
cerionab9132d2005-02-15 15:46:59 +00002496 if (sz == 2) { // the only signed load
ceriona2f75882005-03-15 16:33:38 +00002497 opc1 = (syned) ? 42: 40;
cerionab9132d2005-02-15 15:46:59 +00002498 } else {
cerion7cf8e4e2005-02-16 16:08:17 +00002499 vassert(syned == False);
ceriona2f75882005-03-15 16:33:38 +00002500 opc1 = (sz == 1) ? 34 : 32; // 1:4
cerionab9132d2005-02-15 15:46:59 +00002501 }
cerioned623db2005-06-20 12:42:04 +00002502 p = doAMode_IR(p, opc1, r_dst, am_addr);
cerionab9132d2005-02-15 15:46:59 +00002503 goto done;
ceriond5e38382005-02-11 13:38:15 +00002504 case Pam_RR:
cerionab9132d2005-02-15 15:46:59 +00002505 if (sz == 2) { // the only signed load
ceriona2f75882005-03-15 16:33:38 +00002506 opc2 = (syned) ? 343: 279;
cerionab9132d2005-02-15 15:46:59 +00002507 } else {
cerion7cf8e4e2005-02-16 16:08:17 +00002508 vassert(syned == False);
ceriona2f75882005-03-15 16:33:38 +00002509 opc2 = (sz == 1) ? 87 : 23; // 1:4
cerionab9132d2005-02-15 15:46:59 +00002510 }
cerioned623db2005-06-20 12:42:04 +00002511 p = doAMode_RR(p, 31, opc2, r_dst, am_addr);
cerionab9132d2005-02-15 15:46:59 +00002512 goto done;
ceriond5e38382005-02-11 13:38:15 +00002513 default:
cerionab9132d2005-02-15 15:46:59 +00002514 goto bad;
ceriond5e38382005-02-11 13:38:15 +00002515 }
2516 }
cerionb536af92005-02-10 15:03:19 +00002517
cerionab9132d2005-02-15 15:46:59 +00002518 case Pin_Set32: {
2519 /* Make the destination register be 1 or 0, depending on whether
cerion9e263e32005-03-03 17:21:51 +00002520 the relevant condition holds. */
cerion98411db2005-02-16 14:14:49 +00002521 UInt r_dst = iregNo(i->Pin.Set32.dst);
2522 PPC32CondCode cond = i->Pin.Set32.cond;
cerion7cf8e4e2005-02-16 16:08:17 +00002523 UInt rot_imm;
cerion98411db2005-02-16 14:14:49 +00002524 UInt r_tmp;
2525
2526 if (cond.test == Pct_ALWAYS) {
cerion9e263e32005-03-03 17:21:51 +00002527 // Just load 1 to dst => li dst,1
cerion98411db2005-02-16 14:14:49 +00002528 p = mkFormD(p, 14, r_dst, 0, 1);
cerionab9132d2005-02-15 15:46:59 +00002529 } else {
cerion7cf8e4e2005-02-16 16:08:17 +00002530 rot_imm = 1 + cond.flag;
ceriona56e9cc2005-02-16 18:08:25 +00002531 r_tmp = 0; // Not within scope of regalloc, so no need to declare.
cerion98411db2005-02-16 14:14:49 +00002532
2533 // r_tmp = CR => mfcr r_tmp
2534 p = mkFormX(p, 31, r_tmp, 0, 0, 19, 0);
2535
2536 // r_dst = flag (rotate left and mask)
cerion7cf8e4e2005-02-16 16:08:17 +00002537 // => rlwinm r_dst,r_tmp,rot_imm,31,31
cerione97e1062005-02-21 15:09:19 +00002538 p = mkFormM(p, 21, r_tmp, r_dst, rot_imm, 31, 31, 0);
cerion98411db2005-02-16 14:14:49 +00002539
2540 if (cond.test == Pct_FALSE) {
ceriona2f75882005-03-15 16:33:38 +00002541 // flip bit => xori r_dst,r_dst,1
cerion98411db2005-02-16 14:14:49 +00002542 p = mkFormD(p, 26, r_dst, r_dst, 1);
cerionab9132d2005-02-15 15:46:59 +00002543 }
2544 }
2545 goto done;
cerionab9132d2005-02-15 15:46:59 +00002546 }
cerionb536af92005-02-10 15:03:19 +00002547
cerion98411db2005-02-16 14:14:49 +00002548 case Pin_MFence: {
cerioned623db2005-06-20 12:42:04 +00002549 p = mkFormX(p, 31, 0, 0, 0, 598, 0); // sync, PPC32 p616
2550// CAB: Should this be isync?
2551// p = mkFormXL(p, 19, 0, 0, 0, 150, 0); // isync, PPC32 p467
cerion98411db2005-02-16 14:14:49 +00002552 goto done;
2553 }
cerionb536af92005-02-10 15:03:19 +00002554
ceriond5e38382005-02-11 13:38:15 +00002555 case Pin_Store: {
cerioned623db2005-06-20 12:42:04 +00002556 PPC32AMode* am_addr = i->Pin.Store.dst;
2557 UInt r_src = iregNo(i->Pin.Store.src);
ceriona2f75882005-03-15 16:33:38 +00002558 UInt opc1, opc2, sz = i->Pin.Store.sz;
ceriond5e38382005-02-11 13:38:15 +00002559 switch (i->Pin.Store.dst->tag) {
2560 case Pam_IR:
ceriona2f75882005-03-15 16:33:38 +00002561 opc1 = (sz == 1) ? 38 : ((sz == 2) ? 44 : 36); // 1:2:4
cerioned623db2005-06-20 12:42:04 +00002562 p = doAMode_IR(p, opc1, r_src, am_addr);
cerionab9132d2005-02-15 15:46:59 +00002563 goto done;
ceriond5e38382005-02-11 13:38:15 +00002564 case Pam_RR:
ceriona2f75882005-03-15 16:33:38 +00002565 opc2 = (sz == 1) ? 215 : ((sz == 2) ? 407 : 151); // 1:2:4
cerioned623db2005-06-20 12:42:04 +00002566 p = doAMode_RR(p, 31, opc2, r_src, am_addr);
cerionab9132d2005-02-15 15:46:59 +00002567 goto done;
ceriond5e38382005-02-11 13:38:15 +00002568 default:
cerionab9132d2005-02-15 15:46:59 +00002569 goto bad;
ceriond5e38382005-02-11 13:38:15 +00002570 }
2571 goto done;
2572 }
cerionb536af92005-02-10 15:03:19 +00002573
cerion094d1392005-06-20 13:45:57 +00002574 case Pin_FpUnary: {
2575 UInt fr_dst = fregNo(i->Pin.FpUnary.dst);
2576 UInt fr_src = fregNo(i->Pin.FpUnary.src);
2577 switch (i->Pin.FpUnary.op) {
2578 case Pfp_SQRT: // fsqrt, PPC32 p427
2579 p = mkFormA( p, 63, fr_dst, 0, fr_src, 0, 22, 0 );
2580 break;
2581 case Pfp_ABS: // fabs, PPC32 p399
2582 p = mkFormX(p, 63, fr_dst, 0, fr_src, 264, 0);
2583 break;
2584 case Pfp_NEG: // fneg, PPC32 p416
2585 p = mkFormX(p, 63, fr_dst, 0, fr_src, 40, 0);
2586 break;
2587 case Pfp_MOV: // fmr, PPC32 p410
2588 p = mkFormX(p, 63, fr_dst, 0, fr_src, 72, 0);
2589 break;
2590 default:
2591 goto bad;
2592 }
2593 goto done;
2594 }
2595
2596 case Pin_FpBinary: {
2597 UInt fr_dst = fregNo(i->Pin.FpBinary.dst);
2598 UInt fr_srcL = fregNo(i->Pin.FpBinary.srcL);
2599 UInt fr_srcR = fregNo(i->Pin.FpBinary.srcR);
2600 switch (i->Pin.FpBinary.op) {
2601 case Pfp_ADD: // fadd, PPC32 p400
2602 p = mkFormA( p, 63, fr_dst, fr_srcL, fr_srcR, 0, 21, 0 );
2603 break;
2604 case Pfp_SUB: // fsub, PPC32 p429
2605 p = mkFormA( p, 63, fr_dst, fr_srcL, fr_srcR, 0, 20, 0 );
2606 break;
2607 case Pfp_MUL: // fmul, PPC32 p413
2608 p = mkFormA( p, 63, fr_dst, fr_srcL, 0, fr_srcR, 25, 0 );
2609 break;
2610 case Pfp_DIV: // fdiv, PPC32 p406
2611 p = mkFormA( p, 63, fr_dst, fr_srcL, fr_srcR, 0, 18, 0 );
2612 break;
2613 default:
2614 goto bad;
2615 }
2616 goto done;
2617 }
2618
2619 case Pin_FpLdSt: {
2620 PPC32AMode* am_addr = i->Pin.FpLdSt.addr;
2621 UInt f_reg = fregNo(i->Pin.FpLdSt.reg);
2622 Bool idxd = toBool(i->Pin.FpLdSt.addr->tag == Pam_RR);
2623 UChar sz = i->Pin.FpLdSt.sz;
2624 vassert(sz == 4 || sz == 8);
2625
2626 if (i->Pin.FpLdSt.isLoad) { // Load from memory
2627 if (idxd) { // lf[s|d]x, PPC32 p444|440
2628 p = doAMode_RR(p, 31, ((sz == 4) ? 535 : 599), f_reg, am_addr);
2629 } else { // lf[s|d], PPC32 p441|437
2630 p = doAMode_IR(p, ((sz == 4) ? 48 : 50), f_reg, am_addr);
2631 }
2632 } else { // Store to memory
2633 if (idxd) { // stf[s|d]x, PPC32 p521|516
2634 p = doAMode_RR(p, 31, ((sz == 4) ? 663 : 727), f_reg, am_addr);
2635 } else { // stf[s|d], PPC32 p518|513
2636 p = doAMode_IR(p, ((sz == 4) ? 52 : 54), f_reg, am_addr);
2637 }
2638 }
2639 goto done;
2640 }
2641
2642 case Pin_FpF64toF32: {
2643 UInt fr_dst = fregNo(i->Pin.FpF64toF32.dst);
2644 UInt fr_src = fregNo(i->Pin.FpF64toF32.src);
2645 // frsp, PPC32 p423
2646 p = mkFormX(p, 63, fr_dst, 0, fr_src, 12, 0);
2647 goto done;
2648 }
2649
2650 case Pin_FpF64toI32: {
2651 UInt r_dst = iregNo(i->Pin.FpF64toI32.dst);
2652 UInt fr_src = fregNo(i->Pin.FpF64toI32.src);
2653 UChar fr_tmp = 7; // Temp freg
2654 PPC32AMode* am_addr;
2655
2656 // fctiw (conv f64 to i32), PPC32 p404
2657 p = mkFormX(p, 63, fr_tmp, 0, fr_src, 14, 0);
2658
2659 // No RI form of stfiwx, so need PPC32AMode_RR:
2660 am_addr = PPC32AMode_RR( StackFramePtr, hregPPC32_GPR0() );
2661
2662 // stfiwx (store fp64[lo32] as int32), PPC32 p517
2663 p = doAMode_RR(p, 31, 983, fr_tmp, am_addr);
2664
2665 // lwzx (load int32), PPC32 p463
2666 p = doAMode_RR(p, 31, 23, r_dst, am_addr);
2667 goto done;
2668 }
2669
2670 case Pin_FpCMov: {
2671 UInt fr_dst = fregNo(i->Pin.FpCMov.dst);
2672 UInt fr_src = fregNo(i->Pin.FpCMov.src);
2673 PPC32CondCode cc = i->Pin.FpCMov.cond;
2674
2675 if (fr_dst == fr_src) goto done;
2676
2677 vassert(cc.test != Pct_ALWAYS);
2678
2679 /* jmp fwds if !condition */
2680 if (cc.test != Pct_ALWAYS) {
2681 /* bc !ct,cf,n_bytes>>2 */
2682 p = mkFormB(p, invertCondTest(cc.test), cc.flag, 8>>2, 0, 0);
2683 }
2684
2685 // fmr, PPC32 p410
2686 p = mkFormX(p, 63, fr_dst, 0, fr_src, 72, 0);
2687 goto done;
2688 }
2689
2690 case Pin_FpLdFPSCR: {
2691 UInt fr_src = fregNo(i->Pin.FpLdFPSCR.src);
2692 p = mkFormXFL(p, 0xFF, fr_src); // mtfsf, PPC32 p480
2693 goto done;
2694 }
2695
2696 case Pin_FpCmp: {
2697 UChar crfD = 1;
2698 UInt r_dst = iregNo(i->Pin.FpCmp.dst);
2699 UInt fr_srcL = fregNo(i->Pin.FpCmp.srcL);
2700 UInt fr_srcR = fregNo(i->Pin.FpCmp.srcR);
2701 vassert(crfD < 8);
2702 // fcmpo, PPC32 p402
2703 p = mkFormX(p, 63, (crfD<<2), fr_srcL, fr_srcR, 32, 0);
2704
2705 // mfcr (mv CR to r_dst), PPC32 p467
2706 p = mkFormX(p, 31, r_dst, 0, 0, 19, 0);
2707
2708 // rlwinm r_dst,r_dst,8,28,31, PPC32 p501
2709 // => rotate field 6 to field 0, masking to field 0
2710 p = mkFormM(p, 21, r_dst, r_dst, 8, 28, 31, 0);
2711 goto done;
2712 }
cerionbcf8c3e2005-02-04 16:17:07 +00002713
cerion7f000af2005-02-22 20:36:49 +00002714 case Pin_RdWrLR: {
2715 UInt reg = iregNo(i->Pin.RdWrLR.gpr);
2716 /* wrLR==True ? mtlr r4 : mflr r4 */
2717 p = mkFormXFX(p, reg, 8, (i->Pin.RdWrLR.wrLR==True) ? 467 : 339);
2718 goto done;
2719 }
2720
cerionc3d8bdc2005-06-28 18:06:23 +00002721
2722 /* AltiVec */
2723 case Pin_AvLdSt: {
2724 UInt opc2, v_reg, r_idx, r_base;
2725 UChar sz = i->Pin.AvLdSt.sz;
2726 Bool idxd = toBool(i->Pin.AvLdSt.addr->tag == Pam_RR);
2727 vassert(sz == 8 || sz == 16 || sz == 32 || sz == 128);
2728
2729 v_reg = vregNo(i->Pin.AvLdSt.reg);
2730 r_base = iregNo(i->Pin.AvLdSt.addr->Pam.RR.base);
2731
2732 // Only have AltiVec AMode_RR: kludge AMode_IR
2733 if (!idxd) {
2734 r_idx = 30; // XXX: Using r30 as temp
2735 p = mkLoadImm(p, r_idx, i->Pin.AvLdSt.addr->Pam.IR.index);
2736 } else {
2737 r_idx = iregNo(i->Pin.AvLdSt.addr->Pam.RR.index);
2738 }
2739
2740 if (i->Pin.FpLdSt.isLoad) { // Load from memory (8,16,32,128)
2741 opc2 = (sz == 8) ? 7 : (sz == 16) ? 39 : (sz == 32) ? 71 : 103;
2742 p = mkFormX(p, 31, v_reg, r_idx, r_base, opc2, 0);
2743 } else { // Store to memory (8,16,32,128)
2744 opc2 = (sz == 8) ? 135 : (sz == 16) ? 167 : (sz == 32) ? 199 : 231;
2745 p = mkFormX(p, 31, v_reg, r_idx, r_base, opc2, 0);
2746 }
2747 goto done;
2748 }
2749
2750 case Pin_AvUnary: {
2751 UInt v_dst = vregNo(i->Pin.AvUnary.dst);
2752 UInt v_src = vregNo(i->Pin.AvUnary.src);
2753 UInt opc2;
2754 switch (i->Pin.AvUnary.op) {
2755 case Pav_MOV: opc2 = 1156; break; // vor vD,vS,vS
2756 case Pav_NOT: opc2 = 1284; break; // vnor vD,vS,vS
2757 case Pav_UNPCKH8S: opc2 = 526; break; // vupkhsb
2758 case Pav_UNPCKH16S: opc2 = 590; break; // vupkhsh
2759 case Pav_UNPCKL8S: opc2 = 654; break; // vupklsb
2760 case Pav_UNPCKL16S: opc2 = 718; break; // vupklsh
2761 case Pav_UNPCKHPIX: opc2 = 846; break; // vupkhpx
2762 case Pav_UNPCKLPIX: opc2 = 974; break; // vupklpx
2763 default:
2764 goto bad;
2765 }
2766 switch (i->Pin.AvUnary.op) {
2767 case Pav_MOV:
2768 case Pav_NOT:
2769 p = mkFormVX( p, 4, v_dst, v_src, v_src, opc2 );
2770 break;
2771 default:
2772 p = mkFormVX( p, 4, v_dst, 0, v_src, opc2 );
2773 break;
2774 }
2775 goto done;
2776 }
2777
2778 case Pin_AvBinary: {
2779 UInt v_dst = vregNo(i->Pin.AvBinary.dst);
2780 UInt v_srcL = vregNo(i->Pin.AvBinary.srcL);
2781 UInt v_srcR = vregNo(i->Pin.AvBinary.srcR);
2782 UInt opc2;
2783 switch (i->Pin.AvBinary.op) {
2784 /* Bitwise */
2785 case Pav_AND: opc2 = 1026; break; // vand
2786 case Pav_OR: opc2 = 1156; break; // vor
2787 case Pav_XOR: opc2 = 1120; break; // vxor
2788
cerionc3d8bdc2005-06-28 18:06:23 +00002789 /* Shift */
cerion6b6f59e2005-06-28 20:59:18 +00002790 case Pav_SHL: opc2 = 452; break; // vsl
2791 case Pav_SHR: opc2 = 708; break; // vsr
cerionc3d8bdc2005-06-28 18:06:23 +00002792
2793 default:
2794 goto bad;
2795 }
2796 p = mkFormVX( p, 4, v_dst, v_srcL, v_srcR, opc2 );
2797 goto done;
2798 }
2799
cerion6b6f59e2005-06-28 20:59:18 +00002800 case Pin_AvBin8x16: {
2801 UInt v_dst = vregNo(i->Pin.AvBin8x16.dst);
2802 UInt v_srcL = vregNo(i->Pin.AvBin8x16.srcL);
2803 UInt v_srcR = vregNo(i->Pin.AvBin8x16.srcR);
2804 UInt opc2;
2805 switch (i->Pin.AvBin8x16.op) {
2806
2807 case Pav_ADDUM: opc2 = 0; break; // vaddubm
2808 case Pav_ADDUS: opc2 = 512; break; // vaddubs
2809 case Pav_ADDSS: opc2 = 768; break; // vaddsbs
2810
2811 case Pav_SUBUM: opc2 = 1024; break; // vsububm
2812 case Pav_SUBUS: opc2 = 1536; break; // vsububs
2813 case Pav_SUBSS: opc2 = 1792; break; // vsubsbs
2814
2815 case Pav_OMULU: opc2 = 8; break; // vmuloub
2816 case Pav_OMULS: opc2 = 264; break; // vmulosb
2817 case Pav_EMULU: opc2 = 520; break; // vmuleub
2818 case Pav_EMULS: opc2 = 776; break; // vmulesb
2819
2820 case Pav_AVGU: opc2 = 1026; break; // vavgub
2821 case Pav_AVGS: opc2 = 1282; break; // vavgsb
2822 case Pav_MAXU: opc2 = 2; break; // vmaxub
2823 case Pav_MAXS: opc2 = 258; break; // vmaxsb
2824 case Pav_MINU: opc2 = 514; break; // vminub
2825 case Pav_MINS: opc2 = 770; break; // vminsb
2826
2827 case Pav_CMPEQU: opc2 = 6; break; // vcmpequb
2828 case Pav_CMPGTU: opc2 = 518; break; // vcmpgtub
2829 case Pav_CMPGTS: opc2 = 774; break; // vcmpgtsb
2830
2831 case Pav_SHL: opc2 = 260; break; // vslb
2832 case Pav_SHR: opc2 = 516; break; // vsrb
2833 case Pav_SAR: opc2 = 772; break; // vsrab
2834 case Pav_ROTL: opc2 = 4; break; // vrlb
2835
2836 case Pav_MRGHI: opc2 = 12; break; // vmrghb
2837 case Pav_MRGLO: opc2 = 268; break; // vmrglb
2838
2839 default:
2840 goto bad;
2841 }
2842 p = mkFormVX( p, 4, v_dst, v_srcL, v_srcR, opc2 );
2843 goto done;
2844 }
2845
2846 case Pin_AvBin16x8: {
2847 UInt v_dst = vregNo(i->Pin.AvBin16x8.dst);
2848 UInt v_srcL = vregNo(i->Pin.AvBin16x8.srcL);
2849 UInt v_srcR = vregNo(i->Pin.AvBin16x8.srcR);
2850 UInt opc2;
2851 switch (i->Pin.AvBin16x8.op) {
2852
2853 case Pav_ADDUM: opc2 = 64; break; // vadduhm
2854 case Pav_ADDUS: opc2 = 576; break; // vadduhs
2855 case Pav_ADDSS: opc2 = 832; break; // vaddshs
2856
2857 case Pav_SUBUM: opc2 = 1088; break; // vsubuhm
2858 case Pav_SUBUS: opc2 = 1600; break; // vsubuhs
2859 case Pav_SUBSS: opc2 = 1856; break; // vsubshs
2860
2861 case Pav_OMULU: opc2 = 72; break; // vmulouh
2862 case Pav_OMULS: opc2 = 328; break; // vmulosh
2863 case Pav_EMULU: opc2 = 584; break; // vmuleuh
2864 case Pav_EMULS: opc2 = 840; break; // vmulesh
2865
2866 case Pav_AVGU: opc2 = 1090; break; // vavguh
2867 case Pav_AVGS: opc2 = 1346; break; // vavgsh
2868 case Pav_MAXU: opc2 = 66; break; // vmaxuh
2869 case Pav_MAXS: opc2 = 322; break; // vmaxsh
2870 case Pav_MINS: opc2 = 834; break; // vminsh
2871 case Pav_MINU: opc2 = 578; break; // vminuh
2872
2873 case Pav_CMPEQU: opc2 = 70; break; // vcmpequh
2874 case Pav_CMPGTU: opc2 = 582; break; // vcmpgtuh
2875 case Pav_CMPGTS: opc2 = 838; break; // vcmpgtsh
2876
2877 case Pav_SHL: opc2 = 324; break; // vslh
2878 case Pav_SHR: opc2 = 580; break; // vsrh
2879 case Pav_SAR: opc2 = 836; break; // vsrah
2880 case Pav_ROTL: opc2 = 68; break; // vrlh
2881
2882 case Pav_PACKUUM: opc2 = 14; break; // vpkuhum
2883 case Pav_PACKUUS: opc2 = 142; break; // vpkuhus
2884 case Pav_PACKSUS: opc2 = 270; break; // vpkshus
2885 case Pav_PACKSSS: opc2 = 398; break; // vpkshss
2886 case Pav_PACKPXL: opc2 = 782; break; // vpkpx
2887
2888 case Pav_MRGHI: opc2 = 76; break; // vmrghh
2889 case Pav_MRGLO: opc2 = 332; break; // vmrglh
2890
2891 default:
2892 goto bad;
2893 }
2894 p = mkFormVX( p, 4, v_dst, v_srcL, v_srcR, opc2 );
2895 goto done;
2896 }
2897
2898 case Pin_AvBin32x4: {
2899 UInt v_dst = vregNo(i->Pin.AvBin32x4.dst);
2900 UInt v_srcL = vregNo(i->Pin.AvBin32x4.srcL);
2901 UInt v_srcR = vregNo(i->Pin.AvBin32x4.srcR);
2902 UInt opc2;
2903 switch (i->Pin.AvBin32x4.op) {
2904
2905 case Pav_ADDUM: opc2 = 128; break; // vadduwm
2906 case Pav_ADDUS: opc2 = 640; break; // vadduws
2907 case Pav_ADDSS: opc2 = 896; break; // vaddsws
2908
2909 case Pav_SUBUM: opc2 = 1152; break; // vsubuwm
2910 case Pav_SUBUS: opc2 = 1664; break; // vsubuws
2911 case Pav_SUBSS: opc2 = 1920; break; // vsubsws
2912
2913 case Pav_AVGU: opc2 = 1154; break; // vavguw
2914 case Pav_AVGS: opc2 = 1410; break; // vavgsw
2915
2916 case Pav_MAXU: opc2 = 130; break; // vmaxuw
2917 case Pav_MAXS: opc2 = 386; break; // vmaxsw
2918
2919 case Pav_MINS: opc2 = 898; break; // vminsw
2920 case Pav_MINU: opc2 = 642; break; // vminuw
2921
2922 case Pav_CMPEQU: opc2 = 134; break; // vcmpequw
2923 case Pav_CMPGTS: opc2 = 902; break; // vcmpgtsw
2924 case Pav_CMPGTU: opc2 = 646; break; // vcmpgtuw
2925
2926 case Pav_SHL: opc2 = 388; break; // vslw
2927 case Pav_SHR: opc2 = 644; break; // vsrw
2928 case Pav_SAR: opc2 = 900; break; // vsraw
2929 case Pav_ROTL: opc2 = 132; break; // vrlw
2930
2931 case Pav_PACKUUM: opc2 = 78; break; // vpkuwum
2932 case Pav_PACKUUS: opc2 = 206; break; // vpkuwus
2933 case Pav_PACKSUS: opc2 = 334; break; // vpkswus
2934 case Pav_PACKSSS: opc2 = 462; break; // vpkswss
2935
2936 case Pav_MRGHI: opc2 = 140; break; // vmrghw
2937 case Pav_MRGLO: opc2 = 396; break; // vmrglw
2938
2939 default:
2940 goto bad;
2941 }
2942 p = mkFormVX( p, 4, v_dst, v_srcL, v_srcR, opc2 );
2943 goto done;
2944 }
2945
2946 case Pin_AvBin32Fx4: {
2947 UInt v_dst = vregNo(i->Pin.AvBin32Fx4.dst);
2948 UInt v_srcL = vregNo(i->Pin.AvBin32Fx4.srcL);
2949 UInt v_srcR = vregNo(i->Pin.AvBin32Fx4.srcR);
2950 switch (i->Pin.AvBin32Fx4.op) {
2951
2952 case Pav_ADDF:
2953 p = mkFormVX( p, 4, v_dst, v_srcL, v_srcR, 10 ); // vaddfp
2954 break;
2955 case Pav_SUBF:
2956 p = mkFormVX( p, 4, v_dst, v_srcL, v_srcR, 74 ); // vsubfp
2957 break;
2958 case Pav_MAXF:
2959 p = mkFormVX( p, 4, v_dst, v_srcL, v_srcR, 1034 ); // vmaxfp
2960 break;
2961 case Pav_MINF:
2962 p = mkFormVX( p, 4, v_dst, v_srcL, v_srcR, 1098 ); // vminfp
2963 break;
2964
2965 case Pav_MULF: {
2966 /* Make a vmulfp from a vmaddfp:
2967 load -0.0 (0x8000_0000) to each 32-bit word of vB
2968 this makes the add a noop.
2969 */
2970 UInt vB = 29; // XXX: Using r29 for temp
2971 UInt zero_simm = 0x80000000;
2972
2973 // Better way to load zero_imm?
2974 // vspltisw vB,0x1F (0x1F => each word of vB)
2975 p = mkFormVX( p, 4, vB, zero_simm, 0, 908 );
2976
2977 // vslw vB,vB,vB (each word of vB = (0x1F << 0x1F) = 0x80000000
2978 p = mkFormVX( p, 4, vB, vB, vB, 388 );
2979
2980 // Finally, do the multiply:
2981 p = mkFormVA( p, 4, v_dst, v_srcL, vB, v_srcR, 46 );
2982 break;
2983 }
2984 case Pav_CMPEQF:
2985 p = mkFormVXR( p, 4, v_dst, v_srcL, v_srcR, 0, 198 ); // vcmpeqfp
2986 break;
2987 case Pav_CMPGTF:
2988 p = mkFormVXR( p, 4, v_dst, v_srcL, v_srcR, 1, 710 ); // vcmpgtfp
2989 break;
2990 case Pav_CMPGEF:
2991 p = mkFormVXR( p, 4, v_dst, v_srcL, v_srcR, 1, 454 ); // vcmpgefp
2992 break;
2993
2994 default:
2995 goto bad;
2996 }
2997 goto done;
2998 }
2999
cerionc3d8bdc2005-06-28 18:06:23 +00003000 case Pin_AvPerm: { // vperm
3001 UInt v_ctl = vregNo(i->Pin.AvPerm.ctl);
3002 UInt v_dst = vregNo(i->Pin.AvPerm.dst);
3003 UInt v_srcL = vregNo(i->Pin.AvPerm.srcL);
3004 UInt v_srcR = vregNo(i->Pin.AvPerm.srcR);
3005 p = mkFormVA( p, 4, v_dst, v_srcL, v_srcR, v_ctl, 43 );
3006 goto done;
3007 }
3008
3009 case Pin_AvSel: { // vsel
3010 UInt v_ctl = vregNo(i->Pin.AvSel.ctl);
3011 UInt v_dst = vregNo(i->Pin.AvSel.dst);
3012 UInt v_srcL = vregNo(i->Pin.AvSel.srcL);
3013 UInt v_srcR = vregNo(i->Pin.AvSel.srcR);
3014 p = mkFormVA( p, 4, v_dst, v_srcL, v_srcR, v_ctl, 42 );
3015 goto done;
3016 }
3017
3018 case Pin_AvShlDbl: { // vsldoi
3019 UInt shift = i->Pin.AvShlDbl.shift;
3020 UInt v_dst = vregNo(i->Pin.AvShlDbl.dst);
3021 UInt v_srcL = vregNo(i->Pin.AvShlDbl.srcL);
3022 UInt v_srcR = vregNo(i->Pin.AvShlDbl.srcR);
3023 vassert(shift <= 0xF);
3024 p = mkFormVA( p, 4, v_dst, v_srcL, v_srcR, shift, 44 );
3025 goto done;
3026 }
3027
3028 case Pin_AvSplat: { // vsplt(is)(b,h,w)
3029 UInt v_dst = vregNo(i->Pin.AvShlDbl.dst);
3030 UChar sz = i->Pin.AvSplat.sz;
3031 UInt v_src, simm_src, opc2;
3032 vassert(sz == 8 || sz == 16 || sz == 32);
3033
3034 if (i->Pin.AvSplat.src->tag == Pri_Imm) {
cerion6b6f59e2005-06-28 20:59:18 +00003035 opc2 = (sz == 8) ? 780 : (sz == 16) ? 844 : 908; // 8,16,32
cerionc3d8bdc2005-06-28 18:06:23 +00003036 simm_src = i->Pin.AvSplat.src->Pri.Imm.imm32;
3037 p = mkFormVX( p, 4, v_dst, simm_src, 0, opc2 );
3038 } else { // Pri_Reg
3039 opc2 = (sz == 8) ? 524 : (sz == 16) ? 588 : 652; // 8,16,32
3040 v_src = iregNo(i->Pin.AvSplat.src->Pri.Reg.reg);
3041 p = mkFormVX( p, 4, v_dst, 0, v_src, opc2 );
3042 }
3043 goto done;
3044 }
3045
cerion6b6f59e2005-06-28 20:59:18 +00003046 case Pin_AvCMov: {
3047 UInt v_dst = vregNo(i->Pin.AvCMov.dst);
3048 UInt v_src = vregNo(i->Pin.AvCMov.src);
3049 PPC32CondCode cc = i->Pin.AvCMov.cond;
3050
3051 if (v_dst == v_src) goto done;
3052
3053 vassert(cc.test != Pct_ALWAYS);
3054
3055 /* jmp fwds 2 insns if !condition */
3056 if (cc.test != Pct_ALWAYS) {
3057 /* bc !ct,cf,n_bytes>>2 */
3058 p = mkFormB(p, invertCondTest(cc.test), cc.flag, 8>>2, 0, 0);
3059 }
3060 /* vmr */
3061 p = mkFormVX( p, 4, v_dst, v_src, v_src, 1156 );
3062 goto done;
3063 }
3064
cerionc3d8bdc2005-06-28 18:06:23 +00003065 case Pin_AvLdVSCR: { // mtvscr
3066 UInt v_src = vregNo(i->Pin.AvLdVSCR.src);
3067 p = mkFormVX( p, 4, 0, 0, v_src, 1604 );
3068 goto done;
3069 }
3070
cerionbcf8c3e2005-02-04 16:17:07 +00003071 default:
3072 goto bad;
3073 }
3074
3075 bad:
cerionab9132d2005-02-15 15:46:59 +00003076 vex_printf("\n=> ");
cerionbcf8c3e2005-02-04 16:17:07 +00003077 ppPPC32Instr(i);
3078 vpanic("emit_PPC32Instr");
3079 /*NOTREACHED*/
3080
cerionbcf8c3e2005-02-04 16:17:07 +00003081 done:
3082 vassert(p - &buf[0] <= 32);
3083 return p - &buf[0];
cerionbcf8c3e2005-02-04 16:17:07 +00003084}
3085
3086/*---------------------------------------------------------------*/
3087/*--- end host-ppc32/hdefs.c ---*/
3088/*---------------------------------------------------------------*/