blob: 427aebdab77fd39c06f86e6a952d19625379f717 [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)
cerionf9d6e222005-02-23 18:21:31 +0000280 vex_printf("0(");
cerionb85e8bb2005-02-16 08:54:33 +0000281 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";
cerionb85e8bb2005-02-16 08:54:33 +0000401// case Palu_ADC: return "adc";
402// case Palu_SBB: return "sbb";
403 case Palu_AND: return "and";
404 case Palu_OR: return "or";
405 case Palu_XOR: return "xor";
cerionb85e8bb2005-02-16 08:54:33 +0000406 default: vpanic("showPPC32AluOp");
cerioncd304492005-02-08 19:40:24 +0000407 }
408}
409
410HChar* showPPC32ShiftOp ( PPC32ShiftOp op ) {
411 switch (op) {
cerionb85e8bb2005-02-16 08:54:33 +0000412 case Psh_SHL: return "slw";
413 case Psh_SHR: return "srw";
414 case Psh_SAR: return "sraw";
415 case Psh_ROL: return "rlw";
416 default: vpanic("showPPC32ShiftOp");
cerioncd304492005-02-08 19:40:24 +0000417 }
418}
419
cerionab9132d2005-02-15 15:46:59 +0000420HChar* showPPC32CmpOp ( PPC32CmpOp op ) {
421 switch (op) {
cerionb85e8bb2005-02-16 08:54:33 +0000422 case Pcmp_U: return "cmpl";
423 case Pcmp_S: return "cmp";
424 default: vpanic("showPPC32CmpOp");
cerionab9132d2005-02-15 15:46:59 +0000425 }
426}
427
cerionbcf8c3e2005-02-04 16:17:07 +0000428//.. HChar* showX86FpOp ( X86FpOp op ) {
429//.. switch (op) {
430//.. case Xfp_ADD: return "add";
431//.. case Xfp_SUB: return "sub";
432//.. case Xfp_MUL: return "mul";
433//.. case Xfp_DIV: return "div";
434//.. case Xfp_SCALE: return "scale";
435//.. case Xfp_ATAN: return "atan";
436//.. case Xfp_YL2X: return "yl2x";
437//.. case Xfp_YL2XP1: return "yl2xp1";
438//.. case Xfp_PREM: return "prem";
439//.. case Xfp_PREM1: return "prem1";
440//.. case Xfp_SQRT: return "sqrt";
441//.. case Xfp_ABS: return "abs";
442//.. case Xfp_NEG: return "chs";
443//.. case Xfp_MOV: return "mov";
444//.. case Xfp_SIN: return "sin";
445//.. case Xfp_COS: return "cos";
446//.. case Xfp_TAN: return "tan";
447//.. case Xfp_ROUND: return "round";
448//.. case Xfp_2XM1: return "2xm1";
449//.. default: vpanic("showX86FpOp");
450//.. }
451//.. }
cerioncd304492005-02-08 19:40:24 +0000452
453PPC32Instr* PPC32Instr_Alu32 ( PPC32AluOp op, HReg dst, HReg src1, PPC32RI* src2 ) {
cerion33aa6da2005-02-16 10:25:26 +0000454 if (src2->tag == Pri_Imm)
455 vassert(src2->Pri.Imm.imm32 < 0x10000);
cerioncd304492005-02-08 19:40:24 +0000456 PPC32Instr* i = LibVEX_Alloc(sizeof(PPC32Instr));
457 i->tag = Pin_Alu32;
458 i->Pin.Alu32.op = op;
459 i->Pin.Alu32.dst = dst;
460 i->Pin.Alu32.src1 = src1;
461 i->Pin.Alu32.src2 = src2;
462 return i;
463}
cerion5e2527e2005-02-25 16:39:58 +0000464PPC32Instr* PPC32Instr_Sub32 ( HReg dst, PPC32RI* src1, HReg src2 ) {
465 if (src1->tag == Pri_Imm)
466 vassert(src1->Pri.Imm.imm32 < 0x10000);
467 PPC32Instr* i = LibVEX_Alloc(sizeof(PPC32Instr));
468 i->tag = Pin_Sub32;
469 i->Pin.Sub32.dst = dst;
470 i->Pin.Sub32.src1 = src1;
471 i->Pin.Sub32.src2 = src2;
472 return i;
473}
cerioncd304492005-02-08 19:40:24 +0000474PPC32Instr* PPC32Instr_Sh32 ( PPC32ShiftOp op, HReg dst, HReg src, PPC32RI* shft ) {
cerionab9132d2005-02-15 15:46:59 +0000475 if (op == Psh_SHL || op == Psh_SHR) // No imm versions for these.
476 vassert(shft->tag == Pri_Reg);
477 if (shft->tag == Pri_Imm)
478 vassert(shft->Pri.Imm.imm32 < 32);
cerioncd304492005-02-08 19:40:24 +0000479 PPC32Instr* i = LibVEX_Alloc(sizeof(PPC32Instr));
480 i->tag = Pin_Sh32;
481 i->Pin.Sh32.op = op;
482 i->Pin.Sh32.dst = dst;
483 i->Pin.Sh32.src = src;
484 i->Pin.Sh32.shft = shft;
485 return i;
486}
cerionab9132d2005-02-15 15:46:59 +0000487PPC32Instr* PPC32Instr_Cmp32 ( PPC32CmpOp op, UInt crfD, HReg src1, PPC32RI* src2 ) {
cerion47c526b2005-03-03 05:17:08 +0000488 if (src2->tag == Pri_Imm)
489 vassert(src2->Pri.Imm.imm32 < 0x10000);
cerion2c49e032005-02-09 17:29:49 +0000490 PPC32Instr* i = LibVEX_Alloc(sizeof(PPC32Instr));
cerionab9132d2005-02-15 15:46:59 +0000491 i->tag = Pin_Cmp32;
492 i->Pin.Cmp32.op = op;
493 i->Pin.Cmp32.crfD = crfD;
494 i->Pin.Cmp32.src1 = src1;
495 i->Pin.Cmp32.src2 = src2;
cerion2c49e032005-02-09 17:29:49 +0000496 return i;
497}
cerione13bb312005-02-10 19:51:03 +0000498PPC32Instr* PPC32Instr_Unary32 ( PPC32UnaryOp op, HReg dst, HReg src ) {
cerion2c49e032005-02-09 17:29:49 +0000499 PPC32Instr* i = LibVEX_Alloc(sizeof(PPC32Instr));
500 i->tag = Pin_Unary32;
501 i->Pin.Unary32.op = op;
502 i->Pin.Unary32.dst = dst;
cerione13bb312005-02-10 19:51:03 +0000503 i->Pin.Unary32.src = src;
cerion2c49e032005-02-09 17:29:49 +0000504 return i;
505}
cerion92f5dc72005-02-10 16:11:35 +0000506PPC32Instr* PPC32Instr_MulL ( Bool syned, Bool word, HReg dst,
cerionb85e8bb2005-02-16 08:54:33 +0000507 HReg src1, PPC32RI* src2 ) {
cerion98411db2005-02-16 14:14:49 +0000508 if (word == 1) { // high
509 vassert(src2->tag == Pri_Reg);
510 } else { // low
511 if (src2->tag == Pri_Imm) {
512 vassert(syned == True);
513 vassert(src2->Pri.Imm.imm32 < 0x10000);
514 }
515 }
cerion92f5dc72005-02-10 16:11:35 +0000516 PPC32Instr* i = LibVEX_Alloc(sizeof(PPC32Instr));
517 i->tag = Pin_MulL;
518 i->Pin.MulL.syned = syned;
519 i->Pin.MulL.word = word;
cerionc0e707e2005-02-10 22:35:34 +0000520 i->Pin.MulL.dst = dst;
cerion92f5dc72005-02-10 16:11:35 +0000521 i->Pin.MulL.src1 = src1;
522 i->Pin.MulL.src2 = src2;
523 return i;
524}
cerion33aa6da2005-02-16 10:25:26 +0000525PPC32Instr* PPC32Instr_Div ( Bool syned, HReg dst, HReg src1, HReg src2 ) {
cerionc0e707e2005-02-10 22:35:34 +0000526 PPC32Instr* i = LibVEX_Alloc(sizeof(PPC32Instr));
527 i->tag = Pin_Div;
528 i->Pin.Div.syned = syned;
529 i->Pin.Div.dst = dst;
530 i->Pin.Div.src1 = src1;
531 i->Pin.Div.src2 = src2;
532 return i;
533}
cerionbcf8c3e2005-02-04 16:17:07 +0000534//.. X86Instr* X86Instr_Sh3232 ( X86ShiftOp op, UInt amt, HReg src, HReg dst ) {
535//.. X86Instr* i = LibVEX_Alloc(sizeof(X86Instr));
536//.. i->tag = Xin_Sh3232;
537//.. i->Xin.Sh3232.op = op;
538//.. i->Xin.Sh3232.amt = amt;
539//.. i->Xin.Sh3232.src = src;
540//.. i->Xin.Sh3232.dst = dst;
541//.. vassert(op == Xsh_SHL || op == Xsh_SHR);
542//.. return i;
543//.. }
544//.. X86Instr* X86Instr_Push( X86RMI* src ) {
545//.. X86Instr* i = LibVEX_Alloc(sizeof(X86Instr));
546//.. i->tag = Xin_Push;
547//.. i->Xin.Push.src = src;
548//.. return i;
549//.. }
cerion2c49e032005-02-09 17:29:49 +0000550PPC32Instr* PPC32Instr_Call ( PPC32CondCode cond, Addr32 target, Int regparms ) {
551 PPC32Instr* i = LibVEX_Alloc(sizeof(PPC32Instr));
552 i->tag = Pin_Call;
553 i->Pin.Call.cond = cond;
554 i->Pin.Call.target = target;
555 i->Pin.Call.regparms = regparms;
556 vassert(regparms >= 0 && regparms < PPC32_N_REGPARMS);
557 return i;
558}
559PPC32Instr* PPC32Instr_Goto ( IRJumpKind jk, PPC32CondCode cond, PPC32RI* dst ) {
560 PPC32Instr* i = LibVEX_Alloc(sizeof(PPC32Instr));
561 i->tag = Pin_Goto;
562 i->Pin.Goto.cond = cond;
563 i->Pin.Goto.dst = dst;
564 i->Pin.Goto.jk = jk;
565 return i;
566}
cerionb536af92005-02-10 15:03:19 +0000567PPC32Instr* PPC32Instr_CMov32 ( PPC32CondCode cond, HReg dst, PPC32RI* src ) {
568 PPC32Instr* i = LibVEX_Alloc(sizeof(PPC32Instr));
569 i->tag = Pin_CMov32;
570 i->Pin.CMov32.cond = cond;
571 i->Pin.CMov32.src = src;
572 i->Pin.CMov32.dst = dst;
cerionab9132d2005-02-15 15:46:59 +0000573 vassert(cond.test != Pct_ALWAYS);
cerionb536af92005-02-10 15:03:19 +0000574 return i;
575}
cerion7cf8e4e2005-02-16 16:08:17 +0000576PPC32Instr* PPC32Instr_Load ( UChar sz, Bool syned,
577 HReg dst, PPC32AMode* src ) {
578 PPC32Instr* i = LibVEX_Alloc(sizeof(PPC32Instr));
579 i->tag = Pin_Load;
580 i->Pin.Load.sz = sz;
581 i->Pin.Load.syned = syned;
582 i->Pin.Load.src = src;
583 i->Pin.Load.dst = dst;
cerion2c49e032005-02-09 17:29:49 +0000584 vassert(sz == 1 || sz == 2 || sz == 4);
cerioncd304492005-02-08 19:40:24 +0000585 return i;
586}
587PPC32Instr* PPC32Instr_Store ( UChar sz, PPC32AMode* dst, HReg src ) {
588 PPC32Instr* i = LibVEX_Alloc(sizeof(PPC32Instr));
589 i->tag = Pin_Store;
590 i->Pin.Store.sz = sz;
591 i->Pin.Store.src = src;
592 i->Pin.Store.dst = dst;
593 vassert(sz == 1 || sz == 2 || sz == 4);
594 return i;
595}
cerionb536af92005-02-10 15:03:19 +0000596PPC32Instr* PPC32Instr_Set32 ( PPC32CondCode cond, HReg dst ) {
597 PPC32Instr* i = LibVEX_Alloc(sizeof(PPC32Instr));
598 i->tag = Pin_Set32;
599 i->Pin.Set32.cond = cond;
600 i->Pin.Set32.dst = dst;
601 return i;
602}
cerionbcf8c3e2005-02-04 16:17:07 +0000603//.. X86Instr* X86Instr_Bsfr32 ( Bool isFwds, HReg src, HReg dst ) {
604//.. X86Instr* i = LibVEX_Alloc(sizeof(X86Instr));
605//.. i->tag = Xin_Bsfr32;
606//.. i->Xin.Bsfr32.isFwds = isFwds;
607//.. i->Xin.Bsfr32.src = src;
608//.. i->Xin.Bsfr32.dst = dst;
609//.. return i;
610//.. }
cerion98411db2005-02-16 14:14:49 +0000611PPC32Instr* PPC32Instr_MFence ( void )
cerion92f5dc72005-02-10 16:11:35 +0000612{
613 PPC32Instr* i = LibVEX_Alloc(sizeof(PPC32Instr));
614 i->tag = Pin_MFence;
cerion92f5dc72005-02-10 16:11:35 +0000615 return i;
616}
cerioncd304492005-02-08 19:40:24 +0000617
cerionbcf8c3e2005-02-04 16:17:07 +0000618//.. X86Instr* X86Instr_FpUnary ( X86FpOp op, HReg src, HReg dst ) {
619//.. X86Instr* i = LibVEX_Alloc(sizeof(X86Instr));
620//.. i->tag = Xin_FpUnary;
621//.. i->Xin.FpUnary.op = op;
622//.. i->Xin.FpUnary.src = src;
623//.. i->Xin.FpUnary.dst = dst;
624//.. return i;
625//.. }
626//.. X86Instr* X86Instr_FpBinary ( X86FpOp op, HReg srcL, HReg srcR, HReg dst ) {
627//.. X86Instr* i = LibVEX_Alloc(sizeof(X86Instr));
628//.. i->tag = Xin_FpBinary;
629//.. i->Xin.FpBinary.op = op;
630//.. i->Xin.FpBinary.srcL = srcL;
631//.. i->Xin.FpBinary.srcR = srcR;
632//.. i->Xin.FpBinary.dst = dst;
633//.. return i;
634//.. }
635//.. X86Instr* X86Instr_FpLdSt ( Bool isLoad, UChar sz, HReg reg, X86AMode* addr ) {
636//.. X86Instr* i = LibVEX_Alloc(sizeof(X86Instr));
637//.. i->tag = Xin_FpLdSt;
638//.. i->Xin.FpLdSt.isLoad = isLoad;
639//.. i->Xin.FpLdSt.sz = sz;
640//.. i->Xin.FpLdSt.reg = reg;
641//.. i->Xin.FpLdSt.addr = addr;
642//.. vassert(sz == 4 || sz == 8);
643//.. return i;
644//.. }
645//.. X86Instr* X86Instr_FpLdStI ( Bool isLoad, UChar sz,
646//.. HReg reg, X86AMode* addr ) {
647//.. X86Instr* i = LibVEX_Alloc(sizeof(X86Instr));
648//.. i->tag = Xin_FpLdStI;
649//.. i->Xin.FpLdStI.isLoad = isLoad;
650//.. i->Xin.FpLdStI.sz = sz;
651//.. i->Xin.FpLdStI.reg = reg;
652//.. i->Xin.FpLdStI.addr = addr;
653//.. vassert(sz == 2 || sz == 4 || sz == 8);
654//.. return i;
655//.. }
656//.. X86Instr* X86Instr_Fp64to32 ( HReg src, HReg dst ) {
657//.. X86Instr* i = LibVEX_Alloc(sizeof(X86Instr));
658//.. i->tag = Xin_Fp64to32;
659//.. i->Xin.Fp64to32.src = src;
660//.. i->Xin.Fp64to32.dst = dst;
661//.. return i;
662//.. }
663//.. X86Instr* X86Instr_FpCMov ( X86CondCode cond, HReg src, HReg dst ) {
664//.. X86Instr* i = LibVEX_Alloc(sizeof(X86Instr));
665//.. i->tag = Xin_FpCMov;
666//.. i->Xin.FpCMov.cond = cond;
667//.. i->Xin.FpCMov.src = src;
668//.. i->Xin.FpCMov.dst = dst;
669//.. vassert(cond != Xcc_ALWAYS);
670//.. return i;
671//.. }
672//.. X86Instr* X86Instr_FpLdStCW ( Bool isLoad, X86AMode* addr ) {
673//.. X86Instr* i = LibVEX_Alloc(sizeof(X86Instr));
674//.. i->tag = Xin_FpLdStCW;
675//.. i->Xin.FpLdStCW.isLoad = isLoad;
676//.. i->Xin.FpLdStCW.addr = addr;
677//.. return i;
678//.. }
679//.. X86Instr* X86Instr_FpStSW_AX ( void ) {
680//.. X86Instr* i = LibVEX_Alloc(sizeof(X86Instr));
681//.. i->tag = Xin_FpStSW_AX;
682//.. return i;
683//.. }
684//.. X86Instr* X86Instr_FpCmp ( HReg srcL, HReg srcR, HReg dst ) {
685//.. X86Instr* i = LibVEX_Alloc(sizeof(X86Instr));
686//.. i->tag = Xin_FpCmp;
687//.. i->Xin.FpCmp.srcL = srcL;
688//.. i->Xin.FpCmp.srcR = srcR;
689//.. i->Xin.FpCmp.dst = dst;
690//.. return i;
691//.. }
cerionbcf8c3e2005-02-04 16:17:07 +0000692
cerion7f000af2005-02-22 20:36:49 +0000693/* Read/Write Link Register */
694PPC32Instr* PPC32Instr_RdWrLR ( Bool wrLR, HReg gpr )
695{
696 PPC32Instr* i = LibVEX_Alloc(sizeof(PPC32Instr));
697 i->tag = Pin_RdWrLR;
698 i->Pin.RdWrLR.wrLR = wrLR;
699 i->Pin.RdWrLR.gpr = gpr;
700 return i;
701}
702
cerionbcf8c3e2005-02-04 16:17:07 +0000703void ppPPC32Instr ( PPC32Instr* i )
704{
705 switch (i->tag) {
cerionb85e8bb2005-02-16 08:54:33 +0000706 case Pin_Alu32:
707 if (i->Pin.Alu32.op == Palu_OR && // or Rd,Rs,Rs == mr Rd,Rs
708 i->Pin.Alu32.src2->tag == Pri_Reg &&
709 i->Pin.Alu32.src2->Pri.Reg.reg == i->Pin.Alu32.src1) {
710 vex_printf("mr ");
711 ppHRegPPC32(i->Pin.Alu32.dst);
cerioncd304492005-02-08 19:40:24 +0000712 vex_printf(",");
cerionb85e8bb2005-02-16 08:54:33 +0000713 ppHRegPPC32(i->Pin.Alu32.src1);
cerioncd304492005-02-08 19:40:24 +0000714 return;
cerionb85e8bb2005-02-16 08:54:33 +0000715 }
716 if (i->Pin.Alu32.op == Palu_ADD && // add Rd,R0,Rs == li Rd,Rs
717 i->Pin.Alu32.src1 == hregPPC32_GPR0() &&
718 i->Pin.Alu32.src2->tag == Pri_Imm) {
719 vex_printf("li ");
720 ppHRegPPC32(i->Pin.Alu32.dst);
721 vex_printf(",");
722 ppPPC32RI(i->Pin.Alu32.src2);
723 return;
724 }
cerionb8c3b7f2005-03-01 20:27:49 +0000725 if (i->Pin.Alu32.op == Palu_AND && // 'andi.' - always has the '.'
726 i->Pin.Alu32.src2->tag == Pri_Imm) {
727 vex_printf("andi. ");
728 ppHRegPPC32(i->Pin.Alu32.dst);
729 vex_printf(",");
730 ppHRegPPC32(i->Pin.Alu32.src1);
731 vex_printf(",");
732 ppPPC32RI(i->Pin.Alu32.src2);
733 return;
734 }
cerionb85e8bb2005-02-16 08:54:33 +0000735 vex_printf("%s%s ", showPPC32AluOp(i->Pin.Alu32.op),
736 i->Pin.Alu32.src2->tag == Pri_Imm ? "i" : "" );
737 ppHRegPPC32(i->Pin.Alu32.dst);
738 vex_printf(",");
739 ppHRegPPC32(i->Pin.Alu32.src1);
740 vex_printf(",");
741 ppPPC32RI(i->Pin.Alu32.src2);
742 return;
cerion5e2527e2005-02-25 16:39:58 +0000743 case Pin_Sub32:
744 vex_printf("subf%s ", i->Pin.Sub32.src1->tag == Pri_Imm ? "ic" : "" );
745 ppHRegPPC32(i->Pin.Sub32.dst);
746 vex_printf(",");
747 ppHRegPPC32(i->Pin.Sub32.src2); // yes, order is right :-)
748 vex_printf(",");
749 ppPPC32RI(i->Pin.Sub32.src1);
750 return;
cerionb85e8bb2005-02-16 08:54:33 +0000751 case Pin_Sh32:
752 vex_printf("%s%s ", showPPC32ShiftOp(i->Pin.Sh32.op),
753 i->Pin.Sh32.shft->tag == Pri_Imm ? "i" : "" );
754 ppHRegPPC32(i->Pin.Sh32.dst);
755 vex_printf(",");
756 ppHRegPPC32(i->Pin.Sh32.src);
757 vex_printf(",");
758 ppPPC32RI(i->Pin.Sh32.shft);
759 return;
cerionb85e8bb2005-02-16 08:54:33 +0000760 case Pin_Cmp32:
cerionb8c3b7f2005-03-01 20:27:49 +0000761 vex_printf("%s%s %%crf%d,", showPPC32CmpOp(i->Pin.Cmp32.op),
cerionb85e8bb2005-02-16 08:54:33 +0000762 i->Pin.Cmp32.src2->tag == Pri_Imm ? "i" : "",
cerion8c51ed42005-02-22 11:16:54 +0000763 (7 - i->Pin.Cmp32.crfD));
cerion5e2527e2005-02-25 16:39:58 +0000764 ppHRegPPC32(i->Pin.Cmp32.src1);
cerionb85e8bb2005-02-16 08:54:33 +0000765 vex_printf(",");
cerion5e2527e2005-02-25 16:39:58 +0000766 ppPPC32RI(i->Pin.Cmp32.src2);
cerionb85e8bb2005-02-16 08:54:33 +0000767 return;
768 case Pin_Unary32:
769 vex_printf("%s ", showPPC32UnaryOp(i->Pin.Unary32.op));
770 ppHRegPPC32(i->Pin.Unary32.dst);
771 vex_printf(",");
772 ppHRegPPC32(i->Pin.Unary32.src);
773 return;
774 case Pin_MulL:
775 if (i->Pin.MulL.src2->tag == Pri_Imm) {
776 vex_printf("mulli ");
777 } else {
778 vex_printf("mul%s%c ",
779 i->Pin.MulL.word ? "hw" : "lw",
780 i->Pin.MulL.syned ? 's' : 'u');
781 }
782 ppHRegPPC32(i->Pin.MulL.dst);
783 vex_printf(",");
784 ppHRegPPC32(i->Pin.MulL.src1);
785 vex_printf(",");
786 ppPPC32RI(i->Pin.MulL.src2);
787 return;
788 case Pin_Div:
789 vex_printf("divw%s ",
790 i->Pin.Div.syned ? "" : "u");
cerion33aa6da2005-02-16 10:25:26 +0000791 ppHRegPPC32(i->Pin.Div.dst);
cerionb85e8bb2005-02-16 08:54:33 +0000792 vex_printf(",");
cerion33aa6da2005-02-16 10:25:26 +0000793 ppHRegPPC32(i->Pin.Div.src1);
cerionb85e8bb2005-02-16 08:54:33 +0000794 vex_printf(",");
cerion33aa6da2005-02-16 10:25:26 +0000795 ppHRegPPC32(i->Pin.Div.src2);
cerionb85e8bb2005-02-16 08:54:33 +0000796 return;
cerionbcf8c3e2005-02-04 16:17:07 +0000797//.. case Xin_Sh3232:
798//.. vex_printf("%sdl ", showX86ShiftOp(i->Xin.Sh3232.op));
799//.. if (i->Xin.Sh3232.amt == 0)
800//.. vex_printf(" %%cl,");
801//.. else
802//.. vex_printf(" $%d,", i->Xin.Sh3232.amt);
803//.. ppHRegX86(i->Xin.Sh3232.src);
804//.. vex_printf(",");
805//.. ppHRegX86(i->Xin.Sh3232.dst);
806//.. return;
807//.. case Xin_Push:
808//.. vex_printf("pushl ");
809//.. ppX86RMI(i->Xin.Push.src);
810//.. return;
cerionb85e8bb2005-02-16 08:54:33 +0000811 case Pin_Call:
cerion8c51ed42005-02-22 11:16:54 +0000812 vex_printf("call: ");
813 if (i->Pin.Call.cond.test != Pct_ALWAYS) {
814 vex_printf("if (%%crf0.%s) ", showPPC32CondCode(i->Pin.Call.cond));
815 }
816 vex_printf("{ ");
817 if (i->Pin.Call.target < 0x10000) {
818 vex_printf("li %%r12, 0x%x ;", i->Pin.Call.target);
819 } else {
820 vex_printf("lis %%r12,0x%x ; ", i->Pin.Call.target >> 16);
cerionb8c3b7f2005-03-01 20:27:49 +0000821 vex_printf("ori %%r12,%%r12,0x%x ; ", i->Pin.Call.target & 0xFFFF);
cerion8c51ed42005-02-22 11:16:54 +0000822 }
823 vex_printf("mtctr r12 ; bctrl[%d] }",i->Pin.Call.regparms);
cerionb85e8bb2005-02-16 08:54:33 +0000824 break;
825 case Pin_Goto:
cerion33aa6da2005-02-16 10:25:26 +0000826 vex_printf("goto: ");
cerionb85e8bb2005-02-16 08:54:33 +0000827 if (i->Pin.Goto.cond.test != Pct_ALWAYS) {
cerion8c51ed42005-02-22 11:16:54 +0000828 vex_printf("if (%%crf0.%s) ", showPPC32CondCode(i->Pin.Goto.cond));
cerionb85e8bb2005-02-16 08:54:33 +0000829 }
cerion8c51ed42005-02-22 11:16:54 +0000830 vex_printf("{ ");
cerionb85e8bb2005-02-16 08:54:33 +0000831 if (i->Pin.Goto.jk != Ijk_Boring) {
cerione97e1062005-02-21 15:09:19 +0000832 vex_printf("li %%r31, $");
cerionb85e8bb2005-02-16 08:54:33 +0000833 ppIRJumpKind(i->Pin.Goto.jk);
834 vex_printf(" ; ");
835 }
cerione97e1062005-02-21 15:09:19 +0000836 if (i->Pin.Goto.dst->tag == Pri_Imm) {
cerion8c51ed42005-02-22 11:16:54 +0000837 UInt imm32 = i->Pin.Goto.dst->Pri.Imm.imm32;
838 if (imm32 < 0x10000) {
839 vex_printf("li %%r3, 0x%x ; ", imm32);
cerione97e1062005-02-21 15:09:19 +0000840 } else {
cerion8c51ed42005-02-22 11:16:54 +0000841 vex_printf("lis %%r3,0x%x ; ", imm32 >> 16);
842 vex_printf("ori %%r3,%%r3,0x%x ; ", imm32 & 0xFFFF);
cerione97e1062005-02-21 15:09:19 +0000843 }
844 } else {
845 vex_printf("if (%%r3 != ");
846 ppHRegPPC32(i->Pin.Goto.dst->Pri.Reg.reg);
847 vex_printf(") { mr %%r3,");
848 ppHRegPPC32(i->Pin.Goto.dst->Pri.Reg.reg);
849 vex_printf(" } ; ");
850 }
cerion8c51ed42005-02-22 11:16:54 +0000851 vex_printf("blr }");
cerionb85e8bb2005-02-16 08:54:33 +0000852 return;
853 case Pin_CMov32:
cerionb85e8bb2005-02-16 08:54:33 +0000854 vex_printf("cmov32 (%s) ", showPPC32CondCode(i->Pin.CMov32.cond));
855 ppHRegPPC32(i->Pin.CMov32.dst);
856 vex_printf(",");
857 ppPPC32RI(i->Pin.CMov32.src);
cerion8c51ed42005-02-22 11:16:54 +0000858 vex_printf(": ");
859 if (i->Pin.CMov32.cond.test != Pct_ALWAYS) {
860 vex_printf("if (%%crf0.%s) ", showPPC32CondCode(i->Pin.CMov32.cond));
861 }
862 vex_printf("{ ");
863 if (i->Pin.CMov32.src->tag == Pri_Imm) {
864 UInt imm32 = i->Pin.CMov32.src->Pri.Imm.imm32;
865 if (imm32 < 0x10000) {
866 vex_printf("li ");
867 ppHRegPPC32(i->Pin.CMov32.dst);
cerionb8c3b7f2005-03-01 20:27:49 +0000868 vex_printf(",0x%x", imm32);
cerion8c51ed42005-02-22 11:16:54 +0000869 } else {
870 vex_printf("lis ");
871 ppHRegPPC32(i->Pin.CMov32.dst);
872 vex_printf(",0x%x ; ", imm32 >> 16);
873 vex_printf("ori ");
874 ppHRegPPC32(i->Pin.CMov32.dst);
875 vex_printf(",");
876 ppHRegPPC32(i->Pin.CMov32.dst);
877 vex_printf(",0x%x", imm32 & 0xFFFF);
878 }
879 } else {
880 vex_printf("if (");
881 ppHRegPPC32(i->Pin.CMov32.dst);
882 vex_printf(" != ");
883 ppHRegPPC32(i->Pin.CMov32.src->Pri.Reg.reg);
884 vex_printf(") { mr ");
885 ppHRegPPC32(i->Pin.CMov32.dst);
886 vex_printf(",");
887 ppHRegPPC32(i->Pin.CMov32.src->Pri.Reg.reg);
888 vex_printf(" }");
889 }
890 vex_printf(" }");
cerionb85e8bb2005-02-16 08:54:33 +0000891 return;
cerion7cf8e4e2005-02-16 16:08:17 +0000892 case Pin_Load: {
893 UChar sz = i->Pin.Load.sz;
894 Bool syned = i->Pin.Load.syned;
cerione97e1062005-02-21 15:09:19 +0000895 Bool idxd = (i->Pin.Load.src->tag == Pam_RR) ? True : False;
cerion7cf8e4e2005-02-16 16:08:17 +0000896 vex_printf("l%c%c%s ",
cerionb85e8bb2005-02-16 08:54:33 +0000897 (sz==1) ? 'b' : (sz==2 ? 'h' : 'w'),
898 syned ? 'a' : 'z',
cerionb85e8bb2005-02-16 08:54:33 +0000899 idxd ? "x" : "" );
cerion7cf8e4e2005-02-16 16:08:17 +0000900 ppHRegPPC32(i->Pin.Load.dst);
cerionb85e8bb2005-02-16 08:54:33 +0000901 vex_printf(",");
cerion7cf8e4e2005-02-16 16:08:17 +0000902 ppPPC32AMode(i->Pin.Load.src);
cerionb85e8bb2005-02-16 08:54:33 +0000903 return;
904 }
905 case Pin_Store: {
906 UChar sz = i->Pin.Store.sz;
cerione97e1062005-02-21 15:09:19 +0000907 Bool idxd = (i->Pin.Store.dst->tag == Pam_RR) ? True : False;
cerion7cf8e4e2005-02-16 16:08:17 +0000908 vex_printf("st%c%s ",
cerionb85e8bb2005-02-16 08:54:33 +0000909 (sz==1) ? 'b' : (sz==2 ? 'h' : 'w'),
cerionb85e8bb2005-02-16 08:54:33 +0000910 idxd ? "x" : "" );
911 ppHRegPPC32(i->Pin.Store.src);
912 vex_printf(",");
913 ppPPC32AMode(i->Pin.Store.dst);
914 return;
915 }
cerionf9d6e222005-02-23 18:21:31 +0000916 case Pin_Set32: {
917 PPC32CondCode cc = i->Pin.Set32.cond;
918 vex_printf("set32 (%s),", showPPC32CondCode(cc));
cerionb85e8bb2005-02-16 08:54:33 +0000919 ppHRegPPC32(i->Pin.Set32.dst);
cerionf9d6e222005-02-23 18:21:31 +0000920 if (cc.test == Pct_ALWAYS) {
921 vex_printf(": { li ");
922 ppHRegPPC32(i->Pin.Set32.dst);
923 vex_printf(",1 }");
924 } else {
925 vex_printf(": { mfcr r0 ; rlwinm ");
926 ppHRegPPC32(i->Pin.Set32.dst);
cerionfbda9b72005-02-24 20:01:02 +0000927 vex_printf(",r0,%d,31,31", cc.flag+1);
cerionf9d6e222005-02-23 18:21:31 +0000928 if (cc.test == Pct_FALSE) {
929 vex_printf("; xori ");
930 ppHRegPPC32(i->Pin.Set32.dst);
931 vex_printf(",");
932 ppHRegPPC32(i->Pin.Set32.dst);
933 vex_printf("1");
934 }
935 vex_printf(" }");
936 }
cerionb85e8bb2005-02-16 08:54:33 +0000937 return;
cerionf9d6e222005-02-23 18:21:31 +0000938 }
cerionbcf8c3e2005-02-04 16:17:07 +0000939//.. case Xin_Bsfr32:
940//.. vex_printf("bs%cl ", i->Xin.Bsfr32.isFwds ? 'f' : 'r');
941//.. ppHRegX86(i->Xin.Bsfr32.src);
942//.. vex_printf(",");
943//.. ppHRegX86(i->Xin.Bsfr32.dst);
944//.. return;
cerionb85e8bb2005-02-16 08:54:33 +0000945 case Pin_MFence:
cerion98411db2005-02-16 14:14:49 +0000946 vex_printf("mfence (=sync)");
cerionb85e8bb2005-02-16 08:54:33 +0000947 return;
cerionbcf8c3e2005-02-04 16:17:07 +0000948//.. case Xin_FpUnary:
949//.. vex_printf("g%sD ", showX86FpOp(i->Xin.FpUnary.op));
950//.. ppHRegX86(i->Xin.FpUnary.src);
951//.. vex_printf(",");
952//.. ppHRegX86(i->Xin.FpUnary.dst);
953//.. break;
954//.. case Xin_FpBinary:
955//.. vex_printf("g%sD ", showX86FpOp(i->Xin.FpBinary.op));
956//.. ppHRegX86(i->Xin.FpBinary.srcL);
957//.. vex_printf(",");
958//.. ppHRegX86(i->Xin.FpBinary.srcR);
959//.. vex_printf(",");
960//.. ppHRegX86(i->Xin.FpBinary.dst);
961//.. break;
962//.. case Xin_FpLdSt:
963//.. if (i->Xin.FpLdSt.isLoad) {
964//.. vex_printf("gld%c " , i->Xin.FpLdSt.sz==8 ? 'D' : 'F');
965//.. ppX86AMode(i->Xin.FpLdSt.addr);
966//.. vex_printf(", ");
967//.. ppHRegX86(i->Xin.FpLdSt.reg);
968//.. } else {
969//.. vex_printf("gst%c " , i->Xin.FpLdSt.sz==8 ? 'D' : 'F');
970//.. ppHRegX86(i->Xin.FpLdSt.reg);
971//.. vex_printf(", ");
972//.. ppX86AMode(i->Xin.FpLdSt.addr);
973//.. }
974//.. return;
975//.. case Xin_FpLdStI:
976//.. if (i->Xin.FpLdStI.isLoad) {
977//.. vex_printf("gild%s ", i->Xin.FpLdStI.sz==8 ? "ll" :
978//.. i->Xin.FpLdStI.sz==4 ? "l" : "w");
979//.. ppX86AMode(i->Xin.FpLdStI.addr);
980//.. vex_printf(", ");
981//.. ppHRegX86(i->Xin.FpLdStI.reg);
982//.. } else {
983//.. vex_printf("gist%s ", i->Xin.FpLdStI.sz==8 ? "ll" :
984//.. i->Xin.FpLdStI.sz==4 ? "l" : "w");
985//.. ppHRegX86(i->Xin.FpLdStI.reg);
986//.. vex_printf(", ");
987//.. ppX86AMode(i->Xin.FpLdStI.addr);
988//.. }
989//.. return;
990//.. case Xin_Fp64to32:
991//.. vex_printf("gdtof ");
992//.. ppHRegX86(i->Xin.Fp64to32.src);
993//.. vex_printf(",");
994//.. ppHRegX86(i->Xin.Fp64to32.dst);
995//.. return;
996//.. case Xin_FpCMov:
997//.. vex_printf("gcmov%s ", showX86CondCode(i->Xin.FpCMov.cond));
998//.. ppHRegX86(i->Xin.FpCMov.src);
999//.. vex_printf(",");
1000//.. ppHRegX86(i->Xin.FpCMov.dst);
1001//.. return;
1002//.. case Xin_FpLdStCW:
1003//.. vex_printf(i->Xin.FpLdStCW.isLoad ? "fldcw " : "fstcw ");
1004//.. ppX86AMode(i->Xin.FpLdStCW.addr);
1005//.. return;
1006//.. case Xin_FpStSW_AX:
1007//.. vex_printf("fstsw %%ax");
1008//.. return;
1009//.. case Xin_FpCmp:
1010//.. vex_printf("gcmp ");
1011//.. ppHRegX86(i->Xin.FpCmp.srcL);
1012//.. vex_printf(",");
1013//.. ppHRegX86(i->Xin.FpCmp.srcR);
1014//.. vex_printf(",");
1015//.. ppHRegX86(i->Xin.FpCmp.dst);
1016//.. break;
1017//.. case Xin_SseConst:
1018//.. vex_printf("const $0x%04x,", (Int)i->Xin.SseConst.con);
1019//.. ppHRegX86(i->Xin.SseConst.dst);
1020//.. break;
1021//.. case Xin_SseLdSt:
1022//.. vex_printf("movups ");
1023//.. if (i->Xin.SseLdSt.isLoad) {
1024//.. ppX86AMode(i->Xin.SseLdSt.addr);
1025//.. vex_printf(",");
1026//.. ppHRegX86(i->Xin.SseLdSt.reg);
1027//.. } else {
1028//.. ppHRegX86(i->Xin.SseLdSt.reg);
1029//.. vex_printf(",");
1030//.. ppX86AMode(i->Xin.SseLdSt.addr);
1031//.. }
1032//.. return;
1033//.. case Xin_SseLdzLO:
1034//.. vex_printf("movs%s ", i->Xin.SseLdzLO.sz==4 ? "s" : "d");
1035//.. ppX86AMode(i->Xin.SseLdzLO.addr);
1036//.. vex_printf(",");
1037//.. ppHRegX86(i->Xin.SseLdzLO.reg);
1038//.. return;
1039//.. case Xin_Sse32Fx4:
1040//.. vex_printf("%sps ", showX86SseOp(i->Xin.Sse32Fx4.op));
1041//.. ppHRegX86(i->Xin.Sse32Fx4.src);
1042//.. vex_printf(",");
1043//.. ppHRegX86(i->Xin.Sse32Fx4.dst);
1044//.. return;
1045//.. case Xin_Sse32FLo:
1046//.. vex_printf("%sss ", showX86SseOp(i->Xin.Sse32FLo.op));
1047//.. ppHRegX86(i->Xin.Sse32FLo.src);
1048//.. vex_printf(",");
1049//.. ppHRegX86(i->Xin.Sse32FLo.dst);
1050//.. return;
1051//.. case Xin_Sse64Fx2:
1052//.. vex_printf("%spd ", showX86SseOp(i->Xin.Sse64Fx2.op));
1053//.. ppHRegX86(i->Xin.Sse64Fx2.src);
1054//.. vex_printf(",");
1055//.. ppHRegX86(i->Xin.Sse64Fx2.dst);
1056//.. return;
1057//.. case Xin_Sse64FLo:
1058//.. vex_printf("%ssd ", showX86SseOp(i->Xin.Sse64FLo.op));
1059//.. ppHRegX86(i->Xin.Sse64FLo.src);
1060//.. vex_printf(",");
1061//.. ppHRegX86(i->Xin.Sse64FLo.dst);
1062//.. return;
1063//.. case Xin_SseReRg:
1064//.. vex_printf("%s ", showX86SseOp(i->Xin.SseReRg.op));
1065//.. ppHRegX86(i->Xin.SseReRg.src);
1066//.. vex_printf(",");
1067//.. ppHRegX86(i->Xin.SseReRg.dst);
1068//.. return;
1069//.. case Xin_SseCMov:
1070//.. vex_printf("cmov%s ", showX86CondCode(i->Xin.SseCMov.cond));
1071//.. ppHRegX86(i->Xin.SseCMov.src);
1072//.. vex_printf(",");
1073//.. ppHRegX86(i->Xin.SseCMov.dst);
1074//.. return;
1075//.. case Xin_SseShuf:
1076//.. vex_printf("pshufd $0x%x,", i->Xin.SseShuf.order);
1077//.. ppHRegX86(i->Xin.SseShuf.src);
1078//.. vex_printf(",");
1079//.. ppHRegX86(i->Xin.SseShuf.dst);
1080//.. return;
1081
cerion7f000af2005-02-22 20:36:49 +00001082 case Pin_RdWrLR:
1083 vex_printf("%s ", i->Pin.RdWrLR.wrLR ? "mtlr" : "mflr");
1084 ppHRegPPC32(i->Pin.RdWrLR.gpr);
1085 return;
1086
cerionb85e8bb2005-02-16 08:54:33 +00001087 default:
1088 vex_printf("\nppPPC32Instr(ppc32): No such tag(%d)\n", i->tag);
1089 vpanic("ppPPC32Instr(ppc32)");
cerionbcf8c3e2005-02-04 16:17:07 +00001090 }
1091}
1092
1093/* --------- Helpers for register allocation. --------- */
1094
1095void getRegUsage_PPC32Instr ( HRegUsage* u, PPC32Instr* i )
1096{
1097// Bool unary;
1098 initHRegUsage(u);
1099 switch (i->tag) {
cerionb85e8bb2005-02-16 08:54:33 +00001100 case Pin_Alu32:
1101 addHRegUse(u, HRmRead, i->Pin.Alu32.src1);
1102 addRegUsage_PPC32RI(u, i->Pin.Alu32.src2);
cerionb85e8bb2005-02-16 08:54:33 +00001103 addHRegUse(u, HRmWrite, i->Pin.Alu32.dst);
cerionb85e8bb2005-02-16 08:54:33 +00001104 return;
cerioncd304492005-02-08 19:40:24 +00001105
cerion5e2527e2005-02-25 16:39:58 +00001106 case Pin_Sub32:
1107 addRegUsage_PPC32RI(u, i->Pin.Sub32.src1);
1108 addHRegUse(u, HRmRead, i->Pin.Sub32.src2);
1109 addHRegUse(u, HRmWrite, i->Pin.Sub32.dst);
1110 return;
1111
cerionb85e8bb2005-02-16 08:54:33 +00001112 case Pin_Sh32:
1113 addHRegUse(u, HRmWrite, i->Pin.Sh32.dst);
1114 addHRegUse(u, HRmRead, i->Pin.Sh32.src);
1115 addRegUsage_PPC32RI(u, i->Pin.Sh32.shft);
cerionb85e8bb2005-02-16 08:54:33 +00001116 return;
1117
cerionb85e8bb2005-02-16 08:54:33 +00001118 case Pin_Cmp32:
1119 addHRegUse(u, HRmRead, i->Pin.Cmp32.src1);
1120 addRegUsage_PPC32RI(u, i->Pin.Cmp32.src2);
1121 return;
cerionab9132d2005-02-15 15:46:59 +00001122
cerionb85e8bb2005-02-16 08:54:33 +00001123 case Pin_Unary32:
1124 addHRegUse(u, HRmWrite, i->Pin.Unary32.dst);
1125 addHRegUse(u, HRmRead, i->Pin.Unary32.src);
1126 return;
1127 case Pin_MulL:
1128 addHRegUse(u, HRmWrite, i->Pin.MulL.dst);
1129 addHRegUse(u, HRmRead, i->Pin.MulL.src1);
1130 addRegUsage_PPC32RI(u, i->Pin.MulL.src2);
1131 return;
1132 case Pin_Div:
1133 addHRegUse(u, HRmWrite, i->Pin.Div.dst);
1134 addHRegUse(u, HRmRead, i->Pin.Div.src1);
cerion33aa6da2005-02-16 10:25:26 +00001135 addHRegUse(u, HRmRead, i->Pin.Div.src2);
cerionb85e8bb2005-02-16 08:54:33 +00001136 return;
cerionbcf8c3e2005-02-04 16:17:07 +00001137//.. case Xin_Sh3232:
1138//.. addHRegUse(u, HRmRead, i->Xin.Sh3232.src);
1139//.. addHRegUse(u, HRmModify, i->Xin.Sh3232.dst);
1140//.. if (i->Xin.Sh3232.amt == 0)
1141//.. addHRegUse(u, HRmRead, hregX86_ECX());
1142//.. return;
1143//.. case Xin_Push:
1144//.. addRegUsage_X86RMI(u, i->Xin.Push.src);
1145//.. addHRegUse(u, HRmModify, hregX86_ESP());
1146//.. return;
cerionb85e8bb2005-02-16 08:54:33 +00001147 case Pin_Call:
1148 /* This is a bit subtle. */
1149 /* First off, claim it trashes all the caller-saved regs
1150 which fall within the register allocator's jurisdiction.
ceriona56e9cc2005-02-16 18:08:25 +00001151 These I believe to be: r3:12
cerionb85e8bb2005-02-16 08:54:33 +00001152 */
cerionb85e8bb2005-02-16 08:54:33 +00001153 addHRegUse(u, HRmWrite, hregPPC32_GPR3());
1154 addHRegUse(u, HRmWrite, hregPPC32_GPR4());
1155 addHRegUse(u, HRmWrite, hregPPC32_GPR5());
1156 addHRegUse(u, HRmWrite, hregPPC32_GPR6());
1157 addHRegUse(u, HRmWrite, hregPPC32_GPR7());
1158 addHRegUse(u, HRmWrite, hregPPC32_GPR8());
1159 addHRegUse(u, HRmWrite, hregPPC32_GPR9());
1160 addHRegUse(u, HRmWrite, hregPPC32_GPR10());
1161 addHRegUse(u, HRmWrite, hregPPC32_GPR11());
1162 addHRegUse(u, HRmWrite, hregPPC32_GPR12());
1163
1164 /* Now we have to state any parameter-carrying registers
1165 which might be read. This depends on the regparmness. */
1166 switch (i->Pin.Call.regparms) {
1167 case 8: addHRegUse(u, HRmRead, hregPPC32_GPR10()); /*fallthru*/
1168 case 7: addHRegUse(u, HRmRead, hregPPC32_GPR9() ); /*fallthru*/
1169 case 6: addHRegUse(u, HRmRead, hregPPC32_GPR8() ); /*fallthru*/
1170 case 5: addHRegUse(u, HRmRead, hregPPC32_GPR7() ); /*fallthru*/
1171 case 4: addHRegUse(u, HRmRead, hregPPC32_GPR6() ); /*fallthru*/
1172 case 3: addHRegUse(u, HRmRead, hregPPC32_GPR5() ); /*fallthru*/
1173 case 2: addHRegUse(u, HRmRead, hregPPC32_GPR4() ); /*fallthru*/
1174 case 1: addHRegUse(u, HRmRead, hregPPC32_GPR3() ); /*fallthru*/
1175 case 0: break;
1176 default: vpanic("getRegUsage_PPC32Instr:Call:regparms");
1177 }
1178 /* Finally, there is the issue that the insn trashes a
1179 register because the literal target address has to be
ceriona56e9cc2005-02-16 18:08:25 +00001180 loaded into a register. %r12 seems a suitable victim.
1181 (Can't use %r0, as use ops that interpret it as value zero). */
cerionb85e8bb2005-02-16 08:54:33 +00001182 addHRegUse(u, HRmWrite, hregPPC32_GPR12());
1183 /* Upshot of this is that the assembler really must use %r12,
ceriona56e9cc2005-02-16 18:08:25 +00001184 and no other, as a destination temporary. */
cerionb85e8bb2005-02-16 08:54:33 +00001185 return;
1186 case Pin_Goto:
1187 addRegUsage_PPC32RI(u, i->Pin.Goto.dst);
ceriona56e9cc2005-02-16 18:08:25 +00001188 /* GPR3 holds destination address from Pin_Goto */
1189 addHRegUse(u, HRmWrite, hregPPC32_GPR3());
cerionb85e8bb2005-02-16 08:54:33 +00001190 if (i->Pin.Goto.jk != Ijk_Boring)
1191 addHRegUse(u, HRmWrite, GuestStatePtr);
1192 return;
1193 case Pin_CMov32:
1194 addRegUsage_PPC32RI(u, i->Pin.CMov32.src);
1195 addHRegUse(u, HRmModify, i->Pin.CMov32.dst);
1196 return;
cerion7cf8e4e2005-02-16 16:08:17 +00001197 case Pin_Load:
1198 addRegUsage_PPC32AMode(u, i->Pin.Load.src);
1199 addHRegUse(u, HRmWrite, i->Pin.Load.dst);
cerionb85e8bb2005-02-16 08:54:33 +00001200 return;
1201 case Pin_Store:
1202 addHRegUse(u, HRmRead, i->Pin.Store.src);
1203 addRegUsage_PPC32AMode(u, i->Pin.Store.dst);
1204 return;
1205 case Pin_Set32:
1206 addHRegUse(u, HRmWrite, i->Pin.Set32.dst);
1207 return;
cerionbcf8c3e2005-02-04 16:17:07 +00001208//.. case Xin_Bsfr32:
1209//.. addHRegUse(u, HRmRead, i->Xin.Bsfr32.src);
1210//.. addHRegUse(u, HRmWrite, i->Xin.Bsfr32.dst);
1211//.. return;
cerionb85e8bb2005-02-16 08:54:33 +00001212 case Pin_MFence:
1213 return;
cerionbcf8c3e2005-02-04 16:17:07 +00001214//.. case Xin_FpUnary:
1215//.. addHRegUse(u, HRmRead, i->Xin.FpUnary.src);
1216//.. addHRegUse(u, HRmWrite, i->Xin.FpUnary.dst);
1217//.. return;
1218//.. case Xin_FpBinary:
1219//.. addHRegUse(u, HRmRead, i->Xin.FpBinary.srcL);
1220//.. addHRegUse(u, HRmRead, i->Xin.FpBinary.srcR);
1221//.. addHRegUse(u, HRmWrite, i->Xin.FpBinary.dst);
1222//.. return;
1223//.. case Xin_FpLdSt:
1224//.. addRegUsage_X86AMode(u, i->Xin.FpLdSt.addr);
1225//.. addHRegUse(u, i->Xin.FpLdSt.isLoad ? HRmWrite : HRmRead,
1226//.. i->Xin.FpLdSt.reg);
1227//.. return;
1228//.. case Xin_FpLdStI:
1229//.. addRegUsage_X86AMode(u, i->Xin.FpLdStI.addr);
1230//.. addHRegUse(u, i->Xin.FpLdStI.isLoad ? HRmWrite : HRmRead,
1231//.. i->Xin.FpLdStI.reg);
1232//.. return;
1233//.. case Xin_Fp64to32:
1234//.. addHRegUse(u, HRmRead, i->Xin.Fp64to32.src);
1235//.. addHRegUse(u, HRmWrite, i->Xin.Fp64to32.dst);
1236//.. return;
1237//.. case Xin_FpCMov:
1238//.. addHRegUse(u, HRmRead, i->Xin.FpCMov.src);
1239//.. addHRegUse(u, HRmModify, i->Xin.FpCMov.dst);
1240//.. return;
1241//.. case Xin_FpLdStCW:
1242//.. addRegUsage_X86AMode(u, i->Xin.FpLdStCW.addr);
1243//.. return;
1244//.. case Xin_FpStSW_AX:
1245//.. addHRegUse(u, HRmWrite, hregX86_EAX());
1246//.. return;
1247//.. case Xin_FpCmp:
1248//.. addHRegUse(u, HRmRead, i->Xin.FpCmp.srcL);
1249//.. addHRegUse(u, HRmRead, i->Xin.FpCmp.srcR);
1250//.. addHRegUse(u, HRmWrite, i->Xin.FpCmp.dst);
1251//.. addHRegUse(u, HRmWrite, hregX86_EAX());
1252//.. return;
1253//.. case Xin_SseLdSt:
1254//.. addRegUsage_X86AMode(u, i->Xin.SseLdSt.addr);
1255//.. addHRegUse(u, i->Xin.SseLdSt.isLoad ? HRmWrite : HRmRead,
1256//.. i->Xin.SseLdSt.reg);
1257//.. return;
1258//.. case Xin_SseLdzLO:
1259//.. addRegUsage_X86AMode(u, i->Xin.SseLdzLO.addr);
1260//.. addHRegUse(u, HRmWrite, i->Xin.SseLdzLO.reg);
1261//.. return;
1262//.. case Xin_SseConst:
1263//.. addHRegUse(u, HRmWrite, i->Xin.SseConst.dst);
1264//.. return;
1265//.. case Xin_Sse32Fx4:
1266//.. vassert(i->Xin.Sse32Fx4.op != Xsse_MOV);
1267//.. unary = i->Xin.Sse32Fx4.op == Xsse_RCPF
1268//.. || i->Xin.Sse32Fx4.op == Xsse_RSQRTF
1269//.. || i->Xin.Sse32Fx4.op == Xsse_SQRTF;
1270//.. addHRegUse(u, HRmRead, i->Xin.Sse32Fx4.src);
1271//.. addHRegUse(u, unary ? HRmWrite : HRmModify,
1272//.. i->Xin.Sse32Fx4.dst);
1273//.. return;
1274//.. case Xin_Sse32FLo:
1275//.. vassert(i->Xin.Sse32FLo.op != Xsse_MOV);
1276//.. unary = i->Xin.Sse32FLo.op == Xsse_RCPF
1277//.. || i->Xin.Sse32FLo.op == Xsse_RSQRTF
1278//.. || i->Xin.Sse32FLo.op == Xsse_SQRTF;
1279//.. addHRegUse(u, HRmRead, i->Xin.Sse32FLo.src);
1280//.. addHRegUse(u, unary ? HRmWrite : HRmModify,
1281//.. i->Xin.Sse32FLo.dst);
1282//.. return;
1283//.. case Xin_Sse64Fx2:
1284//.. vassert(i->Xin.Sse64Fx2.op != Xsse_MOV);
1285//.. unary = i->Xin.Sse64Fx2.op == Xsse_RCPF
1286//.. || i->Xin.Sse64Fx2.op == Xsse_RSQRTF
1287//.. || i->Xin.Sse64Fx2.op == Xsse_SQRTF;
1288//.. addHRegUse(u, HRmRead, i->Xin.Sse64Fx2.src);
1289//.. addHRegUse(u, unary ? HRmWrite : HRmModify,
1290//.. i->Xin.Sse64Fx2.dst);
1291//.. return;
1292//.. case Xin_Sse64FLo:
1293//.. vassert(i->Xin.Sse64FLo.op != Xsse_MOV);
1294//.. unary = i->Xin.Sse64FLo.op == Xsse_RCPF
1295//.. || i->Xin.Sse64FLo.op == Xsse_RSQRTF
1296//.. || i->Xin.Sse64FLo.op == Xsse_SQRTF;
1297//.. addHRegUse(u, HRmRead, i->Xin.Sse64FLo.src);
1298//.. addHRegUse(u, unary ? HRmWrite : HRmModify,
1299//.. i->Xin.Sse64FLo.dst);
1300//.. return;
1301//.. case Xin_SseReRg:
1302//.. if (i->Xin.SseReRg.op == Xsse_XOR
1303//.. && i->Xin.SseReRg.src == i->Xin.SseReRg.dst) {
1304//.. /* reg-alloc needs to understand 'xor r,r' as a write of r */
1305//.. /* (as opposed to a rite of passage :-) */
1306//.. addHRegUse(u, HRmWrite, i->Xin.SseReRg.dst);
1307//.. } else {
1308//.. addHRegUse(u, HRmRead, i->Xin.SseReRg.src);
1309//.. addHRegUse(u, i->Xin.SseReRg.op == Xsse_MOV
1310//.. ? HRmWrite : HRmModify,
1311//.. i->Xin.SseReRg.dst);
1312//.. }
1313//.. return;
1314//.. case Xin_SseCMov:
1315//.. addHRegUse(u, HRmRead, i->Xin.SseCMov.src);
1316//.. addHRegUse(u, HRmModify, i->Xin.SseCMov.dst);
1317//.. return;
1318//.. case Xin_SseShuf:
1319//.. addHRegUse(u, HRmRead, i->Xin.SseShuf.src);
1320//.. addHRegUse(u, HRmWrite, i->Xin.SseShuf.dst);
1321//.. return;
cerion7f000af2005-02-22 20:36:49 +00001322
1323 case Pin_RdWrLR:
1324 addHRegUse(u, (i->Pin.RdWrLR.wrLR ? HRmRead : HRmWrite),
1325 i->Pin.RdWrLR.gpr);
1326 return;
1327
cerionb85e8bb2005-02-16 08:54:33 +00001328 default:
1329 ppPPC32Instr(i);
1330 vpanic("getRegUsage_PPC32Instr");
cerionbcf8c3e2005-02-04 16:17:07 +00001331 }
1332}
1333
cerioncd304492005-02-08 19:40:24 +00001334/* local helper */
1335static void mapReg(HRegRemap* m, HReg* r)
1336{
1337 *r = lookupHRegRemap(m, *r);
1338}
cerionbcf8c3e2005-02-04 16:17:07 +00001339
1340void mapRegs_PPC32Instr (HRegRemap* m, PPC32Instr* i)
1341{
1342 switch (i->tag) {
cerionb85e8bb2005-02-16 08:54:33 +00001343 case Pin_Alu32:
1344 mapReg(m, &i->Pin.Alu32.dst);
1345 mapReg(m, &i->Pin.Alu32.src1);
1346 mapRegs_PPC32RI(m, i->Pin.Alu32.src2);
1347 return;
cerion5e2527e2005-02-25 16:39:58 +00001348 case Pin_Sub32:
1349 mapReg(m, &i->Pin.Sub32.dst);
1350 mapRegs_PPC32RI(m, i->Pin.Sub32.src1);
1351 mapReg(m, &i->Pin.Sub32.src2);
1352 return;
cerionb85e8bb2005-02-16 08:54:33 +00001353 case Pin_Sh32:
1354 mapReg(m, &i->Pin.Sh32.dst);
1355 mapReg(m, &i->Pin.Sh32.src);
1356 mapRegs_PPC32RI(m, i->Pin.Sh32.shft);
1357 return;
cerionb85e8bb2005-02-16 08:54:33 +00001358 case Pin_Cmp32:
1359 mapReg(m, &i->Pin.Cmp32.src1);
1360 mapRegs_PPC32RI(m, i->Pin.Cmp32.src2);
1361 return;
1362 case Pin_Unary32:
1363 mapReg(m, &i->Pin.Unary32.dst);
1364 mapReg(m, &i->Pin.Unary32.src);
1365 return;
1366 case Pin_MulL:
1367 mapReg(m, &i->Pin.MulL.dst);
1368 mapReg(m, &i->Pin.MulL.src1);
1369 mapRegs_PPC32RI(m, i->Pin.MulL.src2);
1370 return;
1371 case Pin_Div:
1372 mapReg(m, &i->Pin.Div.dst);
1373 mapReg(m, &i->Pin.Div.src1);
cerion33aa6da2005-02-16 10:25:26 +00001374 mapReg(m, &i->Pin.Div.src2);
cerionb85e8bb2005-02-16 08:54:33 +00001375 return;
cerionbcf8c3e2005-02-04 16:17:07 +00001376//.. case Xin_Sh3232:
1377//.. mapReg(m, &i->Xin.Sh3232.src);
1378//.. mapReg(m, &i->Xin.Sh3232.dst);
1379//.. return;
1380//.. case Xin_Push:
1381//.. mapRegs_X86RMI(m, i->Xin.Push.src);
1382//.. return;
cerionb85e8bb2005-02-16 08:54:33 +00001383 case Pin_Call:
1384 return;
1385 case Pin_Goto:
1386 mapRegs_PPC32RI(m, i->Pin.Goto.dst);
1387 return;
1388 case Pin_CMov32:
1389 mapRegs_PPC32RI(m, i->Pin.CMov32.src);
1390 mapReg(m, &i->Pin.CMov32.dst);
1391 return;
cerion7cf8e4e2005-02-16 16:08:17 +00001392 case Pin_Load:
1393 mapRegs_PPC32AMode(m, i->Pin.Load.src);
1394 mapReg(m, &i->Pin.Load.dst);
cerionb85e8bb2005-02-16 08:54:33 +00001395 return;
1396 case Pin_Store:
1397 mapReg(m, &i->Pin.Store.src);
1398 mapRegs_PPC32AMode(m, i->Pin.Store.dst);
1399 return;
1400 case Pin_Set32:
1401 mapReg(m, &i->Pin.Set32.dst);
1402 return;
cerionbcf8c3e2005-02-04 16:17:07 +00001403//.. case Xin_Bsfr32:
1404//.. mapReg(m, &i->Xin.Bsfr32.src);
1405//.. mapReg(m, &i->Xin.Bsfr32.dst);
1406//.. return;
cerionb85e8bb2005-02-16 08:54:33 +00001407 case Pin_MFence:
1408 return;
cerionbcf8c3e2005-02-04 16:17:07 +00001409//.. case Xin_FpUnary:
1410//.. mapReg(m, &i->Xin.FpUnary.src);
1411//.. mapReg(m, &i->Xin.FpUnary.dst);
1412//.. return;
1413//.. case Xin_FpBinary:
1414//.. mapReg(m, &i->Xin.FpBinary.srcL);
1415//.. mapReg(m, &i->Xin.FpBinary.srcR);
1416//.. mapReg(m, &i->Xin.FpBinary.dst);
1417//.. return;
1418//.. case Xin_FpLdSt:
1419//.. mapRegs_X86AMode(m, i->Xin.FpLdSt.addr);
1420//.. mapReg(m, &i->Xin.FpLdSt.reg);
1421//.. return;
1422//.. case Xin_FpLdStI:
1423//.. mapRegs_X86AMode(m, i->Xin.FpLdStI.addr);
1424//.. mapReg(m, &i->Xin.FpLdStI.reg);
1425//.. return;
1426//.. case Xin_Fp64to32:
1427//.. mapReg(m, &i->Xin.Fp64to32.src);
1428//.. mapReg(m, &i->Xin.Fp64to32.dst);
1429//.. return;
1430//.. case Xin_FpCMov:
1431//.. mapReg(m, &i->Xin.FpCMov.src);
1432//.. mapReg(m, &i->Xin.FpCMov.dst);
1433//.. return;
1434//.. case Xin_FpLdStCW:
1435//.. mapRegs_X86AMode(m, i->Xin.FpLdStCW.addr);
1436//.. return;
1437//.. case Xin_FpStSW_AX:
1438//.. return;
1439//.. case Xin_FpCmp:
1440//.. mapReg(m, &i->Xin.FpCmp.srcL);
1441//.. mapReg(m, &i->Xin.FpCmp.srcR);
1442//.. mapReg(m, &i->Xin.FpCmp.dst);
1443//.. return;
1444//.. case Xin_SseConst:
1445//.. mapReg(m, &i->Xin.SseConst.dst);
1446//.. return;
1447//.. case Xin_SseLdSt:
1448//.. mapReg(m, &i->Xin.SseLdSt.reg);
1449//.. mapRegs_X86AMode(m, i->Xin.SseLdSt.addr);
1450//.. break;
1451//.. case Xin_SseLdzLO:
1452//.. mapReg(m, &i->Xin.SseLdzLO.reg);
1453//.. mapRegs_X86AMode(m, i->Xin.SseLdzLO.addr);
1454//.. break;
1455//.. case Xin_Sse32Fx4:
1456//.. mapReg(m, &i->Xin.Sse32Fx4.src);
1457//.. mapReg(m, &i->Xin.Sse32Fx4.dst);
1458//.. return;
1459//.. case Xin_Sse32FLo:
1460//.. mapReg(m, &i->Xin.Sse32FLo.src);
1461//.. mapReg(m, &i->Xin.Sse32FLo.dst);
1462//.. return;
1463//.. case Xin_Sse64Fx2:
1464//.. mapReg(m, &i->Xin.Sse64Fx2.src);
1465//.. mapReg(m, &i->Xin.Sse64Fx2.dst);
1466//.. return;
1467//.. case Xin_Sse64FLo:
1468//.. mapReg(m, &i->Xin.Sse64FLo.src);
1469//.. mapReg(m, &i->Xin.Sse64FLo.dst);
1470//.. return;
1471//.. case Xin_SseReRg:
1472//.. mapReg(m, &i->Xin.SseReRg.src);
1473//.. mapReg(m, &i->Xin.SseReRg.dst);
1474//.. return;
1475//.. case Xin_SseCMov:
1476//.. mapReg(m, &i->Xin.SseCMov.src);
1477//.. mapReg(m, &i->Xin.SseCMov.dst);
1478//.. return;
1479//.. case Xin_SseShuf:
1480//.. mapReg(m, &i->Xin.SseShuf.src);
1481//.. mapReg(m, &i->Xin.SseShuf.dst);
1482//.. return;
cerion7f000af2005-02-22 20:36:49 +00001483
1484 case Pin_RdWrLR:
1485 mapReg(m, &i->Pin.RdWrLR.gpr);
1486 return;
1487
cerionb85e8bb2005-02-16 08:54:33 +00001488 default:
1489 ppPPC32Instr(i);
1490 vpanic("mapRegs_PPC32Instr");
cerionbcf8c3e2005-02-04 16:17:07 +00001491 }
1492}
1493
1494/* Figure out if i represents a reg-reg move, and if so assign the
1495 source and destination to *src and *dst. If in doubt say No. Used
1496 by the register allocator to do move coalescing.
1497*/
1498Bool isMove_PPC32Instr ( PPC32Instr* i, HReg* src, HReg* dst )
1499{
cerionab9132d2005-02-15 15:46:59 +00001500 /* Moves between integer regs */
1501 if (i->tag == Pin_Alu32) {
1502 // or Rd,Rs,Rs == mr Rd,Rs
1503 if (i->Pin.Alu32.op != Palu_OR)
1504 return False;
1505 if (i->Pin.Alu32.src2->tag != Pri_Reg)
1506 return False;
1507 if (i->Pin.Alu32.src2->Pri.Reg.reg != i->Pin.Alu32.src1)
cerionb85e8bb2005-02-16 08:54:33 +00001508 return False;
cerionab9132d2005-02-15 15:46:59 +00001509 *src = i->Pin.Alu32.src1;
1510 *dst = i->Pin.Alu32.dst;
1511 return True;
1512 }
cerionbcf8c3e2005-02-04 16:17:07 +00001513//.. /* Moves between FP regs */
1514//.. if (i->tag == Xin_FpUnary) {
1515//.. if (i->Xin.FpUnary.op != Xfp_MOV)
1516//.. return False;
1517//.. *src = i->Xin.FpUnary.src;
1518//.. *dst = i->Xin.FpUnary.dst;
1519//.. return True;
1520//.. }
1521//.. if (i->tag == Xin_SseReRg) {
1522//.. if (i->Xin.SseReRg.op != Xsse_MOV)
1523//.. return False;
1524//.. *src = i->Xin.SseReRg.src;
1525//.. *dst = i->Xin.SseReRg.dst;
1526//.. return True;
1527//.. }
1528 return False;
1529}
1530
1531
cerione13bb312005-02-10 19:51:03 +00001532/* Generate ppc32 spill/reload instructions under the direction of the
cerionbcf8c3e2005-02-04 16:17:07 +00001533 register allocator. Note it's critical these don't write the
1534 condition codes. */
1535
1536PPC32Instr* genSpill_PPC32 ( HReg rreg, Int offsetB )
cerione13bb312005-02-10 19:51:03 +00001537{
1538 PPC32AMode* am;
1539 vassert(offsetB >= 0);
1540 vassert(!hregIsVirtual(rreg));
1541 am = PPC32AMode_IR(offsetB, GuestStatePtr);
cerionb85e8bb2005-02-16 08:54:33 +00001542
cerione13bb312005-02-10 19:51:03 +00001543 switch (hregClass(rreg)) {
cerionb85e8bb2005-02-16 08:54:33 +00001544 case HRcInt32:
1545 return PPC32Instr_Store( 4, am, rreg);
1546// case HRcFlt64:
1547// return PPC32Instr_FpLdSt ( False/*store*/, 8, rreg, am );
1548// case HRcVec128:
1549// return PPC32Instr_SseLdSt ( False/*store*/, rreg, am );
1550 default:
1551 ppHRegClass(hregClass(rreg));
1552 vpanic("genSpill_PPC32: unimplemented regclass");
cerione13bb312005-02-10 19:51:03 +00001553 }
cerionbcf8c3e2005-02-04 16:17:07 +00001554}
1555
1556PPC32Instr* genReload_PPC32 ( HReg rreg, Int offsetB )
cerione13bb312005-02-10 19:51:03 +00001557{
1558 PPC32AMode* am;
1559 vassert(offsetB >= 0);
1560 vassert(!hregIsVirtual(rreg));
1561 am = PPC32AMode_IR(offsetB, GuestStatePtr);
1562
1563 switch (hregClass(rreg)) {
cerionb85e8bb2005-02-16 08:54:33 +00001564 case HRcInt32:
cerion7cf8e4e2005-02-16 16:08:17 +00001565 return PPC32Instr_Load( 4, False, rreg, am );
cerionb85e8bb2005-02-16 08:54:33 +00001566// case HRcFlt64:
1567// return PPC32Instr_FpLdSt ( True/*load*/, 8, rreg, am );
1568// case HRcVec128:
1569// return PPC32Instr_SseLdSt ( True/*load*/, rreg, am );
1570 default:
1571 ppHRegClass(hregClass(rreg));
1572 vpanic("genReload_PPC32: unimplemented regclass");
cerione13bb312005-02-10 19:51:03 +00001573 }
cerionbcf8c3e2005-02-04 16:17:07 +00001574}
1575
1576
ceriond5e38382005-02-11 13:38:15 +00001577/* --------- The ppc32 assembler (bleh.) --------- */
cerioncd304492005-02-08 19:40:24 +00001578
cerioncd304492005-02-08 19:40:24 +00001579static UInt iregNo ( HReg r )
1580{
1581 UInt n;
1582 vassert(hregClass(r) == HRcInt32);
1583 vassert(!hregIsVirtual(r));
1584 n = hregNumber(r);
1585 vassert(n <= 32);
1586 return n;
1587}
cerioncd304492005-02-08 19:40:24 +00001588
cerionbcf8c3e2005-02-04 16:17:07 +00001589//.. static UInt fregNo ( HReg r )
1590//.. {
1591//.. UInt n;
1592//.. vassert(hregClass(r) == HRcFlt64);
1593//.. vassert(!hregIsVirtual(r));
1594//.. n = hregNumber(r);
1595//.. vassert(n <= 5);
1596//.. return n;
1597//.. }
cerioncd304492005-02-08 19:40:24 +00001598
cerionbcf8c3e2005-02-04 16:17:07 +00001599//.. static UInt vregNo ( HReg r )
1600//.. {
1601//.. UInt n;
1602//.. vassert(hregClass(r) == HRcVec128);
1603//.. vassert(!hregIsVirtual(r));
1604//.. n = hregNumber(r);
1605//.. vassert(n <= 7);
1606//.. return n;
1607//.. }
cerioncd304492005-02-08 19:40:24 +00001608
cerionbcf8c3e2005-02-04 16:17:07 +00001609//.. static UChar mkModRegRM ( UChar mod, UChar reg, UChar regmem )
1610//.. {
1611//.. return ((mod & 3) << 6) | ((reg & 7) << 3) | (regmem & 7);
1612//.. }
cerioncd304492005-02-08 19:40:24 +00001613
cerionbcf8c3e2005-02-04 16:17:07 +00001614//.. static UChar mkSIB ( Int shift, Int regindex, Int regbase )
1615//.. {
1616//.. return ((shift & 3) << 6) | ((regindex & 7) << 3) | (regbase & 7);
1617//.. }
cerioncd304492005-02-08 19:40:24 +00001618
cerionab9132d2005-02-15 15:46:59 +00001619/* Emit 32bit instruction big-endianly */
ceriond5e38382005-02-11 13:38:15 +00001620static UChar* emit32 ( UChar* p, UInt w32 )
1621{
ceriond5e38382005-02-11 13:38:15 +00001622 *p++ = (w32 >> 24) & 0x000000FF;
cerionc056a882005-02-11 13:55:41 +00001623 *p++ = (w32 >> 16) & 0x000000FF;
1624 *p++ = (w32 >> 8) & 0x000000FF;
1625 *p++ = (w32) & 0x000000FF;
ceriond5e38382005-02-11 13:38:15 +00001626 return p;
1627}
cerioncd304492005-02-08 19:40:24 +00001628
cerionbcf8c3e2005-02-04 16:17:07 +00001629//.. /* Does a sign-extend of the lowest 8 bits give
1630//.. the original number? */
1631//.. static Bool fits8bits ( UInt w32 )
1632//.. {
1633//.. Int i32 = (Int)w32;
1634//.. return i32 == ((i32 << 24) >> 24);
1635//.. }
cerioncd304492005-02-08 19:40:24 +00001636
1637
cerionbcf8c3e2005-02-04 16:17:07 +00001638//.. /* Forming mod-reg-rm bytes and scale-index-base bytes.
1639//..
1640//.. greg, 0(ereg) | ereg != ESP && ereg != EBP
1641//.. = 00 greg ereg
1642//..
1643//.. greg, d8(ereg) | ereg != ESP
1644//.. = 01 greg ereg, d8
1645//..
1646//.. greg, d32(ereg) | ereg != ESP
1647//.. = 10 greg ereg, d32
1648//..
1649//.. greg, d8(%esp) = 01 greg 100, 0x24, d8
1650//..
1651//.. -----------------------------------------------
1652//..
1653//.. greg, d8(base,index,scale)
1654//.. | index != ESP
1655//.. = 01 greg 100, scale index base, d8
1656//..
1657//.. greg, d32(base,index,scale)
1658//.. | index != ESP
1659//.. = 10 greg 100, scale index base, d32
1660//.. */
1661//.. static UChar* doAMode_M ( UChar* p, HReg greg, X86AMode* am )
1662//.. {
1663//.. if (am->tag == Xam_IR) {
1664//.. if (am->Xam.IR.imm == 0
1665//.. && am->Xam.IR.reg != hregX86_ESP()
1666//.. && am->Xam.IR.reg != hregX86_EBP() ) {
1667//.. *p++ = mkModRegRM(0, iregNo(greg), iregNo(am->Xam.IR.reg));
1668//.. return p;
1669//.. }
1670//.. if (fits8bits(am->Xam.IR.imm)
1671//.. && am->Xam.IR.reg != hregX86_ESP()) {
1672//.. *p++ = mkModRegRM(1, iregNo(greg), iregNo(am->Xam.IR.reg));
1673//.. *p++ = am->Xam.IR.imm & 0xFF;
1674//.. return p;
1675//.. }
1676//.. if (am->Xam.IR.reg != hregX86_ESP()) {
1677//.. *p++ = mkModRegRM(2, iregNo(greg), iregNo(am->Xam.IR.reg));
1678//.. p = emit32(p, am->Xam.IR.imm);
1679//.. return p;
1680//.. }
1681//.. if (am->Xam.IR.reg == hregX86_ESP()
1682//.. && fits8bits(am->Xam.IR.imm)) {
cerionb85e8bb2005-02-16 08:54:33 +00001683//.. *p++ = mkModRegRM(1, iregNo(greg), 4);
cerionbcf8c3e2005-02-04 16:17:07 +00001684//.. *p++ = 0x24;
1685//.. *p++ = am->Xam.IR.imm & 0xFF;
1686//.. return p;
1687//.. }
1688//.. ppX86AMode(am);
1689//.. vpanic("doAMode_M: can't emit amode IR");
1690//.. /*NOTREACHED*/
1691//.. }
1692//.. if (am->tag == Xam_IRRS) {
1693//.. if (fits8bits(am->Xam.IRRS.imm)
1694//.. && am->Xam.IRRS.index != hregX86_ESP()) {
1695//.. *p++ = mkModRegRM(1, iregNo(greg), 4);
1696//.. *p++ = mkSIB(am->Xam.IRRS.shift, am->Xam.IRRS.index,
1697//.. am->Xam.IRRS.base);
1698//.. *p++ = am->Xam.IRRS.imm & 0xFF;
1699//.. return p;
1700//.. }
1701//.. if (am->Xam.IRRS.index != hregX86_ESP()) {
1702//.. *p++ = mkModRegRM(2, iregNo(greg), 4);
1703//.. *p++ = mkSIB(am->Xam.IRRS.shift, am->Xam.IRRS.index,
1704//.. am->Xam.IRRS.base);
1705//.. p = emit32(p, am->Xam.IRRS.imm);
1706//.. return p;
1707//.. }
1708//.. ppX86AMode(am);
1709//.. vpanic("doAMode_M: can't emit amode IRRS");
1710//.. /*NOTREACHED*/
1711//.. }
1712//.. vpanic("doAMode_M: unknown amode");
1713//.. /*NOTREACHED*/
1714//.. }
cerioncd304492005-02-08 19:40:24 +00001715
1716
cerionbcf8c3e2005-02-04 16:17:07 +00001717//.. /* Emit a mod-reg-rm byte when the rm bit denotes a reg. */
1718//.. static UChar* doAMode_R ( UChar* p, HReg greg, HReg ereg )
1719//.. {
1720//.. *p++ = mkModRegRM(3, iregNo(greg), iregNo(ereg));
1721//.. return p;
1722//.. }
cerioncd304492005-02-08 19:40:24 +00001723
1724
cerionbcf8c3e2005-02-04 16:17:07 +00001725//.. /* Emit ffree %st(7) */
1726//.. static UChar* do_ffree_st7 ( UChar* p )
1727//.. {
1728//.. *p++ = 0xDD;
1729//.. *p++ = 0xC7;
1730//.. return p;
1731//.. }
cerioncd304492005-02-08 19:40:24 +00001732
cerionbcf8c3e2005-02-04 16:17:07 +00001733//.. /* Emit fstp %st(i), 1 <= i <= 7 */
1734//.. static UChar* do_fstp_st ( UChar* p, Int i )
1735//.. {
1736//.. vassert(1 <= i && i <= 7);
1737//.. *p++ = 0xDD;
1738//.. *p++ = 0xD8+i;
1739//.. return p;
1740//.. }
cerioncd304492005-02-08 19:40:24 +00001741
cerionbcf8c3e2005-02-04 16:17:07 +00001742//.. /* Emit fld %st(i), 0 <= i <= 6 */
1743//.. static UChar* do_fld_st ( UChar* p, Int i )
1744//.. {
1745//.. vassert(0 <= i && i <= 6);
1746//.. *p++ = 0xD9;
1747//.. *p++ = 0xC0+i;
1748//.. return p;
1749//.. }
cerioncd304492005-02-08 19:40:24 +00001750
cerionbcf8c3e2005-02-04 16:17:07 +00001751//.. /* Emit f<op> %st(0) */
1752//.. static UChar* do_fop1_st ( UChar* p, X86FpOp op )
1753//.. {
1754//.. switch (op) {
1755//.. case Xfp_NEG: *p++ = 0xD9; *p++ = 0xE0; break;
1756//.. case Xfp_ABS: *p++ = 0xD9; *p++ = 0xE1; break;
1757//.. case Xfp_SQRT: *p++ = 0xD9; *p++ = 0xFA; break;
1758//.. case Xfp_ROUND: *p++ = 0xD9; *p++ = 0xFC; break;
1759//.. case Xfp_SIN: *p++ = 0xD9; *p++ = 0xFE; break;
1760//.. case Xfp_COS: *p++ = 0xD9; *p++ = 0xFF; break;
1761//.. case Xfp_2XM1: *p++ = 0xD9; *p++ = 0xF0; break;
1762//.. case Xfp_MOV: break;
1763//.. case Xfp_TAN: p = do_ffree_st7(p); /* since fptan pushes 1.0 */
1764//.. *p++ = 0xD9; *p++ = 0xF2; /* fptan */
1765//.. *p++ = 0xD9; *p++ = 0xF7; /* fincstp */
1766//.. break;
1767//.. default: vpanic("do_fop1_st: unknown op");
1768//.. }
1769//.. return p;
1770//.. }
cerioncd304492005-02-08 19:40:24 +00001771
cerionbcf8c3e2005-02-04 16:17:07 +00001772//.. /* Emit f<op> %st(i), 1 <= i <= 5 */
1773//.. static UChar* do_fop2_st ( UChar* p, X86FpOp op, Int i )
1774//.. {
1775//.. # define fake(_n) mkHReg((_n), HRcInt32, False)
1776//.. Int subopc;
1777//.. switch (op) {
1778//.. case Xfp_ADD: subopc = 0; break;
1779//.. case Xfp_SUB: subopc = 4; break;
1780//.. case Xfp_MUL: subopc = 1; break;
1781//.. case Xfp_DIV: subopc = 6; break;
1782//.. default: vpanic("do_fop2_st: unknown op");
1783//.. }
1784//.. *p++ = 0xD8;
1785//.. p = doAMode_R(p, fake(subopc), fake(i));
1786//.. return p;
1787//.. # undef fake
1788//.. }
cerioncd304492005-02-08 19:40:24 +00001789
cerionbcf8c3e2005-02-04 16:17:07 +00001790//.. /* Push a 32-bit word on the stack. The word depends on tags[3:0];
1791//.. each byte is either 0x00 or 0xFF depending on the corresponding bit in tags[].
1792//.. */
1793//.. static UChar* push_word_from_tags ( UChar* p, UShort tags )
1794//.. {
1795//.. UInt w;
1796//.. vassert(0 == (tags & ~0xF));
1797//.. if (tags == 0) {
1798//.. /* pushl $0x00000000 */
1799//.. *p++ = 0x6A;
1800//.. *p++ = 0x00;
1801//.. }
1802//.. else
1803//.. /* pushl $0xFFFFFFFF */
1804//.. if (tags == 0xF) {
1805//.. *p++ = 0x6A;
1806//.. *p++ = 0xFF;
1807//.. } else {
1808//.. vassert(0); /* awaiting test case */
1809//.. w = 0;
1810//.. if (tags & 1) w |= 0x000000FF;
1811//.. if (tags & 2) w |= 0x0000FF00;
1812//.. if (tags & 4) w |= 0x00FF0000;
1813//.. if (tags & 8) w |= 0xFF000000;
1814//.. *p++ = 0x68;
1815//.. p = emit32(p, w);
1816//.. }
1817//.. return p;
1818//.. }
1819
ceriond5e38382005-02-11 13:38:15 +00001820static UChar* mkFormD ( UChar* p, UInt op1, UInt r1, UInt r2, UInt imm )
1821{
1822 vassert(op1 < 0x40);
1823 vassert(r1 < 0x20);
1824 vassert(r2 < 0x20);
cerion35663a72005-03-01 09:11:49 +00001825 vassert(imm < 0x10000 || imm >= 0xFFFF8000); // Pos|Neg
1826 imm = imm & 0xFFFF;
ceriond5e38382005-02-11 13:38:15 +00001827 UInt theInstr = ((op1<<26) | (r1<<21) | (r2<<16) | (imm));
1828 return emit32(p, theInstr);
1829}
1830
1831static UChar* mkFormX ( UChar* p, UInt op1, UInt r1, UInt r2,
cerionb85e8bb2005-02-16 08:54:33 +00001832 UInt r3, UInt op2, UInt b0 )
ceriond5e38382005-02-11 13:38:15 +00001833{
1834 vassert(op1 < 0x40);
1835 vassert(r1 < 0x20);
1836 vassert(r2 < 0x20);
1837 vassert(r3 < 0x20);
1838 vassert(op2 < 0x400);
1839 vassert(b0 < 0x2);
1840 UInt theInstr = ((op1<<26) | (r1<<21) | (r2<<16) |
cerionb85e8bb2005-02-16 08:54:33 +00001841 (r3<<11) | (op2<<1) | (b0));
ceriond5e38382005-02-11 13:38:15 +00001842 return emit32(p, theInstr);
1843}
1844
cerionab9132d2005-02-15 15:46:59 +00001845static UChar* mkFormXO ( UChar* p, UInt op1, UInt r1, UInt r2,
cerionb85e8bb2005-02-16 08:54:33 +00001846 UInt r3, UInt b10, UInt op2, UInt b0 )
cerionab9132d2005-02-15 15:46:59 +00001847{
1848 vassert(op1 < 0x40);
1849 vassert(r1 < 0x20);
1850 vassert(r2 < 0x20);
1851 vassert(r3 < 0x20);
1852 vassert(b10 < 0x2);
cerion33aa6da2005-02-16 10:25:26 +00001853 vassert(op2 < 0x200);
cerionab9132d2005-02-15 15:46:59 +00001854 vassert(b0 < 0x2);
1855 UInt theInstr = ((op1<<26) | (r1<<21) | (r2<<16) |
cerionb85e8bb2005-02-16 08:54:33 +00001856 (r3<<11) | (b10 << 10) | (op2<<1) | (b0));
cerionab9132d2005-02-15 15:46:59 +00001857 return emit32(p, theInstr);
1858}
ceriond5e38382005-02-11 13:38:15 +00001859
cerion33aa6da2005-02-16 10:25:26 +00001860static UChar* mkFormXL ( UChar* p, UInt op1, UInt f1, UInt f2,
1861 UInt f3, UInt op2, UInt b0 )
1862{
1863 vassert(op1 < 0x40);
1864 vassert(f1 < 0x20);
1865 vassert(f2 < 0x20);
1866 vassert(f3 < 0x20);
1867 vassert(op2 < 0x400);
1868 vassert(b0 < 0x2);
1869 UInt theInstr = ((op1<<26) | (f1<<21) | (f2<<16) |
1870 (f3<<11) | (op2<<1) | (b0));
1871 return emit32(p, theInstr);
1872}
1873
1874// Note: for split field ops, give mnemonic arg
1875static UChar* mkFormXFX ( UChar* p, UInt r1, UInt f2, UInt op2 )
1876{
1877 vassert(r1 < 0x20);
1878 vassert(f2 < 0x20);
1879 vassert(op2 < 0x400);
1880 switch (op2) {
1881 case 144: // mtcrf
1882 vassert(f2 < 0x100);
1883 f2 = f2 << 1;
1884 break;
1885 case 339: // mfspr
1886 case 371: // mftb
1887 case 467: // mtspr
1888 vassert(f2 < 0x400);
1889 f2 = ((f2>>5) & 0x1F) | ((f2 & 0x1F)<<5); // re-arrange split field
1890 break;
1891 default: vpanic("mkFormXFX(PPC32)");
1892 }
1893 UInt theInstr = ((31<<26) | (r1<<21) | (f2<<11) | (op2<<1));
1894 return emit32(p, theInstr);
1895}
1896
1897#if 0
1898// 'b'
1899static UChar* mkFormI ( UChar* p, UInt LI, UInt AA, UInt LK )
1900{
1901 vassert(LI < 0x1000000);
1902 vassert(AA < 0x2);
1903 vassert(LK < 0x2);
1904 UInt theInstr = ((18<<26) | (LI<<2) | (AA<<1) | (LK));
1905 return emit32(p, theInstr);
1906}
1907#endif
1908
1909// 'bc'
1910static UChar* mkFormB ( UChar* p, UInt BO, UInt BI,
1911 UInt BD, UInt AA, UInt LK )
1912{
1913 vassert(BO < 0x20);
1914 vassert(BI < 0x20);
1915 vassert(BD < 0x4000);
1916 vassert(AA < 0x2);
1917 vassert(LK < 0x2);
1918 UInt theInstr = ((16<<26) | (BO<<21) | (BI<<16) |
1919 (BD<<2) | (AA<<1) | (LK));
1920 return emit32(p, theInstr);
1921}
1922
cerion33aa6da2005-02-16 10:25:26 +00001923// rotates
1924static UChar* mkFormM ( UChar* p, UInt op1, UInt r1, UInt r2,
1925 UInt f3, UInt MB, UInt ME, UInt Rc )
1926{
1927 vassert(op1 < 0x40);
1928 vassert(r1 < 0x20);
1929 vassert(r2 < 0x20);
1930 vassert(f3 < 0x20);
1931 vassert(MB < 0x20);
1932 vassert(ME < 0x20);
1933 vassert(Rc < 0x2);
1934 UInt theInstr = ((op1<<26) | (r1<<21) | (r2<<16) |
1935 (f3<<11) | (MB<<6) | (ME<<1) | (Rc));
1936 return emit32(p, theInstr);
1937}
cerion33aa6da2005-02-16 10:25:26 +00001938
ceriond5e38382005-02-11 13:38:15 +00001939static UChar* doAMode_IR ( UChar* p, UInt op1, HReg hrSD, PPC32AMode* am )
1940{
1941 vassert(am->tag == Pam_IR);
1942 UInt rSD = iregNo(hrSD);
1943 UInt rA = iregNo(am->Pam.IR.base);
1944 UInt idx = am->Pam.IR.index;
1945 vassert(idx < 0x10000);
1946
1947 p = mkFormD(p, op1, rSD, rA, idx);
1948 return p;
1949}
1950
1951
1952static UChar* doAMode_RR ( UChar* p, UInt op1, UInt op2,
cerionb85e8bb2005-02-16 08:54:33 +00001953 HReg hrSD, PPC32AMode* am )
ceriond5e38382005-02-11 13:38:15 +00001954{
cerionb85e8bb2005-02-16 08:54:33 +00001955// vassert(hregClass(hrSD) == HRcInt32); // CAB: etc. worth doing this?
ceriond5e38382005-02-11 13:38:15 +00001956 vassert(am->tag == Pam_RR);
1957 UInt rSD = iregNo(hrSD);
1958 UInt rA = iregNo(am->Pam.RR.base);
1959 UInt rB = iregNo(am->Pam.RR.index);
1960
1961 p = mkFormX(p, op1, rSD, rA, rB, op2, 0);
1962 return p;
1963}
1964
cerione97e1062005-02-21 15:09:19 +00001965/* Load imm to r_dst */
1966static UChar* mkLoadImm ( UChar* p, UInt r_dst, UInt imm )
1967{
1968 vassert(r_dst < 0x20);
1969
cerion47c526b2005-03-03 05:17:08 +00001970 if (imm >= 0xFFFF8000 || imm <= 0x7FFF) { // sign-extendable from 16 bits?
cerione97e1062005-02-21 15:09:19 +00001971 // addi r_dst,0,imm => li r_dst,imm
1972 p = mkFormD(p, 14, r_dst, 0, imm);
1973 } else {
1974 // addis r_dst,r0,(imm>>16) => lis r_dst, (imm>>16)
1975 p = mkFormD(p, 15, r_dst, 0, (imm>>16));
1976 // ori r_dst, r_dst, (imm & 0xFFFF)
1977 p = mkFormD(p, 24, r_dst, r_dst, (imm & 0xFFFF));
1978 }
1979 return p;
1980}
1981
1982
1983/* Move r_dst to r_src */
1984static UChar* mkMoveReg ( UChar* p, UInt r_dst, UInt r_src )
1985{
1986 vassert(r_dst < 0x20);
1987 vassert(r_src < 0x20);
1988
1989 if (r_dst != r_src) {
1990 /* or r_dst, r_src, r_src */
1991 p = mkFormX(p, 31, r_src, r_dst, r_src, 444, 0 );
1992 }
1993 return p;
1994}
1995
ceriond5e38382005-02-11 13:38:15 +00001996
cerionbcf8c3e2005-02-04 16:17:07 +00001997/* Emit an instruction into buf and return the number of bytes used.
1998 Note that buf is not the insn's final place, and therefore it is
1999 imperative to emit position-independent code. */
2000
2001Int emit_PPC32Instr ( UChar* buf, Int nbuf, PPC32Instr* i )
2002{
2003//.. UInt irno, opc, opc_rr, subopc_imm, opc_imma, opc_cl, opc_imm, subopc;
2004//..
2005//.. UInt xtra;
2006 UChar* p = &buf[0];
cerion7cf8e4e2005-02-16 16:08:17 +00002007 UChar* ptmp = p;
2008 vassert(nbuf >= 32);
cerionbcf8c3e2005-02-04 16:17:07 +00002009//..
2010//.. /* Wrap an integer as a int register, for use assembling
2011//.. GrpN insns, in which the greg field is used as a sub-opcode
2012//.. and does not really contain a register. */
2013//.. # define fake(_n) mkHReg((_n), HRcInt32, False)
cerion2c49e032005-02-09 17:29:49 +00002014
cerion9a934a92005-02-21 16:44:03 +00002015// vex_printf("asm ");ppPPC32Instr(i); vex_printf("\n");
cerionbcf8c3e2005-02-04 16:17:07 +00002016
2017 switch (i->tag) {
2018
cerionab9132d2005-02-15 15:46:59 +00002019 case Pin_Alu32: {
cerion5e2527e2005-02-25 16:39:58 +00002020 UInt op1, op2, rR, immR;
2021 UInt rD = iregNo(i->Pin.Alu32.dst);
2022 UInt rL = iregNo(i->Pin.Alu32.src1);
cerion2c49e032005-02-09 17:29:49 +00002023
cerion5e2527e2005-02-25 16:39:58 +00002024 /* ADD/ADC/SBB/AND/OR/XOR */
cerionab9132d2005-02-15 15:46:59 +00002025 if (i->Pin.Alu32.src2->tag == Pri_Reg) {
2026 op1 = 31;
cerion5e2527e2005-02-25 16:39:58 +00002027 rR = iregNo(i->Pin.Alu32.src2->Pri.Reg.reg);
cerionab9132d2005-02-15 15:46:59 +00002028 switch (i->Pin.Alu32.op) {
2029 case Palu_ADD: op2 = 266; break;
cerionab9132d2005-02-15 15:46:59 +00002030 case Palu_AND: op2 = 28; break;
2031 case Palu_XOR: op2 = 316; break;
2032 case Palu_OR: op2 = 444; break;
2033// case Palu_ADC:
2034// case Palu_SBB:
2035 default:
2036 goto bad;
2037 }
2038
2039 switch (i->Pin.Alu32.op) {
cerion5e2527e2005-02-25 16:39:58 +00002040 case Palu_ADD:
2041 p = mkFormXO(p, op1, rD, rL, rR, 0, op2, 0);
cerionab9132d2005-02-15 15:46:59 +00002042 break;
cerionb85e8bb2005-02-16 08:54:33 +00002043 case Palu_AND: case Palu_XOR: case Palu_OR:
cerion5e2527e2005-02-25 16:39:58 +00002044 p = mkFormX(p, op1, rL, rD, rR, op2, 0);
cerionab9132d2005-02-15 15:46:59 +00002045 break;
2046// case Palu_ADC:
2047// case Palu_SBB:
2048 default:
2049 goto bad;
2050 }
cerionb85e8bb2005-02-16 08:54:33 +00002051 } else { // Pri_Imm:
cerion5e2527e2005-02-25 16:39:58 +00002052 immR = i->Pin.Alu32.src2->Pri.Imm.imm32;
cerionab9132d2005-02-15 15:46:59 +00002053 switch (i->Pin.Alu32.op) {
2054 case Palu_ADD: op1 = 14; break;
cerionab9132d2005-02-15 15:46:59 +00002055 case Palu_AND: op1 = 28; break;
2056 case Palu_XOR: op1 = 26; break;
2057 case Palu_OR: op1 = 24; break;
2058// case Palu_ADC:
2059// case Palu_SBB:
2060 default:
2061 goto bad;
2062 }
2063
2064 switch (i->Pin.Alu32.op) {
cerion5e2527e2005-02-25 16:39:58 +00002065 case Palu_ADD:
2066 p = mkFormD(p, op1, rD, rL, immR); // rD = rA...
cerionab9132d2005-02-15 15:46:59 +00002067 break;
cerionb85e8bb2005-02-16 08:54:33 +00002068 case Palu_AND: case Palu_XOR: case Palu_OR:
cerion5e2527e2005-02-25 16:39:58 +00002069 p = mkFormD(p, op1, rL, rD, immR); // rA = rS...
cerionab9132d2005-02-15 15:46:59 +00002070 break;
2071// case Palu_ADC:
2072// case Palu_SBB:
2073 default:
2074 goto bad;
2075 }
cerionab9132d2005-02-15 15:46:59 +00002076 }
cerionb85e8bb2005-02-16 08:54:33 +00002077 goto done;
cerionab9132d2005-02-15 15:46:59 +00002078 }
2079
cerion5e2527e2005-02-25 16:39:58 +00002080 case Pin_Sub32: {
2081 UInt rD = iregNo(i->Pin.Sub32.dst);
2082 UInt rR = iregNo(i->Pin.Sub32.src2);
2083 UInt rL, immL;
2084
2085 // Note argument swap: PPC32 only has sub-from instrs
2086 switch (i->Pin.Sub32.src1->tag) {
2087 case Pri_Reg:
2088 rL = iregNo(i->Pin.Sub32.src1->Pri.Reg.reg);
2089 // subf rD, rR, rL
2090 p = mkFormXO(p, 31, rD, rR, rL, 0, 40, 0);
2091 break;
2092 case Pri_Imm:
2093 immL = i->Pin.Sub32.src1->Pri.Imm.imm32;
2094 // subf rD, rR, immL
2095 p = mkFormD(p, 8, rD, rR, immL);
2096 break;
2097 default:
2098 goto bad;
2099 }
2100 goto done;
2101 }
2102
cerionab9132d2005-02-15 15:46:59 +00002103 case Pin_Sh32: {
cerion33aa6da2005-02-16 10:25:26 +00002104 UInt opc1 = 31, opc2, rB, sh;
cerionb85e8bb2005-02-16 08:54:33 +00002105 UInt op = i->Pin.Sh32.op;
cerionfbda9b72005-02-24 20:01:02 +00002106 UInt rS = iregNo(i->Pin.Sh32.src);
2107 UInt rA = iregNo(i->Pin.Sh32.dst);
cerion33aa6da2005-02-16 10:25:26 +00002108 PPC32RITag ri_tag = i->Pin.Sh32.shft->tag;
cerionab9132d2005-02-15 15:46:59 +00002109
cerionb85e8bb2005-02-16 08:54:33 +00002110 if ((op == Psh_SHL || op == Psh_SHR) && ri_tag == Pri_Imm)
2111 goto bad; // No imm versions of these
2112
2113 switch (op) {
cerion33aa6da2005-02-16 10:25:26 +00002114 case Psh_SHL: opc2 = 24; break;
2115 case Psh_SHR: opc2 = 536; break;
2116 case Psh_SAR: opc2 = (ri_tag == Pri_Reg) ? 792 : 824; break;
cerionab9132d2005-02-15 15:46:59 +00002117 default: goto bad;
2118 }
2119
cerionab9132d2005-02-15 15:46:59 +00002120 switch (i->Pin.Sh32.shft->tag) {
2121 case Pri_Reg:
cerion33aa6da2005-02-16 10:25:26 +00002122 rB = iregNo(i->Pin.Sh32.shft->Pri.Reg.reg);
2123 p = mkFormX(p, opc1, rS, rA, rB, opc2, 0);
cerionb85e8bb2005-02-16 08:54:33 +00002124 break;
cerionab9132d2005-02-15 15:46:59 +00002125 case Pri_Imm:
cerion33aa6da2005-02-16 10:25:26 +00002126 sh = i->Pin.Sh32.shft->Pri.Imm.imm32;
2127 p = mkFormX(p, opc1, rS, rA, sh, opc2, 0);
cerionb85e8bb2005-02-16 08:54:33 +00002128 break;
cerionab9132d2005-02-15 15:46:59 +00002129 default:
2130 goto bad;
2131 }
cerionb85e8bb2005-02-16 08:54:33 +00002132 goto done;
cerionab9132d2005-02-15 15:46:59 +00002133 }
cerion2c49e032005-02-09 17:29:49 +00002134
cerion98411db2005-02-16 14:14:49 +00002135 case Pin_Cmp32: {
2136 UInt opc1, opc2=0;
2137 UInt op = i->Pin.Cmp32.op;
cerione97e1062005-02-21 15:09:19 +00002138 UInt fld1 = (7 - i->Pin.Cmp32.crfD) << 2;
cerion98411db2005-02-16 14:14:49 +00002139 UInt r1 = iregNo(i->Pin.Cmp32.src1);
2140 UInt r2, imm;
cerionab9132d2005-02-15 15:46:59 +00002141
cerion98411db2005-02-16 14:14:49 +00002142 switch (i->Pin.Cmp32.src2->tag) {
2143 case Pri_Imm:
2144 opc1 = (op == Pcmp_U) ? 10 : 11;
2145 imm = i->Pin.Cmp32.src2->Pri.Imm.imm32;
2146 p = mkFormD(p, opc1, fld1, r1, imm);
2147 break;
2148 case Pri_Reg:
2149 opc1 = 31;
2150 opc2 = (op == Pcmp_U) ? 32 : 0;
2151 r2 = iregNo(i->Pin.Cmp32.src2->Pri.Reg.reg);
2152 p = mkFormX(p, opc1, fld1, r1, r2, opc2, 0);
2153 break;
2154 default: goto bad;
2155 }
2156 goto done;
2157 }
cerionb536af92005-02-10 15:03:19 +00002158
cerion98411db2005-02-16 14:14:49 +00002159 case Pin_Unary32: {
2160 UInt r_dst = iregNo(i->Pin.Unary32.dst);
2161 UInt r_src = iregNo(i->Pin.Unary32.src);
2162
2163 switch (i->Pin.Unary32.op) {
2164 case Pun_NOT: // nor r_dst,r_src,r_src
2165 p = mkFormX(p, 31, r_src, r_dst, r_src, 124, 0);
2166 break;
2167 case Pun_NEG: // neg r_dst,r_src
2168 p = mkFormXO(p, 31, r_dst, r_src, 0, 0, 104, 0);
2169 break;
2170 case Pun_CLZ: // cntlzw r_dst, r_src
2171 p = mkFormX(p, 31, r_dst, r_src, 0, 26, 0);
2172 break;
2173 default: goto bad;
2174 }
2175 goto done;
2176 }
2177
2178 case Pin_MulL: {
2179 Bool syned = i->Pin.MulL.syned;
2180 UInt r_dst = iregNo(i->Pin.MulL.dst);
2181 UInt r_src1 = iregNo(i->Pin.MulL.src1);
2182 UInt r_src2, imm;
2183
2184 switch (i->Pin.MulL.word) {
2185 case 0: // multiply low word
2186 switch (i->Pin.MulL.src2->tag) {
2187 case Pri_Reg:
2188 // mullw r_dst,r_src1,r_src2
2189 // sign makes no difference.
2190 r_src2 = iregNo(i->Pin.MulL.src2->Pri.Reg.reg);
2191 p = mkFormXO(p, 31, r_dst, r_src1, r_src2, 0, 235, 0);
2192 break;
2193 case Pri_Imm:
2194 // mulli r_dst,r_src,imm
2195 vassert(syned == True); // always signed
2196 imm = i->Pin.MulL.src2->Pri.Imm.imm32;
2197 p = mkFormD(p, 07, r_dst, r_src1, imm);
2198 break;
2199 default:
2200 goto bad;
2201 }
2202 break;
2203 case 1: // multiply high word
2204 vassert(i->Pin.MulL.src2->tag == Pri_Reg);
2205 r_src2 = iregNo(i->Pin.MulL.src2->Pri.Reg.reg);
2206 if (syned == True) {
2207 // mulhw r_dst,r_src1,r_src2
2208 p = mkFormXO(p, 31, r_dst, r_src1, r_src2, 0, 75, 0);
2209 } else {
2210 // mulhwu r_dst,r_src1,r_src2
2211 p = mkFormXO(p, 31, r_dst, r_src1, r_src2, 0, 11, 0);
2212 }
2213 break;
2214 default:
2215 goto bad;
2216 }
2217 goto done;
2218 }
cerion2c49e032005-02-09 17:29:49 +00002219
cerionfd0b87f2005-02-16 14:43:14 +00002220 case Pin_Div: {
2221 Bool syned = i->Pin.MulL.syned;
2222 UInt r_dst = iregNo(i->Pin.Div.dst);
2223 UInt r_src1 = iregNo(i->Pin.Div.src1);
2224 UInt r_src2 = iregNo(i->Pin.Div.src2);
2225
2226 if (syned == True) {
2227 // divw r_dst,r_src1,r_src2
2228 p = mkFormXO(p, 31, r_dst, r_src1, r_src2, 0, 491, 0);
2229 } else {
2230 // divwu r_dst,r_src1,r_src2
2231 p = mkFormXO(p, 31, r_dst, r_src1, r_src2, 0, 459, 0);
2232 }
2233 goto done;
2234 }
cerion2c49e032005-02-09 17:29:49 +00002235
cerionbcf8c3e2005-02-04 16:17:07 +00002236//.. case Xin_Sh3232:
2237//.. vassert(i->Xin.Sh3232.op == Xsh_SHL || i->Xin.Sh3232.op == Xsh_SHR);
2238//.. if (i->Xin.Sh3232.amt == 0) {
2239//.. /* shldl/shrdl by %cl */
2240//.. *p++ = 0x0F;
2241//.. if (i->Xin.Sh3232.op == Xsh_SHL) {
2242//.. *p++ = 0xA5;
2243//.. } else {
2244//.. *p++ = 0xAD;
2245//.. }
2246//.. p = doAMode_R(p, i->Xin.Sh3232.src, i->Xin.Sh3232.dst);
2247//.. goto done;
2248//.. }
2249//.. break;
cerion2c49e032005-02-09 17:29:49 +00002250
cerionbcf8c3e2005-02-04 16:17:07 +00002251//.. case Xin_Push:
2252//.. switch (i->Xin.Push.src->tag) {
2253//.. case Xrmi_Mem:
2254//.. *p++ = 0xFF;
2255//.. p = doAMode_M(p, fake(6), i->Xin.Push.src->Xrmi.Mem.am);
2256//.. goto done;
2257//.. case Xrmi_Imm:
2258//.. *p++ = 0x68;
2259//.. p = emit32(p, i->Xin.Push.src->Xrmi.Imm.imm32);
2260//.. goto done;
2261//.. case Xrmi_Reg:
2262//.. *p++ = 0x50 + iregNo(i->Xin.Push.src->Xrmi.Reg.reg);
2263//.. goto done;
2264//.. default:
2265//.. goto bad;
2266//.. }
cerion2c49e032005-02-09 17:29:49 +00002267
cerion33aa6da2005-02-16 10:25:26 +00002268 case Pin_Call: {
cerion7cf8e4e2005-02-16 16:08:17 +00002269 PPC32CondCode cond = i->Pin.Call.cond;
ceriona56e9cc2005-02-16 18:08:25 +00002270 UInt r_dst = 12;
2271 /* As per detailed comment for Pin_Call in
cerionab9132d2005-02-15 15:46:59 +00002272 getRegUsage_PPC32Instr above, %r12 is used as an address
2273 temporary. */
ceriona56e9cc2005-02-16 18:08:25 +00002274
cerionab9132d2005-02-15 15:46:59 +00002275 /* jump over the following two insns if the condition does not
2276 hold */
cerione97e1062005-02-21 15:09:19 +00002277 if (cond.test != Pct_ALWAYS) {
2278 /* don't know how many bytes to jump over yet...
2279 make space for a jump instruction and fill in later. */
2280 ptmp = p; /* fill in this bit later */
2281 p += 4;
cerionab9132d2005-02-15 15:46:59 +00002282 }
2283
cerione97e1062005-02-21 15:09:19 +00002284 /* load target to r_dst */
2285 p = mkLoadImm(p, r_dst, i->Pin.Call.target);
cerionab9132d2005-02-15 15:46:59 +00002286
ceriona56e9cc2005-02-16 18:08:25 +00002287 /* mtspr 9,r_dst => move r_dst to count register */
2288 p = mkFormXFX(p, r_dst, 9, 467);
cerion33aa6da2005-02-16 10:25:26 +00002289
cerion8c51ed42005-02-22 11:16:54 +00002290 /* bctrl => branch to count register (and save to lr) */
cerion33aa6da2005-02-16 10:25:26 +00002291 p = mkFormXL(p, 19, Pct_ALWAYS, 0, 0, 528, 1);
cerionab9132d2005-02-15 15:46:59 +00002292
cerione97e1062005-02-21 15:09:19 +00002293 /* Fix up the conditional jump, if there was one. */
2294 if (cond.test != Pct_ALWAYS) {
2295 Int delta = p - ptmp;
2296 vassert(delta >= 8 && delta <= 16);
2297
2298 /* bca !ct,cf,jump */
2299 mkFormB(ptmp, invertCondTest(cond.test), cond.flag, (delta>>2), 1, 0);
2300 }
2301
cerion33aa6da2005-02-16 10:25:26 +00002302/* CAB: Hmm...
2303 "When possible, independent instructions should separate the load
2304 of the Count Register from the branch to prevent pipeline stalls." */
cerion2c49e032005-02-09 17:29:49 +00002305
cerion33aa6da2005-02-16 10:25:26 +00002306 goto done;
2307 }
2308
2309 case Pin_Goto: {
2310 UInt magic_num = 0;
cerione97e1062005-02-21 15:09:19 +00002311 UChar r_return = 3; /* Put target addr into %r3 */
cerion33aa6da2005-02-16 10:25:26 +00002312 PPC32CondCode cond = i->Pin.Goto.cond;
2313 UInt imm;
2314
2315 /* First off, if this is conditional, create a conditional
2316 jump over the rest of it. */
2317 if (cond.test != Pct_ALWAYS) {
2318 /* jmp fwds if !condition */
cerione97e1062005-02-21 15:09:19 +00002319 /* don't know how many bytes to jump over yet...
2320 make space for a jump instruction and fill in later. */
cerion7cf8e4e2005-02-16 16:08:17 +00002321 ptmp = p; /* fill in this bit later */
cerione97e1062005-02-21 15:09:19 +00002322 p += 4;
cerion33aa6da2005-02-16 10:25:26 +00002323 }
2324
cerione97e1062005-02-21 15:09:19 +00002325 // cond succeeds...
2326
cerion33aa6da2005-02-16 10:25:26 +00002327 /* If a non-boring, set GuestStatePtr appropriately. */
cerion33aa6da2005-02-16 10:25:26 +00002328 switch (i->Pin.Goto.jk) {
2329 case Ijk_ClientReq: magic_num = VEX_TRC_JMP_CLIENTREQ; break;
2330 case Ijk_Syscall: magic_num = VEX_TRC_JMP_SYSCALL; break;
2331 case Ijk_Yield: magic_num = VEX_TRC_JMP_YIELD; break;
2332 case Ijk_EmWarn: magic_num = VEX_TRC_JMP_EMWARN; break;
2333 case Ijk_MapFail: magic_num = VEX_TRC_JMP_MAPFAIL; break;
2334 case Ijk_NoDecode: magic_num = VEX_TRC_JMP_NODECODE; break;
2335 case Ijk_Ret:
2336 case Ijk_Call:
2337 case Ijk_Boring:
2338 break;
2339 default:
2340 ppIRJumpKind(i->Pin.Goto.jk);
2341 vpanic("emit_PPC32Instr.Pin_Goto: unknown jump kind");
2342 }
2343 if (magic_num !=0) {
2344 vassert(magic_num < 0x10000);
cerione97e1062005-02-21 15:09:19 +00002345 /* addi r31,0,magic_num */
cerion33aa6da2005-02-16 10:25:26 +00002346 p = mkFormD(p, 14, 31, 0, magic_num);
2347 }
2348
cerione97e1062005-02-21 15:09:19 +00002349 /* Get the destination address into %r_return */
cerion33aa6da2005-02-16 10:25:26 +00002350 if (i->Pin.Goto.dst->tag == Pri_Imm) {
cerion33aa6da2005-02-16 10:25:26 +00002351 imm = i->Pin.Goto.dst->Pri.Imm.imm32;
cerione97e1062005-02-21 15:09:19 +00002352 p = mkLoadImm(p, r_return, imm);
cerion33aa6da2005-02-16 10:25:26 +00002353 } else {
2354 vassert(i->Pin.Goto.dst->tag == Pri_Reg);
cerione97e1062005-02-21 15:09:19 +00002355 UInt r_dst = iregNo(i->Pin.Goto.dst->Pri.Reg.reg);
2356 p = mkMoveReg(p, r_return, r_dst);
cerion33aa6da2005-02-16 10:25:26 +00002357 }
cerione97e1062005-02-21 15:09:19 +00002358
2359 /* blr */
cerion33aa6da2005-02-16 10:25:26 +00002360 p = mkFormXL(p, 19, Pct_ALWAYS, 0, 0, 16, 0);
cerion7cf8e4e2005-02-16 16:08:17 +00002361
2362 /* Fix up the conditional jump, if there was one. */
2363 if (cond.test != Pct_ALWAYS) {
2364 Int delta = p - ptmp;
cerione97e1062005-02-21 15:09:19 +00002365 vassert(delta >= 8 && delta <= 16);
2366 /* bc !ct,cf,delta */
2367 mkFormB(ptmp, invertCondTest(cond.test), cond.flag, (delta>>2), 0, 0);
cerion7cf8e4e2005-02-16 16:08:17 +00002368 }
cerion33aa6da2005-02-16 10:25:26 +00002369 goto done;
2370 }
cerionb536af92005-02-10 15:03:19 +00002371
cerion98411db2005-02-16 14:14:49 +00002372 case Pin_CMov32: {
2373 vassert(i->Pin.CMov32.cond.test != Pct_ALWAYS);
2374 UInt r_dst = iregNo(i->Pin.CMov32.dst);
2375 PPC32CondCode cond = i->Pin.CMov32.cond;
2376 UInt imm, r_src;
2377
cerione97e1062005-02-21 15:09:19 +00002378 /* branch (if cond fails) over move instrs */
2379 if (cond.test != Pct_ALWAYS) {
2380 /* don't know how many bytes to jump over yet...
2381 make space for a jump instruction and fill in later. */
2382 ptmp = p; /* fill in this bit later */
2383 p += 4;
2384 }
cerion98411db2005-02-16 14:14:49 +00002385
2386 // cond true: move src => dst
2387 switch (i->Pin.CMov32.src->tag) {
2388 case Pri_Imm:
2389 imm = i->Pin.CMov32.src->Pri.Imm.imm32;
cerione97e1062005-02-21 15:09:19 +00002390 p = mkLoadImm(p, r_dst, imm);
cerion98411db2005-02-16 14:14:49 +00002391 break;
2392 case Pri_Reg:
2393 r_src = iregNo(i->Pin.CMov32.src->Pri.Reg.reg);
cerione97e1062005-02-21 15:09:19 +00002394 p = mkMoveReg(p, r_dst, r_src);
cerion98411db2005-02-16 14:14:49 +00002395 break;
2396 default: goto bad;
2397 }
cerione97e1062005-02-21 15:09:19 +00002398
2399 /* Fix up the conditional jump, if there was one. */
2400 if (cond.test != Pct_ALWAYS) {
2401 Int delta = p - ptmp;
2402 vassert(delta >= 4 && delta <= 12);
2403 /* bc !ct,cf,delta */
2404 mkFormB(ptmp, invertCondTest(cond.test), cond.flag, (delta>>2), 0, 0);
2405 }
cerion98411db2005-02-16 14:14:49 +00002406 goto done;
2407 }
cerionb536af92005-02-10 15:03:19 +00002408
cerion7cf8e4e2005-02-16 16:08:17 +00002409 case Pin_Load: {
2410 Bool syned = i->Pin.Load.syned;
2411 UInt op1, op2, sz = i->Pin.Load.sz;
2412 switch (i->Pin.Load.src->tag) {
ceriond5e38382005-02-11 13:38:15 +00002413 case Pam_IR:
cerionab9132d2005-02-15 15:46:59 +00002414 if (sz == 2) { // the only signed load
cerion7cf8e4e2005-02-16 16:08:17 +00002415 op1 = (syned) ? 42: 40;
cerionab9132d2005-02-15 15:46:59 +00002416 } else {
cerion7cf8e4e2005-02-16 16:08:17 +00002417 vassert(syned == False);
cerionb85e8bb2005-02-16 08:54:33 +00002418 op1 = (sz == 1) ? 34 : 32; // 1:4
cerionab9132d2005-02-15 15:46:59 +00002419 }
cerion7cf8e4e2005-02-16 16:08:17 +00002420 p = doAMode_IR(p, op1, i->Pin.Load.dst, i->Pin.Load.src);
cerionab9132d2005-02-15 15:46:59 +00002421 goto done;
ceriond5e38382005-02-11 13:38:15 +00002422 case Pam_RR:
cerionab9132d2005-02-15 15:46:59 +00002423 op1 = 31;
2424 if (sz == 2) { // the only signed load
cerion7cf8e4e2005-02-16 16:08:17 +00002425 op2 = (syned) ? 343: 279;
cerionab9132d2005-02-15 15:46:59 +00002426 } else {
cerion7cf8e4e2005-02-16 16:08:17 +00002427 vassert(syned == False);
cerionb85e8bb2005-02-16 08:54:33 +00002428 op2 = (sz == 1) ? 87 : 23; // 1:4
cerionab9132d2005-02-15 15:46:59 +00002429 }
cerion7cf8e4e2005-02-16 16:08:17 +00002430 p = doAMode_RR(p, op1, op2, i->Pin.Load.dst, i->Pin.Load.src);
cerionab9132d2005-02-15 15:46:59 +00002431 goto done;
ceriond5e38382005-02-11 13:38:15 +00002432 default:
cerionab9132d2005-02-15 15:46:59 +00002433 goto bad;
ceriond5e38382005-02-11 13:38:15 +00002434 }
2435 }
cerionb536af92005-02-10 15:03:19 +00002436
cerionab9132d2005-02-15 15:46:59 +00002437 case Pin_Set32: {
2438 /* Make the destination register be 1 or 0, depending on whether
cerion98411db2005-02-16 14:14:49 +00002439 the relevant condition holds. Yay! - mfcr doesn't change CR. */
2440 UInt r_dst = iregNo(i->Pin.Set32.dst);
2441 PPC32CondCode cond = i->Pin.Set32.cond;
cerion7cf8e4e2005-02-16 16:08:17 +00002442 UInt rot_imm;
cerion98411db2005-02-16 14:14:49 +00002443 UInt r_tmp;
2444
2445 if (cond.test == Pct_ALWAYS) {
2446 // just load 1 to dst => li dst,1
2447 p = mkFormD(p, 14, r_dst, 0, 1);
cerionab9132d2005-02-15 15:46:59 +00002448 } else {
cerion7cf8e4e2005-02-16 16:08:17 +00002449 rot_imm = 1 + cond.flag;
ceriona56e9cc2005-02-16 18:08:25 +00002450 r_tmp = 0; // Not within scope of regalloc, so no need to declare.
cerion98411db2005-02-16 14:14:49 +00002451
2452 // r_tmp = CR => mfcr r_tmp
2453 p = mkFormX(p, 31, r_tmp, 0, 0, 19, 0);
2454
2455 // r_dst = flag (rotate left and mask)
cerion7cf8e4e2005-02-16 16:08:17 +00002456 // => rlwinm r_dst,r_tmp,rot_imm,31,31
cerione97e1062005-02-21 15:09:19 +00002457 p = mkFormM(p, 21, r_tmp, r_dst, rot_imm, 31, 31, 0);
cerion98411db2005-02-16 14:14:49 +00002458
2459 if (cond.test == Pct_FALSE) {
2460 // flip bit => xori rD,rD,1
2461 p = mkFormD(p, 26, r_dst, r_dst, 1);
cerionab9132d2005-02-15 15:46:59 +00002462 }
2463 }
2464 goto done;
cerionab9132d2005-02-15 15:46:59 +00002465 }
cerionb536af92005-02-10 15:03:19 +00002466
cerionbcf8c3e2005-02-04 16:17:07 +00002467//.. case Xin_Bsfr32:
2468//.. *p++ = 0x0F;
2469//.. if (i->Xin.Bsfr32.isFwds) {
2470//.. *p++ = 0xBC;
2471//.. } else {
2472//.. *p++ = 0xBD;
2473//.. }
2474//.. p = doAMode_R(p, i->Xin.Bsfr32.dst, i->Xin.Bsfr32.src);
2475//.. goto done;
cerionb536af92005-02-10 15:03:19 +00002476
cerion98411db2005-02-16 14:14:49 +00002477 case Pin_MFence: {
2478// CAB: choose...
2479#if 1 // sync (Synchronise, p616)
2480 p = mkFormX(p, 31, 0, 0, 0, 598, 0);
2481#else // isync (instruction synchronise, p467)
2482 p = mkFormXL(p, 19, 0, 0, 0, 150, 0);
2483#endif
2484 goto done;
2485 }
cerionb536af92005-02-10 15:03:19 +00002486
ceriond5e38382005-02-11 13:38:15 +00002487 case Pin_Store: {
2488 UInt op1, op2, sz = i->Pin.Store.sz;
2489 switch (i->Pin.Store.dst->tag) {
2490 case Pam_IR:
cerionb85e8bb2005-02-16 08:54:33 +00002491 op1 = (sz == 1) ? 38 : ((sz == 2) ? 44 : 36); // 1:2:4
cerionab9132d2005-02-15 15:46:59 +00002492 p = doAMode_IR(p, op1, i->Pin.Store.src, i->Pin.Store.dst);
2493 goto done;
ceriond5e38382005-02-11 13:38:15 +00002494 case Pam_RR:
cerionab9132d2005-02-15 15:46:59 +00002495 op1 = 31;
cerionb85e8bb2005-02-16 08:54:33 +00002496 op2 = (sz == 1) ? 215 : ((sz == 2) ? 407 : 151); // 1:2:4
cerionab9132d2005-02-15 15:46:59 +00002497 p = doAMode_RR(p, op1, op2, i->Pin.Store.src, i->Pin.Store.dst);
2498 goto done;
ceriond5e38382005-02-11 13:38:15 +00002499 default:
cerionab9132d2005-02-15 15:46:59 +00002500 goto bad;
ceriond5e38382005-02-11 13:38:15 +00002501 }
2502 goto done;
2503 }
cerionb536af92005-02-10 15:03:19 +00002504
cerionbcf8c3e2005-02-04 16:17:07 +00002505//.. case Xin_FpUnary:
2506//.. /* gop %src, %dst
2507//.. --> ffree %st7 ; fld %st(src) ; fop %st(0) ; fstp %st(1+dst)
2508//.. */
2509//.. p = do_ffree_st7(p);
2510//.. p = do_fld_st(p, 0+hregNumber(i->Xin.FpUnary.src));
2511//.. p = do_fop1_st(p, i->Xin.FpUnary.op);
2512//.. p = do_fstp_st(p, 1+hregNumber(i->Xin.FpUnary.dst));
2513//.. goto done;
2514//..
2515//.. case Xin_FpBinary:
2516//.. if (i->Xin.FpBinary.op == Xfp_YL2X
2517//.. || i->Xin.FpBinary.op == Xfp_YL2XP1) {
2518//.. /* Have to do this specially. */
2519//.. /* ffree %st7 ; fld %st(srcL) ;
2520//.. ffree %st7 ; fld %st(srcR+1) ; fyl2x{p1} ; fstp(1+dst) */
2521//.. p = do_ffree_st7(p);
2522//.. p = do_fld_st(p, 0+hregNumber(i->Xin.FpBinary.srcL));
2523//.. p = do_ffree_st7(p);
2524//.. p = do_fld_st(p, 1+hregNumber(i->Xin.FpBinary.srcR));
2525//.. *p++ = 0xD9;
2526//.. *p++ = i->Xin.FpBinary.op==Xfp_YL2X ? 0xF1 : 0xF9;
2527//.. p = do_fstp_st(p, 1+hregNumber(i->Xin.FpBinary.dst));
2528//.. goto done;
2529//.. }
2530//.. if (i->Xin.FpBinary.op == Xfp_ATAN) {
2531//.. /* Have to do this specially. */
2532//.. /* ffree %st7 ; fld %st(srcL) ;
2533//.. ffree %st7 ; fld %st(srcR+1) ; fpatan ; fstp(1+dst) */
2534//.. p = do_ffree_st7(p);
2535//.. p = do_fld_st(p, 0+hregNumber(i->Xin.FpBinary.srcL));
2536//.. p = do_ffree_st7(p);
2537//.. p = do_fld_st(p, 1+hregNumber(i->Xin.FpBinary.srcR));
2538//.. *p++ = 0xD9; *p++ = 0xF3;
2539//.. p = do_fstp_st(p, 1+hregNumber(i->Xin.FpBinary.dst));
2540//.. goto done;
2541//.. }
2542//.. if (i->Xin.FpBinary.op == Xfp_PREM
2543//.. || i->Xin.FpBinary.op == Xfp_PREM1
2544//.. || i->Xin.FpBinary.op == Xfp_SCALE) {
2545//.. /* Have to do this specially. */
2546//.. /* ffree %st7 ; fld %st(srcR) ;
2547//.. ffree %st7 ; fld %st(srcL+1) ; fprem/fprem1/fscale ; fstp(2+dst) ;
2548//.. fincstp ; ffree %st7 */
2549//.. p = do_ffree_st7(p);
2550//.. p = do_fld_st(p, 0+hregNumber(i->Xin.FpBinary.srcR));
2551//.. p = do_ffree_st7(p);
2552//.. p = do_fld_st(p, 1+hregNumber(i->Xin.FpBinary.srcL));
2553//.. *p++ = 0xD9;
2554//.. switch (i->Xin.FpBinary.op) {
2555//.. case Xfp_PREM: *p++ = 0xF8; break;
2556//.. case Xfp_PREM1: *p++ = 0xF5; break;
2557//.. case Xfp_SCALE: *p++ = 0xFD; break;
2558//.. default: vpanic("emitX86Instr(FpBinary,PREM/PREM1/SCALE)");
2559//.. }
2560//.. p = do_fstp_st(p, 2+hregNumber(i->Xin.FpBinary.dst));
2561//.. *p++ = 0xD9; *p++ = 0xF7;
2562//.. p = do_ffree_st7(p);
2563//.. goto done;
2564//.. }
2565//.. /* General case */
2566//.. /* gop %srcL, %srcR, %dst
2567//.. --> ffree %st7 ; fld %st(srcL) ; fop %st(1+srcR) ; fstp %st(1+dst)
2568//.. */
2569//.. p = do_ffree_st7(p);
2570//.. p = do_fld_st(p, 0+hregNumber(i->Xin.FpBinary.srcL));
2571//.. p = do_fop2_st(p, i->Xin.FpBinary.op,
2572//.. 1+hregNumber(i->Xin.FpBinary.srcR));
2573//.. p = do_fstp_st(p, 1+hregNumber(i->Xin.FpBinary.dst));
2574//.. goto done;
2575//..
2576//.. case Xin_FpLdSt:
2577//.. vassert(i->Xin.FpLdSt.sz == 4 || i->Xin.FpLdSt.sz == 8);
2578//.. if (i->Xin.FpLdSt.isLoad) {
2579//.. /* Load from memory into %fakeN.
2580//.. --> ffree %st(7) ; fld{s/l} amode ; fstp st(N+1)
2581//.. */
2582//.. p = do_ffree_st7(p);
2583//.. *p++ = i->Xin.FpLdSt.sz==4 ? 0xD9 : 0xDD;
cerionb85e8bb2005-02-16 08:54:33 +00002584//.. p = doAMode_M(p, fake(0)/*subopcode*/, i->Xin.FpLdSt.addr);
cerionbcf8c3e2005-02-04 16:17:07 +00002585//.. p = do_fstp_st(p, 1+hregNumber(i->Xin.FpLdSt.reg));
2586//.. goto done;
2587//.. } else {
2588//.. /* Store from %fakeN into memory.
2589//.. --> ffree %st(7) ; fld st(N) ; fstp{l|s} amode
cerionb85e8bb2005-02-16 08:54:33 +00002590//.. */
cerionbcf8c3e2005-02-04 16:17:07 +00002591//.. p = do_ffree_st7(p);
2592//.. p = do_fld_st(p, 0+hregNumber(i->Xin.FpLdSt.reg));
2593//.. *p++ = i->Xin.FpLdSt.sz==4 ? 0xD9 : 0xDD;
2594//.. p = doAMode_M(p, fake(3)/*subopcode*/, i->Xin.FpLdSt.addr);
2595//.. goto done;
2596//.. }
2597//.. break;
2598//..
2599//.. case Xin_FpLdStI:
2600//.. if (i->Xin.FpLdStI.isLoad) {
2601//.. /* Load from memory into %fakeN, converting from an int.
2602//.. --> ffree %st(7) ; fild{w/l/ll} amode ; fstp st(N+1)
2603//.. */
2604//.. switch (i->Xin.FpLdStI.sz) {
2605//.. case 8: opc = 0xDF; subopc_imm = 5; break;
2606//.. case 4: opc = 0xDB; subopc_imm = 0; break;
2607//.. case 2: vassert(0); opc = 0xDF; subopc_imm = 0; break;
2608//.. default: vpanic("emitX86Instr(Xin_FpLdStI-load)");
2609//.. }
2610//.. p = do_ffree_st7(p);
2611//.. *p++ = opc;
2612//.. p = doAMode_M(p, fake(subopc_imm)/*subopcode*/, i->Xin.FpLdStI.addr);
2613//.. p = do_fstp_st(p, 1+hregNumber(i->Xin.FpLdStI.reg));
2614//.. goto done;
2615//.. } else {
2616//.. /* Store from %fakeN into memory, converting to an int.
2617//.. --> ffree %st(7) ; fld st(N) ; fistp{w/l/ll} amode
cerionb85e8bb2005-02-16 08:54:33 +00002618//.. */
cerionbcf8c3e2005-02-04 16:17:07 +00002619//.. switch (i->Xin.FpLdStI.sz) {
2620//.. case 8: opc = 0xDF; subopc_imm = 7; break;
2621//.. case 4: opc = 0xDB; subopc_imm = 3; break;
2622//.. case 2: opc = 0xDF; subopc_imm = 3; break;
2623//.. default: vpanic("emitX86Instr(Xin_FpLdStI-store)");
2624//.. }
2625//.. p = do_ffree_st7(p);
2626//.. p = do_fld_st(p, 0+hregNumber(i->Xin.FpLdStI.reg));
2627//.. *p++ = opc;
2628//.. p = doAMode_M(p, fake(subopc_imm)/*subopcode*/, i->Xin.FpLdStI.addr);
2629//.. goto done;
2630//.. }
2631//.. break;
2632//..
2633//.. case Xin_Fp64to32:
2634//.. /* ffree %st7 ; fld %st(src) */
2635//.. p = do_ffree_st7(p);
2636//.. p = do_fld_st(p, 0+fregNo(i->Xin.Fp64to32.src));
2637//.. /* subl $4, %esp */
2638//.. *p++ = 0x83; *p++ = 0xEC; *p++ = 0x04;
2639//.. /* fstps (%esp) */
2640//.. *p++ = 0xD9; *p++ = 0x1C; *p++ = 0x24;
2641//.. /* flds (%esp) */
2642//.. *p++ = 0xD9; *p++ = 0x04; *p++ = 0x24;
2643//.. /* addl $4, %esp */
2644//.. *p++ = 0x83; *p++ = 0xC4; *p++ = 0x04;
2645//.. /* fstp %st(1+dst) */
2646//.. p = do_fstp_st(p, 1+fregNo(i->Xin.Fp64to32.dst));
2647//.. goto done;
2648//..
2649//.. case Xin_FpCMov:
2650//.. /* jmp fwds if !condition */
2651//.. *p++ = 0x70 + (i->Xin.FpCMov.cond ^ 1);
2652//.. *p++ = 0; /* # of bytes in the next bit, which we don't know yet */
2653//.. ptmp = p;
2654//..
2655//.. /* ffree %st7 ; fld %st(src) ; fstp %st(1+dst) */
2656//.. p = do_ffree_st7(p);
2657//.. p = do_fld_st(p, 0+fregNo(i->Xin.FpCMov.src));
2658//.. p = do_fstp_st(p, 1+fregNo(i->Xin.FpCMov.dst));
2659//..
2660//.. /* Fill in the jump offset. */
2661//.. *(ptmp-1) = p - ptmp;
2662//.. goto done;
2663//..
2664//.. case Xin_FpLdStCW:
2665//.. if (i->Xin.FpLdStCW.isLoad) {
2666//.. *p++ = 0xD9;
2667//.. p = doAMode_M(p, fake(5)/*subopcode*/, i->Xin.FpLdStCW.addr);
2668//.. } else {
2669//.. vassert(0);
2670//.. }
2671//.. goto done;
2672//..
2673//.. case Xin_FpStSW_AX:
2674//.. /* note, this emits fnstsw %ax, not fstsw %ax */
2675//.. *p++ = 0xDF;
2676//.. *p++ = 0xE0;
2677//.. goto done;
2678//..
2679//.. case Xin_FpCmp:
2680//.. /* gcmp %fL, %fR, %dst
2681//.. -> ffree %st7; fpush %fL ; fucomp %(fR+1) ;
2682//.. fnstsw %ax ; movl %eax, %dst
2683//.. */
2684//.. /* ffree %st7 */
2685//.. p = do_ffree_st7(p);
2686//.. /* fpush %fL */
2687//.. p = do_fld_st(p, 0+fregNo(i->Xin.FpCmp.srcL));
2688//.. /* fucomp %(fR+1) */
2689//.. *p++ = 0xDD;
2690//.. *p++ = 0xE8 + (7 & (1+fregNo(i->Xin.FpCmp.srcR)));
2691//.. /* fnstsw %ax */
2692//.. *p++ = 0xDF;
2693//.. *p++ = 0xE0;
2694//.. /* movl %eax, %dst */
2695//.. *p++ = 0x89;
2696//.. p = doAMode_R(p, hregX86_EAX(), i->Xin.FpCmp.dst);
2697//.. goto done;
2698//..
2699//.. case Xin_SseConst: {
2700//.. UShort con = i->Xin.SseConst.con;
2701//.. p = push_word_from_tags(p, (con >> 12) & 0xF);
2702//.. p = push_word_from_tags(p, (con >> 8) & 0xF);
2703//.. p = push_word_from_tags(p, (con >> 4) & 0xF);
2704//.. p = push_word_from_tags(p, con & 0xF);
2705//.. /* movl (%esp), %xmm-dst */
2706//.. *p++ = 0x0F;
2707//.. *p++ = 0x10;
2708//.. *p++ = 0x04 + 8 * (7 & vregNo(i->Xin.SseConst.dst));
2709//.. *p++ = 0x24;
2710//.. /* addl $16, %esp */
2711//.. *p++ = 0x83;
2712//.. *p++ = 0xC4;
2713//.. *p++ = 0x10;
2714//.. goto done;
2715//.. }
2716//..
2717//.. case Xin_SseLdSt:
2718//.. *p++ = 0x0F;
2719//.. *p++ = i->Xin.SseLdSt.isLoad ? 0x10 : 0x11;
2720//.. p = doAMode_M(p, fake(vregNo(i->Xin.SseLdSt.reg)), i->Xin.SseLdSt.addr);
2721//.. goto done;
2722//..
2723//.. case Xin_SseLdzLO:
2724//.. vassert(i->Xin.SseLdzLO.sz == 4 || i->Xin.SseLdzLO.sz == 8);
2725//.. /* movs[sd] amode, %xmm-dst */
2726//.. *p++ = i->Xin.SseLdzLO.sz==4 ? 0xF3 : 0xF2;
2727//.. *p++ = 0x0F;
2728//.. *p++ = 0x10;
2729//.. p = doAMode_M(p, fake(vregNo(i->Xin.SseLdzLO.reg)),
2730//.. i->Xin.SseLdzLO.addr);
2731//.. goto done;
2732//..
2733//.. case Xin_Sse32Fx4:
2734//.. xtra = 0;
2735//.. *p++ = 0x0F;
2736//.. switch (i->Xin.Sse32Fx4.op) {
2737//.. case Xsse_ADDF: *p++ = 0x58; break;
2738//.. case Xsse_DIVF: *p++ = 0x5E; break;
2739//.. case Xsse_MAXF: *p++ = 0x5F; break;
2740//.. case Xsse_MINF: *p++ = 0x5D; break;
2741//.. case Xsse_MULF: *p++ = 0x59; break;
2742//.. case Xsse_RCPF: *p++ = 0x53; break;
2743//.. case Xsse_RSQRTF: *p++ = 0x52; break;
2744//.. case Xsse_SQRTF: *p++ = 0x51; break;
2745//.. case Xsse_SUBF: *p++ = 0x5C; break;
2746//.. case Xsse_CMPEQF: *p++ = 0xC2; xtra = 0x100; break;
2747//.. case Xsse_CMPLTF: *p++ = 0xC2; xtra = 0x101; break;
2748//.. case Xsse_CMPLEF: *p++ = 0xC2; xtra = 0x102; break;
2749//.. default: goto bad;
2750//.. }
2751//.. p = doAMode_R(p, fake(vregNo(i->Xin.Sse32Fx4.dst)),
2752//.. fake(vregNo(i->Xin.Sse32Fx4.src)) );
2753//.. if (xtra & 0x100)
2754//.. *p++ = (UChar)(xtra & 0xFF);
2755//.. goto done;
2756//..
2757//.. case Xin_Sse64Fx2:
2758//.. xtra = 0;
2759//.. *p++ = 0x66;
2760//.. *p++ = 0x0F;
2761//.. switch (i->Xin.Sse64Fx2.op) {
2762//.. case Xsse_ADDF: *p++ = 0x58; break;
2763//.. case Xsse_DIVF: *p++ = 0x5E; break;
2764//.. case Xsse_MAXF: *p++ = 0x5F; break;
2765//.. case Xsse_MINF: *p++ = 0x5D; break;
2766//.. case Xsse_MULF: *p++ = 0x59; break;
2767//.. case Xsse_RCPF: *p++ = 0x53; break;
2768//.. case Xsse_RSQRTF: *p++ = 0x52; break;
2769//.. case Xsse_SQRTF: *p++ = 0x51; break;
2770//.. case Xsse_SUBF: *p++ = 0x5C; break;
2771//.. case Xsse_CMPEQF: *p++ = 0xC2; xtra = 0x100; break;
2772//.. case Xsse_CMPLTF: *p++ = 0xC2; xtra = 0x101; break;
2773//.. case Xsse_CMPLEF: *p++ = 0xC2; xtra = 0x102; break;
2774//.. default: goto bad;
2775//.. }
2776//.. p = doAMode_R(p, fake(vregNo(i->Xin.Sse64Fx2.dst)),
2777//.. fake(vregNo(i->Xin.Sse64Fx2.src)) );
2778//.. if (xtra & 0x100)
2779//.. *p++ = (UChar)(xtra & 0xFF);
2780//.. goto done;
2781//..
2782//.. case Xin_Sse32FLo:
2783//.. xtra = 0;
2784//.. *p++ = 0xF3;
2785//.. *p++ = 0x0F;
2786//.. switch (i->Xin.Sse32FLo.op) {
2787//.. case Xsse_ADDF: *p++ = 0x58; break;
2788//.. case Xsse_DIVF: *p++ = 0x5E; break;
2789//.. case Xsse_MAXF: *p++ = 0x5F; break;
2790//.. case Xsse_MINF: *p++ = 0x5D; break;
2791//.. case Xsse_MULF: *p++ = 0x59; break;
2792//.. case Xsse_RCPF: *p++ = 0x53; break;
2793//.. case Xsse_RSQRTF: *p++ = 0x52; break;
2794//.. case Xsse_SQRTF: *p++ = 0x51; break;
2795//.. case Xsse_SUBF: *p++ = 0x5C; break;
2796//.. case Xsse_CMPEQF: *p++ = 0xC2; xtra = 0x100; break;
2797//.. case Xsse_CMPLTF: *p++ = 0xC2; xtra = 0x101; break;
2798//.. case Xsse_CMPLEF: *p++ = 0xC2; xtra = 0x102; break;
2799//.. default: goto bad;
2800//.. }
2801//.. p = doAMode_R(p, fake(vregNo(i->Xin.Sse32FLo.dst)),
2802//.. fake(vregNo(i->Xin.Sse32FLo.src)) );
2803//.. if (xtra & 0x100)
2804//.. *p++ = (UChar)(xtra & 0xFF);
2805//.. goto done;
2806//..
2807//.. case Xin_Sse64FLo:
2808//.. xtra = 0;
2809//.. *p++ = 0xF2;
2810//.. *p++ = 0x0F;
2811//.. switch (i->Xin.Sse64FLo.op) {
2812//.. case Xsse_ADDF: *p++ = 0x58; break;
2813//.. case Xsse_DIVF: *p++ = 0x5E; break;
2814//.. case Xsse_MAXF: *p++ = 0x5F; break;
2815//.. case Xsse_MINF: *p++ = 0x5D; break;
2816//.. case Xsse_MULF: *p++ = 0x59; break;
2817//.. case Xsse_RCPF: *p++ = 0x53; break;
2818//.. case Xsse_RSQRTF: *p++ = 0x52; break;
2819//.. case Xsse_SQRTF: *p++ = 0x51; break;
2820//.. case Xsse_SUBF: *p++ = 0x5C; break;
2821//.. case Xsse_CMPEQF: *p++ = 0xC2; xtra = 0x100; break;
2822//.. case Xsse_CMPLTF: *p++ = 0xC2; xtra = 0x101; break;
2823//.. case Xsse_CMPLEF: *p++ = 0xC2; xtra = 0x102; break;
2824//.. default: goto bad;
2825//.. }
2826//.. p = doAMode_R(p, fake(vregNo(i->Xin.Sse64FLo.dst)),
2827//.. fake(vregNo(i->Xin.Sse64FLo.src)) );
2828//.. if (xtra & 0x100)
2829//.. *p++ = (UChar)(xtra & 0xFF);
2830//.. goto done;
2831//..
2832//.. case Xin_SseReRg:
2833//.. # define XX(_n) *p++ = (_n)
2834//.. switch (i->Xin.SseReRg.op) {
2835//.. case Xsse_MOV: /*movups*/ XX(0x0F); XX(0x10); break;
2836//.. case Xsse_OR: XX(0x0F); XX(0x56); break;
2837//.. case Xsse_XOR: XX(0x0F); XX(0x57); break;
2838//.. case Xsse_AND: XX(0x0F); XX(0x54); break;
2839//.. case Xsse_PACKSSD: XX(0x66); XX(0x0F); XX(0x6B); break;
2840//.. case Xsse_PACKSSW: XX(0x66); XX(0x0F); XX(0x63); break;
2841//.. case Xsse_PACKUSW: XX(0x66); XX(0x0F); XX(0x67); break;
2842//.. case Xsse_ADD8: XX(0x66); XX(0x0F); XX(0xFC); break;
2843//.. case Xsse_ADD16: XX(0x66); XX(0x0F); XX(0xFD); break;
2844//.. case Xsse_ADD32: XX(0x66); XX(0x0F); XX(0xFE); break;
2845//.. case Xsse_ADD64: XX(0x66); XX(0x0F); XX(0xD4); break;
2846//.. case Xsse_QADD8S: XX(0x66); XX(0x0F); XX(0xEC); break;
2847//.. case Xsse_QADD16S: XX(0x66); XX(0x0F); XX(0xED); break;
2848//.. case Xsse_QADD8U: XX(0x66); XX(0x0F); XX(0xDC); break;
2849//.. case Xsse_QADD16U: XX(0x66); XX(0x0F); XX(0xDD); break;
2850//.. case Xsse_AVG8U: XX(0x66); XX(0x0F); XX(0xE0); break;
2851//.. case Xsse_AVG16U: XX(0x66); XX(0x0F); XX(0xE3); break;
2852//.. case Xsse_CMPEQ8: XX(0x66); XX(0x0F); XX(0x74); break;
2853//.. case Xsse_CMPEQ16: XX(0x66); XX(0x0F); XX(0x75); break;
2854//.. case Xsse_CMPEQ32: XX(0x66); XX(0x0F); XX(0x76); break;
2855//.. case Xsse_CMPGT8S: XX(0x66); XX(0x0F); XX(0x64); break;
2856//.. case Xsse_CMPGT16S: XX(0x66); XX(0x0F); XX(0x65); break;
2857//.. case Xsse_CMPGT32S: XX(0x66); XX(0x0F); XX(0x66); break;
2858//.. case Xsse_MAX16S: XX(0x66); XX(0x0F); XX(0xEE); break;
2859//.. case Xsse_MAX8U: XX(0x66); XX(0x0F); XX(0xDE); break;
2860//.. case Xsse_MIN16S: XX(0x66); XX(0x0F); XX(0xEA); break;
2861//.. case Xsse_MIN8U: XX(0x66); XX(0x0F); XX(0xDA); break;
2862//.. case Xsse_MULHI16U: XX(0x66); XX(0x0F); XX(0xE4); break;
2863//.. case Xsse_MULHI16S: XX(0x66); XX(0x0F); XX(0xE5); break;
2864//.. case Xsse_MUL16: XX(0x66); XX(0x0F); XX(0xD5); break;
2865//.. case Xsse_SHL16: XX(0x66); XX(0x0F); XX(0xF1); break;
2866//.. case Xsse_SHL32: XX(0x66); XX(0x0F); XX(0xF2); break;
2867//.. case Xsse_SHL64: XX(0x66); XX(0x0F); XX(0xF3); break;
2868//.. case Xsse_SAR16: XX(0x66); XX(0x0F); XX(0xE1); break;
2869//.. case Xsse_SAR32: XX(0x66); XX(0x0F); XX(0xE2); break;
2870//.. case Xsse_SHR16: XX(0x66); XX(0x0F); XX(0xD1); break;
2871//.. case Xsse_SHR32: XX(0x66); XX(0x0F); XX(0xD2); break;
2872//.. case Xsse_SHR64: XX(0x66); XX(0x0F); XX(0xD3); break;
2873//.. case Xsse_SUB8: XX(0x66); XX(0x0F); XX(0xF8); break;
2874//.. case Xsse_SUB16: XX(0x66); XX(0x0F); XX(0xF9); break;
2875//.. case Xsse_SUB32: XX(0x66); XX(0x0F); XX(0xFA); break;
2876//.. case Xsse_SUB64: XX(0x66); XX(0x0F); XX(0xFB); break;
2877//.. case Xsse_QSUB8S: XX(0x66); XX(0x0F); XX(0xE8); break;
2878//.. case Xsse_QSUB16S: XX(0x66); XX(0x0F); XX(0xE9); break;
2879//.. case Xsse_QSUB8U: XX(0x66); XX(0x0F); XX(0xD8); break;
2880//.. case Xsse_QSUB16U: XX(0x66); XX(0x0F); XX(0xD9); break;
2881//.. case Xsse_UNPCKHB: XX(0x66); XX(0x0F); XX(0x68); break;
2882//.. case Xsse_UNPCKHW: XX(0x66); XX(0x0F); XX(0x69); break;
2883//.. case Xsse_UNPCKHD: XX(0x66); XX(0x0F); XX(0x6A); break;
2884//.. case Xsse_UNPCKHQ: XX(0x66); XX(0x0F); XX(0x6D); break;
2885//.. case Xsse_UNPCKLB: XX(0x66); XX(0x0F); XX(0x60); break;
2886//.. case Xsse_UNPCKLW: XX(0x66); XX(0x0F); XX(0x61); break;
2887//.. case Xsse_UNPCKLD: XX(0x66); XX(0x0F); XX(0x62); break;
2888//.. case Xsse_UNPCKLQ: XX(0x66); XX(0x0F); XX(0x6C); break;
2889//.. default: goto bad;
2890//.. }
2891//.. p = doAMode_R(p, fake(vregNo(i->Xin.SseReRg.dst)),
2892//.. fake(vregNo(i->Xin.SseReRg.src)) );
2893//.. # undef XX
2894//.. goto done;
2895//..
2896//.. case Xin_SseCMov:
2897//.. /* jmp fwds if !condition */
2898//.. *p++ = 0x70 + (i->Xin.SseCMov.cond ^ 1);
2899//.. *p++ = 0; /* # of bytes in the next bit, which we don't know yet */
2900//.. ptmp = p;
2901//..
2902//.. /* movaps %src, %dst */
2903//.. *p++ = 0x0F;
2904//.. *p++ = 0x28;
2905//.. p = doAMode_R(p, fake(vregNo(i->Xin.SseCMov.dst)),
2906//.. fake(vregNo(i->Xin.SseCMov.src)) );
2907//..
2908//.. /* Fill in the jump offset. */
2909//.. *(ptmp-1) = p - ptmp;
2910//.. goto done;
2911//..
2912//.. case Xin_SseShuf:
2913//.. *p++ = 0x66;
2914//.. *p++ = 0x0F;
2915//.. *p++ = 0x70;
2916//.. p = doAMode_R(p, fake(vregNo(i->Xin.SseShuf.dst)),
2917//.. fake(vregNo(i->Xin.SseShuf.src)) );
2918//.. *p++ = (UChar)(i->Xin.SseShuf.order);
2919//.. goto done;
2920
cerion7f000af2005-02-22 20:36:49 +00002921 case Pin_RdWrLR: {
2922 UInt reg = iregNo(i->Pin.RdWrLR.gpr);
2923 /* wrLR==True ? mtlr r4 : mflr r4 */
2924 p = mkFormXFX(p, reg, 8, (i->Pin.RdWrLR.wrLR==True) ? 467 : 339);
2925 goto done;
2926 }
2927
cerionbcf8c3e2005-02-04 16:17:07 +00002928 default:
2929 goto bad;
2930 }
2931
2932 bad:
cerionab9132d2005-02-15 15:46:59 +00002933 vex_printf("\n=> ");
cerionbcf8c3e2005-02-04 16:17:07 +00002934 ppPPC32Instr(i);
2935 vpanic("emit_PPC32Instr");
2936 /*NOTREACHED*/
2937
cerionbcf8c3e2005-02-04 16:17:07 +00002938 done:
2939 vassert(p - &buf[0] <= 32);
2940 return p - &buf[0];
2941
2942# undef fake
2943}
2944
2945/*---------------------------------------------------------------*/
2946/*--- end host-ppc32/hdefs.c ---*/
2947/*---------------------------------------------------------------*/