prints hello world

git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@17 c046a42c-6fe2-441c-8c8c-71466251a162
This commit is contained in:
bellard 2003-03-03 14:32:43 +00:00
parent ba1c6e37fc
commit 0ecfa9930c
6 changed files with 288 additions and 256 deletions

View File

@ -30,16 +30,19 @@ endif
#########################################################
DEFINES+=-D_GNU_SOURCE -DGEMU -DDOSEMU -DNO_TRACE_MSGS
DEFINES+=-D_GNU_SOURCE
DEFINES+=-DCONFIG_PREFIX=\"/usr/local\"
LDSCRIPT=$(ARCH).ld
LIBS+=-ldl -lm
OBJS= i386/fp87.o i386/interp_main.o i386/interp_modrm.o i386/interp_16_32.o \
i386/interp_32_16.o i386/interp_32_32.o i386/emu-utils.o \
i386/dis8086.o i386/emu-ldt.o
#DEFINES+= -DGEMU -DDOSEMU -DNO_TRACE_MSGS
#OBJS= i386/fp87.o i386/interp_main.o i386/interp_modrm.o i386/interp_16_32.o \
# i386/interp_32_16.o i386/interp_32_32.o i386/emu-utils.o \
# i386/dis8086.o i386/emu-ldt.o
OBJS+=translate-i386.o op-i386.o
OBJS+= elfload.o main.o thunk.o syscall.o
# NOTE: the disassembler code is only needed for debugging
OBJS+=i386-dis.o dis-buf.o
SRCS = $(OBJS:.o=.c)
all: gemu

View File

