blob: 55d0effb44e18c64eaeec1d25f2e331466a5c63b [file] [log] [blame]
cerionbcf8c3e2005-02-04 16:17:07 +00001
2/*---------------------------------------------------------------*/
3/*--- ---*/
4/*--- This file (host-ppc32/hdefs.c) is ---*/
5/*--- Copyright (c) 2005 OpenWorks LLP. All rights reserved. ---*/
6/*--- ---*/
7/*---------------------------------------------------------------*/
8
9/*
10 This file is part of LibVEX, a library for dynamic binary
11 instrumentation and translation.
12
13 Copyright (C) 2004-2005 OpenWorks, LLP.
14
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);
69 vassert(r >= 0 && r < 6);
70 vex_printf("%%fpr%d", r);
71 return;
72 default:
73 vpanic("ppHRegPPC32");
cerioncd304492005-02-08 19:40:24 +000074 }
cerionbcf8c3e2005-02-04 16:17:07 +000075}
76
cerioncd304492005-02-08 19:40:24 +000077HReg hregPPC32_GPR0 ( void ) { return mkHReg( 0, HRcInt32, False); }
78HReg hregPPC32_GPR1 ( void ) { return mkHReg( 1, HRcInt32, False); }
79HReg hregPPC32_GPR2 ( void ) { return mkHReg( 2, HRcInt32, False); }
80HReg hregPPC32_GPR3 ( void ) { return mkHReg( 3, HRcInt32, False); }
81HReg hregPPC32_GPR4 ( void ) { return mkHReg( 4, HRcInt32, False); }
82HReg hregPPC32_GPR5 ( void ) { return mkHReg( 5, HRcInt32, False); }
83HReg hregPPC32_GPR6 ( void ) { return mkHReg( 6, HRcInt32, False); }
84HReg hregPPC32_GPR7 ( void ) { return mkHReg( 7, HRcInt32, False); }
85HReg hregPPC32_GPR8 ( void ) { return mkHReg( 8, HRcInt32, False); }
86HReg hregPPC32_GPR9 ( void ) { return mkHReg( 9, HRcInt32, False); }
87HReg hregPPC32_GPR10 ( void ) { return mkHReg(10, HRcInt32, False); }
88HReg hregPPC32_GPR11 ( void ) { return mkHReg(11, HRcInt32, False); }
89HReg hregPPC32_GPR12 ( void ) { return mkHReg(12, HRcInt32, False); }
90HReg hregPPC32_GPR13 ( void ) { return mkHReg(13, HRcInt32, False); }
91HReg hregPPC32_GPR14 ( void ) { return mkHReg(14, HRcInt32, False); }
92HReg hregPPC32_GPR15 ( void ) { return mkHReg(15, HRcInt32, False); }
93HReg hregPPC32_GPR16 ( void ) { return mkHReg(16, HRcInt32, False); }
94HReg hregPPC32_GPR17 ( void ) { return mkHReg(17, HRcInt32, False); }
95HReg hregPPC32_GPR18 ( void ) { return mkHReg(18, HRcInt32, False); }
96HReg hregPPC32_GPR19 ( void ) { return mkHReg(19, HRcInt32, False); }
97HReg hregPPC32_GPR20 ( void ) { return mkHReg(20, HRcInt32, False); }
98HReg hregPPC32_GPR21 ( void ) { return mkHReg(21, HRcInt32, False); }
99HReg hregPPC32_GPR22 ( void ) { return mkHReg(22, HRcInt32, False); }
100HReg hregPPC32_GPR23 ( void ) { return mkHReg(23, HRcInt32, False); }
101HReg hregPPC32_GPR24 ( void ) { return mkHReg(24, HRcInt32, False); }
102HReg hregPPC32_GPR25 ( void ) { return mkHReg(25, HRcInt32, False); }
103HReg hregPPC32_GPR26 ( void ) { return mkHReg(26, HRcInt32, False); }
104HReg hregPPC32_GPR27 ( void ) { return mkHReg(27, HRcInt32, False); }
105HReg hregPPC32_GPR28 ( void ) { return mkHReg(28, HRcInt32, False); }
106HReg hregPPC32_GPR29 ( void ) { return mkHReg(29, HRcInt32, False); }
107HReg hregPPC32_GPR30 ( void ) { return mkHReg(30, HRcInt32, False); }
108HReg hregPPC32_GPR31 ( void ) { return mkHReg(31, HRcInt32, False); }
109
110HReg hregPPC32_FPR0 ( void ) { return mkHReg( 0, HRcFlt64, False); }
111HReg hregPPC32_FPR1 ( void ) { return mkHReg( 1, HRcFlt64, False); }
112HReg hregPPC32_FPR2 ( void ) { return mkHReg( 2, HRcFlt64, False); }
113HReg hregPPC32_FPR3 ( void ) { return mkHReg( 3, HRcFlt64, False); }
114HReg hregPPC32_FPR4 ( void ) { return mkHReg( 4, HRcFlt64, False); }
115HReg hregPPC32_FPR5 ( void ) { return mkHReg( 5, HRcFlt64, False); }
116HReg hregPPC32_FPR6 ( void ) { return mkHReg( 6, HRcFlt64, False); }
117HReg hregPPC32_FPR7 ( void ) { return mkHReg( 7, HRcFlt64, False); }
118HReg hregPPC32_FPR8 ( void ) { return mkHReg( 8, HRcFlt64, False); }
119HReg hregPPC32_FPR9 ( void ) { return mkHReg( 9, HRcFlt64, False); }
120HReg hregPPC32_FPR10 ( void ) { return mkHReg(10, HRcFlt64, False); }
121HReg hregPPC32_FPR11 ( void ) { return mkHReg(11, HRcFlt64, False); }
122HReg hregPPC32_FPR12 ( void ) { return mkHReg(12, HRcFlt64, False); }
123HReg hregPPC32_FPR13 ( void ) { return mkHReg(13, HRcFlt64, False); }
124HReg hregPPC32_FPR14 ( void ) { return mkHReg(14, HRcFlt64, False); }
125HReg hregPPC32_FPR15 ( void ) { return mkHReg(15, HRcFlt64, False); }
126HReg hregPPC32_FPR16 ( void ) { return mkHReg(16, HRcFlt64, False); }
127HReg hregPPC32_FPR17 ( void ) { return mkHReg(17, HRcFlt64, False); }
128HReg hregPPC32_FPR18 ( void ) { return mkHReg(18, HRcFlt64, False); }
129HReg hregPPC32_FPR19 ( void ) { return mkHReg(19, HRcFlt64, False); }
130HReg hregPPC32_FPR20 ( void ) { return mkHReg(20, HRcFlt64, False); }
131HReg hregPPC32_FPR21 ( void ) { return mkHReg(21, HRcFlt64, False); }
132HReg hregPPC32_FPR22 ( void ) { return mkHReg(22, HRcFlt64, False); }
133HReg hregPPC32_FPR23 ( void ) { return mkHReg(23, HRcFlt64, False); }
134HReg hregPPC32_FPR24 ( void ) { return mkHReg(24, HRcFlt64, False); }
135HReg hregPPC32_FPR25 ( void ) { return mkHReg(25, HRcFlt64, False); }
136HReg hregPPC32_FPR26 ( void ) { return mkHReg(26, HRcFlt64, False); }
137HReg hregPPC32_FPR27 ( void ) { return mkHReg(27, HRcFlt64, False); }
138HReg hregPPC32_FPR28 ( void ) { return mkHReg(28, HRcFlt64, False); }
139HReg hregPPC32_FPR29 ( void ) { return mkHReg(29, HRcFlt64, False); }
140HReg hregPPC32_FPR30 ( void ) { return mkHReg(30, HRcFlt64, False); }
141HReg hregPPC32_FPR31 ( void ) { return mkHReg(31, HRcFlt64, False); }
cerionbcf8c3e2005-02-04 16:17:07 +0000142
cerionbcf8c3e2005-02-04 16:17:07 +0000143void getAllocableRegs_PPC32 ( Int* nregs, HReg** arr )
cerioncd304492005-02-08 19:40:24 +0000144{
cerionb4a632a2005-02-09 21:01:22 +0000145 *nregs = 59;
cerioncd304492005-02-08 19:40:24 +0000146 *arr = LibVEX_Alloc(*nregs * sizeof(HReg));
ceriona56e9cc2005-02-16 18:08:25 +0000147 // GPR0 = scratch reg where possible - some ops interpret as value zero
cerion2c49e032005-02-09 17:29:49 +0000148 // GPR1 = stack pointer
149 // GPR2 = TOC pointer
cerionb4a632a2005-02-09 21:01:22 +0000150 (*arr)[ 0] = hregPPC32_GPR3();
151 (*arr)[ 1] = hregPPC32_GPR4();
152 (*arr)[ 2] = hregPPC32_GPR5();
153 (*arr)[ 3] = hregPPC32_GPR6();
154 (*arr)[ 4] = hregPPC32_GPR7();
155 (*arr)[ 5] = hregPPC32_GPR8();
156 (*arr)[ 6] = hregPPC32_GPR9();
157 (*arr)[ 7] = hregPPC32_GPR10();
158 (*arr)[ 8] = hregPPC32_GPR11();
159 (*arr)[ 9] = hregPPC32_GPR12();
cerion2c49e032005-02-09 17:29:49 +0000160 // GPR13 = thread specific pointer
cerionb4a632a2005-02-09 21:01:22 +0000161 (*arr)[10] = hregPPC32_GPR14();
162 (*arr)[11] = hregPPC32_GPR15();
163 (*arr)[12] = hregPPC32_GPR16();
164 (*arr)[13] = hregPPC32_GPR17();
165 (*arr)[14] = hregPPC32_GPR18();
166 (*arr)[15] = hregPPC32_GPR19();
167 (*arr)[16] = hregPPC32_GPR20();
168 (*arr)[17] = hregPPC32_GPR21();
169 (*arr)[18] = hregPPC32_GPR22();
170 (*arr)[19] = hregPPC32_GPR23();
171 (*arr)[20] = hregPPC32_GPR24();
172 (*arr)[21] = hregPPC32_GPR25();
173 (*arr)[22] = hregPPC32_GPR26();
174 (*arr)[23] = hregPPC32_GPR27();
175 (*arr)[24] = hregPPC32_GPR28();
176 (*arr)[25] = hregPPC32_GPR29();
177 (*arr)[26] = hregPPC32_GPR30();
cerion2c49e032005-02-09 17:29:49 +0000178 // GPR31 = GuestStatePtr
cerioncd304492005-02-08 19:40:24 +0000179
cerionb4a632a2005-02-09 21:01:22 +0000180 (*arr)[27] = hregPPC32_FPR0();
181 (*arr)[28] = hregPPC32_FPR1();
182 (*arr)[29] = hregPPC32_FPR2();
183 (*arr)[30] = hregPPC32_FPR3();
184 (*arr)[31] = hregPPC32_FPR4();
185 (*arr)[32] = hregPPC32_FPR5();
186 (*arr)[33] = hregPPC32_FPR6();
187 (*arr)[34] = hregPPC32_FPR7();
188 (*arr)[35] = hregPPC32_FPR8();
189 (*arr)[36] = hregPPC32_FPR9();
190 (*arr)[37] = hregPPC32_FPR10();
191 (*arr)[38] = hregPPC32_FPR11();
192 (*arr)[39] = hregPPC32_FPR12();
193 (*arr)[40] = hregPPC32_FPR13();
194 (*arr)[41] = hregPPC32_FPR14();
195 (*arr)[42] = hregPPC32_FPR15();
196 (*arr)[43] = hregPPC32_FPR16();
197 (*arr)[44] = hregPPC32_FPR17();
198 (*arr)[45] = hregPPC32_FPR18();
199 (*arr)[46] = hregPPC32_FPR19();
200 (*arr)[47] = hregPPC32_FPR20();
201 (*arr)[48] = hregPPC32_FPR21();
202 (*arr)[49] = hregPPC32_FPR22();
203 (*arr)[50] = hregPPC32_FPR23();
204 (*arr)[51] = hregPPC32_FPR24();
205 (*arr)[52] = hregPPC32_FPR25();
206 (*arr)[53] = hregPPC32_FPR26();
207 (*arr)[54] = hregPPC32_FPR27();
208 (*arr)[55] = hregPPC32_FPR28();
209 (*arr)[56] = hregPPC32_FPR29();
210 (*arr)[57] = hregPPC32_FPR30();
211 (*arr)[58] = hregPPC32_FPR31();
cerion2c49e032005-02-09 17:29:49 +0000212}
213
214
215/* --------- Condition codes, Intel encoding. --------- */
216
217HChar* showPPC32CondCode ( PPC32CondCode cond )
218{
cerionab9132d2005-02-15 15:46:59 +0000219 if (cond.test == Pct_ALWAYS) return "always";
220
221 switch (cond.flag) {
222 case Pcf_SO: return (cond.test == Pct_TRUE) ? "so=1" : "so=0";
223 case Pcf_EQ: return (cond.test == Pct_TRUE) ? "eq=1" : "eq=0";
224 case Pcf_GT: return (cond.test == Pct_TRUE) ? "gt=1" : "gt=0";
225 case Pcf_LT: return (cond.test == Pct_TRUE) ? "lt=1" : "lt=0";
226 default: vpanic("ppPPC32CondCode");
cerion2c49e032005-02-09 17:29:49 +0000227 }
cerionbcf8c3e2005-02-04 16:17:07 +0000228}
229
cerion7cf8e4e2005-02-16 16:08:17 +0000230/* constructor */
231PPC32CondCode mk_PPCCondCode ( PPC32CondTest test, PPC32CondFlag flag )
232{
233 PPC32CondCode cc;
234 cc.flag = flag;
235 cc.test = test;
236 return cc;
237}
238
239/* false->true, true->false */
cerion33aa6da2005-02-16 10:25:26 +0000240PPC32CondTest invertCondTest ( PPC32CondTest ct )
241{
242 vassert(ct != Pct_ALWAYS);
243 return (ct == Pct_TRUE) ? Pct_FALSE : Pct_TRUE;
244}
245
246
cerioncd304492005-02-08 19:40:24 +0000247/* --------- PPCAMode: memory address expressions. --------- */
248
249PPC32AMode* PPC32AMode_IR ( UInt idx, HReg base ) {
cerion3c0b12b2005-02-10 11:39:43 +0000250 vassert(idx < 0x10000);
cerioncd304492005-02-08 19:40:24 +0000251 PPC32AMode* am = LibVEX_Alloc(sizeof(PPC32AMode));
252 am->tag = Pam_IR;
253 am->Pam.IR.base = base;
254 am->Pam.IR.index = idx;
255 return am;
256}
257PPC32AMode* PPC32AMode_RR ( HReg idx, HReg base ) {
258 PPC32AMode* am = LibVEX_Alloc(sizeof(PPC32AMode));
259 am->tag = Pam_RR;
260 am->Pam.RR.base = base;
261 am->Pam.RR.index = idx;
262 return am;
263}
264
265PPC32AMode* dopyPPC32AMode ( PPC32AMode* am ) {
266 switch (am->tag) {
cerionb85e8bb2005-02-16 08:54:33 +0000267 case Pam_IR:
268 return PPC32AMode_IR( am->Pam.IR.index, am->Pam.IR.base );
269 case Pam_RR:
270 return PPC32AMode_RR( am->Pam.RR.index, am->Pam.RR.base );
271 default:
272 vpanic("dopyPPC32AMode");
cerioncd304492005-02-08 19:40:24 +0000273 }
274}
275
276void ppPPC32AMode ( PPC32AMode* am ) {
277 switch (am->tag) {
cerionb85e8bb2005-02-16 08:54:33 +0000278 case Pam_IR:
279 if (am->Pam.IR.index == 0)
280 vex_printf("(");
281 else
282 vex_printf("0x%x(", am->Pam.IR.index);
283 ppHRegPPC32(am->Pam.IR.base);
284 vex_printf(")");
285 return;
286 case Pam_RR:
287 ppHRegPPC32(am->Pam.RR.base);
288 vex_printf(",");
289 ppHRegPPC32(am->Pam.RR.index);
290 return;
291 default:
292 vpanic("ppPPC32AMode");
cerioncd304492005-02-08 19:40:24 +0000293 }
294}
295
cerioncd304492005-02-08 19:40:24 +0000296static void addRegUsage_PPC32AMode ( HRegUsage* u, PPC32AMode* am ) {
297 switch (am->tag) {
cerionb85e8bb2005-02-16 08:54:33 +0000298 case Pam_IR:
299 addHRegUse(u, HRmRead, am->Pam.IR.base);
300 return;
301 case Pam_RR:
302 addHRegUse(u, HRmRead, am->Pam.RR.base);
303 addHRegUse(u, HRmRead, am->Pam.RR.index);
304 return;
305 default:
306 vpanic("addRegUsage_PPC32AMode");
cerioncd304492005-02-08 19:40:24 +0000307 }
308}
cerioncd304492005-02-08 19:40:24 +0000309
cerioncd304492005-02-08 19:40:24 +0000310static void mapRegs_PPC32AMode ( HRegRemap* m, PPC32AMode* am ) {
311 switch (am->tag) {
cerionb85e8bb2005-02-16 08:54:33 +0000312 case Pam_IR:
313 am->Pam.IR.base = lookupHRegRemap(m, am->Pam.IR.base);
314 return;
315 case Pam_RR:
316 am->Pam.RR.base = lookupHRegRemap(m, am->Pam.RR.base);
317 am->Pam.RR.index = lookupHRegRemap(m, am->Pam.RR.index);
318 return;
319 default:
320 vpanic("mapRegs_PPC32AMode");
cerioncd304492005-02-08 19:40:24 +0000321 }
322}
cerioncd304492005-02-08 19:40:24 +0000323
324/* --------- Operand, which can be reg or immediate only. --------- */
325
326PPC32RI* PPC32RI_Imm ( UInt imm32 ) {
327 PPC32RI* op = LibVEX_Alloc(sizeof(PPC32RI));
328 op->tag = Pri_Imm;
329 op->Pri.Imm.imm32 = imm32;
330 return op;
331}
332PPC32RI* PPC32RI_Reg ( HReg reg ) {
333 PPC32RI* op = LibVEX_Alloc(sizeof(PPC32RI));
334 op->tag = Pri_Reg;
335 op->Pri.Reg.reg = reg;
336 return op;
337}
338
339void ppPPC32RI ( PPC32RI* op ) {
340 switch (op->tag) {
cerionb85e8bb2005-02-16 08:54:33 +0000341 case Pri_Imm:
342 vex_printf("$0x%x", op->Pri.Imm.imm32);
343 return;
344 case Pri_Reg:
345 ppHRegPPC32(op->Pri.Reg.reg);
346 return;
347 default:
348 vpanic("ppPPC32RI");
cerioncd304492005-02-08 19:40:24 +0000349 }
350}
351
352/* An PPC32RI can only be used in a "read" context (what would it mean
353 to write or modify a literal?) and so we enumerate its registers
354 accordingly. */
355static void addRegUsage_PPC32RI ( HRegUsage* u, PPC32RI* op ) {
356 switch (op->tag) {
cerionb85e8bb2005-02-16 08:54:33 +0000357 case Pri_Imm:
358 return;
359 case Pri_Reg:
360 addHRegUse(u, HRmRead, op->Pri.Reg.reg);
361 return;
362 default:
363 vpanic("addRegUsage_PPC32RI");
cerioncd304492005-02-08 19:40:24 +0000364 }
365}
366
367static void mapRegs_PPC32RI ( HRegRemap* m, PPC32RI* op ) {
368 switch (op->tag) {
cerionb85e8bb2005-02-16 08:54:33 +0000369 case Pri_Imm:
370 return;
371 case Pri_Reg:
372 op->Pri.Reg.reg = lookupHRegRemap(m, op->Pri.Reg.reg);
373 return;
374 default:
375 vpanic("mapRegs_PPC32RI");
cerioncd304492005-02-08 19:40:24 +0000376 }
377}
378
379/* --------- Instructions. --------- */
380
cerionbcf8c3e2005-02-04 16:17:07 +0000381//.. HChar* showX86ScalarSz ( X86ScalarSz sz ) {
382//.. switch (sz) {
383//.. case Xss_16: return "w";
384//.. case Xss_32: return "l";
385//.. default: vpanic("showX86ScalarSz");
386//.. }
387//.. }
cerioncd304492005-02-08 19:40:24 +0000388
cerion2c49e032005-02-09 17:29:49 +0000389HChar* showPPC32UnaryOp ( PPC32UnaryOp op ) {
390 switch (op) {
cerionb85e8bb2005-02-16 08:54:33 +0000391 case Pun_NOT: return "not";
392 case Pun_NEG: return "neg";
393 case Pun_CLZ: return "cntlzw";
394 default: vpanic("showPPC32UnaryOp");
cerion2c49e032005-02-09 17:29:49 +0000395 }
396}
cerioncd304492005-02-08 19:40:24 +0000397
398HChar* showPPC32AluOp ( PPC32AluOp op ) {
399 switch (op) {
cerionb85e8bb2005-02-16 08:54:33 +0000400 case Palu_ADD: return "add";
401 case Palu_SUB: return "subf";
402// case Palu_ADC: return "adc";
403// case Palu_SBB: return "sbb";
404 case Palu_AND: return "and";
405 case Palu_OR: return "or";
406 case Palu_XOR: return "xor";
cerionb85e8bb2005-02-16 08:54:33 +0000407 default: vpanic("showPPC32AluOp");
cerioncd304492005-02-08 19:40:24 +0000408 }
409}
410
411HChar* showPPC32ShiftOp ( PPC32ShiftOp op ) {
412 switch (op) {
cerionb85e8bb2005-02-16 08:54:33 +0000413 case Psh_SHL: return "slw";
414 case Psh_SHR: return "srw";
415 case Psh_SAR: return "sraw";
416 case Psh_ROL: return "rlw";
417 default: vpanic("showPPC32ShiftOp");
cerioncd304492005-02-08 19:40:24 +0000418 }
419}
420
cerionab9132d2005-02-15 15:46:59 +0000421HChar* showPPC32CmpOp ( PPC32CmpOp op ) {
422 switch (op) {
cerionb85e8bb2005-02-16 08:54:33 +0000423 case Pcmp_U: return "cmpl";
424 case Pcmp_S: return "cmp";
425 default: vpanic("showPPC32CmpOp");
cerionab9132d2005-02-15 15:46:59 +0000426 }
427}
428
cerionbcf8c3e2005-02-04 16:17:07 +0000429//.. HChar* showX86FpOp ( X86FpOp op ) {
430//.. switch (op) {
431//.. case Xfp_ADD: return "add";
432//.. case Xfp_SUB: return "sub";
433//.. case Xfp_MUL: return "mul";
434//.. case Xfp_DIV: return "div";
435//.. case Xfp_SCALE: return "scale";
436//.. case Xfp_ATAN: return "atan";
437//.. case Xfp_YL2X: return "yl2x";
438//.. case Xfp_YL2XP1: return "yl2xp1";
439//.. case Xfp_PREM: return "prem";
440//.. case Xfp_PREM1: return "prem1";
441//.. case Xfp_SQRT: return "sqrt";
442//.. case Xfp_ABS: return "abs";
443//.. case Xfp_NEG: return "chs";
444//.. case Xfp_MOV: return "mov";
445//.. case Xfp_SIN: return "sin";
446//.. case Xfp_COS: return "cos";
447//.. case Xfp_TAN: return "tan";
448//.. case Xfp_ROUND: return "round";
449//.. case Xfp_2XM1: return "2xm1";
450//.. default: vpanic("showX86FpOp");
451//.. }
452//.. }
cerioncd304492005-02-08 19:40:24 +0000453
454PPC32Instr* PPC32Instr_Alu32 ( PPC32AluOp op, HReg dst, HReg src1, PPC32RI* src2 ) {
cerion33aa6da2005-02-16 10:25:26 +0000455 if (src2->tag == Pri_Imm)
456 vassert(src2->Pri.Imm.imm32 < 0x10000);
cerioncd304492005-02-08 19:40:24 +0000457 PPC32Instr* i = LibVEX_Alloc(sizeof(PPC32Instr));
458 i->tag = Pin_Alu32;
459 i->Pin.Alu32.op = op;
460 i->Pin.Alu32.dst = dst;
461 i->Pin.Alu32.src1 = src1;
462 i->Pin.Alu32.src2 = src2;
463 return i;
464}
465PPC32Instr* PPC32Instr_Sh32 ( PPC32ShiftOp op, HReg dst, HReg src, PPC32RI* shft ) {
cerionab9132d2005-02-15 15:46:59 +0000466 if (op == Psh_SHL || op == Psh_SHR) // No imm versions for these.
467 vassert(shft->tag == Pri_Reg);
468 if (shft->tag == Pri_Imm)
469 vassert(shft->Pri.Imm.imm32 < 32);
cerioncd304492005-02-08 19:40:24 +0000470 PPC32Instr* i = LibVEX_Alloc(sizeof(PPC32Instr));
471 i->tag = Pin_Sh32;
472 i->Pin.Sh32.op = op;
473 i->Pin.Sh32.dst = dst;
474 i->Pin.Sh32.src = src;
475 i->Pin.Sh32.shft = shft;
476 return i;
477}
cerionab9132d2005-02-15 15:46:59 +0000478PPC32Instr* PPC32Instr_Cmp32 ( PPC32CmpOp op, UInt crfD, HReg src1, PPC32RI* src2 ) {
cerion2c49e032005-02-09 17:29:49 +0000479 PPC32Instr* i = LibVEX_Alloc(sizeof(PPC32Instr));
cerionab9132d2005-02-15 15:46:59 +0000480 i->tag = Pin_Cmp32;
481 i->Pin.Cmp32.op = op;
482 i->Pin.Cmp32.crfD = crfD;
483 i->Pin.Cmp32.src1 = src1;
484 i->Pin.Cmp32.src2 = src2;
cerion2c49e032005-02-09 17:29:49 +0000485 return i;
486}
cerione13bb312005-02-10 19:51:03 +0000487PPC32Instr* PPC32Instr_Unary32 ( PPC32UnaryOp op, HReg dst, HReg src ) {
cerion2c49e032005-02-09 17:29:49 +0000488 PPC32Instr* i = LibVEX_Alloc(sizeof(PPC32Instr));
489 i->tag = Pin_Unary32;
490 i->Pin.Unary32.op = op;
491 i->Pin.Unary32.dst = dst;
cerione13bb312005-02-10 19:51:03 +0000492 i->Pin.Unary32.src = src;
cerion2c49e032005-02-09 17:29:49 +0000493 return i;
494}
cerion92f5dc72005-02-10 16:11:35 +0000495PPC32Instr* PPC32Instr_MulL ( Bool syned, Bool word, HReg dst,
cerionb85e8bb2005-02-16 08:54:33 +0000496 HReg src1, PPC32RI* src2 ) {
cerion98411db2005-02-16 14:14:49 +0000497 if (word == 1) { // high
498 vassert(src2->tag == Pri_Reg);
499 } else { // low
500 if (src2->tag == Pri_Imm) {
501 vassert(syned == True);
502 vassert(src2->Pri.Imm.imm32 < 0x10000);
503 }
504 }
cerion92f5dc72005-02-10 16:11:35 +0000505 PPC32Instr* i = LibVEX_Alloc(sizeof(PPC32Instr));
506 i->tag = Pin_MulL;
507 i->Pin.MulL.syned = syned;
508 i->Pin.MulL.word = word;
cerionc0e707e2005-02-10 22:35:34 +0000509 i->Pin.MulL.dst = dst;
cerion92f5dc72005-02-10 16:11:35 +0000510 i->Pin.MulL.src1 = src1;
511 i->Pin.MulL.src2 = src2;
512 return i;
513}
cerion33aa6da2005-02-16 10:25:26 +0000514PPC32Instr* PPC32Instr_Div ( Bool syned, HReg dst, HReg src1, HReg src2 ) {
cerionc0e707e2005-02-10 22:35:34 +0000515 PPC32Instr* i = LibVEX_Alloc(sizeof(PPC32Instr));
516 i->tag = Pin_Div;
517 i->Pin.Div.syned = syned;
518 i->Pin.Div.dst = dst;
519 i->Pin.Div.src1 = src1;
520 i->Pin.Div.src2 = src2;
521 return i;
522}
cerionbcf8c3e2005-02-04 16:17:07 +0000523//.. X86Instr* X86Instr_Sh3232 ( X86ShiftOp op, UInt amt, HReg src, HReg dst ) {
524//.. X86Instr* i = LibVEX_Alloc(sizeof(X86Instr));
525//.. i->tag = Xin_Sh3232;
526//.. i->Xin.Sh3232.op = op;
527//.. i->Xin.Sh3232.amt = amt;
528//.. i->Xin.Sh3232.src = src;
529//.. i->Xin.Sh3232.dst = dst;
530//.. vassert(op == Xsh_SHL || op == Xsh_SHR);
531//.. return i;
532//.. }
533//.. X86Instr* X86Instr_Push( X86RMI* src ) {
534//.. X86Instr* i = LibVEX_Alloc(sizeof(X86Instr));
535//.. i->tag = Xin_Push;
536//.. i->Xin.Push.src = src;
537//.. return i;
538//.. }
cerion2c49e032005-02-09 17:29:49 +0000539PPC32Instr* PPC32Instr_Call ( PPC32CondCode cond, Addr32 target, Int regparms ) {
540 PPC32Instr* i = LibVEX_Alloc(sizeof(PPC32Instr));
541 i->tag = Pin_Call;
542 i->Pin.Call.cond = cond;
543 i->Pin.Call.target = target;
544 i->Pin.Call.regparms = regparms;
545 vassert(regparms >= 0 && regparms < PPC32_N_REGPARMS);
546 return i;
547}
548PPC32Instr* PPC32Instr_Goto ( IRJumpKind jk, PPC32CondCode cond, PPC32RI* dst ) {
549 PPC32Instr* i = LibVEX_Alloc(sizeof(PPC32Instr));
550 i->tag = Pin_Goto;
551 i->Pin.Goto.cond = cond;
552 i->Pin.Goto.dst = dst;
553 i->Pin.Goto.jk = jk;
554 return i;
555}
cerionb536af92005-02-10 15:03:19 +0000556PPC32Instr* PPC32Instr_CMov32 ( PPC32CondCode cond, HReg dst, PPC32RI* src ) {
557 PPC32Instr* i = LibVEX_Alloc(sizeof(PPC32Instr));
558 i->tag = Pin_CMov32;
559 i->Pin.CMov32.cond = cond;
560 i->Pin.CMov32.src = src;
561 i->Pin.CMov32.dst = dst;
cerionab9132d2005-02-15 15:46:59 +0000562 vassert(cond.test != Pct_ALWAYS);
cerionb536af92005-02-10 15:03:19 +0000563 return i;
564}
cerion7cf8e4e2005-02-16 16:08:17 +0000565PPC32Instr* PPC32Instr_Load ( UChar sz, Bool syned,
566 HReg dst, PPC32AMode* src ) {
567 PPC32Instr* i = LibVEX_Alloc(sizeof(PPC32Instr));
568 i->tag = Pin_Load;
569 i->Pin.Load.sz = sz;
570 i->Pin.Load.syned = syned;
571 i->Pin.Load.src = src;
572 i->Pin.Load.dst = dst;
cerion2c49e032005-02-09 17:29:49 +0000573 vassert(sz == 1 || sz == 2 || sz == 4);
cerioncd304492005-02-08 19:40:24 +0000574 return i;
575}
576PPC32Instr* PPC32Instr_Store ( UChar sz, PPC32AMode* dst, HReg src ) {
577 PPC32Instr* i = LibVEX_Alloc(sizeof(PPC32Instr));
578 i->tag = Pin_Store;
579 i->Pin.Store.sz = sz;
580 i->Pin.Store.src = src;
581 i->Pin.Store.dst = dst;
582 vassert(sz == 1 || sz == 2 || sz == 4);
583 return i;
584}
cerionb536af92005-02-10 15:03:19 +0000585PPC32Instr* PPC32Instr_Set32 ( PPC32CondCode cond, HReg dst ) {
586 PPC32Instr* i = LibVEX_Alloc(sizeof(PPC32Instr));
587 i->tag = Pin_Set32;
588 i->Pin.Set32.cond = cond;
589 i->Pin.Set32.dst = dst;
590 return i;
591}
cerionbcf8c3e2005-02-04 16:17:07 +0000592//.. X86Instr* X86Instr_Bsfr32 ( Bool isFwds, HReg src, HReg dst ) {
593//.. X86Instr* i = LibVEX_Alloc(sizeof(X86Instr));
594//.. i->tag = Xin_Bsfr32;
595//.. i->Xin.Bsfr32.isFwds = isFwds;
596//.. i->Xin.Bsfr32.src = src;
597//.. i->Xin.Bsfr32.dst = dst;
598//.. return i;
599//.. }
cerion98411db2005-02-16 14:14:49 +0000600PPC32Instr* PPC32Instr_MFence ( void )
cerion92f5dc72005-02-10 16:11:35 +0000601{
602 PPC32Instr* i = LibVEX_Alloc(sizeof(PPC32Instr));
603 i->tag = Pin_MFence;
cerion92f5dc72005-02-10 16:11:35 +0000604 return i;
605}
cerioncd304492005-02-08 19:40:24 +0000606
cerionbcf8c3e2005-02-04 16:17:07 +0000607//.. X86Instr* X86Instr_FpUnary ( X86FpOp op, HReg src, HReg dst ) {
608//.. X86Instr* i = LibVEX_Alloc(sizeof(X86Instr));
609//.. i->tag = Xin_FpUnary;
610//.. i->Xin.FpUnary.op = op;
611//.. i->Xin.FpUnary.src = src;
612//.. i->Xin.FpUnary.dst = dst;
613//.. return i;
614//.. }
615//.. X86Instr* X86Instr_FpBinary ( X86FpOp op, HReg srcL, HReg srcR, HReg dst ) {
616//.. X86Instr* i = LibVEX_Alloc(sizeof(X86Instr));
617//.. i->tag = Xin_FpBinary;
618//.. i->Xin.FpBinary.op = op;
619//.. i->Xin.FpBinary.srcL = srcL;
620//.. i->Xin.FpBinary.srcR = srcR;
621//.. i->Xin.FpBinary.dst = dst;
622//.. return i;
623//.. }
624//.. X86Instr* X86Instr_FpLdSt ( Bool isLoad, UChar sz, HReg reg, X86AMode* addr ) {
625//.. X86Instr* i = LibVEX_Alloc(sizeof(X86Instr));
626//.. i->tag = Xin_FpLdSt;
627//.. i->Xin.FpLdSt.isLoad = isLoad;
628//.. i->Xin.FpLdSt.sz = sz;
629//.. i->Xin.FpLdSt.reg = reg;
630//.. i->Xin.FpLdSt.addr = addr;
631//.. vassert(sz == 4 || sz == 8);
632//.. return i;
633//.. }
634//.. X86Instr* X86Instr_FpLdStI ( Bool isLoad, UChar sz,
635//.. HReg reg, X86AMode* addr ) {
636//.. X86Instr* i = LibVEX_Alloc(sizeof(X86Instr));
637//.. i->tag = Xin_FpLdStI;
638//.. i->Xin.FpLdStI.isLoad = isLoad;
639//.. i->Xin.FpLdStI.sz = sz;
640//.. i->Xin.FpLdStI.reg = reg;
641//.. i->Xin.FpLdStI.addr = addr;
642//.. vassert(sz == 2 || sz == 4 || sz == 8);
643//.. return i;
644//.. }
645//.. X86Instr* X86Instr_Fp64to32 ( HReg src, HReg dst ) {
646//.. X86Instr* i = LibVEX_Alloc(sizeof(X86Instr));
647//.. i->tag = Xin_Fp64to32;
648//.. i->Xin.Fp64to32.src = src;
649//.. i->Xin.Fp64to32.dst = dst;
650//.. return i;
651//.. }
652//.. X86Instr* X86Instr_FpCMov ( X86CondCode cond, HReg src, HReg dst ) {
653//.. X86Instr* i = LibVEX_Alloc(sizeof(X86Instr));
654//.. i->tag = Xin_FpCMov;
655//.. i->Xin.FpCMov.cond = cond;
656//.. i->Xin.FpCMov.src = src;
657//.. i->Xin.FpCMov.dst = dst;
658//.. vassert(cond != Xcc_ALWAYS);
659//.. return i;
660//.. }
661//.. X86Instr* X86Instr_FpLdStCW ( Bool isLoad, X86AMode* addr ) {
662//.. X86Instr* i = LibVEX_Alloc(sizeof(X86Instr));
663//.. i->tag = Xin_FpLdStCW;
664//.. i->Xin.FpLdStCW.isLoad = isLoad;
665//.. i->Xin.FpLdStCW.addr = addr;
666//.. return i;
667//.. }
668//.. X86Instr* X86Instr_FpStSW_AX ( void ) {
669//.. X86Instr* i = LibVEX_Alloc(sizeof(X86Instr));
670//.. i->tag = Xin_FpStSW_AX;
671//.. return i;
672//.. }
673//.. X86Instr* X86Instr_FpCmp ( HReg srcL, HReg srcR, HReg dst ) {
674//.. X86Instr* i = LibVEX_Alloc(sizeof(X86Instr));
675//.. i->tag = Xin_FpCmp;
676//.. i->Xin.FpCmp.srcL = srcL;
677//.. i->Xin.FpCmp.srcR = srcR;
678//.. i->Xin.FpCmp.dst = dst;
679//.. return i;
680//.. }
cerionbcf8c3e2005-02-04 16:17:07 +0000681
682void ppPPC32Instr ( PPC32Instr* i )
683{
684 switch (i->tag) {
cerionb85e8bb2005-02-16 08:54:33 +0000685 case Pin_Alu32:
686 if (i->Pin.Alu32.op == Palu_OR && // or Rd,Rs,Rs == mr Rd,Rs
687 i->Pin.Alu32.src2->tag == Pri_Reg &&
688 i->Pin.Alu32.src2->Pri.Reg.reg == i->Pin.Alu32.src1) {
689 vex_printf("mr ");
690 ppHRegPPC32(i->Pin.Alu32.dst);
cerioncd304492005-02-08 19:40:24 +0000691 vex_printf(",");
cerionb85e8bb2005-02-16 08:54:33 +0000692 ppHRegPPC32(i->Pin.Alu32.src1);
cerioncd304492005-02-08 19:40:24 +0000693 return;
cerionb85e8bb2005-02-16 08:54:33 +0000694 }
695 if (i->Pin.Alu32.op == Palu_ADD && // add Rd,R0,Rs == li Rd,Rs
696 i->Pin.Alu32.src1 == hregPPC32_GPR0() &&
697 i->Pin.Alu32.src2->tag == Pri_Imm) {
698 vex_printf("li ");
699 ppHRegPPC32(i->Pin.Alu32.dst);
700 vex_printf(",");
701 ppPPC32RI(i->Pin.Alu32.src2);
702 return;
703 }
704 vex_printf("%s%s ", showPPC32AluOp(i->Pin.Alu32.op),
705 i->Pin.Alu32.src2->tag == Pri_Imm ? "i" : "" );
706 ppHRegPPC32(i->Pin.Alu32.dst);
707 vex_printf(",");
708 ppHRegPPC32(i->Pin.Alu32.src1);
709 vex_printf(",");
710 ppPPC32RI(i->Pin.Alu32.src2);
711 return;
712 case Pin_Sh32:
713 vex_printf("%s%s ", showPPC32ShiftOp(i->Pin.Sh32.op),
714 i->Pin.Sh32.shft->tag == Pri_Imm ? "i" : "" );
715 ppHRegPPC32(i->Pin.Sh32.dst);
716 vex_printf(",");
717 ppHRegPPC32(i->Pin.Sh32.src);
718 vex_printf(",");
719 ppPPC32RI(i->Pin.Sh32.shft);
720 return;
cerionb85e8bb2005-02-16 08:54:33 +0000721 case Pin_Cmp32:
722 vex_printf("cmp%s %%crf%d,",
723 i->Pin.Cmp32.src2->tag == Pri_Imm ? "i" : "",
724 i->Pin.Cmp32.crfD);
725 ppHRegPPC32(i->Pin.Alu32.src1);
726 vex_printf(",");
727 ppPPC32RI(i->Pin.Alu32.src2);
728 return;
729 case Pin_Unary32:
730 vex_printf("%s ", showPPC32UnaryOp(i->Pin.Unary32.op));
731 ppHRegPPC32(i->Pin.Unary32.dst);
732 vex_printf(",");
733 ppHRegPPC32(i->Pin.Unary32.src);
734 return;
735 case Pin_MulL:
736 if (i->Pin.MulL.src2->tag == Pri_Imm) {
737 vex_printf("mulli ");
738 } else {
739 vex_printf("mul%s%c ",
740 i->Pin.MulL.word ? "hw" : "lw",
741 i->Pin.MulL.syned ? 's' : 'u');
742 }
743 ppHRegPPC32(i->Pin.MulL.dst);
744 vex_printf(",");
745 ppHRegPPC32(i->Pin.MulL.src1);
746 vex_printf(",");
747 ppPPC32RI(i->Pin.MulL.src2);
748 return;
749 case Pin_Div:
750 vex_printf("divw%s ",
751 i->Pin.Div.syned ? "" : "u");
cerion33aa6da2005-02-16 10:25:26 +0000752 ppHRegPPC32(i->Pin.Div.dst);
cerionb85e8bb2005-02-16 08:54:33 +0000753 vex_printf(",");
cerion33aa6da2005-02-16 10:25:26 +0000754 ppHRegPPC32(i->Pin.Div.src1);
cerionb85e8bb2005-02-16 08:54:33 +0000755 vex_printf(",");
cerion33aa6da2005-02-16 10:25:26 +0000756 ppHRegPPC32(i->Pin.Div.src2);
cerionb85e8bb2005-02-16 08:54:33 +0000757 return;
cerionbcf8c3e2005-02-04 16:17:07 +0000758//.. case Xin_Sh3232:
759//.. vex_printf("%sdl ", showX86ShiftOp(i->Xin.Sh3232.op));
760//.. if (i->Xin.Sh3232.amt == 0)
761//.. vex_printf(" %%cl,");
762//.. else
763//.. vex_printf(" $%d,", i->Xin.Sh3232.amt);
764//.. ppHRegX86(i->Xin.Sh3232.src);
765//.. vex_printf(",");
766//.. ppHRegX86(i->Xin.Sh3232.dst);
767//.. return;
768//.. case Xin_Push:
769//.. vex_printf("pushl ");
770//.. ppX86RMI(i->Xin.Push.src);
771//.. return;
cerionb85e8bb2005-02-16 08:54:33 +0000772 case Pin_Call:
cerion98411db2005-02-16 14:14:49 +0000773 vex_printf("call: la r12, 0x%x ; mtctr r12 ; bcctrl[%d] %s",
cerion33aa6da2005-02-16 10:25:26 +0000774 i->Pin.Call.target,
775 i->Pin.Call.regparms,
776 showPPC32CondCode(i->Pin.Call.cond));
cerionb85e8bb2005-02-16 08:54:33 +0000777 break;
778 case Pin_Goto:
cerion33aa6da2005-02-16 10:25:26 +0000779 vex_printf("goto: ");
cerionb85e8bb2005-02-16 08:54:33 +0000780 if (i->Pin.Goto.cond.test != Pct_ALWAYS) {
cerione97e1062005-02-21 15:09:19 +0000781 vex_printf("if (%%crf0.%s) { ",
cerionb85e8bb2005-02-16 08:54:33 +0000782 showPPC32CondCode(i->Pin.Goto.cond));
783 }
784 if (i->Pin.Goto.jk != Ijk_Boring) {
cerione97e1062005-02-21 15:09:19 +0000785 vex_printf("li %%r31, $");
cerionb85e8bb2005-02-16 08:54:33 +0000786 ppIRJumpKind(i->Pin.Goto.jk);
787 vex_printf(" ; ");
788 }
cerione97e1062005-02-21 15:09:19 +0000789 if (i->Pin.Goto.dst->tag == Pri_Imm) {
790 if (i->Pin.Goto.dst->Pri.Imm.imm32 < 0x10000) {
791 vex_printf("li %%r3, ");
792 ppPPC32RI(i->Pin.Goto.dst);
793 vex_printf(" ; ");
794 } else {
795 vex_printf("lis %%r3,0x%x ; ",
796 i->Pin.Goto.dst->Pri.Imm.imm32 >> 16);
797 vex_printf("la %%r3,0x%x(%%r3) ; ",
798 i->Pin.Goto.dst->Pri.Imm.imm32 & 0xFFFF);
799 }
800 } else {
801 vex_printf("if (%%r3 != ");
802 ppHRegPPC32(i->Pin.Goto.dst->Pri.Reg.reg);
803 vex_printf(") { mr %%r3,");
804 ppHRegPPC32(i->Pin.Goto.dst->Pri.Reg.reg);
805 vex_printf(" } ; ");
806 }
807 vex_printf("blr");
808 // vex_printf("mtctr %%r_dst ; ");
809 // vex_printf("bctr");
cerionb85e8bb2005-02-16 08:54:33 +0000810 if (i->Pin.Goto.cond.test != Pct_ALWAYS) {
811 vex_printf(" }");
812 }
813 return;
814 case Pin_CMov32:
cerionab9132d2005-02-15 15:46:59 +0000815// bc false,cond,8
816// li ...
cerionb85e8bb2005-02-16 08:54:33 +0000817 vex_printf("cmov32 (%s) ", showPPC32CondCode(i->Pin.CMov32.cond));
818 ppHRegPPC32(i->Pin.CMov32.dst);
819 vex_printf(",");
820 ppPPC32RI(i->Pin.CMov32.src);
821 return;
cerion7cf8e4e2005-02-16 16:08:17 +0000822 case Pin_Load: {
823 UChar sz = i->Pin.Load.sz;
824 Bool syned = i->Pin.Load.syned;
cerione97e1062005-02-21 15:09:19 +0000825 Bool idxd = (i->Pin.Load.src->tag == Pam_RR) ? True : False;
cerion7cf8e4e2005-02-16 16:08:17 +0000826 vex_printf("l%c%c%s ",
cerionb85e8bb2005-02-16 08:54:33 +0000827 (sz==1) ? 'b' : (sz==2 ? 'h' : 'w'),
828 syned ? 'a' : 'z',
cerionb85e8bb2005-02-16 08:54:33 +0000829 idxd ? "x" : "" );
cerion7cf8e4e2005-02-16 16:08:17 +0000830 ppHRegPPC32(i->Pin.Load.dst);
cerionb85e8bb2005-02-16 08:54:33 +0000831 vex_printf(",");
cerion7cf8e4e2005-02-16 16:08:17 +0000832 ppPPC32AMode(i->Pin.Load.src);
cerionb85e8bb2005-02-16 08:54:33 +0000833 return;
834 }
835 case Pin_Store: {
836 UChar sz = i->Pin.Store.sz;
cerione97e1062005-02-21 15:09:19 +0000837 Bool idxd = (i->Pin.Store.dst->tag == Pam_RR) ? True : False;
cerion7cf8e4e2005-02-16 16:08:17 +0000838 vex_printf("st%c%s ",
cerionb85e8bb2005-02-16 08:54:33 +0000839 (sz==1) ? 'b' : (sz==2 ? 'h' : 'w'),
cerionb85e8bb2005-02-16 08:54:33 +0000840 idxd ? "x" : "" );
841 ppHRegPPC32(i->Pin.Store.src);
842 vex_printf(",");
843 ppPPC32AMode(i->Pin.Store.dst);
844 return;
845 }
846 case Pin_Set32:
847 vex_printf("set32 (%s) ", showPPC32CondCode(i->Pin.Set32.cond));
848 ppHRegPPC32(i->Pin.Set32.dst);
849 return;
cerionbcf8c3e2005-02-04 16:17:07 +0000850//.. case Xin_Bsfr32:
851//.. vex_printf("bs%cl ", i->Xin.Bsfr32.isFwds ? 'f' : 'r');
852//.. ppHRegX86(i->Xin.Bsfr32.src);
853//.. vex_printf(",");
854//.. ppHRegX86(i->Xin.Bsfr32.dst);
855//.. return;
cerionb85e8bb2005-02-16 08:54:33 +0000856 case Pin_MFence:
cerion98411db2005-02-16 14:14:49 +0000857 vex_printf("mfence (=sync)");
cerionb85e8bb2005-02-16 08:54:33 +0000858 return;
cerionbcf8c3e2005-02-04 16:17:07 +0000859//.. case Xin_FpUnary:
860//.. vex_printf("g%sD ", showX86FpOp(i->Xin.FpUnary.op));
861//.. ppHRegX86(i->Xin.FpUnary.src);
862//.. vex_printf(",");
863//.. ppHRegX86(i->Xin.FpUnary.dst);
864//.. break;
865//.. case Xin_FpBinary:
866//.. vex_printf("g%sD ", showX86FpOp(i->Xin.FpBinary.op));
867//.. ppHRegX86(i->Xin.FpBinary.srcL);
868//.. vex_printf(",");
869//.. ppHRegX86(i->Xin.FpBinary.srcR);
870//.. vex_printf(",");
871//.. ppHRegX86(i->Xin.FpBinary.dst);
872//.. break;
873//.. case Xin_FpLdSt:
874//.. if (i->Xin.FpLdSt.isLoad) {
875//.. vex_printf("gld%c " , i->Xin.FpLdSt.sz==8 ? 'D' : 'F');
876//.. ppX86AMode(i->Xin.FpLdSt.addr);
877//.. vex_printf(", ");
878//.. ppHRegX86(i->Xin.FpLdSt.reg);
879//.. } else {
880//.. vex_printf("gst%c " , i->Xin.FpLdSt.sz==8 ? 'D' : 'F');
881//.. ppHRegX86(i->Xin.FpLdSt.reg);
882//.. vex_printf(", ");
883//.. ppX86AMode(i->Xin.FpLdSt.addr);
884//.. }
885//.. return;
886//.. case Xin_FpLdStI:
887//.. if (i->Xin.FpLdStI.isLoad) {
888//.. vex_printf("gild%s ", i->Xin.FpLdStI.sz==8 ? "ll" :
889//.. i->Xin.FpLdStI.sz==4 ? "l" : "w");
890//.. ppX86AMode(i->Xin.FpLdStI.addr);
891//.. vex_printf(", ");
892//.. ppHRegX86(i->Xin.FpLdStI.reg);
893//.. } else {
894//.. vex_printf("gist%s ", i->Xin.FpLdStI.sz==8 ? "ll" :
895//.. i->Xin.FpLdStI.sz==4 ? "l" : "w");
896//.. ppHRegX86(i->Xin.FpLdStI.reg);
897//.. vex_printf(", ");
898//.. ppX86AMode(i->Xin.FpLdStI.addr);
899//.. }
900//.. return;
901//.. case Xin_Fp64to32:
902//.. vex_printf("gdtof ");
903//.. ppHRegX86(i->Xin.Fp64to32.src);
904//.. vex_printf(",");
905//.. ppHRegX86(i->Xin.Fp64to32.dst);
906//.. return;
907//.. case Xin_FpCMov:
908//.. vex_printf("gcmov%s ", showX86CondCode(i->Xin.FpCMov.cond));
909//.. ppHRegX86(i->Xin.FpCMov.src);
910//.. vex_printf(",");
911//.. ppHRegX86(i->Xin.FpCMov.dst);
912//.. return;
913//.. case Xin_FpLdStCW:
914//.. vex_printf(i->Xin.FpLdStCW.isLoad ? "fldcw " : "fstcw ");
915//.. ppX86AMode(i->Xin.FpLdStCW.addr);
916//.. return;
917//.. case Xin_FpStSW_AX:
918//.. vex_printf("fstsw %%ax");
919//.. return;
920//.. case Xin_FpCmp:
921//.. vex_printf("gcmp ");
922//.. ppHRegX86(i->Xin.FpCmp.srcL);
923//.. vex_printf(",");
924//.. ppHRegX86(i->Xin.FpCmp.srcR);
925//.. vex_printf(",");
926//.. ppHRegX86(i->Xin.FpCmp.dst);
927//.. break;
928//.. case Xin_SseConst:
929//.. vex_printf("const $0x%04x,", (Int)i->Xin.SseConst.con);
930//.. ppHRegX86(i->Xin.SseConst.dst);
931//.. break;
932//.. case Xin_SseLdSt:
933//.. vex_printf("movups ");
934//.. if (i->Xin.SseLdSt.isLoad) {
935//.. ppX86AMode(i->Xin.SseLdSt.addr);
936//.. vex_printf(",");
937//.. ppHRegX86(i->Xin.SseLdSt.reg);
938//.. } else {
939//.. ppHRegX86(i->Xin.SseLdSt.reg);
940//.. vex_printf(",");
941//.. ppX86AMode(i->Xin.SseLdSt.addr);
942//.. }
943//.. return;
944//.. case Xin_SseLdzLO:
945//.. vex_printf("movs%s ", i->Xin.SseLdzLO.sz==4 ? "s" : "d");
946//.. ppX86AMode(i->Xin.SseLdzLO.addr);
947//.. vex_printf(",");
948//.. ppHRegX86(i->Xin.SseLdzLO.reg);
949//.. return;
950//.. case Xin_Sse32Fx4:
951//.. vex_printf("%sps ", showX86SseOp(i->Xin.Sse32Fx4.op));
952//.. ppHRegX86(i->Xin.Sse32Fx4.src);
953//.. vex_printf(",");
954//.. ppHRegX86(i->Xin.Sse32Fx4.dst);
955//.. return;
956//.. case Xin_Sse32FLo:
957//.. vex_printf("%sss ", showX86SseOp(i->Xin.Sse32FLo.op));
958//.. ppHRegX86(i->Xin.Sse32FLo.src);
959//.. vex_printf(",");
960//.. ppHRegX86(i->Xin.Sse32FLo.dst);
961//.. return;
962//.. case Xin_Sse64Fx2:
963//.. vex_printf("%spd ", showX86SseOp(i->Xin.Sse64Fx2.op));
964//.. ppHRegX86(i->Xin.Sse64Fx2.src);
965//.. vex_printf(",");
966//.. ppHRegX86(i->Xin.Sse64Fx2.dst);
967//.. return;
968//.. case Xin_Sse64FLo:
969//.. vex_printf("%ssd ", showX86SseOp(i->Xin.Sse64FLo.op));
970//.. ppHRegX86(i->Xin.Sse64FLo.src);
971//.. vex_printf(",");
972//.. ppHRegX86(i->Xin.Sse64FLo.dst);
973//.. return;
974//.. case Xin_SseReRg:
975//.. vex_printf("%s ", showX86SseOp(i->Xin.SseReRg.op));
976//.. ppHRegX86(i->Xin.SseReRg.src);
977//.. vex_printf(",");
978//.. ppHRegX86(i->Xin.SseReRg.dst);
979//.. return;
980//.. case Xin_SseCMov:
981//.. vex_printf("cmov%s ", showX86CondCode(i->Xin.SseCMov.cond));
982//.. ppHRegX86(i->Xin.SseCMov.src);
983//.. vex_printf(",");
984//.. ppHRegX86(i->Xin.SseCMov.dst);
985//.. return;
986//.. case Xin_SseShuf:
987//.. vex_printf("pshufd $0x%x,", i->Xin.SseShuf.order);
988//.. ppHRegX86(i->Xin.SseShuf.src);
989//.. vex_printf(",");
990//.. ppHRegX86(i->Xin.SseShuf.dst);
991//.. return;
992
cerionb85e8bb2005-02-16 08:54:33 +0000993 default:
994 vex_printf("\nppPPC32Instr(ppc32): No such tag(%d)\n", i->tag);
995 vpanic("ppPPC32Instr(ppc32)");
cerionbcf8c3e2005-02-04 16:17:07 +0000996 }
997}
998
999/* --------- Helpers for register allocation. --------- */
1000
1001void getRegUsage_PPC32Instr ( HRegUsage* u, PPC32Instr* i )
1002{
1003// Bool unary;
1004 initHRegUsage(u);
1005 switch (i->tag) {
cerionb85e8bb2005-02-16 08:54:33 +00001006 case Pin_Alu32:
1007 addHRegUse(u, HRmRead, i->Pin.Alu32.src1);
1008 addRegUsage_PPC32RI(u, i->Pin.Alu32.src2);
cerionb85e8bb2005-02-16 08:54:33 +00001009 addHRegUse(u, HRmWrite, i->Pin.Alu32.dst);
cerionb85e8bb2005-02-16 08:54:33 +00001010 return;
cerioncd304492005-02-08 19:40:24 +00001011
cerionb85e8bb2005-02-16 08:54:33 +00001012 case Pin_Sh32:
1013 addHRegUse(u, HRmWrite, i->Pin.Sh32.dst);
1014 addHRegUse(u, HRmRead, i->Pin.Sh32.src);
1015 addRegUsage_PPC32RI(u, i->Pin.Sh32.shft);
cerionb85e8bb2005-02-16 08:54:33 +00001016 return;
1017
cerionb85e8bb2005-02-16 08:54:33 +00001018 case Pin_Cmp32:
1019 addHRegUse(u, HRmRead, i->Pin.Cmp32.src1);
1020 addRegUsage_PPC32RI(u, i->Pin.Cmp32.src2);
1021 return;
cerionab9132d2005-02-15 15:46:59 +00001022
cerionb85e8bb2005-02-16 08:54:33 +00001023 case Pin_Unary32:
1024 addHRegUse(u, HRmWrite, i->Pin.Unary32.dst);
1025 addHRegUse(u, HRmRead, i->Pin.Unary32.src);
1026 return;
1027 case Pin_MulL:
1028 addHRegUse(u, HRmWrite, i->Pin.MulL.dst);
1029 addHRegUse(u, HRmRead, i->Pin.MulL.src1);
1030 addRegUsage_PPC32RI(u, i->Pin.MulL.src2);
1031 return;
1032 case Pin_Div:
1033 addHRegUse(u, HRmWrite, i->Pin.Div.dst);
1034 addHRegUse(u, HRmRead, i->Pin.Div.src1);
cerion33aa6da2005-02-16 10:25:26 +00001035 addHRegUse(u, HRmRead, i->Pin.Div.src2);
cerionb85e8bb2005-02-16 08:54:33 +00001036 return;
cerionbcf8c3e2005-02-04 16:17:07 +00001037//.. case Xin_Sh3232:
1038//.. addHRegUse(u, HRmRead, i->Xin.Sh3232.src);
1039//.. addHRegUse(u, HRmModify, i->Xin.Sh3232.dst);
1040//.. if (i->Xin.Sh3232.amt == 0)
1041//.. addHRegUse(u, HRmRead, hregX86_ECX());
1042//.. return;
1043//.. case Xin_Push:
1044//.. addRegUsage_X86RMI(u, i->Xin.Push.src);
1045//.. addHRegUse(u, HRmModify, hregX86_ESP());
1046//.. return;
cerionb85e8bb2005-02-16 08:54:33 +00001047 case Pin_Call:
1048 /* This is a bit subtle. */
1049 /* First off, claim it trashes all the caller-saved regs
1050 which fall within the register allocator's jurisdiction.
ceriona56e9cc2005-02-16 18:08:25 +00001051 These I believe to be: r3:12
cerionb85e8bb2005-02-16 08:54:33 +00001052 */
cerionb85e8bb2005-02-16 08:54:33 +00001053 addHRegUse(u, HRmWrite, hregPPC32_GPR3());
1054 addHRegUse(u, HRmWrite, hregPPC32_GPR4());
1055 addHRegUse(u, HRmWrite, hregPPC32_GPR5());
1056 addHRegUse(u, HRmWrite, hregPPC32_GPR6());
1057 addHRegUse(u, HRmWrite, hregPPC32_GPR7());
1058 addHRegUse(u, HRmWrite, hregPPC32_GPR8());
1059 addHRegUse(u, HRmWrite, hregPPC32_GPR9());
1060 addHRegUse(u, HRmWrite, hregPPC32_GPR10());
1061 addHRegUse(u, HRmWrite, hregPPC32_GPR11());
1062 addHRegUse(u, HRmWrite, hregPPC32_GPR12());
1063
1064 /* Now we have to state any parameter-carrying registers
1065 which might be read. This depends on the regparmness. */
1066 switch (i->Pin.Call.regparms) {
1067 case 8: addHRegUse(u, HRmRead, hregPPC32_GPR10()); /*fallthru*/
1068 case 7: addHRegUse(u, HRmRead, hregPPC32_GPR9() ); /*fallthru*/
1069 case 6: addHRegUse(u, HRmRead, hregPPC32_GPR8() ); /*fallthru*/
1070 case 5: addHRegUse(u, HRmRead, hregPPC32_GPR7() ); /*fallthru*/
1071 case 4: addHRegUse(u, HRmRead, hregPPC32_GPR6() ); /*fallthru*/
1072 case 3: addHRegUse(u, HRmRead, hregPPC32_GPR5() ); /*fallthru*/
1073 case 2: addHRegUse(u, HRmRead, hregPPC32_GPR4() ); /*fallthru*/
1074 case 1: addHRegUse(u, HRmRead, hregPPC32_GPR3() ); /*fallthru*/
1075 case 0: break;
1076 default: vpanic("getRegUsage_PPC32Instr:Call:regparms");
1077 }
1078 /* Finally, there is the issue that the insn trashes a
1079 register because the literal target address has to be
ceriona56e9cc2005-02-16 18:08:25 +00001080 loaded into a register. %r12 seems a suitable victim.
1081 (Can't use %r0, as use ops that interpret it as value zero). */
cerionb85e8bb2005-02-16 08:54:33 +00001082 addHRegUse(u, HRmWrite, hregPPC32_GPR12());
1083 /* Upshot of this is that the assembler really must use %r12,
ceriona56e9cc2005-02-16 18:08:25 +00001084 and no other, as a destination temporary. */
cerionb85e8bb2005-02-16 08:54:33 +00001085 return;
1086 case Pin_Goto:
1087 addRegUsage_PPC32RI(u, i->Pin.Goto.dst);
ceriona56e9cc2005-02-16 18:08:25 +00001088 /* GPR3 holds destination address from Pin_Goto */
1089 addHRegUse(u, HRmWrite, hregPPC32_GPR3());
cerionb85e8bb2005-02-16 08:54:33 +00001090 if (i->Pin.Goto.jk != Ijk_Boring)
1091 addHRegUse(u, HRmWrite, GuestStatePtr);
1092 return;
1093 case Pin_CMov32:
1094 addRegUsage_PPC32RI(u, i->Pin.CMov32.src);
1095 addHRegUse(u, HRmModify, i->Pin.CMov32.dst);
1096 return;
cerion7cf8e4e2005-02-16 16:08:17 +00001097 case Pin_Load:
1098 addRegUsage_PPC32AMode(u, i->Pin.Load.src);
1099 addHRegUse(u, HRmWrite, i->Pin.Load.dst);
cerionb85e8bb2005-02-16 08:54:33 +00001100 return;
1101 case Pin_Store:
1102 addHRegUse(u, HRmRead, i->Pin.Store.src);
1103 addRegUsage_PPC32AMode(u, i->Pin.Store.dst);
1104 return;
1105 case Pin_Set32:
1106 addHRegUse(u, HRmWrite, i->Pin.Set32.dst);
1107 return;
cerionbcf8c3e2005-02-04 16:17:07 +00001108//.. case Xin_Bsfr32:
1109//.. addHRegUse(u, HRmRead, i->Xin.Bsfr32.src);
1110//.. addHRegUse(u, HRmWrite, i->Xin.Bsfr32.dst);
1111//.. return;
cerionb85e8bb2005-02-16 08:54:33 +00001112 case Pin_MFence:
1113 return;
cerionbcf8c3e2005-02-04 16:17:07 +00001114//.. case Xin_FpUnary:
1115//.. addHRegUse(u, HRmRead, i->Xin.FpUnary.src);
1116//.. addHRegUse(u, HRmWrite, i->Xin.FpUnary.dst);
1117//.. return;
1118//.. case Xin_FpBinary:
1119//.. addHRegUse(u, HRmRead, i->Xin.FpBinary.srcL);
1120//.. addHRegUse(u, HRmRead, i->Xin.FpBinary.srcR);
1121//.. addHRegUse(u, HRmWrite, i->Xin.FpBinary.dst);
1122//.. return;
1123//.. case Xin_FpLdSt:
1124//.. addRegUsage_X86AMode(u, i->Xin.FpLdSt.addr);
1125//.. addHRegUse(u, i->Xin.FpLdSt.isLoad ? HRmWrite : HRmRead,
1126//.. i->Xin.FpLdSt.reg);
1127//.. return;
1128//.. case Xin_FpLdStI:
1129//.. addRegUsage_X86AMode(u, i->Xin.FpLdStI.addr);
1130//.. addHRegUse(u, i->Xin.FpLdStI.isLoad ? HRmWrite : HRmRead,
1131//.. i->Xin.FpLdStI.reg);
1132//.. return;
1133//.. case Xin_Fp64to32:
1134//.. addHRegUse(u, HRmRead, i->Xin.Fp64to32.src);
1135//.. addHRegUse(u, HRmWrite, i->Xin.Fp64to32.dst);
1136//.. return;
1137//.. case Xin_FpCMov:
1138//.. addHRegUse(u, HRmRead, i->Xin.FpCMov.src);
1139//.. addHRegUse(u, HRmModify, i->Xin.FpCMov.dst);
1140//.. return;
1141//.. case Xin_FpLdStCW:
1142//.. addRegUsage_X86AMode(u, i->Xin.FpLdStCW.addr);
1143//.. return;
1144//.. case Xin_FpStSW_AX:
1145//.. addHRegUse(u, HRmWrite, hregX86_EAX());
1146//.. return;
1147//.. case Xin_FpCmp:
1148//.. addHRegUse(u, HRmRead, i->Xin.FpCmp.srcL);
1149//.. addHRegUse(u, HRmRead, i->Xin.FpCmp.srcR);
1150//.. addHRegUse(u, HRmWrite, i->Xin.FpCmp.dst);
1151//.. addHRegUse(u, HRmWrite, hregX86_EAX());
1152//.. return;
1153//.. case Xin_SseLdSt:
1154//.. addRegUsage_X86AMode(u, i->Xin.SseLdSt.addr);
1155//.. addHRegUse(u, i->Xin.SseLdSt.isLoad ? HRmWrite : HRmRead,
1156//.. i->Xin.SseLdSt.reg);
1157//.. return;
1158//.. case Xin_SseLdzLO:
1159//.. addRegUsage_X86AMode(u, i->Xin.SseLdzLO.addr);
1160//.. addHRegUse(u, HRmWrite, i->Xin.SseLdzLO.reg);
1161//.. return;
1162//.. case Xin_SseConst:
1163//.. addHRegUse(u, HRmWrite, i->Xin.SseConst.dst);
1164//.. return;
1165//.. case Xin_Sse32Fx4:
1166//.. vassert(i->Xin.Sse32Fx4.op != Xsse_MOV);
1167//.. unary = i->Xin.Sse32Fx4.op == Xsse_RCPF
1168//.. || i->Xin.Sse32Fx4.op == Xsse_RSQRTF
1169//.. || i->Xin.Sse32Fx4.op == Xsse_SQRTF;
1170//.. addHRegUse(u, HRmRead, i->Xin.Sse32Fx4.src);
1171//.. addHRegUse(u, unary ? HRmWrite : HRmModify,
1172//.. i->Xin.Sse32Fx4.dst);
1173//.. return;
1174//.. case Xin_Sse32FLo:
1175//.. vassert(i->Xin.Sse32FLo.op != Xsse_MOV);
1176//.. unary = i->Xin.Sse32FLo.op == Xsse_RCPF
1177//.. || i->Xin.Sse32FLo.op == Xsse_RSQRTF
1178//.. || i->Xin.Sse32FLo.op == Xsse_SQRTF;
1179//.. addHRegUse(u, HRmRead, i->Xin.Sse32FLo.src);
1180//.. addHRegUse(u, unary ? HRmWrite : HRmModify,
1181//.. i->Xin.Sse32FLo.dst);
1182//.. return;
1183//.. case Xin_Sse64Fx2:
1184//.. vassert(i->Xin.Sse64Fx2.op != Xsse_MOV);
1185//.. unary = i->Xin.Sse64Fx2.op == Xsse_RCPF
1186//.. || i->Xin.Sse64Fx2.op == Xsse_RSQRTF
1187//.. || i->Xin.Sse64Fx2.op == Xsse_SQRTF;
1188//.. addHRegUse(u, HRmRead, i->Xin.Sse64Fx2.src);
1189//.. addHRegUse(u, unary ? HRmWrite : HRmModify,
1190//.. i->Xin.Sse64Fx2.dst);
1191//.. return;
1192//.. case Xin_Sse64FLo:
1193//.. vassert(i->Xin.Sse64FLo.op != Xsse_MOV);
1194//.. unary = i->Xin.Sse64FLo.op == Xsse_RCPF
1195//.. || i->Xin.Sse64FLo.op == Xsse_RSQRTF
1196//.. || i->Xin.Sse64FLo.op == Xsse_SQRTF;
1197//.. addHRegUse(u, HRmRead, i->Xin.Sse64FLo.src);
1198//.. addHRegUse(u, unary ? HRmWrite : HRmModify,
1199//.. i->Xin.Sse64FLo.dst);
1200//.. return;
1201//.. case Xin_SseReRg:
1202//.. if (i->Xin.SseReRg.op == Xsse_XOR
1203//.. && i->Xin.SseReRg.src == i->Xin.SseReRg.dst) {
1204//.. /* reg-alloc needs to understand 'xor r,r' as a write of r */
1205//.. /* (as opposed to a rite of passage :-) */
1206//.. addHRegUse(u, HRmWrite, i->Xin.SseReRg.dst);
1207//.. } else {
1208//.. addHRegUse(u, HRmRead, i->Xin.SseReRg.src);
1209//.. addHRegUse(u, i->Xin.SseReRg.op == Xsse_MOV
1210//.. ? HRmWrite : HRmModify,
1211//.. i->Xin.SseReRg.dst);
1212//.. }
1213//.. return;
1214//.. case Xin_SseCMov:
1215//.. addHRegUse(u, HRmRead, i->Xin.SseCMov.src);
1216//.. addHRegUse(u, HRmModify, i->Xin.SseCMov.dst);
1217//.. return;
1218//.. case Xin_SseShuf:
1219//.. addHRegUse(u, HRmRead, i->Xin.SseShuf.src);
1220//.. addHRegUse(u, HRmWrite, i->Xin.SseShuf.dst);
1221//.. return;
cerionb85e8bb2005-02-16 08:54:33 +00001222 default:
1223 ppPPC32Instr(i);
1224 vpanic("getRegUsage_PPC32Instr");
cerionbcf8c3e2005-02-04 16:17:07 +00001225 }
1226}
1227
cerioncd304492005-02-08 19:40:24 +00001228/* local helper */
1229static void mapReg(HRegRemap* m, HReg* r)
1230{
1231 *r = lookupHRegRemap(m, *r);
1232}
cerionbcf8c3e2005-02-04 16:17:07 +00001233
1234void mapRegs_PPC32Instr (HRegRemap* m, PPC32Instr* i)
1235{
1236 switch (i->tag) {
cerionb85e8bb2005-02-16 08:54:33 +00001237 case Pin_Alu32:
1238 mapReg(m, &i->Pin.Alu32.dst);
1239 mapReg(m, &i->Pin.Alu32.src1);
1240 mapRegs_PPC32RI(m, i->Pin.Alu32.src2);
1241 return;
1242 case Pin_Sh32:
1243 mapReg(m, &i->Pin.Sh32.dst);
1244 mapReg(m, &i->Pin.Sh32.src);
1245 mapRegs_PPC32RI(m, i->Pin.Sh32.shft);
1246 return;
cerionb85e8bb2005-02-16 08:54:33 +00001247 case Pin_Cmp32:
1248 mapReg(m, &i->Pin.Cmp32.src1);
1249 mapRegs_PPC32RI(m, i->Pin.Cmp32.src2);
1250 return;
1251 case Pin_Unary32:
1252 mapReg(m, &i->Pin.Unary32.dst);
1253 mapReg(m, &i->Pin.Unary32.src);
1254 return;
1255 case Pin_MulL:
1256 mapReg(m, &i->Pin.MulL.dst);
1257 mapReg(m, &i->Pin.MulL.src1);
1258 mapRegs_PPC32RI(m, i->Pin.MulL.src2);
1259 return;
1260 case Pin_Div:
1261 mapReg(m, &i->Pin.Div.dst);
1262 mapReg(m, &i->Pin.Div.src1);
cerion33aa6da2005-02-16 10:25:26 +00001263 mapReg(m, &i->Pin.Div.src2);
cerionb85e8bb2005-02-16 08:54:33 +00001264 return;
cerionbcf8c3e2005-02-04 16:17:07 +00001265//.. case Xin_Sh3232:
1266//.. mapReg(m, &i->Xin.Sh3232.src);
1267//.. mapReg(m, &i->Xin.Sh3232.dst);
1268//.. return;
1269//.. case Xin_Push:
1270//.. mapRegs_X86RMI(m, i->Xin.Push.src);
1271//.. return;
cerionb85e8bb2005-02-16 08:54:33 +00001272 case Pin_Call:
1273 return;
1274 case Pin_Goto:
1275 mapRegs_PPC32RI(m, i->Pin.Goto.dst);
1276 return;
1277 case Pin_CMov32:
1278 mapRegs_PPC32RI(m, i->Pin.CMov32.src);
1279 mapReg(m, &i->Pin.CMov32.dst);
1280 return;
cerion7cf8e4e2005-02-16 16:08:17 +00001281 case Pin_Load:
1282 mapRegs_PPC32AMode(m, i->Pin.Load.src);
1283 mapReg(m, &i->Pin.Load.dst);
cerionb85e8bb2005-02-16 08:54:33 +00001284 return;
1285 case Pin_Store:
1286 mapReg(m, &i->Pin.Store.src);
1287 mapRegs_PPC32AMode(m, i->Pin.Store.dst);
1288 return;
1289 case Pin_Set32:
1290 mapReg(m, &i->Pin.Set32.dst);
1291 return;
cerionbcf8c3e2005-02-04 16:17:07 +00001292//.. case Xin_Bsfr32:
1293//.. mapReg(m, &i->Xin.Bsfr32.src);
1294//.. mapReg(m, &i->Xin.Bsfr32.dst);
1295//.. return;
cerionb85e8bb2005-02-16 08:54:33 +00001296 case Pin_MFence:
1297 return;
cerionbcf8c3e2005-02-04 16:17:07 +00001298//.. case Xin_FpUnary:
1299//.. mapReg(m, &i->Xin.FpUnary.src);
1300//.. mapReg(m, &i->Xin.FpUnary.dst);
1301//.. return;
1302//.. case Xin_FpBinary:
1303//.. mapReg(m, &i->Xin.FpBinary.srcL);
1304//.. mapReg(m, &i->Xin.FpBinary.srcR);
1305//.. mapReg(m, &i->Xin.FpBinary.dst);
1306//.. return;
1307//.. case Xin_FpLdSt:
1308//.. mapRegs_X86AMode(m, i->Xin.FpLdSt.addr);
1309//.. mapReg(m, &i->Xin.FpLdSt.reg);
1310//.. return;
1311//.. case Xin_FpLdStI:
1312//.. mapRegs_X86AMode(m, i->Xin.FpLdStI.addr);
1313//.. mapReg(m, &i->Xin.FpLdStI.reg);
1314//.. return;
1315//.. case Xin_Fp64to32:
1316//.. mapReg(m, &i->Xin.Fp64to32.src);
1317//.. mapReg(m, &i->Xin.Fp64to32.dst);
1318//.. return;
1319//.. case Xin_FpCMov:
1320//.. mapReg(m, &i->Xin.FpCMov.src);
1321//.. mapReg(m, &i->Xin.FpCMov.dst);
1322//.. return;
1323//.. case Xin_FpLdStCW:
1324//.. mapRegs_X86AMode(m, i->Xin.FpLdStCW.addr);
1325//.. return;
1326//.. case Xin_FpStSW_AX:
1327//.. return;
1328//.. case Xin_FpCmp:
1329//.. mapReg(m, &i->Xin.FpCmp.srcL);
1330//.. mapReg(m, &i->Xin.FpCmp.srcR);
1331//.. mapReg(m, &i->Xin.FpCmp.dst);
1332//.. return;
1333//.. case Xin_SseConst:
1334//.. mapReg(m, &i->Xin.SseConst.dst);
1335//.. return;
1336//.. case Xin_SseLdSt:
1337//.. mapReg(m, &i->Xin.SseLdSt.reg);
1338//.. mapRegs_X86AMode(m, i->Xin.SseLdSt.addr);
1339//.. break;
1340//.. case Xin_SseLdzLO:
1341//.. mapReg(m, &i->Xin.SseLdzLO.reg);
1342//.. mapRegs_X86AMode(m, i->Xin.SseLdzLO.addr);
1343//.. break;
1344//.. case Xin_Sse32Fx4:
1345//.. mapReg(m, &i->Xin.Sse32Fx4.src);
1346//.. mapReg(m, &i->Xin.Sse32Fx4.dst);
1347//.. return;
1348//.. case Xin_Sse32FLo:
1349//.. mapReg(m, &i->Xin.Sse32FLo.src);
1350//.. mapReg(m, &i->Xin.Sse32FLo.dst);
1351//.. return;
1352//.. case Xin_Sse64Fx2:
1353//.. mapReg(m, &i->Xin.Sse64Fx2.src);
1354//.. mapReg(m, &i->Xin.Sse64Fx2.dst);
1355//.. return;
1356//.. case Xin_Sse64FLo:
1357//.. mapReg(m, &i->Xin.Sse64FLo.src);
1358//.. mapReg(m, &i->Xin.Sse64FLo.dst);
1359//.. return;
1360//.. case Xin_SseReRg:
1361//.. mapReg(m, &i->Xin.SseReRg.src);
1362//.. mapReg(m, &i->Xin.SseReRg.dst);
1363//.. return;
1364//.. case Xin_SseCMov:
1365//.. mapReg(m, &i->Xin.SseCMov.src);
1366//.. mapReg(m, &i->Xin.SseCMov.dst);
1367//.. return;
1368//.. case Xin_SseShuf:
1369//.. mapReg(m, &i->Xin.SseShuf.src);
1370//.. mapReg(m, &i->Xin.SseShuf.dst);
1371//.. return;
cerionb85e8bb2005-02-16 08:54:33 +00001372 default:
1373 ppPPC32Instr(i);
1374 vpanic("mapRegs_PPC32Instr");
cerionbcf8c3e2005-02-04 16:17:07 +00001375 }
1376}
1377
1378/* Figure out if i represents a reg-reg move, and if so assign the
1379 source and destination to *src and *dst. If in doubt say No. Used
1380 by the register allocator to do move coalescing.
1381*/
1382Bool isMove_PPC32Instr ( PPC32Instr* i, HReg* src, HReg* dst )
1383{
cerionab9132d2005-02-15 15:46:59 +00001384 /* Moves between integer regs */
1385 if (i->tag == Pin_Alu32) {
1386 // or Rd,Rs,Rs == mr Rd,Rs
1387 if (i->Pin.Alu32.op != Palu_OR)
1388 return False;
1389 if (i->Pin.Alu32.src2->tag != Pri_Reg)
1390 return False;
1391 if (i->Pin.Alu32.src2->Pri.Reg.reg != i->Pin.Alu32.src1)
cerionb85e8bb2005-02-16 08:54:33 +00001392 return False;
cerionab9132d2005-02-15 15:46:59 +00001393 *src = i->Pin.Alu32.src1;
1394 *dst = i->Pin.Alu32.dst;
1395 return True;
1396 }
cerionbcf8c3e2005-02-04 16:17:07 +00001397//.. /* Moves between FP regs */
1398//.. if (i->tag == Xin_FpUnary) {
1399//.. if (i->Xin.FpUnary.op != Xfp_MOV)
1400//.. return False;
1401//.. *src = i->Xin.FpUnary.src;
1402//.. *dst = i->Xin.FpUnary.dst;
1403//.. return True;
1404//.. }
1405//.. if (i->tag == Xin_SseReRg) {
1406//.. if (i->Xin.SseReRg.op != Xsse_MOV)
1407//.. return False;
1408//.. *src = i->Xin.SseReRg.src;
1409//.. *dst = i->Xin.SseReRg.dst;
1410//.. return True;
1411//.. }
1412 return False;
1413}
1414
1415
cerione13bb312005-02-10 19:51:03 +00001416/* Generate ppc32 spill/reload instructions under the direction of the
cerionbcf8c3e2005-02-04 16:17:07 +00001417 register allocator. Note it's critical these don't write the
1418 condition codes. */
1419
1420PPC32Instr* genSpill_PPC32 ( HReg rreg, Int offsetB )
cerione13bb312005-02-10 19:51:03 +00001421{
1422 PPC32AMode* am;
1423 vassert(offsetB >= 0);
1424 vassert(!hregIsVirtual(rreg));
1425 am = PPC32AMode_IR(offsetB, GuestStatePtr);
cerionb85e8bb2005-02-16 08:54:33 +00001426
cerione13bb312005-02-10 19:51:03 +00001427 switch (hregClass(rreg)) {
cerionb85e8bb2005-02-16 08:54:33 +00001428 case HRcInt32:
1429 return PPC32Instr_Store( 4, am, rreg);
1430// case HRcFlt64:
1431// return PPC32Instr_FpLdSt ( False/*store*/, 8, rreg, am );
1432// case HRcVec128:
1433// return PPC32Instr_SseLdSt ( False/*store*/, rreg, am );
1434 default:
1435 ppHRegClass(hregClass(rreg));
1436 vpanic("genSpill_PPC32: unimplemented regclass");
cerione13bb312005-02-10 19:51:03 +00001437 }
cerionbcf8c3e2005-02-04 16:17:07 +00001438}
1439
1440PPC32Instr* genReload_PPC32 ( HReg rreg, Int offsetB )
cerione13bb312005-02-10 19:51:03 +00001441{
1442 PPC32AMode* am;
1443 vassert(offsetB >= 0);
1444 vassert(!hregIsVirtual(rreg));
1445 am = PPC32AMode_IR(offsetB, GuestStatePtr);
1446
1447 switch (hregClass(rreg)) {
cerionb85e8bb2005-02-16 08:54:33 +00001448 case HRcInt32:
cerion7cf8e4e2005-02-16 16:08:17 +00001449 return PPC32Instr_Load( 4, False, rreg, am );
cerionb85e8bb2005-02-16 08:54:33 +00001450// case HRcFlt64:
1451// return PPC32Instr_FpLdSt ( True/*load*/, 8, rreg, am );
1452// case HRcVec128:
1453// return PPC32Instr_SseLdSt ( True/*load*/, rreg, am );
1454 default:
1455 ppHRegClass(hregClass(rreg));
1456 vpanic("genReload_PPC32: unimplemented regclass");
cerione13bb312005-02-10 19:51:03 +00001457 }
cerionbcf8c3e2005-02-04 16:17:07 +00001458}
1459
1460
ceriond5e38382005-02-11 13:38:15 +00001461/* --------- The ppc32 assembler (bleh.) --------- */
cerioncd304492005-02-08 19:40:24 +00001462
cerioncd304492005-02-08 19:40:24 +00001463static UInt iregNo ( HReg r )
1464{
1465 UInt n;
1466 vassert(hregClass(r) == HRcInt32);
1467 vassert(!hregIsVirtual(r));
1468 n = hregNumber(r);
1469 vassert(n <= 32);
1470 return n;
1471}
cerioncd304492005-02-08 19:40:24 +00001472
cerionbcf8c3e2005-02-04 16:17:07 +00001473//.. static UInt fregNo ( HReg r )
1474//.. {
1475//.. UInt n;
1476//.. vassert(hregClass(r) == HRcFlt64);
1477//.. vassert(!hregIsVirtual(r));
1478//.. n = hregNumber(r);
1479//.. vassert(n <= 5);
1480//.. return n;
1481//.. }
cerioncd304492005-02-08 19:40:24 +00001482
cerionbcf8c3e2005-02-04 16:17:07 +00001483//.. static UInt vregNo ( HReg r )
1484//.. {
1485//.. UInt n;
1486//.. vassert(hregClass(r) == HRcVec128);
1487//.. vassert(!hregIsVirtual(r));
1488//.. n = hregNumber(r);
1489//.. vassert(n <= 7);
1490//.. return n;
1491//.. }
cerioncd304492005-02-08 19:40:24 +00001492
cerionbcf8c3e2005-02-04 16:17:07 +00001493//.. static UChar mkModRegRM ( UChar mod, UChar reg, UChar regmem )
1494//.. {
1495//.. return ((mod & 3) << 6) | ((reg & 7) << 3) | (regmem & 7);
1496//.. }
cerioncd304492005-02-08 19:40:24 +00001497
cerionbcf8c3e2005-02-04 16:17:07 +00001498//.. static UChar mkSIB ( Int shift, Int regindex, Int regbase )
1499//.. {
1500//.. return ((shift & 3) << 6) | ((regindex & 7) << 3) | (regbase & 7);
1501//.. }
cerioncd304492005-02-08 19:40:24 +00001502
cerionab9132d2005-02-15 15:46:59 +00001503/* Emit 32bit instruction big-endianly */
ceriond5e38382005-02-11 13:38:15 +00001504static UChar* emit32 ( UChar* p, UInt w32 )
1505{
ceriond5e38382005-02-11 13:38:15 +00001506 *p++ = (w32 >> 24) & 0x000000FF;
cerionc056a882005-02-11 13:55:41 +00001507 *p++ = (w32 >> 16) & 0x000000FF;
1508 *p++ = (w32 >> 8) & 0x000000FF;
1509 *p++ = (w32) & 0x000000FF;
ceriond5e38382005-02-11 13:38:15 +00001510 return p;
1511}
cerioncd304492005-02-08 19:40:24 +00001512
cerionbcf8c3e2005-02-04 16:17:07 +00001513//.. /* Does a sign-extend of the lowest 8 bits give
1514//.. the original number? */
1515//.. static Bool fits8bits ( UInt w32 )
1516//.. {
1517//.. Int i32 = (Int)w32;
1518//.. return i32 == ((i32 << 24) >> 24);
1519//.. }
cerioncd304492005-02-08 19:40:24 +00001520
1521
cerionbcf8c3e2005-02-04 16:17:07 +00001522//.. /* Forming mod-reg-rm bytes and scale-index-base bytes.
1523//..
1524//.. greg, 0(ereg) | ereg != ESP && ereg != EBP
1525//.. = 00 greg ereg
1526//..
1527//.. greg, d8(ereg) | ereg != ESP
1528//.. = 01 greg ereg, d8
1529//..
1530//.. greg, d32(ereg) | ereg != ESP
1531//.. = 10 greg ereg, d32
1532//..
1533//.. greg, d8(%esp) = 01 greg 100, 0x24, d8
1534//..
1535//.. -----------------------------------------------
1536//..
1537//.. greg, d8(base,index,scale)
1538//.. | index != ESP
1539//.. = 01 greg 100, scale index base, d8
1540//..
1541//.. greg, d32(base,index,scale)
1542//.. | index != ESP
1543//.. = 10 greg 100, scale index base, d32
1544//.. */
1545//.. static UChar* doAMode_M ( UChar* p, HReg greg, X86AMode* am )
1546//.. {
1547//.. if (am->tag == Xam_IR) {
1548//.. if (am->Xam.IR.imm == 0
1549//.. && am->Xam.IR.reg != hregX86_ESP()
1550//.. && am->Xam.IR.reg != hregX86_EBP() ) {
1551//.. *p++ = mkModRegRM(0, iregNo(greg), iregNo(am->Xam.IR.reg));
1552//.. return p;
1553//.. }
1554//.. if (fits8bits(am->Xam.IR.imm)
1555//.. && am->Xam.IR.reg != hregX86_ESP()) {
1556//.. *p++ = mkModRegRM(1, iregNo(greg), iregNo(am->Xam.IR.reg));
1557//.. *p++ = am->Xam.IR.imm & 0xFF;
1558//.. return p;
1559//.. }
1560//.. if (am->Xam.IR.reg != hregX86_ESP()) {
1561//.. *p++ = mkModRegRM(2, iregNo(greg), iregNo(am->Xam.IR.reg));
1562//.. p = emit32(p, am->Xam.IR.imm);
1563//.. return p;
1564//.. }
1565//.. if (am->Xam.IR.reg == hregX86_ESP()
1566//.. && fits8bits(am->Xam.IR.imm)) {
cerionb85e8bb2005-02-16 08:54:33 +00001567//.. *p++ = mkModRegRM(1, iregNo(greg), 4);
cerionbcf8c3e2005-02-04 16:17:07 +00001568//.. *p++ = 0x24;
1569//.. *p++ = am->Xam.IR.imm & 0xFF;
1570//.. return p;
1571//.. }
1572//.. ppX86AMode(am);
1573//.. vpanic("doAMode_M: can't emit amode IR");
1574//.. /*NOTREACHED*/
1575//.. }
1576//.. if (am->tag == Xam_IRRS) {
1577//.. if (fits8bits(am->Xam.IRRS.imm)
1578//.. && am->Xam.IRRS.index != hregX86_ESP()) {
1579//.. *p++ = mkModRegRM(1, iregNo(greg), 4);
1580//.. *p++ = mkSIB(am->Xam.IRRS.shift, am->Xam.IRRS.index,
1581//.. am->Xam.IRRS.base);
1582//.. *p++ = am->Xam.IRRS.imm & 0xFF;
1583//.. return p;
1584//.. }
1585//.. if (am->Xam.IRRS.index != hregX86_ESP()) {
1586//.. *p++ = mkModRegRM(2, iregNo(greg), 4);
1587//.. *p++ = mkSIB(am->Xam.IRRS.shift, am->Xam.IRRS.index,
1588//.. am->Xam.IRRS.base);
1589//.. p = emit32(p, am->Xam.IRRS.imm);
1590//.. return p;
1591//.. }
1592//.. ppX86AMode(am);
1593//.. vpanic("doAMode_M: can't emit amode IRRS");
1594//.. /*NOTREACHED*/
1595//.. }
1596//.. vpanic("doAMode_M: unknown amode");
1597//.. /*NOTREACHED*/
1598//.. }
cerioncd304492005-02-08 19:40:24 +00001599
1600
cerionbcf8c3e2005-02-04 16:17:07 +00001601//.. /* Emit a mod-reg-rm byte when the rm bit denotes a reg. */
1602//.. static UChar* doAMode_R ( UChar* p, HReg greg, HReg ereg )
1603//.. {
1604//.. *p++ = mkModRegRM(3, iregNo(greg), iregNo(ereg));
1605//.. return p;
1606//.. }
cerioncd304492005-02-08 19:40:24 +00001607
1608
cerionbcf8c3e2005-02-04 16:17:07 +00001609//.. /* Emit ffree %st(7) */
1610//.. static UChar* do_ffree_st7 ( UChar* p )
1611//.. {
1612//.. *p++ = 0xDD;
1613//.. *p++ = 0xC7;
1614//.. return p;
1615//.. }
cerioncd304492005-02-08 19:40:24 +00001616
cerionbcf8c3e2005-02-04 16:17:07 +00001617//.. /* Emit fstp %st(i), 1 <= i <= 7 */
1618//.. static UChar* do_fstp_st ( UChar* p, Int i )
1619//.. {
1620//.. vassert(1 <= i && i <= 7);
1621//.. *p++ = 0xDD;
1622//.. *p++ = 0xD8+i;
1623//.. return p;
1624//.. }
cerioncd304492005-02-08 19:40:24 +00001625
cerionbcf8c3e2005-02-04 16:17:07 +00001626//.. /* Emit fld %st(i), 0 <= i <= 6 */
1627//.. static UChar* do_fld_st ( UChar* p, Int i )
1628//.. {
1629//.. vassert(0 <= i && i <= 6);
1630//.. *p++ = 0xD9;
1631//.. *p++ = 0xC0+i;
1632//.. return p;
1633//.. }
cerioncd304492005-02-08 19:40:24 +00001634
cerionbcf8c3e2005-02-04 16:17:07 +00001635//.. /* Emit f<op> %st(0) */
1636//.. static UChar* do_fop1_st ( UChar* p, X86FpOp op )
1637//.. {
1638//.. switch (op) {
1639//.. case Xfp_NEG: *p++ = 0xD9; *p++ = 0xE0; break;
1640//.. case Xfp_ABS: *p++ = 0xD9; *p++ = 0xE1; break;
1641//.. case Xfp_SQRT: *p++ = 0xD9; *p++ = 0xFA; break;
1642//.. case Xfp_ROUND: *p++ = 0xD9; *p++ = 0xFC; break;
1643//.. case Xfp_SIN: *p++ = 0xD9; *p++ = 0xFE; break;
1644//.. case Xfp_COS: *p++ = 0xD9; *p++ = 0xFF; break;
1645//.. case Xfp_2XM1: *p++ = 0xD9; *p++ = 0xF0; break;
1646//.. case Xfp_MOV: break;
1647//.. case Xfp_TAN: p = do_ffree_st7(p); /* since fptan pushes 1.0 */
1648//.. *p++ = 0xD9; *p++ = 0xF2; /* fptan */
1649//.. *p++ = 0xD9; *p++ = 0xF7; /* fincstp */
1650//.. break;
1651//.. default: vpanic("do_fop1_st: unknown op");
1652//.. }
1653//.. return p;
1654//.. }
cerioncd304492005-02-08 19:40:24 +00001655
cerionbcf8c3e2005-02-04 16:17:07 +00001656//.. /* Emit f<op> %st(i), 1 <= i <= 5 */
1657//.. static UChar* do_fop2_st ( UChar* p, X86FpOp op, Int i )
1658//.. {
1659//.. # define fake(_n) mkHReg((_n), HRcInt32, False)
1660//.. Int subopc;
1661//.. switch (op) {
1662//.. case Xfp_ADD: subopc = 0; break;
1663//.. case Xfp_SUB: subopc = 4; break;
1664//.. case Xfp_MUL: subopc = 1; break;
1665//.. case Xfp_DIV: subopc = 6; break;
1666//.. default: vpanic("do_fop2_st: unknown op");
1667//.. }
1668//.. *p++ = 0xD8;
1669//.. p = doAMode_R(p, fake(subopc), fake(i));
1670//.. return p;
1671//.. # undef fake
1672//.. }
cerioncd304492005-02-08 19:40:24 +00001673
cerionbcf8c3e2005-02-04 16:17:07 +00001674//.. /* Push a 32-bit word on the stack. The word depends on tags[3:0];
1675//.. each byte is either 0x00 or 0xFF depending on the corresponding bit in tags[].
1676//.. */
1677//.. static UChar* push_word_from_tags ( UChar* p, UShort tags )
1678//.. {
1679//.. UInt w;
1680//.. vassert(0 == (tags & ~0xF));
1681//.. if (tags == 0) {
1682//.. /* pushl $0x00000000 */
1683//.. *p++ = 0x6A;
1684//.. *p++ = 0x00;
1685//.. }
1686//.. else
1687//.. /* pushl $0xFFFFFFFF */
1688//.. if (tags == 0xF) {
1689//.. *p++ = 0x6A;
1690//.. *p++ = 0xFF;
1691//.. } else {
1692//.. vassert(0); /* awaiting test case */
1693//.. w = 0;
1694//.. if (tags & 1) w |= 0x000000FF;
1695//.. if (tags & 2) w |= 0x0000FF00;
1696//.. if (tags & 4) w |= 0x00FF0000;
1697//.. if (tags & 8) w |= 0xFF000000;
1698//.. *p++ = 0x68;
1699//.. p = emit32(p, w);
1700//.. }
1701//.. return p;
1702//.. }
1703
ceriond5e38382005-02-11 13:38:15 +00001704static UChar* mkFormD ( UChar* p, UInt op1, UInt r1, UInt r2, UInt imm )
1705{
1706 vassert(op1 < 0x40);
1707 vassert(r1 < 0x20);
1708 vassert(r2 < 0x20);
cerionab9132d2005-02-15 15:46:59 +00001709 vassert(imm < 0x10000 || imm >= 0xFFFF0000); // Pos|Neg
ceriond5e38382005-02-11 13:38:15 +00001710 UInt theInstr = ((op1<<26) | (r1<<21) | (r2<<16) | (imm));
1711 return emit32(p, theInstr);
1712}
1713
1714static UChar* mkFormX ( UChar* p, UInt op1, UInt r1, UInt r2,
cerionb85e8bb2005-02-16 08:54:33 +00001715 UInt r3, UInt op2, UInt b0 )
ceriond5e38382005-02-11 13:38:15 +00001716{
1717 vassert(op1 < 0x40);
1718 vassert(r1 < 0x20);
1719 vassert(r2 < 0x20);
1720 vassert(r3 < 0x20);
1721 vassert(op2 < 0x400);
1722 vassert(b0 < 0x2);
1723 UInt theInstr = ((op1<<26) | (r1<<21) | (r2<<16) |
cerionb85e8bb2005-02-16 08:54:33 +00001724 (r3<<11) | (op2<<1) | (b0));
ceriond5e38382005-02-11 13:38:15 +00001725 return emit32(p, theInstr);
1726}
1727
cerionab9132d2005-02-15 15:46:59 +00001728static UChar* mkFormXO ( UChar* p, UInt op1, UInt r1, UInt r2,
cerionb85e8bb2005-02-16 08:54:33 +00001729 UInt r3, UInt b10, UInt op2, UInt b0 )
cerionab9132d2005-02-15 15:46:59 +00001730{
1731 vassert(op1 < 0x40);
1732 vassert(r1 < 0x20);
1733 vassert(r2 < 0x20);
1734 vassert(r3 < 0x20);
1735 vassert(b10 < 0x2);
cerion33aa6da2005-02-16 10:25:26 +00001736 vassert(op2 < 0x200);
cerionab9132d2005-02-15 15:46:59 +00001737 vassert(b0 < 0x2);
1738 UInt theInstr = ((op1<<26) | (r1<<21) | (r2<<16) |
cerionb85e8bb2005-02-16 08:54:33 +00001739 (r3<<11) | (b10 << 10) | (op2<<1) | (b0));
cerionab9132d2005-02-15 15:46:59 +00001740 return emit32(p, theInstr);
1741}
ceriond5e38382005-02-11 13:38:15 +00001742
cerion33aa6da2005-02-16 10:25:26 +00001743static UChar* mkFormXL ( UChar* p, UInt op1, UInt f1, UInt f2,
1744 UInt f3, UInt op2, UInt b0 )
1745{
1746 vassert(op1 < 0x40);
1747 vassert(f1 < 0x20);
1748 vassert(f2 < 0x20);
1749 vassert(f3 < 0x20);
1750 vassert(op2 < 0x400);
1751 vassert(b0 < 0x2);
1752 UInt theInstr = ((op1<<26) | (f1<<21) | (f2<<16) |
1753 (f3<<11) | (op2<<1) | (b0));
1754 return emit32(p, theInstr);
1755}
1756
1757// Note: for split field ops, give mnemonic arg
1758static UChar* mkFormXFX ( UChar* p, UInt r1, UInt f2, UInt op2 )
1759{
1760 vassert(r1 < 0x20);
1761 vassert(f2 < 0x20);
1762 vassert(op2 < 0x400);
1763 switch (op2) {
1764 case 144: // mtcrf
1765 vassert(f2 < 0x100);
1766 f2 = f2 << 1;
1767 break;
1768 case 339: // mfspr
1769 case 371: // mftb
1770 case 467: // mtspr
1771 vassert(f2 < 0x400);
1772 f2 = ((f2>>5) & 0x1F) | ((f2 & 0x1F)<<5); // re-arrange split field
1773 break;
1774 default: vpanic("mkFormXFX(PPC32)");
1775 }
1776 UInt theInstr = ((31<<26) | (r1<<21) | (f2<<11) | (op2<<1));
1777 return emit32(p, theInstr);
1778}
1779
1780#if 0
1781// 'b'
1782static UChar* mkFormI ( UChar* p, UInt LI, UInt AA, UInt LK )
1783{
1784 vassert(LI < 0x1000000);
1785 vassert(AA < 0x2);
1786 vassert(LK < 0x2);
1787 UInt theInstr = ((18<<26) | (LI<<2) | (AA<<1) | (LK));
1788 return emit32(p, theInstr);
1789}
1790#endif
1791
1792// 'bc'
1793static UChar* mkFormB ( UChar* p, UInt BO, UInt BI,
1794 UInt BD, UInt AA, UInt LK )
1795{
1796 vassert(BO < 0x20);
1797 vassert(BI < 0x20);
1798 vassert(BD < 0x4000);
1799 vassert(AA < 0x2);
1800 vassert(LK < 0x2);
1801 UInt theInstr = ((16<<26) | (BO<<21) | (BI<<16) |
1802 (BD<<2) | (AA<<1) | (LK));
1803 return emit32(p, theInstr);
1804}
1805
cerion33aa6da2005-02-16 10:25:26 +00001806// rotates
1807static UChar* mkFormM ( UChar* p, UInt op1, UInt r1, UInt r2,
1808 UInt f3, UInt MB, UInt ME, UInt Rc )
1809{
1810 vassert(op1 < 0x40);
1811 vassert(r1 < 0x20);
1812 vassert(r2 < 0x20);
1813 vassert(f3 < 0x20);
1814 vassert(MB < 0x20);
1815 vassert(ME < 0x20);
1816 vassert(Rc < 0x2);
1817 UInt theInstr = ((op1<<26) | (r1<<21) | (r2<<16) |
1818 (f3<<11) | (MB<<6) | (ME<<1) | (Rc));
1819 return emit32(p, theInstr);
1820}
cerion33aa6da2005-02-16 10:25:26 +00001821
ceriond5e38382005-02-11 13:38:15 +00001822static UChar* doAMode_IR ( UChar* p, UInt op1, HReg hrSD, PPC32AMode* am )
1823{
1824 vassert(am->tag == Pam_IR);
1825 UInt rSD = iregNo(hrSD);
1826 UInt rA = iregNo(am->Pam.IR.base);
1827 UInt idx = am->Pam.IR.index;
1828 vassert(idx < 0x10000);
1829
1830 p = mkFormD(p, op1, rSD, rA, idx);
1831 return p;
1832}
1833
1834
1835static UChar* doAMode_RR ( UChar* p, UInt op1, UInt op2,
cerionb85e8bb2005-02-16 08:54:33 +00001836 HReg hrSD, PPC32AMode* am )
ceriond5e38382005-02-11 13:38:15 +00001837{
cerionb85e8bb2005-02-16 08:54:33 +00001838// vassert(hregClass(hrSD) == HRcInt32); // CAB: etc. worth doing this?
ceriond5e38382005-02-11 13:38:15 +00001839 vassert(am->tag == Pam_RR);
1840 UInt rSD = iregNo(hrSD);
1841 UInt rA = iregNo(am->Pam.RR.base);
1842 UInt rB = iregNo(am->Pam.RR.index);
1843
1844 p = mkFormX(p, op1, rSD, rA, rB, op2, 0);
1845 return p;
1846}
1847
cerione97e1062005-02-21 15:09:19 +00001848/* Load imm to r_dst */
1849static UChar* mkLoadImm ( UChar* p, UInt r_dst, UInt imm )
1850{
1851 vassert(r_dst < 0x20);
1852
1853 if (imm < 0x10000) {
1854 // CAB: Sign extends immediate...
1855 // addi r_dst,0,imm => li r_dst,imm
1856 p = mkFormD(p, 14, r_dst, 0, imm);
1857 } else {
1858 // addis r_dst,r0,(imm>>16) => lis r_dst, (imm>>16)
1859 p = mkFormD(p, 15, r_dst, 0, (imm>>16));
1860 // ori r_dst, r_dst, (imm & 0xFFFF)
1861 p = mkFormD(p, 24, r_dst, r_dst, (imm & 0xFFFF));
1862 }
1863 return p;
1864}
1865
1866
1867/* Move r_dst to r_src */
1868static UChar* mkMoveReg ( UChar* p, UInt r_dst, UInt r_src )
1869{
1870 vassert(r_dst < 0x20);
1871 vassert(r_src < 0x20);
1872
1873 if (r_dst != r_src) {
1874 /* or r_dst, r_src, r_src */
1875 p = mkFormX(p, 31, r_src, r_dst, r_src, 444, 0 );
1876 }
1877 return p;
1878}
1879
ceriond5e38382005-02-11 13:38:15 +00001880
cerionbcf8c3e2005-02-04 16:17:07 +00001881/* Emit an instruction into buf and return the number of bytes used.
1882 Note that buf is not the insn's final place, and therefore it is
1883 imperative to emit position-independent code. */
1884
1885Int emit_PPC32Instr ( UChar* buf, Int nbuf, PPC32Instr* i )
1886{
1887//.. UInt irno, opc, opc_rr, subopc_imm, opc_imma, opc_cl, opc_imm, subopc;
1888//..
1889//.. UInt xtra;
1890 UChar* p = &buf[0];
cerion7cf8e4e2005-02-16 16:08:17 +00001891 UChar* ptmp = p;
1892 vassert(nbuf >= 32);
cerionbcf8c3e2005-02-04 16:17:07 +00001893//..
1894//.. /* Wrap an integer as a int register, for use assembling
1895//.. GrpN insns, in which the greg field is used as a sub-opcode
1896//.. and does not really contain a register. */
1897//.. # define fake(_n) mkHReg((_n), HRcInt32, False)
cerion2c49e032005-02-09 17:29:49 +00001898
1899 vex_printf("asm ");ppPPC32Instr(i); vex_printf("\n");
cerionbcf8c3e2005-02-04 16:17:07 +00001900
1901 switch (i->tag) {
1902
cerionab9132d2005-02-15 15:46:59 +00001903 case Pin_Alu32: {
1904 UInt op1 = 31, op2, rB, imm;
1905 UInt r_dst = iregNo(i->Pin.Alu32.dst);
1906 UInt r_src1 = iregNo(i->Pin.Alu32.src1);
cerion2c49e032005-02-09 17:29:49 +00001907
cerionab9132d2005-02-15 15:46:59 +00001908 /* ADD/SUB/ADC/SBB/AND/OR/XOR */
1909 if (i->Pin.Alu32.src2->tag == Pri_Reg) {
1910 op1 = 31;
1911 rB = iregNo(i->Pin.Alu32.src2->Pri.Reg.reg);
1912 switch (i->Pin.Alu32.op) {
1913 case Palu_ADD: op2 = 266; break;
1914 case Palu_SUB: op2 = 266; break;
1915 case Palu_AND: op2 = 28; break;
1916 case Palu_XOR: op2 = 316; break;
1917 case Palu_OR: op2 = 444; break;
1918// case Palu_ADC:
1919// case Palu_SBB:
1920 default:
1921 goto bad;
1922 }
1923
1924 switch (i->Pin.Alu32.op) {
cerionb85e8bb2005-02-16 08:54:33 +00001925 case Palu_ADD: case Palu_SUB:
cerionab9132d2005-02-15 15:46:59 +00001926 p = mkFormXO(p, op1, r_dst, r_src1, rB, 0, op2, 0); // rD = rA...
1927 break;
cerionb85e8bb2005-02-16 08:54:33 +00001928 case Palu_AND: case Palu_XOR: case Palu_OR:
cerionab9132d2005-02-15 15:46:59 +00001929 p = mkFormX(p, op1, r_src1, r_dst, rB, op2, 0); // rA = rS...
1930 break;
1931// case Palu_ADC:
1932// case Palu_SBB:
1933 default:
1934 goto bad;
1935 }
cerionb85e8bb2005-02-16 08:54:33 +00001936 } else { // Pri_Imm:
cerionab9132d2005-02-15 15:46:59 +00001937 imm = i->Pin.Alu32.src2->Pri.Imm.imm32;
1938 switch (i->Pin.Alu32.op) {
1939 case Palu_ADD: op1 = 14; break;
1940 case Palu_SUB: op1 = 8; break;
1941 case Palu_AND: op1 = 28; break;
1942 case Palu_XOR: op1 = 26; break;
1943 case Palu_OR: op1 = 24; break;
1944// case Palu_ADC:
1945// case Palu_SBB:
1946 default:
1947 goto bad;
1948 }
1949
1950 switch (i->Pin.Alu32.op) {
cerionb85e8bb2005-02-16 08:54:33 +00001951 case Palu_ADD: case Palu_SUB:
cerionab9132d2005-02-15 15:46:59 +00001952 p = mkFormD(p, op1, r_dst, r_src1, imm); // rD = rA...
1953 break;
cerionb85e8bb2005-02-16 08:54:33 +00001954 case Palu_AND: case Palu_XOR: case Palu_OR:
cerionab9132d2005-02-15 15:46:59 +00001955 p = mkFormD(p, op1, r_src1, r_dst, imm); // rA = rS...
1956 break;
1957// case Palu_ADC:
1958// case Palu_SBB:
1959 default:
1960 goto bad;
1961 }
cerionab9132d2005-02-15 15:46:59 +00001962 }
cerionb85e8bb2005-02-16 08:54:33 +00001963 goto done;
cerionab9132d2005-02-15 15:46:59 +00001964 }
1965
1966 case Pin_Sh32: {
cerion33aa6da2005-02-16 10:25:26 +00001967 UInt opc1 = 31, opc2, rB, sh;
cerionb85e8bb2005-02-16 08:54:33 +00001968 UInt op = i->Pin.Sh32.op;
cerion33aa6da2005-02-16 10:25:26 +00001969 UInt rS = iregNo(i->Pin.Sh32.dst);
1970 UInt rA = iregNo(i->Pin.Sh32.src);
1971 PPC32RITag ri_tag = i->Pin.Sh32.shft->tag;
cerionab9132d2005-02-15 15:46:59 +00001972
cerionb85e8bb2005-02-16 08:54:33 +00001973 if ((op == Psh_SHL || op == Psh_SHR) && ri_tag == Pri_Imm)
1974 goto bad; // No imm versions of these
1975
1976 switch (op) {
cerion33aa6da2005-02-16 10:25:26 +00001977 case Psh_SHL: opc2 = 24; break;
1978 case Psh_SHR: opc2 = 536; break;
1979 case Psh_SAR: opc2 = (ri_tag == Pri_Reg) ? 792 : 824; break;
cerionab9132d2005-02-15 15:46:59 +00001980 default: goto bad;
1981 }
1982
cerionab9132d2005-02-15 15:46:59 +00001983 switch (i->Pin.Sh32.shft->tag) {
1984 case Pri_Reg:
cerion33aa6da2005-02-16 10:25:26 +00001985 rB = iregNo(i->Pin.Sh32.shft->Pri.Reg.reg);
1986 p = mkFormX(p, opc1, rS, rA, rB, opc2, 0);
cerionb85e8bb2005-02-16 08:54:33 +00001987 break;
cerionab9132d2005-02-15 15:46:59 +00001988 case Pri_Imm:
cerion33aa6da2005-02-16 10:25:26 +00001989 sh = i->Pin.Sh32.shft->Pri.Imm.imm32;
1990 p = mkFormX(p, opc1, rS, rA, sh, opc2, 0);
cerionb85e8bb2005-02-16 08:54:33 +00001991 break;
cerionab9132d2005-02-15 15:46:59 +00001992 default:
1993 goto bad;
1994 }
cerionb85e8bb2005-02-16 08:54:33 +00001995 goto done;
cerionab9132d2005-02-15 15:46:59 +00001996 }
cerion2c49e032005-02-09 17:29:49 +00001997
cerion98411db2005-02-16 14:14:49 +00001998 case Pin_Cmp32: {
1999 UInt opc1, opc2=0;
2000 UInt op = i->Pin.Cmp32.op;
cerione97e1062005-02-21 15:09:19 +00002001 UInt fld1 = (7 - i->Pin.Cmp32.crfD) << 2;
cerion98411db2005-02-16 14:14:49 +00002002 UInt r1 = iregNo(i->Pin.Cmp32.src1);
2003 UInt r2, imm;
cerionab9132d2005-02-15 15:46:59 +00002004
cerion98411db2005-02-16 14:14:49 +00002005 switch (i->Pin.Cmp32.src2->tag) {
2006 case Pri_Imm:
2007 opc1 = (op == Pcmp_U) ? 10 : 11;
2008 imm = i->Pin.Cmp32.src2->Pri.Imm.imm32;
2009 p = mkFormD(p, opc1, fld1, r1, imm);
2010 break;
2011 case Pri_Reg:
2012 opc1 = 31;
2013 opc2 = (op == Pcmp_U) ? 32 : 0;
2014 r2 = iregNo(i->Pin.Cmp32.src2->Pri.Reg.reg);
2015 p = mkFormX(p, opc1, fld1, r1, r2, opc2, 0);
2016 break;
2017 default: goto bad;
2018 }
2019 goto done;
2020 }
cerionb536af92005-02-10 15:03:19 +00002021
cerion98411db2005-02-16 14:14:49 +00002022 case Pin_Unary32: {
2023 UInt r_dst = iregNo(i->Pin.Unary32.dst);
2024 UInt r_src = iregNo(i->Pin.Unary32.src);
2025
2026 switch (i->Pin.Unary32.op) {
2027 case Pun_NOT: // nor r_dst,r_src,r_src
2028 p = mkFormX(p, 31, r_src, r_dst, r_src, 124, 0);
2029 break;
2030 case Pun_NEG: // neg r_dst,r_src
2031 p = mkFormXO(p, 31, r_dst, r_src, 0, 0, 104, 0);
2032 break;
2033 case Pun_CLZ: // cntlzw r_dst, r_src
2034 p = mkFormX(p, 31, r_dst, r_src, 0, 26, 0);
2035 break;
2036 default: goto bad;
2037 }
2038 goto done;
2039 }
2040
2041 case Pin_MulL: {
2042 Bool syned = i->Pin.MulL.syned;
2043 UInt r_dst = iregNo(i->Pin.MulL.dst);
2044 UInt r_src1 = iregNo(i->Pin.MulL.src1);
2045 UInt r_src2, imm;
2046
2047 switch (i->Pin.MulL.word) {
2048 case 0: // multiply low word
2049 switch (i->Pin.MulL.src2->tag) {
2050 case Pri_Reg:
2051 // mullw r_dst,r_src1,r_src2
2052 // sign makes no difference.
2053 r_src2 = iregNo(i->Pin.MulL.src2->Pri.Reg.reg);
2054 p = mkFormXO(p, 31, r_dst, r_src1, r_src2, 0, 235, 0);
2055 break;
2056 case Pri_Imm:
2057 // mulli r_dst,r_src,imm
2058 vassert(syned == True); // always signed
2059 imm = i->Pin.MulL.src2->Pri.Imm.imm32;
2060 p = mkFormD(p, 07, r_dst, r_src1, imm);
2061 break;
2062 default:
2063 goto bad;
2064 }
2065 break;
2066 case 1: // multiply high word
2067 vassert(i->Pin.MulL.src2->tag == Pri_Reg);
2068 r_src2 = iregNo(i->Pin.MulL.src2->Pri.Reg.reg);
2069 if (syned == True) {
2070 // mulhw r_dst,r_src1,r_src2
2071 p = mkFormXO(p, 31, r_dst, r_src1, r_src2, 0, 75, 0);
2072 } else {
2073 // mulhwu r_dst,r_src1,r_src2
2074 p = mkFormXO(p, 31, r_dst, r_src1, r_src2, 0, 11, 0);
2075 }
2076 break;
2077 default:
2078 goto bad;
2079 }
2080 goto done;
2081 }
cerion2c49e032005-02-09 17:29:49 +00002082
cerionfd0b87f2005-02-16 14:43:14 +00002083 case Pin_Div: {
2084 Bool syned = i->Pin.MulL.syned;
2085 UInt r_dst = iregNo(i->Pin.Div.dst);
2086 UInt r_src1 = iregNo(i->Pin.Div.src1);
2087 UInt r_src2 = iregNo(i->Pin.Div.src2);
2088
2089 if (syned == True) {
2090 // divw r_dst,r_src1,r_src2
2091 p = mkFormXO(p, 31, r_dst, r_src1, r_src2, 0, 491, 0);
2092 } else {
2093 // divwu r_dst,r_src1,r_src2
2094 p = mkFormXO(p, 31, r_dst, r_src1, r_src2, 0, 459, 0);
2095 }
2096 goto done;
2097 }
cerion2c49e032005-02-09 17:29:49 +00002098
cerionbcf8c3e2005-02-04 16:17:07 +00002099//.. case Xin_Sh3232:
2100//.. vassert(i->Xin.Sh3232.op == Xsh_SHL || i->Xin.Sh3232.op == Xsh_SHR);
2101//.. if (i->Xin.Sh3232.amt == 0) {
2102//.. /* shldl/shrdl by %cl */
2103//.. *p++ = 0x0F;
2104//.. if (i->Xin.Sh3232.op == Xsh_SHL) {
2105//.. *p++ = 0xA5;
2106//.. } else {
2107//.. *p++ = 0xAD;
2108//.. }
2109//.. p = doAMode_R(p, i->Xin.Sh3232.src, i->Xin.Sh3232.dst);
2110//.. goto done;
2111//.. }
2112//.. break;
cerion2c49e032005-02-09 17:29:49 +00002113
cerionbcf8c3e2005-02-04 16:17:07 +00002114//.. case Xin_Push:
2115//.. switch (i->Xin.Push.src->tag) {
2116//.. case Xrmi_Mem:
2117//.. *p++ = 0xFF;
2118//.. p = doAMode_M(p, fake(6), i->Xin.Push.src->Xrmi.Mem.am);
2119//.. goto done;
2120//.. case Xrmi_Imm:
2121//.. *p++ = 0x68;
2122//.. p = emit32(p, i->Xin.Push.src->Xrmi.Imm.imm32);
2123//.. goto done;
2124//.. case Xrmi_Reg:
2125//.. *p++ = 0x50 + iregNo(i->Xin.Push.src->Xrmi.Reg.reg);
2126//.. goto done;
2127//.. default:
2128//.. goto bad;
2129//.. }
cerion2c49e032005-02-09 17:29:49 +00002130
cerion33aa6da2005-02-16 10:25:26 +00002131 case Pin_Call: {
cerion7cf8e4e2005-02-16 16:08:17 +00002132 PPC32CondCode cond = i->Pin.Call.cond;
ceriona56e9cc2005-02-16 18:08:25 +00002133 UInt r_dst = 12;
2134 /* As per detailed comment for Pin_Call in
cerionab9132d2005-02-15 15:46:59 +00002135 getRegUsage_PPC32Instr above, %r12 is used as an address
2136 temporary. */
ceriona56e9cc2005-02-16 18:08:25 +00002137
cerionab9132d2005-02-15 15:46:59 +00002138 /* jump over the following two insns if the condition does not
2139 hold */
cerione97e1062005-02-21 15:09:19 +00002140 if (cond.test != Pct_ALWAYS) {
2141 /* don't know how many bytes to jump over yet...
2142 make space for a jump instruction and fill in later. */
2143 ptmp = p; /* fill in this bit later */
2144 p += 4;
cerionab9132d2005-02-15 15:46:59 +00002145 }
2146
cerione97e1062005-02-21 15:09:19 +00002147 /* load target to r_dst */
2148 p = mkLoadImm(p, r_dst, i->Pin.Call.target);
cerionab9132d2005-02-15 15:46:59 +00002149
ceriona56e9cc2005-02-16 18:08:25 +00002150 /* mtspr 9,r_dst => move r_dst to count register */
2151 p = mkFormXFX(p, r_dst, 9, 467);
cerion33aa6da2005-02-16 10:25:26 +00002152
2153 /* bcctrl 20,0 => branch w. link to count register */
2154 p = mkFormXL(p, 19, Pct_ALWAYS, 0, 0, 528, 1);
cerionab9132d2005-02-15 15:46:59 +00002155
cerione97e1062005-02-21 15:09:19 +00002156 /* Fix up the conditional jump, if there was one. */
2157 if (cond.test != Pct_ALWAYS) {
2158 Int delta = p - ptmp;
2159 vassert(delta >= 8 && delta <= 16);
2160
2161 /* bca !ct,cf,jump */
2162 mkFormB(ptmp, invertCondTest(cond.test), cond.flag, (delta>>2), 1, 0);
2163 }
2164
cerion33aa6da2005-02-16 10:25:26 +00002165/* CAB: Hmm...
2166 "When possible, independent instructions should separate the load
2167 of the Count Register from the branch to prevent pipeline stalls." */
cerion2c49e032005-02-09 17:29:49 +00002168
cerion33aa6da2005-02-16 10:25:26 +00002169 goto done;
2170 }
2171
2172 case Pin_Goto: {
2173 UInt magic_num = 0;
cerione97e1062005-02-21 15:09:19 +00002174 UChar r_return = 3; /* Put target addr into %r3 */
cerion33aa6da2005-02-16 10:25:26 +00002175 PPC32CondCode cond = i->Pin.Goto.cond;
2176 UInt imm;
2177
2178 /* First off, if this is conditional, create a conditional
2179 jump over the rest of it. */
2180 if (cond.test != Pct_ALWAYS) {
2181 /* jmp fwds if !condition */
cerione97e1062005-02-21 15:09:19 +00002182 /* don't know how many bytes to jump over yet...
2183 make space for a jump instruction and fill in later. */
cerion7cf8e4e2005-02-16 16:08:17 +00002184 ptmp = p; /* fill in this bit later */
cerione97e1062005-02-21 15:09:19 +00002185 p += 4;
cerion33aa6da2005-02-16 10:25:26 +00002186 }
2187
cerione97e1062005-02-21 15:09:19 +00002188 // cond succeeds...
2189
cerion33aa6da2005-02-16 10:25:26 +00002190 /* If a non-boring, set GuestStatePtr appropriately. */
cerion33aa6da2005-02-16 10:25:26 +00002191 switch (i->Pin.Goto.jk) {
2192 case Ijk_ClientReq: magic_num = VEX_TRC_JMP_CLIENTREQ; break;
2193 case Ijk_Syscall: magic_num = VEX_TRC_JMP_SYSCALL; break;
2194 case Ijk_Yield: magic_num = VEX_TRC_JMP_YIELD; break;
2195 case Ijk_EmWarn: magic_num = VEX_TRC_JMP_EMWARN; break;
2196 case Ijk_MapFail: magic_num = VEX_TRC_JMP_MAPFAIL; break;
2197 case Ijk_NoDecode: magic_num = VEX_TRC_JMP_NODECODE; break;
2198 case Ijk_Ret:
2199 case Ijk_Call:
2200 case Ijk_Boring:
2201 break;
2202 default:
2203 ppIRJumpKind(i->Pin.Goto.jk);
2204 vpanic("emit_PPC32Instr.Pin_Goto: unknown jump kind");
2205 }
2206 if (magic_num !=0) {
2207 vassert(magic_num < 0x10000);
cerione97e1062005-02-21 15:09:19 +00002208 /* addi r31,0,magic_num */
cerion33aa6da2005-02-16 10:25:26 +00002209 p = mkFormD(p, 14, 31, 0, magic_num);
2210 }
2211
cerione97e1062005-02-21 15:09:19 +00002212 /* Get the destination address into %r_return */
cerion33aa6da2005-02-16 10:25:26 +00002213 if (i->Pin.Goto.dst->tag == Pri_Imm) {
cerion33aa6da2005-02-16 10:25:26 +00002214 imm = i->Pin.Goto.dst->Pri.Imm.imm32;
cerione97e1062005-02-21 15:09:19 +00002215 p = mkLoadImm(p, r_return, imm);
cerion33aa6da2005-02-16 10:25:26 +00002216 } else {
2217 vassert(i->Pin.Goto.dst->tag == Pri_Reg);
cerione97e1062005-02-21 15:09:19 +00002218 UInt r_dst = iregNo(i->Pin.Goto.dst->Pri.Reg.reg);
2219 p = mkMoveReg(p, r_return, r_dst);
cerion33aa6da2005-02-16 10:25:26 +00002220 }
cerione97e1062005-02-21 15:09:19 +00002221
2222 /* blr */
cerion33aa6da2005-02-16 10:25:26 +00002223 p = mkFormXL(p, 19, Pct_ALWAYS, 0, 0, 16, 0);
cerion7cf8e4e2005-02-16 16:08:17 +00002224
2225 /* Fix up the conditional jump, if there was one. */
2226 if (cond.test != Pct_ALWAYS) {
2227 Int delta = p - ptmp;
cerione97e1062005-02-21 15:09:19 +00002228 vassert(delta >= 8 && delta <= 16);
2229 /* bc !ct,cf,delta */
2230 mkFormB(ptmp, invertCondTest(cond.test), cond.flag, (delta>>2), 0, 0);
cerion7cf8e4e2005-02-16 16:08:17 +00002231 }
cerion33aa6da2005-02-16 10:25:26 +00002232 goto done;
2233 }
cerionb536af92005-02-10 15:03:19 +00002234
cerion98411db2005-02-16 14:14:49 +00002235 case Pin_CMov32: {
2236 vassert(i->Pin.CMov32.cond.test != Pct_ALWAYS);
2237 UInt r_dst = iregNo(i->Pin.CMov32.dst);
2238 PPC32CondCode cond = i->Pin.CMov32.cond;
2239 UInt imm, r_src;
2240
cerione97e1062005-02-21 15:09:19 +00002241 /* branch (if cond fails) over move instrs */
2242 if (cond.test != Pct_ALWAYS) {
2243 /* don't know how many bytes to jump over yet...
2244 make space for a jump instruction and fill in later. */
2245 ptmp = p; /* fill in this bit later */
2246 p += 4;
2247 }
cerion98411db2005-02-16 14:14:49 +00002248
2249 // cond true: move src => dst
2250 switch (i->Pin.CMov32.src->tag) {
2251 case Pri_Imm:
2252 imm = i->Pin.CMov32.src->Pri.Imm.imm32;
cerione97e1062005-02-21 15:09:19 +00002253 p = mkLoadImm(p, r_dst, imm);
cerion98411db2005-02-16 14:14:49 +00002254 break;
2255 case Pri_Reg:
2256 r_src = iregNo(i->Pin.CMov32.src->Pri.Reg.reg);
cerione97e1062005-02-21 15:09:19 +00002257 p = mkMoveReg(p, r_dst, r_src);
cerion98411db2005-02-16 14:14:49 +00002258 break;
2259 default: goto bad;
2260 }
cerione97e1062005-02-21 15:09:19 +00002261
2262 /* Fix up the conditional jump, if there was one. */
2263 if (cond.test != Pct_ALWAYS) {
2264 Int delta = p - ptmp;
2265 vassert(delta >= 4 && delta <= 12);
2266 /* bc !ct,cf,delta */
2267 mkFormB(ptmp, invertCondTest(cond.test), cond.flag, (delta>>2), 0, 0);
2268 }
cerion98411db2005-02-16 14:14:49 +00002269 goto done;
2270 }
cerionb536af92005-02-10 15:03:19 +00002271
cerion7cf8e4e2005-02-16 16:08:17 +00002272 case Pin_Load: {
2273 Bool syned = i->Pin.Load.syned;
2274 UInt op1, op2, sz = i->Pin.Load.sz;
2275 switch (i->Pin.Load.src->tag) {
ceriond5e38382005-02-11 13:38:15 +00002276 case Pam_IR:
cerionab9132d2005-02-15 15:46:59 +00002277 if (sz == 2) { // the only signed load
cerion7cf8e4e2005-02-16 16:08:17 +00002278 op1 = (syned) ? 42: 40;
cerionab9132d2005-02-15 15:46:59 +00002279 } else {
cerion7cf8e4e2005-02-16 16:08:17 +00002280 vassert(syned == False);
cerionb85e8bb2005-02-16 08:54:33 +00002281 op1 = (sz == 1) ? 34 : 32; // 1:4
cerionab9132d2005-02-15 15:46:59 +00002282 }
cerion7cf8e4e2005-02-16 16:08:17 +00002283 p = doAMode_IR(p, op1, i->Pin.Load.dst, i->Pin.Load.src);
cerionab9132d2005-02-15 15:46:59 +00002284 goto done;
ceriond5e38382005-02-11 13:38:15 +00002285 case Pam_RR:
cerionab9132d2005-02-15 15:46:59 +00002286 op1 = 31;
2287 if (sz == 2) { // the only signed load
cerion7cf8e4e2005-02-16 16:08:17 +00002288 op2 = (syned) ? 343: 279;
cerionab9132d2005-02-15 15:46:59 +00002289 } else {
cerion7cf8e4e2005-02-16 16:08:17 +00002290 vassert(syned == False);
cerionb85e8bb2005-02-16 08:54:33 +00002291 op2 = (sz == 1) ? 87 : 23; // 1:4
cerionab9132d2005-02-15 15:46:59 +00002292 }
cerion7cf8e4e2005-02-16 16:08:17 +00002293 p = doAMode_RR(p, op1, op2, i->Pin.Load.dst, i->Pin.Load.src);
cerionab9132d2005-02-15 15:46:59 +00002294 goto done;
ceriond5e38382005-02-11 13:38:15 +00002295 default:
cerionab9132d2005-02-15 15:46:59 +00002296 goto bad;
ceriond5e38382005-02-11 13:38:15 +00002297 }
2298 }
cerionb536af92005-02-10 15:03:19 +00002299
cerionab9132d2005-02-15 15:46:59 +00002300 case Pin_Set32: {
2301 /* Make the destination register be 1 or 0, depending on whether
cerion98411db2005-02-16 14:14:49 +00002302 the relevant condition holds. Yay! - mfcr doesn't change CR. */
2303 UInt r_dst = iregNo(i->Pin.Set32.dst);
2304 PPC32CondCode cond = i->Pin.Set32.cond;
cerion7cf8e4e2005-02-16 16:08:17 +00002305 UInt rot_imm;
cerion98411db2005-02-16 14:14:49 +00002306 UInt r_tmp;
2307
2308 if (cond.test == Pct_ALWAYS) {
2309 // just load 1 to dst => li dst,1
2310 p = mkFormD(p, 14, r_dst, 0, 1);
cerionab9132d2005-02-15 15:46:59 +00002311 } else {
cerion7cf8e4e2005-02-16 16:08:17 +00002312 rot_imm = 1 + cond.flag;
ceriona56e9cc2005-02-16 18:08:25 +00002313 r_tmp = 0; // Not within scope of regalloc, so no need to declare.
cerion98411db2005-02-16 14:14:49 +00002314
2315 // r_tmp = CR => mfcr r_tmp
2316 p = mkFormX(p, 31, r_tmp, 0, 0, 19, 0);
2317
2318 // r_dst = flag (rotate left and mask)
cerion7cf8e4e2005-02-16 16:08:17 +00002319 // => rlwinm r_dst,r_tmp,rot_imm,31,31
cerione97e1062005-02-21 15:09:19 +00002320 p = mkFormM(p, 21, r_tmp, r_dst, rot_imm, 31, 31, 0);
cerion98411db2005-02-16 14:14:49 +00002321
2322 if (cond.test == Pct_FALSE) {
2323 // flip bit => xori rD,rD,1
2324 p = mkFormD(p, 26, r_dst, r_dst, 1);
cerionab9132d2005-02-15 15:46:59 +00002325 }
2326 }
2327 goto done;
cerionab9132d2005-02-15 15:46:59 +00002328 }
cerionb536af92005-02-10 15:03:19 +00002329
cerionbcf8c3e2005-02-04 16:17:07 +00002330//.. case Xin_Bsfr32:
2331//.. *p++ = 0x0F;
2332//.. if (i->Xin.Bsfr32.isFwds) {
2333//.. *p++ = 0xBC;
2334//.. } else {
2335//.. *p++ = 0xBD;
2336//.. }
2337//.. p = doAMode_R(p, i->Xin.Bsfr32.dst, i->Xin.Bsfr32.src);
2338//.. goto done;
cerionb536af92005-02-10 15:03:19 +00002339
cerion98411db2005-02-16 14:14:49 +00002340 case Pin_MFence: {
2341// CAB: choose...
2342#if 1 // sync (Synchronise, p616)
2343 p = mkFormX(p, 31, 0, 0, 0, 598, 0);
2344#else // isync (instruction synchronise, p467)
2345 p = mkFormXL(p, 19, 0, 0, 0, 150, 0);
2346#endif
2347 goto done;
2348 }
cerionb536af92005-02-10 15:03:19 +00002349
ceriond5e38382005-02-11 13:38:15 +00002350 case Pin_Store: {
2351 UInt op1, op2, sz = i->Pin.Store.sz;
2352 switch (i->Pin.Store.dst->tag) {
2353 case Pam_IR:
cerionb85e8bb2005-02-16 08:54:33 +00002354 op1 = (sz == 1) ? 38 : ((sz == 2) ? 44 : 36); // 1:2:4
cerionab9132d2005-02-15 15:46:59 +00002355 p = doAMode_IR(p, op1, i->Pin.Store.src, i->Pin.Store.dst);
2356 goto done;
ceriond5e38382005-02-11 13:38:15 +00002357 case Pam_RR:
cerionab9132d2005-02-15 15:46:59 +00002358 op1 = 31;
cerionb85e8bb2005-02-16 08:54:33 +00002359 op2 = (sz == 1) ? 215 : ((sz == 2) ? 407 : 151); // 1:2:4
cerionab9132d2005-02-15 15:46:59 +00002360 p = doAMode_RR(p, op1, op2, i->Pin.Store.src, i->Pin.Store.dst);
2361 goto done;
ceriond5e38382005-02-11 13:38:15 +00002362 default:
cerionab9132d2005-02-15 15:46:59 +00002363 goto bad;
ceriond5e38382005-02-11 13:38:15 +00002364 }
2365 goto done;
2366 }
cerionb536af92005-02-10 15:03:19 +00002367
cerionbcf8c3e2005-02-04 16:17:07 +00002368//.. case Xin_FpUnary:
2369//.. /* gop %src, %dst
2370//.. --> ffree %st7 ; fld %st(src) ; fop %st(0) ; fstp %st(1+dst)
2371//.. */
2372//.. p = do_ffree_st7(p);
2373//.. p = do_fld_st(p, 0+hregNumber(i->Xin.FpUnary.src));
2374//.. p = do_fop1_st(p, i->Xin.FpUnary.op);
2375//.. p = do_fstp_st(p, 1+hregNumber(i->Xin.FpUnary.dst));
2376//.. goto done;
2377//..
2378//.. case Xin_FpBinary:
2379//.. if (i->Xin.FpBinary.op == Xfp_YL2X
2380//.. || i->Xin.FpBinary.op == Xfp_YL2XP1) {
2381//.. /* Have to do this specially. */
2382//.. /* ffree %st7 ; fld %st(srcL) ;
2383//.. ffree %st7 ; fld %st(srcR+1) ; fyl2x{p1} ; fstp(1+dst) */
2384//.. p = do_ffree_st7(p);
2385//.. p = do_fld_st(p, 0+hregNumber(i->Xin.FpBinary.srcL));
2386//.. p = do_ffree_st7(p);
2387//.. p = do_fld_st(p, 1+hregNumber(i->Xin.FpBinary.srcR));
2388//.. *p++ = 0xD9;
2389//.. *p++ = i->Xin.FpBinary.op==Xfp_YL2X ? 0xF1 : 0xF9;
2390//.. p = do_fstp_st(p, 1+hregNumber(i->Xin.FpBinary.dst));
2391//.. goto done;
2392//.. }
2393//.. if (i->Xin.FpBinary.op == Xfp_ATAN) {
2394//.. /* Have to do this specially. */
2395//.. /* ffree %st7 ; fld %st(srcL) ;
2396//.. ffree %st7 ; fld %st(srcR+1) ; fpatan ; fstp(1+dst) */
2397//.. p = do_ffree_st7(p);
2398//.. p = do_fld_st(p, 0+hregNumber(i->Xin.FpBinary.srcL));
2399//.. p = do_ffree_st7(p);
2400//.. p = do_fld_st(p, 1+hregNumber(i->Xin.FpBinary.srcR));
2401//.. *p++ = 0xD9; *p++ = 0xF3;
2402//.. p = do_fstp_st(p, 1+hregNumber(i->Xin.FpBinary.dst));
2403//.. goto done;
2404//.. }
2405//.. if (i->Xin.FpBinary.op == Xfp_PREM
2406//.. || i->Xin.FpBinary.op == Xfp_PREM1
2407//.. || i->Xin.FpBinary.op == Xfp_SCALE) {
2408//.. /* Have to do this specially. */
2409//.. /* ffree %st7 ; fld %st(srcR) ;
2410//.. ffree %st7 ; fld %st(srcL+1) ; fprem/fprem1/fscale ; fstp(2+dst) ;
2411//.. fincstp ; ffree %st7 */
2412//.. p = do_ffree_st7(p);
2413//.. p = do_fld_st(p, 0+hregNumber(i->Xin.FpBinary.srcR));
2414//.. p = do_ffree_st7(p);
2415//.. p = do_fld_st(p, 1+hregNumber(i->Xin.FpBinary.srcL));
2416//.. *p++ = 0xD9;
2417//.. switch (i->Xin.FpBinary.op) {
2418//.. case Xfp_PREM: *p++ = 0xF8; break;
2419//.. case Xfp_PREM1: *p++ = 0xF5; break;
2420//.. case Xfp_SCALE: *p++ = 0xFD; break;
2421//.. default: vpanic("emitX86Instr(FpBinary,PREM/PREM1/SCALE)");
2422//.. }
2423//.. p = do_fstp_st(p, 2+hregNumber(i->Xin.FpBinary.dst));
2424//.. *p++ = 0xD9; *p++ = 0xF7;
2425//.. p = do_ffree_st7(p);
2426//.. goto done;
2427//.. }
2428//.. /* General case */
2429//.. /* gop %srcL, %srcR, %dst
2430//.. --> ffree %st7 ; fld %st(srcL) ; fop %st(1+srcR) ; fstp %st(1+dst)
2431//.. */
2432//.. p = do_ffree_st7(p);
2433//.. p = do_fld_st(p, 0+hregNumber(i->Xin.FpBinary.srcL));
2434//.. p = do_fop2_st(p, i->Xin.FpBinary.op,
2435//.. 1+hregNumber(i->Xin.FpBinary.srcR));
2436//.. p = do_fstp_st(p, 1+hregNumber(i->Xin.FpBinary.dst));
2437//.. goto done;
2438//..
2439//.. case Xin_FpLdSt:
2440//.. vassert(i->Xin.FpLdSt.sz == 4 || i->Xin.FpLdSt.sz == 8);
2441//.. if (i->Xin.FpLdSt.isLoad) {
2442//.. /* Load from memory into %fakeN.
2443//.. --> ffree %st(7) ; fld{s/l} amode ; fstp st(N+1)
2444//.. */
2445//.. p = do_ffree_st7(p);
2446//.. *p++ = i->Xin.FpLdSt.sz==4 ? 0xD9 : 0xDD;
cerionb85e8bb2005-02-16 08:54:33 +00002447//.. p = doAMode_M(p, fake(0)/*subopcode*/, i->Xin.FpLdSt.addr);
cerionbcf8c3e2005-02-04 16:17:07 +00002448//.. p = do_fstp_st(p, 1+hregNumber(i->Xin.FpLdSt.reg));
2449//.. goto done;
2450//.. } else {
2451//.. /* Store from %fakeN into memory.
2452//.. --> ffree %st(7) ; fld st(N) ; fstp{l|s} amode
cerionb85e8bb2005-02-16 08:54:33 +00002453//.. */
cerionbcf8c3e2005-02-04 16:17:07 +00002454//.. p = do_ffree_st7(p);
2455//.. p = do_fld_st(p, 0+hregNumber(i->Xin.FpLdSt.reg));
2456//.. *p++ = i->Xin.FpLdSt.sz==4 ? 0xD9 : 0xDD;
2457//.. p = doAMode_M(p, fake(3)/*subopcode*/, i->Xin.FpLdSt.addr);
2458//.. goto done;
2459//.. }
2460//.. break;
2461//..
2462//.. case Xin_FpLdStI:
2463//.. if (i->Xin.FpLdStI.isLoad) {
2464//.. /* Load from memory into %fakeN, converting from an int.
2465//.. --> ffree %st(7) ; fild{w/l/ll} amode ; fstp st(N+1)
2466//.. */
2467//.. switch (i->Xin.FpLdStI.sz) {
2468//.. case 8: opc = 0xDF; subopc_imm = 5; break;
2469//.. case 4: opc = 0xDB; subopc_imm = 0; break;
2470//.. case 2: vassert(0); opc = 0xDF; subopc_imm = 0; break;
2471//.. default: vpanic("emitX86Instr(Xin_FpLdStI-load)");
2472//.. }
2473//.. p = do_ffree_st7(p);
2474//.. *p++ = opc;
2475//.. p = doAMode_M(p, fake(subopc_imm)/*subopcode*/, i->Xin.FpLdStI.addr);
2476//.. p = do_fstp_st(p, 1+hregNumber(i->Xin.FpLdStI.reg));
2477//.. goto done;
2478//.. } else {
2479//.. /* Store from %fakeN into memory, converting to an int.
2480//.. --> ffree %st(7) ; fld st(N) ; fistp{w/l/ll} amode
cerionb85e8bb2005-02-16 08:54:33 +00002481//.. */
cerionbcf8c3e2005-02-04 16:17:07 +00002482//.. switch (i->Xin.FpLdStI.sz) {
2483//.. case 8: opc = 0xDF; subopc_imm = 7; break;
2484//.. case 4: opc = 0xDB; subopc_imm = 3; break;
2485//.. case 2: opc = 0xDF; subopc_imm = 3; break;
2486//.. default: vpanic("emitX86Instr(Xin_FpLdStI-store)");
2487//.. }
2488//.. p = do_ffree_st7(p);
2489//.. p = do_fld_st(p, 0+hregNumber(i->Xin.FpLdStI.reg));
2490//.. *p++ = opc;
2491//.. p = doAMode_M(p, fake(subopc_imm)/*subopcode*/, i->Xin.FpLdStI.addr);
2492//.. goto done;
2493//.. }
2494//.. break;
2495//..
2496//.. case Xin_Fp64to32:
2497//.. /* ffree %st7 ; fld %st(src) */
2498//.. p = do_ffree_st7(p);
2499//.. p = do_fld_st(p, 0+fregNo(i->Xin.Fp64to32.src));
2500//.. /* subl $4, %esp */
2501//.. *p++ = 0x83; *p++ = 0xEC; *p++ = 0x04;
2502//.. /* fstps (%esp) */
2503//.. *p++ = 0xD9; *p++ = 0x1C; *p++ = 0x24;
2504//.. /* flds (%esp) */
2505//.. *p++ = 0xD9; *p++ = 0x04; *p++ = 0x24;
2506//.. /* addl $4, %esp */
2507//.. *p++ = 0x83; *p++ = 0xC4; *p++ = 0x04;
2508//.. /* fstp %st(1+dst) */
2509//.. p = do_fstp_st(p, 1+fregNo(i->Xin.Fp64to32.dst));
2510//.. goto done;
2511//..
2512//.. case Xin_FpCMov:
2513//.. /* jmp fwds if !condition */
2514//.. *p++ = 0x70 + (i->Xin.FpCMov.cond ^ 1);
2515//.. *p++ = 0; /* # of bytes in the next bit, which we don't know yet */
2516//.. ptmp = p;
2517//..
2518//.. /* ffree %st7 ; fld %st(src) ; fstp %st(1+dst) */
2519//.. p = do_ffree_st7(p);
2520//.. p = do_fld_st(p, 0+fregNo(i->Xin.FpCMov.src));
2521//.. p = do_fstp_st(p, 1+fregNo(i->Xin.FpCMov.dst));
2522//..
2523//.. /* Fill in the jump offset. */
2524//.. *(ptmp-1) = p - ptmp;
2525//.. goto done;
2526//..
2527//.. case Xin_FpLdStCW:
2528//.. if (i->Xin.FpLdStCW.isLoad) {
2529//.. *p++ = 0xD9;
2530//.. p = doAMode_M(p, fake(5)/*subopcode*/, i->Xin.FpLdStCW.addr);
2531//.. } else {
2532//.. vassert(0);
2533//.. }
2534//.. goto done;
2535//..
2536//.. case Xin_FpStSW_AX:
2537//.. /* note, this emits fnstsw %ax, not fstsw %ax */
2538//.. *p++ = 0xDF;
2539//.. *p++ = 0xE0;
2540//.. goto done;
2541//..
2542//.. case Xin_FpCmp:
2543//.. /* gcmp %fL, %fR, %dst
2544//.. -> ffree %st7; fpush %fL ; fucomp %(fR+1) ;
2545//.. fnstsw %ax ; movl %eax, %dst
2546//.. */
2547//.. /* ffree %st7 */
2548//.. p = do_ffree_st7(p);
2549//.. /* fpush %fL */
2550//.. p = do_fld_st(p, 0+fregNo(i->Xin.FpCmp.srcL));
2551//.. /* fucomp %(fR+1) */
2552//.. *p++ = 0xDD;
2553//.. *p++ = 0xE8 + (7 & (1+fregNo(i->Xin.FpCmp.srcR)));
2554//.. /* fnstsw %ax */
2555//.. *p++ = 0xDF;
2556//.. *p++ = 0xE0;
2557//.. /* movl %eax, %dst */
2558//.. *p++ = 0x89;
2559//.. p = doAMode_R(p, hregX86_EAX(), i->Xin.FpCmp.dst);
2560//.. goto done;
2561//..
2562//.. case Xin_SseConst: {
2563//.. UShort con = i->Xin.SseConst.con;
2564//.. p = push_word_from_tags(p, (con >> 12) & 0xF);
2565//.. p = push_word_from_tags(p, (con >> 8) & 0xF);
2566//.. p = push_word_from_tags(p, (con >> 4) & 0xF);
2567//.. p = push_word_from_tags(p, con & 0xF);
2568//.. /* movl (%esp), %xmm-dst */
2569//.. *p++ = 0x0F;
2570//.. *p++ = 0x10;
2571//.. *p++ = 0x04 + 8 * (7 & vregNo(i->Xin.SseConst.dst));
2572//.. *p++ = 0x24;
2573//.. /* addl $16, %esp */
2574//.. *p++ = 0x83;
2575//.. *p++ = 0xC4;
2576//.. *p++ = 0x10;
2577//.. goto done;
2578//.. }
2579//..
2580//.. case Xin_SseLdSt:
2581//.. *p++ = 0x0F;
2582//.. *p++ = i->Xin.SseLdSt.isLoad ? 0x10 : 0x11;
2583//.. p = doAMode_M(p, fake(vregNo(i->Xin.SseLdSt.reg)), i->Xin.SseLdSt.addr);
2584//.. goto done;
2585//..
2586//.. case Xin_SseLdzLO:
2587//.. vassert(i->Xin.SseLdzLO.sz == 4 || i->Xin.SseLdzLO.sz == 8);
2588//.. /* movs[sd] amode, %xmm-dst */
2589//.. *p++ = i->Xin.SseLdzLO.sz==4 ? 0xF3 : 0xF2;
2590//.. *p++ = 0x0F;
2591//.. *p++ = 0x10;
2592//.. p = doAMode_M(p, fake(vregNo(i->Xin.SseLdzLO.reg)),
2593//.. i->Xin.SseLdzLO.addr);
2594//.. goto done;
2595//..
2596//.. case Xin_Sse32Fx4:
2597//.. xtra = 0;
2598//.. *p++ = 0x0F;
2599//.. switch (i->Xin.Sse32Fx4.op) {
2600//.. case Xsse_ADDF: *p++ = 0x58; break;
2601//.. case Xsse_DIVF: *p++ = 0x5E; break;
2602//.. case Xsse_MAXF: *p++ = 0x5F; break;
2603//.. case Xsse_MINF: *p++ = 0x5D; break;
2604//.. case Xsse_MULF: *p++ = 0x59; break;
2605//.. case Xsse_RCPF: *p++ = 0x53; break;
2606//.. case Xsse_RSQRTF: *p++ = 0x52; break;
2607//.. case Xsse_SQRTF: *p++ = 0x51; break;
2608//.. case Xsse_SUBF: *p++ = 0x5C; break;
2609//.. case Xsse_CMPEQF: *p++ = 0xC2; xtra = 0x100; break;
2610//.. case Xsse_CMPLTF: *p++ = 0xC2; xtra = 0x101; break;
2611//.. case Xsse_CMPLEF: *p++ = 0xC2; xtra = 0x102; break;
2612//.. default: goto bad;
2613//.. }
2614//.. p = doAMode_R(p, fake(vregNo(i->Xin.Sse32Fx4.dst)),
2615//.. fake(vregNo(i->Xin.Sse32Fx4.src)) );
2616//.. if (xtra & 0x100)
2617//.. *p++ = (UChar)(xtra & 0xFF);
2618//.. goto done;
2619//..
2620//.. case Xin_Sse64Fx2:
2621//.. xtra = 0;
2622//.. *p++ = 0x66;
2623//.. *p++ = 0x0F;
2624//.. switch (i->Xin.Sse64Fx2.op) {
2625//.. case Xsse_ADDF: *p++ = 0x58; break;
2626//.. case Xsse_DIVF: *p++ = 0x5E; break;
2627//.. case Xsse_MAXF: *p++ = 0x5F; break;
2628//.. case Xsse_MINF: *p++ = 0x5D; break;
2629//.. case Xsse_MULF: *p++ = 0x59; break;
2630//.. case Xsse_RCPF: *p++ = 0x53; break;
2631//.. case Xsse_RSQRTF: *p++ = 0x52; break;
2632//.. case Xsse_SQRTF: *p++ = 0x51; break;
2633//.. case Xsse_SUBF: *p++ = 0x5C; break;
2634//.. case Xsse_CMPEQF: *p++ = 0xC2; xtra = 0x100; break;
2635//.. case Xsse_CMPLTF: *p++ = 0xC2; xtra = 0x101; break;
2636//.. case Xsse_CMPLEF: *p++ = 0xC2; xtra = 0x102; break;
2637//.. default: goto bad;
2638//.. }
2639//.. p = doAMode_R(p, fake(vregNo(i->Xin.Sse64Fx2.dst)),
2640//.. fake(vregNo(i->Xin.Sse64Fx2.src)) );
2641//.. if (xtra & 0x100)
2642//.. *p++ = (UChar)(xtra & 0xFF);
2643//.. goto done;
2644//..
2645//.. case Xin_Sse32FLo:
2646//.. xtra = 0;
2647//.. *p++ = 0xF3;
2648//.. *p++ = 0x0F;
2649//.. switch (i->Xin.Sse32FLo.op) {
2650//.. case Xsse_ADDF: *p++ = 0x58; break;
2651//.. case Xsse_DIVF: *p++ = 0x5E; break;
2652//.. case Xsse_MAXF: *p++ = 0x5F; break;
2653//.. case Xsse_MINF: *p++ = 0x5D; break;
2654//.. case Xsse_MULF: *p++ = 0x59; break;
2655//.. case Xsse_RCPF: *p++ = 0x53; break;
2656//.. case Xsse_RSQRTF: *p++ = 0x52; break;
2657//.. case Xsse_SQRTF: *p++ = 0x51; break;
2658//.. case Xsse_SUBF: *p++ = 0x5C; break;
2659//.. case Xsse_CMPEQF: *p++ = 0xC2; xtra = 0x100; break;
2660//.. case Xsse_CMPLTF: *p++ = 0xC2; xtra = 0x101; break;
2661//.. case Xsse_CMPLEF: *p++ = 0xC2; xtra = 0x102; break;
2662//.. default: goto bad;
2663//.. }
2664//.. p = doAMode_R(p, fake(vregNo(i->Xin.Sse32FLo.dst)),
2665//.. fake(vregNo(i->Xin.Sse32FLo.src)) );
2666//.. if (xtra & 0x100)
2667//.. *p++ = (UChar)(xtra & 0xFF);
2668//.. goto done;
2669//..
2670//.. case Xin_Sse64FLo:
2671//.. xtra = 0;
2672//.. *p++ = 0xF2;
2673//.. *p++ = 0x0F;
2674//.. switch (i->Xin.Sse64FLo.op) {
2675//.. case Xsse_ADDF: *p++ = 0x58; break;
2676//.. case Xsse_DIVF: *p++ = 0x5E; break;
2677//.. case Xsse_MAXF: *p++ = 0x5F; break;
2678//.. case Xsse_MINF: *p++ = 0x5D; break;
2679//.. case Xsse_MULF: *p++ = 0x59; break;
2680//.. case Xsse_RCPF: *p++ = 0x53; break;
2681//.. case Xsse_RSQRTF: *p++ = 0x52; break;
2682//.. case Xsse_SQRTF: *p++ = 0x51; break;
2683//.. case Xsse_SUBF: *p++ = 0x5C; break;
2684//.. case Xsse_CMPEQF: *p++ = 0xC2; xtra = 0x100; break;
2685//.. case Xsse_CMPLTF: *p++ = 0xC2; xtra = 0x101; break;
2686//.. case Xsse_CMPLEF: *p++ = 0xC2; xtra = 0x102; break;
2687//.. default: goto bad;
2688//.. }
2689//.. p = doAMode_R(p, fake(vregNo(i->Xin.Sse64FLo.dst)),
2690//.. fake(vregNo(i->Xin.Sse64FLo.src)) );
2691//.. if (xtra & 0x100)
2692//.. *p++ = (UChar)(xtra & 0xFF);
2693//.. goto done;
2694//..
2695//.. case Xin_SseReRg:
2696//.. # define XX(_n) *p++ = (_n)
2697//.. switch (i->Xin.SseReRg.op) {
2698//.. case Xsse_MOV: /*movups*/ XX(0x0F); XX(0x10); break;
2699//.. case Xsse_OR: XX(0x0F); XX(0x56); break;
2700//.. case Xsse_XOR: XX(0x0F); XX(0x57); break;
2701//.. case Xsse_AND: XX(0x0F); XX(0x54); break;
2702//.. case Xsse_PACKSSD: XX(0x66); XX(0x0F); XX(0x6B); break;
2703//.. case Xsse_PACKSSW: XX(0x66); XX(0x0F); XX(0x63); break;
2704//.. case Xsse_PACKUSW: XX(0x66); XX(0x0F); XX(0x67); break;
2705//.. case Xsse_ADD8: XX(0x66); XX(0x0F); XX(0xFC); break;
2706//.. case Xsse_ADD16: XX(0x66); XX(0x0F); XX(0xFD); break;
2707//.. case Xsse_ADD32: XX(0x66); XX(0x0F); XX(0xFE); break;
2708//.. case Xsse_ADD64: XX(0x66); XX(0x0F); XX(0xD4); break;
2709//.. case Xsse_QADD8S: XX(0x66); XX(0x0F); XX(0xEC); break;
2710//.. case Xsse_QADD16S: XX(0x66); XX(0x0F); XX(0xED); break;
2711//.. case Xsse_QADD8U: XX(0x66); XX(0x0F); XX(0xDC); break;
2712//.. case Xsse_QADD16U: XX(0x66); XX(0x0F); XX(0xDD); break;
2713//.. case Xsse_AVG8U: XX(0x66); XX(0x0F); XX(0xE0); break;
2714//.. case Xsse_AVG16U: XX(0x66); XX(0x0F); XX(0xE3); break;
2715//.. case Xsse_CMPEQ8: XX(0x66); XX(0x0F); XX(0x74); break;
2716//.. case Xsse_CMPEQ16: XX(0x66); XX(0x0F); XX(0x75); break;
2717//.. case Xsse_CMPEQ32: XX(0x66); XX(0x0F); XX(0x76); break;
2718//.. case Xsse_CMPGT8S: XX(0x66); XX(0x0F); XX(0x64); break;
2719//.. case Xsse_CMPGT16S: XX(0x66); XX(0x0F); XX(0x65); break;
2720//.. case Xsse_CMPGT32S: XX(0x66); XX(0x0F); XX(0x66); break;
2721//.. case Xsse_MAX16S: XX(0x66); XX(0x0F); XX(0xEE); break;
2722//.. case Xsse_MAX8U: XX(0x66); XX(0x0F); XX(0xDE); break;
2723//.. case Xsse_MIN16S: XX(0x66); XX(0x0F); XX(0xEA); break;
2724//.. case Xsse_MIN8U: XX(0x66); XX(0x0F); XX(0xDA); break;
2725//.. case Xsse_MULHI16U: XX(0x66); XX(0x0F); XX(0xE4); break;
2726//.. case Xsse_MULHI16S: XX(0x66); XX(0x0F); XX(0xE5); break;
2727//.. case Xsse_MUL16: XX(0x66); XX(0x0F); XX(0xD5); break;
2728//.. case Xsse_SHL16: XX(0x66); XX(0x0F); XX(0xF1); break;
2729//.. case Xsse_SHL32: XX(0x66); XX(0x0F); XX(0xF2); break;
2730//.. case Xsse_SHL64: XX(0x66); XX(0x0F); XX(0xF3); break;
2731//.. case Xsse_SAR16: XX(0x66); XX(0x0F); XX(0xE1); break;
2732//.. case Xsse_SAR32: XX(0x66); XX(0x0F); XX(0xE2); break;
2733//.. case Xsse_SHR16: XX(0x66); XX(0x0F); XX(0xD1); break;
2734//.. case Xsse_SHR32: XX(0x66); XX(0x0F); XX(0xD2); break;
2735//.. case Xsse_SHR64: XX(0x66); XX(0x0F); XX(0xD3); break;
2736//.. case Xsse_SUB8: XX(0x66); XX(0x0F); XX(0xF8); break;
2737//.. case Xsse_SUB16: XX(0x66); XX(0x0F); XX(0xF9); break;
2738//.. case Xsse_SUB32: XX(0x66); XX(0x0F); XX(0xFA); break;
2739//.. case Xsse_SUB64: XX(0x66); XX(0x0F); XX(0xFB); break;
2740//.. case Xsse_QSUB8S: XX(0x66); XX(0x0F); XX(0xE8); break;
2741//.. case Xsse_QSUB16S: XX(0x66); XX(0x0F); XX(0xE9); break;
2742//.. case Xsse_QSUB8U: XX(0x66); XX(0x0F); XX(0xD8); break;
2743//.. case Xsse_QSUB16U: XX(0x66); XX(0x0F); XX(0xD9); break;
2744//.. case Xsse_UNPCKHB: XX(0x66); XX(0x0F); XX(0x68); break;
2745//.. case Xsse_UNPCKHW: XX(0x66); XX(0x0F); XX(0x69); break;
2746//.. case Xsse_UNPCKHD: XX(0x66); XX(0x0F); XX(0x6A); break;
2747//.. case Xsse_UNPCKHQ: XX(0x66); XX(0x0F); XX(0x6D); break;
2748//.. case Xsse_UNPCKLB: XX(0x66); XX(0x0F); XX(0x60); break;
2749//.. case Xsse_UNPCKLW: XX(0x66); XX(0x0F); XX(0x61); break;
2750//.. case Xsse_UNPCKLD: XX(0x66); XX(0x0F); XX(0x62); break;
2751//.. case Xsse_UNPCKLQ: XX(0x66); XX(0x0F); XX(0x6C); break;
2752//.. default: goto bad;
2753//.. }
2754//.. p = doAMode_R(p, fake(vregNo(i->Xin.SseReRg.dst)),
2755//.. fake(vregNo(i->Xin.SseReRg.src)) );
2756//.. # undef XX
2757//.. goto done;
2758//..
2759//.. case Xin_SseCMov:
2760//.. /* jmp fwds if !condition */
2761//.. *p++ = 0x70 + (i->Xin.SseCMov.cond ^ 1);
2762//.. *p++ = 0; /* # of bytes in the next bit, which we don't know yet */
2763//.. ptmp = p;
2764//..
2765//.. /* movaps %src, %dst */
2766//.. *p++ = 0x0F;
2767//.. *p++ = 0x28;
2768//.. p = doAMode_R(p, fake(vregNo(i->Xin.SseCMov.dst)),
2769//.. fake(vregNo(i->Xin.SseCMov.src)) );
2770//..
2771//.. /* Fill in the jump offset. */
2772//.. *(ptmp-1) = p - ptmp;
2773//.. goto done;
2774//..
2775//.. case Xin_SseShuf:
2776//.. *p++ = 0x66;
2777//.. *p++ = 0x0F;
2778//.. *p++ = 0x70;
2779//.. p = doAMode_R(p, fake(vregNo(i->Xin.SseShuf.dst)),
2780//.. fake(vregNo(i->Xin.SseShuf.src)) );
2781//.. *p++ = (UChar)(i->Xin.SseShuf.order);
2782//.. goto done;
2783
2784 default:
2785 goto bad;
2786 }
2787
2788 bad:
cerionab9132d2005-02-15 15:46:59 +00002789 vex_printf("\n=> ");
cerionbcf8c3e2005-02-04 16:17:07 +00002790 ppPPC32Instr(i);
2791 vpanic("emit_PPC32Instr");
2792 /*NOTREACHED*/
2793
cerionbcf8c3e2005-02-04 16:17:07 +00002794 done:
2795 vassert(p - &buf[0] <= 32);
2796 return p - &buf[0];
2797
2798# undef fake
2799}
2800
2801/*---------------------------------------------------------------*/
2802/*--- end host-ppc32/hdefs.c ---*/
2803/*---------------------------------------------------------------*/