blob: 32660246edc06704c685ea40a3fb51ca433e5046 [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]
51 = { "%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" };
55 /* 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)) {
62 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");
74 }
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));
cerionb4a632a2005-02-09 21:01:22 +0000147 // GPR0 = reserved
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{
219 switch (cond) {
220 case Pcc_O: return "o";
221 case Pcc_NO: return "no";
222 case Pcc_B: return "b";
223 case Pcc_NB: return "nb";
224 case Pcc_Z: return "z";
225 case Pcc_NZ: return "nz";
226 case Pcc_BE: return "be";
227 case Pcc_NBE: return "nbe";
228 case Pcc_S: return "s";
229 case Pcc_NS: return "ns";
230 case Pcc_P: return "p";
231 case Pcc_NP: return "np";
232 case Pcc_L: return "l";
233 case Pcc_NL: return "nl";
234 case Pcc_LE: return "le";
235 case Pcc_NLE: return "nle";
236 case Pcc_ALWAYS: return "ALWAYS";
237 default: vpanic("ppPPC32CondCode");
238 }
cerionbcf8c3e2005-02-04 16:17:07 +0000239}
240
241
cerioncd304492005-02-08 19:40:24 +0000242/* --------- PPCAMode: memory address expressions. --------- */
243
244PPC32AMode* PPC32AMode_IR ( UInt idx, HReg base ) {
cerion3c0b12b2005-02-10 11:39:43 +0000245 vassert(idx < 0x10000);
cerioncd304492005-02-08 19:40:24 +0000246 PPC32AMode* am = LibVEX_Alloc(sizeof(PPC32AMode));
247 am->tag = Pam_IR;
248 am->Pam.IR.base = base;
249 am->Pam.IR.index = idx;
250 return am;
251}
252PPC32AMode* PPC32AMode_RR ( HReg idx, HReg base ) {
253 PPC32AMode* am = LibVEX_Alloc(sizeof(PPC32AMode));
254 am->tag = Pam_RR;
255 am->Pam.RR.base = base;
256 am->Pam.RR.index = idx;
257 return am;
258}
259
260PPC32AMode* dopyPPC32AMode ( PPC32AMode* am ) {
261 switch (am->tag) {
262 case Pam_IR:
263 return PPC32AMode_IR( am->Pam.IR.index, am->Pam.IR.base );
264 case Pam_RR:
265 return PPC32AMode_RR( am->Pam.RR.index, am->Pam.RR.base );
266 default:
267 vpanic("dopyPPC32AMode");
268 }
269}
270
271void ppPPC32AMode ( PPC32AMode* am ) {
272 switch (am->tag) {
273 case Pam_IR:
274 if (am->Pam.IR.index == 0)
275 vex_printf("(");
276 else
277 vex_printf("0x%x(", am->Pam.IR.index);
278 ppHRegPPC32(am->Pam.IR.base);
279 vex_printf(")");
280 return;
281 case Pam_RR:
282 ppHRegPPC32(am->Pam.RR.base);
283 vex_printf(",");
284 ppHRegPPC32(am->Pam.RR.index);
285 return;
286 default:
287 vpanic("ppPPC32AMode");
288 }
289}
290
cerioncd304492005-02-08 19:40:24 +0000291static void addRegUsage_PPC32AMode ( HRegUsage* u, PPC32AMode* am ) {
292 switch (am->tag) {
293 case Pam_IR:
294 addHRegUse(u, HRmRead, am->Pam.IR.base);
295 return;
296 case Pam_RR:
297 addHRegUse(u, HRmRead, am->Pam.RR.base);
298 addHRegUse(u, HRmRead, am->Pam.RR.index);
299 return;
300 default:
301 vpanic("addRegUsage_PPC32AMode");
302 }
303}
cerioncd304492005-02-08 19:40:24 +0000304
cerioncd304492005-02-08 19:40:24 +0000305static void mapRegs_PPC32AMode ( HRegRemap* m, PPC32AMode* am ) {
306 switch (am->tag) {
307 case Pam_IR:
308 am->Pam.IR.base = lookupHRegRemap(m, am->Pam.IR.base);
309 return;
310 case Pam_RR:
311 am->Pam.RR.base = lookupHRegRemap(m, am->Pam.RR.base);
312 am->Pam.RR.index = lookupHRegRemap(m, am->Pam.RR.index);
313 return;
314 default:
315 vpanic("mapRegs_PPC32AMode");
316 }
317}
cerioncd304492005-02-08 19:40:24 +0000318
319/* --------- Operand, which can be reg or immediate only. --------- */
320
321PPC32RI* PPC32RI_Imm ( UInt imm32 ) {
322 PPC32RI* op = LibVEX_Alloc(sizeof(PPC32RI));
323 op->tag = Pri_Imm;
324 op->Pri.Imm.imm32 = imm32;
325 return op;
326}
327PPC32RI* PPC32RI_Reg ( HReg reg ) {
328 PPC32RI* op = LibVEX_Alloc(sizeof(PPC32RI));
329 op->tag = Pri_Reg;
330 op->Pri.Reg.reg = reg;
331 return op;
332}
333
334void ppPPC32RI ( PPC32RI* op ) {
335 switch (op->tag) {
336 case Pri_Imm:
337 vex_printf("$0x%x", op->Pri.Imm.imm32);
338 return;
339 case Pri_Reg:
340 ppHRegPPC32(op->Pri.Reg.reg);
341 return;
342 default:
343 vpanic("ppPPC32RI");
344 }
345}
346
347/* An PPC32RI can only be used in a "read" context (what would it mean
348 to write or modify a literal?) and so we enumerate its registers
349 accordingly. */
350static void addRegUsage_PPC32RI ( HRegUsage* u, PPC32RI* op ) {
351 switch (op->tag) {
352 case Pri_Imm:
353 return;
354 case Pri_Reg:
355 addHRegUse(u, HRmRead, op->Pri.Reg.reg);
356 return;
357 default:
358 vpanic("addRegUsage_PPC32RI");
359 }
360}
361
362static void mapRegs_PPC32RI ( HRegRemap* m, PPC32RI* op ) {
363 switch (op->tag) {
364 case Pri_Imm:
365 return;
366 case Pri_Reg:
367 op->Pri.Reg.reg = lookupHRegRemap(m, op->Pri.Reg.reg);
368 return;
369 default:
370 vpanic("mapRegs_PPC32RI");
371 }
372}
373
374/* --------- Instructions. --------- */
375
cerionbcf8c3e2005-02-04 16:17:07 +0000376//.. HChar* showX86ScalarSz ( X86ScalarSz sz ) {
377//.. switch (sz) {
378//.. case Xss_16: return "w";
379//.. case Xss_32: return "l";
380//.. default: vpanic("showX86ScalarSz");
381//.. }
382//.. }
cerioncd304492005-02-08 19:40:24 +0000383
cerion2c49e032005-02-09 17:29:49 +0000384HChar* showPPC32UnaryOp ( PPC32UnaryOp op ) {
385 switch (op) {
386 case Pun_NOT: return "not";
387 case Pun_NEG: return "neg";
cerione13bb312005-02-10 19:51:03 +0000388 case Pun_CLZ: return "cntlzw";
cerion2c49e032005-02-09 17:29:49 +0000389 default: vpanic("showPPC32UnaryOp");
390 }
391}
cerioncd304492005-02-08 19:40:24 +0000392
393HChar* showPPC32AluOp ( PPC32AluOp op ) {
394 switch (op) {
395 case Palu_CMP: return "cmp";
396 case Palu_ADD: return "add";
ceriond5e38382005-02-11 13:38:15 +0000397 case Palu_SUB: return "subf";
cerioncd304492005-02-08 19:40:24 +0000398 case Palu_ADC: return "adc";
399 case Palu_SBB: return "sbb";
400 case Palu_AND: return "and";
401 case Palu_OR: return "or";
402 case Palu_XOR: return "xor";
ceriond5e38382005-02-11 13:38:15 +0000403 case Palu_MUL: return "mull";
cerioncd304492005-02-08 19:40:24 +0000404 default: vpanic("showPPC32AluOp");
405 }
406}
407
408HChar* showPPC32ShiftOp ( PPC32ShiftOp op ) {
409 switch (op) {
ceriond5e38382005-02-11 13:38:15 +0000410 case Psh_SHL: return "slw";
411 case Psh_SHR: return "srw";
412 case Psh_SAR: return "sraw";
413 case Psh_ROL: return "rlw";
cerioncd304492005-02-08 19:40:24 +0000414 default: vpanic("showPPC32ShiftOp");
415 }
416}
417
cerionbcf8c3e2005-02-04 16:17:07 +0000418//.. HChar* showX86FpOp ( X86FpOp op ) {
419//.. switch (op) {
420//.. case Xfp_ADD: return "add";
421//.. case Xfp_SUB: return "sub";
422//.. case Xfp_MUL: return "mul";
423//.. case Xfp_DIV: return "div";
424//.. case Xfp_SCALE: return "scale";
425//.. case Xfp_ATAN: return "atan";
426//.. case Xfp_YL2X: return "yl2x";
427//.. case Xfp_YL2XP1: return "yl2xp1";
428//.. case Xfp_PREM: return "prem";
429//.. case Xfp_PREM1: return "prem1";
430//.. case Xfp_SQRT: return "sqrt";
431//.. case Xfp_ABS: return "abs";
432//.. case Xfp_NEG: return "chs";
433//.. case Xfp_MOV: return "mov";
434//.. case Xfp_SIN: return "sin";
435//.. case Xfp_COS: return "cos";
436//.. case Xfp_TAN: return "tan";
437//.. case Xfp_ROUND: return "round";
438//.. case Xfp_2XM1: return "2xm1";
439//.. default: vpanic("showX86FpOp");
440//.. }
441//.. }
cerioncd304492005-02-08 19:40:24 +0000442
443PPC32Instr* PPC32Instr_Alu32 ( PPC32AluOp op, HReg dst, HReg src1, PPC32RI* src2 ) {
444 PPC32Instr* i = LibVEX_Alloc(sizeof(PPC32Instr));
445 i->tag = Pin_Alu32;
446 i->Pin.Alu32.op = op;
447 i->Pin.Alu32.dst = dst;
448 i->Pin.Alu32.src1 = src1;
449 i->Pin.Alu32.src2 = src2;
450 return i;
451}
452PPC32Instr* PPC32Instr_Sh32 ( PPC32ShiftOp op, HReg dst, HReg src, PPC32RI* shft ) {
453 PPC32Instr* i = LibVEX_Alloc(sizeof(PPC32Instr));
454 i->tag = Pin_Sh32;
455 i->Pin.Sh32.op = op;
456 i->Pin.Sh32.dst = dst;
457 i->Pin.Sh32.src = src;
458 i->Pin.Sh32.shft = shft;
459 return i;
460}
cerion2c49e032005-02-09 17:29:49 +0000461PPC32Instr* PPC32Instr_Test32 ( HReg dst, PPC32RI* src ) {
462 PPC32Instr* i = LibVEX_Alloc(sizeof(PPC32Instr));
463 i->tag = Pin_Test32;
464 i->Pin.Test32.dst = dst;
465 i->Pin.Test32.src = src;
466 return i;
467}
cerione13bb312005-02-10 19:51:03 +0000468PPC32Instr* PPC32Instr_Unary32 ( PPC32UnaryOp op, HReg dst, HReg src ) {
cerion2c49e032005-02-09 17:29:49 +0000469 PPC32Instr* i = LibVEX_Alloc(sizeof(PPC32Instr));
470 i->tag = Pin_Unary32;
471 i->Pin.Unary32.op = op;
472 i->Pin.Unary32.dst = dst;
cerione13bb312005-02-10 19:51:03 +0000473 i->Pin.Unary32.src = src;
cerion2c49e032005-02-09 17:29:49 +0000474 return i;
475}
cerion92f5dc72005-02-10 16:11:35 +0000476PPC32Instr* PPC32Instr_MulL ( Bool syned, Bool word, HReg dst,
477 HReg src1, PPC32RI* src2 ) {
478 PPC32Instr* i = LibVEX_Alloc(sizeof(PPC32Instr));
479 i->tag = Pin_MulL;
480 i->Pin.MulL.syned = syned;
481 i->Pin.MulL.word = word;
cerionc0e707e2005-02-10 22:35:34 +0000482 i->Pin.MulL.dst = dst;
cerion92f5dc72005-02-10 16:11:35 +0000483 i->Pin.MulL.src1 = src1;
484 i->Pin.MulL.src2 = src2;
485 return i;
486}
cerionc0e707e2005-02-10 22:35:34 +0000487PPC32Instr* PPC32Instr_Div ( Bool syned, HReg dst,
488 HReg src1, PPC32RI* src2 ) {
489 PPC32Instr* i = LibVEX_Alloc(sizeof(PPC32Instr));
490 i->tag = Pin_Div;
491 i->Pin.Div.syned = syned;
492 i->Pin.Div.dst = dst;
493 i->Pin.Div.src1 = src1;
494 i->Pin.Div.src2 = src2;
495 return i;
496}
cerionbcf8c3e2005-02-04 16:17:07 +0000497//.. X86Instr* X86Instr_Sh3232 ( X86ShiftOp op, UInt amt, HReg src, HReg dst ) {
498//.. X86Instr* i = LibVEX_Alloc(sizeof(X86Instr));
499//.. i->tag = Xin_Sh3232;
500//.. i->Xin.Sh3232.op = op;
501//.. i->Xin.Sh3232.amt = amt;
502//.. i->Xin.Sh3232.src = src;
503//.. i->Xin.Sh3232.dst = dst;
504//.. vassert(op == Xsh_SHL || op == Xsh_SHR);
505//.. return i;
506//.. }
507//.. X86Instr* X86Instr_Push( X86RMI* src ) {
508//.. X86Instr* i = LibVEX_Alloc(sizeof(X86Instr));
509//.. i->tag = Xin_Push;
510//.. i->Xin.Push.src = src;
511//.. return i;
512//.. }
cerion2c49e032005-02-09 17:29:49 +0000513PPC32Instr* PPC32Instr_Call ( PPC32CondCode cond, Addr32 target, Int regparms ) {
514 PPC32Instr* i = LibVEX_Alloc(sizeof(PPC32Instr));
515 i->tag = Pin_Call;
516 i->Pin.Call.cond = cond;
517 i->Pin.Call.target = target;
518 i->Pin.Call.regparms = regparms;
519 vassert(regparms >= 0 && regparms < PPC32_N_REGPARMS);
520 return i;
521}
522PPC32Instr* PPC32Instr_Goto ( IRJumpKind jk, PPC32CondCode cond, PPC32RI* dst ) {
523 PPC32Instr* i = LibVEX_Alloc(sizeof(PPC32Instr));
524 i->tag = Pin_Goto;
525 i->Pin.Goto.cond = cond;
526 i->Pin.Goto.dst = dst;
527 i->Pin.Goto.jk = jk;
528 return i;
529}
cerionb536af92005-02-10 15:03:19 +0000530PPC32Instr* PPC32Instr_CMov32 ( PPC32CondCode cond, HReg dst, PPC32RI* src ) {
531 PPC32Instr* i = LibVEX_Alloc(sizeof(PPC32Instr));
532 i->tag = Pin_CMov32;
533 i->Pin.CMov32.cond = cond;
534 i->Pin.CMov32.src = src;
535 i->Pin.CMov32.dst = dst;
536 vassert(cond != Pcc_ALWAYS);
537 return i;
538}
cerion2c49e032005-02-09 17:29:49 +0000539PPC32Instr* PPC32Instr_LoadEX ( UChar sz, Bool syned,
cerioncd304492005-02-08 19:40:24 +0000540 HReg dst, PPC32AMode* src ) {
cerion2c49e032005-02-09 17:29:49 +0000541 PPC32Instr* i = LibVEX_Alloc(sizeof(PPC32Instr));
542 i->tag = Pin_LoadEX;
543 i->Pin.LoadEX.sz = sz;
544 i->Pin.LoadEX.syned = syned;
545 i->Pin.LoadEX.src = src;
546 i->Pin.LoadEX.dst = dst;
547 vassert(sz == 1 || sz == 2 || sz == 4);
cerioncd304492005-02-08 19:40:24 +0000548 return i;
549}
550PPC32Instr* PPC32Instr_Store ( UChar sz, PPC32AMode* dst, HReg src ) {
551 PPC32Instr* i = LibVEX_Alloc(sizeof(PPC32Instr));
552 i->tag = Pin_Store;
553 i->Pin.Store.sz = sz;
554 i->Pin.Store.src = src;
555 i->Pin.Store.dst = dst;
556 vassert(sz == 1 || sz == 2 || sz == 4);
557 return i;
558}
cerionb536af92005-02-10 15:03:19 +0000559PPC32Instr* PPC32Instr_Set32 ( PPC32CondCode cond, HReg dst ) {
560 PPC32Instr* i = LibVEX_Alloc(sizeof(PPC32Instr));
561 i->tag = Pin_Set32;
562 i->Pin.Set32.cond = cond;
563 i->Pin.Set32.dst = dst;
564 return i;
565}
cerionbcf8c3e2005-02-04 16:17:07 +0000566//.. X86Instr* X86Instr_Bsfr32 ( Bool isFwds, HReg src, HReg dst ) {
567//.. X86Instr* i = LibVEX_Alloc(sizeof(X86Instr));
568//.. i->tag = Xin_Bsfr32;
569//.. i->Xin.Bsfr32.isFwds = isFwds;
570//.. i->Xin.Bsfr32.src = src;
571//.. i->Xin.Bsfr32.dst = dst;
572//.. return i;
573//.. }
cerion92f5dc72005-02-10 16:11:35 +0000574PPC32Instr* PPC32Instr_MFence ( VexSubArch subarch )
575{
576 PPC32Instr* i = LibVEX_Alloc(sizeof(PPC32Instr));
577 i->tag = Pin_MFence;
578 i->Pin.MFence.subarch = subarch;
579 vassert(subarch == VexSubArchPPC32_AV
580 || subarch == VexSubArchPPC32_noAV);
581 return i;
582}
cerioncd304492005-02-08 19:40:24 +0000583
cerionbcf8c3e2005-02-04 16:17:07 +0000584//.. X86Instr* X86Instr_FpUnary ( X86FpOp op, HReg src, HReg dst ) {
585//.. X86Instr* i = LibVEX_Alloc(sizeof(X86Instr));
586//.. i->tag = Xin_FpUnary;
587//.. i->Xin.FpUnary.op = op;
588//.. i->Xin.FpUnary.src = src;
589//.. i->Xin.FpUnary.dst = dst;
590//.. return i;
591//.. }
592//.. X86Instr* X86Instr_FpBinary ( X86FpOp op, HReg srcL, HReg srcR, HReg dst ) {
593//.. X86Instr* i = LibVEX_Alloc(sizeof(X86Instr));
594//.. i->tag = Xin_FpBinary;
595//.. i->Xin.FpBinary.op = op;
596//.. i->Xin.FpBinary.srcL = srcL;
597//.. i->Xin.FpBinary.srcR = srcR;
598//.. i->Xin.FpBinary.dst = dst;
599//.. return i;
600//.. }
601//.. X86Instr* X86Instr_FpLdSt ( Bool isLoad, UChar sz, HReg reg, X86AMode* addr ) {
602//.. X86Instr* i = LibVEX_Alloc(sizeof(X86Instr));
603//.. i->tag = Xin_FpLdSt;
604//.. i->Xin.FpLdSt.isLoad = isLoad;
605//.. i->Xin.FpLdSt.sz = sz;
606//.. i->Xin.FpLdSt.reg = reg;
607//.. i->Xin.FpLdSt.addr = addr;
608//.. vassert(sz == 4 || sz == 8);
609//.. return i;
610//.. }
611//.. X86Instr* X86Instr_FpLdStI ( Bool isLoad, UChar sz,
612//.. HReg reg, X86AMode* addr ) {
613//.. X86Instr* i = LibVEX_Alloc(sizeof(X86Instr));
614//.. i->tag = Xin_FpLdStI;
615//.. i->Xin.FpLdStI.isLoad = isLoad;
616//.. i->Xin.FpLdStI.sz = sz;
617//.. i->Xin.FpLdStI.reg = reg;
618//.. i->Xin.FpLdStI.addr = addr;
619//.. vassert(sz == 2 || sz == 4 || sz == 8);
620//.. return i;
621//.. }
622//.. X86Instr* X86Instr_Fp64to32 ( HReg src, HReg dst ) {
623//.. X86Instr* i = LibVEX_Alloc(sizeof(X86Instr));
624//.. i->tag = Xin_Fp64to32;
625//.. i->Xin.Fp64to32.src = src;
626//.. i->Xin.Fp64to32.dst = dst;
627//.. return i;
628//.. }
629//.. X86Instr* X86Instr_FpCMov ( X86CondCode cond, HReg src, HReg dst ) {
630//.. X86Instr* i = LibVEX_Alloc(sizeof(X86Instr));
631//.. i->tag = Xin_FpCMov;
632//.. i->Xin.FpCMov.cond = cond;
633//.. i->Xin.FpCMov.src = src;
634//.. i->Xin.FpCMov.dst = dst;
635//.. vassert(cond != Xcc_ALWAYS);
636//.. return i;
637//.. }
638//.. X86Instr* X86Instr_FpLdStCW ( Bool isLoad, X86AMode* addr ) {
639//.. X86Instr* i = LibVEX_Alloc(sizeof(X86Instr));
640//.. i->tag = Xin_FpLdStCW;
641//.. i->Xin.FpLdStCW.isLoad = isLoad;
642//.. i->Xin.FpLdStCW.addr = addr;
643//.. return i;
644//.. }
645//.. X86Instr* X86Instr_FpStSW_AX ( void ) {
646//.. X86Instr* i = LibVEX_Alloc(sizeof(X86Instr));
647//.. i->tag = Xin_FpStSW_AX;
648//.. return i;
649//.. }
650//.. X86Instr* X86Instr_FpCmp ( HReg srcL, HReg srcR, HReg dst ) {
651//.. X86Instr* i = LibVEX_Alloc(sizeof(X86Instr));
652//.. i->tag = Xin_FpCmp;
653//.. i->Xin.FpCmp.srcL = srcL;
654//.. i->Xin.FpCmp.srcR = srcR;
655//.. i->Xin.FpCmp.dst = dst;
656//.. return i;
657//.. }
cerionbcf8c3e2005-02-04 16:17:07 +0000658
659void ppPPC32Instr ( PPC32Instr* i )
660{
661 switch (i->tag) {
cerioncd304492005-02-08 19:40:24 +0000662 case Pin_Alu32:
cerion2c49e032005-02-09 17:29:49 +0000663 if (i->Pin.Alu32.op == Palu_OR && // or Rd,Rs,Rs == mr Rd,Rs
664 i->Pin.Alu32.src2->tag == Pri_Reg &&
665 i->Pin.Alu32.src2->Pri.Reg.reg == i->Pin.Alu32.src1) {
666 vex_printf("mr ");
667 ppHRegPPC32(i->Pin.Alu32.dst);
668 vex_printf(",");
669 ppHRegPPC32(i->Pin.Alu32.src1);
670 return;
671 }
672 if (i->Pin.Alu32.op == Palu_ADD && // add Rd,R0,Rs == li Rd,Rs
cerion3c0b12b2005-02-10 11:39:43 +0000673 i->Pin.Alu32.src1 == hregPPC32_GPR0() &&
674 i->Pin.Alu32.src2->tag == Pri_Imm) {
cerion2c49e032005-02-09 17:29:49 +0000675 vex_printf("li ");
676 ppHRegPPC32(i->Pin.Alu32.dst);
677 vex_printf(",");
678 ppPPC32RI(i->Pin.Alu32.src2);
679 return;
680 }
ceriond5e38382005-02-11 13:38:15 +0000681 vex_printf("%s%s ", showPPC32AluOp(i->Pin.Alu32.op),
682 i->Pin.Alu32.src2->tag == Pri_Imm ? "i" : "" );
cerion2c49e032005-02-09 17:29:49 +0000683 ppHRegPPC32(i->Pin.Alu32.dst);
684 vex_printf(",");
685 ppHRegPPC32(i->Pin.Alu32.src1);
686 vex_printf(",");
687 ppPPC32RI(i->Pin.Alu32.src2);
cerioncd304492005-02-08 19:40:24 +0000688 return;
689 case Pin_Sh32:
ceriond5e38382005-02-11 13:38:15 +0000690 vex_printf("%s%s ", showPPC32ShiftOp(i->Pin.Sh32.op),
691 i->Pin.Sh32.shft->tag == Pri_Imm ? "i" : "" );
cerioncd304492005-02-08 19:40:24 +0000692 ppHRegPPC32(i->Pin.Sh32.dst);
693 vex_printf(",");
694 ppHRegPPC32(i->Pin.Sh32.src);
695 vex_printf(",");
696 ppPPC32RI(i->Pin.Sh32.shft);
697 return;
cerion2c49e032005-02-09 17:29:49 +0000698 case Pin_Test32:
ceriond5e38382005-02-11 13:38:15 +0000699 vex_printf("test ");
cerion2c49e032005-02-09 17:29:49 +0000700 ppHRegPPC32(i->Pin.Test32.dst);
701 vex_printf(",");
702 ppPPC32RI(i->Pin.Test32.src);
703 return;
cerionb536af92005-02-10 15:03:19 +0000704 case Pin_Unary32:
cerione13bb312005-02-10 19:51:03 +0000705 vex_printf("%s ", showPPC32UnaryOp(i->Pin.Unary32.op));
cerionb536af92005-02-10 15:03:19 +0000706 ppHRegPPC32(i->Pin.Unary32.dst);
cerione13bb312005-02-10 19:51:03 +0000707 vex_printf(",");
708 ppHRegPPC32(i->Pin.Unary32.src);
cerionb536af92005-02-10 15:03:19 +0000709 return;
cerion92f5dc72005-02-10 16:11:35 +0000710 case Pin_MulL:
711 if (i->Pin.MulL.src2->tag == Pri_Imm) {
712 vex_printf("mulli ");
713 } else {
714 vex_printf("mul%s%c ",
715 i->Pin.MulL.word ? "hw" : "lw",
716 i->Pin.MulL.syned ? 's' : 'u');
717 }
718 ppHRegPPC32(i->Pin.MulL.dst);
719 vex_printf(",");
720 ppHRegPPC32(i->Pin.MulL.src1);
721 vex_printf(",");
722 ppPPC32RI(i->Pin.MulL.src2);
723 return;
cerionc0e707e2005-02-10 22:35:34 +0000724 case Pin_Div:
725 vex_printf("divw%s ",
726 i->Pin.Div.syned ? "" : "u");
727 ppHRegPPC32(i->Pin.MulL.dst);
728 vex_printf(",");
729 ppHRegPPC32(i->Pin.MulL.src1);
730 vex_printf(",");
731 ppPPC32RI(i->Pin.MulL.src2);
732 return;
cerionbcf8c3e2005-02-04 16:17:07 +0000733//.. case Xin_Sh3232:
734//.. vex_printf("%sdl ", showX86ShiftOp(i->Xin.Sh3232.op));
735//.. if (i->Xin.Sh3232.amt == 0)
736//.. vex_printf(" %%cl,");
737//.. else
738//.. vex_printf(" $%d,", i->Xin.Sh3232.amt);
739//.. ppHRegX86(i->Xin.Sh3232.src);
740//.. vex_printf(",");
741//.. ppHRegX86(i->Xin.Sh3232.dst);
742//.. return;
743//.. case Xin_Push:
744//.. vex_printf("pushl ");
745//.. ppX86RMI(i->Xin.Push.src);
746//.. return;
cerion2c49e032005-02-09 17:29:49 +0000747 case Pin_Call:
748// CAB: not 'bc' ?
749 vex_printf("call%s[%d] ",
750 i->Pin.Call.cond==Pcc_ALWAYS
751 ? "" : showPPC32CondCode(i->Pin.Call.cond),
752 i->Pin.Call.regparms);
753 vex_printf("0x%x", i->Pin.Call.target);
754 break;
755 case Pin_Goto:
cerionb536af92005-02-10 15:03:19 +0000756// CAB: what instead of movl ?
cerion2c49e032005-02-09 17:29:49 +0000757 if (i->Pin.Goto.cond != Pcc_ALWAYS) {
758 vex_printf("if (%%eflags.%s) { ",
759 showPPC32CondCode(i->Pin.Goto.cond));
760 }
761 if (i->Pin.Goto.jk != Ijk_Boring) {
ceriond5e38382005-02-11 13:38:15 +0000762 vex_printf("la %%r31, $");
cerion2c49e032005-02-09 17:29:49 +0000763 ppIRJumpKind(i->Pin.Goto.jk);
cerionb536af92005-02-10 15:03:19 +0000764 vex_printf(" ; ");
cerion2c49e032005-02-09 17:29:49 +0000765 }
ceriond5e38382005-02-11 13:38:15 +0000766 vex_printf("la ");
cerionb536af92005-02-10 15:03:19 +0000767 vex_printf("%%r4, ");
cerion2c49e032005-02-09 17:29:49 +0000768 ppPPC32RI(i->Pin.Goto.dst);
cerionb536af92005-02-10 15:03:19 +0000769 vex_printf(" ; ret");
cerion2c49e032005-02-09 17:29:49 +0000770 if (i->Pin.Goto.cond != Pcc_ALWAYS) {
771 vex_printf(" }");
772 }
773 return;
cerionb536af92005-02-10 15:03:19 +0000774 case Pin_CMov32:
775 vex_printf("cmov%s ", showPPC32CondCode(i->Pin.CMov32.cond));
776 ppHRegPPC32(i->Pin.CMov32.dst);
777 vex_printf(",");
778 ppPPC32RI(i->Pin.CMov32.src);
779 return;
cerioncd304492005-02-08 19:40:24 +0000780 case Pin_LoadEX: {
cerion2c49e032005-02-09 17:29:49 +0000781 UChar sz = i->Pin.LoadEX.sz;
cerioncd304492005-02-08 19:40:24 +0000782 Bool syned = i->Pin.LoadEX.syned;
cerion2c49e032005-02-09 17:29:49 +0000783// CAB: How to get 'update'... ?
784 Bool update = False;
cerioncd304492005-02-08 19:40:24 +0000785 Bool idxd = (i->Pin.LoadEX.src->tag == Pam_IR) ? True : False;
cerioncd304492005-02-08 19:40:24 +0000786 vex_printf("l%c%c%s%s ",
cerion2c49e032005-02-09 17:29:49 +0000787 (sz==1) ? 'b' : (sz==2 ? 'h' : 'w'),
cerioncd304492005-02-08 19:40:24 +0000788 syned ? 'a' : 'z',
789 update ? "u" : "",
790 idxd ? "x" : "" );
cerioncd304492005-02-08 19:40:24 +0000791 ppHRegPPC32(i->Pin.LoadEX.dst);
792 vex_printf(",");
793 ppPPC32AMode(i->Pin.LoadEX.src);
794 return;
795 }
796 case Pin_Store: {
797 UChar sz = i->Pin.Store.sz;
cerion2c49e032005-02-09 17:29:49 +0000798// CAB: How to get 'update'... ?
799 Bool update = False;
cerioncd304492005-02-08 19:40:24 +0000800 Bool idxd = (i->Pin.Store.dst->tag == Pam_IR) ? True : False;
cerioncd304492005-02-08 19:40:24 +0000801 vex_printf("st%c%s%s ",
cerion2c49e032005-02-09 17:29:49 +0000802 (sz==1) ? 'b' : (sz==2 ? 'h' : 'w'),
cerioncd304492005-02-08 19:40:24 +0000803 update ? "u" : "",
804 idxd ? "x" : "" );
cerioncd304492005-02-08 19:40:24 +0000805 ppHRegPPC32(i->Pin.Store.src);
806 vex_printf(",");
807 ppPPC32AMode(i->Pin.Store.dst);
808 return;
809 }
cerionb536af92005-02-10 15:03:19 +0000810 case Pin_Set32:
ceriond5e38382005-02-11 13:38:15 +0000811 vex_printf("set%s ", showPPC32CondCode(i->Pin.Set32.cond));
cerionb536af92005-02-10 15:03:19 +0000812 ppHRegPPC32(i->Pin.Set32.dst);
813 return;
cerionbcf8c3e2005-02-04 16:17:07 +0000814//.. case Xin_Bsfr32:
815//.. vex_printf("bs%cl ", i->Xin.Bsfr32.isFwds ? 'f' : 'r');
816//.. ppHRegX86(i->Xin.Bsfr32.src);
817//.. vex_printf(",");
818//.. ppHRegX86(i->Xin.Bsfr32.dst);
819//.. return;
cerion92f5dc72005-02-10 16:11:35 +0000820 case Pin_MFence:
821 vex_printf("mfence(%s)",
822 LibVEX_ppVexSubArch(i->Pin.MFence.subarch));
823 return;
cerionbcf8c3e2005-02-04 16:17:07 +0000824//.. case Xin_FpUnary:
825//.. vex_printf("g%sD ", showX86FpOp(i->Xin.FpUnary.op));
826//.. ppHRegX86(i->Xin.FpUnary.src);
827//.. vex_printf(",");
828//.. ppHRegX86(i->Xin.FpUnary.dst);
829//.. break;
830//.. case Xin_FpBinary:
831//.. vex_printf("g%sD ", showX86FpOp(i->Xin.FpBinary.op));
832//.. ppHRegX86(i->Xin.FpBinary.srcL);
833//.. vex_printf(",");
834//.. ppHRegX86(i->Xin.FpBinary.srcR);
835//.. vex_printf(",");
836//.. ppHRegX86(i->Xin.FpBinary.dst);
837//.. break;
838//.. case Xin_FpLdSt:
839//.. if (i->Xin.FpLdSt.isLoad) {
840//.. vex_printf("gld%c " , i->Xin.FpLdSt.sz==8 ? 'D' : 'F');
841//.. ppX86AMode(i->Xin.FpLdSt.addr);
842//.. vex_printf(", ");
843//.. ppHRegX86(i->Xin.FpLdSt.reg);
844//.. } else {
845//.. vex_printf("gst%c " , i->Xin.FpLdSt.sz==8 ? 'D' : 'F');
846//.. ppHRegX86(i->Xin.FpLdSt.reg);
847//.. vex_printf(", ");
848//.. ppX86AMode(i->Xin.FpLdSt.addr);
849//.. }
850//.. return;
851//.. case Xin_FpLdStI:
852//.. if (i->Xin.FpLdStI.isLoad) {
853//.. vex_printf("gild%s ", i->Xin.FpLdStI.sz==8 ? "ll" :
854//.. i->Xin.FpLdStI.sz==4 ? "l" : "w");
855//.. ppX86AMode(i->Xin.FpLdStI.addr);
856//.. vex_printf(", ");
857//.. ppHRegX86(i->Xin.FpLdStI.reg);
858//.. } else {
859//.. vex_printf("gist%s ", i->Xin.FpLdStI.sz==8 ? "ll" :
860//.. i->Xin.FpLdStI.sz==4 ? "l" : "w");
861//.. ppHRegX86(i->Xin.FpLdStI.reg);
862//.. vex_printf(", ");
863//.. ppX86AMode(i->Xin.FpLdStI.addr);
864//.. }
865//.. return;
866//.. case Xin_Fp64to32:
867//.. vex_printf("gdtof ");
868//.. ppHRegX86(i->Xin.Fp64to32.src);
869//.. vex_printf(",");
870//.. ppHRegX86(i->Xin.Fp64to32.dst);
871//.. return;
872//.. case Xin_FpCMov:
873//.. vex_printf("gcmov%s ", showX86CondCode(i->Xin.FpCMov.cond));
874//.. ppHRegX86(i->Xin.FpCMov.src);
875//.. vex_printf(",");
876//.. ppHRegX86(i->Xin.FpCMov.dst);
877//.. return;
878//.. case Xin_FpLdStCW:
879//.. vex_printf(i->Xin.FpLdStCW.isLoad ? "fldcw " : "fstcw ");
880//.. ppX86AMode(i->Xin.FpLdStCW.addr);
881//.. return;
882//.. case Xin_FpStSW_AX:
883//.. vex_printf("fstsw %%ax");
884//.. return;
885//.. case Xin_FpCmp:
886//.. vex_printf("gcmp ");
887//.. ppHRegX86(i->Xin.FpCmp.srcL);
888//.. vex_printf(",");
889//.. ppHRegX86(i->Xin.FpCmp.srcR);
890//.. vex_printf(",");
891//.. ppHRegX86(i->Xin.FpCmp.dst);
892//.. break;
893//.. case Xin_SseConst:
894//.. vex_printf("const $0x%04x,", (Int)i->Xin.SseConst.con);
895//.. ppHRegX86(i->Xin.SseConst.dst);
896//.. break;
897//.. case Xin_SseLdSt:
898//.. vex_printf("movups ");
899//.. if (i->Xin.SseLdSt.isLoad) {
900//.. ppX86AMode(i->Xin.SseLdSt.addr);
901//.. vex_printf(",");
902//.. ppHRegX86(i->Xin.SseLdSt.reg);
903//.. } else {
904//.. ppHRegX86(i->Xin.SseLdSt.reg);
905//.. vex_printf(",");
906//.. ppX86AMode(i->Xin.SseLdSt.addr);
907//.. }
908//.. return;
909//.. case Xin_SseLdzLO:
910//.. vex_printf("movs%s ", i->Xin.SseLdzLO.sz==4 ? "s" : "d");
911//.. ppX86AMode(i->Xin.SseLdzLO.addr);
912//.. vex_printf(",");
913//.. ppHRegX86(i->Xin.SseLdzLO.reg);
914//.. return;
915//.. case Xin_Sse32Fx4:
916//.. vex_printf("%sps ", showX86SseOp(i->Xin.Sse32Fx4.op));
917//.. ppHRegX86(i->Xin.Sse32Fx4.src);
918//.. vex_printf(",");
919//.. ppHRegX86(i->Xin.Sse32Fx4.dst);
920//.. return;
921//.. case Xin_Sse32FLo:
922//.. vex_printf("%sss ", showX86SseOp(i->Xin.Sse32FLo.op));
923//.. ppHRegX86(i->Xin.Sse32FLo.src);
924//.. vex_printf(",");
925//.. ppHRegX86(i->Xin.Sse32FLo.dst);
926//.. return;
927//.. case Xin_Sse64Fx2:
928//.. vex_printf("%spd ", showX86SseOp(i->Xin.Sse64Fx2.op));
929//.. ppHRegX86(i->Xin.Sse64Fx2.src);
930//.. vex_printf(",");
931//.. ppHRegX86(i->Xin.Sse64Fx2.dst);
932//.. return;
933//.. case Xin_Sse64FLo:
934//.. vex_printf("%ssd ", showX86SseOp(i->Xin.Sse64FLo.op));
935//.. ppHRegX86(i->Xin.Sse64FLo.src);
936//.. vex_printf(",");
937//.. ppHRegX86(i->Xin.Sse64FLo.dst);
938//.. return;
939//.. case Xin_SseReRg:
940//.. vex_printf("%s ", showX86SseOp(i->Xin.SseReRg.op));
941//.. ppHRegX86(i->Xin.SseReRg.src);
942//.. vex_printf(",");
943//.. ppHRegX86(i->Xin.SseReRg.dst);
944//.. return;
945//.. case Xin_SseCMov:
946//.. vex_printf("cmov%s ", showX86CondCode(i->Xin.SseCMov.cond));
947//.. ppHRegX86(i->Xin.SseCMov.src);
948//.. vex_printf(",");
949//.. ppHRegX86(i->Xin.SseCMov.dst);
950//.. return;
951//.. case Xin_SseShuf:
952//.. vex_printf("pshufd $0x%x,", i->Xin.SseShuf.order);
953//.. ppHRegX86(i->Xin.SseShuf.src);
954//.. vex_printf(",");
955//.. ppHRegX86(i->Xin.SseShuf.dst);
956//.. return;
957
958 default:
cerionb536af92005-02-10 15:03:19 +0000959 vex_printf("\nppPPC32Instr(ppc32): No such tag(%d)\n", i->tag);
960 vpanic("ppPPC32Instr(ppc32)");
cerionbcf8c3e2005-02-04 16:17:07 +0000961 }
962}
963
964/* --------- Helpers for register allocation. --------- */
965
966void getRegUsage_PPC32Instr ( HRegUsage* u, PPC32Instr* i )
967{
968// Bool unary;
969 initHRegUsage(u);
970 switch (i->tag) {
cerioncd304492005-02-08 19:40:24 +0000971 case Pin_Alu32:
972 addHRegUse(u, HRmRead, i->Pin.Alu32.src1);
973 addRegUsage_PPC32RI(u, i->Pin.Alu32.src2);
974 if (i->Pin.Alu32.op == Palu_CMP) {
975 addHRegUse(u, HRmRead, i->Pin.Alu32.dst);
976 return;
977 }
978 addHRegUse(u, HRmWrite, i->Pin.Alu32.dst);
cerion2c49e032005-02-09 17:29:49 +0000979// CAB TODO: Any circumstance where dst is read & written?
cerioncd304492005-02-08 19:40:24 +0000980 return;
981
982 case Pin_Sh32:
983 addHRegUse(u, HRmWrite, i->Pin.Sh32.dst);
984 addHRegUse(u, HRmRead, i->Pin.Sh32.src);
985 addRegUsage_PPC32RI(u, i->Pin.Sh32.shft);
cerion2c49e032005-02-09 17:29:49 +0000986// CAB TODO: Any circumstance where dst is read & written?
cerioncd304492005-02-08 19:40:24 +0000987 return;
988
cerion2c49e032005-02-09 17:29:49 +0000989 case Pin_Test32:
990 addHRegUse(u, HRmRead, i->Pin.Test32.dst);
991 addRegUsage_PPC32RI(u, i->Pin.Test32.src);
992 return;
cerionb536af92005-02-10 15:03:19 +0000993 case Pin_Unary32:
cerione13bb312005-02-10 19:51:03 +0000994 addHRegUse(u, HRmWrite, i->Pin.Unary32.dst);
995 addHRegUse(u, HRmRead, i->Pin.Unary32.src);
cerionb536af92005-02-10 15:03:19 +0000996 return;
cerion92f5dc72005-02-10 16:11:35 +0000997 case Pin_MulL:
998 addHRegUse(u, HRmWrite, i->Pin.MulL.dst);
999 addHRegUse(u, HRmRead, i->Pin.MulL.src1);
1000 addRegUsage_PPC32RI(u, i->Pin.MulL.src2);
1001 return;
cerionc0e707e2005-02-10 22:35:34 +00001002 case Pin_Div:
1003 addHRegUse(u, HRmWrite, i->Pin.Div.dst);
1004 addHRegUse(u, HRmRead, i->Pin.Div.src1);
1005 addRegUsage_PPC32RI(u, i->Pin.Div.src2);
1006 return;
cerionbcf8c3e2005-02-04 16:17:07 +00001007//.. case Xin_Sh3232:
1008//.. addHRegUse(u, HRmRead, i->Xin.Sh3232.src);
1009//.. addHRegUse(u, HRmModify, i->Xin.Sh3232.dst);
1010//.. if (i->Xin.Sh3232.amt == 0)
1011//.. addHRegUse(u, HRmRead, hregX86_ECX());
1012//.. return;
1013//.. case Xin_Push:
1014//.. addRegUsage_X86RMI(u, i->Xin.Push.src);
1015//.. addHRegUse(u, HRmModify, hregX86_ESP());
1016//.. return;
cerion2c49e032005-02-09 17:29:49 +00001017 case Pin_Call:
1018 /* This is a bit subtle. */
1019 /* First off, claim it trashes all the caller-saved regs
1020 which fall within the register allocator's jurisdiction.
1021 These I believe to be: r0,r3:12
1022 */
1023 addHRegUse(u, HRmWrite, hregPPC32_GPR0());
1024 addHRegUse(u, HRmWrite, hregPPC32_GPR3());
1025 addHRegUse(u, HRmWrite, hregPPC32_GPR4());
1026 addHRegUse(u, HRmWrite, hregPPC32_GPR5());
1027 addHRegUse(u, HRmWrite, hregPPC32_GPR6());
1028 addHRegUse(u, HRmWrite, hregPPC32_GPR7());
1029 addHRegUse(u, HRmWrite, hregPPC32_GPR8());
1030 addHRegUse(u, HRmWrite, hregPPC32_GPR9());
1031 addHRegUse(u, HRmWrite, hregPPC32_GPR10());
1032 addHRegUse(u, HRmWrite, hregPPC32_GPR11());
1033 addHRegUse(u, HRmWrite, hregPPC32_GPR12());
1034
1035 /* Now we have to state any parameter-carrying registers
1036 which might be read. This depends on the regparmness. */
1037 switch (i->Pin.Call.regparms) {
1038 case 8: addHRegUse(u, HRmRead, hregPPC32_GPR10()); /*fallthru*/
1039 case 7: addHRegUse(u, HRmRead, hregPPC32_GPR9() ); /*fallthru*/
1040 case 6: addHRegUse(u, HRmRead, hregPPC32_GPR8() ); /*fallthru*/
1041 case 5: addHRegUse(u, HRmRead, hregPPC32_GPR7() ); /*fallthru*/
1042 case 4: addHRegUse(u, HRmRead, hregPPC32_GPR6() ); /*fallthru*/
1043 case 3: addHRegUse(u, HRmRead, hregPPC32_GPR5() ); /*fallthru*/
1044 case 2: addHRegUse(u, HRmRead, hregPPC32_GPR4() ); /*fallthru*/
1045 case 1: addHRegUse(u, HRmRead, hregPPC32_GPR3() ); /*fallthru*/
1046 case 0: break;
1047 default: vpanic("getRegUsage_PPC32Instr:Call:regparms");
1048 }
1049 /* Finally, there is the issue that the insn trashes a
1050 register because the literal target address has to be
1051 loaded into a register. Fortunately, ?CAB? is stated in the
1052 ABI as a scratch register, and so seems a suitable victim. */
cerionb536af92005-02-10 15:03:19 +00001053 addHRegUse(u, HRmWrite, hregPPC32_GPR12());
cerion2c49e032005-02-09 17:29:49 +00001054 /* Upshot of this is that the assembler really must use ?CAB?,
1055 and no other, as a destination temporary. */
1056 return;
1057 case Pin_Goto:
1058 addRegUsage_PPC32RI(u, i->Pin.Goto.dst);
1059 addHRegUse(u, HRmWrite, hregPPC32_GPR4());
1060 if (i->Pin.Goto.jk != Ijk_Boring)
1061 addHRegUse(u, HRmWrite, GuestStatePtr);
1062 return;
cerionb536af92005-02-10 15:03:19 +00001063 case Pin_CMov32:
1064 addRegUsage_PPC32RI(u, i->Pin.CMov32.src);
1065 addHRegUse(u, HRmModify, i->Pin.CMov32.dst);
1066 return;
cerion2c49e032005-02-09 17:29:49 +00001067 case Pin_LoadEX:
1068 addRegUsage_PPC32AMode(u, i->Pin.LoadEX.src);
1069 addHRegUse(u, HRmWrite, i->Pin.LoadEX.dst);
1070 return;
1071 case Pin_Store:
1072 addHRegUse(u, HRmRead, i->Pin.Store.src);
1073 addRegUsage_PPC32AMode(u, i->Pin.Store.dst);
1074 return;
cerionb536af92005-02-10 15:03:19 +00001075 case Pin_Set32:
1076 addHRegUse(u, HRmWrite, i->Pin.Set32.dst);
1077 return;
cerionbcf8c3e2005-02-04 16:17:07 +00001078//.. case Xin_Bsfr32:
1079//.. addHRegUse(u, HRmRead, i->Xin.Bsfr32.src);
1080//.. addHRegUse(u, HRmWrite, i->Xin.Bsfr32.dst);
1081//.. return;
cerion92f5dc72005-02-10 16:11:35 +00001082 case Pin_MFence:
1083 return;
cerionbcf8c3e2005-02-04 16:17:07 +00001084//.. case Xin_FpUnary:
1085//.. addHRegUse(u, HRmRead, i->Xin.FpUnary.src);
1086//.. addHRegUse(u, HRmWrite, i->Xin.FpUnary.dst);
1087//.. return;
1088//.. case Xin_FpBinary:
1089//.. addHRegUse(u, HRmRead, i->Xin.FpBinary.srcL);
1090//.. addHRegUse(u, HRmRead, i->Xin.FpBinary.srcR);
1091//.. addHRegUse(u, HRmWrite, i->Xin.FpBinary.dst);
1092//.. return;
1093//.. case Xin_FpLdSt:
1094//.. addRegUsage_X86AMode(u, i->Xin.FpLdSt.addr);
1095//.. addHRegUse(u, i->Xin.FpLdSt.isLoad ? HRmWrite : HRmRead,
1096//.. i->Xin.FpLdSt.reg);
1097//.. return;
1098//.. case Xin_FpLdStI:
1099//.. addRegUsage_X86AMode(u, i->Xin.FpLdStI.addr);
1100//.. addHRegUse(u, i->Xin.FpLdStI.isLoad ? HRmWrite : HRmRead,
1101//.. i->Xin.FpLdStI.reg);
1102//.. return;
1103//.. case Xin_Fp64to32:
1104//.. addHRegUse(u, HRmRead, i->Xin.Fp64to32.src);
1105//.. addHRegUse(u, HRmWrite, i->Xin.Fp64to32.dst);
1106//.. return;
1107//.. case Xin_FpCMov:
1108//.. addHRegUse(u, HRmRead, i->Xin.FpCMov.src);
1109//.. addHRegUse(u, HRmModify, i->Xin.FpCMov.dst);
1110//.. return;
1111//.. case Xin_FpLdStCW:
1112//.. addRegUsage_X86AMode(u, i->Xin.FpLdStCW.addr);
1113//.. return;
1114//.. case Xin_FpStSW_AX:
1115//.. addHRegUse(u, HRmWrite, hregX86_EAX());
1116//.. return;
1117//.. case Xin_FpCmp:
1118//.. addHRegUse(u, HRmRead, i->Xin.FpCmp.srcL);
1119//.. addHRegUse(u, HRmRead, i->Xin.FpCmp.srcR);
1120//.. addHRegUse(u, HRmWrite, i->Xin.FpCmp.dst);
1121//.. addHRegUse(u, HRmWrite, hregX86_EAX());
1122//.. return;
1123//.. case Xin_SseLdSt:
1124//.. addRegUsage_X86AMode(u, i->Xin.SseLdSt.addr);
1125//.. addHRegUse(u, i->Xin.SseLdSt.isLoad ? HRmWrite : HRmRead,
1126//.. i->Xin.SseLdSt.reg);
1127//.. return;
1128//.. case Xin_SseLdzLO:
1129//.. addRegUsage_X86AMode(u, i->Xin.SseLdzLO.addr);
1130//.. addHRegUse(u, HRmWrite, i->Xin.SseLdzLO.reg);
1131//.. return;
1132//.. case Xin_SseConst:
1133//.. addHRegUse(u, HRmWrite, i->Xin.SseConst.dst);
1134//.. return;
1135//.. case Xin_Sse32Fx4:
1136//.. vassert(i->Xin.Sse32Fx4.op != Xsse_MOV);
1137//.. unary = i->Xin.Sse32Fx4.op == Xsse_RCPF
1138//.. || i->Xin.Sse32Fx4.op == Xsse_RSQRTF
1139//.. || i->Xin.Sse32Fx4.op == Xsse_SQRTF;
1140//.. addHRegUse(u, HRmRead, i->Xin.Sse32Fx4.src);
1141//.. addHRegUse(u, unary ? HRmWrite : HRmModify,
1142//.. i->Xin.Sse32Fx4.dst);
1143//.. return;
1144//.. case Xin_Sse32FLo:
1145//.. vassert(i->Xin.Sse32FLo.op != Xsse_MOV);
1146//.. unary = i->Xin.Sse32FLo.op == Xsse_RCPF
1147//.. || i->Xin.Sse32FLo.op == Xsse_RSQRTF
1148//.. || i->Xin.Sse32FLo.op == Xsse_SQRTF;
1149//.. addHRegUse(u, HRmRead, i->Xin.Sse32FLo.src);
1150//.. addHRegUse(u, unary ? HRmWrite : HRmModify,
1151//.. i->Xin.Sse32FLo.dst);
1152//.. return;
1153//.. case Xin_Sse64Fx2:
1154//.. vassert(i->Xin.Sse64Fx2.op != Xsse_MOV);
1155//.. unary = i->Xin.Sse64Fx2.op == Xsse_RCPF
1156//.. || i->Xin.Sse64Fx2.op == Xsse_RSQRTF
1157//.. || i->Xin.Sse64Fx2.op == Xsse_SQRTF;
1158//.. addHRegUse(u, HRmRead, i->Xin.Sse64Fx2.src);
1159//.. addHRegUse(u, unary ? HRmWrite : HRmModify,
1160//.. i->Xin.Sse64Fx2.dst);
1161//.. return;
1162//.. case Xin_Sse64FLo:
1163//.. vassert(i->Xin.Sse64FLo.op != Xsse_MOV);
1164//.. unary = i->Xin.Sse64FLo.op == Xsse_RCPF
1165//.. || i->Xin.Sse64FLo.op == Xsse_RSQRTF
1166//.. || i->Xin.Sse64FLo.op == Xsse_SQRTF;
1167//.. addHRegUse(u, HRmRead, i->Xin.Sse64FLo.src);
1168//.. addHRegUse(u, unary ? HRmWrite : HRmModify,
1169//.. i->Xin.Sse64FLo.dst);
1170//.. return;
1171//.. case Xin_SseReRg:
1172//.. if (i->Xin.SseReRg.op == Xsse_XOR
1173//.. && i->Xin.SseReRg.src == i->Xin.SseReRg.dst) {
1174//.. /* reg-alloc needs to understand 'xor r,r' as a write of r */
1175//.. /* (as opposed to a rite of passage :-) */
1176//.. addHRegUse(u, HRmWrite, i->Xin.SseReRg.dst);
1177//.. } else {
1178//.. addHRegUse(u, HRmRead, i->Xin.SseReRg.src);
1179//.. addHRegUse(u, i->Xin.SseReRg.op == Xsse_MOV
1180//.. ? HRmWrite : HRmModify,
1181//.. i->Xin.SseReRg.dst);
1182//.. }
1183//.. return;
1184//.. case Xin_SseCMov:
1185//.. addHRegUse(u, HRmRead, i->Xin.SseCMov.src);
1186//.. addHRegUse(u, HRmModify, i->Xin.SseCMov.dst);
1187//.. return;
1188//.. case Xin_SseShuf:
1189//.. addHRegUse(u, HRmRead, i->Xin.SseShuf.src);
1190//.. addHRegUse(u, HRmWrite, i->Xin.SseShuf.dst);
1191//.. return;
1192 default:
1193 ppPPC32Instr(i);
1194 vpanic("getRegUsage_PPC32Instr");
1195 }
1196}
1197
cerioncd304492005-02-08 19:40:24 +00001198/* local helper */
1199static void mapReg(HRegRemap* m, HReg* r)
1200{
1201 *r = lookupHRegRemap(m, *r);
1202}
cerionbcf8c3e2005-02-04 16:17:07 +00001203
1204void mapRegs_PPC32Instr (HRegRemap* m, PPC32Instr* i)
1205{
1206 switch (i->tag) {
cerioncd304492005-02-08 19:40:24 +00001207 case Pin_Alu32:
1208 mapReg(m, &i->Pin.Alu32.dst);
1209 mapReg(m, &i->Pin.Alu32.src1);
1210 mapRegs_PPC32RI(m, i->Pin.Alu32.src2);
1211 return;
1212 case Pin_Sh32:
1213 mapReg(m, &i->Pin.Sh32.dst);
1214 mapReg(m, &i->Pin.Sh32.src);
1215 mapRegs_PPC32RI(m, i->Pin.Sh32.shft);
1216 return;
cerion2c49e032005-02-09 17:29:49 +00001217 case Pin_Test32:
1218 mapReg(m, &i->Pin.Test32.dst);
1219 mapRegs_PPC32RI(m, i->Pin.Test32.src);
1220 return;
cerionb536af92005-02-10 15:03:19 +00001221 case Pin_Unary32:
1222 mapReg(m, &i->Pin.Unary32.dst);
cerione13bb312005-02-10 19:51:03 +00001223 mapReg(m, &i->Pin.Unary32.src);
cerionb536af92005-02-10 15:03:19 +00001224 return;
cerion92f5dc72005-02-10 16:11:35 +00001225 case Pin_MulL:
1226 mapReg(m, &i->Pin.MulL.dst);
1227 mapReg(m, &i->Pin.MulL.src1);
1228 mapRegs_PPC32RI(m, i->Pin.MulL.src2);
1229 return;
cerionc0e707e2005-02-10 22:35:34 +00001230 case Pin_Div:
1231 mapReg(m, &i->Pin.Div.dst);
1232 mapReg(m, &i->Pin.Div.src1);
1233 mapRegs_PPC32RI(m, i->Pin.Div.src2);
1234 return;
cerionbcf8c3e2005-02-04 16:17:07 +00001235//.. case Xin_Sh3232:
1236//.. mapReg(m, &i->Xin.Sh3232.src);
1237//.. mapReg(m, &i->Xin.Sh3232.dst);
1238//.. return;
1239//.. case Xin_Push:
1240//.. mapRegs_X86RMI(m, i->Xin.Push.src);
1241//.. return;
cerion2c49e032005-02-09 17:29:49 +00001242 case Pin_Call:
1243 return;
1244 case Pin_Goto:
1245 mapRegs_PPC32RI(m, i->Pin.Goto.dst);
1246 return;
cerionb536af92005-02-10 15:03:19 +00001247 case Pin_CMov32:
1248 mapRegs_PPC32RI(m, i->Pin.CMov32.src);
1249 mapReg(m, &i->Pin.CMov32.dst);
1250 return;
cerion2c49e032005-02-09 17:29:49 +00001251 case Pin_LoadEX:
1252 mapRegs_PPC32AMode(m, i->Pin.LoadEX.src);
1253 mapReg(m, &i->Pin.LoadEX.dst);
1254 return;
1255 case Pin_Store:
1256 mapReg(m, &i->Pin.Store.src);
1257 mapRegs_PPC32AMode(m, i->Pin.Store.dst);
1258 return;
cerionb536af92005-02-10 15:03:19 +00001259 case Pin_Set32:
1260 mapReg(m, &i->Pin.Set32.dst);
1261 return;
cerionbcf8c3e2005-02-04 16:17:07 +00001262//.. case Xin_Bsfr32:
1263//.. mapReg(m, &i->Xin.Bsfr32.src);
1264//.. mapReg(m, &i->Xin.Bsfr32.dst);
1265//.. return;
cerion92f5dc72005-02-10 16:11:35 +00001266 case Pin_MFence:
1267 return;
cerionbcf8c3e2005-02-04 16:17:07 +00001268//.. case Xin_FpUnary:
1269//.. mapReg(m, &i->Xin.FpUnary.src);
1270//.. mapReg(m, &i->Xin.FpUnary.dst);
1271//.. return;
1272//.. case Xin_FpBinary:
1273//.. mapReg(m, &i->Xin.FpBinary.srcL);
1274//.. mapReg(m, &i->Xin.FpBinary.srcR);
1275//.. mapReg(m, &i->Xin.FpBinary.dst);
1276//.. return;
1277//.. case Xin_FpLdSt:
1278//.. mapRegs_X86AMode(m, i->Xin.FpLdSt.addr);
1279//.. mapReg(m, &i->Xin.FpLdSt.reg);
1280//.. return;
1281//.. case Xin_FpLdStI:
1282//.. mapRegs_X86AMode(m, i->Xin.FpLdStI.addr);
1283//.. mapReg(m, &i->Xin.FpLdStI.reg);
1284//.. return;
1285//.. case Xin_Fp64to32:
1286//.. mapReg(m, &i->Xin.Fp64to32.src);
1287//.. mapReg(m, &i->Xin.Fp64to32.dst);
1288//.. return;
1289//.. case Xin_FpCMov:
1290//.. mapReg(m, &i->Xin.FpCMov.src);
1291//.. mapReg(m, &i->Xin.FpCMov.dst);
1292//.. return;
1293//.. case Xin_FpLdStCW:
1294//.. mapRegs_X86AMode(m, i->Xin.FpLdStCW.addr);
1295//.. return;
1296//.. case Xin_FpStSW_AX:
1297//.. return;
1298//.. case Xin_FpCmp:
1299//.. mapReg(m, &i->Xin.FpCmp.srcL);
1300//.. mapReg(m, &i->Xin.FpCmp.srcR);
1301//.. mapReg(m, &i->Xin.FpCmp.dst);
1302//.. return;
1303//.. case Xin_SseConst:
1304//.. mapReg(m, &i->Xin.SseConst.dst);
1305//.. return;
1306//.. case Xin_SseLdSt:
1307//.. mapReg(m, &i->Xin.SseLdSt.reg);
1308//.. mapRegs_X86AMode(m, i->Xin.SseLdSt.addr);
1309//.. break;
1310//.. case Xin_SseLdzLO:
1311//.. mapReg(m, &i->Xin.SseLdzLO.reg);
1312//.. mapRegs_X86AMode(m, i->Xin.SseLdzLO.addr);
1313//.. break;
1314//.. case Xin_Sse32Fx4:
1315//.. mapReg(m, &i->Xin.Sse32Fx4.src);
1316//.. mapReg(m, &i->Xin.Sse32Fx4.dst);
1317//.. return;
1318//.. case Xin_Sse32FLo:
1319//.. mapReg(m, &i->Xin.Sse32FLo.src);
1320//.. mapReg(m, &i->Xin.Sse32FLo.dst);
1321//.. return;
1322//.. case Xin_Sse64Fx2:
1323//.. mapReg(m, &i->Xin.Sse64Fx2.src);
1324//.. mapReg(m, &i->Xin.Sse64Fx2.dst);
1325//.. return;
1326//.. case Xin_Sse64FLo:
1327//.. mapReg(m, &i->Xin.Sse64FLo.src);
1328//.. mapReg(m, &i->Xin.Sse64FLo.dst);
1329//.. return;
1330//.. case Xin_SseReRg:
1331//.. mapReg(m, &i->Xin.SseReRg.src);
1332//.. mapReg(m, &i->Xin.SseReRg.dst);
1333//.. return;
1334//.. case Xin_SseCMov:
1335//.. mapReg(m, &i->Xin.SseCMov.src);
1336//.. mapReg(m, &i->Xin.SseCMov.dst);
1337//.. return;
1338//.. case Xin_SseShuf:
1339//.. mapReg(m, &i->Xin.SseShuf.src);
1340//.. mapReg(m, &i->Xin.SseShuf.dst);
1341//.. return;
1342 default:
1343 ppPPC32Instr(i);
1344 vpanic("mapRegs_PPC32Instr");
1345 }
1346}
1347
1348/* Figure out if i represents a reg-reg move, and if so assign the
1349 source and destination to *src and *dst. If in doubt say No. Used
1350 by the register allocator to do move coalescing.
1351*/
1352Bool isMove_PPC32Instr ( PPC32Instr* i, HReg* src, HReg* dst )
1353{
1354//.. /* Moves between integer regs */
1355//.. if (i->tag == Xin_Alu32R) {
1356//.. if (i->Xin.Alu32R.op != Xalu_MOV)
1357//.. return False;
1358//.. if (i->Xin.Alu32R.src->tag != Xrmi_Reg)
1359//.. return False;
1360//.. *src = i->Xin.Alu32R.src->Xrmi.Reg.reg;
1361//.. *dst = i->Xin.Alu32R.dst;
1362//.. return True;
1363//.. }
1364//.. /* Moves between FP regs */
1365//.. if (i->tag == Xin_FpUnary) {
1366//.. if (i->Xin.FpUnary.op != Xfp_MOV)
1367//.. return False;
1368//.. *src = i->Xin.FpUnary.src;
1369//.. *dst = i->Xin.FpUnary.dst;
1370//.. return True;
1371//.. }
1372//.. if (i->tag == Xin_SseReRg) {
1373//.. if (i->Xin.SseReRg.op != Xsse_MOV)
1374//.. return False;
1375//.. *src = i->Xin.SseReRg.src;
1376//.. *dst = i->Xin.SseReRg.dst;
1377//.. return True;
1378//.. }
1379 return False;
1380}
1381
1382
cerione13bb312005-02-10 19:51:03 +00001383/* Generate ppc32 spill/reload instructions under the direction of the
cerionbcf8c3e2005-02-04 16:17:07 +00001384 register allocator. Note it's critical these don't write the
1385 condition codes. */
1386
1387PPC32Instr* genSpill_PPC32 ( HReg rreg, Int offsetB )
cerione13bb312005-02-10 19:51:03 +00001388{
1389 PPC32AMode* am;
1390 vassert(offsetB >= 0);
1391 vassert(!hregIsVirtual(rreg));
1392 am = PPC32AMode_IR(offsetB, GuestStatePtr);
1393
1394 switch (hregClass(rreg)) {
1395 case HRcInt32:
1396 return PPC32Instr_Store( 4, am, rreg);
1397 //case HRcFlt64:
1398 // return PPC32Instr_FpLdSt ( False/*store*/, 8, rreg, am );
1399 //case HRcVec128:
1400 // return PPC32Instr_SseLdSt ( False/*store*/, rreg, am );
1401 default:
1402 ppHRegClass(hregClass(rreg));
1403 vpanic("genSpill_PPC32: unimplemented regclass");
1404 }
cerionbcf8c3e2005-02-04 16:17:07 +00001405}
1406
1407PPC32Instr* genReload_PPC32 ( HReg rreg, Int offsetB )
cerione13bb312005-02-10 19:51:03 +00001408{
1409 PPC32AMode* am;
1410 vassert(offsetB >= 0);
1411 vassert(!hregIsVirtual(rreg));
1412 am = PPC32AMode_IR(offsetB, GuestStatePtr);
1413
1414 switch (hregClass(rreg)) {
1415 case HRcInt32:
1416 return PPC32Instr_LoadEX( 4, False, rreg, am );
1417 //case HRcFlt64:
1418 // return PPC32Instr_FpLdSt ( True/*load*/, 8, rreg, am );
1419 //case HRcVec128:
1420 // return PPC32Instr_SseLdSt ( True/*load*/, rreg, am );
1421 default:
1422 ppHRegClass(hregClass(rreg));
1423 vpanic("genReload_PPC32: unimplemented regclass");
1424 }
cerionbcf8c3e2005-02-04 16:17:07 +00001425}
1426
1427
ceriond5e38382005-02-11 13:38:15 +00001428/* --------- The ppc32 assembler (bleh.) --------- */
cerioncd304492005-02-08 19:40:24 +00001429
cerioncd304492005-02-08 19:40:24 +00001430static UInt iregNo ( HReg r )
1431{
1432 UInt n;
1433 vassert(hregClass(r) == HRcInt32);
1434 vassert(!hregIsVirtual(r));
1435 n = hregNumber(r);
1436 vassert(n <= 32);
1437 return n;
1438}
cerioncd304492005-02-08 19:40:24 +00001439
cerionbcf8c3e2005-02-04 16:17:07 +00001440//.. static UInt fregNo ( HReg r )
1441//.. {
1442//.. UInt n;
1443//.. vassert(hregClass(r) == HRcFlt64);
1444//.. vassert(!hregIsVirtual(r));
1445//.. n = hregNumber(r);
1446//.. vassert(n <= 5);
1447//.. return n;
1448//.. }
cerioncd304492005-02-08 19:40:24 +00001449
cerionbcf8c3e2005-02-04 16:17:07 +00001450//.. static UInt vregNo ( HReg r )
1451//.. {
1452//.. UInt n;
1453//.. vassert(hregClass(r) == HRcVec128);
1454//.. vassert(!hregIsVirtual(r));
1455//.. n = hregNumber(r);
1456//.. vassert(n <= 7);
1457//.. return n;
1458//.. }
cerioncd304492005-02-08 19:40:24 +00001459
cerionbcf8c3e2005-02-04 16:17:07 +00001460//.. static UChar mkModRegRM ( UChar mod, UChar reg, UChar regmem )
1461//.. {
1462//.. return ((mod & 3) << 6) | ((reg & 7) << 3) | (regmem & 7);
1463//.. }
cerioncd304492005-02-08 19:40:24 +00001464
cerionbcf8c3e2005-02-04 16:17:07 +00001465//.. static UChar mkSIB ( Int shift, Int regindex, Int regbase )
1466//.. {
1467//.. return ((shift & 3) << 6) | ((regindex & 7) << 3) | (regbase & 7);
1468//.. }
cerioncd304492005-02-08 19:40:24 +00001469
cerionc056a882005-02-11 13:55:41 +00001470/* Emit 32bit instruction for big-endian host */
ceriond5e38382005-02-11 13:38:15 +00001471static UChar* emit32 ( UChar* p, UInt w32 )
1472{
ceriond5e38382005-02-11 13:38:15 +00001473 *p++ = (w32 >> 24) & 0x000000FF;
cerionc056a882005-02-11 13:55:41 +00001474 *p++ = (w32 >> 16) & 0x000000FF;
1475 *p++ = (w32 >> 8) & 0x000000FF;
1476 *p++ = (w32) & 0x000000FF;
ceriond5e38382005-02-11 13:38:15 +00001477 return p;
1478}
cerioncd304492005-02-08 19:40:24 +00001479
cerionbcf8c3e2005-02-04 16:17:07 +00001480//.. /* Does a sign-extend of the lowest 8 bits give
1481//.. the original number? */
1482//.. static Bool fits8bits ( UInt w32 )
1483//.. {
1484//.. Int i32 = (Int)w32;
1485//.. return i32 == ((i32 << 24) >> 24);
1486//.. }
cerioncd304492005-02-08 19:40:24 +00001487
1488
cerionbcf8c3e2005-02-04 16:17:07 +00001489//.. /* Forming mod-reg-rm bytes and scale-index-base bytes.
1490//..
1491//.. greg, 0(ereg) | ereg != ESP && ereg != EBP
1492//.. = 00 greg ereg
1493//..
1494//.. greg, d8(ereg) | ereg != ESP
1495//.. = 01 greg ereg, d8
1496//..
1497//.. greg, d32(ereg) | ereg != ESP
1498//.. = 10 greg ereg, d32
1499//..
1500//.. greg, d8(%esp) = 01 greg 100, 0x24, d8
1501//..
1502//.. -----------------------------------------------
1503//..
1504//.. greg, d8(base,index,scale)
1505//.. | index != ESP
1506//.. = 01 greg 100, scale index base, d8
1507//..
1508//.. greg, d32(base,index,scale)
1509//.. | index != ESP
1510//.. = 10 greg 100, scale index base, d32
1511//.. */
1512//.. static UChar* doAMode_M ( UChar* p, HReg greg, X86AMode* am )
1513//.. {
1514//.. if (am->tag == Xam_IR) {
1515//.. if (am->Xam.IR.imm == 0
1516//.. && am->Xam.IR.reg != hregX86_ESP()
1517//.. && am->Xam.IR.reg != hregX86_EBP() ) {
1518//.. *p++ = mkModRegRM(0, iregNo(greg), iregNo(am->Xam.IR.reg));
1519//.. return p;
1520//.. }
1521//.. if (fits8bits(am->Xam.IR.imm)
1522//.. && am->Xam.IR.reg != hregX86_ESP()) {
1523//.. *p++ = mkModRegRM(1, iregNo(greg), iregNo(am->Xam.IR.reg));
1524//.. *p++ = am->Xam.IR.imm & 0xFF;
1525//.. return p;
1526//.. }
1527//.. if (am->Xam.IR.reg != hregX86_ESP()) {
1528//.. *p++ = mkModRegRM(2, iregNo(greg), iregNo(am->Xam.IR.reg));
1529//.. p = emit32(p, am->Xam.IR.imm);
1530//.. return p;
1531//.. }
1532//.. if (am->Xam.IR.reg == hregX86_ESP()
1533//.. && fits8bits(am->Xam.IR.imm)) {
1534//.. *p++ = mkModRegRM(1, iregNo(greg), 4);
1535//.. *p++ = 0x24;
1536//.. *p++ = am->Xam.IR.imm & 0xFF;
1537//.. return p;
1538//.. }
1539//.. ppX86AMode(am);
1540//.. vpanic("doAMode_M: can't emit amode IR");
1541//.. /*NOTREACHED*/
1542//.. }
1543//.. if (am->tag == Xam_IRRS) {
1544//.. if (fits8bits(am->Xam.IRRS.imm)
1545//.. && am->Xam.IRRS.index != hregX86_ESP()) {
1546//.. *p++ = mkModRegRM(1, iregNo(greg), 4);
1547//.. *p++ = mkSIB(am->Xam.IRRS.shift, am->Xam.IRRS.index,
1548//.. am->Xam.IRRS.base);
1549//.. *p++ = am->Xam.IRRS.imm & 0xFF;
1550//.. return p;
1551//.. }
1552//.. if (am->Xam.IRRS.index != hregX86_ESP()) {
1553//.. *p++ = mkModRegRM(2, iregNo(greg), 4);
1554//.. *p++ = mkSIB(am->Xam.IRRS.shift, am->Xam.IRRS.index,
1555//.. am->Xam.IRRS.base);
1556//.. p = emit32(p, am->Xam.IRRS.imm);
1557//.. return p;
1558//.. }
1559//.. ppX86AMode(am);
1560//.. vpanic("doAMode_M: can't emit amode IRRS");
1561//.. /*NOTREACHED*/
1562//.. }
1563//.. vpanic("doAMode_M: unknown amode");
1564//.. /*NOTREACHED*/
1565//.. }
cerioncd304492005-02-08 19:40:24 +00001566
1567
cerionbcf8c3e2005-02-04 16:17:07 +00001568//.. /* Emit a mod-reg-rm byte when the rm bit denotes a reg. */
1569//.. static UChar* doAMode_R ( UChar* p, HReg greg, HReg ereg )
1570//.. {
1571//.. *p++ = mkModRegRM(3, iregNo(greg), iregNo(ereg));
1572//.. return p;
1573//.. }
cerioncd304492005-02-08 19:40:24 +00001574
1575
cerionbcf8c3e2005-02-04 16:17:07 +00001576//.. /* Emit ffree %st(7) */
1577//.. static UChar* do_ffree_st7 ( UChar* p )
1578//.. {
1579//.. *p++ = 0xDD;
1580//.. *p++ = 0xC7;
1581//.. return p;
1582//.. }
cerioncd304492005-02-08 19:40:24 +00001583
cerionbcf8c3e2005-02-04 16:17:07 +00001584//.. /* Emit fstp %st(i), 1 <= i <= 7 */
1585//.. static UChar* do_fstp_st ( UChar* p, Int i )
1586//.. {
1587//.. vassert(1 <= i && i <= 7);
1588//.. *p++ = 0xDD;
1589//.. *p++ = 0xD8+i;
1590//.. return p;
1591//.. }
cerioncd304492005-02-08 19:40:24 +00001592
cerionbcf8c3e2005-02-04 16:17:07 +00001593//.. /* Emit fld %st(i), 0 <= i <= 6 */
1594//.. static UChar* do_fld_st ( UChar* p, Int i )
1595//.. {
1596//.. vassert(0 <= i && i <= 6);
1597//.. *p++ = 0xD9;
1598//.. *p++ = 0xC0+i;
1599//.. return p;
1600//.. }
cerioncd304492005-02-08 19:40:24 +00001601
cerionbcf8c3e2005-02-04 16:17:07 +00001602//.. /* Emit f<op> %st(0) */
1603//.. static UChar* do_fop1_st ( UChar* p, X86FpOp op )
1604//.. {
1605//.. switch (op) {
1606//.. case Xfp_NEG: *p++ = 0xD9; *p++ = 0xE0; break;
1607//.. case Xfp_ABS: *p++ = 0xD9; *p++ = 0xE1; break;
1608//.. case Xfp_SQRT: *p++ = 0xD9; *p++ = 0xFA; break;
1609//.. case Xfp_ROUND: *p++ = 0xD9; *p++ = 0xFC; break;
1610//.. case Xfp_SIN: *p++ = 0xD9; *p++ = 0xFE; break;
1611//.. case Xfp_COS: *p++ = 0xD9; *p++ = 0xFF; break;
1612//.. case Xfp_2XM1: *p++ = 0xD9; *p++ = 0xF0; break;
1613//.. case Xfp_MOV: break;
1614//.. case Xfp_TAN: p = do_ffree_st7(p); /* since fptan pushes 1.0 */
1615//.. *p++ = 0xD9; *p++ = 0xF2; /* fptan */
1616//.. *p++ = 0xD9; *p++ = 0xF7; /* fincstp */
1617//.. break;
1618//.. default: vpanic("do_fop1_st: unknown op");
1619//.. }
1620//.. return p;
1621//.. }
cerioncd304492005-02-08 19:40:24 +00001622
cerionbcf8c3e2005-02-04 16:17:07 +00001623//.. /* Emit f<op> %st(i), 1 <= i <= 5 */
1624//.. static UChar* do_fop2_st ( UChar* p, X86FpOp op, Int i )
1625//.. {
1626//.. # define fake(_n) mkHReg((_n), HRcInt32, False)
1627//.. Int subopc;
1628//.. switch (op) {
1629//.. case Xfp_ADD: subopc = 0; break;
1630//.. case Xfp_SUB: subopc = 4; break;
1631//.. case Xfp_MUL: subopc = 1; break;
1632//.. case Xfp_DIV: subopc = 6; break;
1633//.. default: vpanic("do_fop2_st: unknown op");
1634//.. }
1635//.. *p++ = 0xD8;
1636//.. p = doAMode_R(p, fake(subopc), fake(i));
1637//.. return p;
1638//.. # undef fake
1639//.. }
cerioncd304492005-02-08 19:40:24 +00001640
cerionbcf8c3e2005-02-04 16:17:07 +00001641//.. /* Push a 32-bit word on the stack. The word depends on tags[3:0];
1642//.. each byte is either 0x00 or 0xFF depending on the corresponding bit in tags[].
1643//.. */
1644//.. static UChar* push_word_from_tags ( UChar* p, UShort tags )
1645//.. {
1646//.. UInt w;
1647//.. vassert(0 == (tags & ~0xF));
1648//.. if (tags == 0) {
1649//.. /* pushl $0x00000000 */
1650//.. *p++ = 0x6A;
1651//.. *p++ = 0x00;
1652//.. }
1653//.. else
1654//.. /* pushl $0xFFFFFFFF */
1655//.. if (tags == 0xF) {
1656//.. *p++ = 0x6A;
1657//.. *p++ = 0xFF;
1658//.. } else {
1659//.. vassert(0); /* awaiting test case */
1660//.. w = 0;
1661//.. if (tags & 1) w |= 0x000000FF;
1662//.. if (tags & 2) w |= 0x0000FF00;
1663//.. if (tags & 4) w |= 0x00FF0000;
1664//.. if (tags & 8) w |= 0xFF000000;
1665//.. *p++ = 0x68;
1666//.. p = emit32(p, w);
1667//.. }
1668//.. return p;
1669//.. }
1670
ceriond5e38382005-02-11 13:38:15 +00001671static UChar* mkFormD ( UChar* p, UInt op1, UInt r1, UInt r2, UInt imm )
1672{
1673 vassert(op1 < 0x40);
1674 vassert(r1 < 0x20);
1675 vassert(r2 < 0x20);
1676 vassert(imm < 0x10000);
1677 UInt theInstr = ((op1<<26) | (r1<<21) | (r2<<16) | (imm));
1678 return emit32(p, theInstr);
1679}
1680
1681static UChar* mkFormX ( UChar* p, UInt op1, UInt r1, UInt r2,
1682 UInt r3, UInt op2, UInt b0 )
1683{
1684 vassert(op1 < 0x40);
1685 vassert(r1 < 0x20);
1686 vassert(r2 < 0x20);
1687 vassert(r3 < 0x20);
1688 vassert(op2 < 0x400);
1689 vassert(b0 < 0x2);
1690 UInt theInstr = ((op1<<26) | (r1<<21) | (r2<<16) |
1691 (r3<<11) | (op2<<1) | (b0));
1692 return emit32(p, theInstr);
1693}
1694
1695
1696static UChar* doAMode_IR ( UChar* p, UInt op1, HReg hrSD, PPC32AMode* am )
1697{
1698 vassert(am->tag == Pam_IR);
1699 UInt rSD = iregNo(hrSD);
1700 UInt rA = iregNo(am->Pam.IR.base);
1701 UInt idx = am->Pam.IR.index;
1702 vassert(idx < 0x10000);
1703
1704 p = mkFormD(p, op1, rSD, rA, idx);
1705 return p;
1706}
1707
1708
1709static UChar* doAMode_RR ( UChar* p, UInt op1, UInt op2,
1710 HReg hrSD, PPC32AMode* am )
1711{
1712// vassert(hregClass(hrSD) == HRcInt32); // CAB: worth doing this?
1713 vassert(am->tag == Pam_RR);
1714 UInt rSD = iregNo(hrSD);
1715 UInt rA = iregNo(am->Pam.RR.base);
1716 UInt rB = iregNo(am->Pam.RR.index);
1717
1718 p = mkFormX(p, op1, rSD, rA, rB, op2, 0);
1719 return p;
1720}
1721
1722
cerionbcf8c3e2005-02-04 16:17:07 +00001723/* Emit an instruction into buf and return the number of bytes used.
1724 Note that buf is not the insn's final place, and therefore it is
1725 imperative to emit position-independent code. */
1726
1727Int emit_PPC32Instr ( UChar* buf, Int nbuf, PPC32Instr* i )
1728{
1729//.. UInt irno, opc, opc_rr, subopc_imm, opc_imma, opc_cl, opc_imm, subopc;
1730//..
1731//.. UInt xtra;
1732 UChar* p = &buf[0];
1733//.. UChar* ptmp;
1734//.. vassert(nbuf >= 32);
1735//..
1736//.. /* Wrap an integer as a int register, for use assembling
1737//.. GrpN insns, in which the greg field is used as a sub-opcode
1738//.. and does not really contain a register. */
1739//.. # define fake(_n) mkHReg((_n), HRcInt32, False)
cerion2c49e032005-02-09 17:29:49 +00001740
1741 vex_printf("asm ");ppPPC32Instr(i); vex_printf("\n");
cerionbcf8c3e2005-02-04 16:17:07 +00001742
1743 switch (i->tag) {
1744
1745//.. case Xin_Alu32R:
1746//.. /* Deal specially with MOV */
1747//.. if (i->Xin.Alu32R.op == Xalu_MOV) {
1748//.. switch (i->Xin.Alu32R.src->tag) {
1749//.. case Xrmi_Imm:
1750//.. *p++ = 0xB8 + iregNo(i->Xin.Alu32R.dst);
1751//.. p = emit32(p, i->Xin.Alu32R.src->Xrmi.Imm.imm32);
1752//.. goto done;
1753//.. case Xrmi_Reg:
1754//.. *p++ = 0x89;
1755//.. p = doAMode_R(p, i->Xin.Alu32R.src->Xrmi.Reg.reg,
1756//.. i->Xin.Alu32R.dst);
1757//.. goto done;
1758//.. case Xrmi_Mem:
1759//.. *p++ = 0x8B;
1760//.. p = doAMode_M(p, i->Xin.Alu32R.dst,
1761//.. i->Xin.Alu32R.src->Xrmi.Mem.am);
1762//.. goto done;
1763//.. default:
1764//.. goto bad;
1765//.. }
1766//.. }
1767//.. /* MUL */
1768//.. if (i->Xin.Alu32R.op == Xalu_MUL) {
1769//.. switch (i->Xin.Alu32R.src->tag) {
1770//.. case Xrmi_Reg:
1771//.. *p++ = 0x0F;
1772//.. *p++ = 0xAF;
1773//.. p = doAMode_R(p, i->Xin.Alu32R.dst,
1774//.. i->Xin.Alu32R.src->Xrmi.Reg.reg);
1775//.. goto done;
1776//.. case Xrmi_Mem:
1777//.. *p++ = 0x0F;
1778//.. *p++ = 0xAF;
1779//.. p = doAMode_M(p, i->Xin.Alu32R.dst,
1780//.. i->Xin.Alu32R.src->Xrmi.Mem.am);
1781//.. goto done;
1782//.. case Xrmi_Imm:
1783//.. if (fits8bits(i->Xin.Alu32R.src->Xrmi.Imm.imm32)) {
1784//.. *p++ = 0x6B;
1785//.. p = doAMode_R(p, i->Xin.Alu32R.dst, i->Xin.Alu32R.dst);
1786//.. *p++ = 0xFF & i->Xin.Alu32R.src->Xrmi.Imm.imm32;
1787//.. } else {
1788//.. *p++ = 0x69;
1789//.. p = doAMode_R(p, i->Xin.Alu32R.dst, i->Xin.Alu32R.dst);
1790//.. p = emit32(p, i->Xin.Alu32R.src->Xrmi.Imm.imm32);
1791//.. }
1792//.. goto done;
1793//.. default:
1794//.. goto bad;
1795//.. }
1796//.. }
1797//.. /* ADD/SUB/ADC/SBB/AND/OR/XOR/CMP */
1798//.. opc = opc_rr = subopc_imm = opc_imma = 0;
1799//.. switch (i->Xin.Alu32R.op) {
1800//.. case Xalu_ADC: opc = 0x13; opc_rr = 0x11;
1801//.. subopc_imm = 2; opc_imma = 0x15; break;
1802//.. case Xalu_ADD: opc = 0x03; opc_rr = 0x01;
1803//.. subopc_imm = 0; opc_imma = 0x05; break;
1804//.. case Xalu_SUB: opc = 0x2B; opc_rr = 0x29;
1805//.. subopc_imm = 5; opc_imma = 0x2D; break;
1806//.. case Xalu_SBB: opc = 0x1B; opc_rr = 0x19;
1807//.. subopc_imm = 3; opc_imma = 0x1D; break;
1808//.. case Xalu_AND: opc = 0x23; opc_rr = 0x21;
1809//.. subopc_imm = 4; opc_imma = 0x25; break;
1810//.. case Xalu_XOR: opc = 0x33; opc_rr = 0x31;
1811//.. subopc_imm = 6; opc_imma = 0x35; break;
1812//.. case Xalu_OR: opc = 0x0B; opc_rr = 0x09;
1813//.. subopc_imm = 1; opc_imma = 0x0D; break;
1814//.. case Xalu_CMP: opc = 0x3B; opc_rr = 0x39;
1815//.. subopc_imm = 7; opc_imma = 0x3D; break;
1816//.. default: goto bad;
1817//.. }
1818//.. switch (i->Xin.Alu32R.src->tag) {
1819//.. case Xrmi_Imm:
1820//.. if (i->Xin.Alu32R.dst == hregX86_EAX()
1821//.. && !fits8bits(i->Xin.Alu32R.src->Xrmi.Imm.imm32)) {
1822//.. *p++ = opc_imma;
1823//.. p = emit32(p, i->Xin.Alu32R.src->Xrmi.Imm.imm32);
1824//.. } else
1825//.. if (fits8bits(i->Xin.Alu32R.src->Xrmi.Imm.imm32)) {
1826//.. *p++ = 0x83;
1827//.. p = doAMode_R(p, fake(subopc_imm), i->Xin.Alu32R.dst);
1828//.. *p++ = 0xFF & i->Xin.Alu32R.src->Xrmi.Imm.imm32;
1829//.. } else {
1830//.. *p++ = 0x81;
1831//.. p = doAMode_R(p, fake(subopc_imm), i->Xin.Alu32R.dst);
1832//.. p = emit32(p, i->Xin.Alu32R.src->Xrmi.Imm.imm32);
1833//.. }
1834//.. goto done;
1835//.. case Xrmi_Reg:
1836//.. *p++ = opc_rr;
1837//.. p = doAMode_R(p, i->Xin.Alu32R.src->Xrmi.Reg.reg,
1838//.. i->Xin.Alu32R.dst);
1839//.. goto done;
1840//.. case Xrmi_Mem:
1841//.. *p++ = opc;
1842//.. p = doAMode_M(p, i->Xin.Alu32R.dst,
1843//.. i->Xin.Alu32R.src->Xrmi.Mem.am);
1844//.. goto done;
1845//.. default:
1846//.. goto bad;
1847//.. }
1848//.. break;
cerion2c49e032005-02-09 17:29:49 +00001849
cerionbcf8c3e2005-02-04 16:17:07 +00001850//.. case Xin_Alu32M:
1851//.. /* Deal specially with MOV */
1852//.. if (i->Xin.Alu32M.op == Xalu_MOV) {
1853//.. switch (i->Xin.Alu32M.src->tag) {
1854//.. case Xri_Reg:
1855//.. *p++ = 0x89;
1856//.. p = doAMode_M(p, i->Xin.Alu32M.src->Xri.Reg.reg,
1857//.. i->Xin.Alu32M.dst);
1858//.. goto done;
1859//.. case Xri_Imm:
1860//.. *p++ = 0xC7;
1861//.. p = doAMode_M(p, fake(0), i->Xin.Alu32M.dst);
1862//.. p = emit32(p, i->Xin.Alu32M.src->Xri.Imm.imm32);
1863//.. goto done;
1864//.. default:
1865//.. goto bad;
1866//.. }
1867//.. }
1868//.. /* ADD/SUB/ADC/SBB/AND/OR/XOR/CMP. MUL is not
1869//.. allowed here. */
1870//.. opc = subopc_imm = opc_imma = 0;
1871//.. switch (i->Xin.Alu32M.op) {
1872//.. case Xalu_ADD: opc = 0x01; subopc_imm = 0; break;
1873//.. case Xalu_SUB: opc = 0x29; subopc_imm = 5; break;
1874//.. default: goto bad;
1875//.. }
1876//.. switch (i->Xin.Alu32M.src->tag) {
1877//.. case Xri_Reg:
1878//.. *p++ = opc;
1879//.. p = doAMode_M(p, i->Xin.Alu32M.src->Xri.Reg.reg,
1880//.. i->Xin.Alu32M.dst);
1881//.. goto done;
1882//.. case Xri_Imm:
1883//.. if (fits8bits(i->Xin.Alu32M.src->Xri.Imm.imm32)) {
1884//.. *p++ = 0x83;
1885//.. p = doAMode_M(p, fake(subopc_imm), i->Xin.Alu32M.dst);
1886//.. *p++ = 0xFF & i->Xin.Alu32M.src->Xri.Imm.imm32;
1887//.. goto done;
1888//.. } else {
1889//.. *p++ = 0x81;
1890//.. p = doAMode_M(p, fake(subopc_imm), i->Xin.Alu32M.dst);
1891//.. p = emit32(p, i->Xin.Alu32M.src->Xri.Imm.imm32);
1892//.. goto done;
1893//.. }
1894//.. default:
1895//.. goto bad;
1896//.. }
1897//.. break;
cerion2c49e032005-02-09 17:29:49 +00001898
cerionbcf8c3e2005-02-04 16:17:07 +00001899//.. case Xin_Sh32:
1900//.. opc_cl = opc_imm = subopc = 0;
1901//.. switch (i->Xin.Sh32.op) {
1902//.. case Xsh_SHR: opc_cl = 0xD3; opc_imm = 0xC1; subopc = 5; break;
1903//.. case Xsh_SAR: opc_cl = 0xD3; opc_imm = 0xC1; subopc = 7; break;
1904//.. case Xsh_SHL: opc_cl = 0xD3; opc_imm = 0xC1; subopc = 4; break;
1905//.. default: goto bad;
1906//.. }
1907//.. if (i->Xin.Sh32.src == 0) {
1908//.. *p++ = opc_cl;
1909//.. switch (i->Xin.Sh32.dst->tag) {
1910//.. case Xrm_Reg:
1911//.. p = doAMode_R(p, fake(subopc),
1912//.. i->Xin.Sh32.dst->Xrm.Reg.reg);
1913//.. goto done;
1914//.. default:
1915//.. goto bad;
1916//.. }
1917//.. } else {
1918//.. *p++ = opc_imm;
1919//.. switch (i->Xin.Sh32.dst->tag) {
1920//.. case Xrm_Reg:
1921//.. p = doAMode_R(p, fake(subopc),
1922//.. i->Xin.Sh32.dst->Xrm.Reg.reg);
1923//.. *p++ = (UChar)(i->Xin.Sh32.src);
1924//.. goto done;
1925//.. default:
1926//.. goto bad;
1927//.. }
1928//.. }
1929//.. break;
cerion2c49e032005-02-09 17:29:49 +00001930
cerionbcf8c3e2005-02-04 16:17:07 +00001931//.. case Xin_Test32:
1932//.. if (i->Xin.Test32.src->tag == Xri_Imm
1933//.. && i->Xin.Test32.dst->tag == Xrm_Reg) {
1934//.. /* testl $imm32, %reg */
1935//.. *p++ = 0xF7;
1936//.. p = doAMode_R(p, fake(0), i->Xin.Test32.dst->Xrm.Reg.reg);
1937//.. p = emit32(p, i->Xin.Test32.src->Xri.Imm.imm32);
1938//.. goto done;
1939//.. }
1940//.. break;
cerion2c49e032005-02-09 17:29:49 +00001941
cerionbcf8c3e2005-02-04 16:17:07 +00001942//.. case Xin_Unary32:
1943//.. if (i->Xin.Unary32.op == Xun_NOT) {
1944//.. *p++ = 0xF7;
1945//.. if (i->Xin.Unary32.dst->tag == Xrm_Reg) {
1946//.. p = doAMode_R(p, fake(2), i->Xin.Unary32.dst->Xrm.Reg.reg);
1947//.. goto done;
1948//.. } else {
1949//.. goto bad;
1950//.. }
1951//.. }
1952//.. if (i->Xin.Unary32.op == Xun_NEG) {
1953//.. *p++ = 0xF7;
1954//.. if (i->Xin.Unary32.dst->tag == Xrm_Reg) {
1955//.. p = doAMode_R(p, fake(3), i->Xin.Unary32.dst->Xrm.Reg.reg);
1956//.. goto done;
1957//.. } else {
1958//.. goto bad;
1959//.. }
1960//.. }
1961//.. break;
cerionb536af92005-02-10 15:03:19 +00001962
cerionbcf8c3e2005-02-04 16:17:07 +00001963//.. case Xin_MulL:
1964//.. subopc = i->Xin.MulL.syned ? 5 : 4;
1965//.. if (i->Xin.MulL.ssz == Xss_32) {
1966//.. *p++ = 0xF7;
1967//.. switch (i->Xin.MulL.src->tag) {
1968//.. case Xrm_Mem:
1969//.. p = doAMode_M(p, fake(subopc),
1970//.. i->Xin.MulL.src->Xrm.Mem.am);
1971//.. goto done;
1972//.. case Xrm_Reg:
1973//.. p = doAMode_R(p, fake(subopc),
1974//.. i->Xin.MulL.src->Xrm.Reg.reg);
1975//.. goto done;
1976//.. default:
1977//.. goto bad;
1978//.. }
1979//.. }
1980//.. break;
cerion2c49e032005-02-09 17:29:49 +00001981
cerionbcf8c3e2005-02-04 16:17:07 +00001982//.. case Xin_Div:
1983//.. subopc = i->Xin.Div.syned ? 7 : 6;
1984//.. if (i->Xin.Div.ssz == Xss_32) {
1985//.. *p++ = 0xF7;
1986//.. switch (i->Xin.Div.src->tag) {
1987//.. case Xrm_Mem:
1988//.. p = doAMode_M(p, fake(subopc),
1989//.. i->Xin.Div.src->Xrm.Mem.am);
1990//.. goto done;
1991//.. case Xrm_Reg:
1992//.. p = doAMode_R(p, fake(subopc),
1993//.. i->Xin.Div.src->Xrm.Reg.reg);
1994//.. goto done;
1995//.. default:
1996//.. goto bad;
1997//.. }
1998//.. }
1999//.. break;
cerion2c49e032005-02-09 17:29:49 +00002000
cerionbcf8c3e2005-02-04 16:17:07 +00002001//.. case Xin_Sh3232:
2002//.. vassert(i->Xin.Sh3232.op == Xsh_SHL || i->Xin.Sh3232.op == Xsh_SHR);
2003//.. if (i->Xin.Sh3232.amt == 0) {
2004//.. /* shldl/shrdl by %cl */
2005//.. *p++ = 0x0F;
2006//.. if (i->Xin.Sh3232.op == Xsh_SHL) {
2007//.. *p++ = 0xA5;
2008//.. } else {
2009//.. *p++ = 0xAD;
2010//.. }
2011//.. p = doAMode_R(p, i->Xin.Sh3232.src, i->Xin.Sh3232.dst);
2012//.. goto done;
2013//.. }
2014//.. break;
cerion2c49e032005-02-09 17:29:49 +00002015
cerionbcf8c3e2005-02-04 16:17:07 +00002016//.. case Xin_Push:
2017//.. switch (i->Xin.Push.src->tag) {
2018//.. case Xrmi_Mem:
2019//.. *p++ = 0xFF;
2020//.. p = doAMode_M(p, fake(6), i->Xin.Push.src->Xrmi.Mem.am);
2021//.. goto done;
2022//.. case Xrmi_Imm:
2023//.. *p++ = 0x68;
2024//.. p = emit32(p, i->Xin.Push.src->Xrmi.Imm.imm32);
2025//.. goto done;
2026//.. case Xrmi_Reg:
2027//.. *p++ = 0x50 + iregNo(i->Xin.Push.src->Xrmi.Reg.reg);
2028//.. goto done;
2029//.. default:
2030//.. goto bad;
2031//.. }
cerion2c49e032005-02-09 17:29:49 +00002032
cerionbcf8c3e2005-02-04 16:17:07 +00002033//.. case Xin_Call:
2034//.. /* See detailed comment for Xin_Call in getRegUsage_X86Instr above
2035//.. for explanation of this. */
2036//.. switch (i->Xin.Call.regparms) {
2037//.. case 0: irno = iregNo(hregX86_EAX()); break;
2038//.. case 1: irno = iregNo(hregX86_EDX()); break;
2039//.. case 2: irno = iregNo(hregX86_ECX()); break;
2040//.. case 3: irno = iregNo(hregX86_EDI()); break;
2041//.. default: vpanic(" emit_X86Instr:call:regparms");
2042//.. }
2043//.. /* jump over the following two insns if the condition does not
2044//.. hold */
2045//.. if (i->Xin.Call.cond != Xcc_ALWAYS) {
2046//.. *p++ = 0x70 + (0xF & (i->Xin.Call.cond ^ 1));
2047//.. *p++ = 0x07; /* 7 bytes in the next two insns */
2048//.. }
2049//.. /* movl $target, %tmp */
2050//.. *p++ = 0xB8 + irno;
2051//.. p = emit32(p, i->Xin.Call.target);
2052//.. /* call *%tmp */
2053//.. *p++ = 0xFF;
2054//.. *p++ = 0xD0 + irno;
2055//.. goto done;
cerion2c49e032005-02-09 17:29:49 +00002056
cerionbcf8c3e2005-02-04 16:17:07 +00002057//.. case Xin_Goto:
2058//.. /* Use ptmp for backpatching conditional jumps. */
2059//.. ptmp = NULL;
2060//..
2061//.. /* First off, if this is conditional, create a conditional
2062//.. jump over the rest of it. */
2063//.. if (i->Xin.Goto.cond != Xcc_ALWAYS) {
2064//.. /* jmp fwds if !condition */
2065//.. *p++ = 0x70 + (i->Xin.Goto.cond ^ 1);
2066//.. ptmp = p; /* fill in this bit later */
2067//.. *p++ = 0; /* # of bytes to jump over; don't know how many yet. */
2068//.. }
2069//..
2070//.. /* If a non-boring, set %ebp (the guest state pointer)
2071//.. appropriately. */
2072//.. /* movl $magic_number, %ebp */
2073//.. switch (i->Xin.Goto.jk) {
2074//.. case Ijk_ClientReq:
2075//.. *p++ = 0xBD;
2076//.. p = emit32(p, VEX_TRC_JMP_CLIENTREQ); break;
2077//.. case Ijk_Syscall:
2078//.. *p++ = 0xBD;
2079//.. p = emit32(p, VEX_TRC_JMP_SYSCALL); break;
2080//.. case Ijk_Yield:
2081//.. *p++ = 0xBD;
2082//.. p = emit32(p, VEX_TRC_JMP_YIELD); break;
2083//.. case Ijk_EmWarn:
2084//.. *p++ = 0xBD;
2085//.. p = emit32(p, VEX_TRC_JMP_EMWARN); break;
2086//.. case Ijk_MapFail:
2087//.. *p++ = 0xBD;
2088//.. p = emit32(p, VEX_TRC_JMP_MAPFAIL); break;
2089//.. case Ijk_NoDecode:
2090//.. *p++ = 0xBD;
2091//.. p = emit32(p, VEX_TRC_JMP_NODECODE); break;
2092//.. case Ijk_Ret:
2093//.. case Ijk_Call:
2094//.. case Ijk_Boring:
2095//.. break;
2096//.. default:
2097//.. ppIRJumpKind(i->Xin.Goto.jk);
2098//.. vpanic("emit_X86Instr.Xin_Goto: unknown jump kind");
2099//.. }
2100//..
2101//.. /* Get the destination address into %eax */
2102//.. if (i->Xin.Goto.dst->tag == Xri_Imm) {
2103//.. /* movl $immediate, %eax ; ret */
2104//.. *p++ = 0xB8;
2105//.. p = emit32(p, i->Xin.Goto.dst->Xri.Imm.imm32);
2106//.. } else {
2107//.. vassert(i->Xin.Goto.dst->tag == Xri_Reg);
2108//.. /* movl %reg, %eax ; ret */
2109//.. if (i->Xin.Goto.dst->Xri.Reg.reg != hregX86_EAX()) {
2110//.. *p++ = 0x89;
2111//.. p = doAMode_R(p, i->Xin.Goto.dst->Xri.Reg.reg, hregX86_EAX());
2112//.. }
2113//.. }
2114//..
2115//.. /* ret */
2116//.. *p++ = 0xC3;
2117//..
2118//.. /* Fix up the conditional jump, if there was one. */
2119//.. if (i->Xin.Goto.cond != Xcc_ALWAYS) {
2120//.. Int delta = p - ptmp;
2121//.. vassert(delta > 0 && delta < 20);
2122//.. *ptmp = (UChar)(delta-1);
2123//.. }
2124//.. goto done;
cerionb536af92005-02-10 15:03:19 +00002125
cerionbcf8c3e2005-02-04 16:17:07 +00002126//.. case Xin_CMov32:
2127//.. vassert(i->Xin.CMov32.cond != Xcc_ALWAYS);
2128//.. #if 0
2129//.. /* This generates cmov, which is illegal on P54/P55. */
2130//.. *p++ = 0x0F;
2131//.. *p++ = 0x40 + i->Xin.CMov32.cond;
2132//.. if (i->Xin.CMov32.src->tag == Xrm_Reg) {
2133//.. p = doAMode_R(p, i->Xin.CMov32.dst, i->Xin.CMov32.src->Xrm.Reg.reg);
2134//.. goto done;
2135//.. }
2136//.. if (i->Xin.CMov32.src->tag == Xrm_Mem) {
2137//.. p = doAMode_M(p, i->Xin.CMov32.dst, i->Xin.CMov32.src->Xrm.Mem.am);
2138//.. goto done;
2139//.. }
2140//.. #else
2141//.. /* P5 friendly version: conditional jump over an unconditional
2142//.. move. */
2143//.. /* jmp fwds if !condition */
2144//.. *p++ = 0x70 + (i->Xin.CMov32.cond ^ 1);
2145//.. *p++ = 0; /* # of bytes in the next bit, which we don't know yet */
2146//.. ptmp = p;
2147//..
2148//.. switch (i->Xin.CMov32.src->tag) {
2149//.. case Xrm_Reg:
2150//.. /* Big sigh. This is movl E -> G ... */
2151//.. *p++ = 0x89;
2152//.. p = doAMode_R(p, i->Xin.CMov32.src->Xrm.Reg.reg,
2153//.. i->Xin.CMov32.dst);
2154//..
2155//.. break;
2156//.. case Xrm_Mem:
2157//.. /* ... whereas this is movl G -> E. That's why the args
2158//.. to doAMode_R appear to be the wrong way round in the
2159//.. Xrm_Reg case. */
2160//.. *p++ = 0x8B;
2161//.. p = doAMode_M(p, i->Xin.CMov32.dst,
2162//.. i->Xin.CMov32.src->Xrm.Mem.am);
2163//.. break;
2164//.. default:
2165//.. goto bad;
2166//.. }
2167//.. /* Fill in the jump offset. */
2168//.. *(ptmp-1) = p - ptmp;
2169//.. goto done;
2170//.. #endif
2171//.. break;
cerionb536af92005-02-10 15:03:19 +00002172
ceriond5e38382005-02-11 13:38:15 +00002173 case Pin_LoadEX: {
2174 UInt op1, op2, sz = i->Pin.LoadEX.sz;
2175 switch (i->Pin.LoadEX.src->tag) {
2176 case Pam_IR:
2177 if (sz == 2) { // the only signed load
2178 op1 = (i->Pin.LoadEX.syned) ? 42: 40;
2179 } else {
2180 vassert(i->Pin.LoadEX.syned == False);
2181 op1 = (sz == 1) ? 34 : 32;
2182 }
2183 p = doAMode_IR(p, op1, i->Pin.LoadEX.dst, i->Pin.LoadEX.src);
2184 goto done;
2185 case Pam_RR:
2186 op1 = 31;
2187 if (sz == 2) { // the only signed load
2188 op2 = (i->Pin.LoadEX.syned) ? 343: 279;
2189 } else {
2190 vassert(i->Pin.LoadEX.syned == False);
2191 op2 = (sz == 1) ? 87 : 23;
2192 }
2193 p = doAMode_RR(p, op1, op2, i->Pin.LoadEX.dst, i->Pin.LoadEX.src);
2194 goto done;
2195 default:
2196 goto bad;
2197 }
2198 }
cerionb536af92005-02-10 15:03:19 +00002199
cerionbcf8c3e2005-02-04 16:17:07 +00002200//.. case Xin_Set32:
2201//.. /* Make the destination register be 1 or 0, depending on whether
2202//.. the relevant condition holds. We have to dodge and weave
2203//.. when the destination is %esi or %edi as we cannot directly
2204//.. emit the native 'setb %reg' for those. Further complication:
2205//.. the top 24 bits of the destination should be forced to zero,
2206//.. but doing 'xor %r,%r' kills the flag(s) we are about to read.
2207//.. Sigh. So start off my moving $0 into the dest. */
2208//..
2209//.. /* Do we need to swap in %eax? */
2210//.. if (iregNo(i->Xin.Set32.dst) >= 4) {
2211//.. /* xchg %eax, %dst */
2212//.. *p++ = 0x90 + iregNo(i->Xin.Set32.dst);
2213//.. /* movl $0, %eax */
2214//.. *p++ = 0xB8 + iregNo(hregX86_EAX());
2215//.. p = emit32(p, 0);
2216//.. /* setb lo8(%eax) */
2217//.. *p++ = 0x0F;
2218//.. *p++ = 0x90 + (UChar)(i->Xin.Set32.cond);
2219//.. p = doAMode_R(p, fake(0), hregX86_EAX());
2220//.. /* xchg %eax, %dst */
2221//.. *p++ = 0x90 + iregNo(i->Xin.Set32.dst);
2222//.. } else {
2223//.. /* movl $0, %dst */
2224//.. *p++ = 0xB8 + iregNo(i->Xin.Set32.dst);
2225//.. p = emit32(p, 0);
2226//.. /* setb lo8(%dst) */
2227//.. *p++ = 0x0F;
2228//.. *p++ = 0x90 + (UChar)(i->Xin.Set32.cond);
2229//.. p = doAMode_R(p, fake(0), i->Xin.Set32.dst);
2230//.. }
2231//.. goto done;
cerionb536af92005-02-10 15:03:19 +00002232
cerionbcf8c3e2005-02-04 16:17:07 +00002233//.. case Xin_Bsfr32:
2234//.. *p++ = 0x0F;
2235//.. if (i->Xin.Bsfr32.isFwds) {
2236//.. *p++ = 0xBC;
2237//.. } else {
2238//.. *p++ = 0xBD;
2239//.. }
2240//.. p = doAMode_R(p, i->Xin.Bsfr32.dst, i->Xin.Bsfr32.src);
2241//.. goto done;
cerionb536af92005-02-10 15:03:19 +00002242
cerionbcf8c3e2005-02-04 16:17:07 +00002243//.. case Xin_MFence:
2244//.. /* see comment in hdefs.h re this insn */
2245//.. if (0) vex_printf("EMIT FENCE\n");
2246//.. switch (i->Xin.MFence.subarch) {
2247//.. case VexSubArchX86_sse0:
2248//.. vassert(0); /* awaiting test case */
2249//.. /* lock addl $0,0(%esp) */
2250//.. *p++ = 0xF0; *p++ = 0x83; *p++ = 0x44;
2251//.. *p++ = 0x24; *p++ = 0x00; *p++ = 0x00;
2252//.. goto done;
2253//.. case VexSubArchX86_sse1:
2254//.. /* sfence */
2255//.. *p++ = 0x0F; *p++ = 0xAE; *p++ = 0xF8;
2256//.. /* lock addl $0,0(%esp) */
2257//.. *p++ = 0xF0; *p++ = 0x83; *p++ = 0x44;
2258//.. *p++ = 0x24; *p++ = 0x00; *p++ = 0x00;
2259//.. goto done;
2260//.. case VexSubArchX86_sse2:
2261//.. /* mfence */
2262//.. *p++ = 0x0F; *p++ = 0xAE; *p++ = 0xF0;
2263//.. goto done;
2264//.. default:
2265//.. vpanic("emit_X86Instr:mfence:subarch");
2266//.. }
2267//.. break;
cerionb536af92005-02-10 15:03:19 +00002268
ceriond5e38382005-02-11 13:38:15 +00002269 case Pin_Store: {
2270 UInt op1, op2, sz = i->Pin.Store.sz;
2271 switch (i->Pin.Store.dst->tag) {
2272 case Pam_IR:
2273 op1 = (sz == 1) ? 38 : ((sz == 2) ? 44 : 36);
2274 p = doAMode_IR(p, op1, i->Pin.Store.src, i->Pin.Store.dst);
2275 goto done;
2276 case Pam_RR:
2277 op1 = 31;
2278 op2 = (sz == 1) ? 215 : ((sz == 2) ? 407 : 151);
2279 p = doAMode_RR(p, op1, op2, i->Pin.Store.src, i->Pin.Store.dst);
2280 goto done;
2281 default:
2282 goto bad;
2283 }
2284 goto done;
2285 }
cerionb536af92005-02-10 15:03:19 +00002286
cerionbcf8c3e2005-02-04 16:17:07 +00002287//.. case Xin_FpUnary:
2288//.. /* gop %src, %dst
2289//.. --> ffree %st7 ; fld %st(src) ; fop %st(0) ; fstp %st(1+dst)
2290//.. */
2291//.. p = do_ffree_st7(p);
2292//.. p = do_fld_st(p, 0+hregNumber(i->Xin.FpUnary.src));
2293//.. p = do_fop1_st(p, i->Xin.FpUnary.op);
2294//.. p = do_fstp_st(p, 1+hregNumber(i->Xin.FpUnary.dst));
2295//.. goto done;
2296//..
2297//.. case Xin_FpBinary:
2298//.. if (i->Xin.FpBinary.op == Xfp_YL2X
2299//.. || i->Xin.FpBinary.op == Xfp_YL2XP1) {
2300//.. /* Have to do this specially. */
2301//.. /* ffree %st7 ; fld %st(srcL) ;
2302//.. ffree %st7 ; fld %st(srcR+1) ; fyl2x{p1} ; fstp(1+dst) */
2303//.. p = do_ffree_st7(p);
2304//.. p = do_fld_st(p, 0+hregNumber(i->Xin.FpBinary.srcL));
2305//.. p = do_ffree_st7(p);
2306//.. p = do_fld_st(p, 1+hregNumber(i->Xin.FpBinary.srcR));
2307//.. *p++ = 0xD9;
2308//.. *p++ = i->Xin.FpBinary.op==Xfp_YL2X ? 0xF1 : 0xF9;
2309//.. p = do_fstp_st(p, 1+hregNumber(i->Xin.FpBinary.dst));
2310//.. goto done;
2311//.. }
2312//.. if (i->Xin.FpBinary.op == Xfp_ATAN) {
2313//.. /* Have to do this specially. */
2314//.. /* ffree %st7 ; fld %st(srcL) ;
2315//.. ffree %st7 ; fld %st(srcR+1) ; fpatan ; fstp(1+dst) */
2316//.. p = do_ffree_st7(p);
2317//.. p = do_fld_st(p, 0+hregNumber(i->Xin.FpBinary.srcL));
2318//.. p = do_ffree_st7(p);
2319//.. p = do_fld_st(p, 1+hregNumber(i->Xin.FpBinary.srcR));
2320//.. *p++ = 0xD9; *p++ = 0xF3;
2321//.. p = do_fstp_st(p, 1+hregNumber(i->Xin.FpBinary.dst));
2322//.. goto done;
2323//.. }
2324//.. if (i->Xin.FpBinary.op == Xfp_PREM
2325//.. || i->Xin.FpBinary.op == Xfp_PREM1
2326//.. || i->Xin.FpBinary.op == Xfp_SCALE) {
2327//.. /* Have to do this specially. */
2328//.. /* ffree %st7 ; fld %st(srcR) ;
2329//.. ffree %st7 ; fld %st(srcL+1) ; fprem/fprem1/fscale ; fstp(2+dst) ;
2330//.. fincstp ; ffree %st7 */
2331//.. p = do_ffree_st7(p);
2332//.. p = do_fld_st(p, 0+hregNumber(i->Xin.FpBinary.srcR));
2333//.. p = do_ffree_st7(p);
2334//.. p = do_fld_st(p, 1+hregNumber(i->Xin.FpBinary.srcL));
2335//.. *p++ = 0xD9;
2336//.. switch (i->Xin.FpBinary.op) {
2337//.. case Xfp_PREM: *p++ = 0xF8; break;
2338//.. case Xfp_PREM1: *p++ = 0xF5; break;
2339//.. case Xfp_SCALE: *p++ = 0xFD; break;
2340//.. default: vpanic("emitX86Instr(FpBinary,PREM/PREM1/SCALE)");
2341//.. }
2342//.. p = do_fstp_st(p, 2+hregNumber(i->Xin.FpBinary.dst));
2343//.. *p++ = 0xD9; *p++ = 0xF7;
2344//.. p = do_ffree_st7(p);
2345//.. goto done;
2346//.. }
2347//.. /* General case */
2348//.. /* gop %srcL, %srcR, %dst
2349//.. --> ffree %st7 ; fld %st(srcL) ; fop %st(1+srcR) ; fstp %st(1+dst)
2350//.. */
2351//.. p = do_ffree_st7(p);
2352//.. p = do_fld_st(p, 0+hregNumber(i->Xin.FpBinary.srcL));
2353//.. p = do_fop2_st(p, i->Xin.FpBinary.op,
2354//.. 1+hregNumber(i->Xin.FpBinary.srcR));
2355//.. p = do_fstp_st(p, 1+hregNumber(i->Xin.FpBinary.dst));
2356//.. goto done;
2357//..
2358//.. case Xin_FpLdSt:
2359//.. vassert(i->Xin.FpLdSt.sz == 4 || i->Xin.FpLdSt.sz == 8);
2360//.. if (i->Xin.FpLdSt.isLoad) {
2361//.. /* Load from memory into %fakeN.
2362//.. --> ffree %st(7) ; fld{s/l} amode ; fstp st(N+1)
2363//.. */
2364//.. p = do_ffree_st7(p);
2365//.. *p++ = i->Xin.FpLdSt.sz==4 ? 0xD9 : 0xDD;
2366//.. p = doAMode_M(p, fake(0)/*subopcode*/, i->Xin.FpLdSt.addr);
2367//.. p = do_fstp_st(p, 1+hregNumber(i->Xin.FpLdSt.reg));
2368//.. goto done;
2369//.. } else {
2370//.. /* Store from %fakeN into memory.
2371//.. --> ffree %st(7) ; fld st(N) ; fstp{l|s} amode
2372//.. */
2373//.. p = do_ffree_st7(p);
2374//.. p = do_fld_st(p, 0+hregNumber(i->Xin.FpLdSt.reg));
2375//.. *p++ = i->Xin.FpLdSt.sz==4 ? 0xD9 : 0xDD;
2376//.. p = doAMode_M(p, fake(3)/*subopcode*/, i->Xin.FpLdSt.addr);
2377//.. goto done;
2378//.. }
2379//.. break;
2380//..
2381//.. case Xin_FpLdStI:
2382//.. if (i->Xin.FpLdStI.isLoad) {
2383//.. /* Load from memory into %fakeN, converting from an int.
2384//.. --> ffree %st(7) ; fild{w/l/ll} amode ; fstp st(N+1)
2385//.. */
2386//.. switch (i->Xin.FpLdStI.sz) {
2387//.. case 8: opc = 0xDF; subopc_imm = 5; break;
2388//.. case 4: opc = 0xDB; subopc_imm = 0; break;
2389//.. case 2: vassert(0); opc = 0xDF; subopc_imm = 0; break;
2390//.. default: vpanic("emitX86Instr(Xin_FpLdStI-load)");
2391//.. }
2392//.. p = do_ffree_st7(p);
2393//.. *p++ = opc;
2394//.. p = doAMode_M(p, fake(subopc_imm)/*subopcode*/, i->Xin.FpLdStI.addr);
2395//.. p = do_fstp_st(p, 1+hregNumber(i->Xin.FpLdStI.reg));
2396//.. goto done;
2397//.. } else {
2398//.. /* Store from %fakeN into memory, converting to an int.
2399//.. --> ffree %st(7) ; fld st(N) ; fistp{w/l/ll} amode
2400//.. */
2401//.. switch (i->Xin.FpLdStI.sz) {
2402//.. case 8: opc = 0xDF; subopc_imm = 7; break;
2403//.. case 4: opc = 0xDB; subopc_imm = 3; break;
2404//.. case 2: opc = 0xDF; subopc_imm = 3; break;
2405//.. default: vpanic("emitX86Instr(Xin_FpLdStI-store)");
2406//.. }
2407//.. p = do_ffree_st7(p);
2408//.. p = do_fld_st(p, 0+hregNumber(i->Xin.FpLdStI.reg));
2409//.. *p++ = opc;
2410//.. p = doAMode_M(p, fake(subopc_imm)/*subopcode*/, i->Xin.FpLdStI.addr);
2411//.. goto done;
2412//.. }
2413//.. break;
2414//..
2415//.. case Xin_Fp64to32:
2416//.. /* ffree %st7 ; fld %st(src) */
2417//.. p = do_ffree_st7(p);
2418//.. p = do_fld_st(p, 0+fregNo(i->Xin.Fp64to32.src));
2419//.. /* subl $4, %esp */
2420//.. *p++ = 0x83; *p++ = 0xEC; *p++ = 0x04;
2421//.. /* fstps (%esp) */
2422//.. *p++ = 0xD9; *p++ = 0x1C; *p++ = 0x24;
2423//.. /* flds (%esp) */
2424//.. *p++ = 0xD9; *p++ = 0x04; *p++ = 0x24;
2425//.. /* addl $4, %esp */
2426//.. *p++ = 0x83; *p++ = 0xC4; *p++ = 0x04;
2427//.. /* fstp %st(1+dst) */
2428//.. p = do_fstp_st(p, 1+fregNo(i->Xin.Fp64to32.dst));
2429//.. goto done;
2430//..
2431//.. case Xin_FpCMov:
2432//.. /* jmp fwds if !condition */
2433//.. *p++ = 0x70 + (i->Xin.FpCMov.cond ^ 1);
2434//.. *p++ = 0; /* # of bytes in the next bit, which we don't know yet */
2435//.. ptmp = p;
2436//..
2437//.. /* ffree %st7 ; fld %st(src) ; fstp %st(1+dst) */
2438//.. p = do_ffree_st7(p);
2439//.. p = do_fld_st(p, 0+fregNo(i->Xin.FpCMov.src));
2440//.. p = do_fstp_st(p, 1+fregNo(i->Xin.FpCMov.dst));
2441//..
2442//.. /* Fill in the jump offset. */
2443//.. *(ptmp-1) = p - ptmp;
2444//.. goto done;
2445//..
2446//.. case Xin_FpLdStCW:
2447//.. if (i->Xin.FpLdStCW.isLoad) {
2448//.. *p++ = 0xD9;
2449//.. p = doAMode_M(p, fake(5)/*subopcode*/, i->Xin.FpLdStCW.addr);
2450//.. } else {
2451//.. vassert(0);
2452//.. }
2453//.. goto done;
2454//..
2455//.. case Xin_FpStSW_AX:
2456//.. /* note, this emits fnstsw %ax, not fstsw %ax */
2457//.. *p++ = 0xDF;
2458//.. *p++ = 0xE0;
2459//.. goto done;
2460//..
2461//.. case Xin_FpCmp:
2462//.. /* gcmp %fL, %fR, %dst
2463//.. -> ffree %st7; fpush %fL ; fucomp %(fR+1) ;
2464//.. fnstsw %ax ; movl %eax, %dst
2465//.. */
2466//.. /* ffree %st7 */
2467//.. p = do_ffree_st7(p);
2468//.. /* fpush %fL */
2469//.. p = do_fld_st(p, 0+fregNo(i->Xin.FpCmp.srcL));
2470//.. /* fucomp %(fR+1) */
2471//.. *p++ = 0xDD;
2472//.. *p++ = 0xE8 + (7 & (1+fregNo(i->Xin.FpCmp.srcR)));
2473//.. /* fnstsw %ax */
2474//.. *p++ = 0xDF;
2475//.. *p++ = 0xE0;
2476//.. /* movl %eax, %dst */
2477//.. *p++ = 0x89;
2478//.. p = doAMode_R(p, hregX86_EAX(), i->Xin.FpCmp.dst);
2479//.. goto done;
2480//..
2481//.. case Xin_SseConst: {
2482//.. UShort con = i->Xin.SseConst.con;
2483//.. p = push_word_from_tags(p, (con >> 12) & 0xF);
2484//.. p = push_word_from_tags(p, (con >> 8) & 0xF);
2485//.. p = push_word_from_tags(p, (con >> 4) & 0xF);
2486//.. p = push_word_from_tags(p, con & 0xF);
2487//.. /* movl (%esp), %xmm-dst */
2488//.. *p++ = 0x0F;
2489//.. *p++ = 0x10;
2490//.. *p++ = 0x04 + 8 * (7 & vregNo(i->Xin.SseConst.dst));
2491//.. *p++ = 0x24;
2492//.. /* addl $16, %esp */
2493//.. *p++ = 0x83;
2494//.. *p++ = 0xC4;
2495//.. *p++ = 0x10;
2496//.. goto done;
2497//.. }
2498//..
2499//.. case Xin_SseLdSt:
2500//.. *p++ = 0x0F;
2501//.. *p++ = i->Xin.SseLdSt.isLoad ? 0x10 : 0x11;
2502//.. p = doAMode_M(p, fake(vregNo(i->Xin.SseLdSt.reg)), i->Xin.SseLdSt.addr);
2503//.. goto done;
2504//..
2505//.. case Xin_SseLdzLO:
2506//.. vassert(i->Xin.SseLdzLO.sz == 4 || i->Xin.SseLdzLO.sz == 8);
2507//.. /* movs[sd] amode, %xmm-dst */
2508//.. *p++ = i->Xin.SseLdzLO.sz==4 ? 0xF3 : 0xF2;
2509//.. *p++ = 0x0F;
2510//.. *p++ = 0x10;
2511//.. p = doAMode_M(p, fake(vregNo(i->Xin.SseLdzLO.reg)),
2512//.. i->Xin.SseLdzLO.addr);
2513//.. goto done;
2514//..
2515//.. case Xin_Sse32Fx4:
2516//.. xtra = 0;
2517//.. *p++ = 0x0F;
2518//.. switch (i->Xin.Sse32Fx4.op) {
2519//.. case Xsse_ADDF: *p++ = 0x58; break;
2520//.. case Xsse_DIVF: *p++ = 0x5E; break;
2521//.. case Xsse_MAXF: *p++ = 0x5F; break;
2522//.. case Xsse_MINF: *p++ = 0x5D; break;
2523//.. case Xsse_MULF: *p++ = 0x59; break;
2524//.. case Xsse_RCPF: *p++ = 0x53; break;
2525//.. case Xsse_RSQRTF: *p++ = 0x52; break;
2526//.. case Xsse_SQRTF: *p++ = 0x51; break;
2527//.. case Xsse_SUBF: *p++ = 0x5C; break;
2528//.. case Xsse_CMPEQF: *p++ = 0xC2; xtra = 0x100; break;
2529//.. case Xsse_CMPLTF: *p++ = 0xC2; xtra = 0x101; break;
2530//.. case Xsse_CMPLEF: *p++ = 0xC2; xtra = 0x102; break;
2531//.. default: goto bad;
2532//.. }
2533//.. p = doAMode_R(p, fake(vregNo(i->Xin.Sse32Fx4.dst)),
2534//.. fake(vregNo(i->Xin.Sse32Fx4.src)) );
2535//.. if (xtra & 0x100)
2536//.. *p++ = (UChar)(xtra & 0xFF);
2537//.. goto done;
2538//..
2539//.. case Xin_Sse64Fx2:
2540//.. xtra = 0;
2541//.. *p++ = 0x66;
2542//.. *p++ = 0x0F;
2543//.. switch (i->Xin.Sse64Fx2.op) {
2544//.. case Xsse_ADDF: *p++ = 0x58; break;
2545//.. case Xsse_DIVF: *p++ = 0x5E; break;
2546//.. case Xsse_MAXF: *p++ = 0x5F; break;
2547//.. case Xsse_MINF: *p++ = 0x5D; break;
2548//.. case Xsse_MULF: *p++ = 0x59; break;
2549//.. case Xsse_RCPF: *p++ = 0x53; break;
2550//.. case Xsse_RSQRTF: *p++ = 0x52; break;
2551//.. case Xsse_SQRTF: *p++ = 0x51; break;
2552//.. case Xsse_SUBF: *p++ = 0x5C; break;
2553//.. case Xsse_CMPEQF: *p++ = 0xC2; xtra = 0x100; break;
2554//.. case Xsse_CMPLTF: *p++ = 0xC2; xtra = 0x101; break;
2555//.. case Xsse_CMPLEF: *p++ = 0xC2; xtra = 0x102; break;
2556//.. default: goto bad;
2557//.. }
2558//.. p = doAMode_R(p, fake(vregNo(i->Xin.Sse64Fx2.dst)),
2559//.. fake(vregNo(i->Xin.Sse64Fx2.src)) );
2560//.. if (xtra & 0x100)
2561//.. *p++ = (UChar)(xtra & 0xFF);
2562//.. goto done;
2563//..
2564//.. case Xin_Sse32FLo:
2565//.. xtra = 0;
2566//.. *p++ = 0xF3;
2567//.. *p++ = 0x0F;
2568//.. switch (i->Xin.Sse32FLo.op) {
2569//.. case Xsse_ADDF: *p++ = 0x58; break;
2570//.. case Xsse_DIVF: *p++ = 0x5E; break;
2571//.. case Xsse_MAXF: *p++ = 0x5F; break;
2572//.. case Xsse_MINF: *p++ = 0x5D; break;
2573//.. case Xsse_MULF: *p++ = 0x59; break;
2574//.. case Xsse_RCPF: *p++ = 0x53; break;
2575//.. case Xsse_RSQRTF: *p++ = 0x52; break;
2576//.. case Xsse_SQRTF: *p++ = 0x51; break;
2577//.. case Xsse_SUBF: *p++ = 0x5C; break;
2578//.. case Xsse_CMPEQF: *p++ = 0xC2; xtra = 0x100; break;
2579//.. case Xsse_CMPLTF: *p++ = 0xC2; xtra = 0x101; break;
2580//.. case Xsse_CMPLEF: *p++ = 0xC2; xtra = 0x102; break;
2581//.. default: goto bad;
2582//.. }
2583//.. p = doAMode_R(p, fake(vregNo(i->Xin.Sse32FLo.dst)),
2584//.. fake(vregNo(i->Xin.Sse32FLo.src)) );
2585//.. if (xtra & 0x100)
2586//.. *p++ = (UChar)(xtra & 0xFF);
2587//.. goto done;
2588//..
2589//.. case Xin_Sse64FLo:
2590//.. xtra = 0;
2591//.. *p++ = 0xF2;
2592//.. *p++ = 0x0F;
2593//.. switch (i->Xin.Sse64FLo.op) {
2594//.. case Xsse_ADDF: *p++ = 0x58; break;
2595//.. case Xsse_DIVF: *p++ = 0x5E; break;
2596//.. case Xsse_MAXF: *p++ = 0x5F; break;
2597//.. case Xsse_MINF: *p++ = 0x5D; break;
2598//.. case Xsse_MULF: *p++ = 0x59; break;
2599//.. case Xsse_RCPF: *p++ = 0x53; break;
2600//.. case Xsse_RSQRTF: *p++ = 0x52; break;
2601//.. case Xsse_SQRTF: *p++ = 0x51; break;
2602//.. case Xsse_SUBF: *p++ = 0x5C; break;
2603//.. case Xsse_CMPEQF: *p++ = 0xC2; xtra = 0x100; break;
2604//.. case Xsse_CMPLTF: *p++ = 0xC2; xtra = 0x101; break;
2605//.. case Xsse_CMPLEF: *p++ = 0xC2; xtra = 0x102; break;
2606//.. default: goto bad;
2607//.. }
2608//.. p = doAMode_R(p, fake(vregNo(i->Xin.Sse64FLo.dst)),
2609//.. fake(vregNo(i->Xin.Sse64FLo.src)) );
2610//.. if (xtra & 0x100)
2611//.. *p++ = (UChar)(xtra & 0xFF);
2612//.. goto done;
2613//..
2614//.. case Xin_SseReRg:
2615//.. # define XX(_n) *p++ = (_n)
2616//.. switch (i->Xin.SseReRg.op) {
2617//.. case Xsse_MOV: /*movups*/ XX(0x0F); XX(0x10); break;
2618//.. case Xsse_OR: XX(0x0F); XX(0x56); break;
2619//.. case Xsse_XOR: XX(0x0F); XX(0x57); break;
2620//.. case Xsse_AND: XX(0x0F); XX(0x54); break;
2621//.. case Xsse_PACKSSD: XX(0x66); XX(0x0F); XX(0x6B); break;
2622//.. case Xsse_PACKSSW: XX(0x66); XX(0x0F); XX(0x63); break;
2623//.. case Xsse_PACKUSW: XX(0x66); XX(0x0F); XX(0x67); break;
2624//.. case Xsse_ADD8: XX(0x66); XX(0x0F); XX(0xFC); break;
2625//.. case Xsse_ADD16: XX(0x66); XX(0x0F); XX(0xFD); break;
2626//.. case Xsse_ADD32: XX(0x66); XX(0x0F); XX(0xFE); break;
2627//.. case Xsse_ADD64: XX(0x66); XX(0x0F); XX(0xD4); break;
2628//.. case Xsse_QADD8S: XX(0x66); XX(0x0F); XX(0xEC); break;
2629//.. case Xsse_QADD16S: XX(0x66); XX(0x0F); XX(0xED); break;
2630//.. case Xsse_QADD8U: XX(0x66); XX(0x0F); XX(0xDC); break;
2631//.. case Xsse_QADD16U: XX(0x66); XX(0x0F); XX(0xDD); break;
2632//.. case Xsse_AVG8U: XX(0x66); XX(0x0F); XX(0xE0); break;
2633//.. case Xsse_AVG16U: XX(0x66); XX(0x0F); XX(0xE3); break;
2634//.. case Xsse_CMPEQ8: XX(0x66); XX(0x0F); XX(0x74); break;
2635//.. case Xsse_CMPEQ16: XX(0x66); XX(0x0F); XX(0x75); break;
2636//.. case Xsse_CMPEQ32: XX(0x66); XX(0x0F); XX(0x76); break;
2637//.. case Xsse_CMPGT8S: XX(0x66); XX(0x0F); XX(0x64); break;
2638//.. case Xsse_CMPGT16S: XX(0x66); XX(0x0F); XX(0x65); break;
2639//.. case Xsse_CMPGT32S: XX(0x66); XX(0x0F); XX(0x66); break;
2640//.. case Xsse_MAX16S: XX(0x66); XX(0x0F); XX(0xEE); break;
2641//.. case Xsse_MAX8U: XX(0x66); XX(0x0F); XX(0xDE); break;
2642//.. case Xsse_MIN16S: XX(0x66); XX(0x0F); XX(0xEA); break;
2643//.. case Xsse_MIN8U: XX(0x66); XX(0x0F); XX(0xDA); break;
2644//.. case Xsse_MULHI16U: XX(0x66); XX(0x0F); XX(0xE4); break;
2645//.. case Xsse_MULHI16S: XX(0x66); XX(0x0F); XX(0xE5); break;
2646//.. case Xsse_MUL16: XX(0x66); XX(0x0F); XX(0xD5); break;
2647//.. case Xsse_SHL16: XX(0x66); XX(0x0F); XX(0xF1); break;
2648//.. case Xsse_SHL32: XX(0x66); XX(0x0F); XX(0xF2); break;
2649//.. case Xsse_SHL64: XX(0x66); XX(0x0F); XX(0xF3); break;
2650//.. case Xsse_SAR16: XX(0x66); XX(0x0F); XX(0xE1); break;
2651//.. case Xsse_SAR32: XX(0x66); XX(0x0F); XX(0xE2); break;
2652//.. case Xsse_SHR16: XX(0x66); XX(0x0F); XX(0xD1); break;
2653//.. case Xsse_SHR32: XX(0x66); XX(0x0F); XX(0xD2); break;
2654//.. case Xsse_SHR64: XX(0x66); XX(0x0F); XX(0xD3); break;
2655//.. case Xsse_SUB8: XX(0x66); XX(0x0F); XX(0xF8); break;
2656//.. case Xsse_SUB16: XX(0x66); XX(0x0F); XX(0xF9); break;
2657//.. case Xsse_SUB32: XX(0x66); XX(0x0F); XX(0xFA); break;
2658//.. case Xsse_SUB64: XX(0x66); XX(0x0F); XX(0xFB); break;
2659//.. case Xsse_QSUB8S: XX(0x66); XX(0x0F); XX(0xE8); break;
2660//.. case Xsse_QSUB16S: XX(0x66); XX(0x0F); XX(0xE9); break;
2661//.. case Xsse_QSUB8U: XX(0x66); XX(0x0F); XX(0xD8); break;
2662//.. case Xsse_QSUB16U: XX(0x66); XX(0x0F); XX(0xD9); break;
2663//.. case Xsse_UNPCKHB: XX(0x66); XX(0x0F); XX(0x68); break;
2664//.. case Xsse_UNPCKHW: XX(0x66); XX(0x0F); XX(0x69); break;
2665//.. case Xsse_UNPCKHD: XX(0x66); XX(0x0F); XX(0x6A); break;
2666//.. case Xsse_UNPCKHQ: XX(0x66); XX(0x0F); XX(0x6D); break;
2667//.. case Xsse_UNPCKLB: XX(0x66); XX(0x0F); XX(0x60); break;
2668//.. case Xsse_UNPCKLW: XX(0x66); XX(0x0F); XX(0x61); break;
2669//.. case Xsse_UNPCKLD: XX(0x66); XX(0x0F); XX(0x62); break;
2670//.. case Xsse_UNPCKLQ: XX(0x66); XX(0x0F); XX(0x6C); break;
2671//.. default: goto bad;
2672//.. }
2673//.. p = doAMode_R(p, fake(vregNo(i->Xin.SseReRg.dst)),
2674//.. fake(vregNo(i->Xin.SseReRg.src)) );
2675//.. # undef XX
2676//.. goto done;
2677//..
2678//.. case Xin_SseCMov:
2679//.. /* jmp fwds if !condition */
2680//.. *p++ = 0x70 + (i->Xin.SseCMov.cond ^ 1);
2681//.. *p++ = 0; /* # of bytes in the next bit, which we don't know yet */
2682//.. ptmp = p;
2683//..
2684//.. /* movaps %src, %dst */
2685//.. *p++ = 0x0F;
2686//.. *p++ = 0x28;
2687//.. p = doAMode_R(p, fake(vregNo(i->Xin.SseCMov.dst)),
2688//.. fake(vregNo(i->Xin.SseCMov.src)) );
2689//..
2690//.. /* Fill in the jump offset. */
2691//.. *(ptmp-1) = p - ptmp;
2692//.. goto done;
2693//..
2694//.. case Xin_SseShuf:
2695//.. *p++ = 0x66;
2696//.. *p++ = 0x0F;
2697//.. *p++ = 0x70;
2698//.. p = doAMode_R(p, fake(vregNo(i->Xin.SseShuf.dst)),
2699//.. fake(vregNo(i->Xin.SseShuf.src)) );
2700//.. *p++ = (UChar)(i->Xin.SseShuf.order);
2701//.. goto done;
2702
2703 default:
2704 goto bad;
2705 }
2706
2707 bad:
2708 ppPPC32Instr(i);
2709 vpanic("emit_PPC32Instr");
2710 /*NOTREACHED*/
2711
cerionbcf8c3e2005-02-04 16:17:07 +00002712 done:
2713 vassert(p - &buf[0] <= 32);
2714 return p - &buf[0];
2715
2716# undef fake
2717}
2718
2719/*---------------------------------------------------------------*/
2720/*--- end host-ppc32/hdefs.c ---*/
2721/*---------------------------------------------------------------*/