blob: c9dce5afbcd015d4c75b1adfb3ebf3e2b99a57ca [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;
sewardj7d7f1b62005-07-04 09:40:56 +0000184 *nregs = 90 - 24 - 24;
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();
sewardj7d7f1b62005-07-04 09:40:56 +0000227/*
cerionc3d8bdc2005-06-28 18:06:23 +0000228 (*arr)[i++] = hregPPC32_FPR8();
229 (*arr)[i++] = hregPPC32_FPR9();
230 (*arr)[i++] = hregPPC32_FPR10();
231 (*arr)[i++] = hregPPC32_FPR11();
232 (*arr)[i++] = hregPPC32_FPR12();
233 (*arr)[i++] = hregPPC32_FPR13();
234 (*arr)[i++] = hregPPC32_FPR14();
235 (*arr)[i++] = hregPPC32_FPR15();
236 (*arr)[i++] = hregPPC32_FPR16();
237 (*arr)[i++] = hregPPC32_FPR17();
238 (*arr)[i++] = hregPPC32_FPR18();
239 (*arr)[i++] = hregPPC32_FPR19();
240 (*arr)[i++] = hregPPC32_FPR20();
241 (*arr)[i++] = hregPPC32_FPR21();
242 (*arr)[i++] = hregPPC32_FPR22();
243 (*arr)[i++] = hregPPC32_FPR23();
244 (*arr)[i++] = hregPPC32_FPR24();
245 (*arr)[i++] = hregPPC32_FPR25();
246 (*arr)[i++] = hregPPC32_FPR26();
247 (*arr)[i++] = hregPPC32_FPR27();
248 (*arr)[i++] = hregPPC32_FPR28();
249 (*arr)[i++] = hregPPC32_FPR29();
250 (*arr)[i++] = hregPPC32_FPR30();
251 (*arr)[i++] = hregPPC32_FPR31();
sewardj7d7f1b62005-07-04 09:40:56 +0000252*/
cerionc3d8bdc2005-06-28 18:06:23 +0000253 (*arr)[i++] = hregPPC32_VR0();
254 (*arr)[i++] = hregPPC32_VR1();
255 (*arr)[i++] = hregPPC32_VR2();
256 (*arr)[i++] = hregPPC32_VR3();
257 (*arr)[i++] = hregPPC32_VR4();
258 (*arr)[i++] = hregPPC32_VR5();
259 (*arr)[i++] = hregPPC32_VR6();
260 (*arr)[i++] = hregPPC32_VR7();
sewardj7d7f1b62005-07-04 09:40:56 +0000261/*
cerionc3d8bdc2005-06-28 18:06:23 +0000262 (*arr)[i++] = hregPPC32_VR8();
263 (*arr)[i++] = hregPPC32_VR9();
264 (*arr)[i++] = hregPPC32_VR10();
265 (*arr)[i++] = hregPPC32_VR11();
266 (*arr)[i++] = hregPPC32_VR12();
267 (*arr)[i++] = hregPPC32_VR13();
268 (*arr)[i++] = hregPPC32_VR14();
269 (*arr)[i++] = hregPPC32_VR15();
270 (*arr)[i++] = hregPPC32_VR16();
271 (*arr)[i++] = hregPPC32_VR17();
272 (*arr)[i++] = hregPPC32_VR18();
273 (*arr)[i++] = hregPPC32_VR19();
274 (*arr)[i++] = hregPPC32_VR20();
275 (*arr)[i++] = hregPPC32_VR21();
276 (*arr)[i++] = hregPPC32_VR22();
277 (*arr)[i++] = hregPPC32_VR23();
278 (*arr)[i++] = hregPPC32_VR24();
279 (*arr)[i++] = hregPPC32_VR25();
280 (*arr)[i++] = hregPPC32_VR26();
281 (*arr)[i++] = hregPPC32_VR27();
282 (*arr)[i++] = hregPPC32_VR28();
283 (*arr)[i++] = hregPPC32_VR29();
284 (*arr)[i++] = hregPPC32_VR30();
285 (*arr)[i++] = hregPPC32_VR31();
sewardj7d7f1b62005-07-04 09:40:56 +0000286*/
cerion01713102005-06-29 19:05:08 +0000287 vassert(i == *nregs);
cerion2c49e032005-02-09 17:29:49 +0000288}
289
290
291/* --------- Condition codes, Intel encoding. --------- */
292
293HChar* showPPC32CondCode ( PPC32CondCode cond )
294{
cerionab9132d2005-02-15 15:46:59 +0000295 if (cond.test == Pct_ALWAYS) return "always";
296
297 switch (cond.flag) {
298 case Pcf_SO: return (cond.test == Pct_TRUE) ? "so=1" : "so=0";
299 case Pcf_EQ: return (cond.test == Pct_TRUE) ? "eq=1" : "eq=0";
300 case Pcf_GT: return (cond.test == Pct_TRUE) ? "gt=1" : "gt=0";
301 case Pcf_LT: return (cond.test == Pct_TRUE) ? "lt=1" : "lt=0";
302 default: vpanic("ppPPC32CondCode");
cerion2c49e032005-02-09 17:29:49 +0000303 }
cerionbcf8c3e2005-02-04 16:17:07 +0000304}
305
cerioned623db2005-06-20 12:42:04 +0000306/* construct condition code */
cerion7cf8e4e2005-02-16 16:08:17 +0000307PPC32CondCode mk_PPCCondCode ( PPC32CondTest test, PPC32CondFlag flag )
308{
309 PPC32CondCode cc;
310 cc.flag = flag;
311 cc.test = test;
312 return cc;
313}
314
315/* false->true, true->false */
cerion33aa6da2005-02-16 10:25:26 +0000316PPC32CondTest invertCondTest ( PPC32CondTest ct )
317{
318 vassert(ct != Pct_ALWAYS);
319 return (ct == Pct_TRUE) ? Pct_FALSE : Pct_TRUE;
320}
321
322
cerioncd304492005-02-08 19:40:24 +0000323/* --------- PPCAMode: memory address expressions. --------- */
324
sewardja5f957d2005-07-02 01:29:32 +0000325PPC32AMode* PPC32AMode_IR ( Int idx, HReg base ) {
cerioncd304492005-02-08 19:40:24 +0000326 PPC32AMode* am = LibVEX_Alloc(sizeof(PPC32AMode));
sewardja5f957d2005-07-02 01:29:32 +0000327 vassert(idx >= -0x8000 && idx < 0x8000);
cerioncd304492005-02-08 19:40:24 +0000328 am->tag = Pam_IR;
329 am->Pam.IR.base = base;
330 am->Pam.IR.index = idx;
331 return am;
332}
333PPC32AMode* PPC32AMode_RR ( HReg idx, HReg base ) {
334 PPC32AMode* am = LibVEX_Alloc(sizeof(PPC32AMode));
335 am->tag = Pam_RR;
336 am->Pam.RR.base = base;
337 am->Pam.RR.index = idx;
338 return am;
339}
340
341PPC32AMode* dopyPPC32AMode ( PPC32AMode* am ) {
342 switch (am->tag) {
cerionb85e8bb2005-02-16 08:54:33 +0000343 case Pam_IR:
344 return PPC32AMode_IR( am->Pam.IR.index, am->Pam.IR.base );
345 case Pam_RR:
346 return PPC32AMode_RR( am->Pam.RR.index, am->Pam.RR.base );
347 default:
348 vpanic("dopyPPC32AMode");
cerioncd304492005-02-08 19:40:24 +0000349 }
350}
351
352void ppPPC32AMode ( PPC32AMode* am ) {
353 switch (am->tag) {
cerionb85e8bb2005-02-16 08:54:33 +0000354 case Pam_IR:
355 if (am->Pam.IR.index == 0)
cerionf9d6e222005-02-23 18:21:31 +0000356 vex_printf("0(");
cerionb85e8bb2005-02-16 08:54:33 +0000357 else
sewardja5f957d2005-07-02 01:29:32 +0000358 vex_printf("%d(", (Int)am->Pam.IR.index);
cerionb85e8bb2005-02-16 08:54:33 +0000359 ppHRegPPC32(am->Pam.IR.base);
360 vex_printf(")");
361 return;
362 case Pam_RR:
363 ppHRegPPC32(am->Pam.RR.base);
364 vex_printf(",");
365 ppHRegPPC32(am->Pam.RR.index);
366 return;
367 default:
368 vpanic("ppPPC32AMode");
cerioncd304492005-02-08 19:40:24 +0000369 }
370}
371
cerioncd304492005-02-08 19:40:24 +0000372static void addRegUsage_PPC32AMode ( HRegUsage* u, PPC32AMode* am ) {
373 switch (am->tag) {
cerionb85e8bb2005-02-16 08:54:33 +0000374 case Pam_IR:
375 addHRegUse(u, HRmRead, am->Pam.IR.base);
376 return;
377 case Pam_RR:
378 addHRegUse(u, HRmRead, am->Pam.RR.base);
379 addHRegUse(u, HRmRead, am->Pam.RR.index);
380 return;
381 default:
382 vpanic("addRegUsage_PPC32AMode");
cerioncd304492005-02-08 19:40:24 +0000383 }
384}
cerioncd304492005-02-08 19:40:24 +0000385
cerioncd304492005-02-08 19:40:24 +0000386static void mapRegs_PPC32AMode ( HRegRemap* m, PPC32AMode* am ) {
387 switch (am->tag) {
cerionb85e8bb2005-02-16 08:54:33 +0000388 case Pam_IR:
389 am->Pam.IR.base = lookupHRegRemap(m, am->Pam.IR.base);
390 return;
391 case Pam_RR:
392 am->Pam.RR.base = lookupHRegRemap(m, am->Pam.RR.base);
393 am->Pam.RR.index = lookupHRegRemap(m, am->Pam.RR.index);
394 return;
395 default:
396 vpanic("mapRegs_PPC32AMode");
cerioncd304492005-02-08 19:40:24 +0000397 }
398}
cerioncd304492005-02-08 19:40:24 +0000399
400/* --------- Operand, which can be reg or immediate only. --------- */
401
402PPC32RI* PPC32RI_Imm ( UInt imm32 ) {
403 PPC32RI* op = LibVEX_Alloc(sizeof(PPC32RI));
404 op->tag = Pri_Imm;
405 op->Pri.Imm.imm32 = imm32;
406 return op;
407}
408PPC32RI* PPC32RI_Reg ( HReg reg ) {
409 PPC32RI* op = LibVEX_Alloc(sizeof(PPC32RI));
410 op->tag = Pri_Reg;
411 op->Pri.Reg.reg = reg;
412 return op;
413}
414
415void ppPPC32RI ( PPC32RI* op ) {
416 switch (op->tag) {
cerionb85e8bb2005-02-16 08:54:33 +0000417 case Pri_Imm:
418 vex_printf("$0x%x", op->Pri.Imm.imm32);
419 return;
420 case Pri_Reg:
421 ppHRegPPC32(op->Pri.Reg.reg);
422 return;
423 default:
424 vpanic("ppPPC32RI");
cerioncd304492005-02-08 19:40:24 +0000425 }
426}
427
428/* An PPC32RI can only be used in a "read" context (what would it mean
429 to write or modify a literal?) and so we enumerate its registers
430 accordingly. */
431static void addRegUsage_PPC32RI ( HRegUsage* u, PPC32RI* op ) {
432 switch (op->tag) {
cerionb85e8bb2005-02-16 08:54:33 +0000433 case Pri_Imm:
434 return;
435 case Pri_Reg:
436 addHRegUse(u, HRmRead, op->Pri.Reg.reg);
437 return;
438 default:
439 vpanic("addRegUsage_PPC32RI");
cerioncd304492005-02-08 19:40:24 +0000440 }
441}
442
443static void mapRegs_PPC32RI ( HRegRemap* m, PPC32RI* op ) {
444 switch (op->tag) {
cerionb85e8bb2005-02-16 08:54:33 +0000445 case Pri_Imm:
446 return;
447 case Pri_Reg:
448 op->Pri.Reg.reg = lookupHRegRemap(m, op->Pri.Reg.reg);
449 return;
450 default:
451 vpanic("mapRegs_PPC32RI");
cerioncd304492005-02-08 19:40:24 +0000452 }
453}
454
455/* --------- Instructions. --------- */
456
cerionbcf8c3e2005-02-04 16:17:07 +0000457//.. HChar* showX86ScalarSz ( X86ScalarSz sz ) {
458//.. switch (sz) {
459//.. case Xss_16: return "w";
460//.. case Xss_32: return "l";
461//.. default: vpanic("showX86ScalarSz");
462//.. }
463//.. }
cerioncd304492005-02-08 19:40:24 +0000464
cerion2c49e032005-02-09 17:29:49 +0000465HChar* showPPC32UnaryOp ( PPC32UnaryOp op ) {
466 switch (op) {
cerionb85e8bb2005-02-16 08:54:33 +0000467 case Pun_NOT: return "not";
468 case Pun_NEG: return "neg";
469 case Pun_CLZ: return "cntlzw";
470 default: vpanic("showPPC32UnaryOp");
cerion2c49e032005-02-09 17:29:49 +0000471 }
472}
cerioncd304492005-02-08 19:40:24 +0000473
474HChar* showPPC32AluOp ( PPC32AluOp op ) {
475 switch (op) {
cerionb85e8bb2005-02-16 08:54:33 +0000476 case Palu_ADD: return "add";
cerionb85e8bb2005-02-16 08:54:33 +0000477// case Palu_ADC: return "adc";
478// case Palu_SBB: return "sbb";
479 case Palu_AND: return "and";
480 case Palu_OR: return "or";
481 case Palu_XOR: return "xor";
cerionb85e8bb2005-02-16 08:54:33 +0000482 default: vpanic("showPPC32AluOp");
cerioncd304492005-02-08 19:40:24 +0000483 }
484}
485
486HChar* showPPC32ShiftOp ( PPC32ShiftOp op ) {
487 switch (op) {
cerionb85e8bb2005-02-16 08:54:33 +0000488 case Psh_SHL: return "slw";
489 case Psh_SHR: return "srw";
490 case Psh_SAR: return "sraw";
491 case Psh_ROL: return "rlw";
492 default: vpanic("showPPC32ShiftOp");
cerioncd304492005-02-08 19:40:24 +0000493 }
494}
495
cerionab9132d2005-02-15 15:46:59 +0000496HChar* showPPC32CmpOp ( PPC32CmpOp op ) {
497 switch (op) {
cerionb85e8bb2005-02-16 08:54:33 +0000498 case Pcmp_U: return "cmpl";
499 case Pcmp_S: return "cmp";
500 default: vpanic("showPPC32CmpOp");
cerionab9132d2005-02-15 15:46:59 +0000501 }
502}
503
cerion094d1392005-06-20 13:45:57 +0000504HChar* showPPC32FpOp ( PPC32FpOp op ) {
505 switch (op) {
506 case Pfp_ADD: return "fadd";
507 case Pfp_SUB: return "fsub";
508 case Pfp_MUL: return "fmul";
509 case Pfp_DIV: return "fdiv";
510 case Pfp_SQRT: return "fsqrt";
511 case Pfp_ABS: return "fabs";
512 case Pfp_NEG: return "fneg";
513 case Pfp_MOV: return "fmr";
514 default: vpanic("showPPC32FpOp");
515 }
516}
cerioncd304492005-02-08 19:40:24 +0000517
cerionc3d8bdc2005-06-28 18:06:23 +0000518HChar* showPPC32AvOp ( PPC32AvOp op ) {
519 switch (op) {
cerion6b6f59e2005-06-28 20:59:18 +0000520
521 /* Unary */
522 case Pav_MOV: return "vmr"; /* Mov */
cerionc3d8bdc2005-06-28 18:06:23 +0000523
cerion6b6f59e2005-06-28 20:59:18 +0000524 case Pav_AND: return "vand"; /* Bitwise */
cerionc3d8bdc2005-06-28 18:06:23 +0000525 case Pav_OR: return "vor";
526 case Pav_XOR: return "vxor";
527 case Pav_NOT: return "vnot";
528
cerion6b6f59e2005-06-28 20:59:18 +0000529 case Pav_UNPCKH8S: return "vupkhsb"; /* Unpack */
cerionc3d8bdc2005-06-28 18:06:23 +0000530 case Pav_UNPCKH16S: return "vupkhsh";
531 case Pav_UNPCKL8S: return "vupklsb";
532 case Pav_UNPCKL16S: return "vupklsh";
533 case Pav_UNPCKHPIX: return "vupkhpx";
534 case Pav_UNPCKLPIX: return "vupklpx";
cerion6b6f59e2005-06-28 20:59:18 +0000535
536 /* Integer binary */
537 case Pav_ADDUM: return "vaddu_m"; // b,h,w
538 case Pav_ADDUS: return "vaddu_s"; // b,h,w
539 case Pav_ADDSS: return "vadds_s"; // b,h,w
cerionc3d8bdc2005-06-28 18:06:23 +0000540
cerion6b6f59e2005-06-28 20:59:18 +0000541 case Pav_SUBUM: return "vsubu_m"; // b,h,w
542 case Pav_SUBUS: return "vsubu_s"; // b,h,w
543 case Pav_SUBSS: return "vsubs_s"; // b,h,w
544
545 case Pav_OMULU: return "vmulou"; // b,h
546 case Pav_OMULS: return "vmulos"; // b,h
547 case Pav_EMULU: return "vmuleu"; // b,h
548 case Pav_EMULS: return "vmules"; // b,h
549
550 case Pav_AVGU: return "vavgu"; // b,h,w
551 case Pav_AVGS: return "vavgs"; // b,h,w
552
553 case Pav_MAXU: return "vmaxu"; // b,h,w
554 case Pav_MAXS: return "vmaxs"; // b,h,w
555
556 case Pav_MINU: return "vminu"; // b,h,w
557 case Pav_MINS: return "vmins"; // b,h,w
558
559 /* Compare (always affects CR field 6) */
560 case Pav_CMPEQU: return "vcmpequ"; // b,h,w
561 case Pav_CMPGTU: return "vcmpgtu"; // b,h,w
562 case Pav_CMPGTS: return "vcmpgts"; // b,h,w
563
564 /* Shift */
565 case Pav_SHL: return "vsl"; // ' ',b,h,w
566 case Pav_SHR: return "vsr"; // ' ',b,h,w
567 case Pav_SAR: return "vsra"; // b,h,w
568 case Pav_ROTL: return "vrl"; // b,h,w
569
570 /* Pack */
571 case Pav_PACKUUM: return "vpku_um"; // h,w
572 case Pav_PACKUUS: return "vpku_us"; // h,w
573 case Pav_PACKSUS: return "vpks_us"; // h,w
574 case Pav_PACKSSS: return "vpks_ss"; // h,w
575 case Pav_PACKPXL: return "vpkpx";
576
cerionc3d8bdc2005-06-28 18:06:23 +0000577 /* Merge */
cerion6b6f59e2005-06-28 20:59:18 +0000578 case Pav_MRGHI: return "vmrgh"; // b,h,w
579 case Pav_MRGLO: return "vmrgl"; // b,h,w
580
581
582 /* Floating Point Binary */
583 case Pav_ADDF: return "vaddfp";
584 case Pav_SUBF: return "vsubfp";
585 case Pav_MULF: return "vmaddfp";
586 case Pav_MAXF: return "vmaxfp";
587 case Pav_MINF: return "vminfp";
588 case Pav_CMPEQF: return "vcmpeqfp";
589 case Pav_CMPGTF: return "vcmpgtfp";
590 case Pav_CMPGEF: return "vcmpgefp";
cerionc3d8bdc2005-06-28 18:06:23 +0000591
592 default: vpanic("showPPC32AvOp");
593 }
594}
595
ceriona2f75882005-03-15 16:33:38 +0000596PPC32Instr* PPC32Instr_Alu32 ( PPC32AluOp op, HReg dst, HReg srcL, PPC32RI* srcR ) {
sewardj9a036bf2005-03-14 18:19:08 +0000597 PPC32Instr* i = LibVEX_Alloc(sizeof(PPC32Instr));
ceriona2f75882005-03-15 16:33:38 +0000598 if (srcR->tag == Pri_Imm)
599 vassert(srcR->Pri.Imm.imm32 < 0x10000);
cerioncd304492005-02-08 19:40:24 +0000600 i->tag = Pin_Alu32;
601 i->Pin.Alu32.op = op;
602 i->Pin.Alu32.dst = dst;
ceriona2f75882005-03-15 16:33:38 +0000603 i->Pin.Alu32.srcL = srcL;
604 i->Pin.Alu32.srcR = srcR;
cerioncd304492005-02-08 19:40:24 +0000605 return i;
606}
ceriona2f75882005-03-15 16:33:38 +0000607PPC32Instr* PPC32Instr_Sub32 ( HReg dst, PPC32RI* srcL, HReg srcR ) {
sewardj9a036bf2005-03-14 18:19:08 +0000608 PPC32Instr* i = LibVEX_Alloc(sizeof(PPC32Instr));
ceriona2f75882005-03-15 16:33:38 +0000609 if (srcL->tag == Pri_Imm)
610 vassert(srcL->Pri.Imm.imm32 < 0x10000);
cerion5e2527e2005-02-25 16:39:58 +0000611 i->tag = Pin_Sub32;
612 i->Pin.Sub32.dst = dst;
ceriona2f75882005-03-15 16:33:38 +0000613 i->Pin.Sub32.srcL = srcL;
614 i->Pin.Sub32.srcR = srcR;
cerion5e2527e2005-02-25 16:39:58 +0000615 return i;
616}
cerioncd304492005-02-08 19:40:24 +0000617PPC32Instr* PPC32Instr_Sh32 ( PPC32ShiftOp op, HReg dst, HReg src, PPC32RI* shft ) {
sewardj9a036bf2005-03-14 18:19:08 +0000618 PPC32Instr* i = LibVEX_Alloc(sizeof(PPC32Instr));
cerionab9132d2005-02-15 15:46:59 +0000619 if (op == Psh_SHL || op == Psh_SHR) // No imm versions for these.
620 vassert(shft->tag == Pri_Reg);
621 if (shft->tag == Pri_Imm)
622 vassert(shft->Pri.Imm.imm32 < 32);
cerioncd304492005-02-08 19:40:24 +0000623 i->tag = Pin_Sh32;
624 i->Pin.Sh32.op = op;
625 i->Pin.Sh32.dst = dst;
626 i->Pin.Sh32.src = src;
627 i->Pin.Sh32.shft = shft;
628 return i;
629}
ceriona2f75882005-03-15 16:33:38 +0000630PPC32Instr* PPC32Instr_Cmp32 ( PPC32CmpOp op, UInt crfD, HReg srcL, PPC32RI* srcR ) {
sewardj9a036bf2005-03-14 18:19:08 +0000631 PPC32Instr* i = LibVEX_Alloc(sizeof(PPC32Instr));
ceriona2f75882005-03-15 16:33:38 +0000632 if (srcR->tag == Pri_Imm)
633 vassert(srcR->Pri.Imm.imm32 < 0x10000);
cerionab9132d2005-02-15 15:46:59 +0000634 i->tag = Pin_Cmp32;
635 i->Pin.Cmp32.op = op;
636 i->Pin.Cmp32.crfD = crfD;
ceriona2f75882005-03-15 16:33:38 +0000637 i->Pin.Cmp32.srcL = srcL;
638 i->Pin.Cmp32.srcR = srcR;
cerion2c49e032005-02-09 17:29:49 +0000639 return i;
640}
cerione13bb312005-02-10 19:51:03 +0000641PPC32Instr* PPC32Instr_Unary32 ( PPC32UnaryOp op, HReg dst, HReg src ) {
cerion2c49e032005-02-09 17:29:49 +0000642 PPC32Instr* i = LibVEX_Alloc(sizeof(PPC32Instr));
643 i->tag = Pin_Unary32;
644 i->Pin.Unary32.op = op;
645 i->Pin.Unary32.dst = dst;
cerione13bb312005-02-10 19:51:03 +0000646 i->Pin.Unary32.src = src;
cerion2c49e032005-02-09 17:29:49 +0000647 return i;
648}
cerion92f5dc72005-02-10 16:11:35 +0000649PPC32Instr* PPC32Instr_MulL ( Bool syned, Bool word, HReg dst,
ceriona2f75882005-03-15 16:33:38 +0000650 HReg srcL, PPC32RI* srcR ) {
sewardj9a036bf2005-03-14 18:19:08 +0000651 PPC32Instr* i = LibVEX_Alloc(sizeof(PPC32Instr));
cerion98411db2005-02-16 14:14:49 +0000652 if (word == 1) { // high
ceriona2f75882005-03-15 16:33:38 +0000653 vassert(srcR->tag == Pri_Reg);
cerion98411db2005-02-16 14:14:49 +0000654 } else { // low
ceriona2f75882005-03-15 16:33:38 +0000655 if (srcR->tag == Pri_Imm) {
cerion98411db2005-02-16 14:14:49 +0000656 vassert(syned == True);
ceriona2f75882005-03-15 16:33:38 +0000657 vassert(srcR->Pri.Imm.imm32 < 0x10000);
cerion98411db2005-02-16 14:14:49 +0000658 }
659 }
cerion92f5dc72005-02-10 16:11:35 +0000660 i->tag = Pin_MulL;
661 i->Pin.MulL.syned = syned;
662 i->Pin.MulL.word = word;
cerionc0e707e2005-02-10 22:35:34 +0000663 i->Pin.MulL.dst = dst;
ceriona2f75882005-03-15 16:33:38 +0000664 i->Pin.MulL.srcL = srcL;
665 i->Pin.MulL.srcR = srcR;
cerion92f5dc72005-02-10 16:11:35 +0000666 return i;
667}
ceriona2f75882005-03-15 16:33:38 +0000668PPC32Instr* PPC32Instr_Div ( Bool syned, HReg dst, HReg srcL, HReg srcR ) {
sewardj9a036bf2005-03-14 18:19:08 +0000669 PPC32Instr* i = LibVEX_Alloc(sizeof(PPC32Instr));
cerionc0e707e2005-02-10 22:35:34 +0000670 i->tag = Pin_Div;
671 i->Pin.Div.syned = syned;
672 i->Pin.Div.dst = dst;
ceriona2f75882005-03-15 16:33:38 +0000673 i->Pin.Div.srcL = srcL;
674 i->Pin.Div.srcR = srcR;
cerionc0e707e2005-02-10 22:35:34 +0000675 return i;
676}
cerion2c49e032005-02-09 17:29:49 +0000677PPC32Instr* PPC32Instr_Call ( PPC32CondCode cond, Addr32 target, Int regparms ) {
678 PPC32Instr* i = LibVEX_Alloc(sizeof(PPC32Instr));
679 i->tag = Pin_Call;
680 i->Pin.Call.cond = cond;
681 i->Pin.Call.target = target;
682 i->Pin.Call.regparms = regparms;
683 vassert(regparms >= 0 && regparms < PPC32_N_REGPARMS);
684 return i;
685}
686PPC32Instr* PPC32Instr_Goto ( IRJumpKind jk, PPC32CondCode cond, PPC32RI* dst ) {
687 PPC32Instr* i = LibVEX_Alloc(sizeof(PPC32Instr));
688 i->tag = Pin_Goto;
689 i->Pin.Goto.cond = cond;
690 i->Pin.Goto.dst = dst;
691 i->Pin.Goto.jk = jk;
692 return i;
693}
cerionb536af92005-02-10 15:03:19 +0000694PPC32Instr* PPC32Instr_CMov32 ( PPC32CondCode cond, HReg dst, PPC32RI* src ) {
695 PPC32Instr* i = LibVEX_Alloc(sizeof(PPC32Instr));
696 i->tag = Pin_CMov32;
697 i->Pin.CMov32.cond = cond;
698 i->Pin.CMov32.src = src;
699 i->Pin.CMov32.dst = dst;
cerionab9132d2005-02-15 15:46:59 +0000700 vassert(cond.test != Pct_ALWAYS);
cerionb536af92005-02-10 15:03:19 +0000701 return i;
702}
cerion7cf8e4e2005-02-16 16:08:17 +0000703PPC32Instr* PPC32Instr_Load ( UChar sz, Bool syned,
704 HReg dst, PPC32AMode* src ) {
705 PPC32Instr* i = LibVEX_Alloc(sizeof(PPC32Instr));
706 i->tag = Pin_Load;
707 i->Pin.Load.sz = sz;
708 i->Pin.Load.syned = syned;
709 i->Pin.Load.src = src;
710 i->Pin.Load.dst = dst;
cerion2c49e032005-02-09 17:29:49 +0000711 vassert(sz == 1 || sz == 2 || sz == 4);
cerioncd304492005-02-08 19:40:24 +0000712 return i;
713}
714PPC32Instr* PPC32Instr_Store ( UChar sz, PPC32AMode* dst, HReg src ) {
715 PPC32Instr* i = LibVEX_Alloc(sizeof(PPC32Instr));
716 i->tag = Pin_Store;
717 i->Pin.Store.sz = sz;
718 i->Pin.Store.src = src;
719 i->Pin.Store.dst = dst;
720 vassert(sz == 1 || sz == 2 || sz == 4);
721 return i;
722}
cerionb536af92005-02-10 15:03:19 +0000723PPC32Instr* PPC32Instr_Set32 ( PPC32CondCode cond, HReg dst ) {
724 PPC32Instr* i = LibVEX_Alloc(sizeof(PPC32Instr));
725 i->tag = Pin_Set32;
726 i->Pin.Set32.cond = cond;
727 i->Pin.Set32.dst = dst;
728 return i;
729}
cerion98411db2005-02-16 14:14:49 +0000730PPC32Instr* PPC32Instr_MFence ( void )
cerion92f5dc72005-02-10 16:11:35 +0000731{
732 PPC32Instr* i = LibVEX_Alloc(sizeof(PPC32Instr));
733 i->tag = Pin_MFence;
cerion92f5dc72005-02-10 16:11:35 +0000734 return i;
735}
cerioncd304492005-02-08 19:40:24 +0000736
cerion094d1392005-06-20 13:45:57 +0000737PPC32Instr* PPC32Instr_FpUnary ( PPC32FpOp op, HReg dst, HReg src ) {
738 PPC32Instr* i = LibVEX_Alloc(sizeof(PPC32Instr));
739 i->tag = Pin_FpUnary;
740 i->Pin.FpUnary.op = op;
741 i->Pin.FpUnary.dst = dst;
742 i->Pin.FpUnary.src = src;
743 return i;
744}
745PPC32Instr* PPC32Instr_FpBinary ( PPC32FpOp op, HReg dst, HReg srcL, HReg srcR ) {
746 PPC32Instr* i = LibVEX_Alloc(sizeof(PPC32Instr));
747 i->tag = Pin_FpBinary;
748 i->Pin.FpBinary.op = op;
749 i->Pin.FpBinary.dst = dst;
750 i->Pin.FpBinary.srcL = srcL;
751 i->Pin.FpBinary.srcR = srcR;
752 return i;
753}
754PPC32Instr* PPC32Instr_FpLdSt ( Bool isLoad, UChar sz, HReg reg, PPC32AMode* addr ) {
755 PPC32Instr* i = LibVEX_Alloc(sizeof(PPC32Instr));
756 i->tag = Pin_FpLdSt;
757 i->Pin.FpLdSt.isLoad = isLoad;
758 i->Pin.FpLdSt.sz = sz;
759 i->Pin.FpLdSt.reg = reg;
760 i->Pin.FpLdSt.addr = addr;
761 vassert(sz == 4 || sz == 8);
762 return i;
763}
764PPC32Instr* PPC32Instr_FpF64toF32 ( HReg dst, HReg src ) {
765 PPC32Instr* i = LibVEX_Alloc(sizeof(PPC32Instr));
766 i->tag = Pin_FpF64toF32;
767 i->Pin.FpF64toF32.dst = dst;
768 i->Pin.FpF64toF32.src = src;
769 return i;
770}
771PPC32Instr* PPC32Instr_FpF64toI32 ( HReg dst, HReg src ) {
772 PPC32Instr* i = LibVEX_Alloc(sizeof(PPC32Instr));
773 i->tag = Pin_FpF64toI32;
774 i->Pin.FpF64toI32.dst = dst;
775 i->Pin.FpF64toI32.src = src;
776 return i;
777}
778PPC32Instr* PPC32Instr_FpCMov ( PPC32CondCode cond, HReg dst, HReg src ) {
779 PPC32Instr* i = LibVEX_Alloc(sizeof(PPC32Instr));
780 i->tag = Pin_FpCMov;
781 i->Pin.FpCMov.cond = cond;
782 i->Pin.FpCMov.dst = dst;
783 i->Pin.FpCMov.src = src;
784 vassert(cond.test != Pct_ALWAYS);
785 return i;
786}
787PPC32Instr* PPC32Instr_FpLdFPSCR ( HReg src ) {
788 PPC32Instr* i = LibVEX_Alloc(sizeof(PPC32Instr));
789 i->tag = Pin_FpLdFPSCR;
790 i->Pin.FpLdFPSCR.src = src;
791 return i;
792}
793PPC32Instr* PPC32Instr_FpCmp ( HReg dst, HReg srcL, HReg srcR ) {
794 PPC32Instr* i = LibVEX_Alloc(sizeof(PPC32Instr));
795 i->tag = Pin_FpCmp;
796 i->Pin.FpCmp.dst = dst;
797 i->Pin.FpCmp.srcL = srcL;
798 i->Pin.FpCmp.srcR = srcR;
799 return i;
800}
cerionbcf8c3e2005-02-04 16:17:07 +0000801
cerion7f000af2005-02-22 20:36:49 +0000802/* Read/Write Link Register */
cerionc3d8bdc2005-06-28 18:06:23 +0000803PPC32Instr* PPC32Instr_RdWrLR ( Bool wrLR, HReg gpr ) {
cerion7f000af2005-02-22 20:36:49 +0000804 PPC32Instr* i = LibVEX_Alloc(sizeof(PPC32Instr));
805 i->tag = Pin_RdWrLR;
806 i->Pin.RdWrLR.wrLR = wrLR;
807 i->Pin.RdWrLR.gpr = gpr;
808 return i;
809}
810
cerionc3d8bdc2005-06-28 18:06:23 +0000811/* AltiVec */
812PPC32Instr* PPC32Instr_AvLdSt ( Bool isLoad, UChar sz, HReg reg, PPC32AMode* addr ) {
813 PPC32Instr* i = LibVEX_Alloc(sizeof(PPC32Instr));
814 i->tag = Pin_AvLdSt;
815 i->Pin.AvLdSt.isLoad = isLoad;
816 i->Pin.AvLdSt.sz = sz;
817 i->Pin.AvLdSt.reg = reg;
818 i->Pin.AvLdSt.addr = addr;
819 return i;
820}
821PPC32Instr* PPC32Instr_AvUnary ( PPC32AvOp op, HReg dst, HReg src ) {
822 PPC32Instr* i = LibVEX_Alloc(sizeof(PPC32Instr));
823 i->tag = Pin_AvUnary;
824 i->Pin.AvUnary.op = op;
825 i->Pin.AvUnary.dst = dst;
826 i->Pin.AvUnary.src = src;
827 return i;
828}
829PPC32Instr* PPC32Instr_AvBinary ( PPC32AvOp op, HReg dst, HReg srcL, HReg srcR ) {
830 PPC32Instr* i = LibVEX_Alloc(sizeof(PPC32Instr));
831 i->tag = Pin_AvBinary;
832 i->Pin.AvBinary.op = op;
833 i->Pin.AvBinary.dst = dst;
834 i->Pin.AvBinary.srcL = srcL;
835 i->Pin.AvBinary.srcR = srcR;
836 return i;
837}
cerion6b6f59e2005-06-28 20:59:18 +0000838PPC32Instr* PPC32Instr_AvBin8x16 ( PPC32AvOp op, HReg dst, HReg srcL, HReg srcR ) {
839 PPC32Instr* i = LibVEX_Alloc(sizeof(PPC32Instr));
840 i->tag = Pin_AvBin8x16;
841 i->Pin.AvBin8x16.op = op;
842 i->Pin.AvBin8x16.dst = dst;
843 i->Pin.AvBin8x16.srcL = srcL;
844 i->Pin.AvBin8x16.srcR = srcR;
845 return i;
846}
847PPC32Instr* PPC32Instr_AvBin16x8 ( PPC32AvOp op, HReg dst, HReg srcL, HReg srcR ) {
848 PPC32Instr* i = LibVEX_Alloc(sizeof(PPC32Instr));
849 i->tag = Pin_AvBin16x8;
850 i->Pin.AvBin16x8.op = op;
851 i->Pin.AvBin16x8.dst = dst;
852 i->Pin.AvBin16x8.srcL = srcL;
853 i->Pin.AvBin16x8.srcR = srcR;
854 return i;
855}
856PPC32Instr* PPC32Instr_AvBin32x4 ( PPC32AvOp op, HReg dst, HReg srcL, HReg srcR ) {
857 PPC32Instr* i = LibVEX_Alloc(sizeof(PPC32Instr));
858 i->tag = Pin_AvBin32x4;
859 i->Pin.AvBin32x4.op = op;
860 i->Pin.AvBin32x4.dst = dst;
861 i->Pin.AvBin32x4.srcL = srcL;
862 i->Pin.AvBin32x4.srcR = srcR;
863 return i;
864}
865PPC32Instr* PPC32Instr_AvBin32Fx4 ( PPC32AvOp op, HReg dst, HReg srcL, HReg srcR ) {
866 PPC32Instr* i = LibVEX_Alloc(sizeof(PPC32Instr));
867 i->tag = Pin_AvBin32Fx4;
868 i->Pin.AvBin32Fx4.op = op;
869 i->Pin.AvBin32Fx4.dst = dst;
870 i->Pin.AvBin32Fx4.srcL = srcL;
871 i->Pin.AvBin32Fx4.srcR = srcR;
872 return i;
873}
cerionc3d8bdc2005-06-28 18:06:23 +0000874PPC32Instr* PPC32Instr_AvPerm ( HReg ctl, HReg dst, HReg srcL, HReg srcR ) {
875 PPC32Instr* i = LibVEX_Alloc(sizeof(PPC32Instr));
876 i->tag = Pin_AvPerm;
877 i->Pin.AvPerm.ctl = ctl;
878 i->Pin.AvPerm.dst = dst;
879 i->Pin.AvPerm.srcL = srcL;
880 i->Pin.AvPerm.srcR = srcR;
881 return i;
882}
883PPC32Instr* PPC32Instr_AvSel ( HReg ctl, HReg dst, HReg srcL, HReg srcR ) {
884 PPC32Instr* i = LibVEX_Alloc(sizeof(PPC32Instr));
885 i->tag = Pin_AvSel;
886 i->Pin.AvSel.ctl = ctl;
887 i->Pin.AvSel.dst = dst;
888 i->Pin.AvSel.srcL = srcL;
889 i->Pin.AvSel.srcR = srcR;
890 return i;
891}
892PPC32Instr* PPC32Instr_AvShlDbl ( UChar shift, HReg dst, HReg srcL, HReg srcR ) {
893 PPC32Instr* i = LibVEX_Alloc(sizeof(PPC32Instr));
894 i->tag = Pin_AvShlDbl;
895 i->Pin.AvShlDbl.shift = shift;
896 i->Pin.AvShlDbl.dst = dst;
897 i->Pin.AvShlDbl.srcL = srcL;
898 i->Pin.AvShlDbl.srcR = srcR;
899 return i;
900}
901PPC32Instr* PPC32Instr_AvSplat ( UChar sz, HReg dst, PPC32RI* src ) {
902 PPC32Instr* i = LibVEX_Alloc(sizeof(PPC32Instr));
903 i->tag = Pin_AvSplat;
904 i->Pin.AvSplat.sz = sz;
905 i->Pin.AvSplat.dst = dst;
906 i->Pin.AvSplat.src = src;
907 return i;
908}
cerion6b6f59e2005-06-28 20:59:18 +0000909PPC32Instr* PPC32Instr_AvCMov ( PPC32CondCode cond, HReg dst, HReg src ) {
910 PPC32Instr* i = LibVEX_Alloc(sizeof(PPC32Instr));
911 i->tag = Pin_AvCMov;
912 i->Pin.AvCMov.cond = cond;
913 i->Pin.AvCMov.dst = dst;
914 i->Pin.AvCMov.src = src;
915 vassert(cond.test != Pct_ALWAYS);
916 return i;
917}
cerionc3d8bdc2005-06-28 18:06:23 +0000918PPC32Instr* PPC32Instr_AvLdVSCR ( HReg src ) {
919 PPC32Instr* i = LibVEX_Alloc(sizeof(PPC32Instr));
920 i->tag = Pin_AvLdVSCR;
921 i->Pin.AvLdVSCR.src = src;
922 return i;
923}
924
cerion9e263e32005-03-03 17:21:51 +0000925
926/* Pretty Print instructions */
927static void ppLoadImm ( HReg dst, UInt imm ) {
928 if (imm < 0x10000) {
929 vex_printf("li ");
930 ppHRegPPC32(dst);
931 vex_printf(",0x%x", imm);
932 } else {
933 vex_printf("lis ");
934 ppHRegPPC32(dst);
935 vex_printf(",0x%x ; ", imm >> 16);
936 vex_printf("ori ");
937 ppHRegPPC32(dst);
938 vex_printf(",");
939 ppHRegPPC32(dst);
940 vex_printf(",0x%x", imm & 0xFFFF);
941 }
942}
943
944static void ppMovReg ( HReg dst, HReg src ) {
945 if (hregNumber(dst) != hregNumber(src)) {
946 vex_printf("mr ");
947 ppHRegPPC32(dst);
948 vex_printf(",");
949 ppHRegPPC32(src);
950 }
951}
952
cerionbcf8c3e2005-02-04 16:17:07 +0000953void ppPPC32Instr ( PPC32Instr* i )
954{
955 switch (i->tag) {
cerionb85e8bb2005-02-16 08:54:33 +0000956 case Pin_Alu32:
957 if (i->Pin.Alu32.op == Palu_OR && // or Rd,Rs,Rs == mr Rd,Rs
ceriona2f75882005-03-15 16:33:38 +0000958 i->Pin.Alu32.srcR->tag == Pri_Reg &&
959 i->Pin.Alu32.srcR->Pri.Reg.reg == i->Pin.Alu32.srcL) {
cerionb85e8bb2005-02-16 08:54:33 +0000960 vex_printf("mr ");
961 ppHRegPPC32(i->Pin.Alu32.dst);
cerioncd304492005-02-08 19:40:24 +0000962 vex_printf(",");
ceriona2f75882005-03-15 16:33:38 +0000963 ppHRegPPC32(i->Pin.Alu32.srcL);
cerioncd304492005-02-08 19:40:24 +0000964 return;
cerionb85e8bb2005-02-16 08:54:33 +0000965 }
cerion9e263e32005-03-03 17:21:51 +0000966 if (i->Pin.Alu32.op == Palu_ADD && // add rD,r0,val == li rD,val
ceriona2f75882005-03-15 16:33:38 +0000967 i->Pin.Alu32.srcL == hregPPC32_GPR0() &&
968 i->Pin.Alu32.srcR->tag == Pri_Imm) {
cerionb85e8bb2005-02-16 08:54:33 +0000969 vex_printf("li ");
970 ppHRegPPC32(i->Pin.Alu32.dst);
971 vex_printf(",");
ceriona2f75882005-03-15 16:33:38 +0000972 ppPPC32RI(i->Pin.Alu32.srcR);
cerionb85e8bb2005-02-16 08:54:33 +0000973 return;
974 }
cerionb8c3b7f2005-03-01 20:27:49 +0000975 if (i->Pin.Alu32.op == Palu_AND && // 'andi.' - always has the '.'
ceriona2f75882005-03-15 16:33:38 +0000976 i->Pin.Alu32.srcR->tag == Pri_Imm) {
cerionb8c3b7f2005-03-01 20:27:49 +0000977 vex_printf("andi. ");
978 ppHRegPPC32(i->Pin.Alu32.dst);
979 vex_printf(",");
ceriona2f75882005-03-15 16:33:38 +0000980 ppHRegPPC32(i->Pin.Alu32.srcL);
cerionb8c3b7f2005-03-01 20:27:49 +0000981 vex_printf(",");
ceriona2f75882005-03-15 16:33:38 +0000982 ppPPC32RI(i->Pin.Alu32.srcR);
cerionb8c3b7f2005-03-01 20:27:49 +0000983 return;
984 }
cerionb85e8bb2005-02-16 08:54:33 +0000985 vex_printf("%s%s ", showPPC32AluOp(i->Pin.Alu32.op),
ceriona2f75882005-03-15 16:33:38 +0000986 i->Pin.Alu32.srcR->tag == Pri_Imm ? "i" : "" );
cerionb85e8bb2005-02-16 08:54:33 +0000987 ppHRegPPC32(i->Pin.Alu32.dst);
988 vex_printf(",");
ceriona2f75882005-03-15 16:33:38 +0000989 ppHRegPPC32(i->Pin.Alu32.srcL);
cerionb85e8bb2005-02-16 08:54:33 +0000990 vex_printf(",");
ceriona2f75882005-03-15 16:33:38 +0000991 ppPPC32RI(i->Pin.Alu32.srcR);
cerionb85e8bb2005-02-16 08:54:33 +0000992 return;
cerion5e2527e2005-02-25 16:39:58 +0000993 case Pin_Sub32:
ceriona2f75882005-03-15 16:33:38 +0000994 vex_printf("subf%s ", i->Pin.Sub32.srcL->tag == Pri_Imm ? "ic" : "" );
cerion5e2527e2005-02-25 16:39:58 +0000995 ppHRegPPC32(i->Pin.Sub32.dst);
996 vex_printf(",");
ceriona2f75882005-03-15 16:33:38 +0000997 ppHRegPPC32(i->Pin.Sub32.srcR); // yes, order is right :-)
cerion5e2527e2005-02-25 16:39:58 +0000998 vex_printf(",");
ceriona2f75882005-03-15 16:33:38 +0000999 ppPPC32RI(i->Pin.Sub32.srcL);
cerion5e2527e2005-02-25 16:39:58 +00001000 return;
cerionb85e8bb2005-02-16 08:54:33 +00001001 case Pin_Sh32:
1002 vex_printf("%s%s ", showPPC32ShiftOp(i->Pin.Sh32.op),
1003 i->Pin.Sh32.shft->tag == Pri_Imm ? "i" : "" );
1004 ppHRegPPC32(i->Pin.Sh32.dst);
1005 vex_printf(",");
1006 ppHRegPPC32(i->Pin.Sh32.src);
1007 vex_printf(",");
1008 ppPPC32RI(i->Pin.Sh32.shft);
1009 return;
cerionb85e8bb2005-02-16 08:54:33 +00001010 case Pin_Cmp32:
sewardj428fabd2005-03-21 03:11:17 +00001011 vex_printf("%s%s %%crf%u,", showPPC32CmpOp(i->Pin.Cmp32.op),
ceriona2f75882005-03-15 16:33:38 +00001012 i->Pin.Cmp32.srcR->tag == Pri_Imm ? "i" : "",
cerion8c51ed42005-02-22 11:16:54 +00001013 (7 - i->Pin.Cmp32.crfD));
ceriona2f75882005-03-15 16:33:38 +00001014 ppHRegPPC32(i->Pin.Cmp32.srcL);
cerionb85e8bb2005-02-16 08:54:33 +00001015 vex_printf(",");
ceriona2f75882005-03-15 16:33:38 +00001016 ppPPC32RI(i->Pin.Cmp32.srcR);
cerionb85e8bb2005-02-16 08:54:33 +00001017 return;
1018 case Pin_Unary32:
1019 vex_printf("%s ", showPPC32UnaryOp(i->Pin.Unary32.op));
1020 ppHRegPPC32(i->Pin.Unary32.dst);
1021 vex_printf(",");
1022 ppHRegPPC32(i->Pin.Unary32.src);
1023 return;
1024 case Pin_MulL:
ceriona2f75882005-03-15 16:33:38 +00001025 if (i->Pin.MulL.srcR->tag == Pri_Imm) {
cerionb85e8bb2005-02-16 08:54:33 +00001026 vex_printf("mulli ");
1027 } else {
1028 vex_printf("mul%s%c ",
1029 i->Pin.MulL.word ? "hw" : "lw",
1030 i->Pin.MulL.syned ? 's' : 'u');
1031 }
1032 ppHRegPPC32(i->Pin.MulL.dst);
1033 vex_printf(",");
ceriona2f75882005-03-15 16:33:38 +00001034 ppHRegPPC32(i->Pin.MulL.srcL);
cerionb85e8bb2005-02-16 08:54:33 +00001035 vex_printf(",");
ceriona2f75882005-03-15 16:33:38 +00001036 ppPPC32RI(i->Pin.MulL.srcR);
cerionb85e8bb2005-02-16 08:54:33 +00001037 return;
1038 case Pin_Div:
1039 vex_printf("divw%s ",
1040 i->Pin.Div.syned ? "" : "u");
cerion33aa6da2005-02-16 10:25:26 +00001041 ppHRegPPC32(i->Pin.Div.dst);
cerionb85e8bb2005-02-16 08:54:33 +00001042 vex_printf(",");
ceriona2f75882005-03-15 16:33:38 +00001043 ppHRegPPC32(i->Pin.Div.srcL);
cerionb85e8bb2005-02-16 08:54:33 +00001044 vex_printf(",");
ceriona2f75882005-03-15 16:33:38 +00001045 ppHRegPPC32(i->Pin.Div.srcR);
cerionb85e8bb2005-02-16 08:54:33 +00001046 return;
cerionb85e8bb2005-02-16 08:54:33 +00001047 case Pin_Call:
cerion8c51ed42005-02-22 11:16:54 +00001048 vex_printf("call: ");
1049 if (i->Pin.Call.cond.test != Pct_ALWAYS) {
1050 vex_printf("if (%%crf0.%s) ", showPPC32CondCode(i->Pin.Call.cond));
1051 }
1052 vex_printf("{ ");
cerion9e263e32005-03-03 17:21:51 +00001053 ppLoadImm(hregPPC32_GPR12(), i->Pin.Call.target);
cerion9762bbf2005-06-23 08:44:52 +00001054 vex_printf(" ; mtctr r12 ; bctrl [regparms=%d] }",i->Pin.Call.regparms);
cerionb85e8bb2005-02-16 08:54:33 +00001055 break;
1056 case Pin_Goto:
cerion33aa6da2005-02-16 10:25:26 +00001057 vex_printf("goto: ");
cerionb85e8bb2005-02-16 08:54:33 +00001058 if (i->Pin.Goto.cond.test != Pct_ALWAYS) {
cerion8c51ed42005-02-22 11:16:54 +00001059 vex_printf("if (%%crf0.%s) ", showPPC32CondCode(i->Pin.Goto.cond));
cerionb85e8bb2005-02-16 08:54:33 +00001060 }
cerion8c51ed42005-02-22 11:16:54 +00001061 vex_printf("{ ");
cerionb85e8bb2005-02-16 08:54:33 +00001062 if (i->Pin.Goto.jk != Ijk_Boring) {
cerion9e263e32005-03-03 17:21:51 +00001063 vex_printf("li %%r31,$");
cerionb85e8bb2005-02-16 08:54:33 +00001064 ppIRJumpKind(i->Pin.Goto.jk);
1065 vex_printf(" ; ");
1066 }
cerione97e1062005-02-21 15:09:19 +00001067 if (i->Pin.Goto.dst->tag == Pri_Imm) {
cerion9e263e32005-03-03 17:21:51 +00001068 ppLoadImm(hregPPC32_GPR3(), i->Pin.Goto.dst->Pri.Imm.imm32);
cerione97e1062005-02-21 15:09:19 +00001069 } else {
cerion9e263e32005-03-03 17:21:51 +00001070 ppMovReg(hregPPC32_GPR3(), i->Pin.Goto.dst->Pri.Reg.reg);
cerione97e1062005-02-21 15:09:19 +00001071 }
cerion9e263e32005-03-03 17:21:51 +00001072 vex_printf(" ; blr }");
cerionb85e8bb2005-02-16 08:54:33 +00001073 return;
1074 case Pin_CMov32:
cerionb85e8bb2005-02-16 08:54:33 +00001075 vex_printf("cmov32 (%s) ", showPPC32CondCode(i->Pin.CMov32.cond));
1076 ppHRegPPC32(i->Pin.CMov32.dst);
1077 vex_printf(",");
1078 ppPPC32RI(i->Pin.CMov32.src);
cerion8c51ed42005-02-22 11:16:54 +00001079 vex_printf(": ");
1080 if (i->Pin.CMov32.cond.test != Pct_ALWAYS) {
1081 vex_printf("if (%%crf0.%s) ", showPPC32CondCode(i->Pin.CMov32.cond));
1082 }
1083 vex_printf("{ ");
1084 if (i->Pin.CMov32.src->tag == Pri_Imm) {
cerion9e263e32005-03-03 17:21:51 +00001085 ppLoadImm(i->Pin.CMov32.dst, i->Pin.CMov32.src->Pri.Imm.imm32);
cerion8c51ed42005-02-22 11:16:54 +00001086 } else {
cerion9e263e32005-03-03 17:21:51 +00001087 ppMovReg(i->Pin.CMov32.dst, i->Pin.CMov32.src->Pri.Reg.reg);
cerion8c51ed42005-02-22 11:16:54 +00001088 }
1089 vex_printf(" }");
cerionb85e8bb2005-02-16 08:54:33 +00001090 return;
cerion7cf8e4e2005-02-16 16:08:17 +00001091 case Pin_Load: {
1092 UChar sz = i->Pin.Load.sz;
1093 Bool syned = i->Pin.Load.syned;
sewardj428fabd2005-03-21 03:11:17 +00001094 Bool idxd = toBool(i->Pin.Load.src->tag == Pam_RR);
cerion7cf8e4e2005-02-16 16:08:17 +00001095 vex_printf("l%c%c%s ",
cerionb85e8bb2005-02-16 08:54:33 +00001096 (sz==1) ? 'b' : (sz==2 ? 'h' : 'w'),
1097 syned ? 'a' : 'z',
cerionb85e8bb2005-02-16 08:54:33 +00001098 idxd ? "x" : "" );
cerion7cf8e4e2005-02-16 16:08:17 +00001099 ppHRegPPC32(i->Pin.Load.dst);
cerionb85e8bb2005-02-16 08:54:33 +00001100 vex_printf(",");
cerion7cf8e4e2005-02-16 16:08:17 +00001101 ppPPC32AMode(i->Pin.Load.src);
cerionb85e8bb2005-02-16 08:54:33 +00001102 return;
1103 }
1104 case Pin_Store: {
1105 UChar sz = i->Pin.Store.sz;
sewardj428fabd2005-03-21 03:11:17 +00001106 Bool idxd = toBool(i->Pin.Store.dst->tag == Pam_RR);
cerion7cf8e4e2005-02-16 16:08:17 +00001107 vex_printf("st%c%s ",
cerionb85e8bb2005-02-16 08:54:33 +00001108 (sz==1) ? 'b' : (sz==2 ? 'h' : 'w'),
cerionb85e8bb2005-02-16 08:54:33 +00001109 idxd ? "x" : "" );
1110 ppHRegPPC32(i->Pin.Store.src);
1111 vex_printf(",");
1112 ppPPC32AMode(i->Pin.Store.dst);
1113 return;
1114 }
cerionf9d6e222005-02-23 18:21:31 +00001115 case Pin_Set32: {
1116 PPC32CondCode cc = i->Pin.Set32.cond;
1117 vex_printf("set32 (%s),", showPPC32CondCode(cc));
cerionb85e8bb2005-02-16 08:54:33 +00001118 ppHRegPPC32(i->Pin.Set32.dst);
cerionf9d6e222005-02-23 18:21:31 +00001119 if (cc.test == Pct_ALWAYS) {
1120 vex_printf(": { li ");
1121 ppHRegPPC32(i->Pin.Set32.dst);
1122 vex_printf(",1 }");
1123 } else {
1124 vex_printf(": { mfcr r0 ; rlwinm ");
1125 ppHRegPPC32(i->Pin.Set32.dst);
sewardj428fabd2005-03-21 03:11:17 +00001126 vex_printf(",r0,%u,31,31", cc.flag+1);
cerionf9d6e222005-02-23 18:21:31 +00001127 if (cc.test == Pct_FALSE) {
1128 vex_printf("; xori ");
1129 ppHRegPPC32(i->Pin.Set32.dst);
1130 vex_printf(",");
1131 ppHRegPPC32(i->Pin.Set32.dst);
1132 vex_printf("1");
1133 }
1134 vex_printf(" }");
1135 }
cerionb85e8bb2005-02-16 08:54:33 +00001136 return;
cerionf9d6e222005-02-23 18:21:31 +00001137 }
cerionb85e8bb2005-02-16 08:54:33 +00001138 case Pin_MFence:
cerion98411db2005-02-16 14:14:49 +00001139 vex_printf("mfence (=sync)");
cerionb85e8bb2005-02-16 08:54:33 +00001140 return;
cerion094d1392005-06-20 13:45:57 +00001141
1142 case Pin_FpUnary:
1143 vex_printf("%s ", showPPC32FpOp(i->Pin.FpUnary.op));
1144 ppHRegPPC32(i->Pin.FpUnary.dst);
1145 vex_printf(",");
1146 ppHRegPPC32(i->Pin.FpUnary.src);
1147 return;
1148 case Pin_FpBinary:
1149 vex_printf("%s ", showPPC32FpOp(i->Pin.FpBinary.op));
1150 ppHRegPPC32(i->Pin.FpBinary.dst);
1151 vex_printf(",");
1152 ppHRegPPC32(i->Pin.FpBinary.srcL);
1153 vex_printf(",");
1154 ppHRegPPC32(i->Pin.FpBinary.srcR);
1155 return;
1156 case Pin_FpLdSt: {
1157 UChar sz = i->Pin.FpLdSt.sz;
1158 Bool idxd = toBool(i->Pin.FpLdSt.addr->tag == Pam_RR);
1159 if (i->Pin.FpLdSt.isLoad) {
1160 vex_printf("lf%c%s ",
1161 (sz==4 ? 's' : 'd'),
1162 idxd ? "x" : "" );
1163 ppHRegPPC32(i->Pin.FpLdSt.reg);
1164 vex_printf(",");
1165 ppPPC32AMode(i->Pin.FpLdSt.addr);
1166 } else {
1167 vex_printf("stf%c%s ",
1168 (sz==4 ? 's' : 'd'),
1169 idxd ? "x" : "" );
1170 ppHRegPPC32(i->Pin.FpLdSt.reg);
1171 vex_printf(",");
1172 ppPPC32AMode(i->Pin.FpLdSt.addr);
1173 }
1174 return;
1175 }
1176 case Pin_FpF64toF32:
1177 vex_printf("frsp ");
1178 ppHRegPPC32(i->Pin.FpF64toF32.dst);
1179 vex_printf(",");
1180 ppHRegPPC32(i->Pin.FpF64toF32.src);
1181 return;
1182 case Pin_FpF64toI32:
1183 vex_printf("fctiw %%fr7,");
1184 ppHRegPPC32(i->Pin.FpF64toI32.src);
1185 vex_printf("; stfiwx %%fr7,%%r0,%%r1");
1186 vex_printf("; lwzx ");
1187 ppHRegPPC32(i->Pin.FpF64toI32.dst);
1188 vex_printf(",%%r0,%%r1");
1189 return;
1190 case Pin_FpCMov:
1191 vex_printf("fpcmov (%s) ", showPPC32CondCode(i->Pin.FpCMov.cond));
1192 ppHRegPPC32(i->Pin.FpCMov.dst);
1193 vex_printf(",");
1194 ppHRegPPC32(i->Pin.FpCMov.src);
1195 vex_printf(": ");
1196 vex_printf("if (fr_dst != fr_src) { ");
1197 if (i->Pin.FpCMov.cond.test != Pct_ALWAYS) {
1198 vex_printf("if (%%crf0.%s) { ", showPPC32CondCode(i->Pin.FpCMov.cond));
1199 }
1200 vex_printf("fmr ");
1201 ppHRegPPC32(i->Pin.FpCMov.dst);
1202 vex_printf(",");
1203 ppHRegPPC32(i->Pin.FpCMov.src);
1204 if (i->Pin.FpCMov.cond.test != Pct_ALWAYS)
1205 vex_printf(" }");
1206 vex_printf(" }");
1207 return;
1208 case Pin_FpLdFPSCR:
1209 vex_printf("mtfsf 0xFF,");
1210 ppHRegPPC32(i->Pin.FpLdFPSCR.src);
1211 return;
1212 case Pin_FpCmp:
1213 vex_printf("fcmpo %%crf1,");
1214 ppHRegPPC32(i->Pin.FpCmp.srcL);
1215 vex_printf(",");
1216 ppHRegPPC32(i->Pin.FpCmp.srcR);
1217 vex_printf("; mfcr ");
1218 ppHRegPPC32(i->Pin.FpCmp.dst);
1219 vex_printf("; rlwinm ");
1220 ppHRegPPC32(i->Pin.FpCmp.dst);
1221 vex_printf(",");
1222 ppHRegPPC32(i->Pin.FpCmp.dst);
1223 vex_printf(",8,28,31");
1224 return;
cerionbcf8c3e2005-02-04 16:17:07 +00001225
cerion7f000af2005-02-22 20:36:49 +00001226 case Pin_RdWrLR:
1227 vex_printf("%s ", i->Pin.RdWrLR.wrLR ? "mtlr" : "mflr");
1228 ppHRegPPC32(i->Pin.RdWrLR.gpr);
1229 return;
1230
cerionc3d8bdc2005-06-28 18:06:23 +00001231 case Pin_AvLdSt: {
1232 UChar sz = i->Pin.AvLdSt.sz;
cerionc3d8bdc2005-06-28 18:06:23 +00001233 if (i->Pin.AvLdSt.addr->tag == Pam_IR) {
cerionc3d8bdc2005-06-28 18:06:23 +00001234 ppLoadImm(hregPPC32_GPR30(), i->Pin.AvLdSt.addr->Pam.RR.index);
cerion01713102005-06-29 19:05:08 +00001235 vex_printf(" ; ");
cerionc3d8bdc2005-06-28 18:06:23 +00001236 }
cerion01713102005-06-29 19:05:08 +00001237 if (i->Pin.AvLdSt.isLoad)
cerion91c62fd2005-06-29 07:59:18 +00001238 vex_printf("lv%sx ", sz==8 ? "eb" : sz==16 ? "eh" : sz==32 ? "ew" : "");
cerion01713102005-06-29 19:05:08 +00001239 else
cerion91c62fd2005-06-29 07:59:18 +00001240 vex_printf("stv%sx ", sz==8 ? "eb" : sz==16 ? "eh" : sz==32 ? "ew" : "");
cerion01713102005-06-29 19:05:08 +00001241 ppHRegPPC32(i->Pin.AvLdSt.reg);
1242 vex_printf(",");
1243 if (i->Pin.AvLdSt.addr->tag == Pam_IR)
1244 vex_printf("%%r30");
1245 else
1246 ppHRegPPC32(i->Pin.AvLdSt.addr->Pam.RR.index);
1247 vex_printf(",");
1248 ppHRegPPC32(i->Pin.AvLdSt.addr->Pam.RR.base);
cerionc3d8bdc2005-06-28 18:06:23 +00001249 return;
1250 }
1251 case Pin_AvUnary:
1252 vex_printf("%s ", showPPC32AvOp(i->Pin.AvUnary.op));
1253 ppHRegPPC32(i->Pin.AvUnary.dst);
1254 vex_printf(",");
1255 ppHRegPPC32(i->Pin.AvUnary.src);
1256 return;
1257 case Pin_AvBinary:
1258 vex_printf("%s ", showPPC32AvOp(i->Pin.AvBinary.op));
1259 ppHRegPPC32(i->Pin.AvBinary.dst);
1260 vex_printf(",");
1261 ppHRegPPC32(i->Pin.AvBinary.srcL);
1262 vex_printf(",");
1263 ppHRegPPC32(i->Pin.AvBinary.srcR);
1264 return;
cerion6b6f59e2005-06-28 20:59:18 +00001265 case Pin_AvBin8x16:
1266 vex_printf("%s(b) ", showPPC32AvOp(i->Pin.AvBin8x16.op));
1267 ppHRegPPC32(i->Pin.AvBin8x16.dst);
1268 vex_printf(",");
1269 ppHRegPPC32(i->Pin.AvBin8x16.srcL);
1270 vex_printf(",");
1271 ppHRegPPC32(i->Pin.AvBin8x16.srcR);
1272 return;
1273 case Pin_AvBin16x8:
1274 vex_printf("%s(h) ", showPPC32AvOp(i->Pin.AvBin16x8.op));
1275 ppHRegPPC32(i->Pin.AvBin16x8.dst);
1276 vex_printf(",");
1277 ppHRegPPC32(i->Pin.AvBin16x8.srcL);
1278 vex_printf(",");
1279 ppHRegPPC32(i->Pin.AvBin16x8.srcR);
1280 return;
1281 case Pin_AvBin32x4:
1282 vex_printf("%s(w) ", showPPC32AvOp(i->Pin.AvBin32x4.op));
1283 ppHRegPPC32(i->Pin.AvBin32x4.dst);
1284 vex_printf(",");
1285 ppHRegPPC32(i->Pin.AvBin32x4.srcL);
1286 vex_printf(",");
1287 ppHRegPPC32(i->Pin.AvBin32x4.srcR);
1288 return;
1289 case Pin_AvBin32Fx4:
1290 vex_printf("%s ", showPPC32AvOp(i->Pin.AvBin32Fx4.op));
1291 ppHRegPPC32(i->Pin.AvBin32Fx4.dst);
1292 vex_printf(",");
1293 ppHRegPPC32(i->Pin.AvBin32Fx4.srcL);
1294 vex_printf(",");
1295 ppHRegPPC32(i->Pin.AvBin32Fx4.srcR);
1296 return;
cerionc3d8bdc2005-06-28 18:06:23 +00001297 case Pin_AvPerm:
1298 vex_printf("vperm ");
1299 ppHRegPPC32(i->Pin.AvPerm.dst);
1300 vex_printf(",");
1301 ppHRegPPC32(i->Pin.AvPerm.srcL);
1302 vex_printf(",");
1303 ppHRegPPC32(i->Pin.AvPerm.srcR);
1304 vex_printf(",");
1305 ppHRegPPC32(i->Pin.AvPerm.ctl);
1306 return;
1307
1308 case Pin_AvSel:
1309 vex_printf("vsel ");
1310 ppHRegPPC32(i->Pin.AvSel.dst);
1311 vex_printf(",");
1312 ppHRegPPC32(i->Pin.AvSel.srcL);
1313 vex_printf(",");
1314 ppHRegPPC32(i->Pin.AvSel.srcR);
1315 vex_printf(",");
1316 ppHRegPPC32(i->Pin.AvSel.ctl);
1317 return;
1318
1319 case Pin_AvShlDbl:
1320 vex_printf("vsldoi ");
1321 ppHRegPPC32(i->Pin.AvShlDbl.dst);
1322 vex_printf(",");
1323 ppHRegPPC32(i->Pin.AvShlDbl.srcL);
1324 vex_printf(",");
1325 ppHRegPPC32(i->Pin.AvShlDbl.srcR);
sewardjdb36c0f2005-07-03 00:05:31 +00001326 vex_printf(",%d", i->Pin.AvShlDbl.shift);
cerionc3d8bdc2005-06-28 18:06:23 +00001327 return;
1328
1329 case Pin_AvSplat: {
sewardjdb36c0f2005-07-03 00:05:31 +00001330 UChar ch_sz = toUChar(
1331 (i->Pin.AvSplat.sz == 8) ? 'b' :
1332 (i->Pin.AvSplat.sz == 16) ? 'h' : 'w'
1333 );
cerionc3d8bdc2005-06-28 18:06:23 +00001334 vex_printf("vsplt%s%c ",
1335 i->Pin.AvSplat.src->tag == Pri_Imm ? "is" : "", ch_sz);
1336 ppHRegPPC32(i->Pin.AvSplat.dst);
1337 vex_printf(",");
1338 if (i->Pin.AvSplat.src->tag == Pri_Imm) {
1339 vex_printf("%d", (Char)(i->Pin.AvSplat.src->Pri.Imm.imm32));
1340 } else {
1341 ppHRegPPC32(i->Pin.AvSplat.src->Pri.Reg.reg);
1342 vex_printf(", 0");
1343 }
1344 return;
1345 }
1346
cerion6b6f59e2005-06-28 20:59:18 +00001347 case Pin_AvCMov:
1348 vex_printf("avcmov (%s) ", showPPC32CondCode(i->Pin.AvCMov.cond));
1349 ppHRegPPC32(i->Pin.AvCMov.dst);
1350 vex_printf(",");
1351 ppHRegPPC32(i->Pin.AvCMov.src);
1352 vex_printf(": ");
1353 vex_printf("if (v_dst != v_src) { ");
1354 if (i->Pin.AvCMov.cond.test != Pct_ALWAYS) {
1355 vex_printf("if (%%crf0.%s) { ", showPPC32CondCode(i->Pin.AvCMov.cond));
1356 }
1357 vex_printf("vmr ");
1358 ppHRegPPC32(i->Pin.AvCMov.dst);
1359 vex_printf(",");
1360 ppHRegPPC32(i->Pin.AvCMov.src);
1361 if (i->Pin.FpCMov.cond.test != Pct_ALWAYS)
1362 vex_printf(" }");
1363 vex_printf(" }");
1364 return;
1365
cerionc3d8bdc2005-06-28 18:06:23 +00001366 case Pin_AvLdVSCR:
1367 vex_printf("mtvscr ");
1368 ppHRegPPC32(i->Pin.AvLdVSCR.src);
1369 return;
1370
cerionb85e8bb2005-02-16 08:54:33 +00001371 default:
sewardj428fabd2005-03-21 03:11:17 +00001372 vex_printf("\nppPPC32Instr(ppc32): No such tag(%d)\n", (Int)i->tag);
cerionb85e8bb2005-02-16 08:54:33 +00001373 vpanic("ppPPC32Instr(ppc32)");
cerionbcf8c3e2005-02-04 16:17:07 +00001374 }
1375}
1376
1377/* --------- Helpers for register allocation. --------- */
1378
1379void getRegUsage_PPC32Instr ( HRegUsage* u, PPC32Instr* i )
1380{
1381// Bool unary;
1382 initHRegUsage(u);
1383 switch (i->tag) {
cerionb85e8bb2005-02-16 08:54:33 +00001384 case Pin_Alu32:
ceriona2f75882005-03-15 16:33:38 +00001385 addHRegUse(u, HRmRead, i->Pin.Alu32.srcL);
1386 addRegUsage_PPC32RI(u, i->Pin.Alu32.srcR);
cerionb85e8bb2005-02-16 08:54:33 +00001387 addHRegUse(u, HRmWrite, i->Pin.Alu32.dst);
cerionb85e8bb2005-02-16 08:54:33 +00001388 return;
cerioncd304492005-02-08 19:40:24 +00001389
cerion5e2527e2005-02-25 16:39:58 +00001390 case Pin_Sub32:
ceriona2f75882005-03-15 16:33:38 +00001391 addRegUsage_PPC32RI(u, i->Pin.Sub32.srcL);
1392 addHRegUse(u, HRmRead, i->Pin.Sub32.srcR);
cerion5e2527e2005-02-25 16:39:58 +00001393 addHRegUse(u, HRmWrite, i->Pin.Sub32.dst);
1394 return;
1395
cerionb85e8bb2005-02-16 08:54:33 +00001396 case Pin_Sh32:
1397 addHRegUse(u, HRmWrite, i->Pin.Sh32.dst);
1398 addHRegUse(u, HRmRead, i->Pin.Sh32.src);
1399 addRegUsage_PPC32RI(u, i->Pin.Sh32.shft);
cerionb85e8bb2005-02-16 08:54:33 +00001400 return;
1401
cerionb85e8bb2005-02-16 08:54:33 +00001402 case Pin_Cmp32:
ceriona2f75882005-03-15 16:33:38 +00001403 addHRegUse(u, HRmRead, i->Pin.Cmp32.srcL);
1404 addRegUsage_PPC32RI(u, i->Pin.Cmp32.srcR);
cerionb85e8bb2005-02-16 08:54:33 +00001405 return;
cerionab9132d2005-02-15 15:46:59 +00001406
cerionb85e8bb2005-02-16 08:54:33 +00001407 case Pin_Unary32:
1408 addHRegUse(u, HRmWrite, i->Pin.Unary32.dst);
1409 addHRegUse(u, HRmRead, i->Pin.Unary32.src);
1410 return;
1411 case Pin_MulL:
1412 addHRegUse(u, HRmWrite, i->Pin.MulL.dst);
ceriona2f75882005-03-15 16:33:38 +00001413 addHRegUse(u, HRmRead, i->Pin.MulL.srcL);
1414 addRegUsage_PPC32RI(u, i->Pin.MulL.srcR);
cerionb85e8bb2005-02-16 08:54:33 +00001415 return;
1416 case Pin_Div:
1417 addHRegUse(u, HRmWrite, i->Pin.Div.dst);
ceriona2f75882005-03-15 16:33:38 +00001418 addHRegUse(u, HRmRead, i->Pin.Div.srcL);
1419 addHRegUse(u, HRmRead, i->Pin.Div.srcR);
cerionb85e8bb2005-02-16 08:54:33 +00001420 return;
cerionb85e8bb2005-02-16 08:54:33 +00001421 case Pin_Call:
1422 /* This is a bit subtle. */
1423 /* First off, claim it trashes all the caller-saved regs
1424 which fall within the register allocator's jurisdiction.
ceriona56e9cc2005-02-16 18:08:25 +00001425 These I believe to be: r3:12
cerionb85e8bb2005-02-16 08:54:33 +00001426 */
cerionb85e8bb2005-02-16 08:54:33 +00001427 addHRegUse(u, HRmWrite, hregPPC32_GPR3());
1428 addHRegUse(u, HRmWrite, hregPPC32_GPR4());
1429 addHRegUse(u, HRmWrite, hregPPC32_GPR5());
1430 addHRegUse(u, HRmWrite, hregPPC32_GPR6());
1431 addHRegUse(u, HRmWrite, hregPPC32_GPR7());
1432 addHRegUse(u, HRmWrite, hregPPC32_GPR8());
1433 addHRegUse(u, HRmWrite, hregPPC32_GPR9());
1434 addHRegUse(u, HRmWrite, hregPPC32_GPR10());
1435 addHRegUse(u, HRmWrite, hregPPC32_GPR11());
1436 addHRegUse(u, HRmWrite, hregPPC32_GPR12());
1437
1438 /* Now we have to state any parameter-carrying registers
1439 which might be read. This depends on the regparmness. */
1440 switch (i->Pin.Call.regparms) {
1441 case 8: addHRegUse(u, HRmRead, hregPPC32_GPR10()); /*fallthru*/
1442 case 7: addHRegUse(u, HRmRead, hregPPC32_GPR9() ); /*fallthru*/
1443 case 6: addHRegUse(u, HRmRead, hregPPC32_GPR8() ); /*fallthru*/
1444 case 5: addHRegUse(u, HRmRead, hregPPC32_GPR7() ); /*fallthru*/
1445 case 4: addHRegUse(u, HRmRead, hregPPC32_GPR6() ); /*fallthru*/
1446 case 3: addHRegUse(u, HRmRead, hregPPC32_GPR5() ); /*fallthru*/
1447 case 2: addHRegUse(u, HRmRead, hregPPC32_GPR4() ); /*fallthru*/
1448 case 1: addHRegUse(u, HRmRead, hregPPC32_GPR3() ); /*fallthru*/
1449 case 0: break;
1450 default: vpanic("getRegUsage_PPC32Instr:Call:regparms");
1451 }
1452 /* Finally, there is the issue that the insn trashes a
1453 register because the literal target address has to be
ceriona56e9cc2005-02-16 18:08:25 +00001454 loaded into a register. %r12 seems a suitable victim.
1455 (Can't use %r0, as use ops that interpret it as value zero). */
cerionb85e8bb2005-02-16 08:54:33 +00001456 addHRegUse(u, HRmWrite, hregPPC32_GPR12());
1457 /* Upshot of this is that the assembler really must use %r12,
ceriona56e9cc2005-02-16 18:08:25 +00001458 and no other, as a destination temporary. */
cerionb85e8bb2005-02-16 08:54:33 +00001459 return;
1460 case Pin_Goto:
1461 addRegUsage_PPC32RI(u, i->Pin.Goto.dst);
ceriona56e9cc2005-02-16 18:08:25 +00001462 /* GPR3 holds destination address from Pin_Goto */
1463 addHRegUse(u, HRmWrite, hregPPC32_GPR3());
cerionb85e8bb2005-02-16 08:54:33 +00001464 if (i->Pin.Goto.jk != Ijk_Boring)
1465 addHRegUse(u, HRmWrite, GuestStatePtr);
1466 return;
1467 case Pin_CMov32:
1468 addRegUsage_PPC32RI(u, i->Pin.CMov32.src);
cerioned623db2005-06-20 12:42:04 +00001469 addHRegUse(u, HRmWrite, i->Pin.CMov32.dst);
cerionb85e8bb2005-02-16 08:54:33 +00001470 return;
cerion7cf8e4e2005-02-16 16:08:17 +00001471 case Pin_Load:
1472 addRegUsage_PPC32AMode(u, i->Pin.Load.src);
1473 addHRegUse(u, HRmWrite, i->Pin.Load.dst);
cerionb85e8bb2005-02-16 08:54:33 +00001474 return;
1475 case Pin_Store:
1476 addHRegUse(u, HRmRead, i->Pin.Store.src);
1477 addRegUsage_PPC32AMode(u, i->Pin.Store.dst);
1478 return;
1479 case Pin_Set32:
1480 addHRegUse(u, HRmWrite, i->Pin.Set32.dst);
1481 return;
cerionb85e8bb2005-02-16 08:54:33 +00001482 case Pin_MFence:
1483 return;
cerion094d1392005-06-20 13:45:57 +00001484
1485 case Pin_FpUnary:
1486 addHRegUse(u, HRmWrite, i->Pin.FpUnary.dst);
1487 addHRegUse(u, HRmRead, i->Pin.FpUnary.src);
1488 return;
1489 case Pin_FpBinary:
1490 addHRegUse(u, HRmWrite, i->Pin.FpBinary.dst);
1491 addHRegUse(u, HRmRead, i->Pin.FpBinary.srcL);
1492 addHRegUse(u, HRmRead, i->Pin.FpBinary.srcR);
1493 return;
1494 case Pin_FpLdSt:
1495 addHRegUse(u, (i->Pin.FpLdSt.isLoad ? HRmWrite : HRmRead),
1496 i->Pin.FpLdSt.reg);
1497 addRegUsage_PPC32AMode(u, i->Pin.FpLdSt.addr);
1498 return;
1499 case Pin_FpF64toF32:
1500 addHRegUse(u, HRmWrite, i->Pin.FpF64toF32.dst);
1501 addHRegUse(u, HRmRead, i->Pin.FpF64toF32.src);
1502 return;
1503 case Pin_FpF64toI32:
1504 addHRegUse(u, HRmWrite, i->Pin.FpF64toI32.dst);
1505 addHRegUse(u, HRmWrite, hregPPC32_FPR7());
1506 addHRegUse(u, HRmRead, i->Pin.FpF64toI32.src);
1507 return;
1508 case Pin_FpCMov:
1509 addHRegUse(u, HRmModify, i->Pin.FpCMov.dst);
1510 addHRegUse(u, HRmRead, i->Pin.FpCMov.src);
1511 return;
1512 case Pin_FpLdFPSCR:
1513 addHRegUse(u, HRmRead, i->Pin.FpLdFPSCR.src);
1514 return;
1515 case Pin_FpCmp:
1516 addHRegUse(u, HRmWrite, i->Pin.FpCmp.dst);
1517 addHRegUse(u, HRmRead, i->Pin.FpCmp.srcL);
1518 addHRegUse(u, HRmRead, i->Pin.FpCmp.srcR);
1519 return;
cerion7f000af2005-02-22 20:36:49 +00001520
1521 case Pin_RdWrLR:
1522 addHRegUse(u, (i->Pin.RdWrLR.wrLR ? HRmRead : HRmWrite),
1523 i->Pin.RdWrLR.gpr);
1524 return;
1525
cerionc3d8bdc2005-06-28 18:06:23 +00001526 case Pin_AvLdSt:
1527 addHRegUse(u, (i->Pin.AvLdSt.isLoad ? HRmWrite : HRmRead),
1528 i->Pin.AvLdSt.reg);
1529 if (i->Pin.AvLdSt.addr->tag == Pam_IR)
1530 addHRegUse(u, HRmWrite, hregPPC32_GPR30());
1531 addRegUsage_PPC32AMode(u, i->Pin.AvLdSt.addr);
1532 return;
1533 case Pin_AvUnary:
1534 addHRegUse(u, HRmWrite, i->Pin.AvUnary.dst);
1535 addHRegUse(u, HRmRead, i->Pin.AvUnary.src);
1536 return;
1537 case Pin_AvBinary:
1538 addHRegUse(u, HRmWrite, i->Pin.AvBinary.dst);
1539 addHRegUse(u, HRmRead, i->Pin.AvBinary.srcL);
1540 addHRegUse(u, HRmRead, i->Pin.AvBinary.srcR);
1541 return;
cerion6b6f59e2005-06-28 20:59:18 +00001542 case Pin_AvBin8x16:
1543 addHRegUse(u, HRmWrite, i->Pin.AvBin8x16.dst);
1544 addHRegUse(u, HRmRead, i->Pin.AvBin8x16.srcL);
1545 addHRegUse(u, HRmRead, i->Pin.AvBin8x16.srcR);
1546 return;
1547 case Pin_AvBin16x8:
1548 addHRegUse(u, HRmWrite, i->Pin.AvBin16x8.dst);
1549 addHRegUse(u, HRmRead, i->Pin.AvBin16x8.srcL);
1550 addHRegUse(u, HRmRead, i->Pin.AvBin16x8.srcR);
1551 return;
1552 case Pin_AvBin32x4:
1553 addHRegUse(u, HRmWrite, i->Pin.AvBin32x4.dst);
1554 addHRegUse(u, HRmRead, i->Pin.AvBin32x4.srcL);
1555 addHRegUse(u, HRmRead, i->Pin.AvBin32x4.srcR);
1556 if (i->Pin.AvBin32x4.op == Pav_MULF)
1557 addHRegUse(u, HRmWrite, hregPPC32_GPR29());
1558 return;
1559 case Pin_AvBin32Fx4:
1560 addHRegUse(u, HRmWrite, i->Pin.AvBin32Fx4.dst);
1561 addHRegUse(u, HRmRead, i->Pin.AvBin32Fx4.srcL);
1562 addHRegUse(u, HRmRead, i->Pin.AvBin32Fx4.srcR);
1563 return;
cerionc3d8bdc2005-06-28 18:06:23 +00001564 case Pin_AvPerm:
1565 addHRegUse(u, HRmWrite, i->Pin.AvPerm.dst);
1566 addHRegUse(u, HRmRead, i->Pin.AvPerm.ctl);
1567 addHRegUse(u, HRmRead, i->Pin.AvPerm.srcL);
1568 addHRegUse(u, HRmRead, i->Pin.AvPerm.srcR);
1569 return;
1570 case Pin_AvSel:
1571 addHRegUse(u, HRmWrite, i->Pin.AvSel.dst);
1572 addHRegUse(u, HRmRead, i->Pin.AvSel.ctl);
1573 addHRegUse(u, HRmRead, i->Pin.AvSel.srcL);
1574 addHRegUse(u, HRmRead, i->Pin.AvSel.srcR);
1575 return;
1576 case Pin_AvShlDbl:
1577 addHRegUse(u, HRmWrite, i->Pin.AvShlDbl.dst);
1578 addHRegUse(u, HRmRead, i->Pin.AvShlDbl.srcL);
1579 addHRegUse(u, HRmRead, i->Pin.AvShlDbl.srcR);
1580 return;
1581 case Pin_AvSplat:
1582 addHRegUse(u, HRmWrite, i->Pin.AvSplat.dst);
1583 addRegUsage_PPC32RI(u, i->Pin.AvSplat.src);
1584 return;
cerion6b6f59e2005-06-28 20:59:18 +00001585 case Pin_AvCMov:
1586 addHRegUse(u, HRmModify, i->Pin.AvCMov.dst);
1587 addHRegUse(u, HRmRead, i->Pin.AvCMov.src);
1588 return;
cerionc3d8bdc2005-06-28 18:06:23 +00001589 case Pin_AvLdVSCR:
1590 addHRegUse(u, HRmRead, i->Pin.AvLdVSCR.src);
1591 return;
1592
cerionb85e8bb2005-02-16 08:54:33 +00001593 default:
1594 ppPPC32Instr(i);
1595 vpanic("getRegUsage_PPC32Instr");
cerionbcf8c3e2005-02-04 16:17:07 +00001596 }
1597}
1598
cerioncd304492005-02-08 19:40:24 +00001599/* local helper */
1600static void mapReg(HRegRemap* m, HReg* r)
1601{
1602 *r = lookupHRegRemap(m, *r);
1603}
cerionbcf8c3e2005-02-04 16:17:07 +00001604
1605void mapRegs_PPC32Instr (HRegRemap* m, PPC32Instr* i)
1606{
1607 switch (i->tag) {
cerionb85e8bb2005-02-16 08:54:33 +00001608 case Pin_Alu32:
1609 mapReg(m, &i->Pin.Alu32.dst);
ceriona2f75882005-03-15 16:33:38 +00001610 mapReg(m, &i->Pin.Alu32.srcL);
1611 mapRegs_PPC32RI(m, i->Pin.Alu32.srcR);
cerionb85e8bb2005-02-16 08:54:33 +00001612 return;
cerion5e2527e2005-02-25 16:39:58 +00001613 case Pin_Sub32:
1614 mapReg(m, &i->Pin.Sub32.dst);
ceriona2f75882005-03-15 16:33:38 +00001615 mapRegs_PPC32RI(m, i->Pin.Sub32.srcL);
1616 mapReg(m, &i->Pin.Sub32.srcR);
cerion5e2527e2005-02-25 16:39:58 +00001617 return;
cerionb85e8bb2005-02-16 08:54:33 +00001618 case Pin_Sh32:
1619 mapReg(m, &i->Pin.Sh32.dst);
1620 mapReg(m, &i->Pin.Sh32.src);
1621 mapRegs_PPC32RI(m, i->Pin.Sh32.shft);
1622 return;
cerionb85e8bb2005-02-16 08:54:33 +00001623 case Pin_Cmp32:
ceriona2f75882005-03-15 16:33:38 +00001624 mapReg(m, &i->Pin.Cmp32.srcL);
1625 mapRegs_PPC32RI(m, i->Pin.Cmp32.srcR);
cerionb85e8bb2005-02-16 08:54:33 +00001626 return;
1627 case Pin_Unary32:
1628 mapReg(m, &i->Pin.Unary32.dst);
1629 mapReg(m, &i->Pin.Unary32.src);
1630 return;
1631 case Pin_MulL:
1632 mapReg(m, &i->Pin.MulL.dst);
ceriona2f75882005-03-15 16:33:38 +00001633 mapReg(m, &i->Pin.MulL.srcL);
1634 mapRegs_PPC32RI(m, i->Pin.MulL.srcR);
cerionb85e8bb2005-02-16 08:54:33 +00001635 return;
1636 case Pin_Div:
1637 mapReg(m, &i->Pin.Div.dst);
ceriona2f75882005-03-15 16:33:38 +00001638 mapReg(m, &i->Pin.Div.srcL);
1639 mapReg(m, &i->Pin.Div.srcR);
cerionb85e8bb2005-02-16 08:54:33 +00001640 return;
cerionb85e8bb2005-02-16 08:54:33 +00001641 case Pin_Call:
1642 return;
1643 case Pin_Goto:
1644 mapRegs_PPC32RI(m, i->Pin.Goto.dst);
1645 return;
1646 case Pin_CMov32:
1647 mapRegs_PPC32RI(m, i->Pin.CMov32.src);
1648 mapReg(m, &i->Pin.CMov32.dst);
1649 return;
cerion7cf8e4e2005-02-16 16:08:17 +00001650 case Pin_Load:
1651 mapRegs_PPC32AMode(m, i->Pin.Load.src);
1652 mapReg(m, &i->Pin.Load.dst);
cerionb85e8bb2005-02-16 08:54:33 +00001653 return;
1654 case Pin_Store:
1655 mapReg(m, &i->Pin.Store.src);
1656 mapRegs_PPC32AMode(m, i->Pin.Store.dst);
1657 return;
1658 case Pin_Set32:
1659 mapReg(m, &i->Pin.Set32.dst);
1660 return;
cerionb85e8bb2005-02-16 08:54:33 +00001661 case Pin_MFence:
1662 return;
cerion094d1392005-06-20 13:45:57 +00001663
1664 case Pin_FpUnary:
1665 mapReg(m, &i->Pin.FpUnary.dst);
1666 mapReg(m, &i->Pin.FpUnary.src);
1667 return;
1668 case Pin_FpBinary:
1669 mapReg(m, &i->Pin.FpBinary.dst);
1670 mapReg(m, &i->Pin.FpBinary.srcL);
1671 mapReg(m, &i->Pin.FpBinary.srcR);
1672 return;
1673 case Pin_FpLdSt:
1674 mapReg(m, &i->Pin.FpLdSt.reg);
1675 mapRegs_PPC32AMode(m, i->Pin.FpLdSt.addr);
1676 return;
1677 case Pin_FpF64toF32:
1678 mapReg(m, &i->Pin.FpF64toF32.dst);
1679 mapReg(m, &i->Pin.FpF64toF32.src);
1680 return;
1681 case Pin_FpF64toI32:
1682 mapReg(m, &i->Pin.FpF64toI32.dst);
1683 mapReg(m, &i->Pin.FpF64toI32.src);
1684 return;
1685 case Pin_FpCMov:
1686 mapReg(m, &i->Pin.FpCMov.dst);
1687 mapReg(m, &i->Pin.FpCMov.src);
1688 return;
1689 case Pin_FpLdFPSCR:
1690 mapReg(m, &i->Pin.FpLdFPSCR.src);
1691 return;
1692 case Pin_FpCmp:
1693 mapReg(m, &i->Pin.FpCmp.dst);
1694 mapReg(m, &i->Pin.FpCmp.srcL);
1695 mapReg(m, &i->Pin.FpCmp.srcR);
1696 return;
cerion7f000af2005-02-22 20:36:49 +00001697
1698 case Pin_RdWrLR:
1699 mapReg(m, &i->Pin.RdWrLR.gpr);
1700 return;
1701
cerionc3d8bdc2005-06-28 18:06:23 +00001702 case Pin_AvLdSt:
1703 mapReg(m, &i->Pin.AvLdSt.reg);
1704 mapRegs_PPC32AMode(m, i->Pin.AvLdSt.addr);
1705 return;
1706 case Pin_AvUnary:
1707 mapReg(m, &i->Pin.AvUnary.dst);
1708 mapReg(m, &i->Pin.AvUnary.src);
1709 return;
1710 case Pin_AvBinary:
1711 mapReg(m, &i->Pin.AvBinary.dst);
1712 mapReg(m, &i->Pin.AvBinary.srcL);
1713 mapReg(m, &i->Pin.AvBinary.srcR);
1714 return;
cerion6b6f59e2005-06-28 20:59:18 +00001715 case Pin_AvBin8x16:
1716 mapReg(m, &i->Pin.AvBin8x16.dst);
1717 mapReg(m, &i->Pin.AvBin8x16.srcL);
1718 mapReg(m, &i->Pin.AvBin8x16.srcR);
1719 return;
1720 case Pin_AvBin16x8:
1721 mapReg(m, &i->Pin.AvBin16x8.dst);
1722 mapReg(m, &i->Pin.AvBin16x8.srcL);
1723 mapReg(m, &i->Pin.AvBin16x8.srcR);
1724 return;
1725 case Pin_AvBin32x4:
1726 mapReg(m, &i->Pin.AvBin32x4.dst);
1727 mapReg(m, &i->Pin.AvBin32x4.srcL);
1728 mapReg(m, &i->Pin.AvBin32x4.srcR);
1729 return;
1730 case Pin_AvBin32Fx4:
1731 mapReg(m, &i->Pin.AvBin32Fx4.dst);
1732 mapReg(m, &i->Pin.AvBin32Fx4.srcL);
1733 mapReg(m, &i->Pin.AvBin32Fx4.srcR);
1734 return;
cerionc3d8bdc2005-06-28 18:06:23 +00001735 case Pin_AvPerm:
1736 mapReg(m, &i->Pin.AvPerm.dst);
1737 mapReg(m, &i->Pin.AvPerm.srcL);
1738 mapReg(m, &i->Pin.AvPerm.srcR);
1739 mapReg(m, &i->Pin.AvPerm.ctl);
1740 return;
1741 case Pin_AvSel:
1742 mapReg(m, &i->Pin.AvSel.dst);
1743 mapReg(m, &i->Pin.AvSel.srcL);
1744 mapReg(m, &i->Pin.AvSel.srcR);
1745 mapReg(m, &i->Pin.AvSel.ctl);
1746 return;
1747 case Pin_AvShlDbl:
1748 mapReg(m, &i->Pin.AvShlDbl.dst);
1749 mapReg(m, &i->Pin.AvShlDbl.srcL);
1750 mapReg(m, &i->Pin.AvShlDbl.srcR);
1751 return;
1752 case Pin_AvSplat:
1753 mapReg(m, &i->Pin.AvSplat.dst);
1754 mapRegs_PPC32RI(m, i->Pin.AvSplat.src);
1755 return;
cerion6b6f59e2005-06-28 20:59:18 +00001756 case Pin_AvCMov:
1757 mapReg(m, &i->Pin.AvCMov.dst);
1758 mapReg(m, &i->Pin.AvCMov.src);
1759 return;
cerionc3d8bdc2005-06-28 18:06:23 +00001760 case Pin_AvLdVSCR:
1761 mapReg(m, &i->Pin.AvLdVSCR.src);
1762 return;
1763
cerionb85e8bb2005-02-16 08:54:33 +00001764 default:
1765 ppPPC32Instr(i);
1766 vpanic("mapRegs_PPC32Instr");
cerionbcf8c3e2005-02-04 16:17:07 +00001767 }
1768}
1769
1770/* Figure out if i represents a reg-reg move, and if so assign the
1771 source and destination to *src and *dst. If in doubt say No. Used
1772 by the register allocator to do move coalescing.
1773*/
1774Bool isMove_PPC32Instr ( PPC32Instr* i, HReg* src, HReg* dst )
1775{
cerionab9132d2005-02-15 15:46:59 +00001776 /* Moves between integer regs */
1777 if (i->tag == Pin_Alu32) {
1778 // or Rd,Rs,Rs == mr Rd,Rs
1779 if (i->Pin.Alu32.op != Palu_OR)
1780 return False;
ceriona2f75882005-03-15 16:33:38 +00001781 if (i->Pin.Alu32.srcR->tag != Pri_Reg)
cerionab9132d2005-02-15 15:46:59 +00001782 return False;
ceriona2f75882005-03-15 16:33:38 +00001783 if (i->Pin.Alu32.srcR->Pri.Reg.reg != i->Pin.Alu32.srcL)
cerionb85e8bb2005-02-16 08:54:33 +00001784 return False;
ceriona2f75882005-03-15 16:33:38 +00001785 *src = i->Pin.Alu32.srcL;
cerionab9132d2005-02-15 15:46:59 +00001786 *dst = i->Pin.Alu32.dst;
1787 return True;
1788 }
cerion094d1392005-06-20 13:45:57 +00001789 /* Moves between FP regs */
1790 if (i->tag == Pin_FpUnary) {
1791 if (i->Pin.FpUnary.op != Pfp_MOV)
1792 return False;
1793 *src = i->Pin.FpUnary.src;
1794 *dst = i->Pin.FpUnary.dst;
1795 return True;
1796 }
cerionbcf8c3e2005-02-04 16:17:07 +00001797 return False;
1798}
1799
1800
cerione13bb312005-02-10 19:51:03 +00001801/* Generate ppc32 spill/reload instructions under the direction of the
cerionbcf8c3e2005-02-04 16:17:07 +00001802 register allocator. Note it's critical these don't write the
1803 condition codes. */
cerionc3d8bdc2005-06-28 18:06:23 +00001804PPC32Instr* genSpill_PPC32 ( HReg rreg, UShort offsetB )
cerione13bb312005-02-10 19:51:03 +00001805{
1806 PPC32AMode* am;
cerione13bb312005-02-10 19:51:03 +00001807 vassert(!hregIsVirtual(rreg));
1808 am = PPC32AMode_IR(offsetB, GuestStatePtr);
cerionb85e8bb2005-02-16 08:54:33 +00001809
cerione13bb312005-02-10 19:51:03 +00001810 switch (hregClass(rreg)) {
cerionb85e8bb2005-02-16 08:54:33 +00001811 case HRcInt32:
1812 return PPC32Instr_Store( 4, am, rreg);
cerion094d1392005-06-20 13:45:57 +00001813 case HRcFlt64:
1814 return PPC32Instr_FpLdSt ( False/*store*/, 8, rreg, am );
cerionc3d8bdc2005-06-28 18:06:23 +00001815 case HRcVec128:
1816 // XXX: GPR30 used as spill register to kludge AltiVec AMode_IR
1817 return PPC32Instr_AvLdSt ( False/*store*/, 16, rreg, am );
cerionb85e8bb2005-02-16 08:54:33 +00001818 default:
1819 ppHRegClass(hregClass(rreg));
1820 vpanic("genSpill_PPC32: unimplemented regclass");
cerione13bb312005-02-10 19:51:03 +00001821 }
cerionbcf8c3e2005-02-04 16:17:07 +00001822}
1823
cerionc3d8bdc2005-06-28 18:06:23 +00001824PPC32Instr* genReload_PPC32 ( HReg rreg, UShort offsetB )
cerione13bb312005-02-10 19:51:03 +00001825{
1826 PPC32AMode* am;
cerione13bb312005-02-10 19:51:03 +00001827 vassert(!hregIsVirtual(rreg));
1828 am = PPC32AMode_IR(offsetB, GuestStatePtr);
1829
1830 switch (hregClass(rreg)) {
cerionb85e8bb2005-02-16 08:54:33 +00001831 case HRcInt32:
cerion7cf8e4e2005-02-16 16:08:17 +00001832 return PPC32Instr_Load( 4, False, rreg, am );
cerion094d1392005-06-20 13:45:57 +00001833 case HRcFlt64:
1834 return PPC32Instr_FpLdSt ( True/*load*/, 8, rreg, am );
cerionc3d8bdc2005-06-28 18:06:23 +00001835 case HRcVec128:
1836 // XXX: GPR30 used as spill register to kludge AltiVec AMode_IR
1837 return PPC32Instr_AvLdSt ( True/*load*/, 16, rreg, am );
cerionb85e8bb2005-02-16 08:54:33 +00001838 default:
1839 ppHRegClass(hregClass(rreg));
1840 vpanic("genReload_PPC32: unimplemented regclass");
cerione13bb312005-02-10 19:51:03 +00001841 }
cerionbcf8c3e2005-02-04 16:17:07 +00001842}
1843
1844
ceriond5e38382005-02-11 13:38:15 +00001845/* --------- The ppc32 assembler (bleh.) --------- */
cerioncd304492005-02-08 19:40:24 +00001846
cerioncd304492005-02-08 19:40:24 +00001847static UInt iregNo ( HReg r )
1848{
1849 UInt n;
1850 vassert(hregClass(r) == HRcInt32);
1851 vassert(!hregIsVirtual(r));
1852 n = hregNumber(r);
1853 vassert(n <= 32);
1854 return n;
1855}
cerioncd304492005-02-08 19:40:24 +00001856
cerion094d1392005-06-20 13:45:57 +00001857static UInt fregNo ( HReg fr )
1858{
1859 UInt n;
1860 vassert(hregClass(fr) == HRcFlt64);
1861 vassert(!hregIsVirtual(fr));
1862 n = hregNumber(fr);
1863 vassert(n <= 32);
1864 return n;
1865}
cerioncd304492005-02-08 19:40:24 +00001866
cerionc3d8bdc2005-06-28 18:06:23 +00001867static UInt vregNo ( HReg v )
1868{
1869 UInt n;
1870 vassert(hregClass(v) == HRcVec128);
1871 vassert(!hregIsVirtual(v));
1872 n = hregNumber(v);
1873 vassert(n <= 32);
1874 return n;
1875}
1876
cerionab9132d2005-02-15 15:46:59 +00001877/* Emit 32bit instruction big-endianly */
ceriond5e38382005-02-11 13:38:15 +00001878static UChar* emit32 ( UChar* p, UInt w32 )
1879{
sewardj428fabd2005-03-21 03:11:17 +00001880 *p++ = toUChar((w32 >> 24) & 0x000000FF);
1881 *p++ = toUChar((w32 >> 16) & 0x000000FF);
1882 *p++ = toUChar((w32 >> 8) & 0x000000FF);
1883 *p++ = toUChar((w32) & 0x000000FF);
ceriond5e38382005-02-11 13:38:15 +00001884 return p;
1885}
cerioncd304492005-02-08 19:40:24 +00001886
cerion094d1392005-06-20 13:45:57 +00001887/* The following mkForm[...] functions refer to PPC32 instruction forms
1888 as per PPC32 p576
1889 */
cerioned623db2005-06-20 12:42:04 +00001890
ceriona2f75882005-03-15 16:33:38 +00001891static UChar* mkFormD ( UChar* p, UInt opc1, UInt r1, UInt r2, UInt imm )
ceriond5e38382005-02-11 13:38:15 +00001892{
sewardj9a036bf2005-03-14 18:19:08 +00001893 UInt theInstr;
ceriona2f75882005-03-15 16:33:38 +00001894 vassert(opc1 < 0x40);
ceriond5e38382005-02-11 13:38:15 +00001895 vassert(r1 < 0x20);
1896 vassert(r2 < 0x20);
cerion35663a72005-03-01 09:11:49 +00001897 vassert(imm < 0x10000 || imm >= 0xFFFF8000); // Pos|Neg
1898 imm = imm & 0xFFFF;
ceriona2f75882005-03-15 16:33:38 +00001899 theInstr = ((opc1<<26) | (r1<<21) | (r2<<16) | (imm));
ceriond5e38382005-02-11 13:38:15 +00001900 return emit32(p, theInstr);
1901}
1902
ceriona2f75882005-03-15 16:33:38 +00001903static UChar* mkFormX ( UChar* p, UInt opc1, UInt r1, UInt r2,
1904 UInt r3, UInt opc2, UInt b0 )
ceriond5e38382005-02-11 13:38:15 +00001905{
sewardj9a036bf2005-03-14 18:19:08 +00001906 UInt theInstr;
ceriona2f75882005-03-15 16:33:38 +00001907 vassert(opc1 < 0x40);
ceriond5e38382005-02-11 13:38:15 +00001908 vassert(r1 < 0x20);
1909 vassert(r2 < 0x20);
1910 vassert(r3 < 0x20);
ceriona2f75882005-03-15 16:33:38 +00001911 vassert(opc2 < 0x400);
ceriond5e38382005-02-11 13:38:15 +00001912 vassert(b0 < 0x2);
ceriona2f75882005-03-15 16:33:38 +00001913 theInstr = ((opc1<<26) | (r1<<21) | (r2<<16) | (r3<<11) | (opc2<<1) | (b0));
ceriond5e38382005-02-11 13:38:15 +00001914 return emit32(p, theInstr);
1915}
1916
ceriona2f75882005-03-15 16:33:38 +00001917static UChar* mkFormXO ( UChar* p, UInt opc1, UInt r1, UInt r2,
1918 UInt r3, UInt b10, UInt opc2, UInt b0 )
cerionab9132d2005-02-15 15:46:59 +00001919{
sewardj9a036bf2005-03-14 18:19:08 +00001920 UInt theInstr;
ceriona2f75882005-03-15 16:33:38 +00001921 vassert(opc1 < 0x40);
cerionab9132d2005-02-15 15:46:59 +00001922 vassert(r1 < 0x20);
1923 vassert(r2 < 0x20);
1924 vassert(r3 < 0x20);
1925 vassert(b10 < 0x2);
ceriona2f75882005-03-15 16:33:38 +00001926 vassert(opc2 < 0x200);
cerionab9132d2005-02-15 15:46:59 +00001927 vassert(b0 < 0x2);
ceriona2f75882005-03-15 16:33:38 +00001928 theInstr = ((opc1<<26) | (r1<<21) | (r2<<16) |
1929 (r3<<11) | (b10 << 10) | (opc2<<1) | (b0));
cerionab9132d2005-02-15 15:46:59 +00001930 return emit32(p, theInstr);
1931}
ceriond5e38382005-02-11 13:38:15 +00001932
ceriona2f75882005-03-15 16:33:38 +00001933static UChar* mkFormXL ( UChar* p, UInt opc1, UInt f1, UInt f2,
1934 UInt f3, UInt opc2, UInt b0 )
cerion33aa6da2005-02-16 10:25:26 +00001935{
sewardj9a036bf2005-03-14 18:19:08 +00001936 UInt theInstr;
ceriona2f75882005-03-15 16:33:38 +00001937 vassert(opc1 < 0x40);
cerion33aa6da2005-02-16 10:25:26 +00001938 vassert(f1 < 0x20);
1939 vassert(f2 < 0x20);
1940 vassert(f3 < 0x20);
ceriona2f75882005-03-15 16:33:38 +00001941 vassert(opc2 < 0x400);
cerion33aa6da2005-02-16 10:25:26 +00001942 vassert(b0 < 0x2);
ceriona2f75882005-03-15 16:33:38 +00001943 theInstr = ((opc1<<26) | (f1<<21) | (f2<<16) | (f3<<11) | (opc2<<1) | (b0));
cerion33aa6da2005-02-16 10:25:26 +00001944 return emit32(p, theInstr);
1945}
1946
1947// Note: for split field ops, give mnemonic arg
ceriona2f75882005-03-15 16:33:38 +00001948static UChar* mkFormXFX ( UChar* p, UInt r1, UInt f2, UInt opc2 )
cerion33aa6da2005-02-16 10:25:26 +00001949{
sewardj9a036bf2005-03-14 18:19:08 +00001950 UInt theInstr;
cerion33aa6da2005-02-16 10:25:26 +00001951 vassert(r1 < 0x20);
1952 vassert(f2 < 0x20);
ceriona2f75882005-03-15 16:33:38 +00001953 vassert(opc2 < 0x400);
1954 switch (opc2) {
cerion33aa6da2005-02-16 10:25:26 +00001955 case 144: // mtcrf
1956 vassert(f2 < 0x100);
1957 f2 = f2 << 1;
1958 break;
1959 case 339: // mfspr
1960 case 371: // mftb
1961 case 467: // mtspr
1962 vassert(f2 < 0x400);
1963 f2 = ((f2>>5) & 0x1F) | ((f2 & 0x1F)<<5); // re-arrange split field
1964 break;
1965 default: vpanic("mkFormXFX(PPC32)");
1966 }
ceriona2f75882005-03-15 16:33:38 +00001967 theInstr = ((31<<26) | (r1<<21) | (f2<<11) | (opc2<<1));
cerion33aa6da2005-02-16 10:25:26 +00001968 return emit32(p, theInstr);
1969}
1970
cerion094d1392005-06-20 13:45:57 +00001971// Only used by mtfsf
1972static UChar* mkFormXFL ( UChar* p, UInt FM, UInt freg )
1973{
1974 UInt theInstr;
1975 vassert(FM < 0x100);
1976 vassert(freg < 0x20);
1977 theInstr = ((63<<26) | (FM<<17) | (freg<<11) | (711<<1));
1978 return emit32(p, theInstr);
1979}
1980
cerion33aa6da2005-02-16 10:25:26 +00001981#if 0
1982// 'b'
1983static UChar* mkFormI ( UChar* p, UInt LI, UInt AA, UInt LK )
1984{
sewardj9a036bf2005-03-14 18:19:08 +00001985 UInt theInstr;
cerion33aa6da2005-02-16 10:25:26 +00001986 vassert(LI < 0x1000000);
1987 vassert(AA < 0x2);
1988 vassert(LK < 0x2);
sewardj9a036bf2005-03-14 18:19:08 +00001989 theInstr = ((18<<26) | (LI<<2) | (AA<<1) | (LK));
cerion33aa6da2005-02-16 10:25:26 +00001990 return emit32(p, theInstr);
1991}
1992#endif
1993
1994// 'bc'
1995static UChar* mkFormB ( UChar* p, UInt BO, UInt BI,
1996 UInt BD, UInt AA, UInt LK )
1997{
sewardj9a036bf2005-03-14 18:19:08 +00001998 UInt theInstr;
cerion33aa6da2005-02-16 10:25:26 +00001999 vassert(BO < 0x20);
2000 vassert(BI < 0x20);
2001 vassert(BD < 0x4000);
2002 vassert(AA < 0x2);
2003 vassert(LK < 0x2);
ceriona2f75882005-03-15 16:33:38 +00002004 theInstr = ((16<<26) | (BO<<21) | (BI<<16) | (BD<<2) | (AA<<1) | (LK));
cerion33aa6da2005-02-16 10:25:26 +00002005 return emit32(p, theInstr);
2006}
2007
cerion33aa6da2005-02-16 10:25:26 +00002008// rotates
ceriona2f75882005-03-15 16:33:38 +00002009static UChar* mkFormM ( UChar* p, UInt opc1, UInt r1, UInt r2,
cerion33aa6da2005-02-16 10:25:26 +00002010 UInt f3, UInt MB, UInt ME, UInt Rc )
2011{
sewardj9a036bf2005-03-14 18:19:08 +00002012 UInt theInstr;
ceriona2f75882005-03-15 16:33:38 +00002013 vassert(opc1 < 0x40);
cerion33aa6da2005-02-16 10:25:26 +00002014 vassert(r1 < 0x20);
2015 vassert(r2 < 0x20);
2016 vassert(f3 < 0x20);
2017 vassert(MB < 0x20);
2018 vassert(ME < 0x20);
2019 vassert(Rc < 0x2);
ceriona2f75882005-03-15 16:33:38 +00002020 theInstr = ((opc1<<26) | (r1<<21) | (r2<<16) |
sewardj9a036bf2005-03-14 18:19:08 +00002021 (f3<<11) | (MB<<6) | (ME<<1) | (Rc));
cerion33aa6da2005-02-16 10:25:26 +00002022 return emit32(p, theInstr);
2023}
cerion33aa6da2005-02-16 10:25:26 +00002024
cerion094d1392005-06-20 13:45:57 +00002025static UChar* mkFormA ( UChar* p, UInt opc1, UInt r1, UInt r2,
2026 UInt r3, UInt r4, UInt opc2, UInt b0 )
2027{
2028 UInt theInstr;
2029 vassert(opc1 < 0x40);
2030 vassert(r1 < 0x20);
2031 vassert(r2 < 0x20);
2032 vassert(r3 < 0x20);
2033 vassert(r4 < 0x20);
2034 vassert(opc2 < 0x20);
2035 vassert(b0 < 0x2 );
2036 theInstr = ((opc1<<26) | (r1<<21) | (r2<<16) | (r3<<11) |
2037 (r4<<6) | (opc2<<1) | (b0));
2038 return emit32(p, theInstr);
2039}
2040
cerioned623db2005-06-20 12:42:04 +00002041static UChar* doAMode_IR ( UChar* p, UInt opc1, UInt rSD, PPC32AMode* am )
ceriond5e38382005-02-11 13:38:15 +00002042{
cerioned623db2005-06-20 12:42:04 +00002043 UInt rA, idx;
ceriond5e38382005-02-11 13:38:15 +00002044 vassert(am->tag == Pam_IR);
ceriona2f75882005-03-15 16:33:38 +00002045 vassert(am->Pam.IR.index < 0x10000);
2046
sewardj9a036bf2005-03-14 18:19:08 +00002047 rA = iregNo(am->Pam.IR.base);
2048 idx = am->Pam.IR.index;
ceriona2f75882005-03-15 16:33:38 +00002049
2050 p = mkFormD(p, opc1, rSD, rA, idx);
ceriond5e38382005-02-11 13:38:15 +00002051 return p;
2052}
2053
2054
ceriona2f75882005-03-15 16:33:38 +00002055static UChar* doAMode_RR ( UChar* p, UInt opc1, UInt opc2,
cerioned623db2005-06-20 12:42:04 +00002056 UInt rSD, PPC32AMode* am )
ceriond5e38382005-02-11 13:38:15 +00002057{
cerioned623db2005-06-20 12:42:04 +00002058 UInt rA, rB;
ceriond5e38382005-02-11 13:38:15 +00002059 vassert(am->tag == Pam_RR);
ceriona2f75882005-03-15 16:33:38 +00002060
sewardj9a036bf2005-03-14 18:19:08 +00002061 rA = iregNo(am->Pam.RR.base);
2062 rB = iregNo(am->Pam.RR.index);
ceriona2f75882005-03-15 16:33:38 +00002063
2064 p = mkFormX(p, opc1, rSD, rA, rB, opc2, 0);
ceriond5e38382005-02-11 13:38:15 +00002065 return p;
2066}
2067
cerione97e1062005-02-21 15:09:19 +00002068/* Load imm to r_dst */
2069static UChar* mkLoadImm ( UChar* p, UInt r_dst, UInt imm )
2070{
2071 vassert(r_dst < 0x20);
2072
cerion47c526b2005-03-03 05:17:08 +00002073 if (imm >= 0xFFFF8000 || imm <= 0x7FFF) { // sign-extendable from 16 bits?
cerione97e1062005-02-21 15:09:19 +00002074 // addi r_dst,0,imm => li r_dst,imm
2075 p = mkFormD(p, 14, r_dst, 0, imm);
2076 } else {
2077 // addis r_dst,r0,(imm>>16) => lis r_dst, (imm>>16)
2078 p = mkFormD(p, 15, r_dst, 0, (imm>>16));
2079 // ori r_dst, r_dst, (imm & 0xFFFF)
2080 p = mkFormD(p, 24, r_dst, r_dst, (imm & 0xFFFF));
2081 }
2082 return p;
2083}
2084
cerione97e1062005-02-21 15:09:19 +00002085/* Move r_dst to r_src */
2086static UChar* mkMoveReg ( UChar* p, UInt r_dst, UInt r_src )
2087{
2088 vassert(r_dst < 0x20);
2089 vassert(r_src < 0x20);
2090
2091 if (r_dst != r_src) {
2092 /* or r_dst, r_src, r_src */
2093 p = mkFormX(p, 31, r_src, r_dst, r_src, 444, 0 );
2094 }
2095 return p;
2096}
2097
cerionc3d8bdc2005-06-28 18:06:23 +00002098static UChar* mkFormVX ( UChar* p, UInt opc1, UInt r1, UInt r2,
2099 UInt r3, UInt opc2 )
2100{
2101 UInt theInstr;
2102 vassert(opc1 < 0x40);
2103 vassert(r1 < 0x20);
2104 vassert(r2 < 0x20);
2105 vassert(r3 < 0x20);
2106 vassert(opc2 < 0x800);
cerion6b6f59e2005-06-28 20:59:18 +00002107 theInstr = ((opc1<<26) | (r1<<21) | (r2<<16) | (r3<<11) | opc2);
2108 return emit32(p, theInstr);
2109}
2110
2111static UChar* mkFormVXR ( UChar* p, UInt opc1, UInt r1, UInt r2, UInt Rc,
2112 UInt r3, UInt opc2 )
2113{
2114 UInt theInstr;
2115 vassert(opc1 < 0x40);
2116 vassert(r1 < 0x20);
2117 vassert(r2 < 0x20);
2118 vassert(r3 < 0x20);
2119 vassert(Rc < 0x2);
2120 vassert(opc2 < 0x400);
2121 theInstr = ((opc1<<26) | (r1<<21) | (r2<<16) | (r3<<11) | (Rc<<10) | opc2);
cerionc3d8bdc2005-06-28 18:06:23 +00002122 return emit32(p, theInstr);
2123}
2124
2125static UChar* mkFormVA ( UChar* p, UInt opc1, UInt r1, UInt r2,
2126 UInt r3, UInt r4, UInt opc2 )
2127{
2128 UInt theInstr;
2129 vassert(opc1 < 0x40);
2130 vassert(r1 < 0x20);
2131 vassert(r2 < 0x20);
2132 vassert(r3 < 0x20);
2133 vassert(r4 < 0x20);
2134 vassert(opc2 < 0x40);
2135 theInstr = ((opc1<<26) | (r1<<21) | (r2<<16) | (r3<<11) | (r4<<6) | opc2);
2136 return emit32(p, theInstr);
2137}
2138
2139
ceriond5e38382005-02-11 13:38:15 +00002140
cerionbcf8c3e2005-02-04 16:17:07 +00002141/* Emit an instruction into buf and return the number of bytes used.
2142 Note that buf is not the insn's final place, and therefore it is
2143 imperative to emit position-independent code. */
2144
2145Int emit_PPC32Instr ( UChar* buf, Int nbuf, PPC32Instr* i )
2146{
2147//.. UInt irno, opc, opc_rr, subopc_imm, opc_imma, opc_cl, opc_imm, subopc;
cerioned623db2005-06-20 12:42:04 +00002148
cerionbcf8c3e2005-02-04 16:17:07 +00002149 UChar* p = &buf[0];
cerion7cf8e4e2005-02-16 16:08:17 +00002150 UChar* ptmp = p;
2151 vassert(nbuf >= 32);
cerion2c49e032005-02-09 17:29:49 +00002152
cerion9a934a92005-02-21 16:44:03 +00002153// vex_printf("asm ");ppPPC32Instr(i); vex_printf("\n");
cerionbcf8c3e2005-02-04 16:17:07 +00002154
2155 switch (i->tag) {
2156
cerionab9132d2005-02-15 15:46:59 +00002157 case Pin_Alu32: {
ceriona2f75882005-03-15 16:33:38 +00002158 UInt opc1, opc2, r_srcR, imm_srcR;
2159 UInt r_dst = iregNo(i->Pin.Alu32.dst);
2160 UInt r_srcL = iregNo(i->Pin.Alu32.srcL);
cerion2c49e032005-02-09 17:29:49 +00002161
cerion9e263e32005-03-03 17:21:51 +00002162 /* ADD/AND/OR/XOR */
ceriona2f75882005-03-15 16:33:38 +00002163 if (i->Pin.Alu32.srcR->tag == Pri_Reg) {
2164 opc1 = 31;
2165 r_srcR = iregNo(i->Pin.Alu32.srcR->Pri.Reg.reg);
cerionab9132d2005-02-15 15:46:59 +00002166 switch (i->Pin.Alu32.op) {
ceriona2f75882005-03-15 16:33:38 +00002167 case Palu_ADD: opc2 = 266; break;
2168 case Palu_AND: opc2 = 28; break;
2169 case Palu_XOR: opc2 = 316; break;
2170 case Palu_OR: opc2 = 444; break;
cerionab9132d2005-02-15 15:46:59 +00002171 default:
2172 goto bad;
2173 }
2174
cerion9e263e32005-03-03 17:21:51 +00002175 if (i->Pin.Alu32.op == Palu_ADD) {
ceriona2f75882005-03-15 16:33:38 +00002176 p = mkFormXO(p, opc1, r_dst, r_srcL, r_srcR, 0, opc2, 0);
cerion9e263e32005-03-03 17:21:51 +00002177 } else {
ceriona2f75882005-03-15 16:33:38 +00002178 p = mkFormX(p, opc1, r_srcL, r_dst, r_srcR, opc2, 0);
cerionab9132d2005-02-15 15:46:59 +00002179 }
cerioned623db2005-06-20 12:42:04 +00002180 } else { // tag == Pri_Imm:
ceriona2f75882005-03-15 16:33:38 +00002181 imm_srcR = i->Pin.Alu32.srcR->Pri.Imm.imm32;
cerionab9132d2005-02-15 15:46:59 +00002182 switch (i->Pin.Alu32.op) {
ceriona2f75882005-03-15 16:33:38 +00002183 case Palu_ADD: opc1 = 14; break;
2184 case Palu_AND: opc1 = 28; break;
2185 case Palu_XOR: opc1 = 26; break;
2186 case Palu_OR: opc1 = 24; break;
cerionab9132d2005-02-15 15:46:59 +00002187 default:
2188 goto bad;
2189 }
2190
cerion9e263e32005-03-03 17:21:51 +00002191 if (i->Pin.Alu32.op == Palu_ADD) {
ceriona2f75882005-03-15 16:33:38 +00002192 p = mkFormD(p, opc1, r_dst, r_srcL, imm_srcR);
cerion9e263e32005-03-03 17:21:51 +00002193 } else {
ceriona2f75882005-03-15 16:33:38 +00002194 p = mkFormD(p, opc1, r_srcL, r_dst, imm_srcR);
cerionab9132d2005-02-15 15:46:59 +00002195 }
cerionab9132d2005-02-15 15:46:59 +00002196 }
cerionb85e8bb2005-02-16 08:54:33 +00002197 goto done;
cerionab9132d2005-02-15 15:46:59 +00002198 }
2199
cerion5e2527e2005-02-25 16:39:58 +00002200 case Pin_Sub32: {
ceriona2f75882005-03-15 16:33:38 +00002201 UInt r_dst = iregNo(i->Pin.Sub32.dst);
2202 UInt r_srcR = iregNo(i->Pin.Sub32.srcR);
2203 UInt r_srcL, imm_srcL;
cerion5e2527e2005-02-25 16:39:58 +00002204
2205 // Note argument swap: PPC32 only has sub-from instrs
ceriona2f75882005-03-15 16:33:38 +00002206 switch (i->Pin.Sub32.srcL->tag) {
cerion5e2527e2005-02-25 16:39:58 +00002207 case Pri_Reg:
ceriona2f75882005-03-15 16:33:38 +00002208 r_srcL = iregNo(i->Pin.Sub32.srcL->Pri.Reg.reg);
2209 // subf r_dst, r_srcR, r_srcL
2210 p = mkFormXO(p, 31, r_dst, r_srcR, r_srcL, 0, 40, 0);
cerion5e2527e2005-02-25 16:39:58 +00002211 break;
2212 case Pri_Imm:
ceriona2f75882005-03-15 16:33:38 +00002213 imm_srcL = i->Pin.Sub32.srcL->Pri.Imm.imm32;
2214 // subf r_dst, r_srcR, imm_srcL
2215 p = mkFormD(p, 8, r_dst, r_srcR, imm_srcL);
cerion5e2527e2005-02-25 16:39:58 +00002216 break;
2217 default:
2218 goto bad;
2219 }
2220 goto done;
2221 }
2222
cerionab9132d2005-02-15 15:46:59 +00002223 case Pin_Sh32: {
ceriona2f75882005-03-15 16:33:38 +00002224 UInt opc1 = 31, opc2, r_shft, imm_shft;
cerionb85e8bb2005-02-16 08:54:33 +00002225 UInt op = i->Pin.Sh32.op;
ceriona2f75882005-03-15 16:33:38 +00002226 UInt r_src = iregNo(i->Pin.Sh32.src);
2227 UInt r_dst = iregNo(i->Pin.Sh32.dst);
cerionab9132d2005-02-15 15:46:59 +00002228
cerionab9132d2005-02-15 15:46:59 +00002229 switch (i->Pin.Sh32.shft->tag) {
2230 case Pri_Reg:
cerion9e263e32005-03-03 17:21:51 +00002231 switch (op) {
2232 case Psh_SHL: opc2 = 24; break;
2233 case Psh_SHR: opc2 = 536; break;
2234 case Psh_SAR: opc2 = 792; break;
2235 default: goto bad;
2236 }
ceriona2f75882005-03-15 16:33:38 +00002237 r_shft = iregNo(i->Pin.Sh32.shft->Pri.Reg.reg);
2238 p = mkFormX(p, opc1, r_src, r_dst, r_shft, opc2, 0);
cerionb85e8bb2005-02-16 08:54:33 +00002239 break;
cerion9e263e32005-03-03 17:21:51 +00002240
2241 case Pri_Imm: // SAR only
2242 if (op != Psh_SAR) goto bad;
2243 opc2 = 824;
ceriona2f75882005-03-15 16:33:38 +00002244 imm_shft = i->Pin.Sh32.shft->Pri.Imm.imm32;
2245 p = mkFormX(p, opc1, r_src, r_dst, imm_shft, opc2, 0);
cerionb85e8bb2005-02-16 08:54:33 +00002246 break;
cerion9e263e32005-03-03 17:21:51 +00002247
cerionab9132d2005-02-15 15:46:59 +00002248 default:
2249 goto bad;
2250 }
cerionb85e8bb2005-02-16 08:54:33 +00002251 goto done;
cerionab9132d2005-02-15 15:46:59 +00002252 }
cerion2c49e032005-02-09 17:29:49 +00002253
cerion98411db2005-02-16 14:14:49 +00002254 case Pin_Cmp32: {
2255 UInt opc1, opc2=0;
2256 UInt op = i->Pin.Cmp32.op;
cerione97e1062005-02-21 15:09:19 +00002257 UInt fld1 = (7 - i->Pin.Cmp32.crfD) << 2;
ceriona2f75882005-03-15 16:33:38 +00002258 UInt r_srcL = iregNo(i->Pin.Cmp32.srcL);
2259 UInt r_srcR, imm_srcR;
cerionab9132d2005-02-15 15:46:59 +00002260
ceriona2f75882005-03-15 16:33:38 +00002261 switch (i->Pin.Cmp32.srcR->tag) {
cerion98411db2005-02-16 14:14:49 +00002262 case Pri_Imm:
2263 opc1 = (op == Pcmp_U) ? 10 : 11;
ceriona2f75882005-03-15 16:33:38 +00002264 imm_srcR = i->Pin.Cmp32.srcR->Pri.Imm.imm32;
2265 p = mkFormD(p, opc1, fld1, r_srcL, imm_srcR);
cerion98411db2005-02-16 14:14:49 +00002266 break;
2267 case Pri_Reg:
2268 opc1 = 31;
2269 opc2 = (op == Pcmp_U) ? 32 : 0;
ceriona2f75882005-03-15 16:33:38 +00002270 r_srcR = iregNo(i->Pin.Cmp32.srcR->Pri.Reg.reg);
2271 p = mkFormX(p, opc1, fld1, r_srcL, r_srcR, opc2, 0);
cerion98411db2005-02-16 14:14:49 +00002272 break;
2273 default: goto bad;
2274 }
2275 goto done;
2276 }
cerionb536af92005-02-10 15:03:19 +00002277
cerion98411db2005-02-16 14:14:49 +00002278 case Pin_Unary32: {
2279 UInt r_dst = iregNo(i->Pin.Unary32.dst);
2280 UInt r_src = iregNo(i->Pin.Unary32.src);
2281
2282 switch (i->Pin.Unary32.op) {
2283 case Pun_NOT: // nor r_dst,r_src,r_src
2284 p = mkFormX(p, 31, r_src, r_dst, r_src, 124, 0);
2285 break;
2286 case Pun_NEG: // neg r_dst,r_src
2287 p = mkFormXO(p, 31, r_dst, r_src, 0, 0, 104, 0);
2288 break;
2289 case Pun_CLZ: // cntlzw r_dst, r_src
cerion99f35772005-03-15 16:36:02 +00002290 p = mkFormX(p, 31, r_src, r_dst, 0, 26, 0);
cerion98411db2005-02-16 14:14:49 +00002291 break;
2292 default: goto bad;
2293 }
2294 goto done;
2295 }
2296
2297 case Pin_MulL: {
2298 Bool syned = i->Pin.MulL.syned;
2299 UInt r_dst = iregNo(i->Pin.MulL.dst);
ceriona2f75882005-03-15 16:33:38 +00002300 UInt r_srcL = iregNo(i->Pin.MulL.srcL);
2301 UInt r_srcR, imm;
cerion98411db2005-02-16 14:14:49 +00002302
2303 switch (i->Pin.MulL.word) {
cerion9e263e32005-03-03 17:21:51 +00002304 case 0: // Mult LOW word
ceriona2f75882005-03-15 16:33:38 +00002305 switch (i->Pin.MulL.srcR->tag) {
cerion98411db2005-02-16 14:14:49 +00002306 case Pri_Reg:
ceriona2f75882005-03-15 16:33:38 +00002307 // mullw r_dst,r_srcL,r_srcR
cerion98411db2005-02-16 14:14:49 +00002308 // sign makes no difference.
ceriona2f75882005-03-15 16:33:38 +00002309 r_srcR = iregNo(i->Pin.MulL.srcR->Pri.Reg.reg);
2310 p = mkFormXO(p, 31, r_dst, r_srcL, r_srcR, 0, 235, 0);
cerion98411db2005-02-16 14:14:49 +00002311 break;
2312 case Pri_Imm:
2313 // mulli r_dst,r_src,imm
2314 vassert(syned == True); // always signed
ceriona2f75882005-03-15 16:33:38 +00002315 imm = i->Pin.MulL.srcR->Pri.Imm.imm32;
2316 p = mkFormD(p, 07, r_dst, r_srcL, imm);
cerion98411db2005-02-16 14:14:49 +00002317 break;
2318 default:
2319 goto bad;
2320 }
2321 break;
cerion9e263e32005-03-03 17:21:51 +00002322
2323 case 1: // Mult HIGH word
ceriona2f75882005-03-15 16:33:38 +00002324 vassert(i->Pin.MulL.srcR->tag == Pri_Reg);
2325 r_srcR = iregNo(i->Pin.MulL.srcR->Pri.Reg.reg);
cerion98411db2005-02-16 14:14:49 +00002326 if (syned == True) {
ceriona2f75882005-03-15 16:33:38 +00002327 // mulhw r_dst,r_srcL,r_srcR
2328 p = mkFormXO(p, 31, r_dst, r_srcL, r_srcR, 0, 75, 0);
cerion98411db2005-02-16 14:14:49 +00002329 } else {
ceriona2f75882005-03-15 16:33:38 +00002330 // mulhwu r_dst,r_srcL,r_srcR
2331 p = mkFormXO(p, 31, r_dst, r_srcL, r_srcR, 0, 11, 0);
cerion98411db2005-02-16 14:14:49 +00002332 }
2333 break;
cerion9e263e32005-03-03 17:21:51 +00002334
2335 default: goto bad;
cerion98411db2005-02-16 14:14:49 +00002336 }
2337 goto done;
2338 }
cerion2c49e032005-02-09 17:29:49 +00002339
cerionfd0b87f2005-02-16 14:43:14 +00002340 case Pin_Div: {
2341 Bool syned = i->Pin.MulL.syned;
2342 UInt r_dst = iregNo(i->Pin.Div.dst);
ceriona2f75882005-03-15 16:33:38 +00002343 UInt r_srcL = iregNo(i->Pin.Div.srcL);
2344 UInt r_srcR = iregNo(i->Pin.Div.srcR);
cerionfd0b87f2005-02-16 14:43:14 +00002345
2346 if (syned == True) {
ceriona2f75882005-03-15 16:33:38 +00002347 // divw r_dst,r_srcL,r_srcR
2348 p = mkFormXO(p, 31, r_dst, r_srcL, r_srcR, 0, 491, 0);
cerionfd0b87f2005-02-16 14:43:14 +00002349 } else {
ceriona2f75882005-03-15 16:33:38 +00002350 // divwu r_dst,r_srcL,r_srcR
2351 p = mkFormXO(p, 31, r_dst, r_srcL, r_srcR, 0, 459, 0);
cerionfd0b87f2005-02-16 14:43:14 +00002352 }
2353 goto done;
2354 }
cerion2c49e032005-02-09 17:29:49 +00002355
cerion33aa6da2005-02-16 10:25:26 +00002356 case Pin_Call: {
cerion7cf8e4e2005-02-16 16:08:17 +00002357 PPC32CondCode cond = i->Pin.Call.cond;
ceriona56e9cc2005-02-16 18:08:25 +00002358 UInt r_dst = 12;
2359 /* As per detailed comment for Pin_Call in
cerion9e263e32005-03-03 17:21:51 +00002360 getRegUsage_PPC32Instr above, %r12 is used as an address temp */
ceriona56e9cc2005-02-16 18:08:25 +00002361
cerioned623db2005-06-20 12:42:04 +00002362 /* jump over the following insns if condition does not hold */
cerione97e1062005-02-21 15:09:19 +00002363 if (cond.test != Pct_ALWAYS) {
cerion9762bbf2005-06-23 08:44:52 +00002364 /* jmp fwds if !condition */
2365 /* don't know how many bytes to jump over yet...
2366 make space for a jump instruction and fill in later. */
2367 ptmp = p; /* fill in this bit later */
2368 p += 4; // p += 4
cerionab9132d2005-02-15 15:46:59 +00002369 }
2370
cerione97e1062005-02-21 15:09:19 +00002371 /* load target to r_dst */
cerion9762bbf2005-06-23 08:44:52 +00002372 p = mkLoadImm(p, r_dst, i->Pin.Call.target); // p += 4|8
cerionab9132d2005-02-15 15:46:59 +00002373
ceriona56e9cc2005-02-16 18:08:25 +00002374 /* mtspr 9,r_dst => move r_dst to count register */
cerion9762bbf2005-06-23 08:44:52 +00002375 p = mkFormXFX(p, r_dst, 9, 467); // p += 4
cerion33aa6da2005-02-16 10:25:26 +00002376
cerion8c51ed42005-02-22 11:16:54 +00002377 /* bctrl => branch to count register (and save to lr) */
cerion9762bbf2005-06-23 08:44:52 +00002378 p = mkFormXL(p, 19, Pct_ALWAYS, 0, 0, 528, 1); // p += 4
2379
2380 /* Fix up the conditional jump, if there was one. */
2381 if (cond.test != Pct_ALWAYS) {
2382 Int delta = p - ptmp;
2383 vassert(delta >= 16 && delta <= 20);
2384 /* bc !ct,cf,delta */
2385 mkFormB(ptmp, invertCondTest(cond.test), cond.flag, (delta>>2), 0, 0);
2386 }
cerion33aa6da2005-02-16 10:25:26 +00002387 goto done;
2388 }
2389
2390 case Pin_Goto: {
2391 UInt magic_num = 0;
cerione97e1062005-02-21 15:09:19 +00002392 UChar r_return = 3; /* Put target addr into %r3 */
cerion33aa6da2005-02-16 10:25:26 +00002393 PPC32CondCode cond = i->Pin.Goto.cond;
ceriona2f75882005-03-15 16:33:38 +00002394 UInt r_dst, imm_dst;
cerion33aa6da2005-02-16 10:25:26 +00002395
2396 /* First off, if this is conditional, create a conditional
2397 jump over the rest of it. */
2398 if (cond.test != Pct_ALWAYS) {
2399 /* jmp fwds if !condition */
cerione97e1062005-02-21 15:09:19 +00002400 /* don't know how many bytes to jump over yet...
2401 make space for a jump instruction and fill in later. */
cerion7cf8e4e2005-02-16 16:08:17 +00002402 ptmp = p; /* fill in this bit later */
cerione97e1062005-02-21 15:09:19 +00002403 p += 4;
cerion33aa6da2005-02-16 10:25:26 +00002404 }
2405
cerione97e1062005-02-21 15:09:19 +00002406 // cond succeeds...
2407
cerion33aa6da2005-02-16 10:25:26 +00002408 /* If a non-boring, set GuestStatePtr appropriately. */
cerion33aa6da2005-02-16 10:25:26 +00002409 switch (i->Pin.Goto.jk) {
2410 case Ijk_ClientReq: magic_num = VEX_TRC_JMP_CLIENTREQ; break;
2411 case Ijk_Syscall: magic_num = VEX_TRC_JMP_SYSCALL; break;
2412 case Ijk_Yield: magic_num = VEX_TRC_JMP_YIELD; break;
2413 case Ijk_EmWarn: magic_num = VEX_TRC_JMP_EMWARN; break;
2414 case Ijk_MapFail: magic_num = VEX_TRC_JMP_MAPFAIL; break;
2415 case Ijk_NoDecode: magic_num = VEX_TRC_JMP_NODECODE; break;
sewardj7ce9d152005-03-15 16:54:13 +00002416 case Ijk_TInval: magic_num = VEX_TRC_JMP_TINVAL; break;
cerion33aa6da2005-02-16 10:25:26 +00002417 case Ijk_Ret:
2418 case Ijk_Call:
2419 case Ijk_Boring:
2420 break;
2421 default:
2422 ppIRJumpKind(i->Pin.Goto.jk);
2423 vpanic("emit_PPC32Instr.Pin_Goto: unknown jump kind");
2424 }
2425 if (magic_num !=0) {
2426 vassert(magic_num < 0x10000);
cerione97e1062005-02-21 15:09:19 +00002427 /* addi r31,0,magic_num */
cerioned623db2005-06-20 12:42:04 +00002428 p = mkFormD(p, 14, 31, 0, magic_num); // p += 4
cerion33aa6da2005-02-16 10:25:26 +00002429 }
2430
cerione97e1062005-02-21 15:09:19 +00002431 /* Get the destination address into %r_return */
cerion33aa6da2005-02-16 10:25:26 +00002432 if (i->Pin.Goto.dst->tag == Pri_Imm) {
ceriona2f75882005-03-15 16:33:38 +00002433 imm_dst = i->Pin.Goto.dst->Pri.Imm.imm32;
cerioned623db2005-06-20 12:42:04 +00002434 p = mkLoadImm(p, r_return, imm_dst); // p += 4|8
cerion33aa6da2005-02-16 10:25:26 +00002435 } else {
2436 vassert(i->Pin.Goto.dst->tag == Pri_Reg);
sewardj9a036bf2005-03-14 18:19:08 +00002437 r_dst = iregNo(i->Pin.Goto.dst->Pri.Reg.reg);
cerioned623db2005-06-20 12:42:04 +00002438 p = mkMoveReg(p, r_return, r_dst); // p += 4
cerion33aa6da2005-02-16 10:25:26 +00002439 }
cerione97e1062005-02-21 15:09:19 +00002440
2441 /* blr */
cerioned623db2005-06-20 12:42:04 +00002442 p = mkFormXL(p, 19, Pct_ALWAYS, 0, 0, 16, 0); // p += 4
cerion7cf8e4e2005-02-16 16:08:17 +00002443
2444 /* Fix up the conditional jump, if there was one. */
2445 if (cond.test != Pct_ALWAYS) {
2446 Int delta = p - ptmp;
cerioned623db2005-06-20 12:42:04 +00002447 vassert(delta >= 12 && delta <= 20);
cerione97e1062005-02-21 15:09:19 +00002448 /* bc !ct,cf,delta */
2449 mkFormB(ptmp, invertCondTest(cond.test), cond.flag, (delta>>2), 0, 0);
cerion7cf8e4e2005-02-16 16:08:17 +00002450 }
cerion33aa6da2005-02-16 10:25:26 +00002451 goto done;
2452 }
cerionb536af92005-02-10 15:03:19 +00002453
cerion98411db2005-02-16 14:14:49 +00002454 case Pin_CMov32: {
ceriona2f75882005-03-15 16:33:38 +00002455 UInt r_dst, imm_src, r_src;
sewardj9a036bf2005-03-14 18:19:08 +00002456 PPC32CondCode cond;
cerion98411db2005-02-16 14:14:49 +00002457 vassert(i->Pin.CMov32.cond.test != Pct_ALWAYS);
ceriona2f75882005-03-15 16:33:38 +00002458
sewardj9a036bf2005-03-14 18:19:08 +00002459 r_dst = iregNo(i->Pin.CMov32.dst);
2460 cond = i->Pin.CMov32.cond;
cerion98411db2005-02-16 14:14:49 +00002461
cerione97e1062005-02-21 15:09:19 +00002462 /* branch (if cond fails) over move instrs */
2463 if (cond.test != Pct_ALWAYS) {
2464 /* don't know how many bytes to jump over yet...
2465 make space for a jump instruction and fill in later. */
2466 ptmp = p; /* fill in this bit later */
2467 p += 4;
2468 }
cerion98411db2005-02-16 14:14:49 +00002469
2470 // cond true: move src => dst
2471 switch (i->Pin.CMov32.src->tag) {
2472 case Pri_Imm:
ceriona2f75882005-03-15 16:33:38 +00002473 imm_src = i->Pin.CMov32.src->Pri.Imm.imm32;
2474 p = mkLoadImm(p, r_dst, imm_src);
cerion98411db2005-02-16 14:14:49 +00002475 break;
2476 case Pri_Reg:
2477 r_src = iregNo(i->Pin.CMov32.src->Pri.Reg.reg);
cerione97e1062005-02-21 15:09:19 +00002478 p = mkMoveReg(p, r_dst, r_src);
cerion98411db2005-02-16 14:14:49 +00002479 break;
2480 default: goto bad;
2481 }
cerione97e1062005-02-21 15:09:19 +00002482
2483 /* Fix up the conditional jump, if there was one. */
2484 if (cond.test != Pct_ALWAYS) {
2485 Int delta = p - ptmp;
2486 vassert(delta >= 4 && delta <= 12);
2487 /* bc !ct,cf,delta */
2488 mkFormB(ptmp, invertCondTest(cond.test), cond.flag, (delta>>2), 0, 0);
2489 }
cerion98411db2005-02-16 14:14:49 +00002490 goto done;
2491 }
cerionb536af92005-02-10 15:03:19 +00002492
cerion7cf8e4e2005-02-16 16:08:17 +00002493 case Pin_Load: {
cerioned623db2005-06-20 12:42:04 +00002494 PPC32AMode* am_addr = i->Pin.Load.src;
2495 UInt r_dst = iregNo(i->Pin.Load.dst);
cerion7cf8e4e2005-02-16 16:08:17 +00002496 Bool syned = i->Pin.Load.syned;
ceriona2f75882005-03-15 16:33:38 +00002497 UInt opc1, opc2, sz = i->Pin.Load.sz;
cerion7cf8e4e2005-02-16 16:08:17 +00002498 switch (i->Pin.Load.src->tag) {
ceriond5e38382005-02-11 13:38:15 +00002499 case Pam_IR:
cerionab9132d2005-02-15 15:46:59 +00002500 if (sz == 2) { // the only signed load
ceriona2f75882005-03-15 16:33:38 +00002501 opc1 = (syned) ? 42: 40;
cerionab9132d2005-02-15 15:46:59 +00002502 } else {
cerion7cf8e4e2005-02-16 16:08:17 +00002503 vassert(syned == False);
ceriona2f75882005-03-15 16:33:38 +00002504 opc1 = (sz == 1) ? 34 : 32; // 1:4
cerionab9132d2005-02-15 15:46:59 +00002505 }
cerioned623db2005-06-20 12:42:04 +00002506 p = doAMode_IR(p, opc1, r_dst, am_addr);
cerionab9132d2005-02-15 15:46:59 +00002507 goto done;
ceriond5e38382005-02-11 13:38:15 +00002508 case Pam_RR:
cerionab9132d2005-02-15 15:46:59 +00002509 if (sz == 2) { // the only signed load
ceriona2f75882005-03-15 16:33:38 +00002510 opc2 = (syned) ? 343: 279;
cerionab9132d2005-02-15 15:46:59 +00002511 } else {
cerion7cf8e4e2005-02-16 16:08:17 +00002512 vassert(syned == False);
ceriona2f75882005-03-15 16:33:38 +00002513 opc2 = (sz == 1) ? 87 : 23; // 1:4
cerionab9132d2005-02-15 15:46:59 +00002514 }
cerioned623db2005-06-20 12:42:04 +00002515 p = doAMode_RR(p, 31, opc2, r_dst, am_addr);
cerionab9132d2005-02-15 15:46:59 +00002516 goto done;
ceriond5e38382005-02-11 13:38:15 +00002517 default:
cerionab9132d2005-02-15 15:46:59 +00002518 goto bad;
ceriond5e38382005-02-11 13:38:15 +00002519 }
2520 }
cerionb536af92005-02-10 15:03:19 +00002521
cerionab9132d2005-02-15 15:46:59 +00002522 case Pin_Set32: {
2523 /* Make the destination register be 1 or 0, depending on whether
cerion9e263e32005-03-03 17:21:51 +00002524 the relevant condition holds. */
cerion98411db2005-02-16 14:14:49 +00002525 UInt r_dst = iregNo(i->Pin.Set32.dst);
2526 PPC32CondCode cond = i->Pin.Set32.cond;
cerion7cf8e4e2005-02-16 16:08:17 +00002527 UInt rot_imm;
cerion98411db2005-02-16 14:14:49 +00002528 UInt r_tmp;
2529
2530 if (cond.test == Pct_ALWAYS) {
cerion9e263e32005-03-03 17:21:51 +00002531 // Just load 1 to dst => li dst,1
cerion98411db2005-02-16 14:14:49 +00002532 p = mkFormD(p, 14, r_dst, 0, 1);
cerionab9132d2005-02-15 15:46:59 +00002533 } else {
cerion7cf8e4e2005-02-16 16:08:17 +00002534 rot_imm = 1 + cond.flag;
ceriona56e9cc2005-02-16 18:08:25 +00002535 r_tmp = 0; // Not within scope of regalloc, so no need to declare.
cerion98411db2005-02-16 14:14:49 +00002536
2537 // r_tmp = CR => mfcr r_tmp
2538 p = mkFormX(p, 31, r_tmp, 0, 0, 19, 0);
2539
2540 // r_dst = flag (rotate left and mask)
cerion7cf8e4e2005-02-16 16:08:17 +00002541 // => rlwinm r_dst,r_tmp,rot_imm,31,31
cerione97e1062005-02-21 15:09:19 +00002542 p = mkFormM(p, 21, r_tmp, r_dst, rot_imm, 31, 31, 0);
cerion98411db2005-02-16 14:14:49 +00002543
2544 if (cond.test == Pct_FALSE) {
ceriona2f75882005-03-15 16:33:38 +00002545 // flip bit => xori r_dst,r_dst,1
cerion98411db2005-02-16 14:14:49 +00002546 p = mkFormD(p, 26, r_dst, r_dst, 1);
cerionab9132d2005-02-15 15:46:59 +00002547 }
2548 }
2549 goto done;
cerionab9132d2005-02-15 15:46:59 +00002550 }
cerionb536af92005-02-10 15:03:19 +00002551
cerion98411db2005-02-16 14:14:49 +00002552 case Pin_MFence: {
cerioned623db2005-06-20 12:42:04 +00002553 p = mkFormX(p, 31, 0, 0, 0, 598, 0); // sync, PPC32 p616
2554// CAB: Should this be isync?
2555// p = mkFormXL(p, 19, 0, 0, 0, 150, 0); // isync, PPC32 p467
cerion98411db2005-02-16 14:14:49 +00002556 goto done;
2557 }
cerionb536af92005-02-10 15:03:19 +00002558
ceriond5e38382005-02-11 13:38:15 +00002559 case Pin_Store: {
cerioned623db2005-06-20 12:42:04 +00002560 PPC32AMode* am_addr = i->Pin.Store.dst;
2561 UInt r_src = iregNo(i->Pin.Store.src);
ceriona2f75882005-03-15 16:33:38 +00002562 UInt opc1, opc2, sz = i->Pin.Store.sz;
ceriond5e38382005-02-11 13:38:15 +00002563 switch (i->Pin.Store.dst->tag) {
2564 case Pam_IR:
ceriona2f75882005-03-15 16:33:38 +00002565 opc1 = (sz == 1) ? 38 : ((sz == 2) ? 44 : 36); // 1:2:4
cerioned623db2005-06-20 12:42:04 +00002566 p = doAMode_IR(p, opc1, r_src, am_addr);
cerionab9132d2005-02-15 15:46:59 +00002567 goto done;
ceriond5e38382005-02-11 13:38:15 +00002568 case Pam_RR:
ceriona2f75882005-03-15 16:33:38 +00002569 opc2 = (sz == 1) ? 215 : ((sz == 2) ? 407 : 151); // 1:2:4
cerioned623db2005-06-20 12:42:04 +00002570 p = doAMode_RR(p, 31, opc2, r_src, am_addr);
cerionab9132d2005-02-15 15:46:59 +00002571 goto done;
ceriond5e38382005-02-11 13:38:15 +00002572 default:
cerionab9132d2005-02-15 15:46:59 +00002573 goto bad;
ceriond5e38382005-02-11 13:38:15 +00002574 }
2575 goto done;
2576 }
cerionb536af92005-02-10 15:03:19 +00002577
cerion094d1392005-06-20 13:45:57 +00002578 case Pin_FpUnary: {
2579 UInt fr_dst = fregNo(i->Pin.FpUnary.dst);
2580 UInt fr_src = fregNo(i->Pin.FpUnary.src);
2581 switch (i->Pin.FpUnary.op) {
2582 case Pfp_SQRT: // fsqrt, PPC32 p427
2583 p = mkFormA( p, 63, fr_dst, 0, fr_src, 0, 22, 0 );
2584 break;
2585 case Pfp_ABS: // fabs, PPC32 p399
2586 p = mkFormX(p, 63, fr_dst, 0, fr_src, 264, 0);
2587 break;
2588 case Pfp_NEG: // fneg, PPC32 p416
2589 p = mkFormX(p, 63, fr_dst, 0, fr_src, 40, 0);
2590 break;
2591 case Pfp_MOV: // fmr, PPC32 p410
2592 p = mkFormX(p, 63, fr_dst, 0, fr_src, 72, 0);
2593 break;
2594 default:
2595 goto bad;
2596 }
2597 goto done;
2598 }
2599
2600 case Pin_FpBinary: {
2601 UInt fr_dst = fregNo(i->Pin.FpBinary.dst);
2602 UInt fr_srcL = fregNo(i->Pin.FpBinary.srcL);
2603 UInt fr_srcR = fregNo(i->Pin.FpBinary.srcR);
2604 switch (i->Pin.FpBinary.op) {
2605 case Pfp_ADD: // fadd, PPC32 p400
2606 p = mkFormA( p, 63, fr_dst, fr_srcL, fr_srcR, 0, 21, 0 );
2607 break;
2608 case Pfp_SUB: // fsub, PPC32 p429
2609 p = mkFormA( p, 63, fr_dst, fr_srcL, fr_srcR, 0, 20, 0 );
2610 break;
2611 case Pfp_MUL: // fmul, PPC32 p413
2612 p = mkFormA( p, 63, fr_dst, fr_srcL, 0, fr_srcR, 25, 0 );
2613 break;
2614 case Pfp_DIV: // fdiv, PPC32 p406
2615 p = mkFormA( p, 63, fr_dst, fr_srcL, fr_srcR, 0, 18, 0 );
2616 break;
2617 default:
2618 goto bad;
2619 }
2620 goto done;
2621 }
2622
2623 case Pin_FpLdSt: {
2624 PPC32AMode* am_addr = i->Pin.FpLdSt.addr;
2625 UInt f_reg = fregNo(i->Pin.FpLdSt.reg);
2626 Bool idxd = toBool(i->Pin.FpLdSt.addr->tag == Pam_RR);
2627 UChar sz = i->Pin.FpLdSt.sz;
2628 vassert(sz == 4 || sz == 8);
2629
2630 if (i->Pin.FpLdSt.isLoad) { // Load from memory
2631 if (idxd) { // lf[s|d]x, PPC32 p444|440
2632 p = doAMode_RR(p, 31, ((sz == 4) ? 535 : 599), f_reg, am_addr);
2633 } else { // lf[s|d], PPC32 p441|437
2634 p = doAMode_IR(p, ((sz == 4) ? 48 : 50), f_reg, am_addr);
2635 }
2636 } else { // Store to memory
2637 if (idxd) { // stf[s|d]x, PPC32 p521|516
2638 p = doAMode_RR(p, 31, ((sz == 4) ? 663 : 727), f_reg, am_addr);
2639 } else { // stf[s|d], PPC32 p518|513
2640 p = doAMode_IR(p, ((sz == 4) ? 52 : 54), f_reg, am_addr);
2641 }
2642 }
2643 goto done;
2644 }
2645
2646 case Pin_FpF64toF32: {
2647 UInt fr_dst = fregNo(i->Pin.FpF64toF32.dst);
2648 UInt fr_src = fregNo(i->Pin.FpF64toF32.src);
2649 // frsp, PPC32 p423
2650 p = mkFormX(p, 63, fr_dst, 0, fr_src, 12, 0);
2651 goto done;
2652 }
2653
2654 case Pin_FpF64toI32: {
2655 UInt r_dst = iregNo(i->Pin.FpF64toI32.dst);
2656 UInt fr_src = fregNo(i->Pin.FpF64toI32.src);
2657 UChar fr_tmp = 7; // Temp freg
2658 PPC32AMode* am_addr;
2659
2660 // fctiw (conv f64 to i32), PPC32 p404
2661 p = mkFormX(p, 63, fr_tmp, 0, fr_src, 14, 0);
2662
2663 // No RI form of stfiwx, so need PPC32AMode_RR:
2664 am_addr = PPC32AMode_RR( StackFramePtr, hregPPC32_GPR0() );
2665
2666 // stfiwx (store fp64[lo32] as int32), PPC32 p517
2667 p = doAMode_RR(p, 31, 983, fr_tmp, am_addr);
2668
2669 // lwzx (load int32), PPC32 p463
2670 p = doAMode_RR(p, 31, 23, r_dst, am_addr);
2671 goto done;
2672 }
2673
2674 case Pin_FpCMov: {
2675 UInt fr_dst = fregNo(i->Pin.FpCMov.dst);
2676 UInt fr_src = fregNo(i->Pin.FpCMov.src);
2677 PPC32CondCode cc = i->Pin.FpCMov.cond;
2678
2679 if (fr_dst == fr_src) goto done;
2680
2681 vassert(cc.test != Pct_ALWAYS);
2682
2683 /* jmp fwds if !condition */
2684 if (cc.test != Pct_ALWAYS) {
2685 /* bc !ct,cf,n_bytes>>2 */
2686 p = mkFormB(p, invertCondTest(cc.test), cc.flag, 8>>2, 0, 0);
2687 }
2688
2689 // fmr, PPC32 p410
2690 p = mkFormX(p, 63, fr_dst, 0, fr_src, 72, 0);
2691 goto done;
2692 }
2693
2694 case Pin_FpLdFPSCR: {
2695 UInt fr_src = fregNo(i->Pin.FpLdFPSCR.src);
2696 p = mkFormXFL(p, 0xFF, fr_src); // mtfsf, PPC32 p480
2697 goto done;
2698 }
2699
2700 case Pin_FpCmp: {
2701 UChar crfD = 1;
2702 UInt r_dst = iregNo(i->Pin.FpCmp.dst);
2703 UInt fr_srcL = fregNo(i->Pin.FpCmp.srcL);
2704 UInt fr_srcR = fregNo(i->Pin.FpCmp.srcR);
2705 vassert(crfD < 8);
2706 // fcmpo, PPC32 p402
2707 p = mkFormX(p, 63, (crfD<<2), fr_srcL, fr_srcR, 32, 0);
2708
2709 // mfcr (mv CR to r_dst), PPC32 p467
2710 p = mkFormX(p, 31, r_dst, 0, 0, 19, 0);
2711
2712 // rlwinm r_dst,r_dst,8,28,31, PPC32 p501
2713 // => rotate field 6 to field 0, masking to field 0
2714 p = mkFormM(p, 21, r_dst, r_dst, 8, 28, 31, 0);
2715 goto done;
2716 }
cerionbcf8c3e2005-02-04 16:17:07 +00002717
cerion7f000af2005-02-22 20:36:49 +00002718 case Pin_RdWrLR: {
2719 UInt reg = iregNo(i->Pin.RdWrLR.gpr);
2720 /* wrLR==True ? mtlr r4 : mflr r4 */
2721 p = mkFormXFX(p, reg, 8, (i->Pin.RdWrLR.wrLR==True) ? 467 : 339);
2722 goto done;
2723 }
2724
cerionc3d8bdc2005-06-28 18:06:23 +00002725
2726 /* AltiVec */
2727 case Pin_AvLdSt: {
2728 UInt opc2, v_reg, r_idx, r_base;
2729 UChar sz = i->Pin.AvLdSt.sz;
2730 Bool idxd = toBool(i->Pin.AvLdSt.addr->tag == Pam_RR);
2731 vassert(sz == 8 || sz == 16 || sz == 32 || sz == 128);
2732
2733 v_reg = vregNo(i->Pin.AvLdSt.reg);
2734 r_base = iregNo(i->Pin.AvLdSt.addr->Pam.RR.base);
2735
2736 // Only have AltiVec AMode_RR: kludge AMode_IR
2737 if (!idxd) {
2738 r_idx = 30; // XXX: Using r30 as temp
2739 p = mkLoadImm(p, r_idx, i->Pin.AvLdSt.addr->Pam.IR.index);
2740 } else {
2741 r_idx = iregNo(i->Pin.AvLdSt.addr->Pam.RR.index);
2742 }
2743
2744 if (i->Pin.FpLdSt.isLoad) { // Load from memory (8,16,32,128)
2745 opc2 = (sz == 8) ? 7 : (sz == 16) ? 39 : (sz == 32) ? 71 : 103;
2746 p = mkFormX(p, 31, v_reg, r_idx, r_base, opc2, 0);
2747 } else { // Store to memory (8,16,32,128)
2748 opc2 = (sz == 8) ? 135 : (sz == 16) ? 167 : (sz == 32) ? 199 : 231;
2749 p = mkFormX(p, 31, v_reg, r_idx, r_base, opc2, 0);
2750 }
2751 goto done;
2752 }
2753
2754 case Pin_AvUnary: {
2755 UInt v_dst = vregNo(i->Pin.AvUnary.dst);
2756 UInt v_src = vregNo(i->Pin.AvUnary.src);
2757 UInt opc2;
2758 switch (i->Pin.AvUnary.op) {
2759 case Pav_MOV: opc2 = 1156; break; // vor vD,vS,vS
2760 case Pav_NOT: opc2 = 1284; break; // vnor vD,vS,vS
2761 case Pav_UNPCKH8S: opc2 = 526; break; // vupkhsb
2762 case Pav_UNPCKH16S: opc2 = 590; break; // vupkhsh
2763 case Pav_UNPCKL8S: opc2 = 654; break; // vupklsb
2764 case Pav_UNPCKL16S: opc2 = 718; break; // vupklsh
2765 case Pav_UNPCKHPIX: opc2 = 846; break; // vupkhpx
2766 case Pav_UNPCKLPIX: opc2 = 974; break; // vupklpx
2767 default:
2768 goto bad;
2769 }
2770 switch (i->Pin.AvUnary.op) {
2771 case Pav_MOV:
2772 case Pav_NOT:
2773 p = mkFormVX( p, 4, v_dst, v_src, v_src, opc2 );
2774 break;
2775 default:
2776 p = mkFormVX( p, 4, v_dst, 0, v_src, opc2 );
2777 break;
2778 }
2779 goto done;
2780 }
2781
2782 case Pin_AvBinary: {
2783 UInt v_dst = vregNo(i->Pin.AvBinary.dst);
2784 UInt v_srcL = vregNo(i->Pin.AvBinary.srcL);
2785 UInt v_srcR = vregNo(i->Pin.AvBinary.srcR);
2786 UInt opc2;
2787 switch (i->Pin.AvBinary.op) {
2788 /* Bitwise */
2789 case Pav_AND: opc2 = 1026; break; // vand
2790 case Pav_OR: opc2 = 1156; break; // vor
2791 case Pav_XOR: opc2 = 1120; break; // vxor
2792
cerionc3d8bdc2005-06-28 18:06:23 +00002793 /* Shift */
cerion6b6f59e2005-06-28 20:59:18 +00002794 case Pav_SHL: opc2 = 452; break; // vsl
2795 case Pav_SHR: opc2 = 708; break; // vsr
cerionc3d8bdc2005-06-28 18:06:23 +00002796
2797 default:
2798 goto bad;
2799 }
2800 p = mkFormVX( p, 4, v_dst, v_srcL, v_srcR, opc2 );
2801 goto done;
2802 }
2803
cerion6b6f59e2005-06-28 20:59:18 +00002804 case Pin_AvBin8x16: {
2805 UInt v_dst = vregNo(i->Pin.AvBin8x16.dst);
2806 UInt v_srcL = vregNo(i->Pin.AvBin8x16.srcL);
2807 UInt v_srcR = vregNo(i->Pin.AvBin8x16.srcR);
2808 UInt opc2;
2809 switch (i->Pin.AvBin8x16.op) {
2810
2811 case Pav_ADDUM: opc2 = 0; break; // vaddubm
2812 case Pav_ADDUS: opc2 = 512; break; // vaddubs
2813 case Pav_ADDSS: opc2 = 768; break; // vaddsbs
2814
2815 case Pav_SUBUM: opc2 = 1024; break; // vsububm
2816 case Pav_SUBUS: opc2 = 1536; break; // vsububs
2817 case Pav_SUBSS: opc2 = 1792; break; // vsubsbs
2818
2819 case Pav_OMULU: opc2 = 8; break; // vmuloub
2820 case Pav_OMULS: opc2 = 264; break; // vmulosb
2821 case Pav_EMULU: opc2 = 520; break; // vmuleub
2822 case Pav_EMULS: opc2 = 776; break; // vmulesb
2823
2824 case Pav_AVGU: opc2 = 1026; break; // vavgub
2825 case Pav_AVGS: opc2 = 1282; break; // vavgsb
2826 case Pav_MAXU: opc2 = 2; break; // vmaxub
2827 case Pav_MAXS: opc2 = 258; break; // vmaxsb
2828 case Pav_MINU: opc2 = 514; break; // vminub
2829 case Pav_MINS: opc2 = 770; break; // vminsb
2830
2831 case Pav_CMPEQU: opc2 = 6; break; // vcmpequb
2832 case Pav_CMPGTU: opc2 = 518; break; // vcmpgtub
2833 case Pav_CMPGTS: opc2 = 774; break; // vcmpgtsb
2834
2835 case Pav_SHL: opc2 = 260; break; // vslb
2836 case Pav_SHR: opc2 = 516; break; // vsrb
2837 case Pav_SAR: opc2 = 772; break; // vsrab
2838 case Pav_ROTL: opc2 = 4; break; // vrlb
2839
2840 case Pav_MRGHI: opc2 = 12; break; // vmrghb
2841 case Pav_MRGLO: opc2 = 268; break; // vmrglb
2842
2843 default:
2844 goto bad;
2845 }
2846 p = mkFormVX( p, 4, v_dst, v_srcL, v_srcR, opc2 );
2847 goto done;
2848 }
2849
2850 case Pin_AvBin16x8: {
2851 UInt v_dst = vregNo(i->Pin.AvBin16x8.dst);
2852 UInt v_srcL = vregNo(i->Pin.AvBin16x8.srcL);
2853 UInt v_srcR = vregNo(i->Pin.AvBin16x8.srcR);
2854 UInt opc2;
2855 switch (i->Pin.AvBin16x8.op) {
2856
2857 case Pav_ADDUM: opc2 = 64; break; // vadduhm
2858 case Pav_ADDUS: opc2 = 576; break; // vadduhs
2859 case Pav_ADDSS: opc2 = 832; break; // vaddshs
2860
2861 case Pav_SUBUM: opc2 = 1088; break; // vsubuhm
2862 case Pav_SUBUS: opc2 = 1600; break; // vsubuhs
2863 case Pav_SUBSS: opc2 = 1856; break; // vsubshs
2864
2865 case Pav_OMULU: opc2 = 72; break; // vmulouh
2866 case Pav_OMULS: opc2 = 328; break; // vmulosh
2867 case Pav_EMULU: opc2 = 584; break; // vmuleuh
2868 case Pav_EMULS: opc2 = 840; break; // vmulesh
2869
2870 case Pav_AVGU: opc2 = 1090; break; // vavguh
2871 case Pav_AVGS: opc2 = 1346; break; // vavgsh
2872 case Pav_MAXU: opc2 = 66; break; // vmaxuh
2873 case Pav_MAXS: opc2 = 322; break; // vmaxsh
2874 case Pav_MINS: opc2 = 834; break; // vminsh
2875 case Pav_MINU: opc2 = 578; break; // vminuh
2876
2877 case Pav_CMPEQU: opc2 = 70; break; // vcmpequh
2878 case Pav_CMPGTU: opc2 = 582; break; // vcmpgtuh
2879 case Pav_CMPGTS: opc2 = 838; break; // vcmpgtsh
2880
2881 case Pav_SHL: opc2 = 324; break; // vslh
2882 case Pav_SHR: opc2 = 580; break; // vsrh
2883 case Pav_SAR: opc2 = 836; break; // vsrah
2884 case Pav_ROTL: opc2 = 68; break; // vrlh
2885
2886 case Pav_PACKUUM: opc2 = 14; break; // vpkuhum
2887 case Pav_PACKUUS: opc2 = 142; break; // vpkuhus
2888 case Pav_PACKSUS: opc2 = 270; break; // vpkshus
2889 case Pav_PACKSSS: opc2 = 398; break; // vpkshss
2890 case Pav_PACKPXL: opc2 = 782; break; // vpkpx
2891
2892 case Pav_MRGHI: opc2 = 76; break; // vmrghh
2893 case Pav_MRGLO: opc2 = 332; break; // vmrglh
2894
2895 default:
2896 goto bad;
2897 }
2898 p = mkFormVX( p, 4, v_dst, v_srcL, v_srcR, opc2 );
2899 goto done;
2900 }
2901
2902 case Pin_AvBin32x4: {
2903 UInt v_dst = vregNo(i->Pin.AvBin32x4.dst);
2904 UInt v_srcL = vregNo(i->Pin.AvBin32x4.srcL);
2905 UInt v_srcR = vregNo(i->Pin.AvBin32x4.srcR);
2906 UInt opc2;
2907 switch (i->Pin.AvBin32x4.op) {
2908
2909 case Pav_ADDUM: opc2 = 128; break; // vadduwm
2910 case Pav_ADDUS: opc2 = 640; break; // vadduws
2911 case Pav_ADDSS: opc2 = 896; break; // vaddsws
2912
2913 case Pav_SUBUM: opc2 = 1152; break; // vsubuwm
2914 case Pav_SUBUS: opc2 = 1664; break; // vsubuws
2915 case Pav_SUBSS: opc2 = 1920; break; // vsubsws
2916
2917 case Pav_AVGU: opc2 = 1154; break; // vavguw
2918 case Pav_AVGS: opc2 = 1410; break; // vavgsw
2919
2920 case Pav_MAXU: opc2 = 130; break; // vmaxuw
2921 case Pav_MAXS: opc2 = 386; break; // vmaxsw
2922
2923 case Pav_MINS: opc2 = 898; break; // vminsw
2924 case Pav_MINU: opc2 = 642; break; // vminuw
2925
2926 case Pav_CMPEQU: opc2 = 134; break; // vcmpequw
2927 case Pav_CMPGTS: opc2 = 902; break; // vcmpgtsw
2928 case Pav_CMPGTU: opc2 = 646; break; // vcmpgtuw
2929
2930 case Pav_SHL: opc2 = 388; break; // vslw
2931 case Pav_SHR: opc2 = 644; break; // vsrw
2932 case Pav_SAR: opc2 = 900; break; // vsraw
2933 case Pav_ROTL: opc2 = 132; break; // vrlw
2934
2935 case Pav_PACKUUM: opc2 = 78; break; // vpkuwum
2936 case Pav_PACKUUS: opc2 = 206; break; // vpkuwus
2937 case Pav_PACKSUS: opc2 = 334; break; // vpkswus
2938 case Pav_PACKSSS: opc2 = 462; break; // vpkswss
2939
2940 case Pav_MRGHI: opc2 = 140; break; // vmrghw
2941 case Pav_MRGLO: opc2 = 396; break; // vmrglw
2942
2943 default:
2944 goto bad;
2945 }
2946 p = mkFormVX( p, 4, v_dst, v_srcL, v_srcR, opc2 );
2947 goto done;
2948 }
2949
2950 case Pin_AvBin32Fx4: {
2951 UInt v_dst = vregNo(i->Pin.AvBin32Fx4.dst);
2952 UInt v_srcL = vregNo(i->Pin.AvBin32Fx4.srcL);
2953 UInt v_srcR = vregNo(i->Pin.AvBin32Fx4.srcR);
2954 switch (i->Pin.AvBin32Fx4.op) {
2955
2956 case Pav_ADDF:
2957 p = mkFormVX( p, 4, v_dst, v_srcL, v_srcR, 10 ); // vaddfp
2958 break;
2959 case Pav_SUBF:
2960 p = mkFormVX( p, 4, v_dst, v_srcL, v_srcR, 74 ); // vsubfp
2961 break;
2962 case Pav_MAXF:
2963 p = mkFormVX( p, 4, v_dst, v_srcL, v_srcR, 1034 ); // vmaxfp
2964 break;
2965 case Pav_MINF:
2966 p = mkFormVX( p, 4, v_dst, v_srcL, v_srcR, 1098 ); // vminfp
2967 break;
2968
2969 case Pav_MULF: {
2970 /* Make a vmulfp from a vmaddfp:
2971 load -0.0 (0x8000_0000) to each 32-bit word of vB
2972 this makes the add a noop.
2973 */
2974 UInt vB = 29; // XXX: Using r29 for temp
2975 UInt zero_simm = 0x80000000;
2976
2977 // Better way to load zero_imm?
2978 // vspltisw vB,0x1F (0x1F => each word of vB)
2979 p = mkFormVX( p, 4, vB, zero_simm, 0, 908 );
2980
2981 // vslw vB,vB,vB (each word of vB = (0x1F << 0x1F) = 0x80000000
2982 p = mkFormVX( p, 4, vB, vB, vB, 388 );
2983
2984 // Finally, do the multiply:
2985 p = mkFormVA( p, 4, v_dst, v_srcL, vB, v_srcR, 46 );
2986 break;
2987 }
2988 case Pav_CMPEQF:
2989 p = mkFormVXR( p, 4, v_dst, v_srcL, v_srcR, 0, 198 ); // vcmpeqfp
2990 break;
2991 case Pav_CMPGTF:
2992 p = mkFormVXR( p, 4, v_dst, v_srcL, v_srcR, 1, 710 ); // vcmpgtfp
2993 break;
2994 case Pav_CMPGEF:
2995 p = mkFormVXR( p, 4, v_dst, v_srcL, v_srcR, 1, 454 ); // vcmpgefp
2996 break;
2997
2998 default:
2999 goto bad;
3000 }
3001 goto done;
3002 }
3003
cerionc3d8bdc2005-06-28 18:06:23 +00003004 case Pin_AvPerm: { // vperm
3005 UInt v_ctl = vregNo(i->Pin.AvPerm.ctl);
3006 UInt v_dst = vregNo(i->Pin.AvPerm.dst);
3007 UInt v_srcL = vregNo(i->Pin.AvPerm.srcL);
3008 UInt v_srcR = vregNo(i->Pin.AvPerm.srcR);
3009 p = mkFormVA( p, 4, v_dst, v_srcL, v_srcR, v_ctl, 43 );
3010 goto done;
3011 }
3012
3013 case Pin_AvSel: { // vsel
3014 UInt v_ctl = vregNo(i->Pin.AvSel.ctl);
3015 UInt v_dst = vregNo(i->Pin.AvSel.dst);
3016 UInt v_srcL = vregNo(i->Pin.AvSel.srcL);
3017 UInt v_srcR = vregNo(i->Pin.AvSel.srcR);
3018 p = mkFormVA( p, 4, v_dst, v_srcL, v_srcR, v_ctl, 42 );
3019 goto done;
3020 }
3021
3022 case Pin_AvShlDbl: { // vsldoi
3023 UInt shift = i->Pin.AvShlDbl.shift;
3024 UInt v_dst = vregNo(i->Pin.AvShlDbl.dst);
3025 UInt v_srcL = vregNo(i->Pin.AvShlDbl.srcL);
3026 UInt v_srcR = vregNo(i->Pin.AvShlDbl.srcR);
3027 vassert(shift <= 0xF);
3028 p = mkFormVA( p, 4, v_dst, v_srcL, v_srcR, shift, 44 );
3029 goto done;
3030 }
3031
3032 case Pin_AvSplat: { // vsplt(is)(b,h,w)
3033 UInt v_dst = vregNo(i->Pin.AvShlDbl.dst);
3034 UChar sz = i->Pin.AvSplat.sz;
3035 UInt v_src, simm_src, opc2;
3036 vassert(sz == 8 || sz == 16 || sz == 32);
3037
3038 if (i->Pin.AvSplat.src->tag == Pri_Imm) {
cerion6b6f59e2005-06-28 20:59:18 +00003039 opc2 = (sz == 8) ? 780 : (sz == 16) ? 844 : 908; // 8,16,32
cerionc3d8bdc2005-06-28 18:06:23 +00003040 simm_src = i->Pin.AvSplat.src->Pri.Imm.imm32;
3041 p = mkFormVX( p, 4, v_dst, simm_src, 0, opc2 );
3042 } else { // Pri_Reg
3043 opc2 = (sz == 8) ? 524 : (sz == 16) ? 588 : 652; // 8,16,32
3044 v_src = iregNo(i->Pin.AvSplat.src->Pri.Reg.reg);
3045 p = mkFormVX( p, 4, v_dst, 0, v_src, opc2 );
3046 }
3047 goto done;
3048 }
3049
cerion6b6f59e2005-06-28 20:59:18 +00003050 case Pin_AvCMov: {
3051 UInt v_dst = vregNo(i->Pin.AvCMov.dst);
3052 UInt v_src = vregNo(i->Pin.AvCMov.src);
3053 PPC32CondCode cc = i->Pin.AvCMov.cond;
3054
3055 if (v_dst == v_src) goto done;
3056
3057 vassert(cc.test != Pct_ALWAYS);
3058
3059 /* jmp fwds 2 insns if !condition */
3060 if (cc.test != Pct_ALWAYS) {
3061 /* bc !ct,cf,n_bytes>>2 */
3062 p = mkFormB(p, invertCondTest(cc.test), cc.flag, 8>>2, 0, 0);
3063 }
3064 /* vmr */
3065 p = mkFormVX( p, 4, v_dst, v_src, v_src, 1156 );
3066 goto done;
3067 }
3068
cerionc3d8bdc2005-06-28 18:06:23 +00003069 case Pin_AvLdVSCR: { // mtvscr
3070 UInt v_src = vregNo(i->Pin.AvLdVSCR.src);
3071 p = mkFormVX( p, 4, 0, 0, v_src, 1604 );
3072 goto done;
3073 }
3074
cerionbcf8c3e2005-02-04 16:17:07 +00003075 default:
3076 goto bad;
3077 }
3078
3079 bad:
cerionab9132d2005-02-15 15:46:59 +00003080 vex_printf("\n=> ");
cerionbcf8c3e2005-02-04 16:17:07 +00003081 ppPPC32Instr(i);
3082 vpanic("emit_PPC32Instr");
3083 /*NOTREACHED*/
3084
cerionbcf8c3e2005-02-04 16:17:07 +00003085 done:
3086 vassert(p - &buf[0] <= 32);
3087 return p - &buf[0];
cerionbcf8c3e2005-02-04 16:17:07 +00003088}
3089
3090/*---------------------------------------------------------------*/
3091/*--- end host-ppc32/hdefs.c ---*/
3092/*---------------------------------------------------------------*/