@ -1,6 +1,11 @@
/* NOTE: this header is included in op-i386.c where global register
variable are used. Care must be used when including glibc headers.
*/
#ifndef CPU_I386_H
#define CPU_I386_H
#include <setjmp.h>
#define R_EAX 0
#define R_ECX 1
#define R_EDX 2
@ -43,6 +48,27 @@
#define VM_FLAG 0x20000
/* AC 0x40000 */
#define EXCP00_DIVZ 1
#define EXCP01_SSTP 2
#define EXCP02_NMI 3
#define EXCP03_INT3 4
#define EXCP04_INTO 5
#define EXCP05_BOUND 6
#define EXCP06_ILLOP 7
#define EXCP07_PREX 8
#define EXCP08_DBLE 9
#define EXCP09_XERR 10
#define EXCP0A_TSS 11
#define EXCP0B_NOSEG 12
#define EXCP0C_STACK 13
#define EXCP0D_GPF 14
#define EXCP0E_PAGE 15
#define EXCP10_COPR 17
#define EXCP11_ALGN 18
#define EXCP12_MCHK 19
#define EXCP_SIGNAL 256 /* async signal */
enum {
CC_OP_DYNAMIC, /* must use dynamic code to get cc_op */
CC_OP_EFLAGS, /* all cc are explicitely computed, CC_SRC = flags */
@ -89,27 +115,34 @@ typedef struct CPUX86State {
/* standard registers */
uint32_t regs[8];
uint32_t pc; /* cs_case + eip value */
/* eflags handling */
uint32_t eflags;
/* emulator internal eflags handling */
uint32_t cc_src;
uint32_t cc_dst;
uint32_t cc_op;
int32_t df; /* D flag : 1 if D = 0, -1 if D = 1 */
/* segments */
uint8_t *segs_base[6];
uint32_t segs[6];
/* FPU state */
CPU86_LDouble fpregs[8];
uint8_t fptags[8]; /* 0 = valid, 1 = empty */
unsigned int fpstt; /* top of stack index */
unsigned int fpus;
unsigned int fpuc;
uint8_t fptags[8]; /* 0 = valid, 1 = empty */
CPU86_LDouble fpregs[8];
/* segments */
uint32_t segs[6];
/* emulator internal variables */
CPU86_LDouble ft0;
/* exception handling */
jmp_buf jmp_env;
int exception_index;
} CPUX86State;
static inline int ldub(void *ptr)

View File

@ -21,10 +21,11 @@
#include <stdio.h>
#include <stdarg.h>
#include <errno.h>
#include <unistd.h>
#include "gemu.h"
#include "i386/hsw_interp.h"
#include "cpu-i386.h"
unsigned long x86_stack_size;
unsigned long stktop;
@ -38,160 +39,8 @@ void gemu_log(const char *fmt, ...)
va_end(ap);
}
/* virtual x86 CPU stuff */
extern int invoke_code16(Interp_ENV *, int, int);
extern int invoke_code32(Interp_ENV *, int);
extern char *e_print_cpuemu_regs(ENVPARAMS, int is32);
extern char *e_emu_disasm(ENVPARAMS, unsigned char *org, int is32);
extern void init_npu(void);
Interp_ENV env_global;
Interp_ENV *envp_global;
QWORD EMUtime = 0;
int CEmuStat = 0;
long instr_count;
/* who will initialize this? */
unsigned long io_bitmap[IO_BITMAP_SIZE+1];
/* debug flag, 0=disable 1..9=level */
int d_emu = 0;
unsigned long CRs[5] =
{
0x00000013, /* valid bits: 0xe005003f */
0x00000000, /* invalid */
0x00000000,
0x00000000,
0x00000000
};
/*
* DR0-3 = linear address of breakpoint 0-3
* DR4=5 = reserved
* DR6 b0-b3 = BP active
* b13 = BD
* b14 = BS
* b15 = BT
* DR7 b0-b1 = G:L bp#0
* b2-b3 = G:L bp#1
* b4-b5 = G:L bp#2
* b6-b7 = G:L bp#3
* b8-b9 = GE:LE
* b13 = GD
* b16-19= LLRW bp#0 LL=00(1),01(2),11(4)
* b20-23= LLRW bp#1 RW=00(x),01(w),11(rw)
* b24-27= LLRW bp#2
* b28-31= LLRW bp#3
*/
unsigned long DRs[8] =
{
0x00000000,
0x00000000,
0x00000000,
0x00000000,
0xffff1ff0,
0x00000400,
0xffff1ff0,
0x00000400
};
unsigned long TRs[2] =
{
0x00000000,
0x00000000
};
void FatalAppExit(UINT wAction, LPCSTR lpText)
{
fprintf(stderr, "Fatal error '%s' in CPU\n", lpText);
exit(1);
}
int e_debug_check(unsigned char *PC)
{
register unsigned long d7 = DRs[7];
if (d7&0x03) {
if (d7&0x30000) return 0; /* only execute(00) bkp */
if ((long)PC==DRs[0]) {
e_printf("DBRK: DR0 hit at %p\n",PC);
DRs[6] |= 1;
return 1;
}
}
if (d7&0x0c) {
if (d7&0x300000) return 0;
if ((long)PC==DRs[1]) {
e_printf("DBRK: DR1 hit at %p\n",PC);
DRs[6] |= 2;
return 1;
}
}
if (d7&0x30) {
if (d7&0x3000000) return 0;
if ((long)PC==DRs[2]) {
e_printf("DBRK: DR2 hit at %p\n",PC);
DRs[6] |= 4;
return 1;
}
}
if (d7&0xc0) {
if (d7&0x30000000) return 0;
if ((long)PC==DRs[3]) {
e_printf("DBRK: DR3 hit at %p\n",PC);
DRs[6] |= 8;
return 1;
}
}
return 0;
}
/* Debug stuff */
void logstr(unsigned long mask, const char *fmt,...)
{
va_list ap;
va_start(ap, fmt);
vfprintf(stderr, fmt, ap);
va_end(ap);
}
/* unconditional message into debug log and stderr */
#undef error
void error(const char *fmt, ...)
{
va_list ap;
va_start(ap, fmt);
vfprintf(stderr, fmt, ap);
va_end(ap);
exit(1);
}
int PortIO(DWORD port, DWORD value, UINT size, BOOL is_write)
{
fprintf(stderr, "IO: %s port=0x%lx value=0x%lx size=%d",
is_write ? "write" : "read", port, value, size);
return value;
}
void LogProcName(WORD wSel, WORD wOff, WORD wAction)
{
}
void INT_handler(int num, void *env)
{
fprintf(stderr, "EM86: int %d\n", num);
}
/***********************************************************/
/* new CPU core */
/* CPUX86 core interface */
void cpu_x86_outb(int addr, int val)
{
@ -245,7 +94,7 @@ int main(int argc, char **argv)
const char *filename;
struct target_pt_regs regs1, *regs = &regs1;
struct image_info info1, *info = &info1;
Interp_ENV *env;
CPUX86State *env;
if (argc <= 1)
usage();
@ -277,26 +126,25 @@ int main(int argc, char **argv)
target_set_brk((char *)info->brk);
syscall_init();
env = &env_global;
envp_global = env;
memset(env, 0, sizeof(Interp_ENV));
env = cpu_x86_init();
env->rax.e = regs->eax;
env->rbx.e = regs->ebx;
env->rcx.e = regs->ecx;
env->rdx.e = regs->edx;
env->rsi.esi = regs->esi;
env->rdi.edi = regs->edi;
env->rbp.ebp = regs->ebp;
env->rsp.esp = regs->esp;
env->cs.cs = __USER_CS;
env->ds.ds = __USER_DS;
env->es.es = __USER_DS;
env->ss.ss = __USER_DS;
env->fs.fs = __USER_DS;
env->gs.gs = __USER_DS;
env->trans_addr = regs->eip;
env->regs[R_EAX] = regs->eax;
env->regs[R_EBX] = regs->ebx;
env->regs[R_ECX] = regs->ecx;
env->regs[R_EDX] = regs->edx;
env->regs[R_ESI] = regs->esi;
env->regs[R_EDI] = regs->edi;
env->regs[R_EBP] = regs->ebp;
env->regs[R_ESP] = regs->esp;
env->segs[R_CS] = __USER_CS;
env->segs[R_DS] = __USER_DS;
env->segs[R_ES] = __USER_DS;
env->segs[R_SS] = __USER_DS;
env->segs[R_FS] = __USER_DS;
env->segs[R_GS] = __USER_DS;
env->pc = regs->eip;
#if 0
LDT[__USER_CS >> 3].w86Flags = DF_PRESENT | DF_PAGES | DF_32;
LDT[__USER_CS >> 3].dwSelLimit = 0xfffff;
LDT[__USER_CS >> 3].lpSelBase = NULL;
@ -304,41 +152,34 @@ int main(int argc, char **argv)
LDT[__USER_DS >> 3].w86Flags = DF_PRESENT | DF_PAGES | DF_32;
LDT[__USER_DS >> 3].dwSelLimit = 0xfffff;
LDT[__USER_DS >> 3].lpSelBase = NULL;
init_npu();
build_decode_tables();
#endif
for(;;) {
int err;
uint8_t *pc;
err = invoke_code32(env, -1);
env->trans_addr = env->return_addr;
pc = env->seg_regs[0] + env->trans_addr;
err = cpu_x86_exec(env);
switch(err) {
case EXCP0D_GPF:
pc = (uint8_t *)env->pc;
if (pc[0] == 0xcd && pc[1] == 0x80) {
/* syscall */
env->trans_addr += 2;
env->rax.e = do_syscall(env->rax.e,
env->rbx.e,
env->rcx.e,
env->rdx.e,
env->rsi.esi,
env->rdi.edi,
env->rbp.ebp);
env->pc += 2;
env->regs[R_EAX] = do_syscall(env->regs[R_EAX],
env->regs[R_EBX],
env->regs[R_ECX],
env->regs[R_EDX],
env->regs[R_ESI],
env->regs[R_EDI],
env->regs[R_EBP]);
} else {
goto trap_error;
}
break;
default:
trap_error:
fprintf(stderr, "GEMU: Unknown error %d, aborting\n", err);
#ifndef NO_TRACE_MSGS
d_emu = 9;
fprintf(stderr, "%s\n%s\n",
e_print_cpuemu_regs(env, 1),
e_emu_disasm(env,pc,1));
#endif
fprintf(stderr, "0x%08lx: Unknown exception %d, aborting\n",
(long)env->pc, err);
abort();
}
}

103
op-i386.c
View File

@ -10,11 +10,6 @@ typedef signed long long int64_t;
#define NULL 0
typedef struct FILE FILE;
extern FILE *stderr;
extern int fprintf(FILE *, const char *, ...);
#ifdef __i386__
register int T0 asm("esi");
register int T1 asm("ebx");
@ -91,6 +86,7 @@ typedef struct CCTable {
int (*compute_c)(void); /* return the C flag */
} CCTable;
/* NOTE: data are not static to force relocation generation by GCC */
extern CCTable cc_table[];
uint8_t parity_table[256] = {
@ -191,6 +187,14 @@ static inline int lshift(int x, int n)
return x >> (-n);
}
/* exception support */
/* NOTE: not static to force relocation generation by GCC */
void raise_exception(int exception_index)
{
env->exception_index = exception_index;
longjmp(env->jmp_env, 1);
}
/* we define the various pieces of code used by the JIT */
#define REG EAX
@ -321,7 +325,6 @@ void OPPROTO op_decl_T0_cc(void)
void OPPROTO op_testl_T0_T1_cc(void)
{
CC_SRC = T0;
CC_DST = T0 & T1;
}
@ -555,6 +558,7 @@ void OPPROTO op_stl_T0_A0(void)
/* jumps */
/* indirect jump */
void OPPROTO op_jmp_T0(void)
{
PC = T0;
@ -565,6 +569,30 @@ void OPPROTO op_jmp_im(void)
PC = PARAM1;
}
void OPPROTO op_int_im(void)
{
PC = PARAM1;
raise_exception(EXCP0D_GPF);
}
void OPPROTO op_int3(void)
{
PC = PARAM1;
raise_exception(EXCP03_INT3);
}
void OPPROTO op_into(void)
{
int eflags;
eflags = cc_table[CC_OP].compute_all();
if (eflags & CC_O) {
PC = PARAM1;
raise_exception(EXCP04_INTO);
} else {
PC = PARAM2;
}
}
/* string ops */
#define ldul ldl
@ -663,17 +691,19 @@ void OPPROTO op_jo_cc(void)
int eflags;
eflags = cc_table[CC_OP].compute_all();
if (eflags & CC_O)
PC += PARAM1;
PC = PARAM1;
else
PC += PARAM2;
PC = PARAM2;
FORCE_RET();
}
void OPPROTO op_jb_cc(void)
{
if (cc_table[CC_OP].compute_c())
PC += PARAM1;
PC = PARAM1;
else
PC += PARAM2;
PC = PARAM2;
FORCE_RET();
}
void OPPROTO op_jz_cc(void)
@ -681,9 +711,10 @@ void OPPROTO op_jz_cc(void)
int eflags;
eflags = cc_table[CC_OP].compute_all();
if (eflags & CC_Z)
PC += PARAM1;
PC = PARAM1;
else
PC += PARAM2;
PC = PARAM2;
FORCE_RET();
}
void OPPROTO op_jbe_cc(void)
@ -691,9 +722,10 @@ void OPPROTO op_jbe_cc(void)
int eflags;
eflags = cc_table[CC_OP].compute_all();
if (eflags & (CC_Z | CC_C))
PC += PARAM1;
PC = PARAM1;
else
PC += PARAM2;
PC = PARAM2;
FORCE_RET();
}
void OPPROTO op_js_cc(void)
@ -701,9 +733,10 @@ void OPPROTO op_js_cc(void)
int eflags;
eflags = cc_table[CC_OP].compute_all();
if (eflags & CC_S)
PC += PARAM1;
PC = PARAM1;
else
PC += PARAM2;
PC = PARAM2;
FORCE_RET();
}
void OPPROTO op_jp_cc(void)
@ -711,9 +744,10 @@ void OPPROTO op_jp_cc(void)
int eflags;
eflags = cc_table[CC_OP].compute_all();
if (eflags & CC_P)
PC += PARAM1;
PC = PARAM1;
else
PC += PARAM2;
PC = PARAM2;
FORCE_RET();
}
void OPPROTO op_jl_cc(void)
@ -721,9 +755,10 @@ void OPPROTO op_jl_cc(void)
int eflags;
eflags = cc_table[CC_OP].compute_all();
if ((eflags ^ (eflags >> 4)) & 0x80)
PC += PARAM1;
PC = PARAM1;
else
PC += PARAM2;
PC = PARAM2;
FORCE_RET();
}
void OPPROTO op_jle_cc(void)
@ -731,9 +766,10 @@ void OPPROTO op_jle_cc(void)
int eflags;
eflags = cc_table[CC_OP].compute_all();
if (((eflags ^ (eflags >> 4)) & 0x80) || (eflags & CC_Z))
PC += PARAM1;
PC = PARAM1;
else
PC += PARAM2;
PC = PARAM2;
FORCE_RET();
}
/* slow set cases (compute x86 flags) */
@ -1600,14 +1636,13 @@ void OPPROTO op_fcos(void)
/* main execution loop */
uint8_t code_gen_buffer[65536];
int cpu_x86_exec(CPUX86State *env1)
{
int saved_T0, saved_T1, saved_A0;
CPUX86State *saved_env;
int code_gen_size;
int code_gen_size, ret;
void (*gen_func)(void);
/* first we save global registers */
saved_T0 = T0;
saved_T1 = T1;
@ -1615,17 +1650,21 @@ int cpu_x86_exec(CPUX86State *env1)
saved_env = env;
env = env1;
for(;;) {
cpu_x86_gen_code(code_gen_buffer, &code_gen_size, (uint8_t *)env->pc);
/* execute the generated code */
gen_func = (void *)code_gen_buffer;
gen_func();
/* prepare setjmp context for exception handling */
if (setjmp(env->jmp_env) == 0) {
for(;;) {
cpu_x86_gen_code(code_gen_buffer, &code_gen_size, (uint8_t *)env->pc);
/* execute the generated code */
gen_func = (void *)code_gen_buffer;
gen_func();
}
}
ret = env->exception_index;
/* restore global registers */
T0 = saved_T0;
T1 = saved_T1;
A0 = saved_A0;
env = saved_env;
return 0;
return ret;
}

View File

@ -149,18 +149,18 @@ void OPPROTO glue(op_jb_sub, SUFFIX)(void)
src2 = CC_SRC - CC_DST;
if ((DATA_TYPE)src1 < (DATA_TYPE)src2)
PC += PARAM1;
PC = PARAM1;
else
PC += PARAM2;
PC = PARAM2;
FORCE_RET();
}
void OPPROTO glue(op_jz_sub, SUFFIX)(void)
{
if ((DATA_TYPE)CC_DST != 0)
PC += PARAM1;
PC = PARAM1;
else
PC += PARAM2;
PC = PARAM2;
FORCE_RET();
}
@ -171,18 +171,18 @@ void OPPROTO glue(op_jbe_sub, SUFFIX)(void)
src2 = CC_SRC - CC_DST;
if ((DATA_TYPE)src1 <= (DATA_TYPE)src2)
PC += PARAM1;
PC = PARAM1;
else
PC += PARAM2;
PC = PARAM2;
FORCE_RET();
}
void OPPROTO glue(op_js_sub, SUFFIX)(void)
{
if (CC_DST & SIGN_MASK)
PC += PARAM1;
PC = PARAM1;
else
PC += PARAM2;
PC = PARAM2;
FORCE_RET();
}
@ -193,9 +193,9 @@ void OPPROTO glue(op_jl_sub, SUFFIX)(void)
src2 = CC_SRC - CC_DST;
if ((DATA_STYPE)src1 < (DATA_STYPE)src2)
PC += PARAM1;
PC = PARAM1;
else
PC += PARAM2;
PC = PARAM2;
FORCE_RET();
}
@ -206,9 +206,9 @@ void OPPROTO glue(op_jle_sub, SUFFIX)(void)
src2 = CC_SRC - CC_DST;
if ((DATA_STYPE)src1 <= (DATA_STYPE)src2)
PC += PARAM1;
PC = PARAM1;
else
PC += PARAM2;
PC = PARAM2;
FORCE_RET();
}

View File

@ -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, &reg_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;
}