added cmpxchg8b, cpuid, bound, eflags support, vm86 mode, 16bit/override string ops

git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@55 c046a42c-6fe2-441c-8c8c-71466251a162
This commit is contained in:
bellard 2003-03-29 16:51:35 +00:00
parent 24f9e90b0e
commit 9c605cb135
1 changed files with 204 additions and 180 deletions

View File

@ -76,21 +76,16 @@ static void inline flush_icache_range(unsigned long start, unsigned long stop)
extern FILE *logfile; extern FILE *logfile;
extern int loglevel; extern int loglevel;
#define PREFIX_REPZ 1 #define PREFIX_REPZ 0x01
#define PREFIX_REPNZ 2 #define PREFIX_REPNZ 0x02
#define PREFIX_LOCK 4 #define PREFIX_LOCK 0x04
#define PREFIX_CS 8 #define PREFIX_DATA 0x08
#define PREFIX_SS 0x10 #define PREFIX_ADR 0x10
#define PREFIX_DS 0x20 #define PREFIX_FWAIT 0x20
#define PREFIX_ES 0x40
#define PREFIX_FS 0x80
#define PREFIX_GS 0x100
#define PREFIX_DATA 0x200
#define PREFIX_ADR 0x400
#define PREFIX_FWAIT 0x800
typedef struct DisasContext { typedef struct DisasContext {
/* current insn context */ /* current insn context */
int override; /* -1 if no override */
int prefix; int prefix;
int aflag, dflag; int aflag, dflag;
uint8_t *pc; /* pc = eip + cs_base */ uint8_t *pc; /* pc = eip + cs_base */
@ -103,6 +98,7 @@ typedef struct DisasContext {
int cc_op; /* current CC operation */ int cc_op; /* current CC operation */
int addseg; /* non zero if either DS/ES/SS have a non zero base */ int addseg; /* non zero if either DS/ES/SS have a non zero base */
int f_st; /* currently unused */ int f_st; /* currently unused */
int vm86; /* vm86 mode */
} DisasContext; } DisasContext;
/* i386 arith/logic operations */ /* i386 arith/logic operations */
@ -130,7 +126,7 @@ enum {
}; };
enum { enum {
#define DEF(s) INDEX_op_ ## s, #define DEF(s, n) INDEX_op_ ## s,
#include "opc-i386.h" #include "opc-i386.h"
#undef DEF #undef DEF
NB_OPS, NB_OPS,
@ -556,76 +552,100 @@ static GenOpFunc *gen_op_st_T0_A0[3] = {
gen_op_stl_T0_A0, gen_op_stl_T0_A0,
}; };
static GenOpFunc *gen_op_movs[6] = { /* the _a32 and _a16 string operations use A0 as the base register. */
gen_op_movsb,
gen_op_movsw, #define STRINGOP(x) \
gen_op_movsl, gen_op_ ## x ## b_fast, \
gen_op_rep_movsb, gen_op_ ## x ## w_fast, \
gen_op_rep_movsw, gen_op_ ## x ## l_fast, \
gen_op_rep_movsl, gen_op_ ## x ## b_a32, \
gen_op_ ## x ## w_a32, \
gen_op_ ## x ## l_a32, \
gen_op_ ## x ## b_a16, \
gen_op_ ## x ## w_a16, \
gen_op_ ## x ## l_a16,
static GenOpFunc *gen_op_movs[9 * 2] = {
STRINGOP(movs)
STRINGOP(rep_movs)
}; };
static GenOpFunc *gen_op_stos[6] = { static GenOpFunc *gen_op_stos[9 * 2] = {
gen_op_stosb, STRINGOP(stos)
gen_op_stosw, STRINGOP(rep_stos)
gen_op_stosl,
gen_op_rep_stosb,
gen_op_rep_stosw,
gen_op_rep_stosl,
}; };
static GenOpFunc *gen_op_lods[6] = { static GenOpFunc *gen_op_lods[9 * 2] = {
gen_op_lodsb, STRINGOP(lods)
gen_op_lodsw, STRINGOP(rep_lods)
gen_op_lodsl,
gen_op_rep_lodsb,
gen_op_rep_lodsw,
gen_op_rep_lodsl,
}; };
static GenOpFunc *gen_op_scas[9] = { static GenOpFunc *gen_op_scas[9 * 3] = {
gen_op_scasb, STRINGOP(scas)
gen_op_scasw, STRINGOP(repz_scas)
gen_op_scasl, STRINGOP(repnz_scas)
gen_op_repz_scasb,
gen_op_repz_scasw,
gen_op_repz_scasl,
gen_op_repnz_scasb,
gen_op_repnz_scasw,
gen_op_repnz_scasl,
}; };
static GenOpFunc *gen_op_cmps[9] = { static GenOpFunc *gen_op_cmps[9 * 3] = {
gen_op_cmpsb, STRINGOP(cmps)
gen_op_cmpsw, STRINGOP(repz_cmps)
gen_op_cmpsl, STRINGOP(repnz_cmps)
gen_op_repz_cmpsb,
gen_op_repz_cmpsw,
gen_op_repz_cmpsl,
gen_op_repnz_cmpsb,
gen_op_repnz_cmpsw,
gen_op_repnz_cmpsl,
}; };
static GenOpFunc *gen_op_ins[6] = { static GenOpFunc *gen_op_ins[9 * 2] = {
gen_op_insb, STRINGOP(ins)
gen_op_insw, STRINGOP(rep_ins)
gen_op_insl,
gen_op_rep_insb,
gen_op_rep_insw,
gen_op_rep_insl,
}; };
static GenOpFunc *gen_op_outs[6] = { static GenOpFunc *gen_op_outs[9 * 2] = {
gen_op_outsb, STRINGOP(outs)
gen_op_outsw, STRINGOP(rep_outs)
gen_op_outsl,
gen_op_rep_outsb,
gen_op_rep_outsw,
gen_op_rep_outsl,
}; };
static inline void gen_string_ds(DisasContext *s, int ot, GenOpFunc **func)
{
int index, override;
override = s->override;
if (s->aflag) {
/* 32 bit address */
if (s->addseg && override < 0)
override = R_DS;
if (override >= 0) {
gen_op_movl_A0_seg(offsetof(CPUX86State,seg_cache[override].base));
index = 3 + ot;
} else {
index = ot;
}
} else {
if (override < 0)
override = R_DS;
gen_op_movl_A0_seg(offsetof(CPUX86State,seg_cache[override].base));
/* 16 address, always override */
index = 6 + ot;
}
func[index]();
}
static inline void gen_string_es(DisasContext *s, int ot, GenOpFunc **func)
{
int index;
if (s->aflag) {
if (s->addseg) {
index = 3 + ot;
} else {
index = ot;
}
} else {
index = 6 + ot;
}
func[index]();
}
static GenOpFunc *gen_op_in[3] = { static GenOpFunc *gen_op_in[3] = {
gen_op_inb_T0_T1, gen_op_inb_T0_T1,
gen_op_inw_T0_T1, gen_op_inw_T0_T1,
@ -849,26 +869,10 @@ static void gen_lea_modrm(DisasContext *s, int modrm, int *reg_ptr, int *offset_
int opreg; int opreg;
int mod, rm, code, override, must_add_seg; int mod, rm, code, override, must_add_seg;
/* XXX: add a generation time variable to tell if base == 0 in DS/ES/SS */ override = s->override;
override = -1;
must_add_seg = s->addseg; must_add_seg = s->addseg;
if (s->prefix & (PREFIX_CS | PREFIX_SS | PREFIX_DS | if (override >= 0)
PREFIX_ES | PREFIX_FS | PREFIX_GS)) {
if (s->prefix & PREFIX_ES)
override = R_ES;
else if (s->prefix & PREFIX_CS)
override = R_CS;
else if (s->prefix & PREFIX_SS)
override = R_SS;
else if (s->prefix & PREFIX_DS)
override = R_DS;
else if (s->prefix & PREFIX_FS)
override = R_FS;
else
override = R_GS;
must_add_seg = 1; must_add_seg = 1;
}
mod = (modrm >> 6) & 3; mod = (modrm >> 6) & 3;
rm = modrm & 7; rm = modrm & 7;
@ -1343,7 +1347,7 @@ long disas_insn(DisasContext *s, uint8_t *pc_start)
prefixes = 0; prefixes = 0;
aflag = s->code32; aflag = s->code32;
dflag = s->code32; dflag = s->code32;
// cur_pc = s->pc; /* for insn generation */ s->override = -1;
next_byte: next_byte:
b = ldub(s->pc); b = ldub(s->pc);
s->pc++; s->pc++;
@ -1359,22 +1363,22 @@ long disas_insn(DisasContext *s, uint8_t *pc_start)
prefixes |= PREFIX_LOCK; prefixes |= PREFIX_LOCK;
goto next_byte; goto next_byte;
case 0x2e: case 0x2e:
prefixes |= PREFIX_CS; s->override = R_CS;
goto next_byte; goto next_byte;
case 0x36: case 0x36:
prefixes |= PREFIX_SS; s->override = R_SS;
goto next_byte; goto next_byte;
case 0x3e: case 0x3e:
prefixes |= PREFIX_DS; s->override = R_DS;
goto next_byte; goto next_byte;
case 0x26: case 0x26:
prefixes |= PREFIX_ES; s->override = R_ES;
goto next_byte; goto next_byte;
case 0x64: case 0x64:
prefixes |= PREFIX_FS; s->override = R_FS;
goto next_byte; goto next_byte;
case 0x65: case 0x65:
prefixes |= PREFIX_GS; s->override = R_GS;
goto next_byte; goto next_byte;
case 0x66: case 0x66:
prefixes |= PREFIX_DATA; prefixes |= PREFIX_DATA;
@ -1830,6 +1834,17 @@ long disas_insn(DisasContext *s, uint8_t *pc_start)
} }
s->cc_op = CC_OP_SUBB + ot; s->cc_op = CC_OP_SUBB + ot;
break; break;
case 0x1c7: /* cmpxchg8b */
modrm = ldub(s->pc++);
mod = (modrm >> 6) & 3;
if (mod == 3)
goto illegal_op;
if (s->cc_op != CC_OP_DYNAMIC)
gen_op_set_cc_op(s->cc_op);
gen_lea_modrm(s, modrm, &reg_addr, &offset_addr);
gen_op_cmpxchg8b();
s->cc_op = CC_OP_EFLAGS;
break;
/**************************/ /**************************/
/* push/pop */ /* push/pop */
@ -2027,8 +2042,7 @@ long disas_insn(DisasContext *s, uint8_t *pc_start)
modrm = ldub(s->pc++); modrm = ldub(s->pc++);
reg = (modrm >> 3) & 7; reg = (modrm >> 3) & 7;
/* we must ensure that no segment is added */ /* we must ensure that no segment is added */
s->prefix &= ~(PREFIX_CS | PREFIX_SS | PREFIX_DS | s->override = -1;
PREFIX_ES | PREFIX_FS | PREFIX_GS);
val = s->addseg; val = s->addseg;
s->addseg = 0; s->addseg = 0;
gen_lea_modrm(s, modrm, &reg_addr, &offset_addr); gen_lea_modrm(s, modrm, &reg_addr, &offset_addr);
@ -2050,26 +2064,14 @@ long disas_insn(DisasContext *s, uint8_t *pc_start)
offset_addr = insn_get(s, OT_WORD); offset_addr = insn_get(s, OT_WORD);
gen_op_movl_A0_im(offset_addr); gen_op_movl_A0_im(offset_addr);
/* handle override */ /* handle override */
/* XXX: factorize that */
{ {
int override, must_add_seg; int override, must_add_seg;
override = R_DS;
must_add_seg = s->addseg; must_add_seg = s->addseg;
if (s->prefix & (PREFIX_CS | PREFIX_SS | PREFIX_DS | if (s->override >= 0) {
PREFIX_ES | PREFIX_FS | PREFIX_GS)) { override = s->override;
if (s->prefix & PREFIX_ES)
override = R_ES;
else if (s->prefix & PREFIX_CS)
override = R_CS;
else if (s->prefix & PREFIX_SS)
override = R_SS;
else if (s->prefix & PREFIX_DS)
override = R_DS;
else if (s->prefix & PREFIX_FS)
override = R_FS;
else
override = R_GS;
must_add_seg = 1; must_add_seg = 1;
} else {
override = R_DS;
} }
if (must_add_seg) { if (must_add_seg) {
gen_op_addl_A0_seg(offsetof(CPUX86State,seg_cache[override].base)); gen_op_addl_A0_seg(offsetof(CPUX86State,seg_cache[override].base));
@ -2084,31 +2086,20 @@ long disas_insn(DisasContext *s, uint8_t *pc_start)
} }
break; break;
case 0xd7: /* xlat */ case 0xd7: /* xlat */
/* handle override */
gen_op_movl_A0_reg[R_EBX](); gen_op_movl_A0_reg[R_EBX]();
gen_op_addl_A0_AL(); gen_op_addl_A0_AL();
if (s->aflag == 0) if (s->aflag == 0)
gen_op_andl_A0_ffff(); gen_op_andl_A0_ffff();
/* XXX: factorize that */ /* handle override */
{ {
int override, must_add_seg; int override, must_add_seg;
override = R_DS;
must_add_seg = s->addseg; must_add_seg = s->addseg;
if (s->prefix & (PREFIX_CS | PREFIX_SS | PREFIX_DS | override = R_DS;
PREFIX_ES | PREFIX_FS | PREFIX_GS)) { if (s->override >= 0) {
if (s->prefix & PREFIX_ES) override = s->override;
override = R_ES;
else if (s->prefix & PREFIX_CS)
override = R_CS;
else if (s->prefix & PREFIX_SS)
override = R_SS;
else if (s->prefix & PREFIX_DS)
override = R_DS;
else if (s->prefix & PREFIX_FS)
override = R_FS;
else
override = R_GS;
must_add_seg = 1; must_add_seg = 1;
} else {
override = R_DS;
} }
if (must_add_seg) { if (must_add_seg) {
gen_op_addl_A0_seg(offsetof(CPUX86State,seg_cache[override].base)); gen_op_addl_A0_seg(offsetof(CPUX86State,seg_cache[override].base));
@ -2185,6 +2176,7 @@ long disas_insn(DisasContext *s, uint8_t *pc_start)
mod = (modrm >> 6) & 3; mod = (modrm >> 6) & 3;
if (mod == 3) if (mod == 3)
goto illegal_op; goto illegal_op;
gen_lea_modrm(s, modrm, &reg_addr, &offset_addr);
gen_op_ld_T1_A0[ot](); gen_op_ld_T1_A0[ot]();
gen_op_addl_A0_im(1 << (ot - OT_WORD + 1)); gen_op_addl_A0_im(1 << (ot - OT_WORD + 1));
/* load the segment first to handle exceptions properly */ /* load the segment first to handle exceptions properly */
@ -2658,16 +2650,18 @@ long disas_insn(DisasContext *s, uint8_t *pc_start)
break; break;
/************************/ /************************/
/* string ops */ /* string ops */
case 0xa4: /* movsS */ case 0xa4: /* movsS */
case 0xa5: case 0xa5:
if ((b & 1) == 0) if ((b & 1) == 0)
ot = OT_BYTE; ot = OT_BYTE;
else else
ot = dflag ? OT_LONG : OT_WORD; ot = dflag ? OT_LONG : OT_WORD;
if (prefixes & PREFIX_REPZ) { if (prefixes & PREFIX_REPZ) {
gen_op_movs[3 + ot](); gen_string_ds(s, ot, gen_op_movs + 9);
} else { } else {
gen_op_movs[ot](); gen_string_ds(s, ot, gen_op_movs);
} }
break; break;
@ -2677,10 +2671,11 @@ long disas_insn(DisasContext *s, uint8_t *pc_start)
ot = OT_BYTE; ot = OT_BYTE;
else else
ot = dflag ? OT_LONG : OT_WORD; ot = dflag ? OT_LONG : OT_WORD;
if (prefixes & PREFIX_REPZ) { if (prefixes & PREFIX_REPZ) {
gen_op_stos[3 + ot](); gen_string_es(s, ot, gen_op_stos + 9);
} else { } else {
gen_op_stos[ot](); gen_string_es(s, ot, gen_op_stos);
} }
break; break;
case 0xac: /* lodsS */ case 0xac: /* lodsS */
@ -2690,9 +2685,9 @@ long disas_insn(DisasContext *s, uint8_t *pc_start)
else else
ot = dflag ? OT_LONG : OT_WORD; ot = dflag ? OT_LONG : OT_WORD;
if (prefixes & PREFIX_REPZ) { if (prefixes & PREFIX_REPZ) {
gen_op_lods[3 + ot](); gen_string_ds(s, ot, gen_op_lods + 9);
} else { } else {
gen_op_lods[ot](); gen_string_ds(s, ot, gen_op_lods);
} }
break; break;
case 0xae: /* scasS */ case 0xae: /* scasS */
@ -2700,19 +2695,19 @@ long disas_insn(DisasContext *s, uint8_t *pc_start)
if ((b & 1) == 0) if ((b & 1) == 0)
ot = OT_BYTE; ot = OT_BYTE;
else else
ot = dflag ? OT_LONG : OT_WORD; ot = dflag ? OT_LONG : OT_WORD;
if (prefixes & PREFIX_REPNZ) { if (prefixes & PREFIX_REPNZ) {
if (s->cc_op != CC_OP_DYNAMIC) if (s->cc_op != CC_OP_DYNAMIC)
gen_op_set_cc_op(s->cc_op); gen_op_set_cc_op(s->cc_op);
gen_op_scas[6 + ot](); gen_string_es(s, ot, gen_op_scas + 9 * 2);
s->cc_op = CC_OP_DYNAMIC; /* cannot predict flags after */ s->cc_op = CC_OP_DYNAMIC; /* cannot predict flags after */
} else if (prefixes & PREFIX_REPZ) { } else if (prefixes & PREFIX_REPZ) {
if (s->cc_op != CC_OP_DYNAMIC) if (s->cc_op != CC_OP_DYNAMIC)
gen_op_set_cc_op(s->cc_op); gen_op_set_cc_op(s->cc_op);
gen_op_scas[3 + ot](); gen_string_es(s, ot, gen_op_scas + 9);
s->cc_op = CC_OP_DYNAMIC; /* cannot predict flags after */ s->cc_op = CC_OP_DYNAMIC; /* cannot predict flags after */
} else { } else {
gen_op_scas[ot](); gen_string_es(s, ot, gen_op_scas);
s->cc_op = CC_OP_SUBB + ot; s->cc_op = CC_OP_SUBB + ot;
} }
break; break;
@ -2726,21 +2721,18 @@ long disas_insn(DisasContext *s, uint8_t *pc_start)
if (prefixes & PREFIX_REPNZ) { if (prefixes & PREFIX_REPNZ) {
if (s->cc_op != CC_OP_DYNAMIC) if (s->cc_op != CC_OP_DYNAMIC)
gen_op_set_cc_op(s->cc_op); gen_op_set_cc_op(s->cc_op);
gen_op_cmps[6 + ot](); gen_string_ds(s, ot, gen_op_cmps + 9 * 2);
s->cc_op = CC_OP_DYNAMIC; /* cannot predict flags after */ s->cc_op = CC_OP_DYNAMIC; /* cannot predict flags after */
} else if (prefixes & PREFIX_REPZ) { } else if (prefixes & PREFIX_REPZ) {
if (s->cc_op != CC_OP_DYNAMIC) if (s->cc_op != CC_OP_DYNAMIC)
gen_op_set_cc_op(s->cc_op); gen_op_set_cc_op(s->cc_op);
gen_op_cmps[3 + ot](); gen_string_ds(s, ot, gen_op_cmps + 9);
s->cc_op = CC_OP_DYNAMIC; /* cannot predict flags after */ s->cc_op = CC_OP_DYNAMIC; /* cannot predict flags after */
} else { } else {
gen_op_cmps[ot](); gen_string_ds(s, ot, gen_op_cmps);
s->cc_op = CC_OP_SUBB + ot; s->cc_op = CC_OP_SUBB + ot;
} }
break; break;
/************************/
/* port I/O */
case 0x6c: /* insS */ case 0x6c: /* insS */
case 0x6d: case 0x6d:
if ((b & 1) == 0) if ((b & 1) == 0)
@ -2748,9 +2740,9 @@ long disas_insn(DisasContext *s, uint8_t *pc_start)
else else
ot = dflag ? OT_LONG : OT_WORD; ot = dflag ? OT_LONG : OT_WORD;
if (prefixes & PREFIX_REPZ) { if (prefixes & PREFIX_REPZ) {
gen_op_ins[3 + ot](); gen_string_es(s, ot, gen_op_ins + 9);
} else { } else {
gen_op_ins[ot](); gen_string_es(s, ot, gen_op_ins);
} }
break; break;
case 0x6e: /* outsS */ case 0x6e: /* outsS */
@ -2760,11 +2752,14 @@ long disas_insn(DisasContext *s, uint8_t *pc_start)
else else
ot = dflag ? OT_LONG : OT_WORD; ot = dflag ? OT_LONG : OT_WORD;
if (prefixes & PREFIX_REPZ) { if (prefixes & PREFIX_REPZ) {
gen_op_outs[3 + ot](); gen_string_ds(s, ot, gen_op_outs + 9);
} else { } else {
gen_op_outs[ot](); gen_string_ds(s, ot, gen_op_outs);
} }
break; break;
/************************/
/* port I/O */
case 0xe4: case 0xe4:
case 0xe5: case 0xe5:
if ((b & 1) == 0) if ((b & 1) == 0)
@ -3150,14 +3145,27 @@ long disas_insn(DisasContext *s, uint8_t *pc_start)
case 0xcd: /* int N */ case 0xcd: /* int N */
val = ldub(s->pc++); val = ldub(s->pc++);
/* XXX: currently we ignore the interrupt number */ /* XXX: currently we ignore the interrupt number */
gen_op_int_im((long)pc_start); gen_op_int_im(pc_start - s->cs_base);
s->is_jmp = 1; s->is_jmp = 1;
break; break;
case 0xce: /* into */ case 0xce: /* into */
if (s->cc_op != CC_OP_DYNAMIC) if (s->cc_op != CC_OP_DYNAMIC)
gen_op_set_cc_op(s->cc_op); gen_op_set_cc_op(s->cc_op);
gen_op_into((long)pc_start, (long)s->pc); gen_op_into();
s->is_jmp = 1; break;
case 0x62: /* bound */
ot = dflag ? OT_LONG : OT_WORD;
modrm = ldub(s->pc++);
reg = (modrm >> 3) & 7;
mod = (modrm >> 6) & 3;
if (mod == 3)
goto illegal_op;
gen_op_mov_reg_T0[ot][reg]();
gen_lea_modrm(s, modrm, &reg_addr, &offset_addr);
if (ot == OT_WORD)
gen_op_boundw();
else
gen_op_boundl();
break; break;
case 0x1c8 ... 0x1cf: /* bswap reg */ case 0x1c8 ... 0x1cf: /* bswap reg */
reg = b & 7; reg = b & 7;
@ -3188,11 +3196,9 @@ long disas_insn(DisasContext *s, uint8_t *pc_start)
case 0x131: /* rdtsc */ case 0x131: /* rdtsc */
gen_op_rdtsc(); gen_op_rdtsc();
break; break;
#if 0
case 0x1a2: /* cpuid */ case 0x1a2: /* cpuid */
gen_insn0(OP_ASM); gen_op_cpuid();
break; break;
#endif
default: default:
goto illegal_op; goto illegal_op;
} }
@ -3399,28 +3405,30 @@ static uint16_t opc_write_flags[NB_OPS] = {
[INDEX_op_bsrw_T0_cc] = CC_OSZAPC, [INDEX_op_bsrw_T0_cc] = CC_OSZAPC,
[INDEX_op_bsrl_T0_cc] = CC_OSZAPC, [INDEX_op_bsrl_T0_cc] = CC_OSZAPC,
[INDEX_op_scasb] = CC_OSZAPC, #undef STRINGOP
[INDEX_op_scasw] = CC_OSZAPC, #define STRINGOP(x) \
[INDEX_op_scasl] = CC_OSZAPC, [INDEX_op_ ## x ## b_fast] = CC_OSZAPC, \
[INDEX_op_repz_scasb] = CC_OSZAPC, [INDEX_op_ ## x ## w_fast] = CC_OSZAPC, \
[INDEX_op_repz_scasw] = CC_OSZAPC, [INDEX_op_ ## x ## l_fast] = CC_OSZAPC, \
[INDEX_op_repz_scasl] = CC_OSZAPC, [INDEX_op_ ## x ## b_a32] = CC_OSZAPC, \
[INDEX_op_repnz_scasb] = CC_OSZAPC, [INDEX_op_ ## x ## w_a32] = CC_OSZAPC, \
[INDEX_op_repnz_scasw] = CC_OSZAPC, [INDEX_op_ ## x ## l_a32] = CC_OSZAPC, \
[INDEX_op_repnz_scasl] = CC_OSZAPC, [INDEX_op_ ## x ## b_a16] = CC_OSZAPC, \
[INDEX_op_ ## x ## w_a16] = CC_OSZAPC, \
[INDEX_op_ ## x ## l_a16] = CC_OSZAPC,
[INDEX_op_cmpsb] = CC_OSZAPC, STRINGOP(scas)
[INDEX_op_cmpsw] = CC_OSZAPC, STRINGOP(repz_scas)
[INDEX_op_cmpsl] = CC_OSZAPC, STRINGOP(repnz_scas)
[INDEX_op_repz_cmpsb] = CC_OSZAPC, STRINGOP(cmps)
[INDEX_op_repz_cmpsw] = CC_OSZAPC, STRINGOP(repz_cmps)
[INDEX_op_repz_cmpsl] = CC_OSZAPC, STRINGOP(repnz_cmps)
[INDEX_op_repnz_cmpsb] = CC_OSZAPC,
[INDEX_op_repnz_cmpsw] = CC_OSZAPC,
[INDEX_op_repnz_cmpsl] = CC_OSZAPC,
[INDEX_op_cmpxchgb_T0_T1_EAX_cc] = CC_OSZAPC,
[INDEX_op_cmpxchgw_T0_T1_EAX_cc] = CC_OSZAPC, [INDEX_op_cmpxchgw_T0_T1_EAX_cc] = CC_OSZAPC,
[INDEX_op_cmpxchgl_T0_T1_EAX_cc] = CC_OSZAPC, [INDEX_op_cmpxchgl_T0_T1_EAX_cc] = CC_OSZAPC,
[INDEX_op_cmpxchg8b] = CC_Z,
}; };
/* simpler form of an operation if no flags need to be generated */ /* simpler form of an operation if no flags need to be generated */
@ -3495,21 +3503,36 @@ static void optimize_flags(uint16_t *opc_buf, int opc_buf_len)
#ifdef DEBUG_DISAS #ifdef DEBUG_DISAS
static const char *op_str[] = { static const char *op_str[] = {
#define DEF(s) #s, #define DEF(s, n) #s,
#include "opc-i386.h" #include "opc-i386.h"
#undef DEF #undef DEF
}; };
static void dump_ops(const uint16_t *opc_buf) static uint8_t op_nb_args[] = {
#define DEF(s, n) n,
#include "opc-i386.h"
#undef DEF
};
static void dump_ops(const uint16_t *opc_buf, const uint32_t *opparam_buf)
{ {
const uint16_t *opc_ptr; const uint16_t *opc_ptr;
int c; const uint32_t *opparam_ptr;
int c, n, i;
opc_ptr = opc_buf; opc_ptr = opc_buf;
opparam_ptr = opparam_buf;
for(;;) { for(;;) {
c = *opc_ptr++; c = *opc_ptr++;
fprintf(logfile, "0x%04x: %s\n", opc_ptr - opc_buf - 1, op_str[c]); n = op_nb_args[c];
fprintf(logfile, "0x%04x: %s", opc_ptr - opc_buf - 1, op_str[c]);
for(i = 0; i < n; i++) {
fprintf(logfile, " 0x%x", opparam_ptr[i]);
}
fprintf(logfile, "\n");
if (c == INDEX_op_end) if (c == INDEX_op_end)
break; break;
opparam_ptr += n;
} }
} }
@ -3547,6 +3570,7 @@ int cpu_x86_gen_code(uint8_t *gen_code_buf, int max_code_size,
dc->ss32 = (flags >> GEN_FLAG_SS32_SHIFT) & 1; dc->ss32 = (flags >> GEN_FLAG_SS32_SHIFT) & 1;
dc->addseg = (flags >> GEN_FLAG_ADDSEG_SHIFT) & 1; dc->addseg = (flags >> GEN_FLAG_ADDSEG_SHIFT) & 1;
dc->f_st = (flags >> GEN_FLAG_ST_SHIFT) & 7; dc->f_st = (flags >> GEN_FLAG_ST_SHIFT) & 7;
dc->vm86 = (flags >> GEN_FLAG_VM_SHIFT) & 1;
dc->cc_op = CC_OP_DYNAMIC; dc->cc_op = CC_OP_DYNAMIC;
dc->cs_base = cs_base; dc->cs_base = cs_base;
@ -3610,7 +3634,7 @@ int cpu_x86_gen_code(uint8_t *gen_code_buf, int max_code_size,
fprintf(logfile, "\n"); fprintf(logfile, "\n");
fprintf(logfile, "OP:\n"); fprintf(logfile, "OP:\n");
dump_ops(gen_opc_buf); dump_ops(gen_opc_buf, gen_opparam_buf);
fprintf(logfile, "\n"); fprintf(logfile, "\n");
} }
#endif #endif
@ -3621,7 +3645,7 @@ int cpu_x86_gen_code(uint8_t *gen_code_buf, int max_code_size,
#ifdef DEBUG_DISAS #ifdef DEBUG_DISAS
if (loglevel) { if (loglevel) {
fprintf(logfile, "AFTER FLAGS OPT:\n"); fprintf(logfile, "AFTER FLAGS OPT:\n");
dump_ops(gen_opc_buf); dump_ops(gen_opc_buf, gen_opparam_buf);
fprintf(logfile, "\n"); fprintf(logfile, "\n");
} }
#endif #endif
@ -3683,8 +3707,8 @@ CPUX86State *cpu_x86_init(void)
for(i = 0;i < 8; i++) for(i = 0;i < 8; i++)
env->fptags[i] = 1; env->fptags[i] = 1;
env->fpuc = 0x37f; env->fpuc = 0x37f;
/* flags setup */ /* flags setup : we activate the IRQs by default as in user mode */
env->eflags = 0; env->eflags = 0x2 | IF_MASK;
/* init various static tables */ /* init various static tables */
if (!inited) { if (!inited) {