blob: d11dd9b4ffe3ae63008bf3d482045212c577854a [file] [log] [blame]
sewardjde4a1d02002-03-22 01:27:54 +00001
2/*--------------------------------------------------------------------*/
3/*--- The JITter: translate ucode back to x86 code. ---*/
4/*--- vg_from_ucode.c ---*/
5/*--------------------------------------------------------------------*/
6/*
7 This file is part of Valgrind, an x86 protected-mode emulator
8 designed for debugging and profiling binaries on x86-Unixes.
9
10 Copyright (C) 2000-2002 Julian Seward
11 jseward@acm.org
sewardjde4a1d02002-03-22 01:27:54 +000012
13 This program is free software; you can redistribute it and/or
14 modify it under the terms of the GNU General Public License as
15 published by the Free Software Foundation; either version 2 of the
16 License, or (at your option) any later version.
17
18 This program is distributed in the hope that it will be useful, but
19 WITHOUT ANY WARRANTY; without even the implied warranty of
20 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
21 General Public License for more details.
22
23 You should have received a copy of the GNU General Public License
24 along with this program; if not, write to the Free Software
25 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
26 02111-1307, USA.
27
28 The GNU General Public License is contained in the file LICENSE.
29*/
30
31#include "vg_include.h"
32
33
34/*------------------------------------------------------------*/
35/*--- Renamings of frequently-used global functions. ---*/
36/*------------------------------------------------------------*/
37
38#define dis VG_(disassemble)
39#define nameIReg VG_(nameOfIntReg)
40#define nameISize VG_(nameOfIntSize)
41
42
43/*------------------------------------------------------------*/
44/*--- Instruction emission -- turning final uinstrs back ---*/
45/*--- into x86 code. ---*/
46/*------------------------------------------------------------*/
47
48/* [2001-07-08 This comment is now somewhat out of date.]
49
50 This is straightforward but for one thing: to facilitate generating
51 code in a single pass, we generate position-independent code. To
52 do this, calls and jmps to fixed addresses must specify the address
53 by first loading it into a register, and jump to/call that
54 register. Fortunately, the only jump to a literal is the jump back
55 to vg_dispatch, and only %eax is live then, conveniently. Ucode
56 call insns may only have a register as target anyway, so there's no
57 need to do anything fancy for them.
58
59 The emit_* routines constitute the lowest level of instruction
60 emission. They simply emit the sequence of bytes corresponding to
61 the relevant instruction, with no further ado. In particular there
62 is no checking about whether uses of byte registers makes sense,
63 nor whether shift insns have their first operand in %cl, etc.
64
65 These issues are taken care of by the level above, the synth_*
66 routines. These detect impossible operand combinations and turn
67 them into sequences of legal instructions. Finally, emitUInstr is
68 phrased in terms of the synth_* abstraction layer. */
69
70static UChar* emitted_code;
71static Int emitted_code_used;
72static Int emitted_code_size;
73
74static void expandEmittedCode ( void )
75{
76 Int i;
77 UChar* tmp = VG_(jitmalloc)(2 * emitted_code_size);
78 /* VG_(printf)("expand to %d\n", 2 * emitted_code_size); */
79 for (i = 0; i < emitted_code_size; i++)
80 tmp[i] = emitted_code[i];
81 VG_(jitfree)(emitted_code);
82 emitted_code = tmp;
83 emitted_code_size *= 2;
84}
85
86static __inline__ void emitB ( UInt b )
87{
88 if (dis) {
89 if (b < 16) VG_(printf)("0%x ", b); else VG_(printf)("%2x ", b);
90 }
91 if (emitted_code_used == emitted_code_size)
92 expandEmittedCode();
93
94 emitted_code[emitted_code_used] = (UChar)b;
95 emitted_code_used++;
96}
97
98static __inline__ void emitW ( UInt l )
99{
100 emitB ( (l) & 0x000000FF );
101 emitB ( (l >> 8) & 0x000000FF );
102}
103
104static __inline__ void emitL ( UInt l )
105{
106 emitB ( (l) & 0x000000FF );
107 emitB ( (l >> 8) & 0x000000FF );
108 emitB ( (l >> 16) & 0x000000FF );
109 emitB ( (l >> 24) & 0x000000FF );
110}
111
112static __inline__ void newEmit ( void )
113{
114 if (dis)
115 VG_(printf)("\t %4d: ", emitted_code_used );
116}
117
118/* Is this a callee-save register, in the normal C calling convention? */
119#define VG_CALLEE_SAVED(reg) (reg == R_EBX || reg == R_ESI || reg == R_EDI)
120
121
122/*----------------------------------------------------*/
123/*--- Addressing modes ---*/
124/*----------------------------------------------------*/
125
126static __inline__ UChar mkModRegRM ( UChar mod, UChar reg, UChar regmem )
127{
128 return ((mod & 3) << 6) | ((reg & 7) << 3) | (regmem & 7);
129}
130
131static __inline__ UChar mkSIB ( Int scale, Int regindex, Int regbase )
132{
133 Int shift;
134 switch (scale) {
135 case 1: shift = 0; break;
136 case 2: shift = 1; break;
137 case 4: shift = 2; break;
138 case 8: shift = 3; break;
139 default: VG_(panic)( "mkSIB" );
140 }
141 return ((shift & 3) << 6) | ((regindex & 7) << 3) | (regbase & 7);
142}
143
144static __inline__ void emit_amode_litmem_reg ( Addr addr, Int reg )
145{
146 /* ($ADDR), reg */
147 emitB ( mkModRegRM(0, reg, 5) );
148 emitL ( addr );
149}
150
151static __inline__ void emit_amode_regmem_reg ( Int regmem, Int reg )
152{
153 /* (regmem), reg */
154 if (regmem == R_ESP)
155 VG_(panic)("emit_amode_regmem_reg");
156 if (regmem == R_EBP) {
157 emitB ( mkModRegRM(1, reg, 5) );
158 emitB ( 0x00 );
159 } else {
160 emitB( mkModRegRM(0, reg, regmem) );
161 }
162}
163
164static __inline__ void emit_amode_offregmem_reg ( Int off, Int regmem, Int reg )
165{
166 if (regmem == R_ESP)
167 VG_(panic)("emit_amode_offregmem_reg(ESP)");
168 if (off < -128 || off > 127) {
169 /* Use a large offset */
170 /* d32(regmem), reg */
171 emitB ( mkModRegRM(2, reg, regmem) );
172 emitL ( off );
173 } else {
174 /* d8(regmem), reg */
175 emitB ( mkModRegRM(1, reg, regmem) );
176 emitB ( off & 0xFF );
177 }
178}
179
180static __inline__ void emit_amode_sib_reg ( Int off, Int scale, Int regbase,
181 Int regindex, Int reg )
182{
183 if (regindex == R_ESP)
184 VG_(panic)("emit_amode_sib_reg(ESP)");
185 if (off < -128 || off > 127) {
186 /* Use a 32-bit offset */
187 emitB ( mkModRegRM(2, reg, 4) ); /* SIB with 32-bit displacement */
188 emitB ( mkSIB( scale, regindex, regbase ) );
189 emitL ( off );
190 } else {
191 /* Use an 8-bit offset */
192 emitB ( mkModRegRM(1, reg, 4) ); /* SIB with 8-bit displacement */
193 emitB ( mkSIB( scale, regindex, regbase ) );
194 emitB ( off & 0xFF );
195 }
196}
197
198static __inline__ void emit_amode_ereg_greg ( Int e_reg, Int g_reg )
199{
200 /* other_reg, reg */
201 emitB ( mkModRegRM(3, g_reg, e_reg) );
202}
203
204static __inline__ void emit_amode_greg_ereg ( Int g_reg, Int e_reg )
205{
206 /* other_reg, reg */
207 emitB ( mkModRegRM(3, g_reg, e_reg) );
208}
209
210
211/*----------------------------------------------------*/
212/*--- Opcode translation ---*/
213/*----------------------------------------------------*/
214
215static __inline__ Int mkGrp1opcode ( Opcode opc )
216{
217 switch (opc) {
218 case ADD: return 0;
219 case OR: return 1;
220 case ADC: return 2;
221 case SBB: return 3;
222 case AND: return 4;
223 case SUB: return 5;
224 case XOR: return 6;
225 default: VG_(panic)("mkGrp1opcode");
226 }
227}
228
229static __inline__ Int mkGrp2opcode ( Opcode opc )
230{
231 switch (opc) {
232 case ROL: return 0;
233 case ROR: return 1;
234 case RCL: return 2;
235 case RCR: return 3;
236 case SHL: return 4;
237 case SHR: return 5;
238 case SAR: return 7;
239 default: VG_(panic)("mkGrp2opcode");
240 }
241}
242
243static __inline__ Int mkGrp3opcode ( Opcode opc )
244{
245 switch (opc) {
246 case NOT: return 2;
247 case NEG: return 3;
248 default: VG_(panic)("mkGrp3opcode");
249 }
250}
251
252static __inline__ Int mkGrp4opcode ( Opcode opc )
253{
254 switch (opc) {
255 case INC: return 0;
256 case DEC: return 1;
257 default: VG_(panic)("mkGrp4opcode");
258 }
259}
260
261static __inline__ Int mkGrp5opcode ( Opcode opc )
262{
263 switch (opc) {
264 case CALLM: return 2;
265 case JMP: return 4;
266 default: VG_(panic)("mkGrp5opcode");
267 }
268}
269
270static __inline__ UChar mkPrimaryOpcode ( Opcode opc )
271{
272 switch (opc) {
273 case ADD: return 0x00;
274 case ADC: return 0x10;
275 case AND: return 0x20;
276 case XOR: return 0x30;
277 case OR: return 0x08;
278 case SBB: return 0x18;
279 case SUB: return 0x28;
280 default: VG_(panic)("mkPrimaryOpcode");
281 }
282}
283
284/*----------------------------------------------------*/
285/*--- v-size (4, or 2 with OSO) insn emitters ---*/
286/*----------------------------------------------------*/
287
288static void emit_movv_offregmem_reg ( Int sz, Int off, Int areg, Int reg )
289{
290 newEmit();
291 if (sz == 2) emitB ( 0x66 );
292 emitB ( 0x8B ); /* MOV Ev, Gv */
293 emit_amode_offregmem_reg ( off, areg, reg );
294 if (dis)
295 VG_(printf)( "\n\t\tmov%c\t0x%x(%s), %s\n",
296 nameISize(sz), off, nameIReg(4,areg), nameIReg(sz,reg));
297}
298
299static void emit_movv_reg_offregmem ( Int sz, Int reg, Int off, Int areg )
300{
301 newEmit();
302 if (sz == 2) emitB ( 0x66 );
303 emitB ( 0x89 ); /* MOV Gv, Ev */
304 emit_amode_offregmem_reg ( off, areg, reg );
305 if (dis)
306 VG_(printf)( "\n\t\tmov%c\t%s, 0x%x(%s)\n",
307 nameISize(sz), nameIReg(sz,reg), off, nameIReg(4,areg));
308}
309
310static void emit_movv_regmem_reg ( Int sz, Int reg1, Int reg2 )
311{
312 newEmit();
313 if (sz == 2) emitB ( 0x66 );
314 emitB ( 0x8B ); /* MOV Ev, Gv */
315 emit_amode_regmem_reg ( reg1, reg2 );
316 if (dis)
317 VG_(printf)( "\n\t\tmov%c\t(%s), %s\n",
318 nameISize(sz), nameIReg(4,reg1), nameIReg(sz,reg2));
319}
320
321static void emit_movv_reg_regmem ( Int sz, Int reg1, Int reg2 )
322{
323 newEmit();
324 if (sz == 2) emitB ( 0x66 );
325 emitB ( 0x89 ); /* MOV Gv, Ev */
326 emit_amode_regmem_reg ( reg2, reg1 );
327 if (dis)
328 VG_(printf)( "\n\t\tmov%c\t%s, (%s)\n",
329 nameISize(sz), nameIReg(sz,reg1), nameIReg(4,reg2));
330}
331
332static void emit_movv_reg_reg ( Int sz, Int reg1, Int reg2 )
333{
334 newEmit();
335 if (sz == 2) emitB ( 0x66 );
336 emitB ( 0x89 ); /* MOV Gv, Ev */
337 emit_amode_ereg_greg ( reg2, reg1 );
338 if (dis)
339 VG_(printf)( "\n\t\tmov%c\t%s, %s\n",
340 nameISize(sz), nameIReg(sz,reg1), nameIReg(sz,reg2));
341}
342
343static void emit_nonshiftopv_lit_reg ( Int sz, Opcode opc,
344 UInt lit, Int reg )
345{
346 newEmit();
347 if (sz == 2) emitB ( 0x66 );
348 if (lit == VG_(extend_s_8to32)(lit & 0x000000FF)) {
349 /* short form OK */
350 emitB ( 0x83 ); /* Grp1 Ib,Ev */
351 emit_amode_ereg_greg ( reg, mkGrp1opcode(opc) );
352 emitB ( lit & 0x000000FF );
353 } else {
354 emitB ( 0x81 ); /* Grp1 Iv,Ev */
355 emit_amode_ereg_greg ( reg, mkGrp1opcode(opc) );
356 if (sz == 2) emitW ( lit ); else emitL ( lit );
357 }
358 if (dis)
359 VG_(printf)( "\n\t\t%s%c\t$0x%x, %s\n",
360 VG_(nameUOpcode)(False,opc), nameISize(sz),
361 lit, nameIReg(sz,reg));
362}
363
364static void emit_shiftopv_lit_reg ( Int sz, Opcode opc, UInt lit, Int reg )
365{
366 newEmit();
367 if (sz == 2) emitB ( 0x66 );
368 emitB ( 0xC1 ); /* Grp2 Ib,Ev */
369 emit_amode_ereg_greg ( reg, mkGrp2opcode(opc) );
370 emitB ( lit );
371 if (dis)
372 VG_(printf)( "\n\t\t%s%c\t$%d, %s\n",
373 VG_(nameUOpcode)(False,opc), nameISize(sz),
374 lit, nameIReg(sz,reg));
375}
376
377static void emit_shiftopv_cl_stack0 ( Int sz, Opcode opc )
378{
379 newEmit();
380 if (sz == 2) emitB ( 0x66 );
381 emitB ( 0xD3 ); /* Grp2 CL,Ev */
382 emitB ( mkModRegRM ( 1, mkGrp2opcode(opc), 4 ) );
383 emitB ( 0x24 ); /* a SIB, I think `d8(%esp)' */
384 emitB ( 0x00 ); /* the d8 displacement */
385 if (dis)
386 VG_(printf)("\n\t\t%s%c %%cl, 0(%%esp)\n",
387 VG_(nameUOpcode)(False,opc), nameISize(sz) );
388}
389
390static void emit_shiftopb_cl_stack0 ( Opcode opc )
391{
392 newEmit();
393 emitB ( 0xD2 ); /* Grp2 CL,Eb */
394 emitB ( mkModRegRM ( 1, mkGrp2opcode(opc), 4 ) );
395 emitB ( 0x24 ); /* a SIB, I think `d8(%esp)' */
396 emitB ( 0x00 ); /* the d8 displacement */
397 if (dis)
398 VG_(printf)("\n\t\t%s%c %%cl, 0(%%esp)\n",
399 VG_(nameUOpcode)(False,opc), nameISize(1) );
400}
401
402static void emit_nonshiftopv_offregmem_reg ( Int sz, Opcode opc,
403 Int off, Int areg, Int reg )
404{
405 newEmit();
406 if (sz == 2) emitB ( 0x66 );
407 emitB ( 3 + mkPrimaryOpcode(opc) ); /* op Ev, Gv */
408 emit_amode_offregmem_reg ( off, areg, reg );
409 if (dis)
410 VG_(printf)( "\n\t\t%s%c\t0x%x(%s), %s\n",
411 VG_(nameUOpcode)(False,opc), nameISize(sz),
412 off, nameIReg(4,areg), nameIReg(sz,reg));
413}
414
415static void emit_nonshiftopv_reg_reg ( Int sz, Opcode opc,
416 Int reg1, Int reg2 )
417{
418 newEmit();
419 if (sz == 2) emitB ( 0x66 );
420# if 0
421 /* Perfectly correct, but the GNU assembler uses the other form.
422 Therefore we too use the other form, to aid verification. */
423 emitB ( 3 + mkPrimaryOpcode(opc) ); /* op Ev, Gv */
424 emit_amode_ereg_greg ( reg1, reg2 );
425# else
426 emitB ( 1 + mkPrimaryOpcode(opc) ); /* op Gv, Ev */
427 emit_amode_greg_ereg ( reg1, reg2 );
428# endif
429 if (dis)
430 VG_(printf)( "\n\t\t%s%c\t%s, %s\n",
431 VG_(nameUOpcode)(False,opc), nameISize(sz),
432 nameIReg(sz,reg1), nameIReg(sz,reg2));
433}
434
435static void emit_movv_lit_reg ( Int sz, UInt lit, Int reg )
436{
437 if (lit == 0) {
438 emit_nonshiftopv_reg_reg ( sz, XOR, reg, reg );
439 return;
440 }
441 newEmit();
442 if (sz == 2) emitB ( 0x66 );
443 emitB ( 0xB8+reg ); /* MOV imm, Gv */
444 if (sz == 2) emitW ( lit ); else emitL ( lit );
445 if (dis)
446 VG_(printf)( "\n\t\tmov%c\t$0x%x, %s\n",
447 nameISize(sz), lit, nameIReg(sz,reg));
448}
449
450static void emit_unaryopv_reg ( Int sz, Opcode opc, Int reg )
451{
452 newEmit();
453 if (sz == 2) emitB ( 0x66 );
454 switch (opc) {
455 case NEG:
456 emitB ( 0xF7 );
457 emit_amode_ereg_greg ( reg, mkGrp3opcode(NEG) );
458 if (dis)
459 VG_(printf)( "\n\t\tneg%c\t%s\n",
460 nameISize(sz), nameIReg(sz,reg));
461 break;
462 case NOT:
463 emitB ( 0xF7 );
464 emit_amode_ereg_greg ( reg, mkGrp3opcode(NOT) );
465 if (dis)
466 VG_(printf)( "\n\t\tnot%c\t%s\n",
467 nameISize(sz), nameIReg(sz,reg));
468 break;
469 case DEC:
470 emitB ( 0x48 + reg );
471 if (dis)
472 VG_(printf)( "\n\t\tdec%c\t%s\n",
473 nameISize(sz), nameIReg(sz,reg));
474 break;
475 case INC:
476 emitB ( 0x40 + reg );
477 if (dis)
478 VG_(printf)( "\n\t\tinc%c\t%s\n",
479 nameISize(sz), nameIReg(sz,reg));
480 break;
481 default:
482 VG_(panic)("emit_unaryopv_reg");
483 }
484}
485
486static void emit_pushv_reg ( Int sz, Int reg )
487{
488 newEmit();
489 if (sz == 2) {
490 emitB ( 0x66 );
491 } else {
492 vg_assert(sz == 4);
493 }
494 emitB ( 0x50 + reg );
495 if (dis)
496 VG_(printf)("\n\t\tpush%c %s\n", nameISize(sz), nameIReg(sz,reg));
497}
498
499static void emit_popv_reg ( Int sz, Int reg )
500{
501 newEmit();
502 if (sz == 2) {
503 emitB ( 0x66 );
504 } else {
505 vg_assert(sz == 4);
506 }
507 emitB ( 0x58 + reg );
508 if (dis)
509 VG_(printf)("\n\t\tpop%c %s\n", nameISize(sz), nameIReg(sz,reg));
510}
511
512static void emit_pushl_lit8 ( Int lit8 )
513{
514 vg_assert(lit8 >= -128 && lit8 < 128);
515 newEmit();
516 emitB ( 0x6A );
517 emitB ( (UChar)((UInt)lit8) );
518 if (dis)
519 VG_(printf)("\n\t\tpushl $%d\n", lit8 );
520}
521
522static void emit_pushl_lit32 ( UInt int32 )
523{
524 newEmit();
525 emitB ( 0x68 );
526 emitL ( int32 );
527 if (dis)
528 VG_(printf)("\n\t\tpushl $0x%x\n", int32 );
529}
530
531static void emit_cmpl_zero_reg ( Int reg )
532{
533 newEmit();
534 emitB ( 0x83 );
535 emit_amode_ereg_greg ( reg, 7 /* Grp 3 opcode for CMP */ );
536 emitB ( 0x00 );
537 if (dis)
538 VG_(printf)("\n\t\tcmpl $0, %s\n", nameIReg(4,reg));
539}
540
541static void emit_swapl_reg_ECX ( Int reg )
542{
543 newEmit();
544 emitB ( 0x87 ); /* XCHG Gv,Ev */
545 emit_amode_ereg_greg ( reg, R_ECX );
546 if (dis)
547 VG_(printf)("\n\t\txchgl %%ecx, %s\n", nameIReg(4,reg));
548}
549
550static void emit_swapl_reg_EAX ( Int reg )
551{
552 newEmit();
553 emitB ( 0x90 + reg ); /* XCHG Gv,eAX */
554 if (dis)
555 VG_(printf)("\n\t\txchgl %%eax, %s\n", nameIReg(4,reg));
556}
557
558static void emit_swapl_reg_reg ( Int reg1, Int reg2 )
559{
560 newEmit();
561 emitB ( 0x87 ); /* XCHG Gv,Ev */
562 emit_amode_ereg_greg ( reg1, reg2 );
563 if (dis)
564 VG_(printf)("\n\t\txchgl %s, %s\n", nameIReg(4,reg1),
565 nameIReg(4,reg2));
566}
567
568static void emit_bswapl_reg ( Int reg )
569{
570 newEmit();
571 emitB ( 0x0F );
572 emitB ( 0xC8 + reg ); /* BSWAP r32 */
573 if (dis)
574 VG_(printf)("\n\t\tbswapl %s\n", nameIReg(4,reg));
575}
576
577static void emit_movl_reg_reg ( Int regs, Int regd )
578{
579 newEmit();
580 emitB ( 0x89 ); /* MOV Gv,Ev */
581 emit_amode_ereg_greg ( regd, regs );
582 if (dis)
583 VG_(printf)("\n\t\tmovl %s, %s\n", nameIReg(4,regs), nameIReg(4,regd));
584}
585
586static void emit_testv_lit_reg ( Int sz, UInt lit, Int reg )
587{
588 newEmit();
589 if (sz == 2) {
590 emitB ( 0x66 );
591 } else {
592 vg_assert(sz == 4);
593 }
594 emitB ( 0xF7 ); /* Grp3 Ev */
595 emit_amode_ereg_greg ( reg, 0 /* Grp3 subopcode for TEST */ );
596 if (sz == 2) emitW ( lit ); else emitL ( lit );
597 if (dis)
598 VG_(printf)("\n\t\ttest%c $0x%x, %s\n", nameISize(sz),
599 lit, nameIReg(sz,reg));
600}
601
602static void emit_testv_lit_offregmem ( Int sz, UInt lit, Int off, Int reg )
603{
604 newEmit();
605 if (sz == 2) {
606 emitB ( 0x66 );
607 } else {
608 vg_assert(sz == 4);
609 }
610 emitB ( 0xF7 ); /* Grp3 Ev */
611 emit_amode_offregmem_reg ( off, reg, 0 /* Grp3 subopcode for TEST */ );
612 if (sz == 2) emitW ( lit ); else emitL ( lit );
613 if (dis)
614 VG_(printf)("\n\t\ttest%c $%d, 0x%x(%s)\n",
615 nameISize(sz), lit, off, nameIReg(4,reg) );
616}
617
618static void emit_movv_lit_offregmem ( Int sz, UInt lit, Int off, Int memreg )
619{
620 newEmit();
621 if (sz == 2) {
622 emitB ( 0x66 );
623 } else {
624 vg_assert(sz == 4);
625 }
626 emitB ( 0xC7 ); /* Grp11 Ev */
627 emit_amode_offregmem_reg ( off, memreg, 0 /* Grp11 subopcode for MOV */ );
628 if (sz == 2) emitW ( lit ); else emitL ( lit );
629 if (dis)
630 VG_(printf)( "\n\t\tmov%c\t$0x%x, 0x%x(%s)\n",
631 nameISize(sz), lit, off, nameIReg(4,memreg) );
632}
633
634
635/*----------------------------------------------------*/
636/*--- b-size (1 byte) instruction emitters ---*/
637/*----------------------------------------------------*/
638
639/* There is some doubt as to whether C6 (Grp 11) is in the
640 486 insn set. ToDo: investigate. */
641static void emit_movb_lit_offregmem ( UInt lit, Int off, Int memreg )
642{
643 newEmit();
644 emitB ( 0xC6 ); /* Grp11 Eb */
645 emit_amode_offregmem_reg ( off, memreg, 0 /* Grp11 subopcode for MOV */ );
646 emitB ( lit );
647 if (dis)
648 VG_(printf)( "\n\t\tmovb\t$0x%x, 0x%x(%s)\n",
649 lit, off, nameIReg(4,memreg) );
650}
651
652static void emit_nonshiftopb_offregmem_reg ( Opcode opc,
653 Int off, Int areg, Int reg )
654{
655 newEmit();
656 emitB ( 2 + mkPrimaryOpcode(opc) ); /* op Eb, Gb */
657 emit_amode_offregmem_reg ( off, areg, reg );
658 if (dis)
659 VG_(printf)( "\n\t\t%sb\t0x%x(%s), %s\n",
660 VG_(nameUOpcode)(False,opc), off, nameIReg(4,areg),
661 nameIReg(1,reg));
662}
663
664static void emit_movb_reg_offregmem ( Int reg, Int off, Int areg )
665{
666 /* Could do better when reg == %al. */
667 newEmit();
668 emitB ( 0x88 ); /* MOV G1, E1 */
669 emit_amode_offregmem_reg ( off, areg, reg );
670 if (dis)
671 VG_(printf)( "\n\t\tmovb\t%s, 0x%x(%s)\n",
672 nameIReg(1,reg), off, nameIReg(4,areg));
673}
674
675static void emit_nonshiftopb_reg_reg ( Opcode opc, Int reg1, Int reg2 )
676{
677 newEmit();
678 emitB ( 2 + mkPrimaryOpcode(opc) ); /* op Eb, Gb */
679 emit_amode_ereg_greg ( reg1, reg2 );
680 if (dis)
681 VG_(printf)( "\n\t\t%sb\t%s, %s\n",
682 VG_(nameUOpcode)(False,opc),
683 nameIReg(1,reg1), nameIReg(1,reg2));
684}
685
686static void emit_movb_reg_regmem ( Int reg1, Int reg2 )
687{
688 newEmit();
689 emitB ( 0x88 ); /* MOV G1, E1 */
690 emit_amode_regmem_reg ( reg2, reg1 );
691 if (dis)
692 VG_(printf)( "\n\t\tmovb\t%s, (%s)\n", nameIReg(1,reg1),
693 nameIReg(4,reg2));
694}
695
696static void emit_nonshiftopb_lit_reg ( Opcode opc, UInt lit, Int reg )
697{
698 newEmit();
699 emitB ( 0x80 ); /* Grp1 Ib,Eb */
700 emit_amode_ereg_greg ( reg, mkGrp1opcode(opc) );
701 emitB ( lit & 0x000000FF );
702 if (dis)
703 VG_(printf)( "\n\t\t%sb\t$0x%x, %s\n", VG_(nameUOpcode)(False,opc),
704 lit, nameIReg(1,reg));
705}
706
707static void emit_shiftopb_lit_reg ( Opcode opc, UInt lit, Int reg )
708{
709 newEmit();
710 emitB ( 0xC0 ); /* Grp2 Ib,Eb */
711 emit_amode_ereg_greg ( reg, mkGrp2opcode(opc) );
712 emitB ( lit );
713 if (dis)
714 VG_(printf)( "\n\t\t%sb\t$%d, %s\n",
715 VG_(nameUOpcode)(False,opc),
716 lit, nameIReg(1,reg));
717}
718
719static void emit_unaryopb_reg ( Opcode opc, Int reg )
720{
721 newEmit();
722 switch (opc) {
723 case INC:
724 emitB ( 0xFE );
725 emit_amode_ereg_greg ( reg, mkGrp4opcode(INC) );
726 if (dis)
727 VG_(printf)( "\n\t\tincb\t%s\n", nameIReg(1,reg));
728 break;
729 case DEC:
730 emitB ( 0xFE );
731 emit_amode_ereg_greg ( reg, mkGrp4opcode(DEC) );
732 if (dis)
733 VG_(printf)( "\n\t\tdecb\t%s\n", nameIReg(1,reg));
734 break;
735 case NOT:
736 emitB ( 0xF6 );
737 emit_amode_ereg_greg ( reg, mkGrp3opcode(NOT) );
738 if (dis)
739 VG_(printf)( "\n\t\tnotb\t%s\n", nameIReg(1,reg));
740 break;
741 case NEG:
742 emitB ( 0xF6 );
743 emit_amode_ereg_greg ( reg, mkGrp3opcode(NEG) );
744 if (dis)
745 VG_(printf)( "\n\t\tnegb\t%s\n", nameIReg(1,reg));
746 break;
747 default:
748 VG_(panic)("emit_unaryopb_reg");
749 }
750}
751
752static void emit_testb_lit_reg ( UInt lit, Int reg )
753{
754 newEmit();
755 emitB ( 0xF6 ); /* Grp3 Eb */
756 emit_amode_ereg_greg ( reg, 0 /* Grp3 subopcode for TEST */ );
757 emitB ( lit );
758 if (dis)
759 VG_(printf)("\n\t\ttestb $0x%x, %s\n", lit, nameIReg(1,reg));
760}
761
762
763/*----------------------------------------------------*/
764/*--- zero-extended load emitters ---*/
765/*----------------------------------------------------*/
766
767static void emit_movzbl_offregmem_reg ( Int off, Int regmem, Int reg )
768{
769 newEmit();
770 emitB ( 0x0F ); emitB ( 0xB6 ); /* MOVZBL */
771 emit_amode_offregmem_reg ( off, regmem, reg );
772 if (dis)
773 VG_(printf)( "\n\t\tmovzbl\t0x%x(%s), %s\n",
774 off, nameIReg(4,regmem), nameIReg(4,reg));
775}
776
777static void emit_movzbl_regmem_reg ( Int reg1, Int reg2 )
778{
779 newEmit();
780 emitB ( 0x0F ); emitB ( 0xB6 ); /* MOVZBL */
781 emit_amode_regmem_reg ( reg1, reg2 );
782 if (dis)
783 VG_(printf)( "\n\t\tmovzbl\t(%s), %s\n", nameIReg(4,reg1),
784 nameIReg(4,reg2));
785}
786
787static void emit_movzwl_offregmem_reg ( Int off, Int areg, Int reg )
788{
789 newEmit();
790 emitB ( 0x0F ); emitB ( 0xB7 ); /* MOVZWL */
791 emit_amode_offregmem_reg ( off, areg, reg );
792 if (dis)
793 VG_(printf)( "\n\t\tmovzwl\t0x%x(%s), %s\n",
794 off, nameIReg(4,areg), nameIReg(4,reg));
795}
796
797static void emit_movzwl_regmem_reg ( Int reg1, Int reg2 )
798{
799 newEmit();
800 emitB ( 0x0F ); emitB ( 0xB7 ); /* MOVZWL */
801 emit_amode_regmem_reg ( reg1, reg2 );
802 if (dis)
803 VG_(printf)( "\n\t\tmovzwl\t(%s), %s\n", nameIReg(4,reg1),
804 nameIReg(4,reg2));
805}
806
807/*----------------------------------------------------*/
808/*--- FPU instruction emitters ---*/
809/*----------------------------------------------------*/
810
811static void emit_get_fpu_state ( void )
812{
813 Int off = 4 * VGOFF_(m_fpustate);
814 newEmit();
815 emitB ( 0xDD ); emitB ( 0xA5 ); /* frstor d32(%ebp) */
816 emitL ( off );
817 if (dis)
818 VG_(printf)("\n\t\tfrstor\t%d(%%ebp)\n", off );
819}
820
821static void emit_put_fpu_state ( void )
822{
823 Int off = 4 * VGOFF_(m_fpustate);
824 newEmit();
825 emitB ( 0xDD ); emitB ( 0xB5 ); /* fnsave d32(%ebp) */
826 emitL ( off );
827 if (dis)
828 VG_(printf)("\n\t\tfnsave\t%d(%%ebp)\n", off );
829}
830
831static void emit_fpu_no_mem ( UChar first_byte,
832 UChar second_byte )
833{
834 newEmit();
835 emitB ( first_byte );
836 emitB ( second_byte );
837 if (dis)
838 VG_(printf)("\n\t\tfpu-0x%x:0x%x\n",
839 (UInt)first_byte, (UInt)second_byte );
840}
841
842static void emit_fpu_regmem ( UChar first_byte,
843 UChar second_byte_masked,
844 Int reg )
845{
846 newEmit();
847 emitB ( first_byte );
848 emit_amode_regmem_reg ( reg, second_byte_masked >> 3 );
849 if (dis)
850 VG_(printf)("\n\t\tfpu-0x%x:0x%x-(%s)\n",
851 (UInt)first_byte, (UInt)second_byte_masked,
852 nameIReg(4,reg) );
853}
854
855
856/*----------------------------------------------------*/
857/*--- misc instruction emitters ---*/
858/*----------------------------------------------------*/
859
860static void emit_call_reg ( Int reg )
861{
862 newEmit();
863 emitB ( 0xFF ); /* Grp5 */
864 emit_amode_ereg_greg ( reg, mkGrp5opcode(CALLM) );
865 if (dis)
866 VG_(printf)( "\n\t\tcall\t*%s\n", nameIReg(4,reg) );
867}
868
869
870static void emit_call_star_EBP_off ( Int byte_off )
871{
872 newEmit();
873 if (byte_off < -128 || byte_off > 127) {
874 emitB ( 0xFF );
875 emitB ( 0x95 );
876 emitL ( byte_off );
877 } else {
878 emitB ( 0xFF );
879 emitB ( 0x55 );
880 emitB ( byte_off );
881 }
882 if (dis)
883 VG_(printf)( "\n\t\tcall * %d(%%ebp)\n", byte_off );
884}
885
886
887static void emit_addlit8_offregmem ( Int lit8, Int regmem, Int off )
888{
889 vg_assert(lit8 >= -128 && lit8 < 128);
890 newEmit();
891 emitB ( 0x83 ); /* Grp1 Ib,Ev */
892 emit_amode_offregmem_reg ( off, regmem,
893 0 /* Grp1 subopcode for ADD */ );
894 emitB ( lit8 & 0xFF );
895 if (dis)
896 VG_(printf)( "\n\t\taddl $%d, %d(%s)\n", lit8, off,
897 nameIReg(4,regmem));
898}
899
900
901static void emit_add_lit_to_esp ( Int lit )
902{
903 if (lit < -128 || lit > 127) VG_(panic)("emit_add_lit_to_esp");
904 newEmit();
905 emitB ( 0x83 );
906 emitB ( 0xC4 );
907 emitB ( lit & 0xFF );
908 if (dis)
909 VG_(printf)( "\n\t\taddl $%d, %%esp\n", lit );
910}
911
912
913static void emit_movb_AL_zeroESPmem ( void )
914{
915 /* movb %al, 0(%esp) */
916 /* 88442400 movb %al, 0(%esp) */
917 newEmit();
918 emitB ( 0x88 );
919 emitB ( 0x44 );
920 emitB ( 0x24 );
921 emitB ( 0x00 );
922 if (dis)
923 VG_(printf)( "\n\t\tmovb %%al, 0(%%esp)\n" );
924}
925
926static void emit_movb_zeroESPmem_AL ( void )
927{
928 /* movb 0(%esp), %al */
929 /* 8A442400 movb 0(%esp), %al */
930 newEmit();
931 emitB ( 0x8A );
932 emitB ( 0x44 );
933 emitB ( 0x24 );
934 emitB ( 0x00 );
935 if (dis)
936 VG_(printf)( "\n\t\tmovb 0(%%esp), %%al\n" );
937}
938
939
940/* Emit a jump short with an 8-bit signed offset. Note that the
941 offset is that which should be added to %eip once %eip has been
942 advanced over this insn. */
943static void emit_jcondshort_delta ( Condcode cond, Int delta )
944{
945 vg_assert(delta >= -128 && delta <= 127);
946 newEmit();
947 emitB ( 0x70 + (UInt)cond );
948 emitB ( (UChar)delta );
949 if (dis)
950 VG_(printf)( "\n\t\tj%s-8\t%%eip+%d\n",
951 VG_(nameCondcode)(cond), delta );
952}
953
954static void emit_get_eflags ( void )
955{
956 Int off = 4 * VGOFF_(m_eflags);
957 vg_assert(off >= 0 && off < 128);
958 newEmit();
959 emitB ( 0xFF ); /* PUSHL off(%ebp) */
960 emitB ( 0x75 );
961 emitB ( off );
962 emitB ( 0x9D ); /* POPFL */
963 if (dis)
964 VG_(printf)( "\n\t\tpushl %d(%%ebp) ; popfl\n", off );
965}
966
967static void emit_put_eflags ( void )
968{
969 Int off = 4 * VGOFF_(m_eflags);
970 vg_assert(off >= 0 && off < 128);
971 newEmit();
972 emitB ( 0x9C ); /* PUSHFL */
973 emitB ( 0x8F ); /* POPL vg_m_state.m_eflags */
974 emitB ( 0x45 );
975 emitB ( off );
976 if (dis)
977 VG_(printf)( "\n\t\tpushfl ; popl %d(%%ebp)\n", off );
978}
979
980static void emit_setb_reg ( Int reg, Condcode cond )
981{
982 newEmit();
983 emitB ( 0x0F ); emitB ( 0x90 + (UChar)cond );
984 emit_amode_ereg_greg ( reg, 0 );
985 if (dis)
986 VG_(printf)("\n\t\tset%s %s\n",
987 VG_(nameCondcode)(cond), nameIReg(1,reg));
988}
989
990static void emit_ret ( void )
991{
992 newEmit();
993 emitB ( 0xC3 ); /* RET */
994 if (dis)
995 VG_(printf)("\n\t\tret\n");
996}
997
998static void emit_pushal ( void )
999{
1000 newEmit();
1001 emitB ( 0x60 ); /* PUSHAL */
1002 if (dis)
1003 VG_(printf)("\n\t\tpushal\n");
1004}
1005
1006static void emit_popal ( void )
1007{
1008 newEmit();
1009 emitB ( 0x61 ); /* POPAL */
1010 if (dis)
1011 VG_(printf)("\n\t\tpopal\n");
1012}
1013
1014static void emit_lea_litreg_reg ( UInt lit, Int regmem, Int reg )
1015{
1016 newEmit();
1017 emitB ( 0x8D ); /* LEA M,Gv */
1018 emit_amode_offregmem_reg ( (Int)lit, regmem, reg );
1019 if (dis)
1020 VG_(printf)("\n\t\tleal 0x%x(%s), %s\n",
1021 lit, nameIReg(4,regmem), nameIReg(4,reg) );
1022}
1023
1024static void emit_lea_sib_reg ( UInt lit, Int scale,
1025 Int regbase, Int regindex, Int reg )
1026{
1027 newEmit();
1028 emitB ( 0x8D ); /* LEA M,Gv */
1029 emit_amode_sib_reg ( (Int)lit, scale, regbase, regindex, reg );
1030 if (dis)
1031 VG_(printf)("\n\t\tleal 0x%x(%s,%s,%d), %s\n",
1032 lit, nameIReg(4,regbase),
1033 nameIReg(4,regindex), scale,
1034 nameIReg(4,reg) );
1035}
1036
1037static void emit_AMD_prefetch_reg ( Int reg )
1038{
1039 newEmit();
1040 emitB ( 0x0F );
1041 emitB ( 0x0D );
1042 emit_amode_regmem_reg ( reg, 1 /* 0 is prefetch; 1 is prefetchw */ );
1043 if (dis)
1044 VG_(printf)("\n\t\tamd-prefetch (%s)\n", nameIReg(4,reg) );
1045}
1046
1047/*----------------------------------------------------*/
1048/*--- Instruction synthesisers ---*/
1049/*----------------------------------------------------*/
1050
1051static Condcode invertCondition ( Condcode cond )
1052{
1053 return (Condcode)(1 ^ (UInt)cond);
1054}
1055
1056
1057/* Synthesise a call to *baseBlock[offset], ie,
1058 call * (4 x offset)(%ebp).
1059*/
1060static void synth_call_baseBlock_method ( Bool ensure_shortform,
1061 Int word_offset )
1062{
1063 vg_assert(word_offset >= 0);
1064 vg_assert(word_offset < VG_BASEBLOCK_WORDS);
1065 if (ensure_shortform)
1066 vg_assert(word_offset < 32);
1067 emit_call_star_EBP_off ( 4 * word_offset );
1068}
1069
njn6431be72002-07-28 09:53:34 +00001070static void synth_ccall_saveRegs ( void )
1071{
1072 emit_pushv_reg ( 4, R_EAX );
1073 emit_pushv_reg ( 4, R_ECX );
1074 emit_pushv_reg ( 4, R_EDX );
1075}
1076
1077static void synth_ccall_pushOneArg ( Int r1 )
1078{
1079 emit_pushv_reg ( 4, r1 );
1080}
1081
1082static void synth_ccall_pushTwoArgs ( Int r1, Int r2 )
1083{
1084 /* must push in reverse order */
1085 emit_pushv_reg ( 4, r2 );
1086 emit_pushv_reg ( 4, r1 );
1087}
1088
1089/* Synthesise a call to *baseBlock[offset], ie,
1090 call * (4 x offset)(%ebp) with arguments
1091*/
1092static void synth_ccall_call_clearStack_restoreRegs ( Int word_offset,
1093 UInt n_args_bytes )
1094{
1095 vg_assert(word_offset >= 0);
1096 vg_assert(word_offset < VG_BASEBLOCK_WORDS);
1097 vg_assert(n_args_bytes <= 12); /* Max 3 word-sized args */
1098 vg_assert(0 == (n_args_bytes & 0x3)); /* Divisible by four */
1099
1100 emit_call_star_EBP_off ( 4 * word_offset );
1101 if ( 0 != n_args_bytes )
1102 emit_add_lit_to_esp ( n_args_bytes );
1103 emit_popv_reg ( 4, R_EDX );
1104 emit_popv_reg ( 4, R_ECX );
1105 emit_popv_reg ( 4, R_EAX );
1106}
sewardjde4a1d02002-03-22 01:27:54 +00001107
sewardj2e93c502002-04-12 11:12:52 +00001108static void load_ebp_from_JmpKind ( JmpKind jmpkind )
sewardjde4a1d02002-03-22 01:27:54 +00001109{
sewardj2e93c502002-04-12 11:12:52 +00001110 switch (jmpkind) {
1111 case JmpBoring:
1112 break;
1113 case JmpCall:
1114 case JmpRet:
sewardj54cacf02002-04-12 23:24:59 +00001115 emit_movv_lit_reg ( 4, VG_TRC_EBP_JMP_STKADJ, R_EBP );
sewardj2e93c502002-04-12 11:12:52 +00001116 break;
1117 case JmpSyscall:
1118 emit_movv_lit_reg ( 4, VG_TRC_EBP_JMP_SYSCALL, R_EBP );
1119 break;
1120 case JmpClientReq:
1121 emit_movv_lit_reg ( 4, VG_TRC_EBP_JMP_CLIENTREQ, R_EBP );
1122 break;
1123 default:
1124 VG_(panic)("load_ebp_from_JmpKind");
1125 }
1126}
1127
1128/* Jump to the next translation, by loading its original addr into
1129 %eax and returning to the scheduler. Signal special requirements
1130 by loading a special value into %ebp first.
1131*/
1132static void synth_jmp_reg ( Int reg, JmpKind jmpkind )
1133{
1134 load_ebp_from_JmpKind ( jmpkind );
sewardjde4a1d02002-03-22 01:27:54 +00001135 if (reg != R_EAX)
1136 emit_movv_reg_reg ( 4, reg, R_EAX );
sewardjde4a1d02002-03-22 01:27:54 +00001137 emit_ret();
1138}
1139
1140
1141/* Same deal as synth_jmp_reg. */
sewardj2e93c502002-04-12 11:12:52 +00001142static void synth_jmp_lit ( Addr addr, JmpKind jmpkind )
sewardjde4a1d02002-03-22 01:27:54 +00001143{
sewardj2e93c502002-04-12 11:12:52 +00001144 load_ebp_from_JmpKind ( jmpkind );
sewardjde4a1d02002-03-22 01:27:54 +00001145 emit_movv_lit_reg ( 4, addr, R_EAX );
1146 emit_ret();
1147}
1148
1149
sewardjde4a1d02002-03-22 01:27:54 +00001150static void synth_jcond_lit ( Condcode cond, Addr addr )
1151{
1152 /* Do the following:
1153 get eflags
1154 jmp short if not cond to xyxyxy
1155 addr -> eax
1156 ret
1157 xyxyxy
1158
1159 2 0000 750C jnz xyxyxy
1160 3 0002 B877665544 movl $0x44556677, %eax
1161 4 0007 C3 ret
1162 5 0008 FFE3 jmp *%ebx
1163 6 xyxyxy:
1164 */
1165 emit_get_eflags();
1166 emit_jcondshort_delta ( invertCondition(cond), 5+1 );
sewardj2e93c502002-04-12 11:12:52 +00001167 synth_jmp_lit ( addr, JmpBoring );
sewardjde4a1d02002-03-22 01:27:54 +00001168}
1169
1170
1171static void synth_jmp_ifzero_reg_lit ( Int reg, Addr addr )
1172{
1173 /* 0000 83FF00 cmpl $0, %edi
1174 0003 750A jnz next
1175 0005 B844332211 movl $0x11223344, %eax
1176 000a C3 ret
1177 next:
1178 */
1179 emit_cmpl_zero_reg ( reg );
1180 emit_jcondshort_delta ( CondNZ, 5+1 );
sewardj2e93c502002-04-12 11:12:52 +00001181 synth_jmp_lit ( addr, JmpBoring );
sewardjde4a1d02002-03-22 01:27:54 +00001182}
1183
1184
1185static void synth_mov_lit_reg ( Int size, UInt lit, Int reg )
1186{
1187 /* Load the zero-extended literal into reg, at size l,
1188 regardless of the request size. */
1189 emit_movv_lit_reg ( 4, lit, reg );
1190}
1191
1192
1193static void synth_mov_regmem_reg ( Int size, Int reg1, Int reg2 )
1194{
1195 switch (size) {
1196 case 4: emit_movv_regmem_reg ( 4, reg1, reg2 ); break;
1197 case 2: emit_movzwl_regmem_reg ( reg1, reg2 ); break;
1198 case 1: emit_movzbl_regmem_reg ( reg1, reg2 ); break;
1199 default: VG_(panic)("synth_mov_regmem_reg");
1200 }
1201}
1202
1203
1204static void synth_mov_offregmem_reg ( Int size, Int off, Int areg, Int reg )
1205{
1206 switch (size) {
1207 case 4: emit_movv_offregmem_reg ( 4, off, areg, reg ); break;
1208 case 2: emit_movzwl_offregmem_reg ( off, areg, reg ); break;
1209 case 1: emit_movzbl_offregmem_reg ( off, areg, reg ); break;
1210 default: VG_(panic)("synth_mov_offregmem_reg");
1211 }
1212}
1213
1214
1215static void synth_mov_reg_offregmem ( Int size, Int reg,
1216 Int off, Int areg )
1217{
1218 switch (size) {
1219 case 4: emit_movv_reg_offregmem ( 4, reg, off, areg ); break;
1220 case 2: emit_movv_reg_offregmem ( 2, reg, off, areg ); break;
1221 case 1: if (reg < 4) {
1222 emit_movb_reg_offregmem ( reg, off, areg );
1223 }
1224 else {
1225 emit_swapl_reg_EAX ( reg );
1226 emit_movb_reg_offregmem ( R_AL, off, areg );
1227 emit_swapl_reg_EAX ( reg );
1228 }
1229 break;
1230 default: VG_(panic)("synth_mov_reg_offregmem");
1231 }
1232}
1233
1234
1235static void synth_mov_reg_memreg ( Int size, Int reg1, Int reg2 )
1236{
1237 Int s1;
1238 switch (size) {
1239 case 4: emit_movv_reg_regmem ( 4, reg1, reg2 ); break;
1240 case 2: emit_movv_reg_regmem ( 2, reg1, reg2 ); break;
1241 case 1: if (reg1 < 4) {
1242 emit_movb_reg_regmem ( reg1, reg2 );
1243 }
1244 else {
1245 /* Choose a swap reg which is < 4 and not reg1 or reg2. */
1246 for (s1 = 0; s1 == reg1 || s1 == reg2; s1++) ;
1247 emit_swapl_reg_reg ( s1, reg1 );
1248 emit_movb_reg_regmem ( s1, reg2 );
1249 emit_swapl_reg_reg ( s1, reg1 );
1250 }
1251 break;
1252 default: VG_(panic)("synth_mov_reg_litmem");
1253 }
1254}
1255
1256
1257static void synth_unaryop_reg ( Bool upd_cc,
1258 Opcode opcode, Int size,
1259 Int reg )
1260{
1261 /* NB! opcode is a uinstr opcode, not an x86 one! */
1262 switch (size) {
1263 case 4: if (upd_cc) emit_get_eflags();
1264 emit_unaryopv_reg ( 4, opcode, reg );
1265 if (upd_cc) emit_put_eflags();
1266 break;
1267 case 2: if (upd_cc) emit_get_eflags();
1268 emit_unaryopv_reg ( 2, opcode, reg );
1269 if (upd_cc) emit_put_eflags();
1270 break;
1271 case 1: if (reg < 4) {
1272 if (upd_cc) emit_get_eflags();
1273 emit_unaryopb_reg ( opcode, reg );
1274 if (upd_cc) emit_put_eflags();
1275 } else {
1276 emit_swapl_reg_EAX ( reg );
1277 if (upd_cc) emit_get_eflags();
1278 emit_unaryopb_reg ( opcode, R_AL );
1279 if (upd_cc) emit_put_eflags();
1280 emit_swapl_reg_EAX ( reg );
1281 }
1282 break;
1283 default: VG_(panic)("synth_unaryop_reg");
1284 }
1285}
1286
1287
1288
1289static void synth_nonshiftop_reg_reg ( Bool upd_cc,
1290 Opcode opcode, Int size,
1291 Int reg1, Int reg2 )
1292{
1293 /* NB! opcode is a uinstr opcode, not an x86 one! */
1294 switch (size) {
1295 case 4: if (upd_cc) emit_get_eflags();
1296 emit_nonshiftopv_reg_reg ( 4, opcode, reg1, reg2 );
1297 if (upd_cc) emit_put_eflags();
1298 break;
1299 case 2: if (upd_cc) emit_get_eflags();
1300 emit_nonshiftopv_reg_reg ( 2, opcode, reg1, reg2 );
1301 if (upd_cc) emit_put_eflags();
1302 break;
1303 case 1: { /* Horrible ... */
1304 Int s1, s2;
1305 /* Choose s1 and s2 to be x86 regs which we can talk about the
1306 lowest 8 bits, ie either %eax, %ebx, %ecx or %edx. Make
1307 sure s1 != s2 and that neither of them equal either reg1 or
1308 reg2. Then use them as temporaries to make things work. */
1309 if (reg1 < 4 && reg2 < 4) {
1310 if (upd_cc) emit_get_eflags();
1311 emit_nonshiftopb_reg_reg(opcode, reg1, reg2);
1312 if (upd_cc) emit_put_eflags();
1313 break;
1314 }
1315 for (s1 = 0; s1 == reg1 || s1 == reg2; s1++) ;
1316 if (reg1 >= 4 && reg2 < 4) {
1317 emit_swapl_reg_reg ( reg1, s1 );
1318 if (upd_cc) emit_get_eflags();
1319 emit_nonshiftopb_reg_reg(opcode, s1, reg2);
1320 if (upd_cc) emit_put_eflags();
1321 emit_swapl_reg_reg ( reg1, s1 );
1322 break;
1323 }
1324 for (s2 = 0; s2 == reg1 || s2 == reg2 || s2 == s1; s2++) ;
1325 if (reg1 < 4 && reg2 >= 4) {
1326 emit_swapl_reg_reg ( reg2, s2 );
1327 if (upd_cc) emit_get_eflags();
1328 emit_nonshiftopb_reg_reg(opcode, reg1, s2);
1329 if (upd_cc) emit_put_eflags();
1330 emit_swapl_reg_reg ( reg2, s2 );
1331 break;
1332 }
1333 if (reg1 >= 4 && reg2 >= 4 && reg1 != reg2) {
1334 emit_swapl_reg_reg ( reg1, s1 );
1335 emit_swapl_reg_reg ( reg2, s2 );
1336 if (upd_cc) emit_get_eflags();
1337 emit_nonshiftopb_reg_reg(opcode, s1, s2);
1338 if (upd_cc) emit_put_eflags();
1339 emit_swapl_reg_reg ( reg1, s1 );
1340 emit_swapl_reg_reg ( reg2, s2 );
1341 break;
1342 }
1343 if (reg1 >= 4 && reg2 >= 4 && reg1 == reg2) {
1344 emit_swapl_reg_reg ( reg1, s1 );
1345 if (upd_cc) emit_get_eflags();
1346 emit_nonshiftopb_reg_reg(opcode, s1, s1);
1347 if (upd_cc) emit_put_eflags();
1348 emit_swapl_reg_reg ( reg1, s1 );
1349 break;
1350 }
1351 VG_(panic)("synth_nonshiftopb_reg_reg");
1352 }
1353 default: VG_(panic)("synth_nonshiftop_reg_reg");
1354 }
1355}
1356
1357
1358static void synth_nonshiftop_offregmem_reg (
1359 Bool upd_cc,
1360 Opcode opcode, Int size,
1361 Int off, Int areg, Int reg )
1362{
1363 switch (size) {
1364 case 4:
1365 if (upd_cc) emit_get_eflags();
1366 emit_nonshiftopv_offregmem_reg ( 4, opcode, off, areg, reg );
1367 if (upd_cc) emit_put_eflags();
1368 break;
1369 case 2:
1370 if (upd_cc) emit_get_eflags();
1371 emit_nonshiftopv_offregmem_reg ( 2, opcode, off, areg, reg );
1372 if (upd_cc) emit_put_eflags();
1373 break;
1374 case 1:
1375 if (reg < 4) {
1376 if (upd_cc) emit_get_eflags();
1377 emit_nonshiftopb_offregmem_reg ( opcode, off, areg, reg );
1378 if (upd_cc) emit_put_eflags();
1379 } else {
1380 emit_swapl_reg_EAX ( reg );
1381 if (upd_cc) emit_get_eflags();
1382 emit_nonshiftopb_offregmem_reg ( opcode, off, areg, R_AL );
1383 if (upd_cc) emit_put_eflags();
1384 emit_swapl_reg_EAX ( reg );
1385 }
1386 break;
1387 default:
1388 VG_(panic)("synth_nonshiftop_litmem_reg");
1389 }
1390}
1391
1392
1393static void synth_nonshiftop_lit_reg ( Bool upd_cc,
1394 Opcode opcode, Int size,
1395 UInt lit, Int reg )
1396{
1397 switch (size) {
1398 case 4: if (upd_cc) emit_get_eflags();
1399 emit_nonshiftopv_lit_reg ( 4, opcode, lit, reg );
1400 if (upd_cc) emit_put_eflags();
1401 break;
1402 case 2: if (upd_cc) emit_get_eflags();
1403 emit_nonshiftopv_lit_reg ( 2, opcode, lit, reg );
1404 if (upd_cc) emit_put_eflags();
1405 break;
1406 case 1: if (reg < 4) {
1407 if (upd_cc) emit_get_eflags();
1408 emit_nonshiftopb_lit_reg ( opcode, lit, reg );
1409 if (upd_cc) emit_put_eflags();
1410 } else {
1411 emit_swapl_reg_EAX ( reg );
1412 if (upd_cc) emit_get_eflags();
1413 emit_nonshiftopb_lit_reg ( opcode, lit, R_AL );
1414 if (upd_cc) emit_put_eflags();
1415 emit_swapl_reg_EAX ( reg );
1416 }
1417 break;
1418 default: VG_(panic)("synth_nonshiftop_lit_reg");
1419 }
1420}
1421
1422
1423static void synth_push_reg ( Int size, Int reg )
1424{
1425 switch (size) {
1426 case 4:
1427 emit_pushv_reg ( 4, reg );
1428 break;
1429 case 2:
1430 emit_pushv_reg ( 2, reg );
1431 break;
1432 /* Pray that we don't have to generate this really cruddy bit of
1433 code very often. Could do better, but can I be bothered? */
1434 case 1:
1435 vg_assert(reg != R_ESP); /* duh */
1436 emit_add_lit_to_esp(-1);
1437 if (reg != R_EAX) emit_swapl_reg_EAX ( reg );
1438 emit_movb_AL_zeroESPmem();
1439 if (reg != R_EAX) emit_swapl_reg_EAX ( reg );
1440 break;
1441 default:
1442 VG_(panic)("synth_push_reg");
1443 }
1444}
1445
1446
1447static void synth_pop_reg ( Int size, Int reg )
1448{
1449 switch (size) {
1450 case 4:
1451 emit_popv_reg ( 4, reg );
1452 break;
1453 case 2:
1454 emit_popv_reg ( 2, reg );
1455 break;
1456 case 1:
1457 /* Same comment as above applies. */
1458 vg_assert(reg != R_ESP); /* duh */
1459 if (reg != R_EAX) emit_swapl_reg_EAX ( reg );
1460 emit_movb_zeroESPmem_AL();
1461 if (reg != R_EAX) emit_swapl_reg_EAX ( reg );
1462 emit_add_lit_to_esp(1);
1463 break;
1464 default: VG_(panic)("synth_pop_reg");
1465 }
1466}
1467
1468
1469static void synth_shiftop_reg_reg ( Bool upd_cc,
1470 Opcode opcode, Int size,
1471 Int regs, Int regd )
1472{
1473 synth_push_reg ( size, regd );
1474 if (regs != R_ECX) emit_swapl_reg_ECX ( regs );
1475 if (upd_cc) emit_get_eflags();
1476 switch (size) {
1477 case 4: emit_shiftopv_cl_stack0 ( 4, opcode ); break;
1478 case 2: emit_shiftopv_cl_stack0 ( 2, opcode ); break;
1479 case 1: emit_shiftopb_cl_stack0 ( opcode ); break;
1480 default: VG_(panic)("synth_shiftop_reg_reg");
1481 }
1482 if (upd_cc) emit_put_eflags();
1483 if (regs != R_ECX) emit_swapl_reg_ECX ( regs );
1484 synth_pop_reg ( size, regd );
1485}
1486
1487
1488static void synth_shiftop_lit_reg ( Bool upd_cc,
1489 Opcode opcode, Int size,
1490 UInt lit, Int reg )
1491{
1492 switch (size) {
1493 case 4: if (upd_cc) emit_get_eflags();
1494 emit_shiftopv_lit_reg ( 4, opcode, lit, reg );
1495 if (upd_cc) emit_put_eflags();
1496 break;
1497 case 2: if (upd_cc) emit_get_eflags();
1498 emit_shiftopv_lit_reg ( 2, opcode, lit, reg );
1499 if (upd_cc) emit_put_eflags();
1500 break;
1501 case 1: if (reg < 4) {
1502 if (upd_cc) emit_get_eflags();
1503 emit_shiftopb_lit_reg ( opcode, lit, reg );
1504 if (upd_cc) emit_put_eflags();
1505 } else {
1506 emit_swapl_reg_EAX ( reg );
1507 if (upd_cc) emit_get_eflags();
1508 emit_shiftopb_lit_reg ( opcode, lit, R_AL );
1509 if (upd_cc) emit_put_eflags();
1510 emit_swapl_reg_EAX ( reg );
1511 }
1512 break;
1513 default: VG_(panic)("synth_nonshiftop_lit_reg");
1514 }
1515}
1516
1517
1518static void synth_setb_reg ( Int reg, Condcode cond )
1519{
1520 emit_get_eflags();
1521 if (reg < 4) {
1522 emit_setb_reg ( reg, cond );
1523 } else {
1524 emit_swapl_reg_EAX ( reg );
1525 emit_setb_reg ( R_AL, cond );
1526 emit_swapl_reg_EAX ( reg );
1527 }
1528}
1529
1530
1531static void synth_fpu_regmem ( UChar first_byte,
1532 UChar second_byte_masked,
1533 Int reg )
1534{
1535 emit_get_fpu_state();
1536 emit_fpu_regmem ( first_byte, second_byte_masked, reg );
1537 emit_put_fpu_state();
1538}
1539
1540
1541static void synth_fpu_no_mem ( UChar first_byte,
1542 UChar second_byte )
1543{
1544 emit_get_fpu_state();
1545 emit_fpu_no_mem ( first_byte, second_byte );
1546 emit_put_fpu_state();
1547}
1548
1549
1550static void synth_movl_reg_reg ( Int src, Int dst )
1551{
1552 emit_movl_reg_reg ( src, dst );
1553}
1554
1555static void synth_cmovl_reg_reg ( Condcode cond, Int src, Int dst )
1556{
1557 emit_get_eflags();
1558 emit_jcondshort_delta ( invertCondition(cond),
1559 2 /* length of the next insn */ );
1560 emit_movl_reg_reg ( src, dst );
1561}
1562
1563
sewardjde4a1d02002-03-22 01:27:54 +00001564/* Synthesise a minimal test (and which discards result) of reg32
1565 against lit. It's always safe do simply
1566 emit_testv_lit_reg ( 4, lit, reg32 )
1567 but we try to do better when possible.
1568*/
1569static void synth_minimal_test_lit_reg ( UInt lit, Int reg32 )
1570{
1571 if ((lit & 0xFFFFFF00) == 0 && reg32 < 4) {
1572 /* We can get away with a byte insn. */
1573 emit_testb_lit_reg ( lit, reg32 );
1574 }
1575 else
1576 if ((lit & 0xFFFF0000) == 0) {
1577 /* Literal fits in 16 bits; do a word insn. */
1578 emit_testv_lit_reg ( 2, lit, reg32 );
1579 }
1580 else {
1581 /* Totally general ... */
1582 emit_testv_lit_reg ( 4, lit, reg32 );
1583 }
1584}
1585
1586
1587/*----------------------------------------------------*/
1588/*--- Top level of the uinstr -> x86 translation. ---*/
1589/*----------------------------------------------------*/
1590
1591/* Return the byte offset from %ebp (ie, into baseBlock)
1592 for the specified ArchReg or SpillNo. */
1593
1594static Int spillOrArchOffset ( Int size, Tag tag, UInt value )
1595{
1596 if (tag == SpillNo) {
1597 vg_assert(size == 4);
1598 vg_assert(value >= 0 && value < VG_MAX_SPILLSLOTS);
1599 return 4 * (value + VGOFF_(spillslots));
1600 }
1601 if (tag == ArchReg) {
1602 switch (value) {
1603 case R_EAX: return 4 * VGOFF_(m_eax);
1604 case R_ECX: return 4 * VGOFF_(m_ecx);
1605 case R_EDX: return 4 * VGOFF_(m_edx);
1606 case R_EBX: return 4 * VGOFF_(m_ebx);
1607 case R_ESP:
1608 if (size == 1) return 4 * VGOFF_(m_eax) + 1;
1609 else return 4 * VGOFF_(m_esp);
1610 case R_EBP:
1611 if (size == 1) return 4 * VGOFF_(m_ecx) + 1;
1612 else return 4 * VGOFF_(m_ebp);
1613 case R_ESI:
1614 if (size == 1) return 4 * VGOFF_(m_edx) + 1;
1615 else return 4 * VGOFF_(m_esi);
1616 case R_EDI:
1617 if (size == 1) return 4 * VGOFF_(m_ebx) + 1;
1618 else return 4 * VGOFF_(m_edi);
1619 }
1620 }
1621 VG_(panic)("spillOrArchOffset");
1622}
1623
1624
1625static Int eflagsOffset ( void )
1626{
1627 return 4 * VGOFF_(m_eflags);
1628}
1629
1630
1631static Int shadowOffset ( Int arch )
1632{
1633 switch (arch) {
1634 case R_EAX: return 4 * VGOFF_(sh_eax);
1635 case R_ECX: return 4 * VGOFF_(sh_ecx);
1636 case R_EDX: return 4 * VGOFF_(sh_edx);
1637 case R_EBX: return 4 * VGOFF_(sh_ebx);
1638 case R_ESP: return 4 * VGOFF_(sh_esp);
1639 case R_EBP: return 4 * VGOFF_(sh_ebp);
1640 case R_ESI: return 4 * VGOFF_(sh_esi);
1641 case R_EDI: return 4 * VGOFF_(sh_edi);
1642 default: VG_(panic)( "shadowOffset");
1643 }
1644}
1645
1646
1647static Int shadowFlagsOffset ( void )
1648{
1649 return 4 * VGOFF_(sh_eflags);
1650}
1651
1652
1653static void synth_LOADV ( Int sz, Int a_reg, Int tv_reg )
1654{
1655 Int i, j, helper_offw;
1656 Int pushed[VG_MAX_REALREGS+2];
1657 Int n_pushed;
1658 switch (sz) {
1659 case 4: helper_offw = VGOFF_(helperc_LOADV4); break;
1660 case 2: helper_offw = VGOFF_(helperc_LOADV2); break;
1661 case 1: helper_offw = VGOFF_(helperc_LOADV1); break;
1662 default: VG_(panic)("synth_LOADV");
1663 }
1664 n_pushed = 0;
1665 for (i = 0; i < VG_MAX_REALREGS; i++) {
1666 j = VG_(rankToRealRegNo) ( i );
1667 if (VG_CALLEE_SAVED(j)) continue;
1668 if (j == tv_reg || j == a_reg) continue;
1669 emit_pushv_reg ( 4, j );
1670 pushed[n_pushed++] = j;
1671 }
1672 emit_pushv_reg ( 4, a_reg );
1673 pushed[n_pushed++] = a_reg;
1674 vg_assert(n_pushed <= VG_MAX_REALREGS+1);
1675
1676 synth_call_baseBlock_method ( False, helper_offw );
1677 /* Result is in %eax; we need to get it to tv_reg. */
1678 if (tv_reg != R_EAX)
1679 emit_movv_reg_reg ( 4, R_EAX, tv_reg );
1680
1681 while (n_pushed > 0) {
1682 n_pushed--;
1683 if (pushed[n_pushed] == tv_reg) {
1684 emit_add_lit_to_esp ( 4 );
1685 } else {
1686 emit_popv_reg ( 4, pushed[n_pushed] );
1687 }
1688 }
1689}
1690
1691
1692static void synth_STOREV ( Int sz,
1693 Int tv_tag, Int tv_val,
1694 Int a_reg )
1695{
1696 Int i, j, helper_offw;
1697 vg_assert(tv_tag == RealReg || tv_tag == Literal);
1698 switch (sz) {
1699 case 4: helper_offw = VGOFF_(helperc_STOREV4); break;
1700 case 2: helper_offw = VGOFF_(helperc_STOREV2); break;
1701 case 1: helper_offw = VGOFF_(helperc_STOREV1); break;
1702 default: VG_(panic)("synth_STOREV");
1703 }
1704 for (i = 0; i < VG_MAX_REALREGS; i++) {
1705 j = VG_(rankToRealRegNo) ( i );
1706 if (VG_CALLEE_SAVED(j)) continue;
1707 if ((tv_tag == RealReg && j == tv_val) || j == a_reg) continue;
1708 emit_pushv_reg ( 4, j );
1709 }
1710 if (tv_tag == RealReg) {
1711 emit_pushv_reg ( 4, tv_val );
1712 } else {
1713 if (tv_val == VG_(extend_s_8to32)(tv_val))
1714 emit_pushl_lit8 ( VG_(extend_s_8to32)(tv_val) );
1715 else
1716 emit_pushl_lit32(tv_val);
1717 }
1718 emit_pushv_reg ( 4, a_reg );
1719 synth_call_baseBlock_method ( False, helper_offw );
1720 emit_popv_reg ( 4, a_reg );
1721 if (tv_tag == RealReg) {
1722 emit_popv_reg ( 4, tv_val );
1723 } else {
1724 emit_add_lit_to_esp ( 4 );
1725 }
1726 for (i = VG_MAX_REALREGS-1; i >= 0; i--) {
1727 j = VG_(rankToRealRegNo) ( i );
1728 if (VG_CALLEE_SAVED(j)) continue;
1729 if ((tv_tag == RealReg && j == tv_val) || j == a_reg) continue;
1730 emit_popv_reg ( 4, j );
1731 }
1732}
1733
1734
1735static void synth_WIDEN_signed ( Int sz_src, Int sz_dst, Int reg )
1736{
1737 if (sz_src == 1 && sz_dst == 4) {
1738 emit_shiftopv_lit_reg ( 4, SHL, 24, reg );
1739 emit_shiftopv_lit_reg ( 4, SAR, 24, reg );
1740 }
1741 else if (sz_src == 2 && sz_dst == 4) {
1742 emit_shiftopv_lit_reg ( 4, SHL, 16, reg );
1743 emit_shiftopv_lit_reg ( 4, SAR, 16, reg );
1744 }
1745 else if (sz_src == 1 && sz_dst == 2) {
1746 emit_shiftopv_lit_reg ( 2, SHL, 8, reg );
1747 emit_shiftopv_lit_reg ( 2, SAR, 8, reg );
1748 }
1749 else
1750 VG_(panic)("synth_WIDEN");
1751}
1752
1753
1754static void synth_SETV ( Int sz, Int reg )
1755{
1756 UInt val;
1757 switch (sz) {
1758 case 4: val = 0x00000000; break;
1759 case 2: val = 0xFFFF0000; break;
1760 case 1: val = 0xFFFFFF00; break;
1761 case 0: val = 0xFFFFFFFE; break;
1762 default: VG_(panic)("synth_SETV");
1763 }
1764 emit_movv_lit_reg ( 4, val, reg );
1765}
1766
1767
1768static void synth_TESTV ( Int sz, Int tag, Int val )
1769{
1770 vg_assert(tag == ArchReg || tag == RealReg);
1771 if (tag == ArchReg) {
1772 switch (sz) {
1773 case 4:
1774 emit_testv_lit_offregmem (
1775 4, 0xFFFFFFFF, shadowOffset(val), R_EBP );
1776 break;
1777 case 2:
1778 emit_testv_lit_offregmem (
1779 4, 0x0000FFFF, shadowOffset(val), R_EBP );
1780 break;
1781 case 1:
1782 if (val < 4) {
1783 emit_testv_lit_offregmem (
1784 4, 0x000000FF, shadowOffset(val), R_EBP );
1785 } else {
1786 emit_testv_lit_offregmem (
1787 4, 0x0000FF00, shadowOffset(val-4), R_EBP );
1788 }
1789 break;
1790 case 0:
1791 /* should never happen */
1792 default:
1793 VG_(panic)("synth_TESTV(ArchReg)");
1794 }
1795 } else {
1796 switch (sz) {
1797 case 4:
1798 /* Works, but holds the entire 32-bit literal, hence
1799 generating a 6-byte insn. We want to know if any bits
1800 in the reg are set, but since this is for the full reg,
1801 we might as well compare it against zero, which can be
1802 done with a shorter insn. */
1803 /* synth_minimal_test_lit_reg ( 0xFFFFFFFF, val ); */
1804 emit_cmpl_zero_reg ( val );
1805 break;
1806 case 2:
1807 synth_minimal_test_lit_reg ( 0x0000FFFF, val );
1808 break;
1809 case 1:
1810 synth_minimal_test_lit_reg ( 0x000000FF, val );
1811 break;
1812 case 0:
1813 synth_minimal_test_lit_reg ( 0x00000001, val );
1814 break;
1815 default:
1816 VG_(panic)("synth_TESTV(RealReg)");
1817 }
1818 }
1819 emit_jcondshort_delta ( CondZ, 3 );
1820 synth_call_baseBlock_method (
1821 True, /* needed to guarantee that this insn is indeed 3 bytes long */
1822 (sz==4 ? VGOFF_(helper_value_check4_fail)
1823 : (sz==2 ? VGOFF_(helper_value_check2_fail)
1824 : sz == 1 ? VGOFF_(helper_value_check1_fail)
1825 : VGOFF_(helper_value_check0_fail)))
1826 );
1827}
1828
1829
1830static void synth_GETV ( Int sz, Int arch, Int reg )
1831{
1832 /* VG_(printf)("synth_GETV %d of Arch %s\n", sz, nameIReg(sz, arch)); */
1833 switch (sz) {
1834 case 4:
1835 emit_movv_offregmem_reg ( 4, shadowOffset(arch), R_EBP, reg );
1836 break;
1837 case 2:
1838 emit_movzwl_offregmem_reg ( shadowOffset(arch), R_EBP, reg );
1839 emit_nonshiftopv_lit_reg ( 4, OR, 0xFFFF0000, reg );
1840 break;
1841 case 1:
1842 if (arch < 4) {
1843 emit_movzbl_offregmem_reg ( shadowOffset(arch), R_EBP, reg );
1844 } else {
1845 emit_movzbl_offregmem_reg ( shadowOffset(arch-4)+1, R_EBP, reg );
1846 }
1847 emit_nonshiftopv_lit_reg ( 4, OR, 0xFFFFFF00, reg );
1848 break;
1849 default:
1850 VG_(panic)("synth_GETV");
1851 }
1852}
1853
1854
1855static void synth_PUTV ( Int sz, Int srcTag, UInt lit_or_reg, Int arch )
1856{
1857 if (srcTag == Literal) {
1858 /* PUTV with a Literal is only ever used to set the corresponding
1859 ArchReg to `all valid'. Should really be a kind of SETV. */
1860 UInt lit = lit_or_reg;
1861 switch (sz) {
1862 case 4:
1863 vg_assert(lit == 0x00000000);
1864 emit_movv_lit_offregmem ( 4, 0x00000000,
1865 shadowOffset(arch), R_EBP );
1866 break;
1867 case 2:
1868 vg_assert(lit == 0xFFFF0000);
1869 emit_movv_lit_offregmem ( 2, 0x0000,
1870 shadowOffset(arch), R_EBP );
1871 break;
1872 case 1:
1873 vg_assert(lit == 0xFFFFFF00);
1874 if (arch < 4) {
1875 emit_movb_lit_offregmem ( 0x00,
1876 shadowOffset(arch), R_EBP );
1877 } else {
1878 emit_movb_lit_offregmem ( 0x00,
1879 shadowOffset(arch-4)+1, R_EBP );
1880 }
1881 break;
1882 default:
1883 VG_(panic)("synth_PUTV(lit)");
1884 }
1885
1886 } else {
1887
1888 UInt reg;
1889 vg_assert(srcTag == RealReg);
1890
1891 if (sz == 1 && lit_or_reg >= 4) {
1892 emit_swapl_reg_EAX ( lit_or_reg );
1893 reg = R_EAX;
1894 } else {
1895 reg = lit_or_reg;
1896 }
1897
1898 if (sz == 1) vg_assert(reg < 4);
1899
1900 switch (sz) {
1901 case 4:
1902 emit_movv_reg_offregmem ( 4, reg,
1903 shadowOffset(arch), R_EBP );
1904 break;
1905 case 2:
1906 emit_movv_reg_offregmem ( 2, reg,
1907 shadowOffset(arch), R_EBP );
1908 break;
1909 case 1:
1910 if (arch < 4) {
1911 emit_movb_reg_offregmem ( reg,
1912 shadowOffset(arch), R_EBP );
1913 } else {
1914 emit_movb_reg_offregmem ( reg,
1915 shadowOffset(arch-4)+1, R_EBP );
1916 }
1917 break;
1918 default:
1919 VG_(panic)("synth_PUTV(reg)");
1920 }
1921
1922 if (sz == 1 && lit_or_reg >= 4) {
1923 emit_swapl_reg_EAX ( lit_or_reg );
1924 }
1925 }
1926}
1927
1928
1929static void synth_GETVF ( Int reg )
1930{
1931 emit_movv_offregmem_reg ( 4, shadowFlagsOffset(), R_EBP, reg );
1932 /* paranoia only; should be unnecessary ... */
1933 /* emit_nonshiftopv_lit_reg ( 4, OR, 0xFFFFFFFE, reg ); */
1934}
1935
1936
1937static void synth_PUTVF ( UInt reg )
1938{
1939 emit_movv_reg_offregmem ( 4, reg, shadowFlagsOffset(), R_EBP );
1940}
1941
1942
1943static void synth_handle_esp_assignment ( Int reg )
1944{
1945 emit_pushal();
1946 emit_pushv_reg ( 4, reg );
1947 synth_call_baseBlock_method ( False, VGOFF_(handle_esp_assignment) );
1948 emit_add_lit_to_esp ( 4 );
1949 emit_popal();
1950}
1951
1952
1953static void synth_fpu_mem_check_actions ( Bool isWrite,
1954 Int size, Int a_reg )
1955{
1956 Int helper_offw
1957 = isWrite ? VGOFF_(fpu_write_check)
1958 : VGOFF_(fpu_read_check);
1959 emit_pushal();
1960 emit_pushl_lit8 ( size );
1961 emit_pushv_reg ( 4, a_reg );
1962 synth_call_baseBlock_method ( False, helper_offw );
1963 emit_add_lit_to_esp ( 8 );
1964 emit_popal();
1965}
1966
1967
1968#if 0
1969/* FixMe. Useful for debugging. */
1970void VG_(oink) ( Int n )
1971{
1972 VG_(printf)("OiNk(%d): ", n );
1973 VG_(show_reg_tags)( &VG_(m_shadow) );
1974}
1975
1976static void synth_OINK ( Int n )
1977{
1978 emit_pushal();
1979 emit_movv_lit_reg ( 4, n, R_EBP );
1980 emit_pushl_reg ( R_EBP );
1981 emit_movv_lit_reg ( 4, (Addr)&VG_(oink), R_EBP );
1982 emit_call_reg ( R_EBP );
1983 emit_add_lit_to_esp ( 4 );
1984 emit_popal();
1985}
1986#endif
1987
1988static void synth_TAG1_op ( VgTagOp op, Int reg )
1989{
1990 switch (op) {
1991
1992 /* Scheme is
1993 neg<sz> %reg -- CF = %reg==0 ? 0 : 1
1994 sbbl %reg, %reg -- %reg = -CF
1995 or 0xFFFFFFFE, %reg -- invalidate all bits except lowest
1996 */
1997 case VgT_PCast40:
1998 emit_unaryopv_reg(4, NEG, reg);
1999 emit_nonshiftopv_reg_reg(4, SBB, reg, reg);
2000 emit_nonshiftopv_lit_reg(4, OR, 0xFFFFFFFE, reg);
2001 break;
2002 case VgT_PCast20:
2003 emit_unaryopv_reg(2, NEG, reg);
2004 emit_nonshiftopv_reg_reg(4, SBB, reg, reg);
2005 emit_nonshiftopv_lit_reg(4, OR, 0xFFFFFFFE, reg);
2006 break;
2007 case VgT_PCast10:
2008 if (reg >= 4) {
2009 emit_swapl_reg_EAX(reg);
2010 emit_unaryopb_reg(NEG, R_EAX);
2011 emit_swapl_reg_EAX(reg);
2012 } else {
2013 emit_unaryopb_reg(NEG, reg);
2014 }
2015 emit_nonshiftopv_reg_reg(4, SBB, reg, reg);
2016 emit_nonshiftopv_lit_reg(4, OR, 0xFFFFFFFE, reg);
2017 break;
2018
2019 /* Scheme is
2020 andl $1, %reg -- %reg is 0 or 1
2021 negl %reg -- %reg is 0 or 0xFFFFFFFF
2022 and possibly an OR to invalidate unused bits.
2023 */
2024 case VgT_PCast04:
2025 emit_nonshiftopv_lit_reg(4, AND, 0x00000001, reg);
2026 emit_unaryopv_reg(4, NEG, reg);
2027 break;
2028 case VgT_PCast02:
2029 emit_nonshiftopv_lit_reg(4, AND, 0x00000001, reg);
2030 emit_unaryopv_reg(4, NEG, reg);
2031 emit_nonshiftopv_lit_reg(4, OR, 0xFFFF0000, reg);
2032 break;
2033 case VgT_PCast01:
2034 emit_nonshiftopv_lit_reg(4, AND, 0x00000001, reg);
2035 emit_unaryopv_reg(4, NEG, reg);
2036 emit_nonshiftopv_lit_reg(4, OR, 0xFFFFFF00, reg);
2037 break;
2038
2039 /* Scheme is
2040 shl $24, %reg -- make irrelevant bits disappear
2041 negl %reg -- CF = %reg==0 ? 0 : 1
2042 sbbl %reg, %reg -- %reg = -CF
2043 and possibly an OR to invalidate unused bits.
2044 */
2045 case VgT_PCast14:
2046 emit_shiftopv_lit_reg(4, SHL, 24, reg);
2047 emit_unaryopv_reg(4, NEG, reg);
2048 emit_nonshiftopv_reg_reg(4, SBB, reg, reg);
2049 break;
2050 case VgT_PCast12:
2051 emit_shiftopv_lit_reg(4, SHL, 24, reg);
2052 emit_unaryopv_reg(4, NEG, reg);
2053 emit_nonshiftopv_reg_reg(4, SBB, reg, reg);
2054 emit_nonshiftopv_lit_reg(4, OR, 0xFFFF0000, reg);
2055 break;
2056 case VgT_PCast11:
2057 emit_shiftopv_lit_reg(4, SHL, 24, reg);
2058 emit_unaryopv_reg(4, NEG, reg);
2059 emit_nonshiftopv_reg_reg(4, SBB, reg, reg);
2060 emit_nonshiftopv_lit_reg(4, OR, 0xFFFFFF00, reg);
2061 break;
2062
2063 /* We steal %ebp (a non-allocable reg) as a temporary:
2064 pushl %ebp
2065 movl %reg, %ebp
2066 negl %ebp
2067 orl %ebp, %reg
2068 popl %ebp
2069 This sequence turns out to be correct regardless of the
2070 operation width.
2071 */
2072 case VgT_Left4:
2073 case VgT_Left2:
2074 case VgT_Left1:
2075 vg_assert(reg != R_EDI);
2076 emit_movv_reg_reg(4, reg, R_EDI);
2077 emit_unaryopv_reg(4, NEG, R_EDI);
2078 emit_nonshiftopv_reg_reg(4, OR, R_EDI, reg);
2079 break;
2080
2081 /* These are all fairly obvious; do the op and then, if
2082 necessary, invalidate unused bits. */
2083 case VgT_SWiden14:
2084 emit_shiftopv_lit_reg(4, SHL, 24, reg);
2085 emit_shiftopv_lit_reg(4, SAR, 24, reg);
2086 break;
2087 case VgT_SWiden24:
2088 emit_shiftopv_lit_reg(4, SHL, 16, reg);
2089 emit_shiftopv_lit_reg(4, SAR, 16, reg);
2090 break;
2091 case VgT_SWiden12:
2092 emit_shiftopv_lit_reg(4, SHL, 24, reg);
2093 emit_shiftopv_lit_reg(4, SAR, 24, reg);
2094 emit_nonshiftopv_lit_reg(4, OR, 0xFFFF0000, reg);
2095 break;
2096 case VgT_ZWiden14:
2097 emit_nonshiftopv_lit_reg(4, AND, 0x000000FF, reg);
2098 break;
2099 case VgT_ZWiden24:
2100 emit_nonshiftopv_lit_reg(4, AND, 0x0000FFFF, reg);
2101 break;
2102 case VgT_ZWiden12:
2103 emit_nonshiftopv_lit_reg(4, AND, 0x000000FF, reg);
2104 emit_nonshiftopv_lit_reg(4, OR, 0xFFFF0000, reg);
2105 break;
2106
2107 default:
2108 VG_(panic)("synth_TAG1_op");
2109 }
2110}
2111
2112
2113static void synth_TAG2_op ( VgTagOp op, Int regs, Int regd )
2114{
2115 switch (op) {
2116
2117 /* UifU is implemented by OR, since 1 means Undefined. */
2118 case VgT_UifU4:
2119 case VgT_UifU2:
2120 case VgT_UifU1:
2121 case VgT_UifU0:
2122 emit_nonshiftopv_reg_reg(4, OR, regs, regd);
2123 break;
2124
2125 /* DifD is implemented by AND, since 0 means Defined. */
2126 case VgT_DifD4:
2127 case VgT_DifD2:
2128 case VgT_DifD1:
2129 emit_nonshiftopv_reg_reg(4, AND, regs, regd);
2130 break;
2131
2132 /* ImproveAND(value, tags) = value OR tags.
2133 Defined (0) value 0s give defined (0); all other -> undefined (1).
2134 value is in regs; tags is in regd.
2135 Be paranoid and invalidate unused bits; I don't know whether
2136 or not this is actually necessary. */
2137 case VgT_ImproveAND4_TQ:
2138 emit_nonshiftopv_reg_reg(4, OR, regs, regd);
2139 break;
2140 case VgT_ImproveAND2_TQ:
2141 emit_nonshiftopv_reg_reg(4, OR, regs, regd);
2142 emit_nonshiftopv_lit_reg(4, OR, 0xFFFF0000, regd);
2143 break;
2144 case VgT_ImproveAND1_TQ:
2145 emit_nonshiftopv_reg_reg(4, OR, regs, regd);
2146 emit_nonshiftopv_lit_reg(4, OR, 0xFFFFFF00, regd);
2147 break;
2148
2149 /* ImproveOR(value, tags) = (not value) OR tags.
2150 Defined (0) value 1s give defined (0); all other -> undefined (1).
2151 value is in regs; tags is in regd.
2152 To avoid trashing value, this is implemented (re de Morgan) as
2153 not (value AND (not tags))
2154 Be paranoid and invalidate unused bits; I don't know whether
2155 or not this is actually necessary. */
2156 case VgT_ImproveOR4_TQ:
2157 emit_unaryopv_reg(4, NOT, regd);
2158 emit_nonshiftopv_reg_reg(4, AND, regs, regd);
2159 emit_unaryopv_reg(4, NOT, regd);
2160 break;
2161 case VgT_ImproveOR2_TQ:
2162 emit_unaryopv_reg(4, NOT, regd);
2163 emit_nonshiftopv_reg_reg(4, AND, regs, regd);
2164 emit_unaryopv_reg(4, NOT, regd);
2165 emit_nonshiftopv_lit_reg(4, OR, 0xFFFF0000, regd);
2166 break;
2167 case VgT_ImproveOR1_TQ:
2168 emit_unaryopv_reg(4, NOT, regd);
2169 emit_nonshiftopv_reg_reg(4, AND, regs, regd);
2170 emit_unaryopv_reg(4, NOT, regd);
2171 emit_nonshiftopv_lit_reg(4, OR, 0xFFFFFF00, regd);
2172 break;
2173
2174 default:
2175 VG_(panic)("synth_TAG2_op");
2176 }
2177}
2178
2179/*----------------------------------------------------*/
2180/*--- Generate code for a single UInstr. ---*/
2181/*----------------------------------------------------*/
2182
2183static void emitUInstr ( Int i, UInstr* u )
2184{
2185 if (dis)
2186 VG_(ppUInstr)(i, u);
2187
2188# if 0
2189 if (0&& VG_(translations_done) >= 600) {
2190 Bool old_dis = dis;
2191 dis = False;
2192 synth_OINK(i);
2193 dis = old_dis;
2194 }
2195# endif
2196
2197 switch (u->opcode) {
2198
2199 case NOP: case CALLM_S: case CALLM_E: break;
2200
2201 case INCEIP: {
2202 vg_assert(u->tag1 == Lit16);
2203 emit_addlit8_offregmem ( u->val1, R_EBP, 4 * VGOFF_(m_eip) );
2204 break;
2205 }
2206
2207 case LEA1: {
2208 vg_assert(u->tag1 == RealReg);
2209 vg_assert(u->tag2 == RealReg);
2210 emit_lea_litreg_reg ( u->lit32, u->val1, u->val2 );
2211 break;
2212 }
2213
2214 case LEA2: {
2215 vg_assert(u->tag1 == RealReg);
2216 vg_assert(u->tag2 == RealReg);
2217 vg_assert(u->tag3 == RealReg);
2218 emit_lea_sib_reg ( u->lit32, u->extra4b,
2219 u->val1, u->val2, u->val3 );
2220 break;
2221 }
2222
2223 case WIDEN: {
2224 vg_assert(u->tag1 == RealReg);
2225 if (u->signed_widen) {
2226 synth_WIDEN_signed ( u->extra4b, u->size, u->val1 );
2227 } else {
2228 /* no need to generate any code. */
2229 }
2230 break;
2231 }
2232
2233 case SETV: {
2234 vg_assert(VG_(clo_instrument));
2235 vg_assert(u->tag1 == RealReg);
2236 synth_SETV ( u->size, u->val1 );
2237 break;
2238 }
2239
2240 case STOREV: {
2241 vg_assert(VG_(clo_instrument));
2242 vg_assert(u->tag1 == RealReg || u->tag1 == Literal);
2243 vg_assert(u->tag2 == RealReg);
2244 synth_STOREV ( u->size, u->tag1,
2245 u->tag1==Literal ? u->lit32 : u->val1,
2246 u->val2 );
2247 break;
2248 }
2249
2250 case STORE: {
2251 vg_assert(u->tag1 == RealReg);
2252 vg_assert(u->tag2 == RealReg);
2253 synth_mov_reg_memreg ( u->size, u->val1, u->val2 );
sewardj18d75132002-05-16 11:06:21 +00002254 /* No longer possible, but retained for illustrative purposes.
sewardjde4a1d02002-03-22 01:27:54 +00002255 if (u->smc_check)
2256 synth_orig_code_write_check ( u->size, u->val2 );
sewardj18d75132002-05-16 11:06:21 +00002257 */
sewardjde4a1d02002-03-22 01:27:54 +00002258 break;
2259 }
2260
2261 case LOADV: {
2262 vg_assert(VG_(clo_instrument));
2263 vg_assert(u->tag1 == RealReg);
2264 vg_assert(u->tag2 == RealReg);
2265 if (0 && VG_(clo_instrument))
2266 emit_AMD_prefetch_reg ( u->val1 );
2267 synth_LOADV ( u->size, u->val1, u->val2 );
2268 break;
2269 }
2270
2271 case LOAD: {
2272 vg_assert(u->tag1 == RealReg);
2273 vg_assert(u->tag2 == RealReg);
2274 synth_mov_regmem_reg ( u->size, u->val1, u->val2 );
2275 break;
2276 }
2277
2278 case TESTV: {
2279 vg_assert(VG_(clo_instrument));
2280 vg_assert(u->tag1 == RealReg || u->tag1 == ArchReg);
2281 synth_TESTV(u->size, u->tag1, u->val1);
2282 break;
2283 }
2284
2285 case GETV: {
2286 vg_assert(VG_(clo_instrument));
2287 vg_assert(u->tag1 == ArchReg);
2288 vg_assert(u->tag2 == RealReg);
2289 synth_GETV(u->size, u->val1, u->val2);
2290 break;
2291 }
2292
2293 case GETVF: {
2294 vg_assert(VG_(clo_instrument));
2295 vg_assert(u->tag1 == RealReg);
2296 vg_assert(u->size == 0);
2297 synth_GETVF(u->val1);
2298 break;
2299 }
2300
2301 case PUTV: {
2302 vg_assert(VG_(clo_instrument));
2303 vg_assert(u->tag1 == RealReg || u->tag1 == Literal);
2304 vg_assert(u->tag2 == ArchReg);
2305 synth_PUTV(u->size, u->tag1,
2306 u->tag1==Literal ? u->lit32 : u->val1,
2307 u->val2 );
2308 break;
2309 }
2310
2311 case PUTVF: {
2312 vg_assert(VG_(clo_instrument));
2313 vg_assert(u->tag1 == RealReg);
2314 vg_assert(u->size == 0);
2315 synth_PUTVF(u->val1);
2316 break;
2317 }
2318
2319 case GET: {
2320 vg_assert(u->tag1 == ArchReg || u->tag1 == SpillNo);
2321 vg_assert(u->tag2 == RealReg);
2322 synth_mov_offregmem_reg (
2323 u->size,
2324 spillOrArchOffset( u->size, u->tag1, u->val1 ),
2325 R_EBP,
2326 u->val2
2327 );
2328 break;
2329 }
2330
2331 case PUT: {
2332 vg_assert(u->tag2 == ArchReg || u->tag2 == SpillNo);
2333 vg_assert(u->tag1 == RealReg);
2334 if (u->tag2 == ArchReg
2335 && u->val2 == R_ESP
2336 && u->size == 4
2337 && VG_(clo_instrument)) {
2338 synth_handle_esp_assignment ( u->val1 );
2339 }
2340 synth_mov_reg_offregmem (
2341 u->size,
2342 u->val1,
2343 spillOrArchOffset( u->size, u->tag2, u->val2 ),
2344 R_EBP
2345 );
2346 break;
2347 }
2348
2349 case GETF: {
2350 vg_assert(u->size == 2 || u->size == 4);
2351 vg_assert(u->tag1 == RealReg);
2352 synth_mov_offregmem_reg (
2353 u->size,
2354 eflagsOffset(),
2355 R_EBP,
2356 u->val1
2357 );
2358 break;
2359 }
2360
2361 case PUTF: {
2362 vg_assert(u->size == 2 || u->size == 4);
2363 vg_assert(u->tag1 == RealReg);
2364 synth_mov_reg_offregmem (
2365 u->size,
2366 u->val1,
2367 eflagsOffset(),
2368 R_EBP
2369 );
2370 break;
2371 }
2372
2373 case MOV: {
2374 vg_assert(u->tag1 == RealReg || u->tag1 == Literal);
2375 vg_assert(u->tag2 == RealReg);
2376 switch (u->tag1) {
2377 case RealReg: vg_assert(u->size == 4);
2378 if (u->val1 != u->val2)
2379 synth_movl_reg_reg ( u->val1, u->val2 );
2380 break;
2381 case Literal: synth_mov_lit_reg ( u->size, u->lit32, u->val2 );
2382 break;
2383 default: VG_(panic)("emitUInstr:mov");
2384 }
2385 break;
2386 }
2387
2388 case SBB:
2389 case ADC:
2390 case XOR:
2391 case OR:
2392 case AND:
2393 case SUB:
2394 case ADD: {
2395 vg_assert(u->tag2 == RealReg);
2396 switch (u->tag1) {
2397 case Literal: synth_nonshiftop_lit_reg (
2398 VG_(anyFlagUse)(u),
2399 u->opcode, u->size, u->lit32, u->val2 );
2400 break;
2401 case RealReg: synth_nonshiftop_reg_reg (
2402 VG_(anyFlagUse)(u),
2403 u->opcode, u->size, u->val1, u->val2 );
2404 break;
2405 case ArchReg: synth_nonshiftop_offregmem_reg (
2406 VG_(anyFlagUse)(u),
2407 u->opcode, u->size,
2408 spillOrArchOffset( u->size, u->tag1, u->val1 ),
2409 R_EBP,
2410 u->val2 );
2411 break;
2412 default: VG_(panic)("emitUInstr:non-shift-op");
2413 }
2414 break;
2415 }
2416
2417 case RCR:
2418 case RCL:
2419 case ROR:
2420 case ROL:
2421 case SAR:
2422 case SHR:
2423 case SHL: {
2424 vg_assert(u->tag2 == RealReg);
2425 switch (u->tag1) {
2426 case Literal: synth_shiftop_lit_reg (
2427 VG_(anyFlagUse)(u),
2428 u->opcode, u->size, u->lit32, u->val2 );
2429 break;
2430 case RealReg: synth_shiftop_reg_reg (
2431 VG_(anyFlagUse)(u),
2432 u->opcode, u->size, u->val1, u->val2 );
2433 break;
2434 default: VG_(panic)("emitUInstr:non-shift-op");
2435 }
2436 break;
2437 }
2438
2439 case INC:
2440 case DEC:
2441 case NEG:
2442 case NOT:
2443 vg_assert(u->tag1 == RealReg);
2444 synth_unaryop_reg (
2445 VG_(anyFlagUse)(u), u->opcode, u->size, u->val1 );
2446 break;
2447
2448 case BSWAP:
2449 vg_assert(u->tag1 == RealReg);
2450 vg_assert(u->size == 4);
2451 vg_assert(!VG_(anyFlagUse)(u));
2452 emit_bswapl_reg ( u->val1 );
2453 break;
2454
2455 case CMOV:
2456 vg_assert(u->tag1 == RealReg);
2457 vg_assert(u->tag2 == RealReg);
2458 vg_assert(u->cond != CondAlways);
2459 vg_assert(u->size == 4);
2460 synth_cmovl_reg_reg ( u->cond, u->val1, u->val2 );
2461 break;
2462
2463 case JMP: {
2464 vg_assert(u->tag2 == NoValue);
2465 vg_assert(u->tag1 == RealReg || u->tag1 == Literal);
2466 if (u->cond == CondAlways) {
sewardj2e93c502002-04-12 11:12:52 +00002467 switch (u->tag1) {
2468 case RealReg:
2469 synth_jmp_reg ( u->val1, u->jmpkind );
2470 break;
2471 case Literal:
2472 synth_jmp_lit ( u->lit32, u->jmpkind );
2473 break;
2474 default:
2475 VG_(panic)("emitUInstr(JMP, unconditional, default)");
2476 break;
sewardjde4a1d02002-03-22 01:27:54 +00002477 }
2478 } else {
sewardj2e93c502002-04-12 11:12:52 +00002479 switch (u->tag1) {
2480 case RealReg:
2481 VG_(panic)("emitUInstr(JMP, conditional, RealReg)");
2482 break;
2483 case Literal:
2484 vg_assert(u->jmpkind == JmpBoring);
2485 synth_jcond_lit ( u->cond, u->lit32 );
2486 break;
2487 default:
2488 VG_(panic)("emitUInstr(JMP, conditional, default)");
2489 break;
sewardjde4a1d02002-03-22 01:27:54 +00002490 }
2491 }
2492 break;
2493 }
2494
2495 case JIFZ:
2496 vg_assert(u->tag1 == RealReg);
2497 vg_assert(u->tag2 == Literal);
2498 vg_assert(u->size == 4);
2499 synth_jmp_ifzero_reg_lit ( u->val1, u->lit32 );
2500 break;
2501
2502 case TAG1:
2503 synth_TAG1_op ( u->val3, u->val1 );
2504 break;
2505
2506 case TAG2:
2507 if (u->val3 != VgT_DebugFn) {
2508 synth_TAG2_op ( u->val3, u->val1, u->val2 );
2509 } else {
2510 /* Assume a call to VgT_DebugFn passing both args
2511 and placing the result back in the second. */
2512 Int j, k;
2513 /* u->val2 is the reg into which the result is written. So
2514 don't save/restore it. And it can be used at a temp for
2515 the call target, too. Since %eax is used for the return
2516 value from the C procedure, it is preserved only by
2517 virtue of not being mentioned as a VG_CALLEE_SAVED reg. */
2518 for (k = 0; k < VG_MAX_REALREGS; k++) {
2519 j = VG_(rankToRealRegNo) ( k );
2520 if (VG_CALLEE_SAVED(j)) continue;
2521 if (j == u->val2) continue;
2522 emit_pushv_reg ( 4, j );
2523 }
2524 emit_pushv_reg(4, u->val2);
2525 emit_pushv_reg(4, u->val1);
2526 emit_movv_lit_reg ( 4, (UInt)(&VG_(DebugFn)), u->val2 );
2527 emit_call_reg ( u->val2 );
2528 if (u->val2 != R_EAX)
2529 emit_movv_reg_reg ( 4, R_EAX, u->val2 );
2530 /* nuke args */
2531 emit_add_lit_to_esp(8);
2532 for (k = VG_MAX_REALREGS-1; k >= 0; k--) {
2533 j = VG_(rankToRealRegNo) ( k );
2534 if (VG_CALLEE_SAVED(j)) continue;
2535 if (j == u->val2) continue;
2536 emit_popv_reg ( 4, j );
2537 }
2538 }
2539 break;
2540
2541 case PUSH:
2542 vg_assert(u->tag1 == RealReg);
2543 vg_assert(u->tag2 == NoValue);
2544 emit_pushv_reg ( 4, u->val1 );
2545 break;
2546
2547 case POP:
2548 vg_assert(u->tag1 == RealReg);
2549 vg_assert(u->tag2 == NoValue);
2550 emit_popv_reg ( 4, u->val1 );
2551 break;
2552
2553 case CALLM:
2554 vg_assert(u->tag1 == Lit16);
2555 vg_assert(u->tag2 == NoValue);
2556 vg_assert(u->size == 0);
2557 if (u->flags_r != FlagsEmpty || u->flags_w != FlagsEmpty)
2558 emit_get_eflags();
2559 synth_call_baseBlock_method ( False, u->val1 );
2560 if (u->flags_w != FlagsEmpty)
2561 emit_put_eflags();
2562 break;
2563
njn6431be72002-07-28 09:53:34 +00002564 case CCALL_1_0:
2565 vg_assert(u->tag1 == RealReg);
2566 vg_assert(u->tag2 == NoValue);
2567 vg_assert(u->size == 0);
2568
2569 synth_ccall_saveRegs();
2570 synth_ccall_pushOneArg ( u->val1 );
2571 synth_ccall_call_clearStack_restoreRegs ( u->lit32, 4 );
2572 break;
2573
2574 case CCALL_2_0:
2575 vg_assert(u->tag1 == RealReg);
2576 vg_assert(u->tag2 == RealReg);
2577 vg_assert(u->size == 0);
2578
2579 synth_ccall_saveRegs();
2580 synth_ccall_pushTwoArgs ( u->val1, u->val2 );
2581 synth_ccall_call_clearStack_restoreRegs ( u->lit32, 8 );
2582 break;
2583
sewardjde4a1d02002-03-22 01:27:54 +00002584 case CLEAR:
2585 vg_assert(u->tag1 == Lit16);
2586 vg_assert(u->tag2 == NoValue);
2587 emit_add_lit_to_esp ( u->val1 );
2588 break;
2589
2590 case CC2VAL:
2591 vg_assert(u->tag1 == RealReg);
2592 vg_assert(u->tag2 == NoValue);
2593 vg_assert(VG_(anyFlagUse)(u));
2594 synth_setb_reg ( u->val1, u->cond );
2595 break;
2596
2597 /* We assume that writes to memory done by FPU_Ws are not going
2598 to be used to create new code, so there's no orig-code-write
2599 checks done by default. */
2600 case FPU_R:
2601 case FPU_W:
2602 vg_assert(u->tag1 == Lit16);
2603 vg_assert(u->tag2 == RealReg);
2604 if (VG_(clo_instrument))
2605 synth_fpu_mem_check_actions (
2606 u->opcode==FPU_W, u->size, u->val2 );
2607 synth_fpu_regmem ( (u->val1 >> 8) & 0xFF,
2608 u->val1 & 0xFF,
2609 u->val2 );
sewardj18d75132002-05-16 11:06:21 +00002610 /* No longer possible, but retained for illustrative purposes.
sewardjde4a1d02002-03-22 01:27:54 +00002611 if (u->opcode == FPU_W && u->smc_check)
2612 synth_orig_code_write_check ( u->size, u->val2 );
sewardj18d75132002-05-16 11:06:21 +00002613 */
sewardjde4a1d02002-03-22 01:27:54 +00002614 break;
2615
2616 case FPU:
2617 vg_assert(u->tag1 == Lit16);
2618 vg_assert(u->tag2 == NoValue);
sewardj8d32be72002-04-18 02:18:24 +00002619 if (u->flags_r != FlagsEmpty || u->flags_w != FlagsEmpty)
sewardj4a7456e2002-03-24 13:52:19 +00002620 emit_get_eflags();
sewardjde4a1d02002-03-22 01:27:54 +00002621 synth_fpu_no_mem ( (u->val1 >> 8) & 0xFF,
2622 u->val1 & 0xFF );
sewardj4a7456e2002-03-24 13:52:19 +00002623 if (u->flags_w != FlagsEmpty)
2624 emit_put_eflags();
sewardjde4a1d02002-03-22 01:27:54 +00002625 break;
2626
2627 default:
2628 VG_(printf)("emitUInstr: unhandled insn:\n");
2629 VG_(ppUInstr)(0,u);
2630 VG_(panic)("emitUInstr: unimplemented opcode");
2631 }
2632
2633}
2634
2635
2636/* Emit x86 for the ucode in cb, returning the address of the
2637 generated code and setting *nbytes to its size. */
2638UChar* VG_(emit_code) ( UCodeBlock* cb, Int* nbytes )
2639{
2640 Int i;
2641 emitted_code_used = 0;
2642 emitted_code_size = 500; /* reasonable initial size */
2643 emitted_code = VG_(jitmalloc)(emitted_code_size);
2644
2645 if (dis) VG_(printf)("Generated code:\n");
2646
2647 for (i = 0; i < cb->used; i++) {
2648 if (cb->instrs[i].opcode != NOP) {
2649 UInstr* u = &cb->instrs[i];
2650# if 1
2651 /* Check on the sanity of this insn. */
2652 Bool sane = VG_(saneUInstr)( False, u );
2653 if (!sane) {
2654 VG_(printf)("\ninsane instruction\n");
2655 VG_(ppUInstr)( i, u );
2656 }
2657 vg_assert(sane);
2658# endif
2659# if 0
2660 /* Pass args to TAG1/TAG2 to vg_DebugFn for sanity checking.
2661 Requires a suitable definition of vg_DebugFn. */
2662 if (u->opcode == TAG1) {
2663 UInstr t1;
2664 vg_assert(u->tag1 == RealReg);
2665 VG_(emptyUInstr)( &t1 );
2666 t1.opcode = TAG2;
2667 t1.tag1 = t1.tag2 = RealReg;
2668 t1.val1 = t1.val2 = u->val1;
2669 t1.tag3 = Lit16;
2670 t1.val3 = VgT_DebugFn;
2671 emitUInstr( i, &t1 );
2672 }
2673 if (u->opcode == TAG2) {
2674 UInstr t1;
2675 vg_assert(u->tag1 == RealReg);
2676 vg_assert(u->tag2 == RealReg);
2677 VG_(emptyUInstr)( &t1 );
2678 t1.opcode = TAG2;
2679 t1.tag1 = t1.tag2 = RealReg;
2680 t1.val1 = t1.val2 = u->val1;
2681 t1.tag3 = Lit16;
2682 t1.val3 = VgT_DebugFn;
2683 if (u->val3 == VgT_UifU1 || u->val3 == VgT_UifU2
2684 || u->val3 == VgT_UifU4 || u->val3 == VgT_DifD1
2685 || u->val3 == VgT_DifD2 || u->val3 == VgT_DifD4)
2686 emitUInstr( i, &t1 );
2687 t1.val1 = t1.val2 = u->val2;
2688 emitUInstr( i, &t1 );
2689 }
2690# endif
2691 emitUInstr( i, u );
2692 }
2693 }
2694
2695 /* Returns a pointer to the emitted code. This will have to be
2696 copied by the caller into the translation cache, and then freed
2697 using VG_(jitfree). */
2698 *nbytes = emitted_code_used;
2699 return emitted_code;
2700}
2701
2702/*--------------------------------------------------------------------*/
2703/*--- end vg_from_ucode.c ---*/
2704/*--------------------------------------------------------------------*/