blob: 214d2ca1006c1bad097fbc623f4a6cdf873cfa08 [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
1070
sewardj2e93c502002-04-12 11:12:52 +00001071static void load_ebp_from_JmpKind ( JmpKind jmpkind )
sewardjde4a1d02002-03-22 01:27:54 +00001072{
sewardj2e93c502002-04-12 11:12:52 +00001073 switch (jmpkind) {
1074 case JmpBoring:
1075 break;
1076 case JmpCall:
1077 case JmpRet:
sewardj54cacf02002-04-12 23:24:59 +00001078 emit_movv_lit_reg ( 4, VG_TRC_EBP_JMP_STKADJ, R_EBP );
sewardj2e93c502002-04-12 11:12:52 +00001079 break;
1080 case JmpSyscall:
1081 emit_movv_lit_reg ( 4, VG_TRC_EBP_JMP_SYSCALL, R_EBP );
1082 break;
1083 case JmpClientReq:
1084 emit_movv_lit_reg ( 4, VG_TRC_EBP_JMP_CLIENTREQ, R_EBP );
1085 break;
1086 default:
1087 VG_(panic)("load_ebp_from_JmpKind");
1088 }
1089}
1090
1091/* Jump to the next translation, by loading its original addr into
1092 %eax and returning to the scheduler. Signal special requirements
1093 by loading a special value into %ebp first.
1094*/
1095static void synth_jmp_reg ( Int reg, JmpKind jmpkind )
1096{
1097 load_ebp_from_JmpKind ( jmpkind );
sewardjde4a1d02002-03-22 01:27:54 +00001098 if (reg != R_EAX)
1099 emit_movv_reg_reg ( 4, reg, R_EAX );
sewardjde4a1d02002-03-22 01:27:54 +00001100 emit_ret();
1101}
1102
1103
1104/* Same deal as synth_jmp_reg. */
sewardj2e93c502002-04-12 11:12:52 +00001105static void synth_jmp_lit ( Addr addr, JmpKind jmpkind )
sewardjde4a1d02002-03-22 01:27:54 +00001106{
sewardj2e93c502002-04-12 11:12:52 +00001107 load_ebp_from_JmpKind ( jmpkind );
sewardjde4a1d02002-03-22 01:27:54 +00001108 emit_movv_lit_reg ( 4, addr, R_EAX );
1109 emit_ret();
1110}
1111
1112
sewardjde4a1d02002-03-22 01:27:54 +00001113static void synth_jcond_lit ( Condcode cond, Addr addr )
1114{
1115 /* Do the following:
1116 get eflags
1117 jmp short if not cond to xyxyxy
1118 addr -> eax
1119 ret
1120 xyxyxy
1121
1122 2 0000 750C jnz xyxyxy
1123 3 0002 B877665544 movl $0x44556677, %eax
1124 4 0007 C3 ret
1125 5 0008 FFE3 jmp *%ebx
1126 6 xyxyxy:
1127 */
1128 emit_get_eflags();
1129 emit_jcondshort_delta ( invertCondition(cond), 5+1 );
sewardj2e93c502002-04-12 11:12:52 +00001130 synth_jmp_lit ( addr, JmpBoring );
sewardjde4a1d02002-03-22 01:27:54 +00001131}
1132
1133
1134static void synth_jmp_ifzero_reg_lit ( Int reg, Addr addr )
1135{
1136 /* 0000 83FF00 cmpl $0, %edi
1137 0003 750A jnz next
1138 0005 B844332211 movl $0x11223344, %eax
1139 000a C3 ret
1140 next:
1141 */
1142 emit_cmpl_zero_reg ( reg );
1143 emit_jcondshort_delta ( CondNZ, 5+1 );
sewardj2e93c502002-04-12 11:12:52 +00001144 synth_jmp_lit ( addr, JmpBoring );
sewardjde4a1d02002-03-22 01:27:54 +00001145}
1146
1147
1148static void synth_mov_lit_reg ( Int size, UInt lit, Int reg )
1149{
1150 /* Load the zero-extended literal into reg, at size l,
1151 regardless of the request size. */
1152 emit_movv_lit_reg ( 4, lit, reg );
1153}
1154
1155
1156static void synth_mov_regmem_reg ( Int size, Int reg1, Int reg2 )
1157{
1158 switch (size) {
1159 case 4: emit_movv_regmem_reg ( 4, reg1, reg2 ); break;
1160 case 2: emit_movzwl_regmem_reg ( reg1, reg2 ); break;
1161 case 1: emit_movzbl_regmem_reg ( reg1, reg2 ); break;
1162 default: VG_(panic)("synth_mov_regmem_reg");
1163 }
1164}
1165
1166
1167static void synth_mov_offregmem_reg ( Int size, Int off, Int areg, Int reg )
1168{
1169 switch (size) {
1170 case 4: emit_movv_offregmem_reg ( 4, off, areg, reg ); break;
1171 case 2: emit_movzwl_offregmem_reg ( off, areg, reg ); break;
1172 case 1: emit_movzbl_offregmem_reg ( off, areg, reg ); break;
1173 default: VG_(panic)("synth_mov_offregmem_reg");
1174 }
1175}
1176
1177
1178static void synth_mov_reg_offregmem ( Int size, Int reg,
1179 Int off, Int areg )
1180{
1181 switch (size) {
1182 case 4: emit_movv_reg_offregmem ( 4, reg, off, areg ); break;
1183 case 2: emit_movv_reg_offregmem ( 2, reg, off, areg ); break;
1184 case 1: if (reg < 4) {
1185 emit_movb_reg_offregmem ( reg, off, areg );
1186 }
1187 else {
1188 emit_swapl_reg_EAX ( reg );
1189 emit_movb_reg_offregmem ( R_AL, off, areg );
1190 emit_swapl_reg_EAX ( reg );
1191 }
1192 break;
1193 default: VG_(panic)("synth_mov_reg_offregmem");
1194 }
1195}
1196
1197
1198static void synth_mov_reg_memreg ( Int size, Int reg1, Int reg2 )
1199{
1200 Int s1;
1201 switch (size) {
1202 case 4: emit_movv_reg_regmem ( 4, reg1, reg2 ); break;
1203 case 2: emit_movv_reg_regmem ( 2, reg1, reg2 ); break;
1204 case 1: if (reg1 < 4) {
1205 emit_movb_reg_regmem ( reg1, reg2 );
1206 }
1207 else {
1208 /* Choose a swap reg which is < 4 and not reg1 or reg2. */
1209 for (s1 = 0; s1 == reg1 || s1 == reg2; s1++) ;
1210 emit_swapl_reg_reg ( s1, reg1 );
1211 emit_movb_reg_regmem ( s1, reg2 );
1212 emit_swapl_reg_reg ( s1, reg1 );
1213 }
1214 break;
1215 default: VG_(panic)("synth_mov_reg_litmem");
1216 }
1217}
1218
1219
1220static void synth_unaryop_reg ( Bool upd_cc,
1221 Opcode opcode, Int size,
1222 Int reg )
1223{
1224 /* NB! opcode is a uinstr opcode, not an x86 one! */
1225 switch (size) {
1226 case 4: if (upd_cc) emit_get_eflags();
1227 emit_unaryopv_reg ( 4, opcode, reg );
1228 if (upd_cc) emit_put_eflags();
1229 break;
1230 case 2: if (upd_cc) emit_get_eflags();
1231 emit_unaryopv_reg ( 2, opcode, reg );
1232 if (upd_cc) emit_put_eflags();
1233 break;
1234 case 1: if (reg < 4) {
1235 if (upd_cc) emit_get_eflags();
1236 emit_unaryopb_reg ( opcode, reg );
1237 if (upd_cc) emit_put_eflags();
1238 } else {
1239 emit_swapl_reg_EAX ( reg );
1240 if (upd_cc) emit_get_eflags();
1241 emit_unaryopb_reg ( opcode, R_AL );
1242 if (upd_cc) emit_put_eflags();
1243 emit_swapl_reg_EAX ( reg );
1244 }
1245 break;
1246 default: VG_(panic)("synth_unaryop_reg");
1247 }
1248}
1249
1250
1251
1252static void synth_nonshiftop_reg_reg ( Bool upd_cc,
1253 Opcode opcode, Int size,
1254 Int reg1, Int reg2 )
1255{
1256 /* NB! opcode is a uinstr opcode, not an x86 one! */
1257 switch (size) {
1258 case 4: if (upd_cc) emit_get_eflags();
1259 emit_nonshiftopv_reg_reg ( 4, opcode, reg1, reg2 );
1260 if (upd_cc) emit_put_eflags();
1261 break;
1262 case 2: if (upd_cc) emit_get_eflags();
1263 emit_nonshiftopv_reg_reg ( 2, opcode, reg1, reg2 );
1264 if (upd_cc) emit_put_eflags();
1265 break;
1266 case 1: { /* Horrible ... */
1267 Int s1, s2;
1268 /* Choose s1 and s2 to be x86 regs which we can talk about the
1269 lowest 8 bits, ie either %eax, %ebx, %ecx or %edx. Make
1270 sure s1 != s2 and that neither of them equal either reg1 or
1271 reg2. Then use them as temporaries to make things work. */
1272 if (reg1 < 4 && reg2 < 4) {
1273 if (upd_cc) emit_get_eflags();
1274 emit_nonshiftopb_reg_reg(opcode, reg1, reg2);
1275 if (upd_cc) emit_put_eflags();
1276 break;
1277 }
1278 for (s1 = 0; s1 == reg1 || s1 == reg2; s1++) ;
1279 if (reg1 >= 4 && reg2 < 4) {
1280 emit_swapl_reg_reg ( reg1, s1 );
1281 if (upd_cc) emit_get_eflags();
1282 emit_nonshiftopb_reg_reg(opcode, s1, reg2);
1283 if (upd_cc) emit_put_eflags();
1284 emit_swapl_reg_reg ( reg1, s1 );
1285 break;
1286 }
1287 for (s2 = 0; s2 == reg1 || s2 == reg2 || s2 == s1; s2++) ;
1288 if (reg1 < 4 && reg2 >= 4) {
1289 emit_swapl_reg_reg ( reg2, s2 );
1290 if (upd_cc) emit_get_eflags();
1291 emit_nonshiftopb_reg_reg(opcode, reg1, s2);
1292 if (upd_cc) emit_put_eflags();
1293 emit_swapl_reg_reg ( reg2, s2 );
1294 break;
1295 }
1296 if (reg1 >= 4 && reg2 >= 4 && reg1 != reg2) {
1297 emit_swapl_reg_reg ( reg1, s1 );
1298 emit_swapl_reg_reg ( reg2, s2 );
1299 if (upd_cc) emit_get_eflags();
1300 emit_nonshiftopb_reg_reg(opcode, s1, s2);
1301 if (upd_cc) emit_put_eflags();
1302 emit_swapl_reg_reg ( reg1, s1 );
1303 emit_swapl_reg_reg ( reg2, s2 );
1304 break;
1305 }
1306 if (reg1 >= 4 && reg2 >= 4 && reg1 == reg2) {
1307 emit_swapl_reg_reg ( reg1, s1 );
1308 if (upd_cc) emit_get_eflags();
1309 emit_nonshiftopb_reg_reg(opcode, s1, s1);
1310 if (upd_cc) emit_put_eflags();
1311 emit_swapl_reg_reg ( reg1, s1 );
1312 break;
1313 }
1314 VG_(panic)("synth_nonshiftopb_reg_reg");
1315 }
1316 default: VG_(panic)("synth_nonshiftop_reg_reg");
1317 }
1318}
1319
1320
1321static void synth_nonshiftop_offregmem_reg (
1322 Bool upd_cc,
1323 Opcode opcode, Int size,
1324 Int off, Int areg, Int reg )
1325{
1326 switch (size) {
1327 case 4:
1328 if (upd_cc) emit_get_eflags();
1329 emit_nonshiftopv_offregmem_reg ( 4, opcode, off, areg, reg );
1330 if (upd_cc) emit_put_eflags();
1331 break;
1332 case 2:
1333 if (upd_cc) emit_get_eflags();
1334 emit_nonshiftopv_offregmem_reg ( 2, opcode, off, areg, reg );
1335 if (upd_cc) emit_put_eflags();
1336 break;
1337 case 1:
1338 if (reg < 4) {
1339 if (upd_cc) emit_get_eflags();
1340 emit_nonshiftopb_offregmem_reg ( opcode, off, areg, reg );
1341 if (upd_cc) emit_put_eflags();
1342 } else {
1343 emit_swapl_reg_EAX ( reg );
1344 if (upd_cc) emit_get_eflags();
1345 emit_nonshiftopb_offregmem_reg ( opcode, off, areg, R_AL );
1346 if (upd_cc) emit_put_eflags();
1347 emit_swapl_reg_EAX ( reg );
1348 }
1349 break;
1350 default:
1351 VG_(panic)("synth_nonshiftop_litmem_reg");
1352 }
1353}
1354
1355
1356static void synth_nonshiftop_lit_reg ( Bool upd_cc,
1357 Opcode opcode, Int size,
1358 UInt lit, Int reg )
1359{
1360 switch (size) {
1361 case 4: if (upd_cc) emit_get_eflags();
1362 emit_nonshiftopv_lit_reg ( 4, opcode, lit, reg );
1363 if (upd_cc) emit_put_eflags();
1364 break;
1365 case 2: if (upd_cc) emit_get_eflags();
1366 emit_nonshiftopv_lit_reg ( 2, opcode, lit, reg );
1367 if (upd_cc) emit_put_eflags();
1368 break;
1369 case 1: if (reg < 4) {
1370 if (upd_cc) emit_get_eflags();
1371 emit_nonshiftopb_lit_reg ( opcode, lit, reg );
1372 if (upd_cc) emit_put_eflags();
1373 } else {
1374 emit_swapl_reg_EAX ( reg );
1375 if (upd_cc) emit_get_eflags();
1376 emit_nonshiftopb_lit_reg ( opcode, lit, R_AL );
1377 if (upd_cc) emit_put_eflags();
1378 emit_swapl_reg_EAX ( reg );
1379 }
1380 break;
1381 default: VG_(panic)("synth_nonshiftop_lit_reg");
1382 }
1383}
1384
1385
1386static void synth_push_reg ( Int size, Int reg )
1387{
1388 switch (size) {
1389 case 4:
1390 emit_pushv_reg ( 4, reg );
1391 break;
1392 case 2:
1393 emit_pushv_reg ( 2, reg );
1394 break;
1395 /* Pray that we don't have to generate this really cruddy bit of
1396 code very often. Could do better, but can I be bothered? */
1397 case 1:
1398 vg_assert(reg != R_ESP); /* duh */
1399 emit_add_lit_to_esp(-1);
1400 if (reg != R_EAX) emit_swapl_reg_EAX ( reg );
1401 emit_movb_AL_zeroESPmem();
1402 if (reg != R_EAX) emit_swapl_reg_EAX ( reg );
1403 break;
1404 default:
1405 VG_(panic)("synth_push_reg");
1406 }
1407}
1408
1409
1410static void synth_pop_reg ( Int size, Int reg )
1411{
1412 switch (size) {
1413 case 4:
1414 emit_popv_reg ( 4, reg );
1415 break;
1416 case 2:
1417 emit_popv_reg ( 2, reg );
1418 break;
1419 case 1:
1420 /* Same comment as above applies. */
1421 vg_assert(reg != R_ESP); /* duh */
1422 if (reg != R_EAX) emit_swapl_reg_EAX ( reg );
1423 emit_movb_zeroESPmem_AL();
1424 if (reg != R_EAX) emit_swapl_reg_EAX ( reg );
1425 emit_add_lit_to_esp(1);
1426 break;
1427 default: VG_(panic)("synth_pop_reg");
1428 }
1429}
1430
1431
1432static void synth_shiftop_reg_reg ( Bool upd_cc,
1433 Opcode opcode, Int size,
1434 Int regs, Int regd )
1435{
1436 synth_push_reg ( size, regd );
1437 if (regs != R_ECX) emit_swapl_reg_ECX ( regs );
1438 if (upd_cc) emit_get_eflags();
1439 switch (size) {
1440 case 4: emit_shiftopv_cl_stack0 ( 4, opcode ); break;
1441 case 2: emit_shiftopv_cl_stack0 ( 2, opcode ); break;
1442 case 1: emit_shiftopb_cl_stack0 ( opcode ); break;
1443 default: VG_(panic)("synth_shiftop_reg_reg");
1444 }
1445 if (upd_cc) emit_put_eflags();
1446 if (regs != R_ECX) emit_swapl_reg_ECX ( regs );
1447 synth_pop_reg ( size, regd );
1448}
1449
1450
1451static void synth_shiftop_lit_reg ( Bool upd_cc,
1452 Opcode opcode, Int size,
1453 UInt lit, Int reg )
1454{
1455 switch (size) {
1456 case 4: if (upd_cc) emit_get_eflags();
1457 emit_shiftopv_lit_reg ( 4, opcode, lit, reg );
1458 if (upd_cc) emit_put_eflags();
1459 break;
1460 case 2: if (upd_cc) emit_get_eflags();
1461 emit_shiftopv_lit_reg ( 2, opcode, lit, reg );
1462 if (upd_cc) emit_put_eflags();
1463 break;
1464 case 1: if (reg < 4) {
1465 if (upd_cc) emit_get_eflags();
1466 emit_shiftopb_lit_reg ( opcode, lit, reg );
1467 if (upd_cc) emit_put_eflags();
1468 } else {
1469 emit_swapl_reg_EAX ( reg );
1470 if (upd_cc) emit_get_eflags();
1471 emit_shiftopb_lit_reg ( opcode, lit, R_AL );
1472 if (upd_cc) emit_put_eflags();
1473 emit_swapl_reg_EAX ( reg );
1474 }
1475 break;
1476 default: VG_(panic)("synth_nonshiftop_lit_reg");
1477 }
1478}
1479
1480
1481static void synth_setb_reg ( Int reg, Condcode cond )
1482{
1483 emit_get_eflags();
1484 if (reg < 4) {
1485 emit_setb_reg ( reg, cond );
1486 } else {
1487 emit_swapl_reg_EAX ( reg );
1488 emit_setb_reg ( R_AL, cond );
1489 emit_swapl_reg_EAX ( reg );
1490 }
1491}
1492
1493
1494static void synth_fpu_regmem ( UChar first_byte,
1495 UChar second_byte_masked,
1496 Int reg )
1497{
1498 emit_get_fpu_state();
1499 emit_fpu_regmem ( first_byte, second_byte_masked, reg );
1500 emit_put_fpu_state();
1501}
1502
1503
1504static void synth_fpu_no_mem ( UChar first_byte,
1505 UChar second_byte )
1506{
1507 emit_get_fpu_state();
1508 emit_fpu_no_mem ( first_byte, second_byte );
1509 emit_put_fpu_state();
1510}
1511
1512
1513static void synth_movl_reg_reg ( Int src, Int dst )
1514{
1515 emit_movl_reg_reg ( src, dst );
1516}
1517
1518static void synth_cmovl_reg_reg ( Condcode cond, Int src, Int dst )
1519{
1520 emit_get_eflags();
1521 emit_jcondshort_delta ( invertCondition(cond),
1522 2 /* length of the next insn */ );
1523 emit_movl_reg_reg ( src, dst );
1524}
1525
1526
1527/* A word in memory containing a pointer to vg_helper_smc_check4.
1528 Never changes.
1529*/
1530static const Addr vg_helper_smc_check4_ADDR
1531 = (Addr)&VG_(helper_smc_check4);
1532
1533static void synth_orig_code_write_check ( Int sz, Int reg )
1534{
1535 UInt offset;
1536
1537 /*
1538 In this example, reg is %eax and sz == 8:
1539
1540 -- check the first four bytes
1541 0087 89C5 movl %eax, %ebp
1542 0089 FF1544332211 call * 0x11223344
1543
1544 -- check the second four
1545 008f 89C5 movl %eax, %ebp
1546 0091 83C504 addl $4, %ebp
1547 0094 FF1544332211 call * 0x11223344
1548
1549 Because we can't call an absolute address (alas), the
1550 address called is stored in memory at 0x11223344 in this
1551 example, and it just contains the address of
1552 vg_helper_smc_check4 -- which is where we really want
1553 to get to.
1554 */
1555 vg_assert(0);
1556
1557 if (sz < 4) sz = 4;
1558
1559 for (offset = 0; offset < sz; offset += 4) {
1560
1561 emit_movl_reg_reg ( reg, R_EBP );
1562
1563 if (offset > 0) {
1564 newEmit();
1565 emitB ( 0x83 ); emitB ( 0xC5 ); emitB ( offset );
1566 if (dis) VG_(printf)("\n");
1567 }
1568
1569 newEmit();
1570 emitB ( 0xFF ); emitB ( 0x15 );
1571 emitL ( (Addr)&vg_helper_smc_check4_ADDR );
1572 if (dis) VG_(printf)("\n");
1573 }
1574}
1575
1576
1577/* Synthesise a minimal test (and which discards result) of reg32
1578 against lit. It's always safe do simply
1579 emit_testv_lit_reg ( 4, lit, reg32 )
1580 but we try to do better when possible.
1581*/
1582static void synth_minimal_test_lit_reg ( UInt lit, Int reg32 )
1583{
1584 if ((lit & 0xFFFFFF00) == 0 && reg32 < 4) {
1585 /* We can get away with a byte insn. */
1586 emit_testb_lit_reg ( lit, reg32 );
1587 }
1588 else
1589 if ((lit & 0xFFFF0000) == 0) {
1590 /* Literal fits in 16 bits; do a word insn. */
1591 emit_testv_lit_reg ( 2, lit, reg32 );
1592 }
1593 else {
1594 /* Totally general ... */
1595 emit_testv_lit_reg ( 4, lit, reg32 );
1596 }
1597}
1598
1599
1600/*----------------------------------------------------*/
1601/*--- Top level of the uinstr -> x86 translation. ---*/
1602/*----------------------------------------------------*/
1603
1604/* Return the byte offset from %ebp (ie, into baseBlock)
1605 for the specified ArchReg or SpillNo. */
1606
1607static Int spillOrArchOffset ( Int size, Tag tag, UInt value )
1608{
1609 if (tag == SpillNo) {
1610 vg_assert(size == 4);
1611 vg_assert(value >= 0 && value < VG_MAX_SPILLSLOTS);
1612 return 4 * (value + VGOFF_(spillslots));
1613 }
1614 if (tag == ArchReg) {
1615 switch (value) {
1616 case R_EAX: return 4 * VGOFF_(m_eax);
1617 case R_ECX: return 4 * VGOFF_(m_ecx);
1618 case R_EDX: return 4 * VGOFF_(m_edx);
1619 case R_EBX: return 4 * VGOFF_(m_ebx);
1620 case R_ESP:
1621 if (size == 1) return 4 * VGOFF_(m_eax) + 1;
1622 else return 4 * VGOFF_(m_esp);
1623 case R_EBP:
1624 if (size == 1) return 4 * VGOFF_(m_ecx) + 1;
1625 else return 4 * VGOFF_(m_ebp);
1626 case R_ESI:
1627 if (size == 1) return 4 * VGOFF_(m_edx) + 1;
1628 else return 4 * VGOFF_(m_esi);
1629 case R_EDI:
1630 if (size == 1) return 4 * VGOFF_(m_ebx) + 1;
1631 else return 4 * VGOFF_(m_edi);
1632 }
1633 }
1634 VG_(panic)("spillOrArchOffset");
1635}
1636
1637
1638static Int eflagsOffset ( void )
1639{
1640 return 4 * VGOFF_(m_eflags);
1641}
1642
1643
1644static Int shadowOffset ( Int arch )
1645{
1646 switch (arch) {
1647 case R_EAX: return 4 * VGOFF_(sh_eax);
1648 case R_ECX: return 4 * VGOFF_(sh_ecx);
1649 case R_EDX: return 4 * VGOFF_(sh_edx);
1650 case R_EBX: return 4 * VGOFF_(sh_ebx);
1651 case R_ESP: return 4 * VGOFF_(sh_esp);
1652 case R_EBP: return 4 * VGOFF_(sh_ebp);
1653 case R_ESI: return 4 * VGOFF_(sh_esi);
1654 case R_EDI: return 4 * VGOFF_(sh_edi);
1655 default: VG_(panic)( "shadowOffset");
1656 }
1657}
1658
1659
1660static Int shadowFlagsOffset ( void )
1661{
1662 return 4 * VGOFF_(sh_eflags);
1663}
1664
1665
1666static void synth_LOADV ( Int sz, Int a_reg, Int tv_reg )
1667{
1668 Int i, j, helper_offw;
1669 Int pushed[VG_MAX_REALREGS+2];
1670 Int n_pushed;
1671 switch (sz) {
1672 case 4: helper_offw = VGOFF_(helperc_LOADV4); break;
1673 case 2: helper_offw = VGOFF_(helperc_LOADV2); break;
1674 case 1: helper_offw = VGOFF_(helperc_LOADV1); break;
1675 default: VG_(panic)("synth_LOADV");
1676 }
1677 n_pushed = 0;
1678 for (i = 0; i < VG_MAX_REALREGS; i++) {
1679 j = VG_(rankToRealRegNo) ( i );
1680 if (VG_CALLEE_SAVED(j)) continue;
1681 if (j == tv_reg || j == a_reg) continue;
1682 emit_pushv_reg ( 4, j );
1683 pushed[n_pushed++] = j;
1684 }
1685 emit_pushv_reg ( 4, a_reg );
1686 pushed[n_pushed++] = a_reg;
1687 vg_assert(n_pushed <= VG_MAX_REALREGS+1);
1688
1689 synth_call_baseBlock_method ( False, helper_offw );
1690 /* Result is in %eax; we need to get it to tv_reg. */
1691 if (tv_reg != R_EAX)
1692 emit_movv_reg_reg ( 4, R_EAX, tv_reg );
1693
1694 while (n_pushed > 0) {
1695 n_pushed--;
1696 if (pushed[n_pushed] == tv_reg) {
1697 emit_add_lit_to_esp ( 4 );
1698 } else {
1699 emit_popv_reg ( 4, pushed[n_pushed] );
1700 }
1701 }
1702}
1703
1704
1705static void synth_STOREV ( Int sz,
1706 Int tv_tag, Int tv_val,
1707 Int a_reg )
1708{
1709 Int i, j, helper_offw;
1710 vg_assert(tv_tag == RealReg || tv_tag == Literal);
1711 switch (sz) {
1712 case 4: helper_offw = VGOFF_(helperc_STOREV4); break;
1713 case 2: helper_offw = VGOFF_(helperc_STOREV2); break;
1714 case 1: helper_offw = VGOFF_(helperc_STOREV1); break;
1715 default: VG_(panic)("synth_STOREV");
1716 }
1717 for (i = 0; i < VG_MAX_REALREGS; i++) {
1718 j = VG_(rankToRealRegNo) ( i );
1719 if (VG_CALLEE_SAVED(j)) continue;
1720 if ((tv_tag == RealReg && j == tv_val) || j == a_reg) continue;
1721 emit_pushv_reg ( 4, j );
1722 }
1723 if (tv_tag == RealReg) {
1724 emit_pushv_reg ( 4, tv_val );
1725 } else {
1726 if (tv_val == VG_(extend_s_8to32)(tv_val))
1727 emit_pushl_lit8 ( VG_(extend_s_8to32)(tv_val) );
1728 else
1729 emit_pushl_lit32(tv_val);
1730 }
1731 emit_pushv_reg ( 4, a_reg );
1732 synth_call_baseBlock_method ( False, helper_offw );
1733 emit_popv_reg ( 4, a_reg );
1734 if (tv_tag == RealReg) {
1735 emit_popv_reg ( 4, tv_val );
1736 } else {
1737 emit_add_lit_to_esp ( 4 );
1738 }
1739 for (i = VG_MAX_REALREGS-1; i >= 0; i--) {
1740 j = VG_(rankToRealRegNo) ( i );
1741 if (VG_CALLEE_SAVED(j)) continue;
1742 if ((tv_tag == RealReg && j == tv_val) || j == a_reg) continue;
1743 emit_popv_reg ( 4, j );
1744 }
1745}
1746
1747
1748static void synth_WIDEN_signed ( Int sz_src, Int sz_dst, Int reg )
1749{
1750 if (sz_src == 1 && sz_dst == 4) {
1751 emit_shiftopv_lit_reg ( 4, SHL, 24, reg );
1752 emit_shiftopv_lit_reg ( 4, SAR, 24, reg );
1753 }
1754 else if (sz_src == 2 && sz_dst == 4) {
1755 emit_shiftopv_lit_reg ( 4, SHL, 16, reg );
1756 emit_shiftopv_lit_reg ( 4, SAR, 16, reg );
1757 }
1758 else if (sz_src == 1 && sz_dst == 2) {
1759 emit_shiftopv_lit_reg ( 2, SHL, 8, reg );
1760 emit_shiftopv_lit_reg ( 2, SAR, 8, reg );
1761 }
1762 else
1763 VG_(panic)("synth_WIDEN");
1764}
1765
1766
1767static void synth_SETV ( Int sz, Int reg )
1768{
1769 UInt val;
1770 switch (sz) {
1771 case 4: val = 0x00000000; break;
1772 case 2: val = 0xFFFF0000; break;
1773 case 1: val = 0xFFFFFF00; break;
1774 case 0: val = 0xFFFFFFFE; break;
1775 default: VG_(panic)("synth_SETV");
1776 }
1777 emit_movv_lit_reg ( 4, val, reg );
1778}
1779
1780
1781static void synth_TESTV ( Int sz, Int tag, Int val )
1782{
1783 vg_assert(tag == ArchReg || tag == RealReg);
1784 if (tag == ArchReg) {
1785 switch (sz) {
1786 case 4:
1787 emit_testv_lit_offregmem (
1788 4, 0xFFFFFFFF, shadowOffset(val), R_EBP );
1789 break;
1790 case 2:
1791 emit_testv_lit_offregmem (
1792 4, 0x0000FFFF, shadowOffset(val), R_EBP );
1793 break;
1794 case 1:
1795 if (val < 4) {
1796 emit_testv_lit_offregmem (
1797 4, 0x000000FF, shadowOffset(val), R_EBP );
1798 } else {
1799 emit_testv_lit_offregmem (
1800 4, 0x0000FF00, shadowOffset(val-4), R_EBP );
1801 }
1802 break;
1803 case 0:
1804 /* should never happen */
1805 default:
1806 VG_(panic)("synth_TESTV(ArchReg)");
1807 }
1808 } else {
1809 switch (sz) {
1810 case 4:
1811 /* Works, but holds the entire 32-bit literal, hence
1812 generating a 6-byte insn. We want to know if any bits
1813 in the reg are set, but since this is for the full reg,
1814 we might as well compare it against zero, which can be
1815 done with a shorter insn. */
1816 /* synth_minimal_test_lit_reg ( 0xFFFFFFFF, val ); */
1817 emit_cmpl_zero_reg ( val );
1818 break;
1819 case 2:
1820 synth_minimal_test_lit_reg ( 0x0000FFFF, val );
1821 break;
1822 case 1:
1823 synth_minimal_test_lit_reg ( 0x000000FF, val );
1824 break;
1825 case 0:
1826 synth_minimal_test_lit_reg ( 0x00000001, val );
1827 break;
1828 default:
1829 VG_(panic)("synth_TESTV(RealReg)");
1830 }
1831 }
1832 emit_jcondshort_delta ( CondZ, 3 );
1833 synth_call_baseBlock_method (
1834 True, /* needed to guarantee that this insn is indeed 3 bytes long */
1835 (sz==4 ? VGOFF_(helper_value_check4_fail)
1836 : (sz==2 ? VGOFF_(helper_value_check2_fail)
1837 : sz == 1 ? VGOFF_(helper_value_check1_fail)
1838 : VGOFF_(helper_value_check0_fail)))
1839 );
1840}
1841
1842
1843static void synth_GETV ( Int sz, Int arch, Int reg )
1844{
1845 /* VG_(printf)("synth_GETV %d of Arch %s\n", sz, nameIReg(sz, arch)); */
1846 switch (sz) {
1847 case 4:
1848 emit_movv_offregmem_reg ( 4, shadowOffset(arch), R_EBP, reg );
1849 break;
1850 case 2:
1851 emit_movzwl_offregmem_reg ( shadowOffset(arch), R_EBP, reg );
1852 emit_nonshiftopv_lit_reg ( 4, OR, 0xFFFF0000, reg );
1853 break;
1854 case 1:
1855 if (arch < 4) {
1856 emit_movzbl_offregmem_reg ( shadowOffset(arch), R_EBP, reg );
1857 } else {
1858 emit_movzbl_offregmem_reg ( shadowOffset(arch-4)+1, R_EBP, reg );
1859 }
1860 emit_nonshiftopv_lit_reg ( 4, OR, 0xFFFFFF00, reg );
1861 break;
1862 default:
1863 VG_(panic)("synth_GETV");
1864 }
1865}
1866
1867
1868static void synth_PUTV ( Int sz, Int srcTag, UInt lit_or_reg, Int arch )
1869{
1870 if (srcTag == Literal) {
1871 /* PUTV with a Literal is only ever used to set the corresponding
1872 ArchReg to `all valid'. Should really be a kind of SETV. */
1873 UInt lit = lit_or_reg;
1874 switch (sz) {
1875 case 4:
1876 vg_assert(lit == 0x00000000);
1877 emit_movv_lit_offregmem ( 4, 0x00000000,
1878 shadowOffset(arch), R_EBP );
1879 break;
1880 case 2:
1881 vg_assert(lit == 0xFFFF0000);
1882 emit_movv_lit_offregmem ( 2, 0x0000,
1883 shadowOffset(arch), R_EBP );
1884 break;
1885 case 1:
1886 vg_assert(lit == 0xFFFFFF00);
1887 if (arch < 4) {
1888 emit_movb_lit_offregmem ( 0x00,
1889 shadowOffset(arch), R_EBP );
1890 } else {
1891 emit_movb_lit_offregmem ( 0x00,
1892 shadowOffset(arch-4)+1, R_EBP );
1893 }
1894 break;
1895 default:
1896 VG_(panic)("synth_PUTV(lit)");
1897 }
1898
1899 } else {
1900
1901 UInt reg;
1902 vg_assert(srcTag == RealReg);
1903
1904 if (sz == 1 && lit_or_reg >= 4) {
1905 emit_swapl_reg_EAX ( lit_or_reg );
1906 reg = R_EAX;
1907 } else {
1908 reg = lit_or_reg;
1909 }
1910
1911 if (sz == 1) vg_assert(reg < 4);
1912
1913 switch (sz) {
1914 case 4:
1915 emit_movv_reg_offregmem ( 4, reg,
1916 shadowOffset(arch), R_EBP );
1917 break;
1918 case 2:
1919 emit_movv_reg_offregmem ( 2, reg,
1920 shadowOffset(arch), R_EBP );
1921 break;
1922 case 1:
1923 if (arch < 4) {
1924 emit_movb_reg_offregmem ( reg,
1925 shadowOffset(arch), R_EBP );
1926 } else {
1927 emit_movb_reg_offregmem ( reg,
1928 shadowOffset(arch-4)+1, R_EBP );
1929 }
1930 break;
1931 default:
1932 VG_(panic)("synth_PUTV(reg)");
1933 }
1934
1935 if (sz == 1 && lit_or_reg >= 4) {
1936 emit_swapl_reg_EAX ( lit_or_reg );
1937 }
1938 }
1939}
1940
1941
1942static void synth_GETVF ( Int reg )
1943{
1944 emit_movv_offregmem_reg ( 4, shadowFlagsOffset(), R_EBP, reg );
1945 /* paranoia only; should be unnecessary ... */
1946 /* emit_nonshiftopv_lit_reg ( 4, OR, 0xFFFFFFFE, reg ); */
1947}
1948
1949
1950static void synth_PUTVF ( UInt reg )
1951{
1952 emit_movv_reg_offregmem ( 4, reg, shadowFlagsOffset(), R_EBP );
1953}
1954
1955
1956static void synth_handle_esp_assignment ( Int reg )
1957{
1958 emit_pushal();
1959 emit_pushv_reg ( 4, reg );
1960 synth_call_baseBlock_method ( False, VGOFF_(handle_esp_assignment) );
1961 emit_add_lit_to_esp ( 4 );
1962 emit_popal();
1963}
1964
1965
1966static void synth_fpu_mem_check_actions ( Bool isWrite,
1967 Int size, Int a_reg )
1968{
1969 Int helper_offw
1970 = isWrite ? VGOFF_(fpu_write_check)
1971 : VGOFF_(fpu_read_check);
1972 emit_pushal();
1973 emit_pushl_lit8 ( size );
1974 emit_pushv_reg ( 4, a_reg );
1975 synth_call_baseBlock_method ( False, helper_offw );
1976 emit_add_lit_to_esp ( 8 );
1977 emit_popal();
1978}
1979
1980
1981#if 0
1982/* FixMe. Useful for debugging. */
1983void VG_(oink) ( Int n )
1984{
1985 VG_(printf)("OiNk(%d): ", n );
1986 VG_(show_reg_tags)( &VG_(m_shadow) );
1987}
1988
1989static void synth_OINK ( Int n )
1990{
1991 emit_pushal();
1992 emit_movv_lit_reg ( 4, n, R_EBP );
1993 emit_pushl_reg ( R_EBP );
1994 emit_movv_lit_reg ( 4, (Addr)&VG_(oink), R_EBP );
1995 emit_call_reg ( R_EBP );
1996 emit_add_lit_to_esp ( 4 );
1997 emit_popal();
1998}
1999#endif
2000
2001static void synth_TAG1_op ( VgTagOp op, Int reg )
2002{
2003 switch (op) {
2004
2005 /* Scheme is
2006 neg<sz> %reg -- CF = %reg==0 ? 0 : 1
2007 sbbl %reg, %reg -- %reg = -CF
2008 or 0xFFFFFFFE, %reg -- invalidate all bits except lowest
2009 */
2010 case VgT_PCast40:
2011 emit_unaryopv_reg(4, NEG, reg);
2012 emit_nonshiftopv_reg_reg(4, SBB, reg, reg);
2013 emit_nonshiftopv_lit_reg(4, OR, 0xFFFFFFFE, reg);
2014 break;
2015 case VgT_PCast20:
2016 emit_unaryopv_reg(2, NEG, reg);
2017 emit_nonshiftopv_reg_reg(4, SBB, reg, reg);
2018 emit_nonshiftopv_lit_reg(4, OR, 0xFFFFFFFE, reg);
2019 break;
2020 case VgT_PCast10:
2021 if (reg >= 4) {
2022 emit_swapl_reg_EAX(reg);
2023 emit_unaryopb_reg(NEG, R_EAX);
2024 emit_swapl_reg_EAX(reg);
2025 } else {
2026 emit_unaryopb_reg(NEG, reg);
2027 }
2028 emit_nonshiftopv_reg_reg(4, SBB, reg, reg);
2029 emit_nonshiftopv_lit_reg(4, OR, 0xFFFFFFFE, reg);
2030 break;
2031
2032 /* Scheme is
2033 andl $1, %reg -- %reg is 0 or 1
2034 negl %reg -- %reg is 0 or 0xFFFFFFFF
2035 and possibly an OR to invalidate unused bits.
2036 */
2037 case VgT_PCast04:
2038 emit_nonshiftopv_lit_reg(4, AND, 0x00000001, reg);
2039 emit_unaryopv_reg(4, NEG, reg);
2040 break;
2041 case VgT_PCast02:
2042 emit_nonshiftopv_lit_reg(4, AND, 0x00000001, reg);
2043 emit_unaryopv_reg(4, NEG, reg);
2044 emit_nonshiftopv_lit_reg(4, OR, 0xFFFF0000, reg);
2045 break;
2046 case VgT_PCast01:
2047 emit_nonshiftopv_lit_reg(4, AND, 0x00000001, reg);
2048 emit_unaryopv_reg(4, NEG, reg);
2049 emit_nonshiftopv_lit_reg(4, OR, 0xFFFFFF00, reg);
2050 break;
2051
2052 /* Scheme is
2053 shl $24, %reg -- make irrelevant bits disappear
2054 negl %reg -- CF = %reg==0 ? 0 : 1
2055 sbbl %reg, %reg -- %reg = -CF
2056 and possibly an OR to invalidate unused bits.
2057 */
2058 case VgT_PCast14:
2059 emit_shiftopv_lit_reg(4, SHL, 24, reg);
2060 emit_unaryopv_reg(4, NEG, reg);
2061 emit_nonshiftopv_reg_reg(4, SBB, reg, reg);
2062 break;
2063 case VgT_PCast12:
2064 emit_shiftopv_lit_reg(4, SHL, 24, reg);
2065 emit_unaryopv_reg(4, NEG, reg);
2066 emit_nonshiftopv_reg_reg(4, SBB, reg, reg);
2067 emit_nonshiftopv_lit_reg(4, OR, 0xFFFF0000, reg);
2068 break;
2069 case VgT_PCast11:
2070 emit_shiftopv_lit_reg(4, SHL, 24, reg);
2071 emit_unaryopv_reg(4, NEG, reg);
2072 emit_nonshiftopv_reg_reg(4, SBB, reg, reg);
2073 emit_nonshiftopv_lit_reg(4, OR, 0xFFFFFF00, reg);
2074 break;
2075
2076 /* We steal %ebp (a non-allocable reg) as a temporary:
2077 pushl %ebp
2078 movl %reg, %ebp
2079 negl %ebp
2080 orl %ebp, %reg
2081 popl %ebp
2082 This sequence turns out to be correct regardless of the
2083 operation width.
2084 */
2085 case VgT_Left4:
2086 case VgT_Left2:
2087 case VgT_Left1:
2088 vg_assert(reg != R_EDI);
2089 emit_movv_reg_reg(4, reg, R_EDI);
2090 emit_unaryopv_reg(4, NEG, R_EDI);
2091 emit_nonshiftopv_reg_reg(4, OR, R_EDI, reg);
2092 break;
2093
2094 /* These are all fairly obvious; do the op and then, if
2095 necessary, invalidate unused bits. */
2096 case VgT_SWiden14:
2097 emit_shiftopv_lit_reg(4, SHL, 24, reg);
2098 emit_shiftopv_lit_reg(4, SAR, 24, reg);
2099 break;
2100 case VgT_SWiden24:
2101 emit_shiftopv_lit_reg(4, SHL, 16, reg);
2102 emit_shiftopv_lit_reg(4, SAR, 16, reg);
2103 break;
2104 case VgT_SWiden12:
2105 emit_shiftopv_lit_reg(4, SHL, 24, reg);
2106 emit_shiftopv_lit_reg(4, SAR, 24, reg);
2107 emit_nonshiftopv_lit_reg(4, OR, 0xFFFF0000, reg);
2108 break;
2109 case VgT_ZWiden14:
2110 emit_nonshiftopv_lit_reg(4, AND, 0x000000FF, reg);
2111 break;
2112 case VgT_ZWiden24:
2113 emit_nonshiftopv_lit_reg(4, AND, 0x0000FFFF, reg);
2114 break;
2115 case VgT_ZWiden12:
2116 emit_nonshiftopv_lit_reg(4, AND, 0x000000FF, reg);
2117 emit_nonshiftopv_lit_reg(4, OR, 0xFFFF0000, reg);
2118 break;
2119
2120 default:
2121 VG_(panic)("synth_TAG1_op");
2122 }
2123}
2124
2125
2126static void synth_TAG2_op ( VgTagOp op, Int regs, Int regd )
2127{
2128 switch (op) {
2129
2130 /* UifU is implemented by OR, since 1 means Undefined. */
2131 case VgT_UifU4:
2132 case VgT_UifU2:
2133 case VgT_UifU1:
2134 case VgT_UifU0:
2135 emit_nonshiftopv_reg_reg(4, OR, regs, regd);
2136 break;
2137
2138 /* DifD is implemented by AND, since 0 means Defined. */
2139 case VgT_DifD4:
2140 case VgT_DifD2:
2141 case VgT_DifD1:
2142 emit_nonshiftopv_reg_reg(4, AND, regs, regd);
2143 break;
2144
2145 /* ImproveAND(value, tags) = value OR tags.
2146 Defined (0) value 0s give defined (0); all other -> undefined (1).
2147 value is in regs; tags is in regd.
2148 Be paranoid and invalidate unused bits; I don't know whether
2149 or not this is actually necessary. */
2150 case VgT_ImproveAND4_TQ:
2151 emit_nonshiftopv_reg_reg(4, OR, regs, regd);
2152 break;
2153 case VgT_ImproveAND2_TQ:
2154 emit_nonshiftopv_reg_reg(4, OR, regs, regd);
2155 emit_nonshiftopv_lit_reg(4, OR, 0xFFFF0000, regd);
2156 break;
2157 case VgT_ImproveAND1_TQ:
2158 emit_nonshiftopv_reg_reg(4, OR, regs, regd);
2159 emit_nonshiftopv_lit_reg(4, OR, 0xFFFFFF00, regd);
2160 break;
2161
2162 /* ImproveOR(value, tags) = (not value) OR tags.
2163 Defined (0) value 1s give defined (0); all other -> undefined (1).
2164 value is in regs; tags is in regd.
2165 To avoid trashing value, this is implemented (re de Morgan) as
2166 not (value AND (not tags))
2167 Be paranoid and invalidate unused bits; I don't know whether
2168 or not this is actually necessary. */
2169 case VgT_ImproveOR4_TQ:
2170 emit_unaryopv_reg(4, NOT, regd);
2171 emit_nonshiftopv_reg_reg(4, AND, regs, regd);
2172 emit_unaryopv_reg(4, NOT, regd);
2173 break;
2174 case VgT_ImproveOR2_TQ:
2175 emit_unaryopv_reg(4, NOT, regd);
2176 emit_nonshiftopv_reg_reg(4, AND, regs, regd);
2177 emit_unaryopv_reg(4, NOT, regd);
2178 emit_nonshiftopv_lit_reg(4, OR, 0xFFFF0000, regd);
2179 break;
2180 case VgT_ImproveOR1_TQ:
2181 emit_unaryopv_reg(4, NOT, regd);
2182 emit_nonshiftopv_reg_reg(4, AND, regs, regd);
2183 emit_unaryopv_reg(4, NOT, regd);
2184 emit_nonshiftopv_lit_reg(4, OR, 0xFFFFFF00, regd);
2185 break;
2186
2187 default:
2188 VG_(panic)("synth_TAG2_op");
2189 }
2190}
2191
2192/*----------------------------------------------------*/
2193/*--- Generate code for a single UInstr. ---*/
2194/*----------------------------------------------------*/
2195
2196static void emitUInstr ( Int i, UInstr* u )
2197{
2198 if (dis)
2199 VG_(ppUInstr)(i, u);
2200
2201# if 0
2202 if (0&& VG_(translations_done) >= 600) {
2203 Bool old_dis = dis;
2204 dis = False;
2205 synth_OINK(i);
2206 dis = old_dis;
2207 }
2208# endif
2209
2210 switch (u->opcode) {
2211
2212 case NOP: case CALLM_S: case CALLM_E: break;
2213
2214 case INCEIP: {
2215 vg_assert(u->tag1 == Lit16);
2216 emit_addlit8_offregmem ( u->val1, R_EBP, 4 * VGOFF_(m_eip) );
2217 break;
2218 }
2219
2220 case LEA1: {
2221 vg_assert(u->tag1 == RealReg);
2222 vg_assert(u->tag2 == RealReg);
2223 emit_lea_litreg_reg ( u->lit32, u->val1, u->val2 );
2224 break;
2225 }
2226
2227 case LEA2: {
2228 vg_assert(u->tag1 == RealReg);
2229 vg_assert(u->tag2 == RealReg);
2230 vg_assert(u->tag3 == RealReg);
2231 emit_lea_sib_reg ( u->lit32, u->extra4b,
2232 u->val1, u->val2, u->val3 );
2233 break;
2234 }
2235
2236 case WIDEN: {
2237 vg_assert(u->tag1 == RealReg);
2238 if (u->signed_widen) {
2239 synth_WIDEN_signed ( u->extra4b, u->size, u->val1 );
2240 } else {
2241 /* no need to generate any code. */
2242 }
2243 break;
2244 }
2245
2246 case SETV: {
2247 vg_assert(VG_(clo_instrument));
2248 vg_assert(u->tag1 == RealReg);
2249 synth_SETV ( u->size, u->val1 );
2250 break;
2251 }
2252
2253 case STOREV: {
2254 vg_assert(VG_(clo_instrument));
2255 vg_assert(u->tag1 == RealReg || u->tag1 == Literal);
2256 vg_assert(u->tag2 == RealReg);
2257 synth_STOREV ( u->size, u->tag1,
2258 u->tag1==Literal ? u->lit32 : u->val1,
2259 u->val2 );
2260 break;
2261 }
2262
2263 case STORE: {
2264 vg_assert(u->tag1 == RealReg);
2265 vg_assert(u->tag2 == RealReg);
2266 synth_mov_reg_memreg ( u->size, u->val1, u->val2 );
2267 if (u->smc_check)
2268 synth_orig_code_write_check ( u->size, u->val2 );
2269 break;
2270 }
2271
2272 case LOADV: {
2273 vg_assert(VG_(clo_instrument));
2274 vg_assert(u->tag1 == RealReg);
2275 vg_assert(u->tag2 == RealReg);
2276 if (0 && VG_(clo_instrument))
2277 emit_AMD_prefetch_reg ( u->val1 );
2278 synth_LOADV ( u->size, u->val1, u->val2 );
2279 break;
2280 }
2281
2282 case LOAD: {
2283 vg_assert(u->tag1 == RealReg);
2284 vg_assert(u->tag2 == RealReg);
2285 synth_mov_regmem_reg ( u->size, u->val1, u->val2 );
2286 break;
2287 }
2288
2289 case TESTV: {
2290 vg_assert(VG_(clo_instrument));
2291 vg_assert(u->tag1 == RealReg || u->tag1 == ArchReg);
2292 synth_TESTV(u->size, u->tag1, u->val1);
2293 break;
2294 }
2295
2296 case GETV: {
2297 vg_assert(VG_(clo_instrument));
2298 vg_assert(u->tag1 == ArchReg);
2299 vg_assert(u->tag2 == RealReg);
2300 synth_GETV(u->size, u->val1, u->val2);
2301 break;
2302 }
2303
2304 case GETVF: {
2305 vg_assert(VG_(clo_instrument));
2306 vg_assert(u->tag1 == RealReg);
2307 vg_assert(u->size == 0);
2308 synth_GETVF(u->val1);
2309 break;
2310 }
2311
2312 case PUTV: {
2313 vg_assert(VG_(clo_instrument));
2314 vg_assert(u->tag1 == RealReg || u->tag1 == Literal);
2315 vg_assert(u->tag2 == ArchReg);
2316 synth_PUTV(u->size, u->tag1,
2317 u->tag1==Literal ? u->lit32 : u->val1,
2318 u->val2 );
2319 break;
2320 }
2321
2322 case PUTVF: {
2323 vg_assert(VG_(clo_instrument));
2324 vg_assert(u->tag1 == RealReg);
2325 vg_assert(u->size == 0);
2326 synth_PUTVF(u->val1);
2327 break;
2328 }
2329
2330 case GET: {
2331 vg_assert(u->tag1 == ArchReg || u->tag1 == SpillNo);
2332 vg_assert(u->tag2 == RealReg);
2333 synth_mov_offregmem_reg (
2334 u->size,
2335 spillOrArchOffset( u->size, u->tag1, u->val1 ),
2336 R_EBP,
2337 u->val2
2338 );
2339 break;
2340 }
2341
2342 case PUT: {
2343 vg_assert(u->tag2 == ArchReg || u->tag2 == SpillNo);
2344 vg_assert(u->tag1 == RealReg);
2345 if (u->tag2 == ArchReg
2346 && u->val2 == R_ESP
2347 && u->size == 4
2348 && VG_(clo_instrument)) {
2349 synth_handle_esp_assignment ( u->val1 );
2350 }
2351 synth_mov_reg_offregmem (
2352 u->size,
2353 u->val1,
2354 spillOrArchOffset( u->size, u->tag2, u->val2 ),
2355 R_EBP
2356 );
2357 break;
2358 }
2359
2360 case GETF: {
2361 vg_assert(u->size == 2 || u->size == 4);
2362 vg_assert(u->tag1 == RealReg);
2363 synth_mov_offregmem_reg (
2364 u->size,
2365 eflagsOffset(),
2366 R_EBP,
2367 u->val1
2368 );
2369 break;
2370 }
2371
2372 case PUTF: {
2373 vg_assert(u->size == 2 || u->size == 4);
2374 vg_assert(u->tag1 == RealReg);
2375 synth_mov_reg_offregmem (
2376 u->size,
2377 u->val1,
2378 eflagsOffset(),
2379 R_EBP
2380 );
2381 break;
2382 }
2383
2384 case MOV: {
2385 vg_assert(u->tag1 == RealReg || u->tag1 == Literal);
2386 vg_assert(u->tag2 == RealReg);
2387 switch (u->tag1) {
2388 case RealReg: vg_assert(u->size == 4);
2389 if (u->val1 != u->val2)
2390 synth_movl_reg_reg ( u->val1, u->val2 );
2391 break;
2392 case Literal: synth_mov_lit_reg ( u->size, u->lit32, u->val2 );
2393 break;
2394 default: VG_(panic)("emitUInstr:mov");
2395 }
2396 break;
2397 }
2398
2399 case SBB:
2400 case ADC:
2401 case XOR:
2402 case OR:
2403 case AND:
2404 case SUB:
2405 case ADD: {
2406 vg_assert(u->tag2 == RealReg);
2407 switch (u->tag1) {
2408 case Literal: synth_nonshiftop_lit_reg (
2409 VG_(anyFlagUse)(u),
2410 u->opcode, u->size, u->lit32, u->val2 );
2411 break;
2412 case RealReg: synth_nonshiftop_reg_reg (
2413 VG_(anyFlagUse)(u),
2414 u->opcode, u->size, u->val1, u->val2 );
2415 break;
2416 case ArchReg: synth_nonshiftop_offregmem_reg (
2417 VG_(anyFlagUse)(u),
2418 u->opcode, u->size,
2419 spillOrArchOffset( u->size, u->tag1, u->val1 ),
2420 R_EBP,
2421 u->val2 );
2422 break;
2423 default: VG_(panic)("emitUInstr:non-shift-op");
2424 }
2425 break;
2426 }
2427
2428 case RCR:
2429 case RCL:
2430 case ROR:
2431 case ROL:
2432 case SAR:
2433 case SHR:
2434 case SHL: {
2435 vg_assert(u->tag2 == RealReg);
2436 switch (u->tag1) {
2437 case Literal: synth_shiftop_lit_reg (
2438 VG_(anyFlagUse)(u),
2439 u->opcode, u->size, u->lit32, u->val2 );
2440 break;
2441 case RealReg: synth_shiftop_reg_reg (
2442 VG_(anyFlagUse)(u),
2443 u->opcode, u->size, u->val1, u->val2 );
2444 break;
2445 default: VG_(panic)("emitUInstr:non-shift-op");
2446 }
2447 break;
2448 }
2449
2450 case INC:
2451 case DEC:
2452 case NEG:
2453 case NOT:
2454 vg_assert(u->tag1 == RealReg);
2455 synth_unaryop_reg (
2456 VG_(anyFlagUse)(u), u->opcode, u->size, u->val1 );
2457 break;
2458
2459 case BSWAP:
2460 vg_assert(u->tag1 == RealReg);
2461 vg_assert(u->size == 4);
2462 vg_assert(!VG_(anyFlagUse)(u));
2463 emit_bswapl_reg ( u->val1 );
2464 break;
2465
2466 case CMOV:
2467 vg_assert(u->tag1 == RealReg);
2468 vg_assert(u->tag2 == RealReg);
2469 vg_assert(u->cond != CondAlways);
2470 vg_assert(u->size == 4);
2471 synth_cmovl_reg_reg ( u->cond, u->val1, u->val2 );
2472 break;
2473
2474 case JMP: {
2475 vg_assert(u->tag2 == NoValue);
2476 vg_assert(u->tag1 == RealReg || u->tag1 == Literal);
2477 if (u->cond == CondAlways) {
sewardj2e93c502002-04-12 11:12:52 +00002478 switch (u->tag1) {
2479 case RealReg:
2480 synth_jmp_reg ( u->val1, u->jmpkind );
2481 break;
2482 case Literal:
2483 synth_jmp_lit ( u->lit32, u->jmpkind );
2484 break;
2485 default:
2486 VG_(panic)("emitUInstr(JMP, unconditional, default)");
2487 break;
sewardjde4a1d02002-03-22 01:27:54 +00002488 }
2489 } else {
sewardj2e93c502002-04-12 11:12:52 +00002490 switch (u->tag1) {
2491 case RealReg:
2492 VG_(panic)("emitUInstr(JMP, conditional, RealReg)");
2493 break;
2494 case Literal:
2495 vg_assert(u->jmpkind == JmpBoring);
2496 synth_jcond_lit ( u->cond, u->lit32 );
2497 break;
2498 default:
2499 VG_(panic)("emitUInstr(JMP, conditional, default)");
2500 break;
sewardjde4a1d02002-03-22 01:27:54 +00002501 }
2502 }
2503 break;
2504 }
2505
2506 case JIFZ:
2507 vg_assert(u->tag1 == RealReg);
2508 vg_assert(u->tag2 == Literal);
2509 vg_assert(u->size == 4);
2510 synth_jmp_ifzero_reg_lit ( u->val1, u->lit32 );
2511 break;
2512
2513 case TAG1:
2514 synth_TAG1_op ( u->val3, u->val1 );
2515 break;
2516
2517 case TAG2:
2518 if (u->val3 != VgT_DebugFn) {
2519 synth_TAG2_op ( u->val3, u->val1, u->val2 );
2520 } else {
2521 /* Assume a call to VgT_DebugFn passing both args
2522 and placing the result back in the second. */
2523 Int j, k;
2524 /* u->val2 is the reg into which the result is written. So
2525 don't save/restore it. And it can be used at a temp for
2526 the call target, too. Since %eax is used for the return
2527 value from the C procedure, it is preserved only by
2528 virtue of not being mentioned as a VG_CALLEE_SAVED reg. */
2529 for (k = 0; k < VG_MAX_REALREGS; k++) {
2530 j = VG_(rankToRealRegNo) ( k );
2531 if (VG_CALLEE_SAVED(j)) continue;
2532 if (j == u->val2) continue;
2533 emit_pushv_reg ( 4, j );
2534 }
2535 emit_pushv_reg(4, u->val2);
2536 emit_pushv_reg(4, u->val1);
2537 emit_movv_lit_reg ( 4, (UInt)(&VG_(DebugFn)), u->val2 );
2538 emit_call_reg ( u->val2 );
2539 if (u->val2 != R_EAX)
2540 emit_movv_reg_reg ( 4, R_EAX, u->val2 );
2541 /* nuke args */
2542 emit_add_lit_to_esp(8);
2543 for (k = VG_MAX_REALREGS-1; k >= 0; k--) {
2544 j = VG_(rankToRealRegNo) ( k );
2545 if (VG_CALLEE_SAVED(j)) continue;
2546 if (j == u->val2) continue;
2547 emit_popv_reg ( 4, j );
2548 }
2549 }
2550 break;
2551
2552 case PUSH:
2553 vg_assert(u->tag1 == RealReg);
2554 vg_assert(u->tag2 == NoValue);
2555 emit_pushv_reg ( 4, u->val1 );
2556 break;
2557
2558 case POP:
2559 vg_assert(u->tag1 == RealReg);
2560 vg_assert(u->tag2 == NoValue);
2561 emit_popv_reg ( 4, u->val1 );
2562 break;
2563
2564 case CALLM:
2565 vg_assert(u->tag1 == Lit16);
2566 vg_assert(u->tag2 == NoValue);
2567 vg_assert(u->size == 0);
2568 if (u->flags_r != FlagsEmpty || u->flags_w != FlagsEmpty)
2569 emit_get_eflags();
2570 synth_call_baseBlock_method ( False, u->val1 );
2571 if (u->flags_w != FlagsEmpty)
2572 emit_put_eflags();
2573 break;
2574
2575 case CLEAR:
2576 vg_assert(u->tag1 == Lit16);
2577 vg_assert(u->tag2 == NoValue);
2578 emit_add_lit_to_esp ( u->val1 );
2579 break;
2580
2581 case CC2VAL:
2582 vg_assert(u->tag1 == RealReg);
2583 vg_assert(u->tag2 == NoValue);
2584 vg_assert(VG_(anyFlagUse)(u));
2585 synth_setb_reg ( u->val1, u->cond );
2586 break;
2587
2588 /* We assume that writes to memory done by FPU_Ws are not going
2589 to be used to create new code, so there's no orig-code-write
2590 checks done by default. */
2591 case FPU_R:
2592 case FPU_W:
2593 vg_assert(u->tag1 == Lit16);
2594 vg_assert(u->tag2 == RealReg);
2595 if (VG_(clo_instrument))
2596 synth_fpu_mem_check_actions (
2597 u->opcode==FPU_W, u->size, u->val2 );
2598 synth_fpu_regmem ( (u->val1 >> 8) & 0xFF,
2599 u->val1 & 0xFF,
2600 u->val2 );
2601 if (u->opcode == FPU_W && u->smc_check)
2602 synth_orig_code_write_check ( u->size, u->val2 );
2603 break;
2604
2605 case FPU:
2606 vg_assert(u->tag1 == Lit16);
2607 vg_assert(u->tag2 == NoValue);
sewardj8d32be72002-04-18 02:18:24 +00002608 if (u->flags_r != FlagsEmpty || u->flags_w != FlagsEmpty)
sewardj4a7456e2002-03-24 13:52:19 +00002609 emit_get_eflags();
sewardjde4a1d02002-03-22 01:27:54 +00002610 synth_fpu_no_mem ( (u->val1 >> 8) & 0xFF,
2611 u->val1 & 0xFF );
sewardj4a7456e2002-03-24 13:52:19 +00002612 if (u->flags_w != FlagsEmpty)
2613 emit_put_eflags();
sewardjde4a1d02002-03-22 01:27:54 +00002614 break;
2615
2616 default:
2617 VG_(printf)("emitUInstr: unhandled insn:\n");
2618 VG_(ppUInstr)(0,u);
2619 VG_(panic)("emitUInstr: unimplemented opcode");
2620 }
2621
2622}
2623
2624
2625/* Emit x86 for the ucode in cb, returning the address of the
2626 generated code and setting *nbytes to its size. */
2627UChar* VG_(emit_code) ( UCodeBlock* cb, Int* nbytes )
2628{
2629 Int i;
2630 emitted_code_used = 0;
2631 emitted_code_size = 500; /* reasonable initial size */
2632 emitted_code = VG_(jitmalloc)(emitted_code_size);
2633
2634 if (dis) VG_(printf)("Generated code:\n");
2635
2636 for (i = 0; i < cb->used; i++) {
2637 if (cb->instrs[i].opcode != NOP) {
2638 UInstr* u = &cb->instrs[i];
2639# if 1
2640 /* Check on the sanity of this insn. */
2641 Bool sane = VG_(saneUInstr)( False, u );
2642 if (!sane) {
2643 VG_(printf)("\ninsane instruction\n");
2644 VG_(ppUInstr)( i, u );
2645 }
2646 vg_assert(sane);
2647# endif
2648# if 0
2649 /* Pass args to TAG1/TAG2 to vg_DebugFn for sanity checking.
2650 Requires a suitable definition of vg_DebugFn. */
2651 if (u->opcode == TAG1) {
2652 UInstr t1;
2653 vg_assert(u->tag1 == RealReg);
2654 VG_(emptyUInstr)( &t1 );
2655 t1.opcode = TAG2;
2656 t1.tag1 = t1.tag2 = RealReg;
2657 t1.val1 = t1.val2 = u->val1;
2658 t1.tag3 = Lit16;
2659 t1.val3 = VgT_DebugFn;
2660 emitUInstr( i, &t1 );
2661 }
2662 if (u->opcode == TAG2) {
2663 UInstr t1;
2664 vg_assert(u->tag1 == RealReg);
2665 vg_assert(u->tag2 == RealReg);
2666 VG_(emptyUInstr)( &t1 );
2667 t1.opcode = TAG2;
2668 t1.tag1 = t1.tag2 = RealReg;
2669 t1.val1 = t1.val2 = u->val1;
2670 t1.tag3 = Lit16;
2671 t1.val3 = VgT_DebugFn;
2672 if (u->val3 == VgT_UifU1 || u->val3 == VgT_UifU2
2673 || u->val3 == VgT_UifU4 || u->val3 == VgT_DifD1
2674 || u->val3 == VgT_DifD2 || u->val3 == VgT_DifD4)
2675 emitUInstr( i, &t1 );
2676 t1.val1 = t1.val2 = u->val2;
2677 emitUInstr( i, &t1 );
2678 }
2679# endif
2680 emitUInstr( i, u );
2681 }
2682 }
2683
2684 /* Returns a pointer to the emitted code. This will have to be
2685 copied by the caller into the translation cache, and then freed
2686 using VG_(jitfree). */
2687 *nbytes = emitted_code_used;
2688 return emitted_code;
2689}
2690
2691/*--------------------------------------------------------------------*/
2692/*--- end vg_from_ucode.c ---*/
2693/*--------------------------------------------------------------------*/