diff options
author | bellard <bellard@c046a42c-6fe2-441c-8c8c-71466251a162> | 2003-03-03 14:32:43 +0000 |
---|---|---|
committer | bellard <bellard@c046a42c-6fe2-441c-8c8c-71466251a162> | 2003-03-03 14:32:43 +0000 |
commit | 0ecfa9930c7615503ba629a61f7b94a0c3305af5 (patch) | |
tree | e9b87ad13ee9b77cb7c5b5082ad61d877232db7e /translate-i386.c | |
parent | ba1c6e37fc5efc0f3d1e50d0760f9f4a1061187b (diff) |
prints hello world
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@17 c046a42c-6fe2-441c-8c8c-71466251a162
Diffstat (limited to 'translate-i386.c')
-rw-r--r-- | translate-i386.c | 132 |
1 files changed, 124 insertions, 8 deletions
diff --git a/translate-i386.c b/translate-i386.c index 9ebc81e2ce..eb621c3e72 100644 --- a/translate-i386.c +++ b/translate-i386.c @@ -5,12 +5,24 @@ #include <inttypes.h> #include <assert.h> +/* dump all code */ +#define DEBUG_DISAS +#define DEBUG_LOGFILE "/tmp/gemu.log" + +#ifdef DEBUG_DISAS +#include "dis-asm.h" +#endif + #define IN_OP_I386 #include "cpu-i386.h" static uint8_t *gen_code_ptr; int __op_param1, __op_param2, __op_param3; +#ifdef DEBUG_DISAS +static FILE *logfile = NULL; +#endif + /* supress that */ static void error(const char *fmt, ...) { @@ -704,6 +716,9 @@ static void gen_lea_modrm(DisasContext *s, int modrm, int *reg_ptr, int *offset_ int reg1, reg2, opreg; int mod, rm, code; +#ifdef DEBUG_DISAS + fprintf(logfile, "modrm=0x%x\n", modrm); +#endif mod = (modrm >> 6) & 3; rm = modrm & 7; @@ -716,6 +731,9 @@ static void gen_lea_modrm(DisasContext *s, int modrm, int *reg_ptr, int *offset_ if (base == 4) { havesib = 1; code = ldub(s->pc++); +#ifdef DEBUG_DISAS + fprintf(logfile, "sib=0x%x\n", code); +#endif scale = (code >> 6) & 3; index = (code >> 3) & 7; base = code & 7; @@ -762,6 +780,7 @@ static void gen_lea_modrm(DisasContext *s, int modrm, int *reg_ptr, int *offset_ } else if (scale == 0 && disp == 0) { gen_op_movl_A0_reg[reg1](); } else { + gen_op_movl_A0_im(disp); gen_op_addl_A0_reg_sN[scale][reg1](); } } else { @@ -953,8 +972,10 @@ static void gen_setcc(DisasContext *s, int b) } } -/* return the size of the intruction. Return -1 if no insn found */ -int disas_insn(DisasContext *s, uint8_t *pc_start) +/* return the next pc address. Return -1 if no insn found. *is_jmp_ptr + is set to true if the instruction sets the PC (last instruction of + a basic block) */ +long disas_insn(DisasContext *s, uint8_t *pc_start, int *is_jmp_ptr) { int b, prefixes, aflag, dflag; int shift, ot; @@ -967,6 +988,9 @@ int disas_insn(DisasContext *s, uint8_t *pc_start) // cur_pc = s->pc; /* for insn generation */ next_byte: b = ldub(s->pc); +#ifdef DEBUG_DISAS + fprintf(logfile, "ib=0x%02x\n", b); +#endif if (b < 0) return -1; s->pc++; @@ -1195,6 +1219,7 @@ int disas_insn(DisasContext *s, uint8_t *pc_start) gen_op_mull_EAX_T0(); break; } + s->cc_op = CC_OP_MUL; break; case 5: /* imul */ switch(ot) { @@ -1209,6 +1234,7 @@ int disas_insn(DisasContext *s, uint8_t *pc_start) gen_op_imull_EAX_T0(); break; } + s->cc_op = CC_OP_MUL; break; case 6: /* div */ switch(ot) { @@ -1281,9 +1307,11 @@ int disas_insn(DisasContext *s, uint8_t *pc_start) gen_op_movl_T1_im((long)s->pc); gen_op_pushl_T1(); gen_op_jmp_T0(); + *is_jmp_ptr = 1; break; case 4: /* jmp Ev */ gen_op_jmp_T0(); + *is_jmp_ptr = 1; break; case 6: /* push Ev */ gen_op_pushl_T0(); @@ -1362,6 +1390,7 @@ int disas_insn(DisasContext *s, uint8_t *pc_start) op_imulw_T0_T1(); } gen_op_mov_reg_T0[ot][reg](); + s->cc_op = CC_OP_MUL; break; /**************************/ @@ -1418,10 +1447,14 @@ int disas_insn(DisasContext *s, uint8_t *pc_start) ot = dflag ? OT_LONG : OT_WORD; modrm = ldub(s->pc++); mod = (modrm >> 6) & 3; - + if (mod != 3) + gen_lea_modrm(s, modrm, ®_addr, &offset_addr); val = insn_get(s, ot); gen_op_movl_T0_im(val); - gen_ldst_modrm(s, modrm, ot, OR_TMP0, 1); + if (mod != 3) + gen_op_st_T0_A0[ot](); + else + gen_op_mov_reg_T0[ot][modrm & 7](); break; case 0x8a: case 0x8b: /* mov Ev, Gv */ @@ -2068,10 +2101,12 @@ int disas_insn(DisasContext *s, uint8_t *pc_start) gen_op_popl_T0(); gen_op_addl_ESP_im(val); gen_op_jmp_T0(); + *is_jmp_ptr = 1; break; case 0xc3: /* ret */ gen_op_popl_T0(); gen_op_jmp_T0(); + *is_jmp_ptr = 1; break; case 0xe8: /* call */ val = insn_get(s, OT_LONG); @@ -2079,16 +2114,19 @@ int disas_insn(DisasContext *s, uint8_t *pc_start) gen_op_movl_T1_im((long)s->pc); gen_op_pushl_T1(); gen_op_jmp_im(val); + *is_jmp_ptr = 1; break; case 0xe9: /* jmp */ val = insn_get(s, OT_LONG); val += (long)s->pc; gen_op_jmp_im(val); + *is_jmp_ptr = 1; break; case 0xeb: /* jmp Jb */ val = (int8_t)insn_get(s, OT_BYTE); val += (long)s->pc; gen_op_jmp_im(val); + *is_jmp_ptr = 1; break; case 0x70 ... 0x7f: /* jcc Jb */ val = (int8_t)insn_get(s, OT_BYTE); @@ -2103,6 +2141,7 @@ int disas_insn(DisasContext *s, uint8_t *pc_start) val += (long)s->pc; /* XXX: fix 16 bit wrap */ do_jcc: gen_jcc(s, b, val); + *is_jmp_ptr = 1; break; case 0x190 ... 0x19f: @@ -2164,8 +2203,23 @@ int disas_insn(DisasContext *s, uint8_t *pc_start) /* misc */ case 0x90: /* nop */ break; - -#if 0 + case 0xcc: /* int3 */ + gen_op_int3((long)pc_start); + *is_jmp_ptr = 1; + break; + case 0xcd: /* int N */ + val = ldub(s->pc++); + /* XXX: currently we ignore the interrupt number */ + gen_op_int_im((long)pc_start); + *is_jmp_ptr = 1; + break; + case 0xce: /* into */ + if (s->cc_op != CC_OP_DYNAMIC) + gen_op_set_cc_op(s->cc_op); + gen_op_into((long)pc_start, (long)s->pc); + *is_jmp_ptr = 1; + break; +#if 0 case 0x1a2: /* cpuid */ gen_insn0(OP_ASM); break; @@ -2182,16 +2236,78 @@ int cpu_x86_gen_code(uint8_t *gen_code_buf, int *gen_code_size_ptr, uint8_t *pc_start) { DisasContext dc1, *dc = &dc1; + int is_jmp; long ret; +#ifdef DEBUG_DISAS + struct disassemble_info disasm_info; +#endif + dc->cc_op = CC_OP_DYNAMIC; gen_code_ptr = gen_code_buf; gen_start(); - ret = disas_insn(dc, pc_start); + +#ifdef DEBUG_DISAS + if (!logfile) { + logfile = fopen(DEBUG_LOGFILE, "w"); + if (!logfile) { + perror(DEBUG_LOGFILE); + exit(1); + } + setvbuf(logfile, NULL, _IOLBF, 0); + } + + INIT_DISASSEMBLE_INFO(disasm_info, logfile, fprintf); + disasm_info.buffer = pc_start; + disasm_info.buffer_vma = (unsigned long)pc_start; + disasm_info.buffer_length = 15; +#if 0 + disasm_info.flavour = bfd_get_flavour (abfd); + disasm_info.arch = bfd_get_arch (abfd); + disasm_info.mach = bfd_get_mach (abfd); +#endif +#ifdef WORDS_BIGENDIAN + disasm_info.endian = BFD_ENDIAN_BIG; +#else + disasm_info.endian = BFD_ENDIAN_LITTLE; +#endif + fprintf(logfile, "IN:\n"); + fprintf(logfile, "0x%08lx: ", (long)pc_start); + print_insn_i386((unsigned long)pc_start, &disasm_info); + fprintf(logfile, "\n\n"); +#endif + is_jmp = 0; + ret = disas_insn(dc, pc_start, &is_jmp); if (ret == -1) error("unknown instruction at PC=0x%x", pc_start); + /* we must store the eflags state if it is not already done */ + if (dc->cc_op != CC_OP_DYNAMIC) + gen_op_set_cc_op(dc->cc_op); + if (!is_jmp) { + /* we add an additionnal jmp to update the simulated PC */ + gen_op_jmp_im(ret); + } gen_end(); *gen_code_size_ptr = gen_code_ptr - gen_code_buf; - printf("0x%08lx: code_size = %d\n", (long)pc_start, *gen_code_size_ptr); + +#ifdef DEBUG_DISAS + { + uint8_t *pc; + int count; + + pc = gen_code_buf; + disasm_info.buffer = pc; + disasm_info.buffer_vma = (unsigned long)pc; + disasm_info.buffer_length = *gen_code_size_ptr; + fprintf(logfile, "OUT: [size=%d]\n", *gen_code_size_ptr); + while (pc < gen_code_ptr) { + fprintf(logfile, "0x%08lx: ", (long)pc); + count = print_insn_i386((unsigned long)pc, &disasm_info); + fprintf(logfile, "\n"); + pc += count; + } + fprintf(logfile, "\n"); + } +#endif return 0; } |