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